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()
This commit is contained in:
commit
fd83941d50
@ -3147,6 +3147,8 @@
|
||||
on: Turn realloc on
|
||||
realloc same as realloc=on
|
||||
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
|
||||
only look for one device below a PCIe downstream
|
||||
port.
|
||||
|
@ -355,6 +355,9 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev)
|
||||
};
|
||||
int i, pos;
|
||||
|
||||
if (pci_ats_disabled())
|
||||
return false;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
pos = pci_find_ext_capability(pdev, caps[i]);
|
||||
if (pos == 0)
|
||||
@ -3524,9 +3527,11 @@ int amd_iommu_device_info(struct pci_dev *pdev,
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
|
||||
if (pos)
|
||||
info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP;
|
||||
if (!pci_ats_disabled()) {
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS);
|
||||
if (pos)
|
||||
info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP;
|
||||
}
|
||||
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
|
||||
if (pos)
|
||||
|
@ -2459,7 +2459,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
|
||||
if (dev && dev_is_pci(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) &&
|
||||
dmar_find_matched_atsr_unit(pdev))
|
||||
info->ats_supported = 1;
|
||||
|
@ -3385,32 +3385,6 @@ err_disable_device:
|
||||
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
|
||||
@ -3526,7 +3500,7 @@ static struct pci_driver ena_pci_driver = {
|
||||
.suspend = ena_suspend,
|
||||
.resume = ena_resume,
|
||||
#endif
|
||||
.sriov_configure = ena_sriov_configure,
|
||||
.sriov_configure = pci_sriov_configure_simple,
|
||||
};
|
||||
|
||||
static int __init ena_init(void)
|
||||
|
@ -2598,24 +2598,6 @@ static void nvme_remove(struct pci_dev *pdev)
|
||||
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
|
||||
static int nvme_suspend(struct device *dev)
|
||||
{
|
||||
@ -2734,7 +2716,7 @@ static struct pci_driver nvme_driver = {
|
||||
.driver = {
|
||||
.pm = &nvme_dev_pm_ops,
|
||||
},
|
||||
.sriov_configure = nvme_pci_sriov_configure,
|
||||
.sriov_configure = pci_sriov_configure_simple,
|
||||
.err_handler = &nvme_err_handler,
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
54
drivers/pci/pci-pf-stub.c
Normal file
54
drivers/pci/pci-pf-stub.c
Normal file
@ -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");
|
@ -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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1485,6 +1485,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
|
||||
static inline void pcie_ecrc_get_policy(char *str) { }
|
||||
#endif
|
||||
|
||||
bool pci_ats_disabled(void);
|
||||
|
||||
#ifdef CONFIG_PCI_ATS
|
||||
/* Address Translation Service */
|
||||
void pci_ats_init(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_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
|
||||
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);
|
||||
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)
|
||||
{ return 0; }
|
||||
static inline int pci_sriov_get_totalvfs(struct pci_dev *dev)
|
||||
{ return 0; }
|
||||
#define pci_sriov_configure_simple NULL
|
||||
static inline resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
|
||||
{ return 0; }
|
||||
static inline void pci_vf_drivers_autoprobe(struct pci_dev *dev, bool probe) { }
|
||||
|
@ -2555,6 +2555,8 @@
|
||||
#define PCI_VENDOR_ID_CIRCUITCO 0x1cc8
|
||||
#define PCI_SUBSYSTEM_ID_CIRCUITCO_MINNOWBOARD 0x0001
|
||||
|
||||
#define PCI_VENDOR_ID_AMAZON 0x1d0f
|
||||
|
||||
#define PCI_VENDOR_ID_TEKRAM 0x1de1
|
||||
#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user