On Wed, May 20, 2015 at 05:19:13PM -0500, Suravee Suthikulpanit wrote:
Current logic does not parse the _PRT object inside the DSDT of PCI host bridge, and result in failing to route PCI legacy interrupt. This patch adds the logic to do so.
Signed-off-by: Suravee Suthikulpanit Suravee.Suthikulpanit@amd.com
drivers/acpi/pci_irq.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-)
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b1def41..671c92c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -157,13 +157,13 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, } } -static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev, +static int acpi_pci_irq_check_entry(acpi_handle handle,
struct pci_bus *pbus, int device, int pin, struct acpi_pci_routing_table *prt, struct acpi_prt_entry **entry_ptr)
{
- int segment = pci_domain_nr(dev->bus);
- int bus = dev->bus->number;
- int device = PCI_SLOT(dev->devfn);
- int segment = pci_domain_nr(pbus);
- int bus = pbus->number; struct acpi_prt_entry *entry;
if (((prt->address >> 16) & 0xffff) != device || @@ -223,7 +223,7 @@ static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev, return 0; } -static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, +static int acpi_pci_irq_find_prt_entry(struct pci_bus *bus, int devid, int pin, struct acpi_prt_entry **entry_ptr) { acpi_status status; @@ -231,8 +231,8 @@ static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, struct acpi_pci_routing_table *entry; acpi_handle handle = NULL;
- if (dev->bus->bridge)
handle = ACPI_HANDLE(dev->bus->bridge);
- if (bus->bridge)
handle = ACPI_HANDLE(bus->bridge);
if (!handle) return -ENODEV; @@ -246,8 +246,8 @@ static int acpi_pci_irq_find_prt_entry(struct pci_dev *dev, entry = buffer.pointer; while (entry && (entry->length > 0)) {
if (!acpi_pci_irq_check_entry(handle, dev, pin,
entry, entry_ptr))
if (!acpi_pci_irq_check_entry(handle, bus, devid,
entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length);pin, entry, entry_ptr)) break;
@@ -322,7 +322,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) u8 bridge_pin, orig_pin = pin; int ret;
- ret = acpi_pci_irq_find_prt_entry(dev, pin, &entry);
- ret = acpi_pci_irq_find_prt_entry(dev->bus, PCI_SLOT(dev->devfn), pin, &entry); if (!ret && entry) {
#ifdef CONFIG_X86_IO_APIC acpi_reroute_boot_interrupt(dev, entry); @@ -336,7 +336,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) * Attempt to derive an IRQ for this device from a parent bridge's * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). */
- bridge = dev->bus->self;
- bridge = pci_upstream_bridge(dev); while (bridge) { pin = pci_swizzle_interrupt_pin(dev, pin);
@@ -352,7 +352,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) pin = bridge_pin; }
ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
if (!ret && entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI for %s INT %c from %s\n",ret = acpi_pci_irq_find_prt_entry(bridge->bus, PCI_SLOT(bridge->devfn), pin, &entry);
@@ -362,7 +362,27 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) } dev = bridge;
bridge = dev->bus->self;
bridge = pci_upstream_bridge(dev);
- }
- if (!bridge) {
struct device *hb_dev = pci_get_host_bridge_device(dev);
struct pci_host_bridge *h_br = NULL;
if (hb_dev)
h_br = to_pci_host_bridge(hb_dev);
if (h_br)
ret = acpi_pci_irq_find_prt_entry(h_br->bus, 0, pin,
&entry);
pci_put_host_bridge_device(hdev);
Was this compile tested? hdev is undefined here according to my compiler
Graeme
if (!ret && entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Derived GSI for %s INT %c from %s\n",
pci_name(dev), pin_name(orig_pin),
"host bridge"));
return entry;
}}
dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", -- 2.1.0
Linaro-acpi mailing list Linaro-acpi@lists.linaro.org https://lists.linaro.org/mailman/listinfo/linaro-acpi