diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-13 14:03:58 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-21 00:46:54 -0400 |
commit | 95247b57ed844511a212265b45cf9a919753aea1 (patch) | |
tree | ffabb4e3b868120f3d9a2c6463d568ad12d2f7f5 /drivers/pci | |
parent | 34220909a26b7f7cfc71e88ce01856c2563fe1d4 (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')
-rw-r--r-- | drivers/pci/search.c | 249 |
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 | */ |
130 | struct pci_dev * | 133 | struct pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn) |
131 | pci_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 | } |
145 | EXPORT_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 | */ | ||
164 | struct 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 | } | ||
173 | EXPORT_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 | 239 | static 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 | */ | ||
227 | static 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; | ||
259 | exit: | ||
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 | */ |
281 | struct pci_dev * | 265 | static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, |
282 | pci_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 | */ |
304 | struct pci_dev * | 302 | struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device, |
305 | pci_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; |
335 | exit: | ||
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 | */ |
376 | struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) | 366 | struct 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; | ||
392 | exit: | ||
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 | */ |
410 | int pci_dev_present(const struct pci_device_id *ids) | 394 | int 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 | } |
424 | exit: | 405 | exit: |
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 | } |
430 | EXPORT_SYMBOL(pci_dev_present); | 410 | EXPORT_SYMBOL(pci_dev_present); |
431 | 411 | ||
432 | #ifdef CONFIG_PCI_LEGACY | ||
433 | EXPORT_SYMBOL(pci_find_device); | ||
434 | EXPORT_SYMBOL(pci_find_slot); | ||
435 | #endif /* CONFIG_PCI_LEGACY */ | ||
436 | |||
437 | /* For boot time work */ | 412 | /* For boot time work */ |
438 | EXPORT_SYMBOL(pci_find_bus); | 413 | EXPORT_SYMBOL(pci_find_bus); |
439 | EXPORT_SYMBOL(pci_find_next_bus); | 414 | EXPORT_SYMBOL(pci_find_next_bus); |