diff options
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e74d75843047..8e287a828d5d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -63,11 +63,38 @@ pci_max_busnr(void) | |||
63 | return max; | 63 | return max; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) | ||
67 | { | ||
68 | u8 id; | ||
69 | int ttl = 48; | ||
70 | |||
71 | while (ttl--) { | ||
72 | pci_bus_read_config_byte(bus, devfn, pos, &pos); | ||
73 | if (pos < 0x40) | ||
74 | break; | ||
75 | pos &= ~3; | ||
76 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, | ||
77 | &id); | ||
78 | if (id == 0xff) | ||
79 | break; | ||
80 | if (id == cap) | ||
81 | return pos; | ||
82 | pos += PCI_CAP_LIST_NEXT; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) | ||
88 | { | ||
89 | return __pci_find_next_cap(dev->bus, dev->devfn, | ||
90 | pos + PCI_CAP_LIST_NEXT, cap); | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(pci_find_next_capability); | ||
93 | |||
66 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) | 94 | static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) |
67 | { | 95 | { |
68 | u16 status; | 96 | u16 status; |
69 | u8 pos, id; | 97 | u8 pos; |
70 | int ttl = 48; | ||
71 | 98 | ||
72 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); | 99 | pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); |
73 | if (!(status & PCI_STATUS_CAP_LIST)) | 100 | 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 | |||
76 | switch (hdr_type) { | 103 | switch (hdr_type) { |
77 | case PCI_HEADER_TYPE_NORMAL: | 104 | case PCI_HEADER_TYPE_NORMAL: |
78 | case PCI_HEADER_TYPE_BRIDGE: | 105 | case PCI_HEADER_TYPE_BRIDGE: |
79 | pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); | 106 | pos = PCI_CAPABILITY_LIST; |
80 | break; | 107 | break; |
81 | case PCI_HEADER_TYPE_CARDBUS: | 108 | case PCI_HEADER_TYPE_CARDBUS: |
82 | pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); | 109 | pos = PCI_CB_CAPABILITY_LIST; |
83 | break; | 110 | break; |
84 | default: | 111 | default: |
85 | return 0; | 112 | return 0; |
86 | } | 113 | } |
87 | while (ttl-- && pos >= 0x40) { | 114 | return __pci_find_next_cap(bus, devfn, pos, cap); |
88 | pos &= ~3; | ||
89 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); | ||
90 | if (id == 0xff) | ||
91 | break; | ||
92 | if (id == cap) | ||
93 | return pos; | ||
94 | pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); | ||
95 | } | ||
96 | return 0; | ||
97 | } | 115 | } |
98 | 116 | ||
99 | /** | 117 | /** |