^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * pci_link.c - ACPI PCI Interrupt Link Device Driver ($Revision: 34 $)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * TBD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 1. Support more than one IRQ resource entry per link device (index).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 2. Implement start/stop mechanism and use ACPI Bus Driver facilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * for IRQ management (e.g. start()->_SRS).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/syscore_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define _COMPONENT ACPI_PCI_COMPONENT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ACPI_MODULE_NAME("pci_link");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ACPI_PCI_LINK_CLASS "pci_irq_routing"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ACPI_PCI_LINK_MAX_POSSIBLE 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int acpi_pci_link_add(struct acpi_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) const struct acpi_device_id *not_used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void acpi_pci_link_remove(struct acpi_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static const struct acpi_device_id link_device_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {"PNP0C0F", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {"", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static struct acpi_scan_handler pci_link_handler = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .ids = link_device_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .attach = acpi_pci_link_add,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .detach = acpi_pci_link_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * If a link is initialized, we never change its active and initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * later even the link is disable. Instead, we just repick the active irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct acpi_pci_link_irq {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u32 active; /* Current IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u8 triggering; /* All IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u8 polarity; /* All IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u8 resource_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u8 possible_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u8 initialized:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 reserved:7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct acpi_pci_link {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct acpi_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct acpi_pci_link_irq irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static LIST_HEAD(acpi_link_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static DEFINE_MUTEX(acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int sci_irq = -1, sci_penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) PCI Link Device Management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * set context (link) possible list from resource list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct acpi_pci_link *link = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) switch (resource->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case ACPI_RESOURCE_TYPE_START_DEPENDENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case ACPI_RESOURCE_TYPE_END_TAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) case ACPI_RESOURCE_TYPE_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct acpi_resource_irq *p = &resource->data.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!p || !p->interrupt_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) "Blank _PRS IRQ resource\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) (i < p->interrupt_count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!p->interrupts[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) "Invalid _PRS IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) p->interrupts[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) link->irq.possible[i] = p->interrupts[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) link->irq.possible_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) link->irq.triggering = p->triggering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) link->irq.polarity = p->polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) link->irq.resource_type = ACPI_RESOURCE_TYPE_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct acpi_resource_extended_irq *p =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) &resource->data.extended_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!p || !p->interrupt_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "Blank _PRS EXT IRQ resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) for (i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (i < p->interrupt_count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!p->interrupts[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "Invalid _PRS IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) p->interrupts[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) link->irq.possible[i] = p->interrupts[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) link->irq.possible_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) link->irq.triggering = p->triggering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) link->irq.polarity = p->polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) resource->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return AE_CTRL_TERMINATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static int acpi_pci_link_get_possible(struct acpi_pci_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) acpi_pci_link_check_possible, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) acpi_handle_debug(link->device->handle, "_PRS not present or invalid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) "Found %d possible IRQs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) link->irq.possible_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void *context)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int *irq = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) switch (resource->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case ACPI_RESOURCE_TYPE_START_DEPENDENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case ACPI_RESOURCE_TYPE_END_TAG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) case ACPI_RESOURCE_TYPE_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct acpi_resource_irq *p = &resource->data.irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!p || !p->interrupt_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * IRQ descriptors may have no IRQ# bits set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * particularly those those w/ _STA disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) "Blank _CRS IRQ resource\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *irq = p->interrupts[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct acpi_resource_extended_irq *p =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) &resource->data.extended_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!p || !p->interrupt_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * extended IRQ descriptors must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) * return at least 1 IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) "Blank _CRS EXT IRQ resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *irq = p->interrupts[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) resource->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return AE_CTRL_TERMINATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * Run _CRS and set link->irq.active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * return value:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * 0 - success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * !0 - failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int acpi_pci_link_get_current(struct acpi_pci_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) int irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) link->irq.active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* in practice, status disabled is meaningless, ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (acpi_strict) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Query _STA, set link->device->status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) result = acpi_bus_get_status(link->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) printk(KERN_ERR PREFIX "Unable to read status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (!link->device->status.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Query and parse _CRS to get the current IRQ assignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) status = acpi_walk_resources(link->device->handle, METHOD_NAME__CRS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) acpi_pci_link_check_current, &irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _CRS"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (acpi_strict && !irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) printk(KERN_ERR PREFIX "_CRS returned 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) link->irq.active = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) acpi_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct acpi_resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct acpi_resource end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) } *resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct acpi_buffer buffer = { 0, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!resource)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) buffer.length = sizeof(*resource) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) buffer.pointer = resource;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) switch (link->irq.resource_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case ACPI_RESOURCE_TYPE_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) resource->res.type = ACPI_RESOURCE_TYPE_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) resource->res.length = sizeof(struct acpi_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) resource->res.data.irq.triggering = link->irq.triggering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) resource->res.data.irq.polarity =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) link->irq.polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) resource->res.data.irq.shareable =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ACPI_EXCLUSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) resource->res.data.irq.shareable = ACPI_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) resource->res.data.irq.interrupt_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) resource->res.data.irq.interrupts[0] = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) resource->res.type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) resource->res.length = sizeof(struct acpi_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) resource->res.data.extended_irq.producer_consumer =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ACPI_CONSUMER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) resource->res.data.extended_irq.triggering =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) link->irq.triggering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) resource->res.data.extended_irq.polarity =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) link->irq.polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if (link->irq.triggering == ACPI_EDGE_SENSITIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) resource->res.data.extended_irq.shareable =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ACPI_EXCLUSIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) resource->res.data.extended_irq.shareable = ACPI_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) resource->res.data.extended_irq.interrupt_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) resource->res.data.extended_irq.interrupts[0] = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* ignore resource_source, it's optional */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) result = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) resource->end.type = ACPI_RESOURCE_TYPE_END_TAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) resource->end.length = sizeof(struct acpi_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* Attempt to set the resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) status = acpi_set_current_resources(link->device->handle, &buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /* check for total failure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SRS"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) result = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* Query _STA, set device->status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) result = acpi_bus_get_status(link->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) printk(KERN_ERR PREFIX "Unable to read status\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (!link->device->status.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "%s [%s] disabled and referenced, BIOS bug\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) acpi_device_name(link->device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) acpi_device_bid(link->device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Query _CRS, set link->irq.active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) result = acpi_pci_link_get_current(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Is current setting not what we set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * set link->irq.active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (link->irq.active != irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * policy: when _CRS doesn't return what we just _SRS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * assume _SRS worked and override _CRS value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) printk(KERN_WARNING PREFIX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) "%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) acpi_device_name(link->device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) acpi_device_bid(link->device), link->irq.active, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) link->irq.active = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) kfree(resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) PCI Link IRQ Management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * "acpi_irq_balance" (default in APIC mode) enables ACPI to use PIC Interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * Link Devices to move the PIRQs around to minimize sharing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * "acpi_irq_nobalance" (default in PIC mode) tells ACPI not to move any PIC IRQs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * that the BIOS has already set to active. This is necessary because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * ACPI has no automatic means of knowing what ISA IRQs are used. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * if the BIOS doesn't set a Link Device active, ACPI needs to program it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * even if acpi_irq_nobalance is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * A tables of penalties avoids directing PCI interrupts to well known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * ISA IRQs. Boot params are available to over-ride the default table:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * List interrupts that are free for PCI use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * acpi_irq_pci=n[,m]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * List interrupts that should not be used for PCI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * acpi_irq_isa=n[,m]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * Note that PCI IRQ routers have a list of possible IRQs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * which may not include the IRQs this table says are available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Since this heuristic can't tell the difference between a link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * that no device will attach to, vs. a link which may be shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * by multiple active devices -- it is not optimal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * If interrupt performance is that important, get an IO-APIC system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * with a pin dedicated to each device. Or for that matter, an MSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * enabled system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) #define ACPI_MAX_ISA_IRQS 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) #define PIRQ_PENALTY_PCI_POSSIBLE (16*16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) #define PIRQ_PENALTY_PCI_USING (16*16*16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ5 sometimes SoundBlaster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 0, /* IRQ9 PCI, often acpi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 0, /* IRQ10 PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 0, /* IRQ11 PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* >IRQ15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static int acpi_irq_pci_sharing_penalty(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int penalty = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) list_for_each_entry(link, &acpi_link_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * If a link is active, penalize its IRQ heavily
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * so we try to choose a different IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (link->irq.active && link->irq.active == irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) penalty += PIRQ_PENALTY_PCI_USING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * penalize the IRQs PCI might use, but not as severely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) for (i = 0; i < link->irq.possible_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (link->irq.possible[i] == irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) penalty += PIRQ_PENALTY_PCI_POSSIBLE /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) link->irq.possible_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) static int acpi_irq_get_penalty(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int penalty = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (irq == sci_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) penalty += sci_penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (irq < ACPI_MAX_ISA_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return penalty + acpi_isa_irq_penalty[irq];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return penalty + acpi_irq_pci_sharing_penalty(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int __init acpi_irq_penalty_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * Update penalties to facilitate IRQ balancing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) list_for_each_entry(link, &acpi_link_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * reflect the possible and active irqs in the penalty table --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * useful for breaking ties.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (link->irq.possible_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int penalty =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) PIRQ_PENALTY_PCI_POSSIBLE /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) link->irq.possible_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) for (i = 0; i < link->irq.possible_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) acpi_isa_irq_penalty[link->irq.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) possible[i]] +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) } else if (link->irq.active &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) (link->irq.active < ACPI_MAX_ISA_IRQS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) acpi_isa_irq_penalty[link->irq.active] +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) PIRQ_PENALTY_PCI_POSSIBLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int acpi_irq_balance = -1; /* 0: static, 1: balance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static int acpi_pci_link_allocate(struct acpi_pci_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (link->irq.initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (link->refcnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* This means the link is disabled but initialized */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) acpi_pci_link_set(link, link->irq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * search for active IRQ in list of possible IRQs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) for (i = 0; i < link->irq.possible_count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (link->irq.active == link->irq.possible[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * forget active IRQ that is not in possible list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (i == link->irq.possible_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (acpi_strict)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) printk(KERN_WARNING PREFIX "_CRS %d not found"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) " in _PRS\n", link->irq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) link->irq.active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * if active found, use it; else pick entry from end of possible list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (link->irq.active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) irq = link->irq.active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) irq = link->irq.possible[link->irq.possible_count - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (acpi_irq_balance || !link->irq.active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * Select the best IRQ. This is done in reverse to promote
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) * the use of IRQs 9, 10, 11, and >15.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) for (i = (link->irq.possible_count - 1); i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (acpi_irq_get_penalty(irq) >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) acpi_irq_get_penalty(link->irq.possible[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) irq = link->irq.possible[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) "Try pci=noacpi or acpi=off\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) acpi_device_name(link->device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) acpi_device_bid(link->device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* Attempt to enable the link device at this IRQ. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (acpi_pci_link_set(link, irq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) printk(KERN_ERR PREFIX "Unable to set IRQ for %s [%s]. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) "Try pci=noacpi or acpi=off\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) acpi_device_name(link->device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) acpi_device_bid(link->device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (link->irq.active < ACPI_MAX_ISA_IRQS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) acpi_isa_irq_penalty[link->irq.active] +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) PIRQ_PENALTY_PCI_USING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) pr_info("%s [%s] enabled at IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) acpi_device_name(link->device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) acpi_device_bid(link->device), link->irq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) link->irq.initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * acpi_pci_link_allocate_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * success: return IRQ >= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * failure: return -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) int *polarity, char **name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct acpi_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) result = acpi_bus_get_device(handle, &device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) printk(KERN_ERR PREFIX "Invalid link device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) link = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (!link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) printk(KERN_ERR PREFIX "Invalid link context\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) /* TBD: Support multiple index (IRQ) entries per Link Device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) printk(KERN_ERR PREFIX "Invalid index %d\n", index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) mutex_lock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (acpi_pci_link_allocate(link)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!link->irq.active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) link->refcnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (triggering)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) *triggering = link->irq.triggering;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) *polarity = link->irq.polarity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *name = acpi_device_bid(link->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) "Link %s is referenced\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) acpi_device_bid(link->device)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return link->irq.active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * We don't change link's irq information here. After it is reenabled, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * continue use the info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int acpi_pci_link_free_irq(acpi_handle handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct acpi_device *device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) acpi_status result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) result = acpi_bus_get_device(handle, &device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) printk(KERN_ERR PREFIX "Invalid link device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) link = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (!link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) printk(KERN_ERR PREFIX "Invalid link context\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) mutex_lock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (!link->irq.initialized) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) printk(KERN_ERR PREFIX "Link isn't initialized\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) #ifdef FUTURE_USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * The Link reference count allows us to _DISable an unused link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * and suspend time, and set it again on resume.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * However, 2.6.12 still has irq_router.resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * which blindly restores the link state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * So we disable the reference count method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * to prevent duplicate acpi_pci_link_set()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * which would harm some systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) link->refcnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ACPI_DEBUG_PRINT((ACPI_DB_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) "Link %s is dereferenced\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) acpi_device_bid(link->device)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (link->refcnt == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return link->irq.active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /* --------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) Driver Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) -------------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int acpi_pci_link_add(struct acpi_device *device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) const struct acpi_device_id *not_used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int found = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) link->device = device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) device->driver_data = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) mutex_lock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) result = acpi_pci_link_get_possible(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) goto end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* query and set link->irq.active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) acpi_pci_link_get_current(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) acpi_device_bid(device));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) for (i = 0; i < link->irq.possible_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if (link->irq.active == link->irq.possible[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) printk(KERN_CONT " *%d", link->irq.possible[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) found = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) printk(KERN_CONT " %d", link->irq.possible[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) printk(KERN_CONT ")");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (!found)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) printk(KERN_CONT " *%d", link->irq.active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (!link->device->status.enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) printk(KERN_CONT ", disabled.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) printk(KERN_CONT "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) list_add_tail(&link->list, &acpi_link_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) /* disable all links -- to be activated on use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) acpi_evaluate_object(device->handle, "_DIS", NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return result < 0 ? result : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) static int acpi_pci_link_resume(struct acpi_pci_link *link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (link->refcnt && link->irq.active && link->irq.initialized)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return (acpi_pci_link_set(link, link->irq.active));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) static void irqrouter_resume(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) list_for_each_entry(link, &acpi_link_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) acpi_pci_link_resume(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static void acpi_pci_link_remove(struct acpi_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) struct acpi_pci_link *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) link = acpi_driver_data(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) mutex_lock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) list_del(&link->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) mutex_unlock(&acpi_link_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) kfree(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * modify acpi_isa_irq_penalty[] from cmdline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int __init acpi_irq_penalty_update(char *str, int used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) int new_penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) retval = get_option(&str, &irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (!retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) break; /* no number found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) /* see if this is a ISA IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) new_penalty = acpi_isa_irq_penalty[irq] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) PIRQ_PENALTY_ISA_USED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) new_penalty = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) acpi_isa_irq_penalty[irq] = new_penalty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (retval != 2) /* no next number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * We'd like PNP to call this routine for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * single ISA_USED value for each legacy device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * But instead it calls us with each POSSIBLE setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * There is no ISA_POSSIBLE weight, so we simply use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * the (small) PCI_USING penalty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) void acpi_penalize_isa_irq(int irq, int active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) acpi_isa_irq_penalty[irq] +=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) bool acpi_isa_irq_available(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) sci_irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (trigger == ACPI_MADT_TRIGGER_LEVEL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) polarity == ACPI_MADT_POLARITY_ACTIVE_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) sci_penalty = PIRQ_PENALTY_PCI_USING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) sci_penalty = PIRQ_PENALTY_ISA_ALWAYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * Over-ride default table to reserve additional IRQs for use by ISA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * e.g. acpi_irq_isa=5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * Useful for telling ACPI how not to interfere with your ISA sound card.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static int __init acpi_irq_isa(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) return acpi_irq_penalty_update(str, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) __setup("acpi_irq_isa=", acpi_irq_isa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * Over-ride default table to free additional IRQs for use by PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * e.g. acpi_irq_pci=7,15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * Used for acpi_irq_balance to free up IRQs to reduce PCI IRQ sharing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int __init acpi_irq_pci(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return acpi_irq_penalty_update(str, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) __setup("acpi_irq_pci=", acpi_irq_pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static int __init acpi_irq_nobalance_set(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) acpi_irq_balance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) __setup("acpi_irq_nobalance", acpi_irq_nobalance_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) static int __init acpi_irq_balance_set(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) acpi_irq_balance = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) __setup("acpi_irq_balance", acpi_irq_balance_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static struct syscore_ops irqrouter_syscore_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .resume = irqrouter_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) void __init acpi_pci_link_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (acpi_noirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (acpi_irq_balance == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /* no command line switch: enable balancing in IOAPIC mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) acpi_irq_balance = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) acpi_irq_balance = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) register_syscore_ops(&irqrouter_syscore_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) acpi_scan_add_handler(&pci_link_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }