From 21a53283a012f21764f2aaaac9414849e1153d93 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:05 -0700 Subject: ACPI: PCI: use conventional PCI address format Use the conventional format for PCI addresses (%04x:%02x:%02x.%d). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_bind.c | 12 ++++++------ drivers/acpi/pci_irq.c | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 4b252ea0e95..53f502d29b3 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -99,7 +99,7 @@ acpi_status acpi_get_pci_id(acpi_handle handle, struct acpi_pci_id *id) */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %s has PCI address %02x:%02x:%02x.%02x\n", + "Device %s has PCI address %04x:%02x:%02x.%d\n", acpi_device_bid(device), id->segment, id->bus, id->device, id->function)); @@ -166,7 +166,7 @@ int acpi_pci_bind(struct acpi_device *device) data->id.device = device->pnp.bus_address >> 16; data->id.function = device->pnp.bus_address & 0xFFFF; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %02x:%02x:%02x.%02x\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "...to %04x:%02x:%02x.%d\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); @@ -196,7 +196,7 @@ int acpi_pci_bind(struct acpi_device *device) } if (!data->dev) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %02x:%02x:%02x.%02x not present in PCI namespace\n", + "Device %04x:%02x:%02x.%d not present in PCI namespace\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); result = -ENODEV; @@ -204,7 +204,7 @@ int acpi_pci_bind(struct acpi_device *device) } if (!data->dev->bus) { printk(KERN_ERR PREFIX - "Device %02x:%02x:%02x.%02x has invalid 'bus' field\n", + "Device %04x:%02x:%02x.%d has invalid 'bus' field\n", data->id.segment, data->id.bus, data->id.device, data->id.function); result = -ENODEV; @@ -219,7 +219,7 @@ int acpi_pci_bind(struct acpi_device *device) */ if (data->dev->subordinate) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device %02x:%02x:%02x.%02x is a PCI bridge\n", + "Device %04x:%02x:%02x.%d is a PCI bridge\n", data->id.segment, data->id.bus, data->id.device, data->id.function)); data->bus = data->dev->subordinate; @@ -353,7 +353,7 @@ acpi_pci_bind_root(struct acpi_device *device, acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " - "%02x:%02x\n", pathname, id->segment, id->bus)); + "%04x:%02x\n", pathname, id->segment, id->bus)); status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 11acaee14d6..63a13260999 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -222,7 +222,7 @@ acpi_pci_irq_add_entry(acpi_handle handle, entry->link.index = prt->source_index; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, - " %02X:%02X:%02X[%c] -> %s[%d]\n", + " %04x:%02x:%02x[%c] -> %s[%d]\n", entry->id.segment, entry->id.bus, entry->id.device, ('A' + entry->pin), prt->source, entry->link.index)); @@ -328,8 +328,8 @@ void acpi_pci_irq_del_prt(int segment, int bus) } printk(KERN_DEBUG - "ACPI: Delete PCI Interrupt Routing Table for %x:%x\n", segment, - bus); + "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", + segment, bus); spin_lock(&acpi_prt_lock); list_for_each_safe(node, n, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -403,12 +403,12 @@ acpi_pci_irq_lookup(struct pci_bus *bus, ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Searching for PRT entry for %02x:%02x:%02x[%c]\n", + "Searching for _PRT entry for %04x:%02x:%02x[%c]\n", segment, bus_nr, device, ('A' + pin))); entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); if (!entry) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PRT entry not found\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_PRT entry not found\n")); return -1; } -- cgit v1.2.3 From 3b8249de43ecf05407888c1ca6ca6e4945ff823c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:10 -0700 Subject: ACPI: PCI: remove unnecessary null pointer checks Better to oops and learn about a bug than to silently cover it up. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 63a13260999..6c04060d063 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -178,10 +178,6 @@ acpi_pci_irq_add_entry(acpi_handle handle, { struct acpi_prt_entry *entry = NULL; - - if (!prt) - return -EINVAL; - entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); if (!entry) return -ENOMEM; @@ -432,9 +428,6 @@ acpi_pci_irq_derive(struct pci_dev *dev, u8 bridge_pin = 0, orig_pin = pin; - if (!dev) - return -EINVAL; - /* * 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). @@ -491,9 +484,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev) int rc; - if (!dev) - return -EINVAL; - pin = dev->pin; if (!pin) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -503,11 +493,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev) } pin--; - if (!dev->bus) { - dev_err(&dev->dev, "invalid (NULL) 'bus' field\n"); - return -ENODEV; - } - /* * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. @@ -586,9 +571,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) int polarity = ACPI_ACTIVE_LOW; - if (!dev || !dev->bus) - return; - pin = dev->pin; if (!pin) return; -- cgit v1.2.3 From 2320ac6cb078eec77bf93742895dc35e64fae124 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:15 -0700 Subject: ACPI: PCI: simplify buffer management for evaluating _PRT Previously, acpi_pci_irq_add_prt() did all its own buffer management. But now that we have ACPI_ALLOCATE_BUFFER, we no longer need to do that management. And we don't have to call acpi_get_irq_routing_table() twice (once to learn the size of the buffer needed, and again to actually get the table). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 52 ++++++++++++-------------------------------------- 1 file changed, 12 insertions(+), 40 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 6c04060d063..6a9f3ddb322 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -243,55 +243,29 @@ acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry) int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) { - acpi_status status = AE_OK; - char *pathname = NULL; - struct acpi_buffer buffer = { 0, NULL }; - struct acpi_pci_routing_table *prt = NULL; - struct acpi_pci_routing_table *entry = NULL; + acpi_status status; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_pci_routing_table *entry; static int first_time = 1; - - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); - if (!pathname) - return -ENOMEM; - if (first_time) { acpi_prt.count = 0; INIT_LIST_HEAD(&acpi_prt.entries); first_time = 0; } - /* - * NOTE: We're given a 'handle' to the _PRT object's parent device - * (either a PCI root bridge or PCI-PCI bridge). - */ - - buffer.length = ACPI_PATHNAME_MAX; - buffer.pointer = pathname; - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) + return -ENODEV; printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n", - pathname); + (char *) buffer.pointer); - /* - * Evaluate this _PRT and add its entries to our global list (acpi_prt). - */ + kfree(buffer.pointer); - buffer.length = 0; + buffer.length = ACPI_ALLOCATE_BUFFER; buffer.pointer = NULL; - kfree(pathname); - status = acpi_get_irq_routing_table(handle, &buffer); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRT [%s]", - acpi_format_exception(status))); - return -ENODEV; - } - - prt = kzalloc(buffer.length, GFP_KERNEL); - if (!prt) { - return -ENOMEM; - } - buffer.pointer = prt; status = acpi_get_irq_routing_table(handle, &buffer); if (ACPI_FAILURE(status)) { @@ -301,16 +275,14 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) return -ENODEV; } - entry = prt; - + entry = buffer.pointer; while (entry && (entry->length > 0)) { acpi_pci_irq_add_entry(handle, segment, bus, entry); entry = (struct acpi_pci_routing_table *) ((unsigned long)entry + entry->length); } - kfree(prt); - + kfree(buffer.pointer); return 0; } -- cgit v1.2.3 From b52b3f4af83571e86f910b07a61b177e2b7d8409 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:20 -0700 Subject: ACPI: PCI: ignore _PRT function information _PRT entries don't contain any useful PCI function information (the function part of the PCI address is supposed to be 0xffff), and we don't ever look at it, so this patch just removes the reference to it. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 6a9f3ddb322..c6a0364715c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -185,7 +185,6 @@ acpi_pci_irq_add_entry(acpi_handle handle, entry->id.segment = segment; entry->id.bus = bus; entry->id.device = (prt->address >> 16) & 0xFFFF; - entry->id.function = prt->address & 0xFFFF; entry->pin = prt->pin; do_prt_fixups(entry, prt); -- cgit v1.2.3 From c13f889a24e6ced50abb582dab3ee4b7c79b038e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:26 -0700 Subject: ACPI: PCI: fix GSI/IRQ naming confusion The interrupt numbers from _PRT entries are GSIs, not Linux IRQs. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index c6a0364715c..9302f4bb89e 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -333,7 +333,7 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, *polarity = ACPI_ACTIVE_LOW; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found GSI %d\n", irq)); return irq; } @@ -432,7 +432,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, return -1; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive GSI %d for device %s from %s\n", irq, pci_name(dev), pci_name(bridge))); return irq; @@ -446,7 +446,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, int acpi_pci_irq_enable(struct pci_dev *dev) { - int irq = 0; + int gsi = 0; u8 pin = 0; int triggering = ACPI_LEVEL_SENSITIVE; int polarity = ACPI_ACTIVE_LOW; @@ -468,7 +468,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, + gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &triggering, &polarity, &link, acpi_pci_allocate_irq); @@ -476,12 +476,12 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ - if (irq < 0) - irq = acpi_pci_irq_derive(dev, pin, &triggering, + if (gsi < 0) + gsi = acpi_pci_irq_derive(dev, pin, &triggering, &polarity, &link, acpi_pci_allocate_irq); - if (irq < 0) { + if (gsi < 0) { /* * IDE legacy mode controller IRQs are magic. Why do compat * extensions always make such a nasty mess. @@ -494,7 +494,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. */ - if (irq < 0) { + if (gsi < 0) { dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq > 0 && (dev->irq <= 0xF)) { @@ -508,7 +508,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) } } - rc = acpi_register_gsi(irq, triggering, polarity); + rc = acpi_register_gsi(gsi, triggering, polarity); if (rc < 0) { dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", 'A' + pin); @@ -522,7 +522,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) link_desc[0] = '\0'; dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", - 'A' + pin, link_desc, irq, + 'A' + pin, link_desc, gsi, (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); -- cgit v1.2.3 From f748bafa3ca1fb056e63afdeecacc1c68d8104df Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:31 -0700 Subject: ACPI: PCI: move struct acpi_prt_entry declaration out of public header file The struct acpi_prt_entry is used only in pci_irq.c, so there's no need for the declaration to be public. This patch moves it into pci_irq.c. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 9302f4bb89e..ea003bab7ec 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -41,6 +41,22 @@ #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_irq"); +struct acpi_prt_entry { + struct list_head node; + struct acpi_pci_id id; + u8 pin; + struct { + acpi_handle handle; + u32 index; + } link; + u32 irq; +}; + +struct acpi_prt_list { + int count; + struct list_head entries; +}; + static struct acpi_prt_list acpi_prt; static DEFINE_SPINLOCK(acpi_prt_lock); -- cgit v1.2.3 From cf68b80b0e0cbc6a0d7bbb36b07ce94779ef5f1f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:36 -0700 Subject: ACPI: PCI: add a helper to convert _PRT INTx pin number to name This adds a helper function to convert INTx pin numbers from the _PRT (0, 1, 2, 3) to the pin name ('A', 'B', 'C', 'D'). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index ea003bab7ec..5ce1fcf7745 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -60,6 +60,11 @@ struct acpi_prt_list { static struct acpi_prt_list acpi_prt; static DEFINE_SPINLOCK(acpi_prt_lock); +static inline char pin_name(int pin) +{ + return 'A' + pin; +} + /* -------------------------------------------------------------------------- PCI IRQ Routing Table (PRT) Support -------------------------------------------------------------------------- */ @@ -174,14 +179,14 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) entry->id.segment == quirk->segment && entry->id.bus == quirk->bus && entry->id.device == quirk->device && - entry->pin + 'A' == quirk->pin && + pin_name(entry->pin) == quirk->pin && !strcmp(prt->source, quirk->source) && strlen(prt->source) >= strlen(quirk->actual_source)) { printk(KERN_WARNING PREFIX "firmware reports " "%04x:%02x:%02x PCI INT %c connected to %s; " "changing to %s\n", entry->id.segment, entry->id.bus, - entry->id.device, 'A' + entry->pin, + entry->id.device, pin_name(entry->pin), prt->source, quirk->actual_source); strcpy(prt->source, quirk->actual_source); } @@ -235,8 +240,8 @@ acpi_pci_irq_add_entry(acpi_handle handle, ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, " %04x:%02x:%02x[%c] -> %s[%d]\n", entry->id.segment, entry->id.bus, - entry->id.device, ('A' + entry->pin), prt->source, - entry->link.index)); + entry->id.device, pin_name(entry->pin), + prt->source, entry->link.index)); spin_lock(&acpi_prt_lock); list_add_tail(&entry->node, &acpi_prt.entries); @@ -387,7 +392,7 @@ acpi_pci_irq_lookup(struct pci_bus *bus, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Searching for _PRT entry for %04x:%02x:%02x[%c]\n", - segment, bus_nr, device, ('A' + pin))); + segment, bus_nr, device, pin_name(pin))); entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); if (!entry) { @@ -444,7 +449,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, if (irq < 0) { dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", - 'A' + orig_pin); + pin_name(orig_pin)); return -1; } @@ -511,7 +516,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * driver reported one, then use it. Exit in any case. */ if (gsi < 0) { - dev_warn(&dev->dev, "PCI INT %c: no GSI", 'A' + pin); + dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); /* Interrupt Line values above 0xF are forbidden */ if (dev->irq > 0 && (dev->irq <= 0xF)) { printk(" - using IRQ %d\n", dev->irq); @@ -527,7 +532,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) rc = acpi_register_gsi(gsi, triggering, polarity); if (rc < 0) { dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", - 'A' + pin); + pin_name(pin)); return rc; } dev->irq = rc; @@ -538,7 +543,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) link_desc[0] = '\0'; dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", - 'A' + pin, link_desc, gsi, + pin_name(pin), link_desc, gsi, (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); @@ -585,6 +590,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) * (e.g. PCI_UNDEFINED_IRQ). */ - dev_info(&dev->dev, "PCI INT %c disabled\n", 'A' + pin); + dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); acpi_unregister_gsi(gsi); } -- cgit v1.2.3 From e64e9db53ab78d20dff4cc1aec8a6b0e4e70ce8c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:41 -0700 Subject: ACPI: PCI: always use the PCI INTx pin values, not the _PRT ones This patch changes pci_irq.c to always use PCI INTx pin encodings instead of a mix of PCI and _PRT encodings. The PCI INTx pin numbers from the PCI_INTERRUPT_PIN config register are 0=device doesn't use interrupts, 1=INTA, ..., 4=INTD. But the _PRT table uses 0=INTA, ..., 3=INTD. This patch converts the _PRT encoding to the PCI encoding immediately when we add a _PRT entry to the global list. All the rest of the code can then use the PCI encoding consistently. The point of this is to make the interrupt swizzling look the same as on other architectures, so someday we can unify them. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 5ce1fcf7745..2c52cf0004b 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -62,7 +62,7 @@ static DEFINE_SPINLOCK(acpi_prt_lock); static inline char pin_name(int pin) { - return 'A' + pin; + return 'A' + pin - 1; } /* -------------------------------------------------------------------------- @@ -203,10 +203,15 @@ acpi_pci_irq_add_entry(acpi_handle handle, if (!entry) return -ENOMEM; + /* + * Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses + * 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert + * it here. + */ entry->id.segment = segment; entry->id.bus = bus; entry->id.device = (prt->address >> 16) & 0xFFFF; - entry->pin = prt->pin; + entry->pin = prt->pin + 1; do_prt_fixups(entry, prt); @@ -425,7 +430,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge). */ while (irq < 0 && bridge->bus->self) { - pin = (pin + PCI_SLOT(bridge->devfn)) % 4; + pin = (((pin - 1) + PCI_SLOT(bridge->devfn)) % 4) + 1; bridge = bridge->bus->self; if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { @@ -437,8 +442,6 @@ acpi_pci_irq_derive(struct pci_dev *dev, pci_name(bridge))); return -1; } - /* Pin is from 0 to 3 */ - bridge_pin--; pin = bridge_pin; } @@ -483,7 +486,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev) pci_name(dev))); return 0; } - pin--; /* * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT @@ -566,7 +568,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev) pin = dev->pin; if (!pin) return; - pin--; /* * First we check the PCI IRQ routing table (PRT) for an IRQ. -- cgit v1.2.3 From c458033c9b72a81b890d97ec6339694bab252383 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:46 -0700 Subject: ACPI: PCI: use 1-based encoding for _PRT quirks Use the PCI INTx pin encoding (1=INTA, 2=INTB, etc) for _PRT quirks. Then we can simply compare "entry->pin == quirk->pin". Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 2c52cf0004b..c4a5c49809d 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -145,19 +145,21 @@ struct prt_quirk { char *actual_source; }; +#define PCI_INTX_PIN(c) (c - 'A' + 1) + /* * These systems have incorrect _PRT entries. The BIOS claims the PCI * interrupt at the listed segment/bus/device/pin is connected to the first * link device, but it is actually connected to the second. */ static struct prt_quirk prt_quirks[] = { - { medion_md9580, 0, 0, 9, 'A', + { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'), "\\_SB_.PCI0.ISA_.LNKA", "\\_SB_.PCI0.ISA_.LNKB"}, - { dell_optiplex, 0, 0, 0xd, 'A', + { dell_optiplex, 0, 0, 0xd, PCI_INTX_PIN('A'), "\\_SB_.LNKB", "\\_SB_.LNKA"}, - { hp_t5710, 0, 0, 1, 'A', + { hp_t5710, 0, 0, 1, PCI_INTX_PIN('A'), "\\_SB_.PCI0.LNK1", "\\_SB_.PCI0.LNK3"}, }; @@ -179,7 +181,7 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) entry->id.segment == quirk->segment && entry->id.bus == quirk->bus && entry->id.device == quirk->device && - pin_name(entry->pin) == quirk->pin && + entry->pin == quirk->pin && !strcmp(prt->source, quirk->source) && strlen(prt->source) >= strlen(quirk->actual_source)) { printk(KERN_WARNING PREFIX "firmware reports " -- cgit v1.2.3 From 063563b4b8f87e2be0e127ccf3a8e6eef6309ff4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:51 -0700 Subject: ACPI: PCI: lookup _PRT entry by PCI dev and pin, not segment/bus/dev/pin There's no reason to pass around segment, bus, and device independently when we can just pass the pci_dev pointer, which carries all those already. The pci_dev contains an interrupt pin, too, but we still have to pass both the pci_dev and the pin because when we use a bridge to derive an IRQ, we need the pin from the downstream device, not the bridge. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index c4a5c49809d..aabf8a965af 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -69,11 +69,13 @@ static inline char pin_name(int pin) PCI IRQ Routing Table (PRT) Support -------------------------------------------------------------------------- */ -static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, - int bus, - int device, int pin) +static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, + int pin) { struct acpi_prt_entry *entry = NULL; + int segment = pci_domain_nr(dev->bus); + int bus = dev->bus->number; + int device = PCI_SLOT(dev->devfn); if (!acpi_prt.count) return NULL; @@ -385,23 +387,18 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry, * failure: return -1 */ static int -acpi_pci_irq_lookup(struct pci_bus *bus, - int device, - int pin, +acpi_pci_irq_lookup(struct pci_dev *dev, int pin, int *triggering, int *polarity, char **link, irq_lookup_func func) { struct acpi_prt_entry *entry = NULL; - int segment = pci_domain_nr(bus); - int bus_nr = bus->number; int ret; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Searching for _PRT entry for %04x:%02x:%02x[%c]\n", - segment, bus_nr, device, pin_name(pin))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Searching for _PRT entry for %s[%c]\n", + pci_name(dev), pin_name(pin))); - entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); + entry = acpi_pci_irq_find_prt_entry(dev, pin); if (!entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_PRT entry not found\n")); return -1; @@ -447,7 +444,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, pin = bridge_pin; } - irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), + irq = acpi_pci_irq_lookup(bridge, pin, triggering, polarity, link, func); } @@ -493,7 +490,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, + gsi = acpi_pci_irq_lookup(dev, pin, &triggering, &polarity, &link, acpi_pci_allocate_irq); @@ -574,7 +571,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) /* * First we check the PCI IRQ routing table (PRT) for an IRQ. */ - gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, + gsi = acpi_pci_irq_lookup(dev, pin, &triggering, &polarity, NULL, acpi_pci_free_irq); /* -- cgit v1.2.3 From 1350487eeb616889f589e9b8c06bd5077452b7e3 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:30:56 -0700 Subject: ACPI: PCI: tweak _PRT lookup debug Print one message (either "found" or "not found") for every _PRT search. And add pin information to the INTx swizzling debug. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index aabf8a965af..7978c97afb0 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -395,15 +395,16 @@ acpi_pci_irq_lookup(struct pci_dev *dev, int pin, int ret; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Searching for _PRT entry for %s[%c]\n", - pci_name(dev), pin_name(pin))); - entry = acpi_pci_irq_find_prt_entry(dev, pin); if (!entry) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_PRT entry not found\n")); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n", + pci_name(dev), pin_name(pin))); return -1; } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", + pci_name(dev), pin_name(pin))); + ret = func(entry, triggering, polarity, link); return ret; } @@ -455,8 +456,8 @@ acpi_pci_irq_derive(struct pci_dev *dev, return -1; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive GSI %d for device %s from %s\n", - irq, pci_name(dev), pci_name(bridge))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI %d for %s INT %c from %s\n", + irq, pci_name(dev), pin_name(orig_pin), pci_name(bridge))); return irq; } -- cgit v1.2.3 From beba8a643d7f774cf27c3c92a51b99cebf787415 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:01 -0700 Subject: ACPI: PCI: remove callback from acpi_pci_irq_lookup & acpi_pci_irq_derive We currently pass a callback function (either acpi_pci_allocate_irq() or acpi_pci_free_irq()) to acpi_pci_irq_lookup() and acpi_pci_irq_derive(). I think it's simpler to remove the callback and just have the enable/ disable functions make the calls directly. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 93 +++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 57 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 7978c97afb0..28338227dd5 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -339,8 +339,6 @@ void acpi_pci_irq_del_prt(int segment, int bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ -typedef int (*irq_lookup_func) (struct acpi_prt_entry *, int *, int *, char **); - static int acpi_pci_allocate_irq(struct acpi_prt_entry *entry, int *triggering, int *polarity, char **link) @@ -368,8 +366,7 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, } static int -acpi_pci_free_irq(struct acpi_prt_entry *entry, - int *triggering, int *polarity, char **link) +acpi_pci_free_irq(struct acpi_prt_entry *entry) { int irq; @@ -381,47 +378,29 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry, return irq; } -/* - * acpi_pci_irq_lookup - * success: return IRQ >= 0 - * failure: return -1 - */ -static int -acpi_pci_irq_lookup(struct pci_dev *dev, int pin, - int *triggering, - int *polarity, char **link, irq_lookup_func func) +static struct acpi_prt_entry * +acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { - struct acpi_prt_entry *entry = NULL; - int ret; - + struct acpi_prt_entry *entry; entry = acpi_pci_irq_find_prt_entry(dev, pin); if (!entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); - return -1; + return NULL; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); - ret = func(entry, triggering, polarity, link); - return ret; + return entry; } -/* - * acpi_pci_irq_derive - * success: return IRQ >= 0 - * failure: return < 0 - */ -static int -acpi_pci_irq_derive(struct pci_dev *dev, - int pin, - int *triggering, - int *polarity, char **link, irq_lookup_func func) +static struct acpi_prt_entry * +acpi_pci_irq_derive(struct pci_dev *dev, int pin) { + struct acpi_prt_entry *entry = NULL; struct pci_dev *bridge = dev; - int irq = -1; u8 bridge_pin = 0, orig_pin = pin; @@ -429,7 +408,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, * 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). */ - while (irq < 0 && bridge->bus->self) { + while (!entry && bridge->bus->self) { pin = (((pin - 1) + PCI_SLOT(bridge->devfn)) % 4) + 1; bridge = bridge->bus->self; @@ -440,26 +419,24 @@ acpi_pci_irq_derive(struct pci_dev *dev, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No interrupt pin configured for device %s\n", pci_name(bridge))); - return -1; + return NULL; } pin = bridge_pin; } - irq = acpi_pci_irq_lookup(bridge, - pin, triggering, polarity, - link, func); + entry = acpi_pci_irq_lookup(bridge, pin); } - if (irq < 0) { + if (!entry) { dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", pin_name(orig_pin)); - return -1; + return NULL; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI %d for %s INT %c from %s\n", - irq, pci_name(dev), pin_name(orig_pin), pci_name(bridge))); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI for %s INT %c from %s\n", + pci_name(dev), pin_name(orig_pin), pci_name(bridge))); - return irq; + return entry; } /* @@ -470,6 +447,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, int acpi_pci_irq_enable(struct pci_dev *dev) { + struct acpi_prt_entry *entry; int gsi = 0; u8 pin = 0; int triggering = ACPI_LEVEL_SENSITIVE; @@ -491,18 +469,20 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT * values override any BIOS-assigned IRQs set during boot. */ - gsi = acpi_pci_irq_lookup(dev, pin, - &triggering, &polarity, &link, - acpi_pci_allocate_irq); + entry = acpi_pci_irq_lookup(dev, pin); /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ - if (gsi < 0) - gsi = acpi_pci_irq_derive(dev, pin, &triggering, - &polarity, &link, - acpi_pci_allocate_irq); + if (!entry) + entry = acpi_pci_irq_derive(dev, pin); + + if (entry) + gsi = acpi_pci_allocate_irq(entry, &triggering, &polarity, + &link); + else + gsi = -1; if (gsi < 0) { /* @@ -559,10 +539,9 @@ void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) void acpi_pci_irq_disable(struct pci_dev *dev) { + struct acpi_prt_entry *entry; int gsi = 0; u8 pin = 0; - int triggering = ACPI_LEVEL_SENSITIVE; - int polarity = ACPI_ACTIVE_LOW; pin = dev->pin; @@ -572,20 +551,20 @@ void acpi_pci_irq_disable(struct pci_dev *dev) /* * First we check the PCI IRQ routing table (PRT) for an IRQ. */ - gsi = acpi_pci_irq_lookup(dev, pin, - &triggering, &polarity, NULL, - acpi_pci_free_irq); + entry = acpi_pci_irq_lookup(dev, pin); + /* * If no PRT entry was found, we'll try to derive an IRQ from the * device's parent bridge. */ - if (gsi < 0) - gsi = acpi_pci_irq_derive(dev, pin, - &triggering, &polarity, NULL, - acpi_pci_free_irq); - if (gsi < 0) + if (!entry) + entry = acpi_pci_irq_derive(dev, pin); + + if (!entry) return; + gsi = acpi_pci_free_irq(entry); + /* * TBD: It might be worth clearing dev->irq by magic constant * (e.g. PCI_UNDEFINED_IRQ). -- cgit v1.2.3 From 3b1ea18d3b3542b55861d7f968ded705e3bc2aa6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:06 -0700 Subject: ACPI: PCI: use positive logic to simplify code This doesn't change anything functionally; it just changes tests so we test for success instead of failure. This makes the code read more easily and allows us to remove the "!entry" in the while loop condition. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 28338227dd5..e42481f6449 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -384,16 +384,15 @@ acpi_pci_irq_lookup(struct pci_dev *dev, int pin) struct acpi_prt_entry *entry; entry = acpi_pci_irq_find_prt_entry(dev, pin); - if (!entry) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n", + if (entry) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); - return NULL; + return entry; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n", pci_name(dev), pin_name(pin))); - - return entry; + return NULL; } static struct acpi_prt_entry * @@ -408,7 +407,7 @@ acpi_pci_irq_derive(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). */ - while (!entry && bridge->bus->self) { + while (bridge->bus->self) { pin = (((pin - 1) + PCI_SLOT(bridge->devfn)) % 4) + 1; bridge = bridge->bus->self; @@ -425,18 +424,18 @@ acpi_pci_irq_derive(struct pci_dev *dev, int pin) } entry = acpi_pci_irq_lookup(bridge, pin); + if (entry) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Derived GSI for %s INT %c from %s\n", + pci_name(dev), pin_name(orig_pin), + pci_name(bridge))); + return entry; + } } - if (!entry) { - dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", - pin_name(orig_pin)); - return NULL; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI for %s INT %c from %s\n", - pci_name(dev), pin_name(orig_pin), pci_name(bridge))); - - return entry; + dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", + pin_name(orig_pin)); + return NULL; } /* -- cgit v1.2.3 From ee40136313323db1096b17df7b436d22a24ef2be Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:11 -0700 Subject: ACPI: PCI: follow typical PCI INTx swizzling pattern No functional change; this just uses the typical pattern of PCI INTx swizzling done on other architectures. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index e42481f6449..b35e64d7140 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -399,7 +399,7 @@ static struct acpi_prt_entry * acpi_pci_irq_derive(struct pci_dev *dev, int pin) { struct acpi_prt_entry *entry = NULL; - struct pci_dev *bridge = dev; + struct pci_dev *bridge; u8 bridge_pin = 0, orig_pin = pin; @@ -407,9 +407,9 @@ acpi_pci_irq_derive(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). */ - while (bridge->bus->self) { - pin = (((pin - 1) + PCI_SLOT(bridge->devfn)) % 4) + 1; - bridge = bridge->bus->self; + bridge = dev->bus->self; + while (bridge) { + pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { /* PC card has the same IRQ as its cardbridge */ @@ -431,6 +431,9 @@ acpi_pci_irq_derive(struct pci_dev *dev, int pin) pci_name(bridge))); return entry; } + + dev = bridge; + bridge = dev->bus->self; } dev_warn(&dev->dev, "can't derive routing for PCI INT %c\n", -- cgit v1.2.3 From 5697b7ca406b4ee0afeef6d9a29b823767716cab Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:16 -0700 Subject: ACPI: PCI: combine lookup and derive This folds acpi_pci_irq_derive() into acpi_pci_irq_lookup() so it can be easily used by both acpi_pci_irq_enable() and acpi_pci_irq_disable(). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 55 ++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 44 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b35e64d7140..b03bb84266b 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -382,6 +382,8 @@ static struct acpi_prt_entry * acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { struct acpi_prt_entry *entry; + struct pci_dev *bridge; + u8 bridge_pin, orig_pin = pin; entry = acpi_pci_irq_find_prt_entry(dev, pin); if (entry) { @@ -390,19 +392,6 @@ acpi_pci_irq_lookup(struct pci_dev *dev, int pin) return entry; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No %s[%c] _PRT entry\n", - pci_name(dev), pin_name(pin))); - return NULL; -} - -static struct acpi_prt_entry * -acpi_pci_irq_derive(struct pci_dev *dev, int pin) -{ - struct acpi_prt_entry *entry = NULL; - struct pci_dev *bridge; - u8 bridge_pin = 0, orig_pin = 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). @@ -423,7 +412,7 @@ acpi_pci_irq_derive(struct pci_dev *dev, int pin) pin = bridge_pin; } - entry = acpi_pci_irq_lookup(bridge, pin); + entry = acpi_pci_irq_find_prt_entry(bridge, pin); if (entry) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derived GSI for %s INT %c from %s\n", @@ -467,26 +456,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) return 0; } - /* - * First we check the PCI IRQ routing table (PRT) for an IRQ. PRT - * values override any BIOS-assigned IRQs set during boot. - */ entry = acpi_pci_irq_lookup(dev, pin); - - /* - * If no PRT entry was found, we'll try to derive an IRQ from the - * device's parent bridge. - */ - if (!entry) - entry = acpi_pci_irq_derive(dev, pin); - - if (entry) - gsi = acpi_pci_allocate_irq(entry, &triggering, &polarity, - &link); - else - gsi = -1; - - if (gsi < 0) { + if (!entry) { /* * IDE legacy mode controller IRQs are magic. Why do compat * extensions always make such a nasty mess. @@ -495,6 +466,13 @@ int acpi_pci_irq_enable(struct pci_dev *dev) (dev->class & 0x05) == 0) return 0; } + + if (entry) + gsi = acpi_pci_allocate_irq(entry, &triggering, &polarity, + &link); + else + gsi = -1; + /* * No IRQ known to the ACPI subsystem - maybe the BIOS / * driver reported one, then use it. Exit in any case. @@ -550,18 +528,7 @@ void acpi_pci_irq_disable(struct pci_dev *dev) if (!pin) return; - /* - * First we check the PCI IRQ routing table (PRT) for an IRQ. - */ entry = acpi_pci_irq_lookup(dev, pin); - - /* - * If no PRT entry was found, we'll try to derive an IRQ from the - * device's parent bridge. - */ - if (!entry) - entry = acpi_pci_irq_derive(dev, pin); - if (!entry) return; -- cgit v1.2.3 From 3604a9f445afde2801b8c24b63dd289c33e290a6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:21 -0700 Subject: ACPI: PCI: simplify list of _PRT entries We don't need a struct containing a count and a list_head; a simple list_head is sufficient. The list iterators handle empty lists fine. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 60 ++++++++++---------------------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b03bb84266b..42b195ed792 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -42,7 +42,7 @@ ACPI_MODULE_NAME("pci_irq"); struct acpi_prt_entry { - struct list_head node; + struct list_head list; struct acpi_pci_id id; u8 pin; struct { @@ -52,12 +52,7 @@ struct acpi_prt_entry { u32 irq; }; -struct acpi_prt_list { - int count; - struct list_head entries; -}; - -static struct acpi_prt_list acpi_prt; +static LIST_HEAD(acpi_prt_list); static DEFINE_SPINLOCK(acpi_prt_lock); static inline char pin_name(int pin) @@ -72,21 +67,13 @@ static inline char pin_name(int pin) static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, int pin) { - struct acpi_prt_entry *entry = NULL; + struct acpi_prt_entry *entry; int segment = pci_domain_nr(dev->bus); int bus = dev->bus->number; int device = PCI_SLOT(dev->devfn); - if (!acpi_prt.count) - return NULL; - - /* - * Parse through all PRT entries looking for a match on the specified - * PCI device's segment, bus, device, and pin (don't care about func). - * - */ spin_lock(&acpi_prt_lock); - list_for_each_entry(entry, &acpi_prt.entries, node) { + list_for_each_entry(entry, &acpi_prt_list, list) { if ((segment == entry->id.segment) && (bus == entry->id.bus) && (device == entry->id.device) @@ -95,7 +82,6 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, return entry; } } - spin_unlock(&acpi_prt_lock); return NULL; } @@ -201,7 +187,7 @@ static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, struct acpi_pci_routing_table *prt) { - struct acpi_prt_entry *entry = NULL; + struct acpi_prt_entry *entry; entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL); if (!entry) @@ -253,35 +239,17 @@ acpi_pci_irq_add_entry(acpi_handle handle, prt->source, entry->link.index)); spin_lock(&acpi_prt_lock); - list_add_tail(&entry->node, &acpi_prt.entries); - acpi_prt.count++; + list_add_tail(&entry->list, &acpi_prt_list); spin_unlock(&acpi_prt_lock); return 0; } -static void -acpi_pci_irq_del_entry(int segment, int bus, struct acpi_prt_entry *entry) -{ - if (segment == entry->id.segment && bus == entry->id.bus) { - acpi_prt.count--; - list_del(&entry->node); - kfree(entry); - } -} - int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_pci_routing_table *entry; - static int first_time = 1; - - if (first_time) { - acpi_prt.count = 0; - INIT_LIST_HEAD(&acpi_prt.entries); - first_time = 0; - } /* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */ status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -317,21 +285,17 @@ int acpi_pci_irq_add_prt(acpi_handle handle, int segment, int bus) void acpi_pci_irq_del_prt(int segment, int bus) { - struct list_head *node = NULL, *n = NULL; - struct acpi_prt_entry *entry = NULL; - - if (!acpi_prt.count) { - return; - } + struct acpi_prt_entry *entry, *tmp; printk(KERN_DEBUG "ACPI: Delete PCI Interrupt Routing Table for %04x:%02x\n", segment, bus); spin_lock(&acpi_prt_lock); - list_for_each_safe(node, n, &acpi_prt.entries) { - entry = list_entry(node, struct acpi_prt_entry, node); - - acpi_pci_irq_del_entry(segment, bus, entry); + list_for_each_entry_safe(entry, tmp, &acpi_prt_list, list) { + if (segment == entry->id.segment && bus == entry->id.bus) { + list_del(&entry->list); + kfree(entry); + } } spin_unlock(&acpi_prt_lock); } -- cgit v1.2.3 From 4eaf6db3ea0edf7e011a613b5a15360444e58fec Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:27 -0700 Subject: ACPI: PCI: simplify struct acpi_prt_entry Remove unused "irq" field, remove unnecessary struct, rename "handle" to "link". Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 42b195ed792..643c4e86429 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -45,11 +45,8 @@ struct acpi_prt_entry { struct list_head list; struct acpi_pci_id id; u8 pin; - struct { - acpi_handle handle; - u32 index; - } link; - u32 irq; + acpi_handle link; + u32 index; /* GSI, or link _CRS index */ }; static LIST_HEAD(acpi_prt_list); @@ -205,6 +202,8 @@ acpi_pci_irq_add_entry(acpi_handle handle, do_prt_fixups(entry, prt); + entry->index = prt->source_index; + /* * Type 1: Dynamic * --------------- @@ -218,10 +217,9 @@ acpi_pci_irq_add_entry(acpi_handle handle, * (e.g. exists somewhere 'below' this _PRT entry in the ACPI * namespace). */ - if (prt->source[0]) { - acpi_get_handle(handle, prt->source, &entry->link.handle); - entry->link.index = prt->source_index; - } + if (prt->source[0]) + acpi_get_handle(handle, prt->source, &entry->link); + /* * Type 2: Static * -------------- @@ -229,14 +227,12 @@ acpi_pci_irq_add_entry(acpi_handle handle, * the IRQ value, which is hardwired to specific interrupt inputs on * the interrupt controller. */ - else - entry->link.index = prt->source_index; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, " %04x:%02x:%02x[%c] -> %s[%d]\n", entry->id.segment, entry->id.bus, entry->id.device, pin_name(entry->pin), - prt->source, entry->link.index)); + prt->source, entry->index)); spin_lock(&acpi_prt_lock); list_add_tail(&entry->list, &acpi_prt_list); @@ -310,17 +306,16 @@ acpi_pci_allocate_irq(struct acpi_prt_entry *entry, int irq; - if (entry->link.handle) { - irq = acpi_pci_link_allocate_irq(entry->link.handle, - entry->link.index, triggering, - polarity, link); + if (entry->link) { + irq = acpi_pci_link_allocate_irq(entry->link, entry->index, + triggering, polarity, link); if (irq < 0) { printk(KERN_WARNING PREFIX "Invalid IRQ link routing entry\n"); return -1; } } else { - irq = entry->link.index; + irq = entry->index; *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_LOW; } @@ -334,10 +329,10 @@ acpi_pci_free_irq(struct acpi_prt_entry *entry) { int irq; - if (entry->link.handle) { - irq = acpi_pci_link_free_irq(entry->link.handle); + if (entry->link) { + irq = acpi_pci_link_free_irq(entry->link); } else { - irq = entry->link.index; + irq = entry->index; } return irq; } -- cgit v1.2.3 From 74f82af1eda39c26c17f8030e4f60c00929ec9df Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:32 -0700 Subject: ACPI: PCI: expand acpi_pci_allocate_irq() and acpi_pci_free_irq() inline acpi_pci_allocate_irq() and acpi_pci_free_irq() are trivial and only used once, so just open-code them. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 56 ++++++++++++-------------------------------------- 1 file changed, 13 insertions(+), 43 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 643c4e86429..03d528e02c2 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -299,44 +299,6 @@ void acpi_pci_irq_del_prt(int segment, int bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ -static int -acpi_pci_allocate_irq(struct acpi_prt_entry *entry, - int *triggering, int *polarity, char **link) -{ - int irq; - - - if (entry->link) { - irq = acpi_pci_link_allocate_irq(entry->link, entry->index, - triggering, polarity, link); - if (irq < 0) { - printk(KERN_WARNING PREFIX - "Invalid IRQ link routing entry\n"); - return -1; - } - } else { - irq = entry->index; - *triggering = ACPI_LEVEL_SENSITIVE; - *polarity = ACPI_ACTIVE_LOW; - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found GSI %d\n", irq)); - return irq; -} - -static int -acpi_pci_free_irq(struct acpi_prt_entry *entry) -{ - int irq; - - if (entry->link) { - irq = acpi_pci_link_free_irq(entry->link); - } else { - irq = entry->index; - } - return irq; -} - static struct acpi_prt_entry * acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { @@ -426,10 +388,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev) return 0; } - if (entry) - gsi = acpi_pci_allocate_irq(entry, &triggering, &polarity, - &link); - else + if (entry) { + if (entry->link) + gsi = acpi_pci_link_allocate_irq(entry->link, + entry->index, + &triggering, &polarity, + &link); + else + gsi = entry->index; + } else gsi = -1; /* @@ -491,7 +458,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev) if (!entry) return; - gsi = acpi_pci_free_irq(entry); + if (entry->link) + gsi = acpi_pci_link_free_irq(entry->link); + else + gsi = entry->index; /* * TBD: It might be worth clearing dev->irq by magic constant -- cgit v1.2.3 From 3f0f3c27be19d390f23af1075d9948d0310e2673 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:37 -0700 Subject: ACPI: PCI: whitespace and useless initialization cleanup This patch makes function declarations consistent throughout the file and removes some unnecessary initializations. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 03d528e02c2..cba8d4dc56a 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -149,8 +149,8 @@ static struct prt_quirk prt_quirks[] = { "\\_SB_.PCI0.LNK3"}, }; -static void -do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) +static void do_prt_fixups(struct acpi_prt_entry *entry, + struct acpi_pci_routing_table *prt) { int i; struct prt_quirk *quirk; @@ -180,9 +180,8 @@ do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) } } -static int -acpi_pci_irq_add_entry(acpi_handle handle, - int segment, int bus, struct acpi_pci_routing_table *prt) +static int acpi_pci_irq_add_entry(acpi_handle handle, int segment, int bus, + struct acpi_pci_routing_table *prt) { struct acpi_prt_entry *entry; @@ -299,8 +298,7 @@ void acpi_pci_irq_del_prt(int segment, int bus) /* -------------------------------------------------------------------------- PCI Interrupt Routing Support -------------------------------------------------------------------------- */ -static struct acpi_prt_entry * -acpi_pci_irq_lookup(struct pci_dev *dev, int pin) +static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) { struct acpi_prt_entry *entry; struct pci_dev *bridge; @@ -351,24 +349,17 @@ acpi_pci_irq_lookup(struct pci_dev *dev, int pin) return NULL; } -/* - * acpi_pci_irq_enable - * success: return 0 - * failure: return < 0 - */ - int acpi_pci_irq_enable(struct pci_dev *dev) { struct acpi_prt_entry *entry; - int gsi = 0; - u8 pin = 0; + int gsi; + u8 pin; int triggering = ACPI_LEVEL_SENSITIVE; int polarity = ACPI_ACTIVE_LOW; char *link = NULL; char link_desc[16]; int rc; - pin = dev->pin; if (!pin) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -446,9 +437,8 @@ void __attribute__ ((weak)) acpi_unregister_gsi(u32 i) void acpi_pci_irq_disable(struct pci_dev *dev) { struct acpi_prt_entry *entry; - int gsi = 0; - u8 pin = 0; - + int gsi; + u8 pin; pin = dev->pin; if (!pin) -- cgit v1.2.3 From 39488b041e2fdc206b3de4517b8f220ae07b2a20 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 8 Dec 2008 21:31:42 -0700 Subject: ACPI: PCI: add HP copyright Add HP copyright to pci_irq.c. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index cba8d4dc56a..891bdf6679f 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -4,6 +4,8 @@ * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh * Copyright (C) 2002 Dominik Brodowski + * (c) Copyright 2008 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * -- cgit v1.2.3 From 087da3b4e2d7d3ef70a4fa649b9a286fdeb0e44e Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 30 Dec 2008 22:44:33 -0500 Subject: ACPI: simplify buffer management for acpi_pci_bind() etc. use ACPI_ALLOCATE_BUFFER to remove the allocations within acpi_pci_bind(), acpi_pci_unbind() and acpi_pci_bind_root(). While there, delete some unnecessary param inits from those routines. Delete concept of ACPI_PATHNAME_MAX, since this was the last use. Signed-off-by: Len Brown --- drivers/acpi/pci_bind.c | 80 ++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 47 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 53f502d29b3..95650f83ce2 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c @@ -111,12 +111,11 @@ EXPORT_SYMBOL(acpi_get_pci_id); int acpi_pci_bind(struct acpi_device *device) { int result = 0; - acpi_status status = AE_OK; - struct acpi_pci_data *data = NULL; - struct acpi_pci_data *pdata = NULL; - char *pathname = NULL; - struct acpi_buffer buffer = { 0, NULL }; - acpi_handle handle = NULL; + acpi_status status; + struct acpi_pci_data *data; + struct acpi_pci_data *pdata; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle handle; struct pci_dev *dev; struct pci_bus *bus; @@ -124,21 +123,18 @@ int acpi_pci_bind(struct acpi_device *device) if (!device || !device->parent) return -EINVAL; - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); - if (!pathname) - return -ENOMEM; - buffer.length = ACPI_PATHNAME_MAX; - buffer.pointer = pathname; - data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); - if (!data) { - kfree(pathname); + if (!data) return -ENOMEM; + + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) { + kfree(data); + return -ENODEV; } - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI device [%s]...\n", - pathname)); + (char *)buffer.pointer)); /* * Segment & Bus @@ -262,7 +258,7 @@ int acpi_pci_bind(struct acpi_device *device) } end: - kfree(pathname); + kfree(buffer.pointer); if (result) kfree(data); @@ -272,25 +268,21 @@ int acpi_pci_bind(struct acpi_device *device) static int acpi_pci_unbind(struct acpi_device *device) { int result = 0; - acpi_status status = AE_OK; - struct acpi_pci_data *data = NULL; - char *pathname = NULL; - struct acpi_buffer buffer = { 0, NULL }; + acpi_status status; + struct acpi_pci_data *data; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!device || !device->parent) return -EINVAL; - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); - if (!pathname) - return -ENOMEM; + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) + return -ENODEV; - buffer.length = ACPI_PATHNAME_MAX; - buffer.pointer = pathname; - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unbinding PCI device [%s]...\n", - pathname)); - kfree(pathname); + (char *) buffer.pointer)); + kfree(buffer.pointer); status = acpi_get_data(device->handle, acpi_pci_data_handler, @@ -322,50 +314,44 @@ acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *bus) { int result = 0; - acpi_status status = AE_OK; + acpi_status status; struct acpi_pci_data *data = NULL; - char *pathname = NULL; - struct acpi_buffer buffer = { 0, NULL }; - - pathname = kzalloc(ACPI_PATHNAME_MAX, GFP_KERNEL); - if (!pathname) - return -ENOMEM; - - buffer.length = ACPI_PATHNAME_MAX; - buffer.pointer = pathname; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; if (!device || !id || !bus) { - kfree(pathname); return -EINVAL; } data = kzalloc(sizeof(struct acpi_pci_data), GFP_KERNEL); - if (!data) { - kfree(pathname); + if (!data) return -ENOMEM; - } data->id = *id; data->bus = bus; device->ops.bind = acpi_pci_bind; device->ops.unbind = acpi_pci_unbind; - acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + status = acpi_get_name(device->handle, ACPI_FULL_PATHNAME, &buffer); + if (ACPI_FAILURE(status)) { + kfree (data); + return -ENODEV; + } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Binding PCI root bridge [%s] to " - "%04x:%02x\n", pathname, id->segment, id->bus)); + "%04x:%02x\n", (char *)buffer.pointer, + id->segment, id->bus)); status = acpi_attach_data(device->handle, acpi_pci_data_handler, data); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Unable to attach ACPI-PCI context to device %s", - pathname)); + (char *)buffer.pointer)); result = -ENODEV; goto end; } end: - kfree(pathname); + kfree(buffer.pointer); if (result != 0) kfree(data); -- cgit v1.2.3