diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6e100ae7f5b5..fdcf01af6762 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -303,6 +303,49 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap) | |||
303 | } | 303 | } |
304 | EXPORT_SYMBOL_GPL(pci_find_ext_capability); | 304 | EXPORT_SYMBOL_GPL(pci_find_ext_capability); |
305 | 305 | ||
306 | /** | ||
307 | * pci_bus_find_ext_capability - find an extended capability | ||
308 | * @bus: the PCI bus to query | ||
309 | * @devfn: PCI device to query | ||
310 | * @cap: capability code | ||
311 | * | ||
312 | * Like pci_find_ext_capability() but works for pci devices that do not have a | ||
313 | * pci_dev structure set up yet. | ||
314 | * | ||
315 | * Returns the address of the requested capability structure within the | ||
316 | * device's PCI configuration space or 0 in case the device does not | ||
317 | * support it. | ||
318 | */ | ||
319 | int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn, | ||
320 | int cap) | ||
321 | { | ||
322 | u32 header; | ||
323 | int ttl; | ||
324 | int pos = PCI_CFG_SPACE_SIZE; | ||
325 | |||
326 | /* minimum 8 bytes per capability */ | ||
327 | ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; | ||
328 | |||
329 | if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) | ||
330 | return 0; | ||
331 | if (header == 0xffffffff || header == 0) | ||
332 | return 0; | ||
333 | |||
334 | while (ttl-- > 0) { | ||
335 | if (PCI_EXT_CAP_ID(header) == cap) | ||
336 | return pos; | ||
337 | |||
338 | pos = PCI_EXT_CAP_NEXT(header); | ||
339 | if (pos < PCI_CFG_SPACE_SIZE) | ||
340 | break; | ||
341 | |||
342 | if (!pci_bus_read_config_dword(bus, devfn, pos, &header)) | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
306 | static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) | 349 | static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) |
307 | { | 350 | { |
308 | int rc, ttl = PCI_FIND_CAP_TTL; | 351 | int rc, ttl = PCI_FIND_CAP_TTL; |
@@ -2445,7 +2488,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2445 | if (!probe) { | 2488 | if (!probe) { |
2446 | pci_block_user_cfg_access(dev); | 2489 | pci_block_user_cfg_access(dev); |
2447 | /* block PM suspend, driver probe, etc. */ | 2490 | /* block PM suspend, driver probe, etc. */ |
2448 | down(&dev->dev.sem); | 2491 | device_lock(&dev->dev); |
2449 | } | 2492 | } |
2450 | 2493 | ||
2451 | rc = pci_dev_specific_reset(dev, probe); | 2494 | rc = pci_dev_specific_reset(dev, probe); |
@@ -2467,7 +2510,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) | |||
2467 | rc = pci_parent_bus_reset(dev, probe); | 2510 | rc = pci_parent_bus_reset(dev, probe); |
2468 | done: | 2511 | done: |
2469 | if (!probe) { | 2512 | if (!probe) { |
2470 | up(&dev->dev.sem); | 2513 | device_unlock(&dev->dev); |
2471 | pci_unblock_user_cfg_access(dev); | 2514 | pci_unblock_user_cfg_access(dev); |
2472 | } | 2515 | } |
2473 | 2516 | ||