aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c46
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
66static 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
87int 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}
92EXPORT_SYMBOL_GPL(pci_find_next_capability);
93
66static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) 94static 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/**