Merge branch 'acpi-pci'

Merge the ACPI PCI topic branch depended on by the following material.
This commit is contained in:
Rafael J. Wysocki 2021-03-08 16:54:00 +01:00
commit 68eab52e71
6 changed files with 85 additions and 126 deletions

View file

@ -50,7 +50,7 @@
CONFIG_ACPI_DEBUG must be enabled to produce any ACPI
debug output. Bits in debug_layer correspond to a
_COMPONENT in an ACPI source file, e.g.,
#define _COMPONENT ACPI_PCI_COMPONENT
#define _COMPONENT ACPI_EVENTS
Bits in debug_level correspond to a level in
ACPI_DEBUG_PRINT statements, e.g.,
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ...
@ -60,8 +60,6 @@
Enable processor driver info messages:
acpi.debug_layer=0x20000000
Enable PCI/PCI interrupt routing info messages:
acpi.debug_layer=0x400000
Enable AML "Debug" output, i.e., stores to the Debug
object while interpreting AML:
acpi.debug_layer=0xffffffff acpi.debug_level=0x2

View file

@ -54,7 +54,6 @@ shows the supported mask values, currently these::
ACPI_TOOLS 0x00002000
ACPI_SBS_COMPONENT 0x00100000
ACPI_FAN_COMPONENT 0x00200000
ACPI_PCI_COMPONENT 0x00400000
ACPI_CONTAINER_COMPONENT 0x01000000
ACPI_SYSTEM_COMPONENT 0x02000000
ACPI_MEMORY_DEVICE_COMPONENT 0x08000000
@ -126,10 +125,6 @@ AML) during boot::
acpi.debug_layer=0xffffffff acpi.debug_level=0x2
Enable PCI and PCI interrupt routing debug messages::
acpi.debug_layer=0x400000 acpi.debug_level=0x4
Enable all ACPI hardware-related messages::
acpi.debug_layer=0x2 acpi.debug_level=0xffffffff

View file

@ -9,6 +9,7 @@
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*/
#define pr_fmt(fmt) "ACPI: PCI: " fmt
#include <linux/dmi.h>
#include <linux/kernel.h>
@ -22,11 +23,6 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#define PREFIX "ACPI: "
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME("pci_irq");
struct acpi_prt_entry {
struct acpi_pci_id id;
u8 pin;
@ -126,7 +122,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry,
entry->pin == quirk->pin &&
!strcmp(prt->source, quirk->source) &&
strlen(prt->source) >= strlen(quirk->actual_source)) {
printk(KERN_WARNING PREFIX "firmware reports "
pr_warn("Firmware reports "
"%04x:%02x:%02x PCI INT %c connected to %s; "
"changing to %s\n",
entry->id.segment, entry->id.bus,
@ -191,12 +187,9 @@ static int acpi_pci_irq_check_entry(acpi_handle handle, struct pci_dev *dev,
* the IRQ value, which is hardwired to specific interrupt inputs on
* the interrupt controller.
*/
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
" %04x:%02x:%02x[%c] -> %s[%d]\n",
entry->id.segment, entry->id.bus,
entry->id.device, pin_name(entry->pin),
prt->source, entry->index));
pr_debug("%04x:%02x:%02x[%c] -> %s[%d]\n",
entry->id.segment, entry->id.bus, entry->id.device,
pin_name(entry->pin), prt->source, entry->index);
*entry_ptr = entry;
@ -307,8 +300,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
#ifdef CONFIG_X86_IO_APIC
acpi_reroute_boot_interrupt(dev, entry);
#endif /* CONFIG_X86_IO_APIC */
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %s[%c] _PRT entry\n",
pci_name(dev), pin_name(pin)));
dev_dbg(&dev->dev, "Found [%c] _PRT entry\n", pin_name(pin));
return entry;
}
@ -324,9 +316,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
/* PC card has the same IRQ as its cardbridge */
bridge_pin = bridge->pin;
if (!bridge_pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
pci_name(bridge)));
dev_dbg(&bridge->dev, "No interrupt pin configured\n");
return NULL;
}
pin = bridge_pin;
@ -334,10 +324,8 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin)
ret = acpi_pci_irq_find_prt_entry(bridge, pin, &entry);
if (!ret && entry) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Derived GSI for %s INT %c from %s\n",
pci_name(dev), pin_name(orig_pin),
pci_name(bridge)));
dev_dbg(&dev->dev, "Derived GSI INT %c from %s\n",
pin_name(orig_pin), pci_name(bridge));
return entry;
}
@ -413,9 +401,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
pin = dev->pin;
if (!pin) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"No interrupt pin configured for device %s\n",
pci_name(dev)));
dev_dbg(&dev->dev, "No interrupt pin configured\n");
return 0;
}

View file

@ -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)

View file

@ -54,7 +54,6 @@ static const struct acpi_dlayer acpi_debug_layers[] = {
ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT),
ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT),
ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT),
ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT),
ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT),
ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT),

View file

@ -17,7 +17,6 @@
*/
#define ACPI_SBS_COMPONENT 0x00100000
#define ACPI_FAN_COMPONENT 0x00200000
#define ACPI_PCI_COMPONENT 0x00400000
#define ACPI_CONTAINER_COMPONENT 0x01000000
#define ACPI_SYSTEM_COMPONENT 0x02000000
#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000