|
@@ -63,11 +63,38 @@ pci_max_busnr(void)
|
|
|
return max;
|
|
|
}
|
|
|
|
|
|
+static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
|
|
|
+{
|
|
|
+ u8 id;
|
|
|
+ int ttl = 48;
|
|
|
+
|
|
|
+ while (ttl--) {
|
|
|
+ pci_bus_read_config_byte(bus, devfn, pos, &pos);
|
|
|
+ if (pos < 0x40)
|
|
|
+ break;
|
|
|
+ pos &= ~3;
|
|
|
+ pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
|
|
|
+ &id);
|
|
|
+ if (id == 0xff)
|
|
|
+ break;
|
|
|
+ if (id == cap)
|
|
|
+ return pos;
|
|
|
+ pos += PCI_CAP_LIST_NEXT;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
|
|
|
+{
|
|
|
+ return __pci_find_next_cap(dev->bus, dev->devfn,
|
|
|
+ pos + PCI_CAP_LIST_NEXT, cap);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(pci_find_next_capability);
|
|
|
+
|
|
|
static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
|
|
|
{
|
|
|
u16 status;
|
|
|
- u8 pos, id;
|
|
|
- int ttl = 48;
|
|
|
+ u8 pos;
|
|
|
|
|
|
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
|
|
|
if (!(status & PCI_STATUS_CAP_LIST))
|
|
@@ -76,24 +103,15 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
|
|
|
switch (hdr_type) {
|
|
|
case PCI_HEADER_TYPE_NORMAL:
|
|
|
case PCI_HEADER_TYPE_BRIDGE:
|
|
|
- pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
|
|
|
+ pos = PCI_CAPABILITY_LIST;
|
|
|
break;
|
|
|
case PCI_HEADER_TYPE_CARDBUS:
|
|
|
- pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
|
|
|
+ pos = PCI_CB_CAPABILITY_LIST;
|
|
|
break;
|
|
|
default:
|
|
|
return 0;
|
|
|
}
|
|
|
- while (ttl-- && pos >= 0x40) {
|
|
|
- pos &= ~3;
|
|
|
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
|
|
|
- if (id == 0xff)
|
|
|
- break;
|
|
|
- if (id == cap)
|
|
|
- return pos;
|
|
|
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ return __pci_find_next_cap(bus, devfn, pos, cap);
|
|
|
}
|
|
|
|
|
|
/**
|