diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Kconfig | 12 | ||||
-rw-r--r-- | drivers/pci/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/ats.c | 3 | ||||
-rw-r--r-- | drivers/pci/iov.c | 42 | ||||
-rw-r--r-- | drivers/pci/pci-pf-stub.c | 54 | ||||
-rw-r--r-- | drivers/pci/pci.c | 11 | ||||
-rw-r--r-- | drivers/pci/quirks.c | 20 |
7 files changed, 139 insertions, 4 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 34b56a8f8480..cdef2a2a9bc5 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -71,6 +71,18 @@ config PCI_STUB 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 tristate "Xen PCI Frontend" depends on PCI && X86 && XEN diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 952addc7bacf..84c9eef6b1c3 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_PCI_LABEL) += pci-label.o obj-$(CONFIG_X86_INTEL_MID) += pci-mid.o obj-$(CONFIG_PCI_SYSCALL) += syscall.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_XEN_PCIDEV_FRONTEND) += xen-pcifront.o diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 89305b569d3d..4923a2a8e14b 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -20,6 +20,9 @@ void pci_ats_init(struct pci_dev *dev) { int pos; + if (pci_ats_disabled()) + return; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); if (!pos) return; diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 8adf4a64f291..d0d73dbbd5ca 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -469,6 +469,7 @@ found: iov->nres = nres; iov->ctrl = ctrl; iov->total_VFs = total; + iov->driver_max_VFs = total; pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &iov->vf_device); iov->pgsz = pgsz; iov->self = dev; @@ -827,9 +828,42 @@ int pci_sriov_get_totalvfs(struct pci_dev *dev) if (!dev->is_physfn) return 0; - if (dev->sriov->driver_max_VFs) - return dev->sriov->driver_max_VFs; - - return dev->sriov->total_VFs; + return dev->sriov->driver_max_VFs; } 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); diff --git a/drivers/pci/pci-pf-stub.c b/drivers/pci/pci-pf-stub.c new file mode 100644 index 000000000000..9795649fc6f9 --- /dev/null +++ b/drivers/pci/pci-pf-stub.c @@ -0,0 +1,54 @@ +// 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"); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 1da93e6e8623..b345d20227b8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -112,6 +112,14 @@ unsigned int pcibios_max_latency = 255; /* If set, the PCIe ARI capability will not be used. */ 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 */ static bool pci_bridge_d3_disable; /* Force bridge_d3 for all PCIe ports */ @@ -5777,6 +5785,9 @@ static int __init pci_setup(char *str) if (*str && (str = pcibios_setup(str)) && *str) { if (!strcmp(str, "nomsi")) { 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")) { pci_no_aer(); } else if (!strncmp(str, "realloc=", 8)) { diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e7bf44515fd6..341d3a138217 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -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} * 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 * [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 * [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 + * [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) { @@ -4244,6 +4262,8 @@ static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) switch (dev->device) { case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */ case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */ + case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */ + case 0xa32c ... 0xa343: /* 300 series */ return true; } |