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.c112
1 files changed, 100 insertions, 12 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5a14b73cf3a1..6bfb942428e4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -68,12 +68,14 @@ pci_max_busnr(void)
68 68
69#endif /* 0 */ 69#endif /* 0 */
70 70
71static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap) 71#define PCI_FIND_CAP_TTL 48
72
73static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
74 u8 pos, int cap, int *ttl)
72{ 75{
73 u8 id; 76 u8 id;
74 int ttl = 48;
75 77
76 while (ttl--) { 78 while ((*ttl)--) {
77 pci_bus_read_config_byte(bus, devfn, pos, &pos); 79 pci_bus_read_config_byte(bus, devfn, pos, &pos);
78 if (pos < 0x40) 80 if (pos < 0x40)
79 break; 81 break;
@@ -89,6 +91,14 @@ static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos,
89 return 0; 91 return 0;
90} 92}
91 93
94static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
95 u8 pos, int cap)
96{
97 int ttl = PCI_FIND_CAP_TTL;
98
99 return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
100}
101
92int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap) 102int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
93{ 103{
94 return __pci_find_next_cap(dev->bus, dev->devfn, 104 return __pci_find_next_cap(dev->bus, dev->devfn,
@@ -96,10 +106,10 @@ int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
96} 106}
97EXPORT_SYMBOL_GPL(pci_find_next_capability); 107EXPORT_SYMBOL_GPL(pci_find_next_capability);
98 108
99static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) 109static int __pci_bus_find_cap_start(struct pci_bus *bus,
110 unsigned int devfn, u8 hdr_type)
100{ 111{
101 u16 status; 112 u16 status;
102 u8 pos;
103 113
104 pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); 114 pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
105 if (!(status & PCI_STATUS_CAP_LIST)) 115 if (!(status & PCI_STATUS_CAP_LIST))
@@ -108,15 +118,14 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
108 switch (hdr_type) { 118 switch (hdr_type) {
109 case PCI_HEADER_TYPE_NORMAL: 119 case PCI_HEADER_TYPE_NORMAL:
110 case PCI_HEADER_TYPE_BRIDGE: 120 case PCI_HEADER_TYPE_BRIDGE:
111 pos = PCI_CAPABILITY_LIST; 121 return PCI_CAPABILITY_LIST;
112 break;
113 case PCI_HEADER_TYPE_CARDBUS: 122 case PCI_HEADER_TYPE_CARDBUS:
114 pos = PCI_CB_CAPABILITY_LIST; 123 return PCI_CB_CAPABILITY_LIST;
115 break;
116 default: 124 default:
117 return 0; 125 return 0;
118 } 126 }
119 return __pci_find_next_cap(bus, devfn, pos, cap); 127
128 return 0;
120} 129}
121 130
122/** 131/**
@@ -140,7 +149,13 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
140 */ 149 */
141int pci_find_capability(struct pci_dev *dev, int cap) 150int pci_find_capability(struct pci_dev *dev, int cap)
142{ 151{
143 return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap); 152 int pos;
153
154 pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
155 if (pos)
156 pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
157
158 return pos;
144} 159}
145 160
146/** 161/**
@@ -158,11 +173,16 @@ int pci_find_capability(struct pci_dev *dev, int cap)
158 */ 173 */
159int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) 174int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
160{ 175{
176 int pos;
161 u8 hdr_type; 177 u8 hdr_type;
162 178
163 pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); 179 pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
164 180
165 return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap); 181 pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f);
182 if (pos)
183 pos = __pci_find_next_cap(bus, devfn, pos, cap);
184
185 return pos;
166} 186}
167 187
168/** 188/**
@@ -214,6 +234,74 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
214} 234}
215EXPORT_SYMBOL_GPL(pci_find_ext_capability); 235EXPORT_SYMBOL_GPL(pci_find_ext_capability);
216 236
237static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
238{
239 int rc, ttl = PCI_FIND_CAP_TTL;
240 u8 cap, mask;
241
242 if (ht_cap == HT_CAPTYPE_SLAVE || ht_cap == HT_CAPTYPE_HOST)
243 mask = HT_3BIT_CAP_MASK;
244 else
245 mask = HT_5BIT_CAP_MASK;
246
247 pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
248 PCI_CAP_ID_HT, &ttl);
249 while (pos) {
250 rc = pci_read_config_byte(dev, pos + 3, &cap);
251 if (rc != PCIBIOS_SUCCESSFUL)
252 return 0;
253
254 if ((cap & mask) == ht_cap)
255 return pos;
256
257 pos = __pci_find_next_cap_ttl(dev->bus, dev->devfn, pos,
258 PCI_CAP_ID_HT, &ttl);
259 }
260
261 return 0;
262}
263/**
264 * pci_find_next_ht_capability - query a device's Hypertransport capabilities
265 * @dev: PCI device to query
266 * @pos: Position from which to continue searching
267 * @ht_cap: Hypertransport capability code
268 *
269 * To be used in conjunction with pci_find_ht_capability() to search for
270 * all capabilities matching @ht_cap. @pos should always be a value returned
271 * from pci_find_ht_capability().
272 *
273 * NB. To be 100% safe against broken PCI devices, the caller should take
274 * steps to avoid an infinite loop.
275 */
276int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap)
277{
278 return __pci_find_next_ht_cap(dev, pos + PCI_CAP_LIST_NEXT, ht_cap);
279}
280EXPORT_SYMBOL_GPL(pci_find_next_ht_capability);
281
282/**
283 * pci_find_ht_capability - query a device's Hypertransport capabilities
284 * @dev: PCI device to query
285 * @ht_cap: Hypertransport capability code
286 *
287 * Tell if a device supports a given Hypertransport capability.
288 * Returns an address within the device's PCI configuration space
289 * or 0 in case the device does not support the request capability.
290 * The address points to the PCI capability, of type PCI_CAP_ID_HT,
291 * which has a Hypertransport capability matching @ht_cap.
292 */
293int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
294{
295 int pos;
296
297 pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
298 if (pos)
299 pos = __pci_find_next_ht_cap(dev, pos, ht_cap);
300
301 return pos;
302}
303EXPORT_SYMBOL_GPL(pci_find_ht_capability);
304
217/** 305/**
218 * pci_find_parent_resource - return resource region of parent bus of given region 306 * pci_find_parent_resource - return resource region of parent bus of given region
219 * @dev: PCI device structure contains resources to be searched 307 * @dev: PCI device structure contains resources to be searched