Commit 77641575 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] acpi_pci_irq_enable() now returns 0 on success.

This bubbles all the way up to pci_enable_device().
This allows IRQ0 to be used as a legal PCI device IRQ.

The ES7000 uses an interrupt source override to assign pin20 to IRQ0.
Then platform_rename_gsi assigns pin0 a high-numbered IRQ -- available
for PCI devices.  But IRQ0 needs to be a legal PCI IRQ in the lookup code
to make it as far as the re-name code. 
Signed-off-by: default avatarNatalie Protasevich <Natalie.Protasevich@UNISYS.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 634d6b5f
...@@ -227,6 +227,11 @@ acpi_pci_irq_add_prt ( ...@@ -227,6 +227,11 @@ acpi_pci_irq_add_prt (
PCI Interrupt Routing Support PCI Interrupt Routing Support
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
/*
* acpi_pci_irq_lookup
* success: return IRQ >= 0
* failure: return -1
*/
static int static int
acpi_pci_irq_lookup ( acpi_pci_irq_lookup (
struct pci_bus *bus, struct pci_bus *bus,
...@@ -249,14 +254,14 @@ acpi_pci_irq_lookup ( ...@@ -249,14 +254,14 @@ acpi_pci_irq_lookup (
entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin); entry = acpi_pci_irq_find_prt_entry(segment, bus_nr, device, pin);
if (!entry) { 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_VALUE(0); return_VALUE(-1);
} }
if (entry->link.handle) { if (entry->link.handle) {
irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low); irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low);
if (!irq) { if (irq < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
return_VALUE(0); return_VALUE(-1);
} }
} else { } else {
irq = entry->link.index; irq = entry->link.index;
...@@ -269,6 +274,11 @@ acpi_pci_irq_lookup ( ...@@ -269,6 +274,11 @@ acpi_pci_irq_lookup (
return_VALUE(irq); return_VALUE(irq);
} }
/*
* acpi_pci_irq_derive
* success: return IRQ >= 0
* failure: return < 0
*/
static int static int
acpi_pci_irq_derive ( acpi_pci_irq_derive (
struct pci_dev *dev, struct pci_dev *dev,
...@@ -277,7 +287,7 @@ acpi_pci_irq_derive ( ...@@ -277,7 +287,7 @@ acpi_pci_irq_derive (
int *active_high_low) int *active_high_low)
{ {
struct pci_dev *bridge = dev; struct pci_dev *bridge = dev;
int irq = 0; int irq = -1;
u8 bridge_pin = 0; u8 bridge_pin = 0;
ACPI_FUNCTION_TRACE("acpi_pci_irq_derive"); ACPI_FUNCTION_TRACE("acpi_pci_irq_derive");
...@@ -289,7 +299,7 @@ acpi_pci_irq_derive ( ...@@ -289,7 +299,7 @@ acpi_pci_irq_derive (
* Attempt to derive an IRQ for this device from a parent bridge's * 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). * PCI interrupt routing entry (eg. yenta bridge and add-in card bridge).
*/ */
while (!irq && bridge->bus->self) { while (irq < 0 && bridge->bus->self) {
pin = (pin + PCI_SLOT(bridge->devfn)) % 4; pin = (pin + PCI_SLOT(bridge->devfn)) % 4;
bridge = bridge->bus->self; bridge = bridge->bus->self;
...@@ -299,7 +309,7 @@ acpi_pci_irq_derive ( ...@@ -299,7 +309,7 @@ acpi_pci_irq_derive (
if (!bridge_pin) { if (!bridge_pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n", pci_name(bridge))); "No interrupt pin configured for device %s\n", pci_name(bridge)));
return_VALUE(0); return_VALUE(-1);
} }
/* Pin is from 0 to 3 */ /* Pin is from 0 to 3 */
bridge_pin --; bridge_pin --;
...@@ -310,9 +320,9 @@ acpi_pci_irq_derive ( ...@@ -310,9 +320,9 @@ acpi_pci_irq_derive (
pin, edge_level, active_high_low); pin, edge_level, active_high_low);
} }
if (!irq) { if (irq < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev))); ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Unable to derive IRQ for device %s\n", pci_name(dev)));
return_VALUE(0); return_VALUE(-1);
} }
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n", ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Derive IRQ %d for device %s from %s\n",
...@@ -321,6 +331,11 @@ acpi_pci_irq_derive ( ...@@ -321,6 +331,11 @@ acpi_pci_irq_derive (
return_VALUE(irq); return_VALUE(irq);
} }
/*
* acpi_pci_irq_enable
* success: return 0
* failure: return < 0
*/
int int
acpi_pci_irq_enable ( acpi_pci_irq_enable (
...@@ -358,20 +373,20 @@ acpi_pci_irq_enable ( ...@@ -358,20 +373,20 @@ acpi_pci_irq_enable (
* If no PRT entry was found, we'll try to derive an IRQ from the * If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge. * device's parent bridge.
*/ */
if (!irq) if (irq < 0)
irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low); irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low);
/* /*
* No IRQ known to the ACPI subsystem - maybe the BIOS / * No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case. * driver reported one, then use it. Exit in any case.
*/ */
if (!irq) { if (irq < 0) {
printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI", printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
pci_name(dev), ('A' + pin)); pci_name(dev), ('A' + pin));
/* Interrupt Line values above 0xF are forbidden */ /* Interrupt Line values above 0xF are forbidden */
if (dev->irq && (dev->irq <= 0xF)) { if (dev->irq >= 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq); printk(" - using IRQ %d\n", dev->irq);
return_VALUE(dev->irq); return_VALUE(0);
} }
else { else {
printk("\n"); printk("\n");
...@@ -388,5 +403,5 @@ acpi_pci_irq_enable ( ...@@ -388,5 +403,5 @@ acpi_pci_irq_enable (
(active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high", (active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
dev->irq); dev->irq);
return_VALUE(dev->irq); return_VALUE(0);
} }
...@@ -577,6 +577,11 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) { ...@@ -577,6 +577,11 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
return_VALUE(0); return_VALUE(0);
} }
/*
* acpi_pci_link_get_irq
* success: return IRQ >= 0
* failure: return -1
*/
int int
acpi_pci_link_get_irq ( acpi_pci_link_get_irq (
...@@ -594,27 +599,27 @@ acpi_pci_link_get_irq ( ...@@ -594,27 +599,27 @@ acpi_pci_link_get_irq (
result = acpi_bus_get_device(handle, &device); result = acpi_bus_get_device(handle, &device);
if (result) { if (result) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n"));
return_VALUE(0); return_VALUE(-1);
} }
link = (struct acpi_pci_link *) acpi_driver_data(device); link = (struct acpi_pci_link *) acpi_driver_data(device);
if (!link) { if (!link) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
return_VALUE(0); return_VALUE(-1);
} }
/* TBD: Support multiple index (IRQ) entries per Link Device */ /* TBD: Support multiple index (IRQ) entries per Link Device */
if (index) { if (index) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index)); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid index %d\n", index));
return_VALUE(0); return_VALUE(-1);
} }
if (acpi_pci_link_allocate(link)) if (acpi_pci_link_allocate(link))
return_VALUE(0); return_VALUE(-1);
if (!link->irq.active) { if (!link->irq.active) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
return_VALUE(0); return_VALUE(-1);
} }
if (edge_level) *edge_level = link->irq.edge_level; if (edge_level) *edge_level = link->irq.edge_level;
......
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