mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-11 03:48:00 +00:00
Merge branch 'pci/enumeration'
- neaten pci=earlydump output (Andy Shevchenko) - avoid errors when extended config space inaccessible (Gilles Buloz) - prevent sysfs disable of device while driver attached (Christoph Hellwig) - use core interface to report PCIe link properties in bnx2x, bnxt_en, cxgb4, ixgbe (Bjorn Helgaas) - remove unused pcie_get_minimum_link() (Bjorn Helgaas) * pci/enumeration: PCI: Remove unused pcie_get_minimum_link() ixgbe: Report PCIe link properties with pcie_print_link_status() cxgb4: Report PCIe link properties with pcie_print_link_status() bnxt_en: Report PCIe link properties with pcie_print_link_status() bnx2x: Report PCIe link properties with pcie_print_link_status() PCI: Prevent sysfs disable of device while driver is attached PCI: Check whether bridges allow access to extended config space x86/PCI: Make pci=earlydump output neat
This commit is contained in:
commit
5e3165d1a8
@ -59,24 +59,15 @@ int early_pci_allowed(void)
|
||||
|
||||
void early_dump_pci_device(u8 bus, u8 slot, u8 func)
|
||||
{
|
||||
u32 value[256 / 4];
|
||||
int i;
|
||||
int j;
|
||||
u32 val;
|
||||
|
||||
printk(KERN_INFO "pci 0000:%02x:%02x.%d config space:",
|
||||
bus, slot, func);
|
||||
pr_info("pci 0000:%02x:%02x.%d config space:\n", bus, slot, func);
|
||||
|
||||
for (i = 0; i < 256; i += 4) {
|
||||
if (!(i & 0x0f))
|
||||
printk("\n %02x:",i);
|
||||
for (i = 0; i < 256; i += 4)
|
||||
value[i / 4] = read_pci_config(bus, slot, func, i);
|
||||
|
||||
val = read_pci_config(bus, slot, func, i);
|
||||
for (j = 0; j < 4; j++) {
|
||||
printk(" %02x", val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, value, 256, false);
|
||||
}
|
||||
|
||||
void early_dump_pci_devices(void)
|
||||
|
@ -13922,8 +13922,6 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
{
|
||||
struct net_device *dev = NULL;
|
||||
struct bnx2x *bp;
|
||||
enum pcie_link_width pcie_width;
|
||||
enum pci_bus_speed pcie_speed;
|
||||
int rc, max_non_def_sbs;
|
||||
int rx_count, tx_count, rss_count, doorbell_size;
|
||||
int max_cos_est;
|
||||
@ -14091,21 +14089,12 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
||||
dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
|
||||
rtnl_unlock();
|
||||
}
|
||||
if (pcie_get_minimum_link(bp->pdev, &pcie_speed, &pcie_width) ||
|
||||
pcie_speed == PCI_SPEED_UNKNOWN ||
|
||||
pcie_width == PCIE_LNK_WIDTH_UNKNOWN)
|
||||
BNX2X_DEV_INFO("Failed to determine PCI Express Bandwidth\n");
|
||||
else
|
||||
BNX2X_DEV_INFO(
|
||||
"%s (%c%d) PCI-E x%d %s found at mem %lx, IRQ %d, node addr %pM\n",
|
||||
board_info[ent->driver_data].name,
|
||||
(CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
|
||||
pcie_width,
|
||||
pcie_speed == PCIE_SPEED_2_5GT ? "2.5GHz" :
|
||||
pcie_speed == PCIE_SPEED_5_0GT ? "5.0GHz" :
|
||||
pcie_speed == PCIE_SPEED_8_0GT ? "8.0GHz" :
|
||||
"Unknown",
|
||||
dev->base_addr, bp->pdev->irq, dev->dev_addr);
|
||||
BNX2X_DEV_INFO(
|
||||
"%s (%c%d) PCI-E found at mem %lx, IRQ %d, node addr %pM\n",
|
||||
board_info[ent->driver_data].name,
|
||||
(CHIP_REV(bp) >> 12) + 'A', (CHIP_METAL(bp) >> 4),
|
||||
dev->base_addr, bp->pdev->irq, dev->dev_addr);
|
||||
pcie_print_link_status(bp->pdev);
|
||||
|
||||
bnx2x_register_phc(bp);
|
||||
|
||||
|
@ -8621,22 +8621,6 @@ static int bnxt_init_mac_addr(struct bnxt *bp)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnxt_parse_log_pcie_link(struct bnxt *bp)
|
||||
{
|
||||
enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
|
||||
|
||||
if (pcie_get_minimum_link(pci_physfn(bp->pdev), &speed, &width) ||
|
||||
speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN)
|
||||
netdev_info(bp->dev, "Failed to determine PCIe Link Info\n");
|
||||
else
|
||||
netdev_info(bp->dev, "PCIe: Speed %s Width x%d\n",
|
||||
speed == PCIE_SPEED_2_5GT ? "2.5GT/s" :
|
||||
speed == PCIE_SPEED_5_0GT ? "5.0GT/s" :
|
||||
speed == PCIE_SPEED_8_0GT ? "8.0GT/s" :
|
||||
"Unknown", width);
|
||||
}
|
||||
|
||||
static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
static int version_printed;
|
||||
@ -8851,8 +8835,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
|
||||
board_info[ent->driver_data].name,
|
||||
(long)pci_resource_start(pdev, 0), dev->dev_addr);
|
||||
|
||||
bnxt_parse_log_pcie_link(bp);
|
||||
pcie_print_link_status(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -5042,79 +5042,6 @@ static int init_rss(struct adapter *adap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgb4_get_pcie_dev_link_caps(struct adapter *adap,
|
||||
enum pci_bus_speed *speed,
|
||||
enum pcie_link_width *width)
|
||||
{
|
||||
u32 lnkcap1, lnkcap2;
|
||||
int err1, err2;
|
||||
|
||||
#define PCIE_MLW_CAP_SHIFT 4 /* start of MLW mask in link capabilities */
|
||||
|
||||
*speed = PCI_SPEED_UNKNOWN;
|
||||
*width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
|
||||
err1 = pcie_capability_read_dword(adap->pdev, PCI_EXP_LNKCAP,
|
||||
&lnkcap1);
|
||||
err2 = pcie_capability_read_dword(adap->pdev, PCI_EXP_LNKCAP2,
|
||||
&lnkcap2);
|
||||
if (!err2 && lnkcap2) { /* PCIe r3.0-compliant */
|
||||
if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
|
||||
*speed = PCIE_SPEED_8_0GT;
|
||||
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
|
||||
*speed = PCIE_SPEED_5_0GT;
|
||||
else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
|
||||
*speed = PCIE_SPEED_2_5GT;
|
||||
}
|
||||
if (!err1) {
|
||||
*width = (lnkcap1 & PCI_EXP_LNKCAP_MLW) >> PCIE_MLW_CAP_SHIFT;
|
||||
if (!lnkcap2) { /* pre-r3.0 */
|
||||
if (lnkcap1 & PCI_EXP_LNKCAP_SLS_5_0GB)
|
||||
*speed = PCIE_SPEED_5_0GT;
|
||||
else if (lnkcap1 & PCI_EXP_LNKCAP_SLS_2_5GB)
|
||||
*speed = PCIE_SPEED_2_5GT;
|
||||
}
|
||||
}
|
||||
|
||||
if (*speed == PCI_SPEED_UNKNOWN || *width == PCIE_LNK_WIDTH_UNKNOWN)
|
||||
return err1 ? err1 : err2 ? err2 : -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cxgb4_check_pcie_caps(struct adapter *adap)
|
||||
{
|
||||
enum pcie_link_width width, width_cap;
|
||||
enum pci_bus_speed speed, speed_cap;
|
||||
|
||||
#define PCIE_SPEED_STR(speed) \
|
||||
(speed == PCIE_SPEED_8_0GT ? "8.0GT/s" : \
|
||||
speed == PCIE_SPEED_5_0GT ? "5.0GT/s" : \
|
||||
speed == PCIE_SPEED_2_5GT ? "2.5GT/s" : \
|
||||
"Unknown")
|
||||
|
||||
if (cxgb4_get_pcie_dev_link_caps(adap, &speed_cap, &width_cap)) {
|
||||
dev_warn(adap->pdev_dev,
|
||||
"Unable to determine PCIe device BW capabilities\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pcie_get_minimum_link(adap->pdev, &speed, &width) ||
|
||||
speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) {
|
||||
dev_warn(adap->pdev_dev,
|
||||
"Unable to determine PCI Express bandwidth.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dev_info(adap->pdev_dev, "PCIe link speed is %s, device supports %s\n",
|
||||
PCIE_SPEED_STR(speed), PCIE_SPEED_STR(speed_cap));
|
||||
dev_info(adap->pdev_dev, "PCIe link width is x%d, device supports x%d\n",
|
||||
width, width_cap);
|
||||
if (speed < speed_cap || width < width_cap)
|
||||
dev_info(adap->pdev_dev,
|
||||
"A slot with more lanes and/or higher speed is "
|
||||
"suggested for optimal performance.\n");
|
||||
}
|
||||
|
||||
/* Dump basic information about the adapter */
|
||||
static void print_adapter_info(struct adapter *adapter)
|
||||
{
|
||||
@ -5750,7 +5677,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
}
|
||||
|
||||
/* check for PCI Express bandwidth capabiltites */
|
||||
cxgb4_check_pcie_caps(adapter);
|
||||
pcie_print_link_status(pdev);
|
||||
|
||||
err = init_rss(adapter);
|
||||
if (err)
|
||||
|
@ -270,9 +270,6 @@ static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
|
||||
int expected_gts)
|
||||
{
|
||||
struct ixgbe_hw *hw = &adapter->hw;
|
||||
int max_gts = 0;
|
||||
enum pci_bus_speed speed = PCI_SPEED_UNKNOWN;
|
||||
enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* Some devices are not connected over PCIe and thus do not negotiate
|
||||
@ -288,49 +285,7 @@ static void ixgbe_check_minimum_link(struct ixgbe_adapter *adapter,
|
||||
else
|
||||
pdev = adapter->pdev;
|
||||
|
||||
if (pcie_get_minimum_link(pdev, &speed, &width) ||
|
||||
speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) {
|
||||
e_dev_warn("Unable to determine PCI Express bandwidth.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (speed) {
|
||||
case PCIE_SPEED_2_5GT:
|
||||
/* 8b/10b encoding reduces max throughput by 20% */
|
||||
max_gts = 2 * width;
|
||||
break;
|
||||
case PCIE_SPEED_5_0GT:
|
||||
/* 8b/10b encoding reduces max throughput by 20% */
|
||||
max_gts = 4 * width;
|
||||
break;
|
||||
case PCIE_SPEED_8_0GT:
|
||||
/* 128b/130b encoding reduces throughput by less than 2% */
|
||||
max_gts = 8 * width;
|
||||
break;
|
||||
default:
|
||||
e_dev_warn("Unable to determine PCI Express bandwidth.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
e_dev_info("PCI Express bandwidth of %dGT/s available\n",
|
||||
max_gts);
|
||||
e_dev_info("(Speed:%s, Width: x%d, Encoding Loss:%s)\n",
|
||||
(speed == PCIE_SPEED_8_0GT ? "8.0GT/s" :
|
||||
speed == PCIE_SPEED_5_0GT ? "5.0GT/s" :
|
||||
speed == PCIE_SPEED_2_5GT ? "2.5GT/s" :
|
||||
"Unknown"),
|
||||
width,
|
||||
(speed == PCIE_SPEED_2_5GT ? "20%" :
|
||||
speed == PCIE_SPEED_5_0GT ? "20%" :
|
||||
speed == PCIE_SPEED_8_0GT ? "<2%" :
|
||||
"Unknown"));
|
||||
|
||||
if (max_gts < expected_gts) {
|
||||
e_dev_warn("This is not sufficient for optimal performance of this card.\n");
|
||||
e_dev_warn("For optimal performance, at least %dGT/s of bandwidth is required.\n",
|
||||
expected_gts);
|
||||
e_dev_warn("A slot with more lanes and/or higher speed is suggested.\n");
|
||||
}
|
||||
pcie_print_link_status(pdev);
|
||||
}
|
||||
|
||||
static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
|
||||
|
@ -288,13 +288,16 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (!val) {
|
||||
if (pci_is_enabled(pdev))
|
||||
pci_disable_device(pdev);
|
||||
else
|
||||
result = -EIO;
|
||||
} else
|
||||
device_lock(dev);
|
||||
if (dev->driver)
|
||||
result = -EBUSY;
|
||||
else if (val)
|
||||
result = pci_enable_device(pdev);
|
||||
else if (pci_is_enabled(pdev))
|
||||
pci_disable_device(pdev);
|
||||
else
|
||||
result = -EIO;
|
||||
device_unlock(dev);
|
||||
|
||||
return result < 0 ? result : count;
|
||||
}
|
||||
|
@ -5098,49 +5098,6 @@ int pcie_set_mps(struct pci_dev *dev, int mps)
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_set_mps);
|
||||
|
||||
/**
|
||||
* pcie_get_minimum_link - determine minimum link settings of a PCI device
|
||||
* @dev: PCI device to query
|
||||
* @speed: storage for minimum speed
|
||||
* @width: storage for minimum width
|
||||
*
|
||||
* This function will walk up the PCI device chain and determine the minimum
|
||||
* link width and speed of the device.
|
||||
*/
|
||||
int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
|
||||
enum pcie_link_width *width)
|
||||
{
|
||||
int ret;
|
||||
|
||||
*speed = PCI_SPEED_UNKNOWN;
|
||||
*width = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
|
||||
while (dev) {
|
||||
u16 lnksta;
|
||||
enum pci_bus_speed next_speed;
|
||||
enum pcie_link_width next_width;
|
||||
|
||||
ret = pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
next_speed = pcie_link_speed[lnksta & PCI_EXP_LNKSTA_CLS];
|
||||
next_width = (lnksta & PCI_EXP_LNKSTA_NLW) >>
|
||||
PCI_EXP_LNKSTA_NLW_SHIFT;
|
||||
|
||||
if (next_speed < *speed)
|
||||
*speed = next_speed;
|
||||
|
||||
if (next_width < *width)
|
||||
*width = next_width;
|
||||
|
||||
dev = dev->bus->self;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_get_minimum_link);
|
||||
|
||||
/**
|
||||
* pcie_bandwidth_available - determine minimum link settings of a PCIe
|
||||
* device and its bandwidth limitation
|
||||
|
@ -883,6 +883,45 @@ free:
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool pci_bridge_child_ext_cfg_accessible(struct pci_dev *bridge)
|
||||
{
|
||||
int pos;
|
||||
u32 status;
|
||||
|
||||
/*
|
||||
* If extended config space isn't accessible on a bridge's primary
|
||||
* bus, we certainly can't access it on the secondary bus.
|
||||
*/
|
||||
if (bridge->bus->bus_flags & PCI_BUS_FLAGS_NO_EXTCFG)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* PCIe Root Ports and switch ports are PCIe on both sides, so if
|
||||
* extended config space is accessible on the primary, it's also
|
||||
* accessible on the secondary.
|
||||
*/
|
||||
if (pci_is_pcie(bridge) &&
|
||||
(pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
pci_pcie_type(bridge) == PCI_EXP_TYPE_UPSTREAM ||
|
||||
pci_pcie_type(bridge) == PCI_EXP_TYPE_DOWNSTREAM))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* For the other bridge types:
|
||||
* - PCI-to-PCI bridges
|
||||
* - PCIe-to-PCI/PCI-X forward bridges
|
||||
* - PCI/PCI-X-to-PCIe reverse bridges
|
||||
* extended config space on the secondary side is only accessible
|
||||
* if the bridge supports PCI-X Mode 2.
|
||||
*/
|
||||
pos = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
|
||||
if (!pos)
|
||||
return false;
|
||||
|
||||
pci_read_config_dword(bridge, pos + PCI_X_STATUS, &status);
|
||||
return status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ);
|
||||
}
|
||||
|
||||
static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
|
||||
struct pci_dev *bridge, int busnr)
|
||||
{
|
||||
@ -924,6 +963,16 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
|
||||
pci_set_bus_of_node(child);
|
||||
pci_set_bus_speed(child);
|
||||
|
||||
/*
|
||||
* Check whether extended config space is accessible on the child
|
||||
* bus. Note that we currently assume it is always accessible on
|
||||
* the root bus.
|
||||
*/
|
||||
if (!pci_bridge_child_ext_cfg_accessible(bridge)) {
|
||||
child->bus_flags |= PCI_BUS_FLAGS_NO_EXTCFG;
|
||||
pci_info(child, "extended config space not accessible\n");
|
||||
}
|
||||
|
||||
/* Set up default resource pointers and names */
|
||||
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
|
||||
child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
|
||||
@ -1394,6 +1443,9 @@ int pci_cfg_space_size(struct pci_dev *dev)
|
||||
u32 status;
|
||||
u16 class;
|
||||
|
||||
if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_EXTCFG)
|
||||
return PCI_CFG_SPACE_SIZE;
|
||||
|
||||
class = dev->class >> 8;
|
||||
if (class == PCI_CLASS_BRIDGE_HOST)
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
|
@ -217,6 +217,7 @@ enum pci_bus_flags {
|
||||
PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
|
||||
PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
|
||||
PCI_BUS_FLAGS_NO_AERSID = (__force pci_bus_flags_t) 4,
|
||||
PCI_BUS_FLAGS_NO_EXTCFG = (__force pci_bus_flags_t) 8,
|
||||
};
|
||||
|
||||
/* Values from Link Status register, PCIe r3.1, sec 7.8.8 */
|
||||
@ -1080,8 +1081,6 @@ int pcie_get_readrq(struct pci_dev *dev);
|
||||
int pcie_set_readrq(struct pci_dev *dev, int rq);
|
||||
int pcie_get_mps(struct pci_dev *dev);
|
||||
int pcie_set_mps(struct pci_dev *dev, int mps);
|
||||
int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
|
||||
enum pcie_link_width *width);
|
||||
u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
|
||||
enum pci_bus_speed *speed,
|
||||
enum pcie_link_width *width);
|
||||
|
Loading…
x
Reference in New Issue
Block a user