aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2012-07-13 16:24:59 -0400
committerBjorn Helgaas <bhelgaas@google.com>2012-08-22 15:47:27 -0400
commit44a9a36f6be43636ac2342c06d9feb60db77826a (patch)
tree3ff1b3d23d6416454599aa5712a081fdbe5aaaa0 /drivers/pci/pci.c
parent0d7614f09c1ebdbaa1599a5aba7593f147bf96ee (diff)
PCI: Add pci_find_next_ext_capability()
Some extended capabilities, e.g., the vendor-specific capability, can occur several times. The existing pci_find_ext_capability() only finds the first occurrence. This adds pci_find_next_ext_capability(), which can iterate through all of them. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index f3ea977a5b1b..d34415ba0f64 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -286,20 +286,17 @@ static int pci_pcie_cap2(struct pci_dev *dev)
286} 286}
287 287
288/** 288/**
289 * pci_find_ext_capability - Find an extended capability 289 * pci_find_next_ext_capability - Find an extended capability
290 * @dev: PCI device to query 290 * @dev: PCI device to query
291 * @start: address at which to start looking (0 to start at beginning of list)
291 * @cap: capability code 292 * @cap: capability code
292 * 293 *
293 * Returns the address of the requested extended capability structure 294 * Returns the address of the next matching extended capability structure
294 * within the device's PCI configuration space or 0 if the device does 295 * within the device's PCI configuration space or 0 if the device does
295 * not support it. Possible values for @cap: 296 * not support it. Some capabilities can occur several times, e.g., the
296 * 297 * vendor-specific capability, and this provides a way to find them all.
297 * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
298 * %PCI_EXT_CAP_ID_VC Virtual Channel
299 * %PCI_EXT_CAP_ID_DSN Device Serial Number
300 * %PCI_EXT_CAP_ID_PWR Power Budgeting
301 */ 298 */
302int pci_find_ext_capability(struct pci_dev *dev, int cap) 299int pci_find_next_ext_capability(struct pci_dev *dev, int start, int cap)
303{ 300{
304 u32 header; 301 u32 header;
305 int ttl; 302 int ttl;
@@ -311,6 +308,9 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
311 if (dev->cfg_size <= PCI_CFG_SPACE_SIZE) 308 if (dev->cfg_size <= PCI_CFG_SPACE_SIZE)
312 return 0; 309 return 0;
313 310
311 if (start)
312 pos = start;
313
314 if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL) 314 if (pci_read_config_dword(dev, pos, &header) != PCIBIOS_SUCCESSFUL)
315 return 0; 315 return 0;
316 316
@@ -322,7 +322,7 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
322 return 0; 322 return 0;
323 323
324 while (ttl-- > 0) { 324 while (ttl-- > 0) {
325 if (PCI_EXT_CAP_ID(header) == cap) 325 if (PCI_EXT_CAP_ID(header) == cap && pos != start)
326 return pos; 326 return pos;
327 327
328 pos = PCI_EXT_CAP_NEXT(header); 328 pos = PCI_EXT_CAP_NEXT(header);
@@ -335,6 +335,26 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
335 335
336 return 0; 336 return 0;
337} 337}
338EXPORT_SYMBOL_GPL(pci_find_next_ext_capability);
339
340/**
341 * pci_find_ext_capability - Find an extended capability
342 * @dev: PCI device to query
343 * @cap: capability code
344 *
345 * Returns the address of the requested extended capability structure
346 * within the device's PCI configuration space or 0 if the device does
347 * not support it. Possible values for @cap:
348 *
349 * %PCI_EXT_CAP_ID_ERR Advanced Error Reporting
350 * %PCI_EXT_CAP_ID_VC Virtual Channel
351 * %PCI_EXT_CAP_ID_DSN Device Serial Number
352 * %PCI_EXT_CAP_ID_PWR Power Budgeting
353 */
354int pci_find_ext_capability(struct pci_dev *dev, int cap)
355{
356 return pci_find_next_ext_capability(dev, 0, cap);
357}
338EXPORT_SYMBOL_GPL(pci_find_ext_capability); 358EXPORT_SYMBOL_GPL(pci_find_ext_capability);
339 359
340static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap) 360static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)