Commit ec9f168fcc344d2ffec1c8c822076bf22dab5c33
Exists in
master
and in
39 other branches
Merge branch 'simplify_PRT' into release
Conflicts: drivers/acpi/pci_irq.c Note that this merge disables e1d3a90846b40ad3160bf4b648d36c6badad39ac pci, acpi: reroute PCI interrupt to legacy boot interrupt equivalent Signed-off-by: Len Brown <len.brown@intel.com>
Showing 4 changed files Side-by-side Diff
drivers/acpi/pci_bind.c
... | ... | @@ -99,7 +99,7 @@ |
99 | 99 | */ |
100 | 100 | |
101 | 101 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
102 | - "Device %s has PCI address %02x:%02x:%02x.%02x\n", | |
102 | + "Device %s has PCI address %04x:%02x:%02x.%d\n", | |
103 | 103 | acpi_device_bid(device), id->segment, id->bus, |
104 | 104 | id->device, id->function)); |
105 | 105 | |
... | ... | @@ -111,12 +111,11 @@ |
111 | 111 | int acpi_pci_bind(struct acpi_device *device) |
112 | 112 | { |
113 | 113 | int result = 0; |
114 | - acpi_status status = AE_OK; | |
115 | - struct acpi_pci_data *data = NULL; | |
116 | - struct acpi_pci_data *pdata = NULL; | |
117 | - char *pathname = NULL; | |
118 | - struct acpi_buffer buffer = { 0, NULL }; | |
119 | - acpi_handle handle = NULL; | |
114 | + acpi_status status; | |
115 | + struct acpi_pci_data *data; | |
116 | + struct acpi_pci_data *pdata; | |
117 | + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
118 | + acpi_handle handle; | |
120 | 119 | struct pci_dev *dev; |
121 | 120 | struct pci_bus *bus; |
122 | 121 | |
123 | 122 | |
124 | 123 | |
125 | 124 | |
126 | 125 | |
... | ... | @@ -124,21 +123,18 @@ |
124 | 123 | if (!device || !device->parent) |
125 | 124 | return -EINVAL; |
126 | 125 | |
127 | - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); | |
128 | - if (!pathname) | |
129 | - return -ENOMEM; | |
130 | - buffer.length = ACPI_PATHNAME_MAX; | |
131 | - buffer.pointer = pathname; | |
132 | - | |
133 | 126 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); |
134 | - if (!data) { | |
135 | - kfree(pathname); | |
127 | + if (!data) | |
136 | 128 | return -ENOMEM; |
129 | + | |
130 | + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
131 | + if (ACPI_FAILURE(status)) { | |
132 | + kfree(data); | |
133 | + return -ENODEV; | |
137 | 134 | } |
138 | 135 | |
139 | - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
140 | 136 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", |
141 | - pathname)); | |
137 | + (char *)buffer.pointer)); | |
142 | 138 | |
143 | 139 | /* |
144 | 140 | * Segment & Bus |
... | ... | @@ -166,7 +162,7 @@ |
166 | 162 | data->id.device = device->pnp.bus_address >> 16; |
167 | 163 | data->id.function = device->pnp.bus_address & 0xFFFF; |
168 | 164 | |
169 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n", | |
165 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", | |
170 | 166 | data->id.segment, data->id.bus, data->id.device, |
171 | 167 | data->id.function)); |
172 | 168 | |
... | ... | @@ -196,7 +192,7 @@ |
196 | 192 | } |
197 | 193 | if (!data->dev) { |
198 | 194 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
199 | - "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", | |
195 | + "Device %04x:%02x:%02x.%d not present in PCI namespace\n", | |
200 | 196 | data->id.segment, data->id.bus, |
201 | 197 | data->id.device, data->id.function)); |
202 | 198 | result = -ENODEV; |
... | ... | @@ -204,7 +200,7 @@ |
204 | 200 | } |
205 | 201 | if (!data->dev->bus) { |
206 | 202 | printk(KERN_ERR PREFIX |
207 | - "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", | |
203 | + "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", | |
208 | 204 | data->id.segment, data->id.bus, |
209 | 205 | data->id.device, data->id.function); |
210 | 206 | result = -ENODEV; |
... | ... | @@ -219,7 +215,7 @@ |
219 | 215 | */ |
220 | 216 | if (data->dev->subordinate) { |
221 | 217 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
222 | - "Device %02x:%02x:%02x.%02x is a PCI bridge\n", | |
218 | + "Device %04x:%02x:%02x.%d is a PCI bridge\n", | |
223 | 219 | data->id.segment, data->id.bus, |
224 | 220 | data->id.device, data->id.function)); |
225 | 221 | data->bus = data->dev->subordinate; |
... | ... | @@ -262,7 +258,7 @@ |
262 | 258 | } |
263 | 259 | |
264 | 260 | end: |
265 | - kfree(pathname); | |
261 | + kfree(buffer.pointer); | |
266 | 262 | if (result) |
267 | 263 | kfree(data); |
268 | 264 | |
269 | 265 | |
270 | 266 | |
271 | 267 | |
... | ... | @@ -272,25 +268,21 @@ |
272 | 268 | static int acpi_pci_unbind(struct acpi_device *device) |
273 | 269 | { |
274 | 270 | int result = 0; |
275 | - acpi_status status = AE_OK; | |
276 | - struct acpi_pci_data *data = NULL; | |
277 | - char *pathname = NULL; | |
278 | - struct acpi_buffer buffer = { 0, NULL }; | |
271 | + acpi_status status; | |
272 | + struct acpi_pci_data *data; | |
273 | + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
279 | 274 | |
280 | 275 | |
281 | 276 | if (!device || !device->parent) |
282 | 277 | return -EINVAL; |
283 | 278 | |
284 | - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); | |
285 | - if (!pathname) | |
286 | - return -ENOMEM; | |
279 | + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
280 | + if (ACPI_FAILURE(status)) | |
281 | + return -ENODEV; | |
287 | 282 | |
288 | - buffer.length = ACPI_PATHNAME_MAX; | |
289 | - buffer.pointer = pathname; | |
290 | - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
291 | 283 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", |
292 | - pathname)); | |
293 | - kfree(pathname); | |
284 | + (char *) buffer.pointer)); | |
285 | + kfree(buffer.pointer); | |
294 | 286 | |
295 | 287 | status = |
296 | 288 | acpi_get_data(device->handle, acpi_pci_data_handler, |
297 | 289 | |
298 | 290 | |
299 | 291 | |
300 | 292 | |
301 | 293 | |
302 | 294 | |
303 | 295 | |
304 | 296 | |
305 | 297 | |
... | ... | @@ -322,50 +314,44 @@ |
322 | 314 | struct acpi_pci_id *id, struct pci_bus *bus) |
323 | 315 | { |
324 | 316 | int result = 0; |
325 | - acpi_status status = AE_OK; | |
317 | + acpi_status status; | |
326 | 318 | struct acpi_pci_data *data = NULL; |
327 | - char *pathname = NULL; | |
328 | - struct acpi_buffer buffer = { 0, NULL }; | |
319 | + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
329 | 320 | |
330 | - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); | |
331 | - if (!pathname) | |
332 | - return -ENOMEM; | |
333 | - | |
334 | - buffer.length = ACPI_PATHNAME_MAX; | |
335 | - buffer.pointer = pathname; | |
336 | - | |
337 | 321 | if (!device || !id || !bus) { |
338 | - kfree(pathname); | |
339 | 322 | return -EINVAL; |
340 | 323 | } |
341 | 324 | |
342 | 325 | data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); |
343 | - if (!data) { | |
344 | - kfree(pathname); | |
326 | + if (!data) | |
345 | 327 | return -ENOMEM; |
346 | - } | |
347 | 328 | |
348 | 329 | data->id = *id; |
349 | 330 | data->bus = bus; |
350 | 331 | device->ops.bind = acpi_pci_bind; |
351 | 332 | device->ops.unbind = acpi_pci_unbind; |
352 | 333 | |
353 | - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
334 | + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); | |
335 | + if (ACPI_FAILURE(status)) { | |
336 | + kfree (data); | |
337 | + return -ENODEV; | |
338 | + } | |
354 | 339 | |
355 | 340 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " |
356 | - "%02x:%02x\n", pathname, id->segment, id->bus)); | |
341 | + "%04x:%02x\n", (char *)buffer.pointer, | |
342 | + id->segment, id->bus)); | |
357 | 343 | |
358 | 344 | status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); |
359 | 345 | if (ACPI_FAILURE(status)) { |
360 | 346 | ACPI_EXCEPTION((AE_INFO, status, |
361 | 347 | "Unable to attach ACPI-PCI context to device %s", |
362 | - pathname)); | |
348 | + (char *)buffer.pointer)); | |
363 | 349 | result = -ENODEV; |
364 | 350 | goto end; |
365 | 351 | } |
366 | 352 | |
367 | 353 | end: |
368 | - kfree(pathname); | |
354 | + kfree(buffer.pointer); | |
369 | 355 | if (result != 0) |
370 | 356 | kfree(data); |
371 | 357 |
drivers/acpi/pci_irq.c
... | ... | @@ -4,6 +4,8 @@ |
4 | 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
6 | 6 | * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> |
7 | + * (c) Copyright 2008 Hewlett-Packard Development Company, L.P. | |
8 | + * Bjorn Helgaas <bjorn.helgaas@hp.com> | |
7 | 9 | * |
8 | 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
9 | 11 | * |
10 | 12 | |
11 | 13 | |
12 | 14 | |
13 | 15 | |
14 | 16 | |
... | ... | @@ -41,29 +43,36 @@ |
41 | 43 | #define _COMPONENT ACPI_PCI_COMPONENT |
42 | 44 | ACPI_MODULE_NAME("pci_irq"); |
43 | 45 | |
44 | -static struct acpi_prt_list acpi_prt; | |
46 | +struct acpi_prt_entry { | |
47 | + struct list_head list; | |
48 | + struct acpi_pci_id id; | |
49 | + u8 pin; | |
50 | + acpi_handle link; | |
51 | + u32 index; /* GSI, or link _CRS index */ | |
52 | +}; | |
53 | + | |
54 | +static LIST_HEAD(acpi_prt_list); | |
45 | 55 | static DEFINE_SPINLOCK(acpi_prt_lock); |
46 | 56 | |
57 | +static inline char pin_name(int pin) | |
58 | +{ | |
59 | + return 'A' + pin - 1; | |
60 | +} | |
61 | + | |
47 | 62 | /* -------------------------------------------------------------------------- |
48 | 63 | PCI IRQ Routing Table (PRT) Support |
49 | 64 | -------------------------------------------------------------------------- */ |
50 | 65 | |
51 | -static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, | |
52 | - int bus, | |
53 | - int device, int pin) | |
66 | +static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, | |
67 | + int pin) | |
54 | 68 | { |
55 | - struct acpi_prt_entry *entry = NULL; | |
69 | + struct acpi_prt_entry *entry; | |
70 | + int segment = pci_domain_nr(dev->bus); | |
71 | + int bus = dev->bus->number; | |
72 | + int device = PCI_SLOT(dev->devfn); | |
56 | 73 | |
57 | - if (!acpi_prt.count) | |
58 | - return NULL; | |
59 | - | |
60 | - /* | |
61 | - * Parse through all PRT entries looking for a match on the specified | |
62 | - * PCI device's segment, bus, device, and pin (don't care about func). | |
63 | - * | |
64 | - */ | |
65 | 74 | spin_lock(&acpi_prt_lock); |
66 | - list_for_each_entry(entry, &acpi_prt.entries, node) { | |
75 | + list_for_each_entry(entry, &acpi_prt_list, list) { | |
67 | 76 | if ((segment == entry->id.segment) |
68 | 77 | && (bus == entry->id.bus) |
69 | 78 | && (device == entry->id.device) |
... | ... | @@ -72,7 +81,6 @@ |
72 | 81 | return entry; |
73 | 82 | } |
74 | 83 | } |
75 | - | |
76 | 84 | spin_unlock(&acpi_prt_lock); |
77 | 85 | return NULL; |
78 | 86 | } |
79 | 87 | |
80 | 88 | |
81 | 89 | |
82 | 90 | |
... | ... | @@ -124,25 +132,27 @@ |
124 | 132 | char *actual_source; |
125 | 133 | }; |
126 | 134 | |
135 | +#define PCI_INTX_PIN(c) (c - 'A' + 1) | |
136 | + | |
127 | 137 | /* |
128 | 138 | * These systems have incorrect _PRT entries. The BIOS claims the PCI |
129 | 139 | * interrupt at the listed segment/bus/device/pin is connected to the first |
130 | 140 | * link device, but it is actually connected to the second. |
131 | 141 | */ |
132 | 142 | static struct prt_quirk prt_quirks[] = { |
133 | - { medion_md9580, 0, 0, 9, 'A', | |
143 | + { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'), | |
134 | 144 | "\\_SB_.PCI0.ISA_.LNKA", |
135 | 145 | "\\_SB_.PCI0.ISA_.LNKB"}, |
136 | - { dell_optiplex, 0, 0, 0xd, 'A', | |
146 | + { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'), | |
137 | 147 | "\\_SB_.LNKB", |
138 | 148 | "\\_SB_.LNKA"}, |
139 | - { hp_t5710, 0, 0, 1, 'A', | |
149 | + { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'), | |
140 | 150 | "\\_SB_.PCI0.LNK1", |
141 | 151 | "\\_SB_.PCI0.LNK3"}, |
142 | 152 | }; |
143 | 153 | |
144 | -static void | |
145 | -do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) | |
154 | +static void do_prt_fixups(struct acpi_prt_entry *entry, | |
155 | + struct acpi_pci_routing_table *prt) | |
146 | 156 | { |
147 | 157 | int i; |
148 | 158 | struct prt_quirk *quirk; |
149 | 159 | |
150 | 160 | |
151 | 161 | |
152 | 162 | |
153 | 163 | |
154 | 164 | |
155 | 165 | |
... | ... | @@ -158,42 +168,43 @@ |
158 | 168 | entry->id.segment == quirk->segment && |
159 | 169 | entry->id.bus == quirk->bus && |
160 | 170 | entry->id.device == quirk->device && |
161 | - entry->pin + 'A' == quirk->pin && | |
171 | + entry->pin == quirk->pin && | |
162 | 172 | !strcmp(prt->source, quirk->source) && |
163 | 173 | strlen(prt->source) >= strlen(quirk->actual_source)) { |
164 | 174 | printk(KERN_WARNING PREFIX "firmware reports " |
165 | 175 | "%04x:%02x:%02x PCI INT %c connected to %s; " |
166 | 176 | "changing to %s\n", |
167 | 177 | entry->id.segment, entry->id.bus, |
168 | - entry->id.device, 'A' + entry->pin, | |
178 | + entry->id.device, pin_name(entry->pin), | |
169 | 179 | prt->source, quirk->actual_source); |
170 | 180 | strcpy(prt->source, quirk->actual_source); |
171 | 181 | } |
172 | 182 | } |
173 | 183 | } |
174 | 184 | |
175 | -static int | |
176 | -acpi_pci_irq_add_entry(acpi_handle handle, | |
177 | - int segment, int bus, struct acpi_pci_routing_table *prt) | |
185 | +static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, | |
186 | + struct acpi_pci_routing_table *prt) | |
178 | 187 | { |
179 | - struct acpi_prt_entry *entry = NULL; | |
188 | + struct acpi_prt_entry *entry; | |
180 | 189 | |
181 | - | |
182 | - if (!prt) | |
183 | - return -EINVAL; | |
184 | - | |
185 | 190 | entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); |
186 | 191 | if (!entry) |
187 | 192 | return -ENOMEM; |
188 | 193 | |
194 | + /* | |
195 | + * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses | |
196 | + * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert | |
197 | + * it here. | |
198 | + */ | |
189 | 199 | entry->id.segment = segment; |
190 | 200 | entry->id.bus = bus; |
191 | 201 | entry->id.device = (prt->address >> 16) & 0xFFFF; |
192 | - entry->id.function = prt->address & 0xFFFF; | |
193 | - entry->pin = prt->pin; | |
202 | + entry->pin = prt->pin + 1; | |
194 | 203 | |
195 | 204 | do_prt_fixups(entry, prt); |
196 | 205 | |
206 | + entry->index = prt->source_index; | |
207 | + | |
197 | 208 | /* |
198 | 209 | * Type 1: Dynamic |
199 | 210 | * --------------- |
... | ... | @@ -207,10 +218,9 @@ |
207 | 218 | * (e.g. exists somewhere 'below' this _PRT entry in the ACPI |
208 | 219 | * namespace). |
209 | 220 | */ |
210 | - if (prt->source[0]) { | |
211 | - acpi_get_handle(handle, prt->source, &entry->link.handle); | |
212 | - entry->link.index = prt->source_index; | |
213 | - } | |
221 | + if (prt->source[0]) | |
222 | + acpi_get_handle(handle, prt->source, &entry->link); | |
223 | + | |
214 | 224 | /* |
215 | 225 | * Type 2: Static |
216 | 226 | * -------------- |
217 | 227 | |
218 | 228 | |
219 | 229 | |
220 | 230 | |
221 | 231 | |
222 | 232 | |
223 | 233 | |
224 | 234 | |
225 | 235 | |
226 | 236 | |
227 | 237 | |
228 | 238 | |
... | ... | @@ -218,85 +228,39 @@ |
218 | 228 | * the IRQ value, which is hardwired to specific interrupt inputs on |
219 | 229 | * the interrupt controller. |
220 | 230 | */ |
221 | - else | |
222 | - entry->link.index = prt->source_index; | |
223 | 231 | |
224 | 232 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, |
225 | - " %02X:%02X:%02X[%c] -> %s[%d]\n", | |
233 | + " %04x:%02x:%02x[%c] -> %s[%d]\n", | |
226 | 234 | entry->id.segment, entry->id.bus, |
227 | - entry->id.device, ('A' + entry->pin), prt->source, | |
228 | - entry->link.index)); | |
235 | + entry->id.device, pin_name(entry->pin), | |
236 | + prt->source, entry->index)); | |
229 | 237 | |
230 | 238 | spin_lock(&acpi_prt_lock); |
231 | - list_add_tail(&entry->node, &acpi_prt.entries); | |
232 | - acpi_prt.count++; | |
239 | + list_add_tail(&entry->list, &acpi_prt_list); | |
233 | 240 | spin_unlock(&acpi_prt_lock); |
234 | 241 | |
235 | 242 | return 0; |
236 | 243 | } |
237 | 244 | |
238 | -static void | |
239 | -acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry) | |
240 | -{ | |
241 | - if (segment == entry->id.segment && bus == entry->id.bus) { | |
242 | - acpi_prt.count--; | |
243 | - list_del(&entry->node); | |
244 | - kfree(entry); | |
245 | - } | |
246 | -} | |
247 | - | |
248 | 245 | int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) |
249 | 246 | { |
250 | - acpi_status status = AE_OK; | |
251 | - char *pathname = NULL; | |
252 | - struct acpi_buffer buffer = { 0, NULL }; | |
253 | - struct acpi_pci_routing_table *prt = NULL; | |
254 | - struct acpi_pci_routing_table *entry = NULL; | |
255 | - static int first_time = 1; | |
247 | + acpi_status status; | |
248 | + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
249 | + struct acpi_pci_routing_table *entry; | |
256 | 250 | |
251 | + /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ | |
252 | + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | |
253 | + if (ACPI_FAILURE(status)) | |
254 | + return -ENODEV; | |
257 | 255 | |
258 | - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); | |
259 | - if (!pathname) | |
260 | - return -ENOMEM; | |
261 | - | |
262 | - if (first_time) { | |
263 | - acpi_prt.count = 0; | |
264 | - INIT_LIST_HEAD(&acpi_prt.entries); | |
265 | - first_time = 0; | |
266 | - } | |
267 | - | |
268 | - /* | |
269 | - * NOTE: We're given a 'handle' to the _PRT object's parent device | |
270 | - * (either a PCI root bridge or PCI-PCI bridge). | |
271 | - */ | |
272 | - | |
273 | - buffer.length = ACPI_PATHNAME_MAX; | |
274 | - buffer.pointer = pathname; | |
275 | - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | |
276 | - | |
277 | 256 | printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", |
278 | - pathname); | |
257 | + (char *) buffer.pointer); | |
279 | 258 | |
280 | - /* | |
281 | - * Evaluate this _PRT and add its entries to our global list (acpi_prt). | |
282 | - */ | |
259 | + kfree(buffer.pointer); | |
283 | 260 | |
284 | - buffer.length = 0; | |
261 | + buffer.length = ACPI_ALLOCATE_BUFFER; | |
285 | 262 | buffer.pointer = NULL; |
286 | - kfree(pathname); | |
287 | - status = acpi_get_irq_routing_table(handle, &buffer); | |
288 | - if (status != AE_BUFFER_OVERFLOW) { | |
289 | - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", | |
290 | - acpi_format_exception(status))); | |
291 | - return -ENODEV; | |
292 | - } | |
293 | 263 | |
294 | - prt = kzalloc(buffer.length, GFP_KERNEL); | |
295 | - if (!prt) { | |
296 | - return -ENOMEM; | |
297 | - } | |
298 | - buffer.pointer = prt; | |
299 | - | |
300 | 264 | status = acpi_get_irq_routing_table(handle, &buffer); |
301 | 265 | if (ACPI_FAILURE(status)) { |
302 | 266 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", |
303 | 267 | |
304 | 268 | |
305 | 269 | |
306 | 270 | |
307 | 271 | |
... | ... | @@ -305,36 +269,30 @@ |
305 | 269 | return -ENODEV; |
306 | 270 | } |
307 | 271 | |
308 | - entry = prt; | |
309 | - | |
272 | + entry = buffer.pointer; | |
310 | 273 | while (entry && (entry->length > 0)) { |
311 | 274 | acpi_pci_irq_add_entry(handle, segment, bus, entry); |
312 | 275 | entry = (struct acpi_pci_routing_table *) |
313 | 276 | ((unsigned long)entry + entry->length); |
314 | 277 | } |
315 | 278 | |
316 | - kfree(prt); | |
317 | - | |
279 | + kfree(buffer.pointer); | |
318 | 280 | return 0; |
319 | 281 | } |
320 | 282 | |
321 | 283 | void acpi_pci_irq_del_prt(int segment, int bus) |
322 | 284 | { |
323 | - struct list_head *node = NULL, *n = NULL; | |
324 | - struct acpi_prt_entry *entry = NULL; | |
285 | + struct acpi_prt_entry *entry, *tmp; | |
325 | 286 | |
326 | - if (!acpi_prt.count) { | |
327 | - return; | |
328 | - } | |
329 | - | |
330 | 287 | printk(KERN_DEBUG |
331 | - "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", segment, | |
332 | - bus); | |
288 | + "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", | |
289 | + segment, bus); | |
333 | 290 | spin_lock(&acpi_prt_lock); |
334 | - list_for_each_safe(node, n, &acpi_prt.entries) { | |
335 | - entry = list_entry(node, struct acpi_prt_entry, node); | |
336 | - | |
337 | - acpi_pci_irq_del_entry(segment, bus, entry); | |
291 | + list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { | |
292 | + if (segment == entry->id.segment && bus == entry->id.bus) { | |
293 | + list_del(&entry->list); | |
294 | + kfree(entry); | |
295 | + } | |
338 | 296 | } |
339 | 297 | spin_unlock(&acpi_prt_lock); |
340 | 298 | } |
341 | 299 | |
342 | 300 | |
343 | 301 | |
344 | 302 | |
... | ... | @@ -342,162 +300,26 @@ |
342 | 300 | /* -------------------------------------------------------------------------- |
343 | 301 | PCI Interrupt Routing Support |
344 | 302 | -------------------------------------------------------------------------- */ |
345 | -typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **); | |
346 | - | |
347 | -static int | |
348 | -acpi_pci_allocate_irq(struct acpi_prt_entry *entry, | |
349 | - int *triggering, int *polarity, char **link) | |
303 | +static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) | |
350 | 304 | { |
351 | - int irq; | |
305 | + struct acpi_prt_entry *entry; | |
306 | + struct pci_dev *bridge; | |
307 | + u8 bridge_pin, orig_pin = pin; | |
352 | 308 | |
353 | - | |
354 | - if (entry->link.handle) { | |
355 | - irq = acpi_pci_link_allocate_irq(entry->link.handle, | |
356 | - entry->link.index, triggering, | |
357 | - polarity, link); | |
358 | - if (irq < 0) { | |
359 | - printk(KERN_WARNING PREFIX | |
360 | - "Invalid IRQ link routing entry\n"); | |
361 | - return -1; | |
362 | - } | |
363 | - } else { | |
364 | - irq = entry->link.index; | |
365 | - *triggering = ACPI_LEVEL_SENSITIVE; | |
366 | - *polarity = ACPI_ACTIVE_LOW; | |
309 | + entry = acpi_pci_irq_find_prt_entry(dev, pin); | |
310 | + if (entry) { | |
311 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", | |
312 | + pci_name(dev), pin_name(pin))); | |
313 | + return entry; | |
367 | 314 | } |
368 | 315 | |
369 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | |
370 | - return irq; | |
371 | -} | |
372 | - | |
373 | -static int | |
374 | -acpi_pci_free_irq(struct acpi_prt_entry *entry, | |
375 | - int *triggering, int *polarity, char **link) | |
376 | -{ | |
377 | - int irq; | |
378 | - | |
379 | - if (entry->link.handle) { | |
380 | - irq = acpi_pci_link_free_irq(entry->link.handle); | |
381 | - } else { | |
382 | - irq = entry->link.index; | |
383 | - } | |
384 | - return irq; | |
385 | -} | |
386 | - | |
387 | -#ifdef CONFIG_X86_IO_APIC | |
388 | -extern int noioapicquirk; | |
389 | - | |
390 | -static int bridge_has_boot_interrupt_variant(struct pci_bus *bus) | |
391 | -{ | |
392 | - struct pci_bus *bus_it; | |
393 | - | |
394 | - for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { | |
395 | - if (!bus_it->self) | |
396 | - return 0; | |
397 | - | |
398 | - printk(KERN_INFO "vendor=%04x device=%04x\n", bus_it->self->vendor, | |
399 | - bus_it->self->device); | |
400 | - | |
401 | - if (bus_it->self->irq_reroute_variant) | |
402 | - return bus_it->self->irq_reroute_variant; | |
403 | - } | |
404 | - return 0; | |
405 | -} | |
406 | -#endif /* CONFIG_X86_IO_APIC */ | |
407 | - | |
408 | -/* | |
409 | - * acpi_pci_irq_lookup | |
410 | - * success: return IRQ >= 0 | |
411 | - * failure: return -1 | |
412 | - */ | |
413 | -static int | |
414 | -acpi_pci_irq_lookup(struct pci_bus *bus, | |
415 | - int device, | |
416 | - int pin, | |
417 | - int *triggering, | |
418 | - int *polarity, char **link, irq_lookup_func func) | |
419 | -{ | |
420 | - struct acpi_prt_entry *entry = NULL; | |
421 | - int segment = pci_domain_nr(bus); | |
422 | - int bus_nr = bus->number; | |
423 | - int ret; | |
424 | - | |
425 | - | |
426 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
427 | - "Searching for PRT entry for %02x:%02x:%02x[%c]\n", | |
428 | - segment, bus_nr, device, ('A' + pin))); | |
429 | - | |
430 | - entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); | |
431 | - if (!entry) { | |
432 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); | |
433 | - return -1; | |
434 | - } | |
435 | - | |
436 | - ret = func(entry, triggering, polarity, link); | |
437 | - | |
438 | -#ifdef CONFIG_X86_IO_APIC | |
439 | - /* | |
440 | - * Some chipsets (e.g. intel 6700PXH) generate a legacy INTx when the | |
441 | - * IRQ entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel | |
442 | - * does during interrupt handling). When this INTx generation cannot be | |
443 | - * disabled, we reroute these interrupts to their legacy equivalent to | |
444 | - * get rid of spurious interrupts. | |
445 | - */ | |
446 | - if (!noioapicquirk) { | |
447 | - switch (bridge_has_boot_interrupt_variant(bus)) { | |
448 | - case 0: | |
449 | - /* no rerouting necessary */ | |
450 | - break; | |
451 | - | |
452 | - case INTEL_IRQ_REROUTE_VARIANT: | |
453 | - /* | |
454 | - * Remap according to INTx routing table in 6700PXH | |
455 | - * specs, intel order number 302628-002, section | |
456 | - * 2.15.2. Other chipsets (80332, ...) have the same | |
457 | - * mapping and are handled here as well. | |
458 | - */ | |
459 | - printk(KERN_INFO "pci irq %d -> rerouted to legacy " | |
460 | - "irq %d\n", ret, (ret % 4) + 16); | |
461 | - ret = (ret % 4) + 16; | |
462 | - break; | |
463 | - | |
464 | - default: | |
465 | - printk(KERN_INFO "not rerouting irq %d to legacy irq: " | |
466 | - "unknown mapping\n", ret); | |
467 | - break; | |
468 | - } | |
469 | - } | |
470 | -#endif /* CONFIG_X86_IO_APIC */ | |
471 | - | |
472 | - return ret; | |
473 | -} | |
474 | - | |
475 | -/* | |
476 | - * acpi_pci_irq_derive | |
477 | - * success: return IRQ >= 0 | |
478 | - * failure: return < 0 | |
479 | - */ | |
480 | -static int | |
481 | -acpi_pci_irq_derive(struct pci_dev *dev, | |
482 | - int pin, | |
483 | - int *triggering, | |
484 | - int *polarity, char **link, irq_lookup_func func) | |
485 | -{ | |
486 | - struct pci_dev *bridge = dev; | |
487 | - int irq = -1; | |
488 | - u8 bridge_pin = 0, orig_pin = pin; | |
489 | - | |
490 | - | |
491 | - if (!dev) | |
492 | - return -EINVAL; | |
493 | - | |
494 | 316 | /* |
495 | 317 | * Attempt to derive an IRQ for this device from a parent bridge's |
496 | 318 | * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). |
497 | 319 | */ |
498 | - while (irq < 0 && bridge->bus->self) { | |
499 | - pin = (pin + PCI_SLOT(bridge->devfn)) % 4; | |
500 | - bridge = bridge->bus->self; | |
320 | + bridge = dev->bus->self; | |
321 | + while (bridge) { | |
322 | + pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; | |
501 | 323 | |
502 | 324 | if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { |
503 | 325 | /* PC card has the same IRQ as its cardbridge */ |
504 | 326 | |
505 | 327 | |
506 | 328 | |
507 | 329 | |
508 | 330 | |
509 | 331 | |
510 | 332 | |
... | ... | @@ -506,50 +328,40 @@ |
506 | 328 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
507 | 329 | "No interrupt pin configured for device %s\n", |
508 | 330 | pci_name(bridge))); |
509 | - return -1; | |
331 | + return NULL; | |
510 | 332 | } |
511 | - /* Pin is from 0 to 3 */ | |
512 | - bridge_pin--; | |
513 | 333 | pin = bridge_pin; |
514 | 334 | } |
515 | 335 | |
516 | - irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), | |
517 | - pin, triggering, polarity, | |
518 | - link, func); | |
519 | - } | |
336 | + entry = acpi_pci_irq_find_prt_entry(bridge, pin); | |
337 | + if (entry) { | |
338 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
339 | + "Derived GSI for %s INT %c from %s\n", | |
340 | + pci_name(dev), pin_name(orig_pin), | |
341 | + pci_name(bridge))); | |
342 | + return entry; | |
343 | + } | |
520 | 344 | |
521 | - if (irq < 0) { | |
522 | - dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", | |
523 | - 'A' + orig_pin); | |
524 | - return -1; | |
345 | + dev = bridge; | |
346 | + bridge = dev->bus->self; | |
525 | 347 | } |
526 | 348 | |
527 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n", | |
528 | - irq, pci_name(dev), pci_name(bridge))); | |
529 | - | |
530 | - return irq; | |
349 | + dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", | |
350 | + pin_name(orig_pin)); | |
351 | + return NULL; | |
531 | 352 | } |
532 | 353 | |
533 | -/* | |
534 | - * acpi_pci_irq_enable | |
535 | - * success: return 0 | |
536 | - * failure: return < 0 | |
537 | - */ | |
538 | - | |
539 | 354 | int acpi_pci_irq_enable(struct pci_dev *dev) |
540 | 355 | { |
541 | - int irq = 0; | |
542 | - u8 pin = 0; | |
356 | + struct acpi_prt_entry *entry; | |
357 | + int gsi; | |
358 | + u8 pin; | |
543 | 359 | int triggering = ACPI_LEVEL_SENSITIVE; |
544 | 360 | int polarity = ACPI_ACTIVE_LOW; |
545 | 361 | char *link = NULL; |
546 | 362 | char link_desc[16]; |
547 | 363 | int rc; |
548 | 364 | |
549 | - | |
550 | - if (!dev) | |
551 | - return -EINVAL; | |
552 | - | |
553 | 365 | pin = dev->pin; |
554 | 366 | if (!pin) { |
555 | 367 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
556 | 368 | |
... | ... | @@ -557,31 +369,9 @@ |
557 | 369 | pci_name(dev))); |
558 | 370 | return 0; |
559 | 371 | } |
560 | - pin--; | |
561 | 372 | |
562 | - if (!dev->bus) { | |
563 | - dev_err(&dev->dev, "invalid (NULL) 'bus' field\n"); | |
564 | - return -ENODEV; | |
565 | - } | |
566 | - | |
567 | - /* | |
568 | - * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT | |
569 | - * values override any BIOS-assigned IRQs set during boot. | |
570 | - */ | |
571 | - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | |
572 | - &triggering, &polarity, &link, | |
573 | - acpi_pci_allocate_irq); | |
574 | - | |
575 | - /* | |
576 | - * If no PRT entry was found, we'll try to derive an IRQ from the | |
577 | - * device's parent bridge. | |
578 | - */ | |
579 | - if (irq < 0) | |
580 | - irq = acpi_pci_irq_derive(dev, pin, &triggering, | |
581 | - &polarity, &link, | |
582 | - acpi_pci_allocate_irq); | |
583 | - | |
584 | - if (irq < 0) { | |
373 | + entry = acpi_pci_irq_lookup(dev, pin); | |
374 | + if (!entry) { | |
585 | 375 | /* |
586 | 376 | * IDE legacy mode controller IRQs are magic. Why do compat |
587 | 377 | * extensions always make such a nasty mess. |
588 | 378 | |
... | ... | @@ -590,12 +380,24 @@ |
590 | 380 | (dev->class & 0x05) == 0) |
591 | 381 | return 0; |
592 | 382 | } |
383 | + | |
384 | + if (entry) { | |
385 | + if (entry->link) | |
386 | + gsi = acpi_pci_link_allocate_irq(entry->link, | |
387 | + entry->index, | |
388 | + &triggering, &polarity, | |
389 | + &link); | |
390 | + else | |
391 | + gsi = entry->index; | |
392 | + } else | |
393 | + gsi = -1; | |
394 | + | |
593 | 395 | /* |
594 | 396 | * No IRQ known to the ACPI subsystem - maybe the BIOS / |
595 | 397 | * driver reported one, then use it. Exit in any case. |
596 | 398 | */ |
597 | - if (irq < 0) { | |
598 | - dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin); | |
399 | + if (gsi < 0) { | |
400 | + dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); | |
599 | 401 | /* Interrupt Line values above 0xF are forbidden */ |
600 | 402 | if (dev->irq > 0 && (dev->irq <= 0xF)) { |
601 | 403 | printk(" - using IRQ %d\n", dev->irq); |
602 | 404 | |
... | ... | @@ -608,10 +410,10 @@ |
608 | 410 | } |
609 | 411 | } |
610 | 412 | |
611 | - rc = acpi_register_gsi(irq, triggering, polarity); | |
413 | + rc = acpi_register_gsi(gsi, triggering, polarity); | |
612 | 414 | if (rc < 0) { |
613 | 415 | dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", |
614 | - 'A' + pin); | |
416 | + pin_name(pin)); | |
615 | 417 | return rc; |
616 | 418 | } |
617 | 419 | dev->irq = rc; |
... | ... | @@ -622,7 +424,7 @@ |
622 | 424 | link_desc[0] = '\0'; |
623 | 425 | |
624 | 426 | dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", |
625 | - 'A' + pin, link_desc, irq, | |
427 | + pin_name(pin), link_desc, gsi, | |
626 | 428 | (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", |
627 | 429 | (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); |
628 | 430 | |
629 | 431 | |
630 | 432 | |
631 | 433 | |
632 | 434 | |
633 | 435 | |
... | ... | @@ -636,43 +438,29 @@ |
636 | 438 | |
637 | 439 | void acpi_pci_irq_disable(struct pci_dev *dev) |
638 | 440 | { |
639 | - int gsi = 0; | |
640 | - u8 pin = 0; | |
641 | - int triggering = ACPI_LEVEL_SENSITIVE; | |
642 | - int polarity = ACPI_ACTIVE_LOW; | |
441 | + struct acpi_prt_entry *entry; | |
442 | + int gsi; | |
443 | + u8 pin; | |
643 | 444 | |
644 | - | |
645 | - if (!dev || !dev->bus) | |
646 | - return; | |
647 | - | |
648 | 445 | pin = dev->pin; |
649 | 446 | if (!pin) |
650 | 447 | return; |
651 | - pin--; | |
652 | 448 | |
653 | - /* | |
654 | - * First we check the PCI IRQ routing table (PRT) for an IRQ. | |
655 | - */ | |
656 | - gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | |
657 | - &triggering, &polarity, NULL, | |
658 | - acpi_pci_free_irq); | |
659 | - /* | |
660 | - * If no PRT entry was found, we'll try to derive an IRQ from the | |
661 | - * device's parent bridge. | |
662 | - */ | |
663 | - if (gsi < 0) | |
664 | - gsi = acpi_pci_irq_derive(dev, pin, | |
665 | - &triggering, &polarity, NULL, | |
666 | - acpi_pci_free_irq); | |
667 | - if (gsi < 0) | |
449 | + entry = acpi_pci_irq_lookup(dev, pin); | |
450 | + if (!entry) | |
668 | 451 | return; |
669 | 452 | |
453 | + if (entry->link) | |
454 | + gsi = acpi_pci_link_free_irq(entry->link); | |
455 | + else | |
456 | + gsi = entry->index; | |
457 | + | |
670 | 458 | /* |
671 | 459 | * TBD: It might be worth clearing dev->irq by magic constant |
672 | 460 | * (e.g. PCI_UNDEFINED_IRQ). |
673 | 461 | */ |
674 | 462 | |
675 | - dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin); | |
463 | + dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); | |
676 | 464 | acpi_unregister_gsi(gsi); |
677 | 465 | } |
include/acpi/platform/aclinux.h
include/linux/acpi.h
... | ... | @@ -131,22 +131,6 @@ |
131 | 131 | */ |
132 | 132 | void acpi_unregister_gsi (u32 gsi); |
133 | 133 | |
134 | -struct acpi_prt_entry { | |
135 | - struct list_head node; | |
136 | - struct acpi_pci_id id; | |
137 | - u8 pin; | |
138 | - struct { | |
139 | - acpi_handle handle; | |
140 | - u32 index; | |
141 | - } link; | |
142 | - u32 irq; | |
143 | -}; | |
144 | - | |
145 | -struct acpi_prt_list { | |
146 | - int count; | |
147 | - struct list_head entries; | |
148 | -}; | |
149 | - | |
150 | 134 | struct pci_dev; |
151 | 135 | |
152 | 136 | int acpi_pci_irq_enable (struct pci_dev *dev); |