aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2017-02-15 12:56:11 -0500
committerBjorn Helgaas <bhelgaas@google.com>2017-02-15 12:56:11 -0500
commit8b9c156262f9ebaa88736b93263c1af5ae5fa43e (patch)
treed86c3b6a072f4a0374c0da17999281a72128b468
parent0dc49eb2a25a6b48e235803eeb2b52677f577ca5 (diff)
parent5b0948dfe138f0837699f46f5877f4f81c252dac (diff)
Merge branch 'pci/virtualization' into next
* pci/virtualization: PCI: Lock each enable/disable num_vfs operation in sysfs PCI: Add ACS quirk for Intel Union Point
-rw-r--r--drivers/pci/iov.c7
-rw-r--r--drivers/pci/pci-sysfs.c23
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/quirks.c28
4 files changed, 41 insertions, 19 deletions
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 47227820406d..2479ae876482 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -124,7 +124,6 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
124 struct pci_sriov *iov = dev->sriov; 124 struct pci_sriov *iov = dev->sriov;
125 struct pci_bus *bus; 125 struct pci_bus *bus;
126 126
127 mutex_lock(&iov->dev->sriov->lock);
128 bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id)); 127 bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id));
129 if (!bus) 128 if (!bus)
130 goto failed; 129 goto failed;
@@ -162,7 +161,6 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
162 __pci_reset_function(virtfn); 161 __pci_reset_function(virtfn);
163 162
164 pci_device_add(virtfn, virtfn->bus); 163 pci_device_add(virtfn, virtfn->bus);
165 mutex_unlock(&iov->dev->sriov->lock);
166 164
167 pci_bus_add_device(virtfn); 165 pci_bus_add_device(virtfn);
168 sprintf(buf, "virtfn%u", id); 166 sprintf(buf, "virtfn%u", id);
@@ -181,12 +179,10 @@ failed2:
181 sysfs_remove_link(&dev->dev.kobj, buf); 179 sysfs_remove_link(&dev->dev.kobj, buf);
182failed1: 180failed1:
183 pci_dev_put(dev); 181 pci_dev_put(dev);
184 mutex_lock(&iov->dev->sriov->lock);
185 pci_stop_and_remove_bus_device(virtfn); 182 pci_stop_and_remove_bus_device(virtfn);
186failed0: 183failed0:
187 virtfn_remove_bus(dev->bus, bus); 184 virtfn_remove_bus(dev->bus, bus);
188failed: 185failed:
189 mutex_unlock(&iov->dev->sriov->lock);
190 186
191 return rc; 187 return rc;
192} 188}
@@ -195,7 +191,6 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset)
195{ 191{
196 char buf[VIRTFN_ID_LEN]; 192 char buf[VIRTFN_ID_LEN];
197 struct pci_dev *virtfn; 193 struct pci_dev *virtfn;
198 struct pci_sriov *iov = dev->sriov;
199 194
200 virtfn = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus), 195 virtfn = pci_get_domain_bus_and_slot(pci_domain_nr(dev->bus),
201 pci_iov_virtfn_bus(dev, id), 196 pci_iov_virtfn_bus(dev, id),
@@ -218,10 +213,8 @@ void pci_iov_remove_virtfn(struct pci_dev *dev, int id, int reset)
218 if (virtfn->dev.kobj.sd) 213 if (virtfn->dev.kobj.sd)
219 sysfs_remove_link(&virtfn->dev.kobj, "physfn"); 214 sysfs_remove_link(&virtfn->dev.kobj, "physfn");
220 215
221 mutex_lock(&iov->dev->sriov->lock);
222 pci_stop_and_remove_bus_device(virtfn); 216 pci_stop_and_remove_bus_device(virtfn);
223 virtfn_remove_bus(dev->bus, virtfn->bus); 217 virtfn_remove_bus(dev->bus, virtfn->bus);
224 mutex_unlock(&iov->dev->sriov->lock);
225 218
226 /* balance pci_get_domain_bus_and_slot() */ 219 /* balance pci_get_domain_bus_and_slot() */
227 pci_dev_put(virtfn); 220 pci_dev_put(virtfn);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 066628776e1b..25d010d449a3 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -472,6 +472,7 @@ static ssize_t sriov_numvfs_store(struct device *dev,
472 const char *buf, size_t count) 472 const char *buf, size_t count)
473{ 473{
474 struct pci_dev *pdev = to_pci_dev(dev); 474 struct pci_dev *pdev = to_pci_dev(dev);
475 struct pci_sriov *iov = pdev->sriov;
475 int ret; 476 int ret;
476 u16 num_vfs; 477 u16 num_vfs;
477 478
@@ -482,38 +483,46 @@ static ssize_t sriov_numvfs_store(struct device *dev,
482 if (num_vfs > pci_sriov_get_totalvfs(pdev)) 483 if (num_vfs > pci_sriov_get_totalvfs(pdev))
483 return -ERANGE; 484 return -ERANGE;
484 485
486 mutex_lock(&iov->dev->sriov->lock);
487
485 if (num_vfs == pdev->sriov->num_VFs) 488 if (num_vfs == pdev->sriov->num_VFs)
486 return count; /* no change */ 489 goto exit;
487 490
488 /* is PF driver loaded w/callback */ 491 /* is PF driver loaded w/callback */
489 if (!pdev->driver || !pdev->driver->sriov_configure) { 492 if (!pdev->driver || !pdev->driver->sriov_configure) {
490 dev_info(&pdev->dev, "Driver doesn't support SRIOV configuration via sysfs\n"); 493 dev_info(&pdev->dev, "Driver doesn't support SRIOV configuration via sysfs\n");
491 return -ENOSYS; 494 ret = -ENOENT;
495 goto exit;
492 } 496 }
493 497
494 if (num_vfs == 0) { 498 if (num_vfs == 0) {
495 /* disable VFs */ 499 /* disable VFs */
496 ret = pdev->driver->sriov_configure(pdev, 0); 500 ret = pdev->driver->sriov_configure(pdev, 0);
497 if (ret < 0) 501 goto exit;
498 return ret;
499 return count;
500 } 502 }
501 503
502 /* enable VFs */ 504 /* enable VFs */
503 if (pdev->sriov->num_VFs) { 505 if (pdev->sriov->num_VFs) {
504 dev_warn(&pdev->dev, "%d VFs already enabled. Disable before enabling %d VFs\n", 506 dev_warn(&pdev->dev, "%d VFs already enabled. Disable before enabling %d VFs\n",
505 pdev->sriov->num_VFs, num_vfs); 507 pdev->sriov->num_VFs, num_vfs);
506 return -EBUSY; 508 ret = -EBUSY;
509 goto exit;
507 } 510 }
508 511
509 ret = pdev->driver->sriov_configure(pdev, num_vfs); 512 ret = pdev->driver->sriov_configure(pdev, num_vfs);
510 if (ret < 0) 513 if (ret < 0)
511 return ret; 514 goto exit;
512 515
513 if (ret != num_vfs) 516 if (ret != num_vfs)
514 dev_warn(&pdev->dev, "%d VFs requested; only %d enabled\n", 517 dev_warn(&pdev->dev, "%d VFs requested; only %d enabled\n",
515 num_vfs, ret); 518 num_vfs, ret);
516 519
520exit:
521 mutex_unlock(&iov->dev->sriov->lock);
522
523 if (ret < 0)
524 return ret;
525
517 return count; 526 return count;
518} 527}
519 528
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index cb17db242f30..8dd38e69d6f2 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -270,7 +270,7 @@ struct pci_sriov {
270 u16 driver_max_VFs; /* max num VFs driver supports */ 270 u16 driver_max_VFs; /* max num VFs driver supports */
271 struct pci_dev *dev; /* lowest numbered PF */ 271 struct pci_dev *dev; /* lowest numbered PF */
272 struct pci_dev *self; /* this PF */ 272 struct pci_dev *self; /* this PF */
273 struct mutex lock; /* lock for VF bus */ 273 struct mutex lock; /* lock for setting sriov_numvfs in sysfs */
274 resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */ 274 resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */
275}; 275};
276 276
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 1800befa8b8b..a0b3cd5726dc 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -4150,15 +4150,35 @@ static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
4150 * 4150 *
4151 * N.B. This doesn't fix what lspci shows. 4151 * N.B. This doesn't fix what lspci shows.
4152 * 4152 *
4153 * The 100 series chipset specification update includes this as errata #23[3].
4154 *
4155 * The 200 series chipset (Union Point) has the same bug according to the
4156 * specification update (Intel 200 Series Chipset Family Platform Controller
4157 * Hub, Specification Update, January 2017, Revision 001, Document# 335194-001,
4158 * Errata 22)[4]. Per the datasheet[5], root port PCI Device IDs for this
4159 * chipset include:
4160 *
4161 * 0xa290-0xa29f PCI Express Root port #{0-16}
4162 * 0xa2e7-0xa2ee PCI Express Root port #{17-24}
4163 *
4153 * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html 4164 * [1] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-2.html
4154 * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html 4165 * [2] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-datasheet-vol-1.html
4166 * [3] http://www.intel.com/content/www/us/en/chipsets/100-series-chipset-spec-update.html
4167 * [4] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-spec-update.html
4168 * [5] http://www.intel.com/content/www/us/en/chipsets/200-series-chipset-pch-datasheet-vol-1.html
4155 */ 4169 */
4156static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev) 4170static bool pci_quirk_intel_spt_pch_acs_match(struct pci_dev *dev)
4157{ 4171{
4158 return pci_is_pcie(dev) && 4172 if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
4159 pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT && 4173 return false;
4160 ((dev->device & ~0xf) == 0xa110 || 4174
4161 (dev->device >= 0xa167 && dev->device <= 0xa16a)); 4175 switch (dev->device) {
4176 case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */
4177 case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */
4178 return true;
4179 }
4180
4181 return false;
4162} 4182}
4163 4183
4164#define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4) 4184#define INTEL_SPT_ACS_CTRL (PCI_ACS_CAP + 4)