2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-20 19:23:57 +08:00

Merge branch 'pci/virtualization' into next

* 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
This commit is contained in:
Bjorn Helgaas 2016-12-12 11:25:05 -06:00
commit 2583157141
9 changed files with 286 additions and 153 deletions

View 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, }
};

View 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;
BUG_ON(!dev->is_physfn);
/*
* 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;
return dev->sriov->pos + PCI_SRIOV_BAR +
4 * (resno - PCI_IOV_RESOURCES);
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;
pcibios_resource_to_bus(dev->bus, &region, res);
new = region.start;
new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
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,

View 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;

View 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)
{
}

View 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;

View 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)
{

View 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;

View File

@ -25,21 +25,18 @@
#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];

View File

@ -2256,12 +2256,29 @@
#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