提交 fd83941d 编写于 作者: B Bjorn Helgaas

Merge branch 'pci/virtualization'

  - add generic enable function for simple SR-IOV hardware (Alexander
    Duyck)

  - use generic SR-IOV enable for ena, nvme (Alexander Duyck)

  - add ACS quirk for Intel 7th & 8th Gen mobile (Alex Williamson)

  - add ACS quirk for Intel 300 series (Mika Westerberg)

* pci/virtualization:
  PCI/IOV: Allow PF drivers to limit total_VFs to 0
  PCI: Add "pci=noats" boot parameter
  PCI: Add ACS quirk for Intel 300 series
  PCI: Add ACS quirk for Intel 7th & 8th Gen mobile
  nvme-pci: Use pci_sriov_configure_simple() to enable VFs
  net: ena: Use pci_sriov_configure_simple() to enable VFs
  PCI/IOV: Add pci-pf-stub driver for PFs that only enable VFs
  PCI/IOV: Add pci_sriov_configure_simple()
...@@ -3147,6 +3147,8 @@ ...@@ -3147,6 +3147,8 @@
on: Turn realloc on on: Turn realloc on
realloc same as realloc=on realloc same as realloc=on
noari do not use PCIe ARI. noari do not use PCIe ARI.
noats [PCIE, Intel-IOMMU, AMD-IOMMU]
do not use PCIe ATS (and IOMMU device IOTLB).
pcie_scan_all Scan all possible PCIe devices. Otherwise we pcie_scan_all Scan all possible PCIe devices. Otherwise we
only look for one device below a PCIe downstream only look for one device below a PCIe downstream
port. port.
......
...@@ -355,6 +355,9 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev) ...@@ -355,6 +355,9 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev)
}; };
int i, pos; int i, pos;
if (pci_ats_disabled())
return false;
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
pos = pci_find_ext_capability(pdev, caps[i]); pos = pci_find_ext_capability(pdev, caps[i]);
if (pos == 0) if (pos == 0)
...@@ -3524,9 +3527,11 @@ int amd_iommu_device_info(struct pci_dev *pdev, ...@@ -3524,9 +3527,11 @@ int amd_iommu_device_info(struct pci_dev *pdev,
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
if (!pci_ats_disabled()) {
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
if (pos) if (pos)
info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP;
}
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (pos) if (pos)
......
...@@ -2459,7 +2459,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, ...@@ -2459,7 +2459,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (dev && dev_is_pci(dev)) { if (dev && dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(info->dev); struct pci_dev *pdev = to_pci_dev(info->dev);
if (ecap_dev_iotlb_support(iommu->ecap) && if (!pci_ats_disabled() &&
ecap_dev_iotlb_support(iommu->ecap) &&
pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) && pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
dmar_find_matched_atsr_unit(pdev)) dmar_find_matched_atsr_unit(pdev))
info->ats_supported = 1; info->ats_supported = 1;
......
...@@ -3385,32 +3385,6 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3385,32 +3385,6 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
} }
/*****************************************************************************/
static int ena_sriov_configure(struct pci_dev *dev, int numvfs)
{
int rc;
if (numvfs > 0) {
rc = pci_enable_sriov(dev, numvfs);
if (rc != 0) {
dev_err(&dev->dev,
"pci_enable_sriov failed to enable: %d vfs with the error: %d\n",
numvfs, rc);
return rc;
}
return numvfs;
}
if (numvfs == 0) {
pci_disable_sriov(dev);
return 0;
}
return -EINVAL;
}
/*****************************************************************************/
/*****************************************************************************/ /*****************************************************************************/
/* ena_remove - Device Removal Routine /* ena_remove - Device Removal Routine
...@@ -3526,7 +3500,7 @@ static struct pci_driver ena_pci_driver = { ...@@ -3526,7 +3500,7 @@ static struct pci_driver ena_pci_driver = {
.suspend = ena_suspend, .suspend = ena_suspend,
.resume = ena_resume, .resume = ena_resume,
#endif #endif
.sriov_configure = ena_sriov_configure, .sriov_configure = pci_sriov_configure_simple,
}; };
static int __init ena_init(void) static int __init ena_init(void)
......
...@@ -2598,24 +2598,6 @@ static void nvme_remove(struct pci_dev *pdev) ...@@ -2598,24 +2598,6 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_put_ctrl(&dev->ctrl); nvme_put_ctrl(&dev->ctrl);
} }
static int nvme_pci_sriov_configure(struct pci_dev *pdev, int numvfs)
{
int ret = 0;
if (numvfs == 0) {
if (pci_vfs_assigned(pdev)) {
dev_warn(&pdev->dev,
"Cannot disable SR-IOV VFs while assigned\n");
return -EPERM;
}
pci_disable_sriov(pdev);
return 0;
}
ret = pci_enable_sriov(pdev, numvfs);
return ret ? ret : numvfs;
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int nvme_suspend(struct device *dev) static int nvme_suspend(struct device *dev)
{ {
...@@ -2734,7 +2716,7 @@ static struct pci_driver nvme_driver = { ...@@ -2734,7 +2716,7 @@ static struct pci_driver nvme_driver = {
.driver = { .driver = {
.pm = &nvme_dev_pm_ops, .pm = &nvme_dev_pm_ops,
}, },
.sriov_configure = nvme_pci_sriov_configure, .sriov_configure = pci_sriov_configure_simple,
.err_handler = &nvme_err_handler, .err_handler = &nvme_err_handler,
}; };
......
...@@ -71,6 +71,18 @@ config PCI_STUB ...@@ -71,6 +71,18 @@ config PCI_STUB
When in doubt, say N. When in doubt, say N.
config PCI_PF_STUB
tristate "PCI PF Stub driver"
depends on PCI
depends on PCI_IOV
help
Say Y or M here if you want to enable support for devices that
require SR-IOV support, while at the same time the PF itself is
not providing any actual services on the host itself such as
storage or networking.
When in doubt, say N.
config XEN_PCIDEV_FRONTEND config XEN_PCIDEV_FRONTEND
tristate "Xen PCI Frontend" tristate "Xen PCI Frontend"
depends on PCI && X86 && XEN depends on PCI && X86 && XEN
......
...@@ -24,6 +24,7 @@ obj-$(CONFIG_PCI_LABEL) += pci-label.o ...@@ -24,6 +24,7 @@ obj-$(CONFIG_PCI_LABEL) += pci-label.o
obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o
obj-$(CONFIG_PCI_SYSCALL) += syscall.o obj-$(CONFIG_PCI_SYSCALL) += syscall.o
obj-$(CONFIG_PCI_STUB) += pci-stub.o obj-$(CONFIG_PCI_STUB) += pci-stub.o
obj-$(CONFIG_PCI_PF_STUB) += pci-pf-stub.o
obj-$(CONFIG_PCI_ECAM) += ecam.o obj-$(CONFIG_PCI_ECAM) += ecam.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
......
...@@ -20,6 +20,9 @@ void pci_ats_init(struct pci_dev *dev) ...@@ -20,6 +20,9 @@ void pci_ats_init(struct pci_dev *dev)
{ {
int pos; int pos;
if (pci_ats_disabled())
return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
if (!pos) if (!pos)
return; return;
......
...@@ -469,6 +469,7 @@ static int sriov_init(struct pci_dev *dev, int pos) ...@@ -469,6 +469,7 @@ static int sriov_init(struct pci_dev *dev, int pos)
iov->nres = nres; iov->nres = nres;
iov->ctrl = ctrl; iov->ctrl = ctrl;
iov->total_VFs = total; iov->total_VFs = total;
iov->driver_max_VFs = total;
pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device); pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device);
iov->pgsz = pgsz; iov->pgsz = pgsz;
iov->self = dev; iov->self = dev;
...@@ -827,9 +828,42 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev) ...@@ -827,9 +828,42 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev)
if (!dev->is_physfn) if (!dev->is_physfn)
return 0; return 0;
if (dev->sriov->driver_max_VFs)
return dev->sriov->driver_max_VFs; return dev->sriov->driver_max_VFs;
return dev->sriov->total_VFs;
} }
EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs); EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
/**
* pci_sriov_configure_simple - helper to configure SR-IOV
* @dev: the PCI device
* @nr_virtfn: number of virtual functions to enable, 0 to disable
*
* Enable or disable SR-IOV for devices that don't require any PF setup
* before enabling SR-IOV. Return value is negative on error, or number of
* VFs allocated on success.
*/
int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn)
{
int rc;
might_sleep();
if (!dev->is_physfn)
return -ENODEV;
if (pci_vfs_assigned(dev)) {
pci_warn(dev, "Cannot modify SR-IOV while VFs are assigned\n");
return -EPERM;
}
if (nr_virtfn == 0) {
sriov_disable(dev);
return 0;
}
rc = sriov_enable(dev, nr_virtfn);
if (rc < 0)
return rc;
return nr_virtfn;
}
EXPORT_SYMBOL_GPL(pci_sriov_configure_simple);
// SPDX-License-Identifier: GPL-2.0
/* pci-pf-stub - simple stub driver for PCI SR-IOV PF device
*
* This driver is meant to act as a "whitelist" for devices that provde
* SR-IOV functionality while at the same time not actually needing a
* driver of their own.
*/
#include <linux/module.h>
#include <linux/pci.h>
/**
* pci_pf_stub_whitelist - White list of devices to bind pci-pf-stub onto
*
* This table provides the list of IDs this driver is supposed to bind
* onto. You could think of this as a list of "quirked" devices where we
* are adding support for SR-IOV here since there are no other drivers
* that they would be running under.
*/
static const struct pci_device_id pci_pf_stub_whitelist[] = {
{ PCI_VDEVICE(AMAZON, 0x0053) },
/* required last entry */
{ 0 }
};
MODULE_DEVICE_TABLE(pci, pci_pf_stub_whitelist);
static int pci_pf_stub_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
pci_info(dev, "claimed by pci-pf-stub\n");
return 0;
}
static struct pci_driver pf_stub_driver = {
.name = "pci-pf-stub",
.id_table = pci_pf_stub_whitelist,
.probe = pci_pf_stub_probe,
.sriov_configure = pci_sriov_configure_simple,
};
static int __init pci_pf_stub_init(void)
{
return pci_register_driver(&pf_stub_driver);
}
static void __exit pci_pf_stub_exit(void)
{
pci_unregister_driver(&pf_stub_driver);
}
module_init(pci_pf_stub_init);
module_exit(pci_pf_stub_exit);
MODULE_LICENSE("GPL");
...@@ -112,6 +112,14 @@ unsigned int pcibios_max_latency = 255; ...@@ -112,6 +112,14 @@ unsigned int pcibios_max_latency = 255;
/* If set, the PCIe ARI capability will not be used. */ /* If set, the PCIe ARI capability will not be used. */
static bool pcie_ari_disabled; static bool pcie_ari_disabled;
/* If set, the PCIe ATS capability will not be used. */
static bool pcie_ats_disabled;
bool pci_ats_disabled(void)
{
return pcie_ats_disabled;
}
/* Disable bridge_d3 for all PCIe ports */ /* Disable bridge_d3 for all PCIe ports */
static bool pci_bridge_d3_disable; static bool pci_bridge_d3_disable;
/* Force bridge_d3 for all PCIe ports */ /* Force bridge_d3 for all PCIe ports */
...@@ -5777,6 +5785,9 @@ static int __init pci_setup(char *str) ...@@ -5777,6 +5785,9 @@ static int __init pci_setup(char *str)
if (*str && (str = pcibios_setup(str)) && *str) { if (*str && (str = pcibios_setup(str)) && *str) {
if (!strcmp(str, "nomsi")) { if (!strcmp(str, "nomsi")) {
pci_no_msi(); pci_no_msi();
} else if (!strncmp(str, "noats", 5)) {
pr_info("PCIe: ATS is disabled\n");
pcie_ats_disabled = true;
} else if (!strcmp(str, "noaer")) { } else if (!strcmp(str, "noaer")) {
pci_no_aer(); pci_no_aer();
} else if (!strncmp(str, "realloc=", 8)) { } else if (!strncmp(str, "realloc=", 8)) {
......
...@@ -4230,11 +4230,29 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags) ...@@ -4230,11 +4230,29 @@ static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags)
* 0xa290-0xa29f PCI Express Root port #{0-16} * 0xa290-0xa29f PCI Express Root port #{0-16}
* 0xa2e7-0xa2ee PCI Express Root port #{17-24} * 0xa2e7-0xa2ee PCI Express Root port #{17-24}
* *
* Mobile chipsets are also affected, 7th & 8th Generation
* Specification update confirms ACS errata 22, status no fix: (7th Generation
* Intel Processor Family I/O for U/Y Platforms and 8th Generation Intel
* Processor Family I/O for U Quad Core Platforms Specification Update,
* August 2017, Revision 002, Document#: 334660-002)[6]
* Device IDs from I/O datasheet: (7th Generation Intel Processor Family I/O
* for U/Y Platforms and 8th Generation Intel ® Processor Family I/O for U
* Quad Core Platforms, Vol 1 of 2, August 2017, Document#: 334658-003)[7]
*
* 0x9d10-0x9d1b PCI Express Root port #{1-12}
*
* The 300 series chipset suffers from the same bug so include those root
* ports here as well.
*
* 0xa32c-0xa343 PCI Express Root port #{0-24}
*
* [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html
* [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html
* [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html
* [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html * [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html
* [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html * [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html
* [6] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-spec-update.html
* [7] https://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-u-y-processor-lines-i-o-datasheet-vol-1.html
*/ */
static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev)
{ {
...@@ -4244,6 +4262,8 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) ...@@ -4244,6 +4262,8 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev)
switch (dev->device) { switch (dev->device) {
case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */
case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */
case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */
case 0xa32c ... 0xa343: /* 300 series */
return true; return true;
} }
......
...@@ -1485,6 +1485,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { } ...@@ -1485,6 +1485,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
static inline void pcie_ecrc_get_policy(char *str) { } static inline void pcie_ecrc_get_policy(char *str) { }
#endif #endif
bool pci_ats_disabled(void);
#ifdef CONFIG_PCI_ATS #ifdef CONFIG_PCI_ATS
/* Address Translation Service */ /* Address Translation Service */
void pci_ats_init(struct pci_dev *dev); void pci_ats_init(struct pci_dev *dev);
...@@ -1957,6 +1959,7 @@ int pci_num_vf(struct pci_dev *dev); ...@@ -1957,6 +1959,7 @@ int pci_num_vf(struct pci_dev *dev);
int pci_vfs_assigned(struct pci_dev *dev); int pci_vfs_assigned(struct pci_dev *dev);
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
int pci_sriov_get_totalvfs(struct pci_dev *dev); int pci_sriov_get_totalvfs(struct pci_dev *dev);
int pci_sriov_configure_simple(struct pci_dev *dev, int nr_virtfn);
resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno); resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno);
void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe); void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe);
...@@ -1989,6 +1992,7 @@ static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) ...@@ -1989,6 +1992,7 @@ static inline int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
{ return 0; } { return 0; }
static inline int pci_sriov_get_totalvfs(struct pci_dev *dev) static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
{ return 0; } { return 0; }
#define pci_sriov_configure_simple NULL
static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno) static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
{ return 0; } { return 0; }
static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { } static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { }
......
...@@ -2555,6 +2555,8 @@ ...@@ -2555,6 +2555,8 @@
#define PCI_VENDOR_ID_CIRCUITCO 0x1cc8 #define PCI_VENDOR_ID_CIRCUITCO 0x1cc8
#define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001 #define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001
#define PCI_VENDOR_ID_AMAZON 0x1d0f
#define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_VENDOR_ID_TEKRAM 0x1de1
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册