aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-driver.c25
-rw-r--r--drivers/pci/pci-sysfs.c40
-rw-r--r--drivers/pci/probe.c1
3 files changed, 63 insertions, 3 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d911e0c1f359..4393c12e9135 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -216,6 +216,13 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
216 return NULL; 216 return NULL;
217} 217}
218 218
219static const struct pci_device_id pci_device_id_any = {
220 .vendor = PCI_ANY_ID,
221 .device = PCI_ANY_ID,
222 .subvendor = PCI_ANY_ID,
223 .subdevice = PCI_ANY_ID,
224};
225
219/** 226/**
220 * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure 227 * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
221 * @drv: the PCI driver to match against 228 * @drv: the PCI driver to match against
@@ -229,18 +236,30 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
229 struct pci_dev *dev) 236 struct pci_dev *dev)
230{ 237{
231 struct pci_dynid *dynid; 238 struct pci_dynid *dynid;
239 const struct pci_device_id *found_id = NULL;
240
241 /* When driver_override is set, only bind to the matching driver */
242 if (dev->driver_override && strcmp(dev->driver_override, drv->name))
243 return NULL;
232 244
233 /* Look at the dynamic ids first, before the static ones */ 245 /* Look at the dynamic ids first, before the static ones */
234 spin_lock(&drv->dynids.lock); 246 spin_lock(&drv->dynids.lock);
235 list_for_each_entry(dynid, &drv->dynids.list, node) { 247 list_for_each_entry(dynid, &drv->dynids.list, node) {
236 if (pci_match_one_device(&dynid->id, dev)) { 248 if (pci_match_one_device(&dynid->id, dev)) {
237 spin_unlock(&drv->dynids.lock); 249 found_id = &dynid->id;
238 return &dynid->id; 250 break;
239 } 251 }
240 } 252 }
241 spin_unlock(&drv->dynids.lock); 253 spin_unlock(&drv->dynids.lock);
242 254
243 return pci_match_id(drv->id_table, dev); 255 if (!found_id)
256 found_id = pci_match_id(drv->id_table, dev);
257
258 /* driver_override will always match, send a dummy id */
259 if (!found_id && dev->driver_override)
260 found_id = &pci_device_id_any;
261
262 return found_id;
244} 263}
245 264
246struct drv_dev_and_id { 265struct drv_dev_and_id {
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 4e0acefb7565..faa4ab554d68 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -499,6 +499,45 @@ static struct device_attribute sriov_numvfs_attr =
499 sriov_numvfs_show, sriov_numvfs_store); 499 sriov_numvfs_show, sriov_numvfs_store);
500#endif /* CONFIG_PCI_IOV */ 500#endif /* CONFIG_PCI_IOV */
501 501
502static ssize_t driver_override_store(struct device *dev,
503 struct device_attribute *attr,
504 const char *buf, size_t count)
505{
506 struct pci_dev *pdev = to_pci_dev(dev);
507 char *driver_override, *old = pdev->driver_override, *cp;
508
509 if (count > PATH_MAX)
510 return -EINVAL;
511
512 driver_override = kstrndup(buf, count, GFP_KERNEL);
513 if (!driver_override)
514 return -ENOMEM;
515
516 cp = strchr(driver_override, '\n');
517 if (cp)
518 *cp = '\0';
519
520 if (strlen(driver_override)) {
521 pdev->driver_override = driver_override;
522 } else {
523 kfree(driver_override);
524 pdev->driver_override = NULL;
525 }
526
527 kfree(old);
528
529 return count;
530}
531
532static ssize_t driver_override_show(struct device *dev,
533 struct device_attribute *attr, char *buf)
534{
535 struct pci_dev *pdev = to_pci_dev(dev);
536
537 return sprintf(buf, "%s\n", pdev->driver_override);
538}
539static DEVICE_ATTR_RW(driver_override);
540
502static struct attribute *pci_dev_attrs[] = { 541static struct attribute *pci_dev_attrs[] = {
503 &dev_attr_resource.attr, 542 &dev_attr_resource.attr,
504 &dev_attr_vendor.attr, 543 &dev_attr_vendor.attr,
@@ -521,6 +560,7 @@ static struct attribute *pci_dev_attrs[] = {
521#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) 560#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
522 &dev_attr_d3cold_allowed.attr, 561 &dev_attr_d3cold_allowed.attr,
523#endif 562#endif
563 &dev_attr_driver_override.attr,
524 NULL, 564 NULL,
525}; 565};
526 566
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ef09f5f2fe6c..54268de45f59 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1215,6 +1215,7 @@ static void pci_release_dev(struct device *dev)
1215 pci_release_of_node(pci_dev); 1215 pci_release_of_node(pci_dev);
1216 pcibios_release_device(pci_dev); 1216 pcibios_release_device(pci_dev);
1217 pci_bus_put(pci_dev->bus); 1217 pci_bus_put(pci_dev->bus);
1218 kfree(pci_dev->driver_override);
1218 kfree(pci_dev); 1219 kfree(pci_dev);
1219} 1220}
1220 1221