diff options
Diffstat (limited to 'drivers/pci/search.c')
-rw-r--r-- | drivers/pci/search.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d529462d1b53..2f13eba5d5ae 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -140,6 +140,31 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * pci_get_bus_and_slot - locate PCI device from a given PCI slot | ||
144 | * @bus: number of PCI bus on which desired PCI device resides | ||
145 | * @devfn: encodes number of PCI slot in which the desired PCI | ||
146 | * device resides and the logical device number within that slot | ||
147 | * in case of multi-function devices. | ||
148 | * | ||
149 | * Given a PCI bus and slot/function number, the desired PCI device | ||
150 | * is located in system global list of PCI devices. If the device | ||
151 | * is found, a pointer to its data structure is returned. If no | ||
152 | * device is found, %NULL is returned. The returned device has its | ||
153 | * reference count bumped by one. | ||
154 | */ | ||
155 | |||
156 | struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) | ||
157 | { | ||
158 | struct pci_dev *dev = NULL; | ||
159 | |||
160 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
161 | if (dev->bus->number == bus && dev->devfn == devfn) | ||
162 | return dev; | ||
163 | } | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | /** | ||
143 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id | 168 | * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id |
144 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | 169 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids |
145 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | 170 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids |
@@ -274,6 +299,45 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) | |||
274 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); | 299 | return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); |
275 | } | 300 | } |
276 | 301 | ||
302 | /** | ||
303 | * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id | ||
304 | * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids | ||
305 | * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids | ||
306 | * @from: Previous PCI device found in search, or %NULL for new search. | ||
307 | * | ||
308 | * Iterates through the list of known PCI devices in the reverse order of | ||
309 | * pci_get_device. | ||
310 | * If a PCI device is found with a matching @vendor and @device, the reference | ||
311 | * count to the device is incremented and a pointer to its device structure | ||
312 | * is returned Otherwise, %NULL is returned. A new search is initiated by | ||
313 | * passing %NULL as the @from argument. Otherwise if @from is not %NULL, | ||
314 | * searches continue from next device on the global list. The reference | ||
315 | * count for @from is always decremented if it is not %NULL. | ||
316 | */ | ||
317 | struct pci_dev * | ||
318 | pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from) | ||
319 | { | ||
320 | struct list_head *n; | ||
321 | struct pci_dev *dev; | ||
322 | |||
323 | WARN_ON(in_interrupt()); | ||
324 | down_read(&pci_bus_sem); | ||
325 | n = from ? from->global_list.prev : pci_devices.prev; | ||
326 | |||
327 | while (n && (n != &pci_devices)) { | ||
328 | dev = pci_dev_g(n); | ||
329 | if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && | ||
330 | (device == PCI_ANY_ID || dev->device == device)) | ||
331 | goto exit; | ||
332 | n = n->prev; | ||
333 | } | ||
334 | dev = NULL; | ||
335 | exit: | ||
336 | dev = pci_dev_get(dev); | ||
337 | up_read(&pci_bus_sem); | ||
338 | pci_dev_put(from); | ||
339 | return dev; | ||
340 | } | ||
277 | 341 | ||
278 | /** | 342 | /** |
279 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id | 343 | * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id |
@@ -382,12 +446,16 @@ exit: | |||
382 | } | 446 | } |
383 | EXPORT_SYMBOL(pci_dev_present); | 447 | EXPORT_SYMBOL(pci_dev_present); |
384 | 448 | ||
385 | EXPORT_SYMBOL(pci_find_bus); | ||
386 | EXPORT_SYMBOL(pci_find_next_bus); | ||
387 | EXPORT_SYMBOL(pci_find_device); | 449 | EXPORT_SYMBOL(pci_find_device); |
388 | EXPORT_SYMBOL(pci_find_device_reverse); | 450 | EXPORT_SYMBOL(pci_find_device_reverse); |
389 | EXPORT_SYMBOL(pci_find_slot); | 451 | EXPORT_SYMBOL(pci_find_slot); |
452 | /* For boot time work */ | ||
453 | EXPORT_SYMBOL(pci_find_bus); | ||
454 | EXPORT_SYMBOL(pci_find_next_bus); | ||
455 | /* For everyone */ | ||
390 | EXPORT_SYMBOL(pci_get_device); | 456 | EXPORT_SYMBOL(pci_get_device); |
457 | EXPORT_SYMBOL(pci_get_device_reverse); | ||
391 | EXPORT_SYMBOL(pci_get_subsys); | 458 | EXPORT_SYMBOL(pci_get_subsys); |
392 | EXPORT_SYMBOL(pci_get_slot); | 459 | EXPORT_SYMBOL(pci_get_slot); |
460 | EXPORT_SYMBOL(pci_get_bus_and_slot); | ||
393 | EXPORT_SYMBOL(pci_get_class); | 461 | EXPORT_SYMBOL(pci_get_class); |