PCI: Fix pci_find_present
[linux-2.6] / drivers / pci / search.c
1 /*
2  *      PCI searching functions.
3  *
4  *      Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,
5  *                                      David Mosberger-Tang
6  *      Copyright (C) 1997 -- 2000 Martin Mares <mj@ucw.cz>
7  *      Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>
8  */
9
10 #include <linux/init.h>
11 #include <linux/pci.h>
12 #include <linux/module.h>
13 #include <linux/interrupt.h>
14 #include "pci.h"
15
16 DECLARE_RWSEM(pci_bus_sem);
17
18 static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
19 {
20         struct pci_bus* child;
21         struct list_head *tmp;
22
23         if(bus->number == busnr)
24                 return bus;
25
26         list_for_each(tmp, &bus->children) {
27                 child = pci_do_find_bus(pci_bus_b(tmp), busnr);
28                 if(child)
29                         return child;
30         }
31         return NULL;
32 }
33
34 /**
35  * pci_find_bus - locate PCI bus from a given domain and bus number
36  * @domain: number of PCI domain to search
37  * @busnr: number of desired PCI bus
38  *
39  * Given a PCI bus number and domain number, the desired PCI bus is located
40  * in the global list of PCI buses.  If the bus is found, a pointer to its
41  * data structure is returned.  If no bus is found, %NULL is returned.
42  */
43 struct pci_bus * pci_find_bus(int domain, int busnr)
44 {
45         struct pci_bus *bus = NULL;
46         struct pci_bus *tmp_bus;
47
48         while ((bus = pci_find_next_bus(bus)) != NULL)  {
49                 if (pci_domain_nr(bus) != domain)
50                         continue;
51                 tmp_bus = pci_do_find_bus(bus, busnr);
52                 if (tmp_bus)
53                         return tmp_bus;
54         }
55         return NULL;
56 }
57
58 /**
59  * pci_find_next_bus - begin or continue searching for a PCI bus
60  * @from: Previous PCI bus found, or %NULL for new search.
61  *
62  * Iterates through the list of known PCI busses.  A new search is
63  * initiated by passing %NULL as the @from argument.  Otherwise if
64  * @from is not %NULL, searches continue from next device on the
65  * global list.
66  */
67 struct pci_bus * 
68 pci_find_next_bus(const struct pci_bus *from)
69 {
70         struct list_head *n;
71         struct pci_bus *b = NULL;
72
73         WARN_ON(in_interrupt());
74         down_read(&pci_bus_sem);
75         n = from ? from->node.next : pci_root_buses.next;
76         if (n != &pci_root_buses)
77                 b = pci_bus_b(n);
78         up_read(&pci_bus_sem);
79         return b;
80 }
81
82 /**
83  * pci_find_slot - locate PCI device from a given PCI slot
84  * @bus: number of PCI bus on which desired PCI device resides
85  * @devfn: encodes number of PCI slot in which the desired PCI 
86  * device resides and the logical device number within that slot 
87  * in case of multi-function devices.
88  *
89  * Given a PCI bus and slot/function number, the desired PCI device 
90  * is located in system global list of PCI devices.  If the device
91  * is found, a pointer to its data structure is returned.  If no 
92  * device is found, %NULL is returned.
93  */
94 struct pci_dev *
95 pci_find_slot(unsigned int bus, unsigned int devfn)
96 {
97         struct pci_dev *dev = NULL;
98
99         while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
100                 if (dev->bus->number == bus && dev->devfn == devfn)
101                         return dev;
102         }
103         return NULL;
104 }
105
106 /**
107  * pci_get_slot - locate PCI device for a given PCI slot
108  * @bus: PCI bus on which desired PCI device resides
109  * @devfn: encodes number of PCI slot in which the desired PCI 
110  * device resides and the logical device number within that slot 
111  * in case of multi-function devices.
112  *
113  * Given a PCI bus and slot/function number, the desired PCI device 
114  * is located in the list of PCI devices.
115  * If the device is found, its reference count is increased and this
116  * function returns a pointer to its data structure.  The caller must
117  * decrement the reference count by calling pci_dev_put().
118  * If no device is found, %NULL is returned.
119  */
120 struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
121 {
122         struct list_head *tmp;
123         struct pci_dev *dev;
124
125         WARN_ON(in_interrupt());
126         down_read(&pci_bus_sem);
127
128         list_for_each(tmp, &bus->devices) {
129                 dev = pci_dev_b(tmp);
130                 if (dev->devfn == devfn)
131                         goto out;
132         }
133
134         dev = NULL;
135  out:
136         pci_dev_get(dev);
137         up_read(&pci_bus_sem);
138         return dev;
139 }
140
141 /**
142  * pci_get_bus_and_slot - locate PCI device from a given PCI slot
143  * @bus: number of PCI bus on which desired PCI device resides
144  * @devfn: encodes number of PCI slot in which the desired PCI
145  * device resides and the logical device number within that slot
146  * in case of multi-function devices.
147  *
148  * Given a PCI bus and slot/function number, the desired PCI device
149  * is located in system global list of PCI devices.  If the device
150  * is found, a pointer to its data structure is returned.  If no
151  * device is found, %NULL is returned. The returned device has its
152  * reference count bumped by one.
153  */
154
155 struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
156 {
157         struct pci_dev *dev = NULL;
158
159         while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
160                 if (dev->bus->number == bus && dev->devfn == devfn)
161                         return dev;
162         }
163         return NULL;
164 }
165
166 /**
167  * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
168  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
169  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
170  * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
171  * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
172  * @from: Previous PCI device found in search, or %NULL for new search.
173  *
174  * Iterates through the list of known PCI devices.  If a PCI device is
175  * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
176  * pointer to its device structure is returned.  Otherwise, %NULL is returned.
177  * A new search is initiated by passing %NULL as the @from argument.
178  * Otherwise if @from is not %NULL, searches continue from next device
179  * on the global list.
180  *
181  * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
182  * the PCI device returned by this function can disappear at any moment in
183  * time.
184  */
185 static struct pci_dev * pci_find_subsys(unsigned int vendor,
186                                         unsigned int device,
187                                         unsigned int ss_vendor,
188                                         unsigned int ss_device,
189                                         const struct pci_dev *from)
190 {
191         struct list_head *n;
192         struct pci_dev *dev;
193
194         WARN_ON(in_interrupt());
195
196         /*
197          * pci_find_subsys() can be called on the ide_setup() path, super-early
198          * in boot.  But the down_read() will enable local interrupts, which
199          * can cause some machines to crash.  So here we detect and flag that
200          * situation and bail out early.
201          */
202         if (unlikely(list_empty(&pci_devices)))
203                 return NULL;
204         down_read(&pci_bus_sem);
205         n = from ? from->global_list.next : pci_devices.next;
206
207         while (n && (n != &pci_devices)) {
208                 dev = pci_dev_g(n);
209                 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
210                     (device == PCI_ANY_ID || dev->device == device) &&
211                     (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
212                     (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
213                         goto exit;
214                 n = n->next;
215         }
216         dev = NULL;
217 exit:
218         up_read(&pci_bus_sem);
219         return dev;
220 }
221
222 /**
223  * pci_find_device - begin or continue searching for a PCI device by vendor/device id
224  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
225  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
226  * @from: Previous PCI device found in search, or %NULL for new search.
227  *
228  * Iterates through the list of known PCI devices.  If a PCI device is found
229  * with a matching @vendor and @device, a pointer to its device structure is
230  * returned.  Otherwise, %NULL is returned.
231  * A new search is initiated by passing %NULL as the @from argument.
232  * Otherwise if @from is not %NULL, searches continue from next device
233  * on the global list.
234  * 
235  * NOTE: Do not use this function any more; use pci_get_device() instead, as
236  * the PCI device returned by this function can disappear at any moment in
237  * time.
238  */
239 struct pci_dev *
240 pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from)
241 {
242         return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
243 }
244
245 /**
246  * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
247  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
248  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
249  * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
250  * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
251  * @from: Previous PCI device found in search, or %NULL for new search.
252  *
253  * Iterates through the list of known PCI devices.  If a PCI device is found
254  * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its
255  * device structure is returned, and the reference count to the device is
256  * incremented.  Otherwise, %NULL is returned.  A new search is initiated by
257  * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
258  * searches continue from next device on the global list.
259  * The reference count for @from is always decremented if it is not %NULL.
260  */
261 struct pci_dev * 
262 pci_get_subsys(unsigned int vendor, unsigned int device,
263                unsigned int ss_vendor, unsigned int ss_device,
264                struct pci_dev *from)
265 {
266         struct list_head *n;
267         struct pci_dev *dev;
268
269         WARN_ON(in_interrupt());
270
271         /*
272          * pci_get_subsys() can potentially be called by drivers super-early
273          * in boot.  But the down_read() will enable local interrupts, which
274          * can cause some machines to crash.  So here we detect and flag that
275          * situation and bail out early.
276          */
277         if (unlikely(list_empty(&pci_devices)))
278                 return NULL;
279         down_read(&pci_bus_sem);
280         n = from ? from->global_list.next : pci_devices.next;
281
282         while (n && (n != &pci_devices)) {
283                 dev = pci_dev_g(n);
284                 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
285                     (device == PCI_ANY_ID || dev->device == device) &&
286                     (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
287                     (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
288                         goto exit;
289                 n = n->next;
290         }
291         dev = NULL;
292 exit:
293         dev = pci_dev_get(dev);
294         up_read(&pci_bus_sem);
295         pci_dev_put(from);
296         return dev;
297 }
298
299 /**
300  * pci_get_device - begin or continue searching for a PCI device by vendor/device id
301  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
302  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
303  * @from: Previous PCI device found in search, or %NULL for new search.
304  *
305  * Iterates through the list of known PCI devices.  If a PCI device is
306  * found with a matching @vendor and @device, the reference count to the
307  * device is incremented and a pointer to its device structure is returned.
308  * Otherwise, %NULL is returned.  A new search is initiated by passing %NULL
309  * as the @from argument.  Otherwise if @from is not %NULL, searches continue
310  * from next device on the global list.  The reference count for @from is
311  * always decremented if it is not %NULL.
312  */
313 struct pci_dev *
314 pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
315 {
316         return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
317 }
318
319 /**
320  * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id
321  * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
322  * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
323  * @from: Previous PCI device found in search, or %NULL for new search.
324  *
325  * Iterates through the list of known PCI devices in the reverse order of
326  * pci_get_device.
327  * If a PCI device is found with a matching @vendor and @device, the reference
328  * count to the  device is incremented and a pointer to its device structure
329  * is returned Otherwise, %NULL is returned.  A new search is initiated by
330  * passing %NULL as the @from argument.  Otherwise if @from is not %NULL,
331  * searches continue from next device on the global list.  The reference
332  * count for @from is always decremented if it is not %NULL.
333  */
334 struct pci_dev *
335 pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from)
336 {
337         struct list_head *n;
338         struct pci_dev *dev;
339
340         WARN_ON(in_interrupt());
341         down_read(&pci_bus_sem);
342         n = from ? from->global_list.prev : pci_devices.prev;
343
344         while (n && (n != &pci_devices)) {
345                 dev = pci_dev_g(n);
346                 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
347                     (device == PCI_ANY_ID || dev->device == device))
348                         goto exit;
349                 n = n->prev;
350         }
351         dev = NULL;
352 exit:
353         dev = pci_dev_get(dev);
354         up_read(&pci_bus_sem);
355         pci_dev_put(from);
356         return dev;
357 }
358
359 /**
360  * pci_get_class - begin or continue searching for a PCI device by class
361  * @class: search for a PCI device with this class designation
362  * @from: Previous PCI device found in search, or %NULL for new search.
363  *
364  * Iterates through the list of known PCI devices.  If a PCI device is
365  * found with a matching @class, the reference count to the device is
366  * incremented and a pointer to its device structure is returned.
367  * Otherwise, %NULL is returned.
368  * A new search is initiated by passing %NULL as the @from argument.
369  * Otherwise if @from is not %NULL, searches continue from next device
370  * on the global list.  The reference count for @from is always decremented
371  * if it is not %NULL.
372  */
373 struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
374 {
375         struct list_head *n;
376         struct pci_dev *dev;
377
378         WARN_ON(in_interrupt());
379         down_read(&pci_bus_sem);
380         n = from ? from->global_list.next : pci_devices.next;
381
382         while (n && (n != &pci_devices)) {
383                 dev = pci_dev_g(n);
384                 if (dev->class == class)
385                         goto exit;
386                 n = n->next;
387         }
388         dev = NULL;
389 exit:
390         dev = pci_dev_get(dev);
391         up_read(&pci_bus_sem);
392         pci_dev_put(from);
393         return dev;
394 }
395
396 const struct pci_device_id *pci_find_present(const struct pci_device_id *ids)
397 {
398         struct pci_dev *dev;
399         const struct pci_device_id *found = NULL;
400
401         WARN_ON(in_interrupt());
402         down_read(&pci_bus_sem);
403         while (ids->vendor || ids->subvendor || ids->class_mask) {
404                 list_for_each_entry(dev, &pci_devices, global_list) {
405                         if ((found = pci_match_one_device(ids, dev)) != NULL)
406                                 goto exit;
407                 }
408                 ids++;
409         }
410 exit:
411         up_read(&pci_bus_sem);
412         return found;
413 }
414
415 /**
416  * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
417  * @ids: A pointer to a null terminated list of struct pci_device_id structures
418  * that describe the type of PCI device the caller is trying to find.
419  *
420  * Obvious fact: You do not have a reference to any device that might be found
421  * by this function, so if that device is removed from the system right after
422  * this function is finished, the value will be stale.  Use this function to
423  * find devices that are usually built into a system, or for a general hint as
424  * to if another device happens to be present at this specific moment in time.
425  */
426 int pci_dev_present(const struct pci_device_id *ids)
427 {
428         return pci_find_present(ids) == NULL ? 0 : 1;
429 }
430
431 EXPORT_SYMBOL(pci_dev_present);
432 EXPORT_SYMBOL(pci_find_present);
433
434 EXPORT_SYMBOL(pci_find_device);
435 EXPORT_SYMBOL(pci_find_slot);
436 /* For boot time work */
437 EXPORT_SYMBOL(pci_find_bus);
438 EXPORT_SYMBOL(pci_find_next_bus);
439 /* For everyone */
440 EXPORT_SYMBOL(pci_get_device);
441 EXPORT_SYMBOL(pci_get_device_reverse);
442 EXPORT_SYMBOL(pci_get_subsys);
443 EXPORT_SYMBOL(pci_get_slot);
444 EXPORT_SYMBOL(pci_get_bus_and_slot);
445 EXPORT_SYMBOL(pci_get_class);