in pci_link.c [277:386]
static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
{
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;
resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
if (!resource)
return -ENOMEM;
buffer.length = sizeof(*resource) + 1;
buffer.pointer = resource;
switch (link->irq.resource_type) {
case ACPI_RESOURCE_TYPE_IRQ:
resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
resource->res.length = sizeof(struct acpi_resource);
resource->res.data.irq.triggering = link->irq.triggering;
resource->res.data.irq.polarity =
link->irq.polarity;
if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
resource->res.data.irq.shareable =
ACPI_EXCLUSIVE;
else
resource->res.data.irq.shareable = ACPI_SHARED;
resource->res.data.irq.interrupt_count = 1;
resource->res.data.irq.interrupts[0] = irq;
break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
resource->res.length = sizeof(struct acpi_resource);
resource->res.data.extended_irq.producer_consumer =
ACPI_CONSUMER;
resource->res.data.extended_irq.triggering =
link->irq.triggering;
resource->res.data.extended_irq.polarity =
link->irq.polarity;
if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
resource->res.data.extended_irq.shareable =
ACPI_EXCLUSIVE;
else
resource->res.data.extended_irq.shareable = ACPI_SHARED;
resource->res.data.extended_irq.interrupt_count = 1;
resource->res.data.extended_irq.interrupts[0] = irq;
/* ignore resource_source, it's optional */
break;
default:
acpi_handle_err(handle, "Invalid resource type %d\n",
link->irq.resource_type);
result = -EINVAL;
goto end;
}
resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
resource->end.length = sizeof(struct acpi_resource);
/* Attempt to set the resource */
status = acpi_set_current_resources(link->device->handle, &buffer);
/* check for total failure */
if (ACPI_FAILURE(status)) {
acpi_evaluation_failure_warn(handle, "_SRS", status);
result = -ENODEV;
goto end;
}
/* Query _STA, set device->status */
result = acpi_bus_get_status(link->device);
if (result) {
acpi_handle_err(handle, "Unable to read status\n");
goto end;
}
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);
if (result) {
goto end;
}
/*
* Is current setting not what we set?
* set link->irq.active
*/
if (link->irq.active != irq) {
/*
* policy: when _CRS doesn't return what we just _SRS
* assume _SRS worked and override _CRS value.
*/
acpi_handle_warn(handle, "BIOS reported IRQ %d, using IRQ %d\n",
link->irq.active, irq);
link->irq.active = irq;
}
acpi_handle_debug(handle, "Set IRQ %d\n", link->irq.active);
end:
kfree(resource);
return result;
}