11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pci_irq.c - ACPI PCI Interrupt Routing ($Revision: 11 $) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> 739488b041e2fdc206b3de4517b8f220ae07b2a20Bjorn Helgaas * (c) Copyright 2008 Hewlett-Packard Development Company, L.P. 839488b041e2fdc206b3de4517b8f220ae07b2a20Bjorn Helgaas * Bjorn Helgaas <bjorn.helgaas@hp.com> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License for more details. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License along 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas#include <linux/dmi.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pm.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/acpi.h> 395a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 43a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#define PREFIX "ACPI: " 44a192a9580bcc41692be1f36b77c3b681827f566aLen Brown 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_PCI_COMPONENT 46f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("pci_irq"); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 48f748bafa3ca1fb056e63afdeecacc1c68d8104dfBjorn Helgaasstruct acpi_prt_entry { 493604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas struct list_head list; 50f748bafa3ca1fb056e63afdeecacc1c68d8104dfBjorn Helgaas struct acpi_pci_id id; 51f748bafa3ca1fb056e63afdeecacc1c68d8104dfBjorn Helgaas u8 pin; 524eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas acpi_handle link; 534eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas u32 index; /* GSI, or link _CRS index */ 54f748bafa3ca1fb056e63afdeecacc1c68d8104dfBjorn Helgaas}; 55f748bafa3ca1fb056e63afdeecacc1c68d8104dfBjorn Helgaas 563604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaasstatic LIST_HEAD(acpi_prt_list); 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_prt_lock); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 59cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaasstatic inline char pin_name(int pin) 60cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas{ 61e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas return 'A' + pin - 1; 62cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas} 63cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI IRQ Routing Table (PRT) Support 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 68063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaasstatic struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, 69063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaas int pin) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 713604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas struct acpi_prt_entry *entry; 72063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaas int segment = pci_domain_nr(dev->bus); 73063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaas int bus = dev->bus->number; 74063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaas int device = PCI_SLOT(dev->devfn); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&acpi_prt_lock); 773604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas list_for_each_entry(entry, &acpi_prt_list, list) { 784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown if ((segment == entry->id.segment) 794be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown && (bus == entry->id.bus) 804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown && (device == entry->id.device) 814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown && (pin == entry->pin)) { 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&acpi_prt_lock); 83d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return entry; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&acpi_prt_lock); 87d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return NULL; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas/* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ 91609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulichstatic const struct dmi_system_id medion_md9580[] = { 92391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { 93391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .ident = "Medion MD9580-F laptop", 94391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .matches = { 95391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), 96391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_PRODUCT_NAME, "A555"), 97391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 98391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 99391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { } 100391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas}; 101391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 102391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas/* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */ 103609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulichstatic const struct dmi_system_id dell_optiplex[] = { 104391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { 105391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .ident = "Dell Optiplex GX1", 106391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .matches = { 107391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), 108391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX1 600S+"), 109391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 110391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 111391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { } 112391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas}; 113391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 114391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas/* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */ 115609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulichstatic const struct dmi_system_id hp_t5710[] = { 116391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { 117391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .ident = "HP t5710", 118391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas .matches = { 119391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 120391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_PRODUCT_NAME, "hp t5000 series"), 121391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas DMI_MATCH(DMI_BOARD_NAME, "098Ch"), 122391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 123391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas }, 124391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas { } 125391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas}; 126391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 127391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaasstruct prt_quirk { 128609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulich const struct dmi_system_id *system; 129391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas unsigned int segment; 130391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas unsigned int bus; 131391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas unsigned int device; 132391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas unsigned char pin; 133609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulich const char *source; /* according to BIOS */ 134609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulich const char *actual_source; 135391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas}; 136391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 137c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas#define PCI_INTX_PIN(c) (c - 'A' + 1) 138c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas 139391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas/* 140391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas * These systems have incorrect _PRT entries. The BIOS claims the PCI 141391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas * interrupt at the listed segment/bus/device/pin is connected to the first 142391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas * link device, but it is actually connected to the second. 143391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas */ 144609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulichstatic const struct prt_quirk prt_quirks[] = { 145c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'), 146b97d4803400a4442b0e4ae14d0bd8e83994b9004Bjorn Helgaas "\\_SB_.PCI0.ISA_.LNKA", 147b97d4803400a4442b0e4ae14d0bd8e83994b9004Bjorn Helgaas "\\_SB_.PCI0.ISA_.LNKB"}, 148c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'), 149391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas "\\_SB_.LNKB", 150391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas "\\_SB_.LNKA"}, 151c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'), 152391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas "\\_SB_.PCI0.LNK1", 153391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas "\\_SB_.PCI0.LNK3"}, 154391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas}; 155391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 1563f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaasstatic void do_prt_fixups(struct acpi_prt_entry *entry, 1573f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas struct acpi_pci_routing_table *prt) 158391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas{ 159391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas int i; 160609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427Jan Beulich const struct prt_quirk *quirk; 161391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 162391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) { 163391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas quirk = &prt_quirks[i]; 164391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 165391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas /* All current quirks involve link devices, not GSIs */ 166391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas if (!prt->source) 167391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas continue; 168391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 169391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas if (dmi_check_system(quirk->system) && 170391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas entry->id.segment == quirk->segment && 171391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas entry->id.bus == quirk->bus && 172391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas entry->id.device == quirk->device && 173c458033c9b72a81b890d97ec6339694bab252383Bjorn Helgaas entry->pin == quirk->pin && 174391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas !strcmp(prt->source, quirk->source) && 175391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas strlen(prt->source) >= strlen(quirk->actual_source)) { 176391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas printk(KERN_WARNING PREFIX "firmware reports " 177c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas "%04x:%02x:%02x PCI INT %c connected to %s; " 178391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas "changing to %s\n", 179391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas entry->id.segment, entry->id.bus, 180cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas entry->id.device, pin_name(entry->pin), 181391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas prt->source, quirk->actual_source); 182391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas strcpy(prt->source, quirk->actual_source); 183391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas } 184391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas } 185391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas} 186391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 187859a3f86ca83346f4097e956d0b27d96aa7a1cffAlexander Chiangstatic int acpi_pci_irq_add_entry(acpi_handle handle, struct pci_bus *bus, 1883f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas struct acpi_pci_routing_table *prt) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1903604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas struct acpi_prt_entry *entry; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19236bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 194d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 196e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas /* 197e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses 198e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert 199e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas * it here. 200e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas */ 201859a3f86ca83346f4097e956d0b27d96aa7a1cffAlexander Chiang entry->id.segment = pci_domain_nr(bus); 202859a3f86ca83346f4097e956d0b27d96aa7a1cffAlexander Chiang entry->id.bus = bus->number; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->id.device = (prt->address >> 16) & 0xFFFF; 204e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8cBjorn Helgaas entry->pin = prt->pin + 1; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 206391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas do_prt_fixups(entry, prt); 207391df5dce30a5aab477b9e55ea65a3e83bae96b1Bjorn Helgaas 2084eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas entry->index = prt->source_index; 2094eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Type 1: Dynamic 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * --------------- 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The 'source' field specifies the PCI interrupt link device used to 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configure the IRQ assigned to this slot|dev|pin. The 'source_index' 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * indicates which resource descriptor in the resource template (of 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the link device) this interrupt is allocated from. 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE: Don't query the Link Device for IRQ information at this time 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * because Link Device enumeration may not have occurred yet 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (e.g. exists somewhere 'below' this _PRT entry in the ACPI 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * namespace). 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2234eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas if (prt->source[0]) 2244eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas acpi_get_handle(handle, prt->source, &entry->link); 2254eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Type 2: Static 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -------------- 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The 'source' field is NULL, and the 'source_index' field specifies 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the IRQ value, which is hardwired to specific interrupt inputs on 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the interrupt controller. 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, 23521a53283a012f21764f2aaaac9414849e1153d93Bjorn Helgaas " %04x:%02x:%02x[%c] -> %s[%d]\n", 2364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown entry->id.segment, entry->id.bus, 237cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas entry->id.device, pin_name(entry->pin), 2384eaf6db3ea0edf7e011a613b5a15360444e58fecBjorn Helgaas prt->source, entry->index)); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&acpi_prt_lock); 2413604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas list_add_tail(&entry->list, &acpi_prt_list); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&acpi_prt_lock); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 244d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 247859a3f86ca83346f4097e956d0b27d96aa7a1cffAlexander Chiangint acpi_pci_irq_add_prt(acpi_handle handle, struct pci_bus *bus) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2492320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas acpi_status status; 2502320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 2512320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas struct acpi_pci_routing_table *entry; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2532320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ 2542320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 2552320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas if (ACPI_FAILURE(status)) 2562320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas return -ENODEV; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", 2592320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas (char *) buffer.pointer); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2612320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas kfree(buffer.pointer); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2632320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas buffer.length = ACPI_ALLOCATE_BUFFER; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer.pointer = NULL; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = acpi_get_irq_routing_table(handle, &buffer); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 268a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", 269a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger acpi_format_exception(status))); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(buffer.pointer); 271d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2742320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas entry = buffer.pointer; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (entry && (entry->length > 0)) { 276859a3f86ca83346f4097e956d0b27d96aa7a1cffAlexander Chiang acpi_pci_irq_add_entry(handle, bus, entry); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = (struct acpi_pci_routing_table *) 2784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ((unsigned long)entry + entry->length); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2812320ac6cb078eec77bf93742895dc35e64fae124Bjorn Helgaas kfree(buffer.pointer); 282d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 285d9efae3688addb15994c9ad9761dada6f988bc14Alexander Chiangvoid acpi_pci_irq_del_prt(struct pci_bus *bus) 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2873604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas struct acpi_prt_entry *entry, *tmp; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_DEBUG 29021a53283a012f21764f2aaaac9414849e1153d93Bjorn Helgaas "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", 291d9efae3688addb15994c9ad9761dada6f988bc14Alexander Chiang pci_domain_nr(bus), bus->number); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&acpi_prt_lock); 2933604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { 294d9efae3688addb15994c9ad9761dada6f988bc14Alexander Chiang if (pci_domain_nr(bus) == entry->id.segment 295d9efae3688addb15994c9ad9761dada6f988bc14Alexander Chiang && bus->number == entry->id.bus) { 2963604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas list_del(&entry->list); 2973604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas kfree(entry); 2983604a9f445afde2801b8c24b63dd289c33e290a6Bjorn Helgaas } 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&acpi_prt_lock); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3024be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI Interrupt Routing Support 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 306d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann#ifdef CONFIG_X86_IO_APIC 307d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmannextern int noioapicquirk; 308d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmannextern int noioapicreroute; 309d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann 310d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmannstatic int bridge_has_boot_interrupt_variant(struct pci_bus *bus) 311d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann{ 312d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann struct pci_bus *bus_it; 313d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann 314d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann for (bus_it = bus ; bus_it ; bus_it = bus_it->parent) { 315d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann if (!bus_it->self) 316d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return 0; 317d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann if (bus_it->self->irq_reroute_variant) 318d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return bus_it->self->irq_reroute_variant; 319d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann } 320d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return 0; 321d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann} 322d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann 323d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann/* 324d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * Some chipsets (e.g. Intel 6700PXH) generate a legacy INTx when the IRQ 325d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * entry in the chipset's IO-APIC is masked (as, e.g. the RT kernel does 326d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * during interrupt handling). When this INTx generation cannot be disabled, 327d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * we reroute these interrupts to their legacy equivalent to get rid of 328d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * spurious interrupts. 329d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann */ 330d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmannstatic int acpi_reroute_boot_interrupt(struct pci_dev *dev, 331d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann struct acpi_prt_entry *entry) 332d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann{ 333d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann if (noioapicquirk || noioapicreroute) { 334d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return 0; 335d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann } else { 336d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann switch (bridge_has_boot_interrupt_variant(dev->bus)) { 337d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann case 0: 338d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann /* no rerouting necessary */ 339d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return 0; 340d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann case INTEL_IRQ_REROUTE_VARIANT: 341d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann /* 342d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * Remap according to INTx routing table in 6700PXH 343d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * specs, intel order number 302628-002, section 344d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * 2.15.2. Other chipsets (80332, ...) have the same 345d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann * mapping and are handled here as well. 346d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann */ 347d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann dev_info(&dev->dev, "PCI IRQ %d -> rerouted to legacy " 348d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann "IRQ %d\n", entry->index, 349d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann (entry->index % 4) + 16); 350d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann entry->index = (entry->index % 4) + 16; 351d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return 1; 352d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann default: 353d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann dev_warn(&dev->dev, "Cannot reroute IRQ %d to legacy " 354d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann "IRQ: unknown mapping\n", entry->index); 355d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann return -1; 356d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann } 357d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann } 358d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann} 359d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann#endif /* CONFIG_X86_IO_APIC */ 360d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann 3613f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaasstatic struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 363beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas struct acpi_prt_entry *entry; 3645697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas struct pci_dev *bridge; 3655697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas u8 bridge_pin, orig_pin = pin; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 367063563b4b8f87e2be0e127ccf3a8e6eef6309ff4Bjorn Helgaas entry = acpi_pci_irq_find_prt_entry(dev, pin); 3683b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas if (entry) { 369d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann#ifdef CONFIG_X86_IO_APIC 370d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann acpi_reroute_boot_interrupt(dev, entry); 371d7f6169a0d32002657886fee561c641acddb9a75Stefan Assmann#endif /* CONFIG_X86_IO_APIC */ 3723b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", 3731350487eeb616889f589e9b8c06bd5077452b7e3Bjorn Helgaas pci_name(dev), pin_name(pin))); 3743b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas return entry; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attempt to derive an IRQ for this device from a parent bridge's 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 381ee40136313323db1096b17df7b436d22a24ef2beBjorn Helgaas bridge = dev->bus->self; 382ee40136313323db1096b17df7b436d22a24ef2beBjorn Helgaas while (bridge) { 383c686d141c7c668ac186015841a1ccd285a1f3362Bjorn Helgaas pin = pci_swizzle_interrupt_pin(dev, pin); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PC card has the same IRQ as its cardbridge */ 3878015a01486a0f789c9e98e8bf1f12a3ccb535b30Kristen Accardi bridge_pin = bridge->pin; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bridge_pin) { 3894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 3904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown "No interrupt pin configured for device %s\n", 3914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown pci_name(bridge))); 392beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas return NULL; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pin = bridge_pin; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3975697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas entry = acpi_pci_irq_find_prt_entry(bridge, pin); 3983b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas if (entry) { 3993b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas ACPI_DEBUG_PRINT((ACPI_DB_INFO, 4003b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas "Derived GSI for %s INT %c from %s\n", 4013b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas pci_name(dev), pin_name(orig_pin), 4023b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas pci_name(bridge))); 4033b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas return entry; 4043b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas } 405ee40136313323db1096b17df7b436d22a24ef2beBjorn Helgaas 406ee40136313323db1096b17df7b436d22a24ef2beBjorn Helgaas dev = bridge; 407ee40136313323db1096b17df7b436d22a24ef2beBjorn Helgaas bridge = dev->bus->self; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4103b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", 4113b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas pin_name(orig_pin)); 4123b1ea18d3b3542b55861d7f968ded705e3bc2aa6Bjorn Helgaas return NULL; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint acpi_pci_irq_enable(struct pci_dev *dev) 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 417beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas struct acpi_prt_entry *entry; 4183f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas int gsi; 4193f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas u8 pin; 42050eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore int triggering = ACPI_LEVEL_SENSITIVE; 42150eca3eb89d73d9f0aa070b126c7ee6a616016abBob Moore int polarity = ACPI_ACTIVE_LOW; 4224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown char *link = NULL; 423c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas char link_desc[16]; 4244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int rc; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4268015a01486a0f789c9e98e8bf1f12a3ccb535b30Kristen Accardi pin = dev->pin; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pin) { 4284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 4294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown "No interrupt pin configured for device %s\n", 4304be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown pci_name(dev))); 431d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 434beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas entry = acpi_pci_irq_lookup(dev, pin); 4355697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas if (!entry) { 43696c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox /* 43796c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox * IDE legacy mode controller IRQs are magic. Why do compat 43896c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox * extensions always make such a nasty mess. 43996c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox */ 44096c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && 44196c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox (dev->class & 0x05) == 0) 44296c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox return 0; 44396c2a8766bf4fe91abac863749c11637fabcc64fAlan Cox } 4445697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas 44574f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas if (entry) { 44674f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas if (entry->link) 44774f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas gsi = acpi_pci_link_allocate_irq(entry->link, 44874f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas entry->index, 44974f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas &triggering, &polarity, 45074f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas &link); 45174f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas else 45274f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas gsi = entry->index; 45374f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas } else 4545697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas gsi = -1; 4555697b7ca406b4ee0afeef6d9a29b823767716cabBjorn Helgaas 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * No IRQ known to the ACPI subsystem - maybe the BIOS / 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver reported one, then use it. Exit in any case. 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 460c13f889a24e6ced50abb582dab3ee4b7c79b038eBjorn Helgaas if (gsi < 0) { 461414d3448dbcb40807a1265ace64b2576ef919fbeEric W. Biederman u32 dev_gsi; 462cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Interrupt Line values above 0xF are forbidden */ 464414d3448dbcb40807a1265ace64b2576ef919fbeEric W. Biederman if (dev->irq > 0 && (dev->irq <= 0xF) && 465414d3448dbcb40807a1265ace64b2576ef919fbeEric W. Biederman (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { 466414d3448dbcb40807a1265ace64b2576ef919fbeEric W. Biederman printk(" - using ISA IRQ %d\n", dev->irq); 467414d3448dbcb40807a1265ace64b2576ef919fbeEric W. Biederman acpi_register_gsi(&dev->dev, dev_gsi, 468a2f809b08ae4dddc1015c7dcd8659e5729e45b3eYinghai Lu ACPI_LEVEL_SENSITIVE, 4694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ACPI_ACTIVE_LOW); 470d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 4714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown } else { 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("\n"); 473d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown } 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 477a2f809b08ae4dddc1015c7dcd8659e5729e45b3eYinghai Lu rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity); 478349f0d5640c18db09a646f9da51a97f1da908660Kenji Kaneshige if (rc < 0) { 479c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", 480cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1fBjorn Helgaas pin_name(pin)); 481d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return rc; 482349f0d5640c18db09a646f9da51a97f1da908660Kenji Kaneshige } 483349f0d5640c18db09a646f9da51a97f1da908660Kenji Kaneshige dev->irq = rc; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (link) 486c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link); 487c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas else 488c83642d5123225a22cccd75adea6e97c245714cbBjorn Helgaas link_desc[0] = '\0'; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49085b8582d7ca516030efb84d94fa29a73c1d9a125Vincent Palatin dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", 49185b8582d7ca516030efb84d94fa29a73c1d9a125Vincent Palatin pin_name(pin), link_desc, gsi, 49285b8582d7ca516030efb84d94fa29a73c1d9a125Vincent Palatin (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", 49385b8582d7ca516030efb84d94fa29a73c1d9a125Vincent Palatin (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 495d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 49887bec66b9691522414862dd8d41e430b063735efDavid Shaohua Li/* FIXME: implement x86/x86_64 version */ 4994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownvoid __attribute__ ((weak)) acpi_unregister_gsi(u32 i) 5004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown{ 5014be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown} 50287bec66b9691522414862dd8d41e430b063735efDavid Shaohua Li 5034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownvoid acpi_pci_irq_disable(struct pci_dev *dev) 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 505beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas struct acpi_prt_entry *entry; 5063f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas int gsi; 5073f0f3c27be19d390f23af1075d9948d0310e2673Bjorn Helgaas u8 pin; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5098015a01486a0f789c9e98e8bf1f12a3ccb535b30Kristen Accardi pin = dev->pin; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pin) 511d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 513beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas entry = acpi_pci_irq_lookup(dev, pin); 514beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas if (!entry) 515d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51774f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas if (entry->link) 51874f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas gsi = acpi_pci_link_free_irq(entry->link); 51974f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas else 52074f82af1eda39c26c17f8030e4f60c00929ec9dfBjorn Helgaas gsi = entry->index; 521beba8a643d7f774cf27c3c92a51b99cebf787415Bjorn Helgaas 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TBD: It might be worth clearing dev->irq by magic constant 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (e.g. PCI_UNDEFINED_IRQ). 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52785b8582d7ca516030efb84d94fa29a73c1d9a125Vincent Palatin dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_unregister_gsi(gsi); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 530