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 * (c) Copyright 2008 Hewlett-Packard Development Company, L.P. 8 * Bjorn Helgaas <bjorn.helgaas@hp.com> 9 * 10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or (at 15 * your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License along 23 * with this program; if not, write to the Free Software Foundation, Inc., 24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 25 * 26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 */ 28 29 30 #include <linux/dmi.h> 31 #include <linux/kernel.h> 32 #include <linux/module.h> 33 #include <linux/init.h> 34 #include <linux/types.h> 35 #include <linux/proc_fs.h> 36 #include <linux/spinlock.h> 37 #include <linux/pm.h> 38 #include <linux/pci.h> 39 #include <linux/acpi.h> 40 #include <acpi/acpi_bus.h> 41 #include <acpi/acpi_drivers.h> 42 43 #define _COMPONENT ACPI_PCI_COMPONENT 44 ACPI_MODULE_NAME("pci_irq"); 45 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); 55 static DEFINE_SPINLOCK(acpi_prt_lock); 56 57 static inline char pin_name(int pin) 58 { 59 return 'A' + pin - 1; 60 } 61 62 /* -------------------------------------------------------------------------- 63 PCI IRQ Routing Table (PRT) Support 64 -------------------------------------------------------------------------- */ 65 66 static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, 67 int pin) 68 { 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); 73 74 spin_lock(&acpi_prt_lock); 75 list_for_each_entry(entry, &acpi_prt_list, list) { 76 if ((segment == entry->id.segment) 77 && (bus == entry->id.bus) 78 && (device == entry->id.device) 79 && (pin == entry->pin)) { 80 spin_unlock(&acpi_prt_lock); 81 return entry; 82 } 83 } 84 spin_unlock(&acpi_prt_lock); 85 return NULL; 86 } 87 88 /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ 89 static const struct dmi_system_id medion_md9580[] = { 90 { 91 .ident = "Medion MD9580-F laptop", 92 .matches = { 93 DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 94 DMI_MATCH(DMI_PRODUCT_NAME, "A555"), 95 }, 96 }, 97 { } 98 }; 99 100 /* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */ 101 static const struct dmi_system_id dell_optiplex[] = { 102 { 103 .ident = "Dell Optiplex GX1", 104 .matches = { 105 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 106 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"), 107 }, 108 }, 109 { } 110 }; 111 112 /* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */ 113 static const struct dmi_system_id hp_t5710[] = { 114 { 115 .ident = "HP t5710", 116 .matches = { 117 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 118 DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"), 119 DMI_MATCH(DMI_BOARD_NAME, "098Ch"), 120 }, 121 }, 122 { } 123 }; 124 125 struct prt_quirk { 126 const struct dmi_system_id *system; 127 unsigned int segment; 128 unsigned int bus; 129 unsigned int device; 130 unsigned char pin; 131 const char *source; /* according to BIOS */ 132 const char *actual_source; 133 }; 134 135 #define PCI_INTX_PIN(c) (c - 'A' + 1) 136 137 /* 138 * These systems have incorrect _PRT entries. The BIOS claims the PCI 139 * interrupt at the listed segment/bus/device/pin is connected to the first 140 * link device, but it is actually connected to the second. 141 */ 142 static const struct prt_quirk prt_quirks[] = { 143 { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'), 144 "\\_SB_.PCI0.ISA_.LNKA", 145 "\\_SB_.PCI0.ISA_.LNKB"}, 146 { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'), 147 "\\_SB_.LNKB", 148 "\\_SB_.LNKA"}, 149 { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'), 150 "\\_SB_.PCI0.LNK1", 151 "\\_SB_.PCI0.LNK3"}, 152 }; 153 154 static void do_prt_fixups(struct acpi_prt_entry *entry, 155 struct acpi_pci_routing_table *prt) 156 { 157 int i; 158 const struct prt_quirk *quirk; 159 160 for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) { 161 quirk = &prt_quirks[i]; 162 163 /* All current quirks involve link devices, not GSIs */ 164 if (!prt->source) 165 continue; 166 167 if (dmi_check_system(quirk->system) && 168 entry->id.segment == quirk->segment && 169 entry->id.bus == quirk->bus && 170 entry->id.device == quirk->device && 171 entry->pin == quirk->pin && 172 !strcmp(prt->source, quirk->source) && 173 strlen(prt->source) >= strlen(quirk->actual_source)) { 174 printk(KERN_WARNING PREFIX "firmware reports " 175 "%04x:%02x:%02x PCI INT %c connected to %s; " 176 "changing to %s\n", 177 entry->id.segment, entry->id.bus, 178 entry->id.device, pin_name(entry->pin), 179 prt->source, quirk->actual_source); 180 strcpy(prt->source, quirk->actual_source); 181 } 182 } 183 } 184 185 static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, 186 struct acpi_pci_routing_table *prt) 187 { 188 struct acpi_prt_entry *entry; 189 190 entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); 191 if (!entry) 192 return -ENOMEM; 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 */ 199 entry->id.segment = segment; 200 entry->id.bus = bus; 201 entry->id.device = (prt->address >> 16) & 0xFFFF; 202 entry->pin = prt->pin + 1; 203 204 do_prt_fixups(entry, prt); 205 206 entry->index = prt->source_index; 207 208 /* 209 * Type 1: Dynamic 210 * --------------- 211 * The 'source' field specifies the PCI interrupt link device used to 212 * configure the IRQ assigned to this slot|dev|pin. The 'source_index' 213 * indicates which resource descriptor in the resource template (of 214 * the link device) this interrupt is allocated from. 215 * 216 * NOTE: Don't query the Link Device for IRQ information at this time 217 * because Link Device enumeration may not have occurred yet 218 * (e.g. exists somewhere 'below' this _PRT entry in the ACPI 219 * namespace). 220 */ 221 if (prt->source[0]) 222 acpi_get_handle(handle, prt->source, &entry->link); 223 224 /* 225 * Type 2: Static 226 * -------------- 227 * The 'source' field is NULL, and the 'source_index' field specifies 228 * the IRQ value, which is hardwired to specific interrupt inputs on 229 * the interrupt controller. 230 */ 231 232 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, 233 " %04x:%02x:%02x[%c] -> %s[%d]\n", 234 entry->id.segment, entry->id.bus, 235 entry->id.device, pin_name(entry->pin), 236 prt->source, entry->index)); 237 238 spin_lock(&acpi_prt_lock); 239 list_add_tail(&entry->list, &acpi_prt_list); 240 spin_unlock(&acpi_prt_lock); 241 242 return 0; 243 } 244 245 int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) 246 { 247 acpi_status status; 248 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 249 struct acpi_pci_routing_table *entry; 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; 255 256 printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", 257 (char *) buffer.pointer); 258 259 kfree(buffer.pointer); 260 261 buffer.length = ACPI_ALLOCATE_BUFFER; 262 buffer.pointer = NULL; 263 264 status = acpi_get_irq_routing_table(handle, &buffer); 265 if (ACPI_FAILURE(status)) { 266 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", 267 acpi_format_exception(status))); 268 kfree(buffer.pointer); 269 return -ENODEV; 270 } 271 272 entry = buffer.pointer; 273 while (entry && (entry->length > 0)) { 274 acpi_pci_irq_add_entry(handle, segment, bus, entry); 275 entry = (struct acpi_pci_routing_table *) 276 ((unsigned long)entry + entry->length); 277 } 278 279 kfree(buffer.pointer); 280 return 0; 281 } 282 283 void acpi_pci_irq_del_prt(int segment, int bus) 284 { 285 struct acpi_prt_entry *entry, *tmp; 286 287 printk(KERN_DEBUG 288 "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", 289 segment, bus); 290 spin_lock(&acpi_prt_lock); 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 } 296 } 297 spin_unlock(&acpi_prt_lock); 298 } 299 300 /* -------------------------------------------------------------------------- 301 PCI Interrupt Routing Support 302 -------------------------------------------------------------------------- */ 303 static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) 304 { 305 struct acpi_prt_entry *entry; 306 struct pci_dev *bridge; 307 u8 bridge_pin, orig_pin = pin; 308 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; 314 } 315 316 /* 317 * Attempt to derive an IRQ for this device from a parent bridge's 318 * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). 319 */ 320 bridge = dev->bus->self; 321 while (bridge) { 322 pin = pci_swizzle_interrupt_pin(dev, pin); 323 324 if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { 325 /* PC card has the same IRQ as its cardbridge */ 326 bridge_pin = bridge->pin; 327 if (!bridge_pin) { 328 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 329 "No interrupt pin configured for device %s\n", 330 pci_name(bridge))); 331 return NULL; 332 } 333 pin = bridge_pin; 334 } 335 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 } 344 345 dev = bridge; 346 bridge = dev->bus->self; 347 } 348 349 dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", 350 pin_name(orig_pin)); 351 return NULL; 352 } 353 354 int acpi_pci_irq_enable(struct pci_dev *dev) 355 { 356 struct acpi_prt_entry *entry; 357 int gsi; 358 u8 pin; 359 int triggering = ACPI_LEVEL_SENSITIVE; 360 int polarity = ACPI_ACTIVE_LOW; 361 char *link = NULL; 362 char link_desc[16]; 363 int rc; 364 365 pin = dev->pin; 366 if (!pin) { 367 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 368 "No interrupt pin configured for device %s\n", 369 pci_name(dev))); 370 return 0; 371 } 372 373 entry = acpi_pci_irq_lookup(dev, pin); 374 if (!entry) { 375 /* 376 * IDE legacy mode controller IRQs are magic. Why do compat 377 * extensions always make such a nasty mess. 378 */ 379 if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && 380 (dev->class & 0x05) == 0) 381 return 0; 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 395 /* 396 * No IRQ known to the ACPI subsystem - maybe the BIOS / 397 * driver reported one, then use it. Exit in any case. 398 */ 399 if (gsi < 0) { 400 dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); 401 /* Interrupt Line values above 0xF are forbidden */ 402 if (dev->irq > 0 && (dev->irq <= 0xF)) { 403 printk(" - using IRQ %d\n", dev->irq); 404 acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, 405 ACPI_ACTIVE_LOW); 406 return 0; 407 } else { 408 printk("\n"); 409 return 0; 410 } 411 } 412 413 rc = acpi_register_gsi(gsi, triggering, polarity); 414 if (rc < 0) { 415 dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", 416 pin_name(pin)); 417 return rc; 418 } 419 dev->irq = rc; 420 421 if (link) 422 snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); 423 else 424 link_desc[0] = '\0'; 425 426 dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", 427 pin_name(pin), link_desc, gsi, 428 (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", 429 (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); 430 431 return 0; 432 } 433 434 /* FIXME: implement x86/x86_64 version */ 435 void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) 436 { 437 } 438 439 void acpi_pci_irq_disable(struct pci_dev *dev) 440 { 441 struct acpi_prt_entry *entry; 442 int gsi; 443 u8 pin; 444 445 pin = dev->pin; 446 if (!pin) 447 return; 448 449 entry = acpi_pci_irq_lookup(dev, pin); 450 if (!entry) 451 return; 452 453 if (entry->link) 454 gsi = acpi_pci_link_free_irq(entry->link); 455 else 456 gsi = entry->index; 457 458 /* 459 * TBD: It might be worth clearing dev->irq by magic constant 460 * (e.g. PCI_UNDEFINED_IRQ). 461 */ 462 463 dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); 464 acpi_unregister_gsi(gsi); 465 } 466