]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'pci/enumeration'
authorBjorn Helgaas <bhelgaas@google.com>
Wed, 6 Jun 2018 21:10:08 +0000 (16:10 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 6 Jun 2018 21:10:08 +0000 (16:10 -0500)
  - 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

arch/x86/pci/early.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/probe.c
include/linux/pci.h

index f0114007e9159acbba649b7b03eb95d41ce2b433..e5f753cbb1c3dc2c9a5ade77176dd3669e6a29ab 100644 (file)
@@ -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)
index c766ae23bc74f3a7da353a3bbddf72aabf1664cd..5b1ed240bf18be0963cc580ab4256b6adc924046 100644 (file)
@@ -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);
 
index f83769d8047b4d383adebf839bcd88775496cada..34fddb48fecc325718676a44c397c0daf10f592e 100644 (file)
@@ -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;
 
index 24d2865b880665910c4a4a53d9e613124724432b..7328f24ba1dd61c2eaae14f7b8a83728ef549c1a 100644 (file)
@@ -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)
index afadba99f7b8286e287a2a88703026319f78924b..8990285f6e1229934e4eea5af6a79171c477d4b8 100644 (file)
@@ -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)
index 366d93af051d45f174fe96af4e6c1c3f106f678d..788a200fb2dc4b3956f66ee07b7aeaa55157d0b2 100644 (file)
@@ -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;
 }
index 764bf64a097df00aa177c047af81b76e0dd723af..2aaab81341ac9557b1d682076a479ea9eaaf20c5 100644 (file)
@@ -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
index cc1688d75664242c5547f58d94c544bdff9d63e3..4fd402946b43249c48f5aa237ecbc2a2125b72b6 100644 (file)
@@ -883,6 +883,45 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
        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);
index e2e85772255302e1aba0fb773f7eaf61ecf968e3..2619ab35dae9d448e99ebb52c91c4c9572a41c5d 100644 (file)
@@ -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);