Merge branch 'pci/virtualization' into next
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 12 Dec 2016 17:25:05 +0000 (11:25 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 12 Dec 2016 17:25:05 +0000 (11:25 -0600)
* pci/virtualization:
  PCI: Add comments about ROM BAR updating
  PCI: Decouple IORESOURCE_ROM_ENABLE and PCI_ROM_ADDRESS_ENABLE
  PCI: Remove pci_resource_bar() and pci_iov_resource_bar()
  PCI: Don't update VF BARs while VF memory space is enabled
  PCI: Separate VF BAR updates from standard BAR updates
  PCI: Update BARs using property bits appropriate for type
  PCI: Ignore BAR updates on virtual functions
  PCI: Do any VF BAR updates before enabling the BARs
  PCI: Support INTx masking on ConnectX-4 with firmware x.14.1100+
  PCI: Convert Mellanox broken INTx quirks to be for listed devices only
  PCI: Convert broken INTx masking quirks from HEADER to FINAL
  net/mlx4_core: Use device ID defines
  PCI: Add Mellanox device IDs

drivers/net/ethernet/mellanox/mlx4/main.c
drivers/pci/iov.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/rom.c
drivers/pci/setup-res.c
include/linux/pci_ids.h

index 7183ac4..62788b7 100644 (file)
@@ -4012,49 +4012,51 @@ int mlx4_restart_one(struct pci_dev *pdev)
        return err;
 }
 
+#define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT }
+#define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF }
+#define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 }
+
 static const struct pci_device_id mlx4_pci_table[] = {
-       /* MT25408 "Hermon" SDR */
-       { PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" DDR */
-       { PCI_VDEVICE(MELLANOX, 0x634a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" QDR */
-       { PCI_VDEVICE(MELLANOX, 0x6354), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" DDR PCIe gen2 */
-       { PCI_VDEVICE(MELLANOX, 0x6732), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" QDR PCIe gen2 */
-       { PCI_VDEVICE(MELLANOX, 0x673c), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" EN 10GigE */
-       { PCI_VDEVICE(MELLANOX, 0x6368), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
-       { PCI_VDEVICE(MELLANOX, 0x6750), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25458 ConnectX EN 10GBASE-T 10GigE */
-       { PCI_VDEVICE(MELLANOX, 0x6372), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
-       { PCI_VDEVICE(MELLANOX, 0x675a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT26468 ConnectX EN 10GigE PCIe gen2*/
-       { PCI_VDEVICE(MELLANOX, 0x6764), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
-       { PCI_VDEVICE(MELLANOX, 0x6746), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT26478 ConnectX2 40GigE PCIe gen2 */
-       { PCI_VDEVICE(MELLANOX, 0x676e), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-       /* MT25400 Family [ConnectX-2 Virtual Function] */
-       { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_PCI_DEV_IS_VF },
+       /* MT25408 "Hermon" */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_SDR),      /* SDR */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR),      /* DDR */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR),      /* QDR */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2), /* DDR Gen2 */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2), /* QDR Gen2 */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN),       /* EN 10GigE */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2),  /* EN 10GigE Gen2 */
+       /* MT25458 ConnectX EN 10GBASE-T */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN),
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2),      /* Gen2 */
+       /* MT26468 ConnectX EN 10GigE PCIe Gen2*/
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2),
+       /* MT26438 ConnectX EN 40GigE PCIe Gen2 5GT/s */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2),
+       /* MT26478 ConnectX2 40GigE PCIe Gen2 */
+       MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX2),
+       /* MT25400 Family [ConnectX-2] */
+       MLX_VF(0x1002),                                 /* Virtual Function */
        /* MT27500 Family [ConnectX-3] */
-       { PCI_VDEVICE(MELLANOX, 0x1003), 0 },
-       /* MT27500 Family [ConnectX-3 Virtual Function] */
-       { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_PCI_DEV_IS_VF },
-       { PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */
-       { PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */
-       { PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */
-       { PCI_VDEVICE(MELLANOX, 0x1008), 0 }, /* MT27521 Family */
-       { PCI_VDEVICE(MELLANOX, 0x1009), 0 }, /* MT27530 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100a), 0 }, /* MT27531 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100b), 0 }, /* MT27540 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100c), 0 }, /* MT27541 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100d), 0 }, /* MT27550 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100e), 0 }, /* MT27551 Family */
-       { PCI_VDEVICE(MELLANOX, 0x100f), 0 }, /* MT27560 Family */
-       { PCI_VDEVICE(MELLANOX, 0x1010), 0 }, /* MT27561 Family */
+       MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3),
+       MLX_VF(0x1004),                                 /* Virtual Function */
+       MLX_GN(0x1005),                                 /* MT27510 Family */
+       MLX_GN(0x1006),                                 /* MT27511 Family */
+       MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO),   /* MT27520 Family */
+       MLX_GN(0x1008),                                 /* MT27521 Family */
+       MLX_GN(0x1009),                                 /* MT27530 Family */
+       MLX_GN(0x100a),                                 /* MT27531 Family */
+       MLX_GN(0x100b),                                 /* MT27540 Family */
+       MLX_GN(0x100c),                                 /* MT27541 Family */
+       MLX_GN(0x100d),                                 /* MT27550 Family */
+       MLX_GN(0x100e),                                 /* MT27551 Family */
+       MLX_GN(0x100f),                                 /* MT27560 Family */
+       MLX_GN(0x1010),                                 /* MT27561 Family */
+
+       /*
+        * See the mellanox_check_broken_intx_masking() quirk when
+        * adding devices
+        */
+
        { 0, }
 };
 
index e30f05c..4722782 100644 (file)
@@ -306,13 +306,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                        return rc;
        }
 
-       pci_iov_set_numvfs(dev, nr_virtfn);
-       iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
-       pci_cfg_access_lock(dev);
-       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
-       msleep(100);
-       pci_cfg_access_unlock(dev);
-
        iov->initial_VFs = initial;
        if (nr_virtfn < initial)
                initial = nr_virtfn;
@@ -323,6 +316,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
                goto err_pcibios;
        }
 
+       pci_iov_set_numvfs(dev, nr_virtfn);
+       iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
+       pci_cfg_access_lock(dev);
+       pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
+       msleep(100);
+       pci_cfg_access_unlock(dev);
+
        for (i = 0; i < initial; i++) {
                rc = pci_iov_add_virtfn(dev, i, 0);
                if (rc)
@@ -554,21 +554,61 @@ void pci_iov_release(struct pci_dev *dev)
 }
 
 /**
- * pci_iov_resource_bar - get position of the SR-IOV BAR
+ * pci_iov_update_resource - update a VF BAR
  * @dev: the PCI device
  * @resno: the resource number
  *
- * Returns position of the BAR encapsulated in the SR-IOV capability.
+ * Update a VF BAR in the SR-IOV capability of a PF.
  */
-int pci_iov_resource_bar(struct pci_dev *dev, int resno)
+void pci_iov_update_resource(struct pci_dev *dev, int resno)
 {
-       if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END)
-               return 0;
+       struct pci_sriov *iov = dev->is_physfn ? dev->sriov : NULL;
+       struct resource *res = dev->resource + resno;
+       int vf_bar = resno - PCI_IOV_RESOURCES;
+       struct pci_bus_region region;
+       u16 cmd;
+       u32 new;
+       int reg;
+
+       /*
+        * The generic pci_restore_bars() path calls this for all devices,
+        * including VFs and non-SR-IOV devices.  If this is not a PF, we
+        * have nothing to do.
+        */
+       if (!iov)
+               return;
+
+       pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &cmd);
+       if ((cmd & PCI_SRIOV_CTRL_VFE) && (cmd & PCI_SRIOV_CTRL_MSE)) {
+               dev_WARN(&dev->dev, "can't update enabled VF BAR%d %pR\n",
+                        vf_bar, res);
+               return;
+       }
+
+       /*
+        * Ignore unimplemented BARs, unused resource slots for 64-bit
+        * BARs, and non-movable resources, e.g., those described via
+        * Enhanced Allocation.
+        */
+       if (!res->flags)
+               return;
+
+       if (res->flags & IORESOURCE_UNSET)
+               return;
+
+       if (res->flags & IORESOURCE_PCI_FIXED)
+               return;
 
-       BUG_ON(!dev->is_physfn);
+       pcibios_resource_to_bus(dev->bus, &region, res);
+       new = region.start;
+       new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
 
-       return dev->sriov->pos + PCI_SRIOV_BAR +
-               4 * (resno - PCI_IOV_RESOURCES);
+       reg = iov->pos + PCI_SRIOV_BAR + 4 * vf_bar;
+       pci_write_config_dword(dev, reg, new);
+       if (res->flags & IORESOURCE_MEM_64) {
+               new = region.start >> 16 >> 16;
+               pci_write_config_dword(dev, reg + 4, new);
+       }
 }
 
 resource_size_t __weak pcibios_iov_resource_alignment(struct pci_dev *dev,
index 1eb622c..a881c0d 100644 (file)
@@ -564,10 +564,6 @@ static void pci_restore_bars(struct pci_dev *dev)
 {
        int i;
 
-       /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
-       if (dev->is_virtfn)
-               return;
-
        for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
                pci_update_resource(dev, i);
 }
@@ -4831,36 +4827,6 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)
 }
 EXPORT_SYMBOL(pci_select_bars);
 
-/**
- * pci_resource_bar - get position of the BAR associated with a resource
- * @dev: the PCI device
- * @resno: the resource number
- * @type: the BAR type to be filled in
- *
- * Returns BAR position in config space, or 0 if the BAR is invalid.
- */
-int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
-{
-       int reg;
-
-       if (resno < PCI_ROM_RESOURCE) {
-               *type = pci_bar_unknown;
-               return PCI_BASE_ADDRESS_0 + 4 * resno;
-       } else if (resno == PCI_ROM_RESOURCE) {
-               *type = pci_bar_mem32;
-               return dev->rom_base_reg;
-       } else if (resno < PCI_BRIDGE_RESOURCES) {
-               /* device specific resource */
-               *type = pci_bar_unknown;
-               reg = pci_iov_resource_bar(dev, resno);
-               if (reg)
-                       return reg;
-       }
-
-       dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
-       return 0;
-}
-
 /* Some architectures require additional programming to enable VGA */
 static arch_set_vga_state_t arch_set_vga_state;
 
index bb1e07b..cb17db2 100644 (file)
@@ -242,7 +242,6 @@ bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
 int pci_setup_device(struct pci_dev *dev);
 int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                    struct resource *res, unsigned int reg);
-int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
 void pci_configure_ari(struct pci_dev *dev);
 void __pci_bus_size_bridges(struct pci_bus *bus,
                        struct list_head *realloc_head);
@@ -286,7 +285,7 @@ static inline void pci_restore_ats_state(struct pci_dev *dev)
 #ifdef CONFIG_PCI_IOV
 int pci_iov_init(struct pci_dev *dev);
 void pci_iov_release(struct pci_dev *dev);
-int pci_iov_resource_bar(struct pci_dev *dev, int resno);
+void pci_iov_update_resource(struct pci_dev *dev, int resno);
 resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 void pci_restore_iov_state(struct pci_dev *dev);
 int pci_iov_bus_range(struct pci_bus *bus);
@@ -300,10 +299,6 @@ static inline void pci_iov_release(struct pci_dev *dev)
 
 {
 }
-static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno)
-{
-       return 0;
-}
 static inline void pci_restore_iov_state(struct pci_dev *dev)
 {
 }
index ab00267..cf7670e 100644 (file)
@@ -227,7 +227,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        mask64 = (u32)PCI_BASE_ADDRESS_MEM_MASK;
                }
        } else {
-               res->flags |= (l & IORESOURCE_ROM_ENABLE);
+               if (l & PCI_ROM_ADDRESS_ENABLE)
+                       res->flags |= IORESOURCE_ROM_ENABLE;
                l64 = l & PCI_ROM_ADDRESS_MASK;
                sz64 = sz & PCI_ROM_ADDRESS_MASK;
                mask64 = (u32)PCI_ROM_ADDRESS_MASK;
index bdc23ce..9236e40 100644 (file)
@@ -3137,8 +3137,9 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b5, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x22b7, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2298, quirk_remove_d3_delay);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x229c, quirk_remove_d3_delay);
+
 /*
- * Some devices may pass our check in pci_intx_mask_supported if
+ * Some devices may pass our check in pci_intx_mask_supported() if
  * PCI_COMMAND_INTX_DISABLE works though they actually do not properly
  * support this feature.
  */
@@ -3146,53 +3147,139 @@ static void quirk_broken_intx_masking(struct pci_dev *dev)
 {
        dev->broken_intx_masking = 1;
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
-                        quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, 0x0030,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
+                       quirk_broken_intx_masking);
+
 /*
  * Realtek RTL8169 PCI Gigabit Ethernet Controller (rev 10)
  * Subsystem: Realtek RTL8169/8110 Family PCI Gigabit Ethernet NIC
  *
  * RTL8110SC - Fails under PCI device assignment using DisINTx masking.
  */
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, PCI_ANY_ID,
-                        quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, 0x8169,
+                       quirk_broken_intx_masking);
 
 /*
  * Intel i40e (XL710/X710) 10/20/40GbE NICs all have broken INTx masking,
  * DisINTx can be set but the interrupt status bit is non-functional.
  */
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1572,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1574,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1580,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1581,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1583,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1584,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1585,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1586,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1587,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1588,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1589,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d0,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d1,
-                        quirk_broken_intx_masking);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x37d2,
-                        quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1572,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1574,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1580,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1581,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1583,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1584,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1585,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1586,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1587,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1588,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1589,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x37d0,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x37d1,
+                       quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x37d2,
+                       quirk_broken_intx_masking);
+
+static u16 mellanox_broken_intx_devs[] = {
+       PCI_DEVICE_ID_MELLANOX_HERMON_SDR,
+       PCI_DEVICE_ID_MELLANOX_HERMON_DDR,
+       PCI_DEVICE_ID_MELLANOX_HERMON_QDR,
+       PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2,
+       PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2,
+       PCI_DEVICE_ID_MELLANOX_HERMON_EN,
+       PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX_EN,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX2,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX3,
+       PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO,
+};
+
+#define CONNECTX_4_CURR_MAX_MINOR 99
+#define CONNECTX_4_INTX_SUPPORT_MINOR 14
+
+/*
+ * Check ConnectX-4/LX FW version to see if it supports legacy interrupts.
+ * If so, don't mark it as broken.
+ * FW minor > 99 means older FW version format and no INTx masking support.
+ * FW minor < 14 means new FW version format and no INTx masking support.
+ */
+static void mellanox_check_broken_intx_masking(struct pci_dev *pdev)
+{
+       __be32 __iomem *fw_ver;
+       u16 fw_major;
+       u16 fw_minor;
+       u16 fw_subminor;
+       u32 fw_maj_min;
+       u32 fw_sub_min;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mellanox_broken_intx_devs); i++) {
+               if (pdev->device == mellanox_broken_intx_devs[i]) {
+                       pdev->broken_intx_masking = 1;
+                       return;
+               }
+       }
+
+       /* Getting here means Connect-IB cards and up. Connect-IB has no INTx
+        * support so shouldn't be checked further
+        */
+       if (pdev->device == PCI_DEVICE_ID_MELLANOX_CONNECTIB)
+               return;
+
+       if (pdev->device != PCI_DEVICE_ID_MELLANOX_CONNECTX4 &&
+           pdev->device != PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX)
+               return;
+
+       /* For ConnectX-4 and ConnectX-4LX, need to check FW support */
+       if (pci_enable_device_mem(pdev)) {
+               dev_warn(&pdev->dev, "Can't enable device memory\n");
+               return;
+       }
+
+       fw_ver = ioremap(pci_resource_start(pdev, 0), 4);
+       if (!fw_ver) {
+               dev_warn(&pdev->dev, "Can't map ConnectX-4 initialization segment\n");
+               goto out;
+       }
+
+       /* Reading from resource space should be 32b aligned */
+       fw_maj_min = ioread32be(fw_ver);
+       fw_sub_min = ioread32be(fw_ver + 1);
+       fw_major = fw_maj_min & 0xffff;
+       fw_minor = fw_maj_min >> 16;
+       fw_subminor = fw_sub_min & 0xffff;
+       if (fw_minor > CONNECTX_4_CURR_MAX_MINOR ||
+           fw_minor < CONNECTX_4_INTX_SUPPORT_MINOR) {
+               dev_warn(&pdev->dev, "ConnectX-4: FW %u.%u.%u doesn't support INTx masking, disabling. Please upgrade FW to %d.14.1100 and up for INTx support\n",
+                        fw_major, fw_minor, fw_subminor, pdev->device ==
+                        PCI_DEVICE_ID_MELLANOX_CONNECTX4 ? 12 : 14);
+               pdev->broken_intx_masking = 1;
+       }
+
+       iounmap(fw_ver);
+
+out:
+       pci_disable_device(pdev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX, PCI_ANY_ID,
+                       mellanox_check_broken_intx_masking);
 
 static void quirk_no_bus_reset(struct pci_dev *dev)
 {
index 06663d3..b6edb18 100644 (file)
@@ -35,6 +35,11 @@ int pci_enable_rom(struct pci_dev *pdev)
        if (res->flags & IORESOURCE_ROM_SHADOW)
                return 0;
 
+       /*
+        * Ideally pci_update_resource() would update the ROM BAR address,
+        * and we would only set the enable bit here.  But apparently some
+        * devices have buggy ROM BARs that read as zero when disabled.
+        */
        pcibios_resource_to_bus(pdev->bus, &region, res);
        pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
        rom_addr &= ~PCI_ROM_ADDRESS_MASK;
index 66c4d8f..0454273 100644 (file)
 #include <linux/slab.h>
 #include "pci.h"
 
-
-void pci_update_resource(struct pci_dev *dev, int resno)
+static void pci_std_update_resource(struct pci_dev *dev, int resno)
 {
        struct pci_bus_region region;
        bool disable;
        u16 cmd;
        u32 new, check, mask;
        int reg;
-       enum pci_bar_type type;
        struct resource *res = dev->resource + resno;
 
-       if (dev->is_virtfn) {
-               dev_warn(&dev->dev, "can't update VF BAR%d\n", resno);
+       /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
+       if (dev->is_virtfn)
                return;
-       }
 
        /*
         * Ignore resources for unimplemented BARs and unused resource slots
@@ -60,21 +57,34 @@ void pci_update_resource(struct pci_dev *dev, int resno)
                return;
 
        pcibios_resource_to_bus(dev->bus, &region, res);
+       new = region.start;
 
-       new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
-       if (res->flags & IORESOURCE_IO)
+       if (res->flags & IORESOURCE_IO) {
                mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
-       else
+               new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
+       } else if (resno == PCI_ROM_RESOURCE) {
+               mask = (u32)PCI_ROM_ADDRESS_MASK;
+       } else {
                mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+               new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
+       }
 
-       reg = pci_resource_bar(dev, resno, &type);
-       if (!reg)
-               return;
-       if (type != pci_bar_unknown) {
+       if (resno < PCI_ROM_RESOURCE) {
+               reg = PCI_BASE_ADDRESS_0 + 4 * resno;
+       } else if (resno == PCI_ROM_RESOURCE) {
+
+               /*
+                * Apparently some Matrox devices have ROM BARs that read
+                * as zero when disabled, so don't update ROM BARs unless
+                * they're enabled.  See https://lkml.org/lkml/2005/8/30/138.
+                */
                if (!(res->flags & IORESOURCE_ROM_ENABLE))
                        return;
+
+               reg = dev->rom_base_reg;
                new |= PCI_ROM_ADDRESS_ENABLE;
-       }
+       } else
+               return;
 
        /*
         * We can't update a 64-bit BAR atomically, so when possible,
@@ -110,6 +120,16 @@ void pci_update_resource(struct pci_dev *dev, int resno)
                pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
+void pci_update_resource(struct pci_dev *dev, int resno)
+{
+       if (resno <= PCI_ROM_RESOURCE)
+               pci_std_update_resource(dev, resno);
+#ifdef CONFIG_PCI_IOV
+       else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
+               pci_iov_update_resource(dev, resno);
+#endif
+}
+
 int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];
index c58752f..f020ab4 100644 (file)
 #define PCI_DEVICE_ID_ZOLTRIX_2BD0     0x2bd0
 
 #define PCI_VENDOR_ID_MELLANOX         0x15b3
-#define PCI_DEVICE_ID_MELLANOX_TAVOR   0x5a44
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX3       0x1003
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO   0x1007
+#define PCI_DEVICE_ID_MELLANOX_CONNECTIB       0x1011
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX4       0x1013
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX4_LX    0x1015
+#define PCI_DEVICE_ID_MELLANOX_TAVOR           0x5a44
 #define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE    0x5a46
-#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278
-#define PCI_DEVICE_ID_MELLANOX_ARBEL   0x6282
-#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
-#define PCI_DEVICE_ID_MELLANOX_SINAI   0x6274
+#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD       0x5e8c
+#define PCI_DEVICE_ID_MELLANOX_SINAI           0x6274
+#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT    0x6278
+#define PCI_DEVICE_ID_MELLANOX_ARBEL           0x6282
+#define PCI_DEVICE_ID_MELLANOX_HERMON_SDR      0x6340
+#define PCI_DEVICE_ID_MELLANOX_HERMON_DDR      0x634a
+#define PCI_DEVICE_ID_MELLANOX_HERMON_QDR      0x6354
+#define PCI_DEVICE_ID_MELLANOX_HERMON_EN       0x6368
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN     0x6372
+#define PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2 0x6732
+#define PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2 0x673c
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2 0x6746
+#define PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2  0x6750
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2 0x675a
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2        0x6764
+#define PCI_DEVICE_ID_MELLANOX_CONNECTX2       0x676e
 
 #define PCI_VENDOR_ID_DFI              0x15bd