status = acpi_walk_resources(handle, METHOD_NAME__PRS,
acpi_pci_link_check_possible, link); if (ACPI_FAILURE(status)) {
acpi_handle_debug(handle, "_PRS not present or invalid"); return0;
}
acpi_handle_debug(handle, "Found %d possible IRQs\n",
link->irq.possible_count);
switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_END_TAG: return AE_OK; case ACPI_RESOURCE_TYPE_IRQ:
{ struct acpi_resource_irq *p = &resource->data.irq; if (!p->interrupt_count) { /* *IRQdescriptorsmayhavenoIRQ#bitsset, *particularlythosew/_STAdisabled
*/
pr_debug("Blank _CRS IRQ resource\n"); return AE_OK;
}
*irq = p->interrupts[0]; break;
} case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
{ struct acpi_resource_extended_irq *p =
&resource->data.extended_irq; if (!p->interrupt_count) { /* *extendedIRQdescriptorsmust *returnatleast1IRQ
*/
pr_debug("Blank _CRS EXT IRQ resource\n"); return AE_OK;
}
*irq = p->interrupts[0]; break;
} break; default:
pr_debug("_CRS resource type 0x%x is not IRQ\n",
resource->type); return AE_OK;
}
return AE_CTRL_TERMINATE;
}
/* *Run_CRSandsetlink->irq.active * *returnvalue: *0-success *!0-failure
*/ staticint acpi_pci_link_get_current(struct acpi_pci_link *link)
{
acpi_handle handle = link->device->handle;
acpi_status status; int result = 0; int irq = 0;
link->irq.active = 0;
/* in practice, status disabled is meaningless, ignore it */ if (acpi_strict) { /* Query _STA, set link->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_debug(handle, "Link disabled\n"); return0;
}
}
/* 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;
}
/* *reflectthepossibleandactiveirqsinthepenaltytable-- *usefulforbreakingties.
*/ if (link->irq.possible_count) { int penalty =
PIRQ_PENALTY_PCI_POSSIBLE /
link->irq.possible_count;
for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
acpi_isa_irq_penalty[link->irq.
possible[i]] +=
penalty;
}
staticint acpi_pci_link_allocate(struct acpi_pci_link *link)
{
acpi_handle handle = link->device->handle; int irq; int i;
if (link->irq.initialized) { if (link->refcnt == 0) /* This means the link is disabled but initialized */
acpi_pci_link_set(link, link->irq.active); return0;
}
/* *searchforactiveIRQinlistofpossibleIRQs.
*/ for (i = 0; i < link->irq.possible_count; ++i) { if (link->irq.active == link->irq.possible[i]) break;
} /* *forgetactiveIRQthatisnotinpossiblelist
*/ if (i == link->irq.possible_count) { if (acpi_strict)
acpi_handle_warn(handle, "_CRS %d not found in _PRS\n",
link->irq.active);
link->irq.active = 0;
}
if (acpi_irq_balance || !link->irq.active) { /* *SelectthebestIRQ.Thisisdoneinreversetopromote *theuseofIRQs9,10,11,and>15.
*/ for (i = (link->irq.possible_count - 1); i >= 0; i--) { if (acpi_irq_get_penalty(irq) >
acpi_irq_get_penalty(link->irq.possible[i]))
irq = link->irq.possible[i];
}
} if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
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)) {
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;
acpi_handle_info(handle, "Enabled at IRQ %d\n",
link->irq.active);
}
link->irq.initialized = 1; return0;
}
/* *acpi_pci_link_allocate_irq *success:returnIRQ>=0 *failure:return-1
*/ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, int *polarity, char **name)
{ struct acpi_device *device = acpi_fetch_acpi_dev(handle); struct acpi_pci_link *link;
if (!device) {
acpi_handle_err(handle, "Invalid link device\n"); return -1;
}
link = acpi_driver_data(device); if (!link) {
acpi_handle_err(handle, "Invalid link context\n"); return -1;
}
/* TBD: Support multiple index (IRQ) entries per Link Device */ if (index) {
acpi_handle_err(handle, "Invalid index %d\n", index); return -1;
}
mutex_lock(&acpi_link_lock); if (acpi_pci_link_allocate(link)) {
mutex_unlock(&acpi_link_lock); return -1;
}
if (!link->irq.active) {
mutex_unlock(&acpi_link_lock);
acpi_handle_err(handle, "Link active IRQ is 0!\n"); return -1;
}
link->refcnt++;
mutex_unlock(&acpi_link_lock);
if (triggering)
*triggering = link->irq.triggering; if (polarity)
*polarity = link->irq.polarity; if (name)
*name = acpi_device_bid(link->device);
acpi_handle_debug(handle, "Link is referenced\n"); return link->irq.active;
}
mutex_lock(&acpi_link_lock);
result = acpi_pci_link_get_possible(link); if (result) goto end;
/* query and set link->irq.active */
acpi_pci_link_get_current(link);
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])
acpi_handle_debug(handle, "Possible IRQ %d\n",
link->irq.possible[i]);
}
if (!link->device->status.enabled)
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(handle, "_DIS", NULL, NULL);
mutex_unlock(&acpi_link_lock);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.