diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/pci_irq.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acpi/pci_irq.c')
-rw-r--r-- | drivers/acpi/pci_irq.c | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c new file mode 100644 index 000000000000..12b0eea63407 --- /dev/null +++ b/drivers/acpi/pci_irq.c | |||
@@ -0,0 +1,518 @@ | |||
1 | /* | ||
2 | * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $) | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
6 | * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> | ||
7 | * | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
13 | * your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License along | ||
21 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
23 | * | ||
24 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
25 | */ | ||
26 | |||
27 | #include <linux/config.h> | ||
28 | |||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/types.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/pm.h> | ||
36 | #include <linux/pci.h> | ||
37 | #include <linux/acpi.h> | ||
38 | #include <acpi/acpi_bus.h> | ||
39 | #include <acpi/acpi_drivers.h> | ||
40 | |||
41 | |||
42 | #define _COMPONENT ACPI_PCI_COMPONENT | ||
43 | ACPI_MODULE_NAME ("pci_irq") | ||
44 | |||
45 | static struct acpi_prt_list acpi_prt; | ||
46 | static DEFINE_SPINLOCK(acpi_prt_lock); | ||
47 | |||
48 | /* -------------------------------------------------------------------------- | ||
49 | PCI IRQ Routing Table (PRT) Support | ||
50 | -------------------------------------------------------------------------- */ | ||
51 | |||
52 | static struct acpi_prt_entry * | ||
53 | acpi_pci_irq_find_prt_entry ( | ||
54 | int segment, | ||
55 | int bus, | ||
56 | int device, | ||
57 | int pin) | ||
58 | { | ||
59 | struct list_head *node = NULL; | ||
60 | struct acpi_prt_entry *entry = NULL; | ||
61 | |||
62 | ACPI_FUNCTION_TRACE("acpi_pci_irq_find_prt_entry"); | ||
63 | |||
64 | if (!acpi_prt.count) | ||
65 | return_PTR(NULL); | ||
66 | |||
67 | /* | ||
68 | * Parse through all PRT entries looking for a match on the specified | ||
69 | * PCI device's segment, bus, device, and pin (don't care about func). | ||
70 | * | ||
71 | */ | ||
72 | spin_lock(&acpi_prt_lock); | ||
73 | list_for_each(node, &acpi_prt.entries) { | ||
74 | entry = list_entry(node, struct acpi_prt_entry, node); | ||
75 | if ((segment == entry->id.segment) | ||
76 | && (bus == entry->id.bus) | ||
77 | && (device == entry->id.device) | ||
78 | && (pin == entry->pin)) { | ||
79 | spin_unlock(&acpi_prt_lock); | ||
80 | return_PTR(entry); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | spin_unlock(&acpi_prt_lock); | ||
85 | return_PTR(NULL); | ||
86 | } | ||
87 | |||
88 | |||
89 | static int | ||
90 | acpi_pci_irq_add_entry ( | ||
91 | acpi_handle handle, | ||
92 | int segment, | ||
93 | int bus, | ||
94 | struct acpi_pci_routing_table *prt) | ||
95 | { | ||
96 | struct acpi_prt_entry *entry = NULL; | ||
97 | |||
98 | ACPI_FUNCTION_TRACE("acpi_pci_irq_add_entry"); | ||
99 | |||
100 | if (!prt) | ||
101 | return_VALUE(-EINVAL); | ||
102 | |||
103 | entry = kmalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); | ||
104 | if (!entry) | ||
105 | return_VALUE(-ENOMEM); | ||
106 | memset(entry, 0, sizeof(struct acpi_prt_entry)); | ||
107 | |||
108 | entry->id.segment = segment; | ||
109 | entry->id.bus = bus; | ||
110 | entry->id.device = (prt->address >> 16) & 0xFFFF; | ||
111 | entry->id.function = prt->address & 0xFFFF; | ||
112 | entry->pin = prt->pin; | ||
113 | |||
114 | /* | ||
115 | * Type 1: Dynamic | ||
116 | * --------------- | ||
117 | * The 'source' field specifies the PCI interrupt link device used to | ||
118 | * configure the IRQ assigned to this slot|dev|pin. The 'source_index' | ||
119 | * indicates which resource descriptor in the resource template (of | ||
120 | * the link device) this interrupt is allocated from. | ||
121 | * | ||
122 | * NOTE: Don't query the Link Device for IRQ information at this time | ||
123 | * because Link Device enumeration may not have occurred yet | ||
124 | * (e.g. exists somewhere 'below' this _PRT entry in the ACPI | ||
125 | * namespace). | ||
126 | */ | ||
127 | if (prt->source[0]) { | ||
128 | acpi_get_handle(handle, prt->source, &entry->link.handle); | ||
129 | entry->link.index = prt->source_index; | ||
130 | } | ||
131 | /* | ||
132 | * Type 2: Static | ||
133 | * -------------- | ||
134 | * The 'source' field is NULL, and the 'source_index' field specifies | ||
135 | * the IRQ value, which is hardwired to specific interrupt inputs on | ||
136 | * the interrupt controller. | ||
137 | */ | ||
138 | else | ||
139 | entry->link.index = prt->source_index; | ||
140 | |||
141 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, | ||
142 | " %02X:%02X:%02X[%c] -> %s[%d]\n", | ||
143 | entry->id.segment, entry->id.bus, entry->id.device, | ||
144 | ('A' + entry->pin), prt->source, entry->link.index)); | ||
145 | |||
146 | spin_lock(&acpi_prt_lock); | ||
147 | list_add_tail(&entry->node, &acpi_prt.entries); | ||
148 | acpi_prt.count++; | ||
149 | spin_unlock(&acpi_prt_lock); | ||
150 | |||
151 | return_VALUE(0); | ||
152 | } | ||
153 | |||
154 | |||
155 | static void | ||
156 | acpi_pci_irq_del_entry ( | ||
157 | int segment, | ||
158 | int bus, | ||
159 | struct acpi_prt_entry *entry) | ||
160 | { | ||
161 | if (segment == entry->id.segment && bus == entry->id.bus){ | ||
162 | acpi_prt.count--; | ||
163 | list_del(&entry->node); | ||
164 | kfree(entry); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | int | ||
170 | acpi_pci_irq_add_prt ( | ||
171 | acpi_handle handle, | ||
172 | int segment, | ||
173 | int bus) | ||
174 | { | ||
175 | acpi_status status = AE_OK; | ||
176 | char *pathname = NULL; | ||
177 | struct acpi_buffer buffer = {0, NULL}; | ||
178 | struct acpi_pci_routing_table *prt = NULL; | ||
179 | struct acpi_pci_routing_table *entry = NULL; | ||
180 | static int first_time = 1; | ||
181 | |||
182 | ACPI_FUNCTION_TRACE("acpi_pci_irq_add_prt"); | ||
183 | |||
184 | pathname = (char *) kmalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); | ||
185 | if(!pathname) | ||
186 | return_VALUE(-ENOMEM); | ||
187 | memset(pathname, 0, ACPI_PATHNAME_MAX); | ||
188 | |||
189 | if (first_time) { | ||
190 | acpi_prt.count = 0; | ||
191 | INIT_LIST_HEAD(&acpi_prt.entries); | ||
192 | first_time = 0; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * NOTE: We're given a 'handle' to the _PRT object's parent device | ||
197 | * (either a PCI root bridge or PCI-PCI bridge). | ||
198 | */ | ||
199 | |||
200 | buffer.length = ACPI_PATHNAME_MAX; | ||
201 | buffer.pointer = pathname; | ||
202 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
203 | |||
204 | printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", | ||
205 | pathname); | ||
206 | |||
207 | /* | ||
208 | * Evaluate this _PRT and add its entries to our global list (acpi_prt). | ||
209 | */ | ||
210 | |||
211 | buffer.length = 0; | ||
212 | buffer.pointer = NULL; | ||
213 | kfree(pathname); | ||
214 | status = acpi_get_irq_routing_table(handle, &buffer); | ||
215 | if (status != AE_BUFFER_OVERFLOW) { | ||
216 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", | ||
217 | acpi_format_exception(status))); | ||
218 | return_VALUE(-ENODEV); | ||
219 | } | ||
220 | |||
221 | prt = kmalloc(buffer.length, GFP_KERNEL); | ||
222 | if (!prt){ | ||
223 | return_VALUE(-ENOMEM); | ||
224 | } | ||
225 | memset(prt, 0, buffer.length); | ||
226 | buffer.pointer = prt; | ||
227 | |||
228 | status = acpi_get_irq_routing_table(handle, &buffer); | ||
229 | if (ACPI_FAILURE(status)) { | ||
230 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRT [%s]\n", | ||
231 | acpi_format_exception(status))); | ||
232 | kfree(buffer.pointer); | ||
233 | return_VALUE(-ENODEV); | ||
234 | } | ||
235 | |||
236 | entry = prt; | ||
237 | |||
238 | while (entry && (entry->length > 0)) { | ||
239 | acpi_pci_irq_add_entry(handle, segment, bus, entry); | ||
240 | entry = (struct acpi_pci_routing_table *) | ||
241 | ((unsigned long) entry + entry->length); | ||
242 | } | ||
243 | |||
244 | kfree(prt); | ||
245 | |||
246 | return_VALUE(0); | ||
247 | } | ||
248 | |||
249 | void | ||
250 | acpi_pci_irq_del_prt (int segment, int bus) | ||
251 | { | ||
252 | struct list_head *node = NULL, *n = NULL; | ||
253 | struct acpi_prt_entry *entry = NULL; | ||
254 | |||
255 | if (!acpi_prt.count) { | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", | ||
260 | segment, bus); | ||
261 | spin_lock(&acpi_prt_lock); | ||
262 | list_for_each_safe(node, n, &acpi_prt.entries) { | ||
263 | entry = list_entry(node, struct acpi_prt_entry, node); | ||
264 | |||
265 | acpi_pci_irq_del_entry(segment, bus, entry); | ||
266 | } | ||
267 | spin_unlock(&acpi_prt_lock); | ||
268 | } | ||
269 | /* -------------------------------------------------------------------------- | ||
270 | PCI Interrupt Routing Support | ||
271 | -------------------------------------------------------------------------- */ | ||
272 | |||
273 | /* | ||
274 | * acpi_pci_irq_lookup | ||
275 | * success: return IRQ >= 0 | ||
276 | * failure: return -1 | ||
277 | */ | ||
278 | static int | ||
279 | acpi_pci_irq_lookup ( | ||
280 | struct pci_bus *bus, | ||
281 | int device, | ||
282 | int pin, | ||
283 | int *edge_level, | ||
284 | int *active_high_low, | ||
285 | char **link) | ||
286 | { | ||
287 | struct acpi_prt_entry *entry = NULL; | ||
288 | int segment = pci_domain_nr(bus); | ||
289 | int bus_nr = bus->number; | ||
290 | int irq; | ||
291 | |||
292 | ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); | ||
293 | |||
294 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
295 | "Searching for PRT entry for %02x:%02x:%02x[%c]\n", | ||
296 | segment, bus_nr, device, ('A' + pin))); | ||
297 | |||
298 | entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); | ||
299 | if (!entry) { | ||
300 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); | ||
301 | return_VALUE(-1); | ||
302 | } | ||
303 | |||
304 | if (entry->link.handle) { | ||
305 | irq = acpi_pci_link_get_irq(entry->link.handle, | ||
306 | entry->link.index, edge_level, active_high_low, link); | ||
307 | if (irq < 0) { | ||
308 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); | ||
309 | return_VALUE(-1); | ||
310 | } | ||
311 | } else { | ||
312 | irq = entry->link.index; | ||
313 | *edge_level = ACPI_LEVEL_SENSITIVE; | ||
314 | *active_high_low = ACPI_ACTIVE_LOW; | ||
315 | } | ||
316 | |||
317 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); | ||
318 | |||
319 | return_VALUE(irq); | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * acpi_pci_irq_derive | ||
324 | * success: return IRQ >= 0 | ||
325 | * failure: return < 0 | ||
326 | */ | ||
327 | static int | ||
328 | acpi_pci_irq_derive ( | ||
329 | struct pci_dev *dev, | ||
330 | int pin, | ||
331 | int *edge_level, | ||
332 | int *active_high_low, | ||
333 | char **link) | ||
334 | { | ||
335 | struct pci_dev *bridge = dev; | ||
336 | int irq = -1; | ||
337 | u8 bridge_pin = 0; | ||
338 | |||
339 | ACPI_FUNCTION_TRACE("acpi_pci_irq_derive"); | ||
340 | |||
341 | if (!dev) | ||
342 | return_VALUE(-EINVAL); | ||
343 | |||
344 | /* | ||
345 | * Attempt to derive an IRQ for this device from a parent bridge's | ||
346 | * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). | ||
347 | */ | ||
348 | while (irq < 0 && bridge->bus->self) { | ||
349 | pin = (pin + PCI_SLOT(bridge->devfn)) % 4; | ||
350 | bridge = bridge->bus->self; | ||
351 | |||
352 | if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { | ||
353 | /* PC card has the same IRQ as its cardbridge */ | ||
354 | pci_read_config_byte(bridge, PCI_INTERRUPT_PIN, &bridge_pin); | ||
355 | if (!bridge_pin) { | ||
356 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
357 | "No interrupt pin configured for device %s\n", pci_name(bridge))); | ||
358 | return_VALUE(-1); | ||
359 | } | ||
360 | /* Pin is from 0 to 3 */ | ||
361 | bridge_pin --; | ||
362 | pin = bridge_pin; | ||
363 | } | ||
364 | |||
365 | irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), | ||
366 | pin, edge_level, active_high_low, link); | ||
367 | } | ||
368 | |||
369 | if (irq < 0) { | ||
370 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev))); | ||
371 | return_VALUE(-1); | ||
372 | } | ||
373 | |||
374 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n", | ||
375 | irq, pci_name(dev), pci_name(bridge))); | ||
376 | |||
377 | return_VALUE(irq); | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * acpi_pci_irq_enable | ||
382 | * success: return 0 | ||
383 | * failure: return < 0 | ||
384 | */ | ||
385 | |||
386 | int | ||
387 | acpi_pci_irq_enable ( | ||
388 | struct pci_dev *dev) | ||
389 | { | ||
390 | int irq = 0; | ||
391 | u8 pin = 0; | ||
392 | int edge_level = ACPI_LEVEL_SENSITIVE; | ||
393 | int active_high_low = ACPI_ACTIVE_LOW; | ||
394 | extern int via_interrupt_line_quirk; | ||
395 | char *link = NULL; | ||
396 | |||
397 | ACPI_FUNCTION_TRACE("acpi_pci_irq_enable"); | ||
398 | |||
399 | if (!dev) | ||
400 | return_VALUE(-EINVAL); | ||
401 | |||
402 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
403 | if (!pin) { | ||
404 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(dev))); | ||
405 | return_VALUE(0); | ||
406 | } | ||
407 | pin--; | ||
408 | |||
409 | if (!dev->bus) { | ||
410 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid (NULL) 'bus' field\n")); | ||
411 | return_VALUE(-ENODEV); | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT | ||
416 | * values override any BIOS-assigned IRQs set during boot. | ||
417 | */ | ||
418 | irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | ||
419 | &edge_level, &active_high_low, &link); | ||
420 | |||
421 | /* | ||
422 | * If no PRT entry was found, we'll try to derive an IRQ from the | ||
423 | * device's parent bridge. | ||
424 | */ | ||
425 | if (irq < 0) | ||
426 | irq = acpi_pci_irq_derive(dev, pin, &edge_level, | ||
427 | &active_high_low, &link); | ||
428 | |||
429 | /* | ||
430 | * No IRQ known to the ACPI subsystem - maybe the BIOS / | ||
431 | * driver reported one, then use it. Exit in any case. | ||
432 | */ | ||
433 | if (irq < 0) { | ||
434 | printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI", | ||
435 | pci_name(dev), ('A' + pin)); | ||
436 | /* Interrupt Line values above 0xF are forbidden */ | ||
437 | if (dev->irq >= 0 && (dev->irq <= 0xF)) { | ||
438 | printk(" - using IRQ %d\n", dev->irq); | ||
439 | return_VALUE(0); | ||
440 | } | ||
441 | else { | ||
442 | printk("\n"); | ||
443 | return_VALUE(0); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | if (via_interrupt_line_quirk) | ||
448 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15); | ||
449 | |||
450 | dev->irq = acpi_register_gsi(irq, edge_level, active_high_low); | ||
451 | |||
452 | printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ", | ||
453 | pci_name(dev), 'A' + pin); | ||
454 | |||
455 | if (link) | ||
456 | printk("Link [%s] -> ", link); | ||
457 | |||
458 | printk("GSI %u (%s, %s) -> IRQ %d\n", irq, | ||
459 | (edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", | ||
460 | (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", | ||
461 | dev->irq); | ||
462 | |||
463 | return_VALUE(0); | ||
464 | } | ||
465 | EXPORT_SYMBOL(acpi_pci_irq_enable); | ||
466 | |||
467 | |||
468 | #ifdef CONFIG_ACPI_DEALLOCATE_IRQ | ||
469 | void | ||
470 | acpi_pci_irq_disable ( | ||
471 | struct pci_dev *dev) | ||
472 | { | ||
473 | int gsi = 0; | ||
474 | u8 pin = 0; | ||
475 | int edge_level = ACPI_LEVEL_SENSITIVE; | ||
476 | int active_high_low = ACPI_ACTIVE_LOW; | ||
477 | |||
478 | ACPI_FUNCTION_TRACE("acpi_pci_irq_disable"); | ||
479 | |||
480 | if (!dev) | ||
481 | return_VOID; | ||
482 | |||
483 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
484 | if (!pin) | ||
485 | return_VOID; | ||
486 | pin--; | ||
487 | |||
488 | if (!dev->bus) | ||
489 | return_VOID; | ||
490 | |||
491 | /* | ||
492 | * First we check the PCI IRQ routing table (PRT) for an IRQ. | ||
493 | */ | ||
494 | gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, | ||
495 | &edge_level, &active_high_low, NULL); | ||
496 | /* | ||
497 | * If no PRT entry was found, we'll try to derive an IRQ from the | ||
498 | * device's parent bridge. | ||
499 | */ | ||
500 | if (gsi < 0) | ||
501 | gsi = acpi_pci_irq_derive(dev, pin, | ||
502 | &edge_level, &active_high_low, NULL); | ||
503 | if (gsi < 0) | ||
504 | return_VOID; | ||
505 | |||
506 | /* | ||
507 | * TBD: It might be worth clearing dev->irq by magic constant | ||
508 | * (e.g. PCI_UNDEFINED_IRQ). | ||
509 | */ | ||
510 | |||
511 | printk(KERN_INFO PREFIX "PCI interrupt for device %s disabled\n", | ||
512 | pci_name(dev)); | ||
513 | |||
514 | acpi_unregister_gsi(gsi); | ||
515 | |||
516 | return_VOID; | ||
517 | } | ||
518 | #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */ | ||