diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-driver.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 4940a53c56a3..b4cdd690ae71 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -43,18 +43,32 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
43 | { | 43 | { |
44 | struct pci_dynid *dynid; | 44 | struct pci_dynid *dynid; |
45 | struct pci_driver *pdrv = to_pci_driver(driver); | 45 | struct pci_driver *pdrv = to_pci_driver(driver); |
46 | const struct pci_device_id *ids = pdrv->id_table; | ||
46 | __u32 vendor, device, subvendor=PCI_ANY_ID, | 47 | __u32 vendor, device, subvendor=PCI_ANY_ID, |
47 | subdevice=PCI_ANY_ID, class=0, class_mask=0; | 48 | subdevice=PCI_ANY_ID, class=0, class_mask=0; |
48 | unsigned long driver_data=0; | 49 | unsigned long driver_data=0; |
49 | int fields=0; | 50 | int fields=0; |
50 | int retval = 0; | 51 | int retval; |
51 | 52 | ||
52 | fields = sscanf(buf, "%x %x %x %x %x %x %lux", | 53 | fields = sscanf(buf, "%x %x %x %x %x %x %lx", |
53 | &vendor, &device, &subvendor, &subdevice, | 54 | &vendor, &device, &subvendor, &subdevice, |
54 | &class, &class_mask, &driver_data); | 55 | &class, &class_mask, &driver_data); |
55 | if (fields < 2) | 56 | if (fields < 2) |
56 | return -EINVAL; | 57 | return -EINVAL; |
57 | 58 | ||
59 | /* Only accept driver_data values that match an existing id_table | ||
60 | entry */ | ||
61 | retval = -EINVAL; | ||
62 | while (ids->vendor || ids->subvendor || ids->class_mask) { | ||
63 | if (driver_data == ids->driver_data) { | ||
64 | retval = 0; | ||
65 | break; | ||
66 | } | ||
67 | ids++; | ||
68 | } | ||
69 | if (retval) /* No match */ | ||
70 | return retval; | ||
71 | |||
58 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); | 72 | dynid = kzalloc(sizeof(*dynid), GFP_KERNEL); |
59 | if (!dynid) | 73 | if (!dynid) |
60 | return -ENOMEM; | 74 | return -ENOMEM; |