aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/search.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2008-02-13 14:03:58 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-04-21 00:46:54 -0400
commit95247b57ed844511a212265b45cf9a919753aea1 (patch)
treeffabb4e3b868120f3d9a2c6463d568ad12d2f7f5 /drivers/pci/search.c
parent34220909a26b7f7cfc71e88ce01856c2563fe1d4 (diff)
PCI: clean up search.c a lot
This cleans up the search.c file, now using the pci list of devices that are created for the driver core, instead of relying on our separate list of devices. It's better to use the functions already created for this kind of thing, instead of rolling our own all the time. This work is done in anticipation of getting rid of that second list of pci devices all together. And it ends up saving code, always a nice benefit. This also removes one compiler warning for when CONFIG_PCI_LEGACY is enabled as we no longer internally use the deprecated functions anymore. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/search.c')
-rw-r--r--drivers/pci/search.c249
1 files changed, 112 insertions, 137 deletions
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index a04c43ffce4c..217814fef4ef 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -114,31 +114,63 @@ pci_find_next_bus(const struct pci_bus *from)
114} 114}
115 115
116#ifdef CONFIG_PCI_LEGACY 116#ifdef CONFIG_PCI_LEGACY
117
118/** 117/**
119 * pci_find_slot - locate PCI device from a given PCI slot 118 * pci_find_slot - locate PCI device from a given PCI slot
120 * @bus: number of PCI bus on which desired PCI device resides 119 * @bus: number of PCI bus on which desired PCI device resides
121 * @devfn: encodes number of PCI slot in which the desired PCI 120 * @devfn: encodes number of PCI slot in which the desired PCI
122 * device resides and the logical device number within that slot 121 * device resides and the logical device number within that slot
123 * in case of multi-function devices. 122 * in case of multi-function devices.
124 * 123 *
125 * Given a PCI bus and slot/function number, the desired PCI device 124 * Given a PCI bus and slot/function number, the desired PCI device
126 * is located in system global list of PCI devices. If the device 125 * is located in system global list of PCI devices. If the device
127 * is found, a pointer to its data structure is returned. If no 126 * is found, a pointer to its data structure is returned. If no
128 * device is found, %NULL is returned. 127 * device is found, %NULL is returned.
128 *
129 * NOTE: Do not use this function any more; use pci_get_slot() instead, as
130 * the PCI device returned by this function can disappear at any moment in
131 * time.
129 */ 132 */
130struct pci_dev * 133struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
131pci_find_slot(unsigned int bus, unsigned int devfn)
132{ 134{
133 struct pci_dev *dev = NULL; 135 struct pci_dev *dev = NULL;
134 136
135 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 137 while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
136 if (dev->bus->number == bus && dev->devfn == devfn) 138 if (dev->bus->number == bus && dev->devfn == devfn) {
139 pci_dev_put(dev);
137 return dev; 140 return dev;
141 }
138 } 142 }
139 return NULL; 143 return NULL;
140} 144}
145EXPORT_SYMBOL(pci_find_slot);
141 146
147/**
148 * pci_find_device - begin or continue searching for a PCI device by vendor/device id
149 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
150 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
151 * @from: Previous PCI device found in search, or %NULL for new search.
152 *
153 * Iterates through the list of known PCI devices. If a PCI device is found
154 * with a matching @vendor and @device, a pointer to its device structure is
155 * returned. Otherwise, %NULL is returned.
156 * A new search is initiated by passing %NULL as the @from argument.
157 * Otherwise if @from is not %NULL, searches continue from next device
158 * on the global list.
159 *
160 * NOTE: Do not use this function any more; use pci_get_device() instead, as
161 * the PCI device returned by this function can disappear at any moment in
162 * time.
163 */
164struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device,
165 const struct pci_dev *from)
166{
167 struct pci_dev *pdev;
168
169 pdev = pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
170 pci_dev_put(pdev);
171 return pdev;
172}
173EXPORT_SYMBOL(pci_find_device);
142#endif /* CONFIG_PCI_LEGACY */ 174#endif /* CONFIG_PCI_LEGACY */
143 175
144/** 176/**
@@ -204,86 +236,52 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
204 return NULL; 236 return NULL;
205} 237}
206 238
207#ifdef CONFIG_PCI_LEGACY 239static int match_pci_dev_by_id(struct device *dev, void *data)
208/**
209 * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
210 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
211 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
212 * @ss_vendor: PCI subsystem vendor id to match, or %PCI_ANY_ID to match all vendor ids
213 * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids
214 * @from: Previous PCI device found in search, or %NULL for new search.
215 *
216 * Iterates through the list of known PCI devices. If a PCI device is
217 * found with a matching @vendor, @device, @ss_vendor and @ss_device, a
218 * pointer to its device structure is returned. Otherwise, %NULL is returned.
219 * A new search is initiated by passing %NULL as the @from argument.
220 * Otherwise if @from is not %NULL, searches continue from next device
221 * on the global list.
222 *
223 * NOTE: Do not use this function any more; use pci_get_subsys() instead, as
224 * the PCI device returned by this function can disappear at any moment in
225 * time.
226 */
227static struct pci_dev * pci_find_subsys(unsigned int vendor,
228 unsigned int device,
229 unsigned int ss_vendor,
230 unsigned int ss_device,
231 const struct pci_dev *from)
232{ 240{
233 struct list_head *n; 241 struct pci_dev *pdev = to_pci_dev(dev);
234 struct pci_dev *dev; 242 struct pci_device_id *id = data;
235 243
236 WARN_ON(in_interrupt()); 244 if (pci_match_one_device(id, pdev))
237 245 return 1;
238 /* 246 return 0;
239 * pci_find_subsys() can be called on the ide_setup() path, super-early
240 * in boot. But the down_read() will enable local interrupts, which
241 * can cause some machines to crash. So here we detect and flag that
242 * situation and bail out early.
243 */
244 if (unlikely(no_pci_devices()))
245 return NULL;
246 down_read(&pci_bus_sem);
247 n = from ? from->global_list.next : pci_devices.next;
248
249 while (n && (n != &pci_devices)) {
250 dev = pci_dev_g(n);
251 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) &&
252 (device == PCI_ANY_ID || dev->device == device) &&
253 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) &&
254 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device))
255 goto exit;
256 n = n->next;
257 }
258 dev = NULL;
259exit:
260 up_read(&pci_bus_sem);
261 return dev;
262} 247}
263 248
264/** 249/*
265 * pci_find_device - begin or continue searching for a PCI device by vendor/device id 250 * pci_get_dev_by_id - begin or continue searching for a PCI device by id
266 * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids 251 * @id: pointer to struct pci_device_id to match for the device
267 * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids
268 * @from: Previous PCI device found in search, or %NULL for new search. 252 * @from: Previous PCI device found in search, or %NULL for new search.
269 * 253 *
270 * Iterates through the list of known PCI devices. If a PCI device is found 254 * Iterates through the list of known PCI devices. If a PCI device is found
271 * with a matching @vendor and @device, a pointer to its device structure is 255 * with a matching id a pointer to its device structure is returned, and the
272 * returned. Otherwise, %NULL is returned. 256 * reference count to the device is incremented. Otherwise, %NULL is returned.
273 * A new search is initiated by passing %NULL as the @from argument. 257 * A new search is initiated by passing %NULL as the @from argument. Otherwise
274 * Otherwise if @from is not %NULL, searches continue from next device 258 * if @from is not %NULL, searches continue from next device on the global
275 * on the global list. 259 * list. The reference count for @from is always decremented if it is not
276 * 260 * %NULL.
277 * NOTE: Do not use this function any more; use pci_get_device() instead, as 261 *
278 * the PCI device returned by this function can disappear at any moment in 262 * This is an internal function for use by the other search functions in
279 * time. 263 * this file.
280 */ 264 */
281struct pci_dev * 265static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id,
282pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *from) 266 const struct pci_dev *from)
283{ 267{
284 return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); 268 struct device *dev;
269 struct device *dev_start = NULL;
270 struct pci_dev *pdev = NULL;
271
272 WARN_ON(in_interrupt());
273 if (from) {
274 /* FIXME
275 * take the cast off, when bus_find_device is made const.
276 */
277 dev_start = (struct device *)&from->dev;
278 }
279 dev = bus_find_device(&pci_bus_type, dev_start, (void *)id,
280 match_pci_dev_by_id);
281 if (dev)
282 pdev = to_pci_dev(dev);
283 return pdev;
285} 284}
286#endif /* CONFIG_PCI_LEGACY */
287 285
288/** 286/**
289 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id 287 * pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
@@ -301,42 +299,34 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *
301 * searches continue from next device on the global list. 299 * searches continue from next device on the global list.
302 * The reference count for @from is always decremented if it is not %NULL. 300 * The reference count for @from is always decremented if it is not %NULL.
303 */ 301 */
304struct pci_dev * 302struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
305pci_get_subsys(unsigned int vendor, unsigned int device, 303 unsigned int ss_vendor, unsigned int ss_device,
306 unsigned int ss_vendor, unsigned int ss_device, 304 const struct pci_dev *from)
307 struct pci_dev *from)
308{ 305{
309 struct list_head *n; 306 struct pci_dev *pdev;
310 struct pci_dev *dev; 307 struct pci_device_id *id;
311
312 WARN_ON(in_interrupt());
313 308
314 /* 309 /*
315 * pci_get_subsys() can potentially be called by drivers super-early 310 * pci_find_subsys() can be called on the ide_setup() path,
316 * in boot. But the down_read() will enable local interrupts, which 311 * super-early in boot. But the down_read() will enable local
317 * can cause some machines to crash. So here we detect and flag that 312 * interrupts, which can cause some machines to crash. So here we
318 * situation and bail out early. 313 * detect and flag that situation and bail out early.
319 */ 314 */
320 if (unlikely(no_pci_devices())) 315 if (unlikely(no_pci_devices()))
321 return NULL; 316 return NULL;
322 down_read(&pci_bus_sem); 317
323 n = from ? from->global_list.next : pci_devices.next; 318 id = kzalloc(sizeof(*id), GFP_KERNEL);
324 319 if (!id)
325 while (n && (n != &pci_devices)) { 320 return NULL;
326 dev = pci_dev_g(n); 321 id->vendor = vendor;
327 if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && 322 id->device = device;
328 (device == PCI_ANY_ID || dev->device == device) && 323 id->subvendor = ss_vendor;
329 (ss_vendor == PCI_ANY_ID || dev->subsystem_vendor == ss_vendor) && 324 id->subdevice = ss_device;
330 (ss_device == PCI_ANY_ID || dev->subsystem_device == ss_device)) 325
331 goto exit; 326 pdev = pci_get_dev_by_id(id, from);
332 n = n->next; 327 kfree(id);
333 } 328
334 dev = NULL; 329 return pdev;
335exit:
336 dev = pci_dev_get(dev);
337 up_read(&pci_bus_sem);
338 pci_dev_put(from);
339 return dev;
340} 330}
341 331
342/** 332/**
@@ -375,24 +365,18 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
375 */ 365 */
376struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) 366struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
377{ 367{
378 struct list_head *n;
379 struct pci_dev *dev; 368 struct pci_dev *dev;
369 struct pci_device_id *id;
380 370
381 WARN_ON(in_interrupt()); 371 id = kzalloc(sizeof(*id), GFP_KERNEL);
382 down_read(&pci_bus_sem); 372 if (!id)
383 n = from ? from->global_list.next : pci_devices.next; 373 return NULL;
374 id->vendor = id->device = id->subvendor = id->subdevice = PCI_ANY_ID;
375 id->class_mask = PCI_ANY_ID;
376 id->class = class;
384 377
385 while (n && (n != &pci_devices)) { 378 dev = pci_get_dev_by_id(id, from);
386 dev = pci_dev_g(n); 379 kfree(id);
387 if (dev->class == class)
388 goto exit;
389 n = n->next;
390 }
391 dev = NULL;
392exit:
393 dev = pci_dev_get(dev);
394 up_read(&pci_bus_sem);
395 pci_dev_put(from);
396 return dev; 380 return dev;
397} 381}
398 382
@@ -409,31 +393,22 @@ exit:
409 */ 393 */
410int pci_dev_present(const struct pci_device_id *ids) 394int pci_dev_present(const struct pci_device_id *ids)
411{ 395{
412 struct pci_dev *dev; 396 struct pci_dev *found = NULL;
413 const struct pci_device_id *found = NULL;
414 397
415 WARN_ON(in_interrupt()); 398 WARN_ON(in_interrupt());
416 down_read(&pci_bus_sem);
417 while (ids->vendor || ids->subvendor || ids->class_mask) { 399 while (ids->vendor || ids->subvendor || ids->class_mask) {
418 list_for_each_entry(dev, &pci_devices, global_list) { 400 found = pci_get_dev_by_id(ids, NULL);
419 if ((found = pci_match_one_device(ids, dev)) != NULL) 401 if (found)
420 goto exit; 402 goto exit;
421 }
422 ids++; 403 ids++;
423 } 404 }
424exit: 405exit:
425 up_read(&pci_bus_sem);
426 if (found) 406 if (found)
427 return 1; 407 return 1;
428 return 0; 408 return 0;
429} 409}
430EXPORT_SYMBOL(pci_dev_present); 410EXPORT_SYMBOL(pci_dev_present);
431 411
432#ifdef CONFIG_PCI_LEGACY
433EXPORT_SYMBOL(pci_find_device);
434EXPORT_SYMBOL(pci_find_slot);
435#endif /* CONFIG_PCI_LEGACY */
436
437/* For boot time work */ 412/* For boot time work */
438EXPORT_SYMBOL(pci_find_bus); 413EXPORT_SYMBOL(pci_find_bus);
439EXPORT_SYMBOL(pci_find_next_bus); 414EXPORT_SYMBOL(pci_find_next_bus);