|
|
|
@@ -12,6 +12,8 @@
|
|
|
|
|
* for IRQ management (e.g. start()->_SRS).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define pr_fmt(fmt) "ACPI: PCI: " fmt
|
|
|
|
|
|
|
|
|
|
#include <linux/syscore_ops.h>
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
@@ -27,8 +29,6 @@
|
|
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
|
|
#define _COMPONENT ACPI_PCI_COMPONENT
|
|
|
|
|
ACPI_MODULE_NAME("pci_link");
|
|
|
|
|
#define ACPI_PCI_LINK_CLASS "pci_irq_routing"
|
|
|
|
|
#define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
|
|
|
|
|
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
|
|
|
|
@@ -85,6 +85,7 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
|
|
|
|
|
void *context)
|
|
|
|
|
{
|
|
|
|
|
struct acpi_pci_link *link = context;
|
|
|
|
|
acpi_handle handle = link->device->handle;
|
|
|
|
|
u32 i;
|
|
|
|
|
|
|
|
|
|
switch (resource->type) {
|
|
|
|
@@ -95,17 +96,17 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
|
|
|
|
|
{
|
|
|
|
|
struct acpi_resource_irq *p = &resource->data.irq;
|
|
|
|
|
if (!p || !p->interrupt_count) {
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
|
|
"Blank _PRS IRQ resource\n"));
|
|
|
|
|
acpi_handle_debug(handle,
|
|
|
|
|
"Blank _PRS IRQ resource\n");
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0;
|
|
|
|
|
(i < p->interrupt_count
|
|
|
|
|
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
|
|
|
|
|
if (!p->interrupts[i]) {
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"Invalid _PRS IRQ %d\n",
|
|
|
|
|
p->interrupts[i]);
|
|
|
|
|
acpi_handle_debug(handle,
|
|
|
|
|
"Invalid _PRS IRQ %d\n",
|
|
|
|
|
p->interrupts[i]);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
link->irq.possible[i] = p->interrupts[i];
|
|
|
|
@@ -121,17 +122,17 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
|
|
|
|
|
struct acpi_resource_extended_irq *p =
|
|
|
|
|
&resource->data.extended_irq;
|
|
|
|
|
if (!p || !p->interrupt_count) {
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"Blank _PRS EXT IRQ resource\n");
|
|
|
|
|
acpi_handle_debug(handle,
|
|
|
|
|
"Blank _PRS EXT IRQ resource\n");
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0;
|
|
|
|
|
(i < p->interrupt_count
|
|
|
|
|
&& i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
|
|
|
|
|
if (!p->interrupts[i]) {
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"Invalid _PRS IRQ %d\n",
|
|
|
|
|
p->interrupts[i]);
|
|
|
|
|
acpi_handle_debug(handle,
|
|
|
|
|
"Invalid _PRS IRQ %d\n",
|
|
|
|
|
p->interrupts[i]);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
link->irq.possible[i] = p->interrupts[i];
|
|
|
|
@@ -143,8 +144,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n",
|
|
|
|
|
resource->type);
|
|
|
|
|
acpi_handle_debug(handle, "_PRS resource type 0x%x is not IRQ\n",
|
|
|
|
|
resource->type);
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -153,18 +154,18 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
|
|
|
|
|
|
|
|
|
|
static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
|
|
|
|
|
{
|
|
|
|
|
acpi_handle handle = link->device->handle;
|
|
|
|
|
acpi_status status;
|
|
|
|
|
|
|
|
|
|
status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS,
|
|
|
|
|
status = acpi_walk_resources(handle, METHOD_NAME__PRS,
|
|
|
|
|
acpi_pci_link_check_possible, link);
|
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
|
|
acpi_handle_debug(link->device->handle, "_PRS not present or invalid");
|
|
|
|
|
acpi_handle_debug(handle, "_PRS not present or invalid");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
|
|
"Found %d possible IRQs\n",
|
|
|
|
|
link->irq.possible_count));
|
|
|
|
|
acpi_handle_debug(handle, "Found %d possible IRQs\n",
|
|
|
|
|
link->irq.possible_count);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -186,8 +187,7 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
|
|
|
|
|
* IRQ descriptors may have no IRQ# bits set,
|
|
|
|
|
* particularly those those w/ _STA disabled
|
|
|
|
|
*/
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
|
|
"Blank _CRS IRQ resource\n"));
|
|
|
|
|
pr_debug("Blank _CRS IRQ resource\n");
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
*irq = p->interrupts[0];
|
|
|
|
@@ -202,8 +202,7 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
|
|
|
|
|
* extended IRQ descriptors must
|
|
|
|
|
* return at least 1 IRQ
|
|
|
|
|
*/
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"Blank _CRS EXT IRQ resource\n");
|
|
|
|
|
pr_debug("Blank _CRS EXT IRQ resource\n");
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
*irq = p->interrupts[0];
|
|
|
|
@@ -211,8 +210,8 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n",
|
|
|
|
|
resource->type);
|
|
|
|
|
pr_debug("_CRS resource type 0x%x is not IRQ\n",
|
|
|
|
|
resource->type);
|
|
|
|
|
return AE_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -228,8 +227,9 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
|
|
|
|
|
*/
|
|
|
|
|
static int acpi_pci_link_get_current(struct acpi_pci_link *link)
|
|
|
|
|
{
|
|
|
|
|
int result = 0;
|
|
|
|
|
acpi_handle handle = link->device->handle;
|
|
|
|
|
acpi_status status;
|
|
|
|
|
int result = 0;
|
|
|
|
|
int irq = 0;
|
|
|
|
|
|
|
|
|
|
link->irq.active = 0;
|
|
|
|
@@ -239,12 +239,12 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
|
|
|
|
|
/* Query _STA, set link->device->status */
|
|
|
|
|
result = acpi_bus_get_status(link->device);
|
|
|
|
|
if (result) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Unable to read status\n");
|
|
|
|
|
acpi_handle_err(handle, "Unable to read status\n");
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!link->device->status.enabled) {
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
|
|
|
|
|
acpi_handle_debug(handle, "Link disabled\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -253,22 +253,23 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
|
|
|
|
|
* Query and parse _CRS to get the current IRQ assignment.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
|
|
|
|
|
status = acpi_walk_resources(handle, METHOD_NAME__CRS,
|
|
|
|
|
acpi_pci_link_check_current, &irq);
|
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
|
|
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _CRS"));
|
|
|
|
|
acpi_handle_warn(handle, "_CRS evaluation failed: %s\n",
|
|
|
|
|
acpi_format_exception(status));
|
|
|
|
|
result = -ENODEV;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (acpi_strict && !irq) {
|
|
|
|
|
printk(KERN_ERR PREFIX "_CRS returned 0\n");
|
|
|
|
|
acpi_handle_err(handle, "_CRS returned 0\n");
|
|
|
|
|
result = -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link->irq.active = irq;
|
|
|
|
|
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
|
|
|
|
|
acpi_handle_debug(handle, "Link at IRQ %d \n", link->irq.active);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
return result;
|
|
|
|
@@ -276,13 +277,14 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link)
|
|
|
|
|
|
|
|
|
|
static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|
|
|
|
{
|
|
|
|
|
int result;
|
|
|
|
|
acpi_status status;
|
|
|
|
|
struct {
|
|
|
|
|
struct acpi_resource res;
|
|
|
|
|
struct acpi_resource end;
|
|
|
|
|
} *resource;
|
|
|
|
|
struct acpi_buffer buffer = { 0, NULL };
|
|
|
|
|
acpi_handle handle = link->device->handle;
|
|
|
|
|
acpi_status status;
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
if (!irq)
|
|
|
|
|
return -EINVAL;
|
|
|
|
@@ -329,7 +331,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|
|
|
|
/* ignore resource_source, it's optional */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
|
|
|
|
|
acpi_handle_err(handle, "Invalid resource type %d\n",
|
|
|
|
|
link->irq.resource_type);
|
|
|
|
|
result = -EINVAL;
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
|
@@ -342,7 +345,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|
|
|
|
|
|
|
|
|
/* check for total failure */
|
|
|
|
|
if (ACPI_FAILURE(status)) {
|
|
|
|
|
ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SRS"));
|
|
|
|
|
acpi_handle_warn(handle, "_SRS evaluation failed: %s",
|
|
|
|
|
acpi_format_exception(status));
|
|
|
|
|
result = -ENODEV;
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
@@ -350,15 +354,11 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|
|
|
|
/* Query _STA, set device->status */
|
|
|
|
|
result = acpi_bus_get_status(link->device);
|
|
|
|
|
if (result) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Unable to read status\n");
|
|
|
|
|
acpi_handle_err(handle, "Unable to read status\n");
|
|
|
|
|
goto end;
|
|
|
|
|
}
|
|
|
|
|
if (!link->device->status.enabled) {
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"%s [%s] disabled and referenced, BIOS bug\n",
|
|
|
|
|
acpi_device_name(link->device),
|
|
|
|
|
acpi_device_bid(link->device));
|
|
|
|
|
}
|
|
|
|
|
if (!link->device->status.enabled)
|
|
|
|
|
acpi_handle_warn(handle, "Disabled and referenced, BIOS bug\n");
|
|
|
|
|
|
|
|
|
|
/* Query _CRS, set link->irq.active */
|
|
|
|
|
result = acpi_pci_link_get_current(link);
|
|
|
|
@@ -375,14 +375,12 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
|
|
|
|
|
* policy: when _CRS doesn't return what we just _SRS
|
|
|
|
|
* assume _SRS worked and override _CRS value.
|
|
|
|
|
*/
|
|
|
|
|
printk(KERN_WARNING PREFIX
|
|
|
|
|
"%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
|
|
|
|
|
acpi_device_name(link->device),
|
|
|
|
|
acpi_device_bid(link->device), link->irq.active, irq);
|
|
|
|
|
acpi_handle_warn(handle, "BIOS reported IRQ %d, using IRQ %d\n",
|
|
|
|
|
link->irq.active, irq);
|
|
|
|
|
link->irq.active = irq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
|
|
|
|
|
acpi_handle_debug(handle, "Set IRQ %d\n", link->irq.active);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
kfree(resource);
|
|
|
|
@@ -531,6 +529,7 @@ static int acpi_irq_balance = -1; /* 0: static, 1: balance */
|
|
|
|
|
|
|
|
|
|
static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
|
|
|
|
{
|
|
|
|
|
acpi_handle handle = link->device->handle;
|
|
|
|
|
int irq;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@@ -553,8 +552,8 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
|
|
|
|
*/
|
|
|
|
|
if (i == link->irq.possible_count) {
|
|
|
|
|
if (acpi_strict)
|
|
|
|
|
printk(KERN_WARNING PREFIX "_CRS %d not found"
|
|
|
|
|
" in _PRS\n", link->irq.active);
|
|
|
|
|
acpi_handle_warn(handle, "_CRS %d not found in _PRS\n",
|
|
|
|
|
link->irq.active);
|
|
|
|
|
link->irq.active = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -578,28 +577,23 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
|
|
|
|
|
printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
|
|
|
|
|
"Try pci=noacpi or acpi=off\n",
|
|
|
|
|
acpi_device_name(link->device),
|
|
|
|
|
acpi_device_bid(link->device));
|
|
|
|
|
acpi_handle_err(handle,
|
|
|
|
|
"No IRQ available. Try pci=noacpi or acpi=off\n");
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Attempt to enable the link device at this IRQ. */
|
|
|
|
|
if (acpi_pci_link_set(link, irq)) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Unable to set IRQ for %s [%s]. "
|
|
|
|
|
"Try pci=noacpi or acpi=off\n",
|
|
|
|
|
acpi_device_name(link->device),
|
|
|
|
|
acpi_device_bid(link->device));
|
|
|
|
|
acpi_handle_err(handle,
|
|
|
|
|
"Unable to set IRQ. Try pci=noacpi or acpi=off\n");
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
} else {
|
|
|
|
|
if (link->irq.active < ACPI_MAX_ISA_IRQS)
|
|
|
|
|
acpi_isa_irq_penalty[link->irq.active] +=
|
|
|
|
|
PIRQ_PENALTY_PCI_USING;
|
|
|
|
|
|
|
|
|
|
pr_info("%s [%s] enabled at IRQ %d\n",
|
|
|
|
|
acpi_device_name(link->device),
|
|
|
|
|
acpi_device_bid(link->device), link->irq.active);
|
|
|
|
|
acpi_handle_info(handle, "Enabled at IRQ %d\n",
|
|
|
|
|
link->irq.active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link->irq.initialized = 1;
|
|
|
|
@@ -620,19 +614,19 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
|
|
|
|
|
|
|
|
|
result = acpi_bus_get_device(handle, &device);
|
|
|
|
|
if (result) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid link device\n");
|
|
|
|
|
acpi_handle_err(handle, "Invalid link device\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link = acpi_driver_data(device);
|
|
|
|
|
if (!link) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid link context\n");
|
|
|
|
|
acpi_handle_err(handle, "Invalid link context\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TBD: Support multiple index (IRQ) entries per Link Device */
|
|
|
|
|
if (index) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid index %d\n", index);
|
|
|
|
|
acpi_handle_err(handle, "Invalid index %d\n", index);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -644,7 +638,7 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
|
|
|
|
|
|
|
|
|
if (!link->irq.active) {
|
|
|
|
|
mutex_unlock(&acpi_link_lock);
|
|
|
|
|
printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
|
|
|
|
|
acpi_handle_err(handle, "Link active IRQ is 0!\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
link->refcnt++;
|
|
|
|
@@ -656,9 +650,7 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
|
|
|
|
*polarity = link->irq.polarity;
|
|
|
|
|
if (name)
|
|
|
|
|
*name = acpi_device_bid(link->device);
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
|
|
"Link %s is referenced\n",
|
|
|
|
|
acpi_device_bid(link->device)));
|
|
|
|
|
acpi_handle_debug(handle, "Link is referenced\n");
|
|
|
|
|
return link->irq.active;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -674,20 +666,20 @@ int acpi_pci_link_free_irq(acpi_handle handle)
|
|
|
|
|
|
|
|
|
|
result = acpi_bus_get_device(handle, &device);
|
|
|
|
|
if (result) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid link device\n");
|
|
|
|
|
acpi_handle_err(handle, "Invalid link device\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
link = acpi_driver_data(device);
|
|
|
|
|
if (!link) {
|
|
|
|
|
printk(KERN_ERR PREFIX "Invalid link context\n");
|
|
|
|
|
acpi_handle_err(handle, "Invalid link context\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutex_lock(&acpi_link_lock);
|
|
|
|
|
if (!link->irq.initialized) {
|
|
|
|
|
mutex_unlock(&acpi_link_lock);
|
|
|
|
|
printk(KERN_ERR PREFIX "Link isn't initialized\n");
|
|
|
|
|
acpi_handle_err(handle, "Link isn't initialized\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
#ifdef FUTURE_USE
|
|
|
|
@@ -702,9 +694,7 @@ int acpi_pci_link_free_irq(acpi_handle handle)
|
|
|
|
|
*/
|
|
|
|
|
link->refcnt--;
|
|
|
|
|
#endif
|
|
|
|
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
|
|
|
|
"Link %s is dereferenced\n",
|
|
|
|
|
acpi_device_bid(link->device)));
|
|
|
|
|
acpi_handle_debug(handle, "Link is dereferenced\n");
|
|
|
|
|
|
|
|
|
|
if (link->refcnt == 0)
|
|
|
|
|
acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
|
|
|
|
@@ -720,10 +710,10 @@ int acpi_pci_link_free_irq(acpi_handle handle)
|
|
|
|
|
static int acpi_pci_link_add(struct acpi_device *device,
|
|
|
|
|
const struct acpi_device_id *not_used)
|
|
|
|
|
{
|
|
|
|
|
int result;
|
|
|
|
|
acpi_handle handle = device->handle;
|
|
|
|
|
struct acpi_pci_link *link;
|
|
|
|
|
int result;
|
|
|
|
|
int i;
|
|
|
|
|
int found = 0;
|
|
|
|
|
|
|
|
|
|
link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
|
|
|
|
|
if (!link)
|
|
|
|
@@ -742,31 +732,23 @@ static int acpi_pci_link_add(struct acpi_device *device,
|
|
|
|
|
/* query and set link->irq.active */
|
|
|
|
|
acpi_pci_link_get_current(link);
|
|
|
|
|
|
|
|
|
|
printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device),
|
|
|
|
|
acpi_device_bid(device));
|
|
|
|
|
pr_info("Interrupt link %s configured for IRQ %d\n",
|
|
|
|
|
acpi_device_bid(device), link->irq.active);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < link->irq.possible_count; i++) {
|
|
|
|
|
if (link->irq.active == link->irq.possible[i]) {
|
|
|
|
|
printk(KERN_CONT " *%d", link->irq.possible[i]);
|
|
|
|
|
found = 1;
|
|
|
|
|
} else
|
|
|
|
|
printk(KERN_CONT " %d", link->irq.possible[i]);
|
|
|
|
|
if (link->irq.active != link->irq.possible[i])
|
|
|
|
|
acpi_handle_debug(handle, "Possible IRQ %d\n",
|
|
|
|
|
link->irq.possible[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printk(KERN_CONT ")");
|
|
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
|
printk(KERN_CONT " *%d", link->irq.active);
|
|
|
|
|
|
|
|
|
|
if (!link->device->status.enabled)
|
|
|
|
|
printk(KERN_CONT ", disabled.");
|
|
|
|
|
|
|
|
|
|
printk(KERN_CONT "\n");
|
|
|
|
|
pr_info("Interrupt link %s disabled\n", acpi_device_bid(device));
|
|
|
|
|
|
|
|
|
|
list_add_tail(&link->list, &acpi_link_list);
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
/* disable all links -- to be activated on use */
|
|
|
|
|
acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
|
|
|
|
|
acpi_evaluate_object(handle, "_DIS", NULL, NULL);
|
|
|
|
|
mutex_unlock(&acpi_link_lock);
|
|
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
|