Commit f961b5f3 authored by Len Brown's avatar Len Brown

Extended IRQ resource type for nForce (Andrew de Quincey)

parent 7f3257ab
...@@ -315,6 +315,7 @@ acpi_pci_link_set ( ...@@ -315,6 +315,7 @@ acpi_pci_link_set (
struct acpi_buffer buffer = {sizeof(resource)+1, &resource}; struct acpi_buffer buffer = {sizeof(resource)+1, &resource};
int i = 0; int i = 0;
int valid = 0; int valid = 0;
int resource_type = 0;
ACPI_FUNCTION_TRACE("acpi_pci_link_set"); ACPI_FUNCTION_TRACE("acpi_pci_link_set");
...@@ -338,20 +339,32 @@ acpi_pci_link_set ( ...@@ -338,20 +339,32 @@ acpi_pci_link_set (
} }
} }
/* 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)); memset(&resource, 0, sizeof(resource));
/* NOTE: PCI interrupts are always level / active_low / shared. But not all /* NOTE: PCI interrupts are always level / active_low / shared. But not all
interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for
parameters */ parameters */
if (irq <= 15) { switch(resource_type) {
case ACPI_RSTYPE_IRQ:
resource.res.id = ACPI_RSTYPE_IRQ; resource.res.id = ACPI_RSTYPE_IRQ;
resource.res.length = sizeof(struct acpi_resource); resource.res.length = sizeof(struct acpi_resource);
resource.res.data.irq.edge_level = link->irq.edge_level; resource.res.data.irq.edge_level = link->irq.edge_level;
resource.res.data.irq.active_high_low = link->irq.active_high_low; resource.res.data.irq.active_high_low = link->irq.active_high_low;
resource.res.data.irq.number_of_interrupts = 1; resource.res.data.irq.number_of_interrupts = 1;
resource.res.data.irq.interrupts[0] = irq; resource.res.data.irq.interrupts[0] = irq;
} break;
else {
case ACPI_RSTYPE_EXT_IRQ:
resource.res.id = ACPI_RSTYPE_EXT_IRQ; resource.res.id = ACPI_RSTYPE_EXT_IRQ;
resource.res.length = sizeof(struct acpi_resource); resource.res.length = sizeof(struct acpi_resource);
resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER; resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
...@@ -360,11 +373,21 @@ acpi_pci_link_set ( ...@@ -360,11 +373,21 @@ acpi_pci_link_set (
resource.res.data.extended_irq.number_of_interrupts = 1; resource.res.data.extended_irq.number_of_interrupts = 1;
resource.res.data.extended_irq.interrupts[0] = irq; resource.res.data.extended_irq.interrupts[0] = irq;
/* ignore resource_source, it's optional */ /* ignore resource_source, it's optional */
break;
} }
resource.end.id = ACPI_RSTYPE_END_TAG; resource.end.id = ACPI_RSTYPE_END_TAG;
/* Attempt to set the resource */ /* Attempt to set the resource */
status = acpi_set_current_resources(link->handle, &buffer); 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)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
...@@ -479,14 +502,14 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) { ...@@ -479,14 +502,14 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
irq = link->irq.possible[0]; irq = link->irq.possible[0];
} }
/* /*
* Select the best IRQ. This is done in reverse to promote * Select the best IRQ. This is done in reverse to promote
* the use of IRQs 9, 10, 11, and >15. * the use of IRQs 9, 10, 11, and >15.
*/ */
for (i=(link->irq.possible_count-1); i>0; i--) { for (i=(link->irq.possible_count-1); i>0; i--) {
if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]])
irq = link->irq.possible[i]; irq = link->irq.possible[i];
} }
/* Attempt to enable the link device at this IRQ. */ /* Attempt to enable the link device at this IRQ. */
if (acpi_pci_link_set(link, irq)) { if (acpi_pci_link_set(link, irq)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment