# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1100 -> 1.1101 # drivers/acpi/pci_link.c 1.7 -> 1.9 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/09/08 len.brown@intel.com 1.1101 # Extended IRQ resource type for nForce (Andrew de Quincey) # Handle BIOS with _CRS that fails (Jun Nakajima) # -------------------------------------------- # diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c Tue Sep 23 12:10:57 2003 +++ b/drivers/acpi/pci_link.c Tue Sep 23 12:10:57 2003 @@ -216,7 +216,6 @@ return AE_CTRL_TERMINATE; } - static int acpi_pci_link_get_current ( struct acpi_pci_link *link) @@ -275,6 +274,28 @@ return_VALUE(result); } +static int +acpi_pci_link_try_get_current ( + struct acpi_pci_link *link, + int irq) +{ + int result; + + ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current"); + + result = acpi_pci_link_get_current(link); + if (result && link->irq.active) { + return_VALUE(result); + } + + if (!link->irq.active) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); + printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device)); + link->irq.active = irq; + } + + return 0; +} static int acpi_pci_link_set ( @@ -290,7 +311,8 @@ struct acpi_buffer buffer = {sizeof(resource)+1, &resource}; int i = 0; int valid = 0; - + int resource_type = 0; + ACPI_FUNCTION_TRACE("acpi_pci_link_set"); if (!link || !irq) @@ -313,12 +335,23 @@ } } + /* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with + * an extended one */ + if (irq <= 15) { + resource_type = ACPI_RSTYPE_IRQ; + } else { + resource_type = ACPI_RSTYPE_EXT_IRQ; + } + +retry_programming: + memset(&resource, 0, sizeof(resource)); /* NOTE: PCI interrupts are always level / active_low / shared. But not all interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for parameters */ - if (irq <= 15) { + switch(resource_type) { + case ACPI_RSTYPE_IRQ: resource.res.id = ACPI_RSTYPE_IRQ; resource.res.length = sizeof(struct acpi_resource); resource.res.data.irq.edge_level = link->irq.edge_level; @@ -326,8 +359,9 @@ resource.res.data.irq.shared_exclusive = ACPI_SHARED; resource.res.data.irq.number_of_interrupts = 1; resource.res.data.irq.interrupts[0] = irq; - } - else { + break; + + case ACPI_RSTYPE_EXT_IRQ: resource.res.id = ACPI_RSTYPE_EXT_IRQ; resource.res.length = sizeof(struct acpi_resource); resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER; @@ -337,11 +371,22 @@ resource.res.data.extended_irq.number_of_interrupts = 1; resource.res.data.extended_irq.interrupts[0] = irq; /* ignore resource_source, it's optional */ + break; } resource.end.id = ACPI_RSTYPE_END_TAG; /* Attempt to set the resource */ status = acpi_set_current_resources(link->handle, &buffer); + + + /* if we failed and IRQ <= 15, try again with an extended descriptor */ + if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) { + resource_type = ACPI_RSTYPE_EXT_IRQ; + printk(PREFIX "Retrying with extended IRQ descriptor\n"); + goto retry_programming; + } + + /* check for total failure */ if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n")); return_VALUE(-ENODEV); @@ -359,7 +404,7 @@ } /* Make sure the active IRQ is the one we requested. */ - result = acpi_pci_link_get_current(link); + result = acpi_pci_link_try_get_current(link, irq); if (result) { return_VALUE(result); } @@ -573,10 +618,6 @@ else printk(" %d", link->irq.possible[i]); } - if (!link->irq.active) - printk(", disabled"); - else if (!found) - printk(", enabled at IRQ %d", link->irq.active); printk(")\n"); /* TBD: Acquire/release lock */