diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 19:41:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-16 19:41:41 -0700 |
commit | 46c13450624e36302547a2ac3695f2350fe7ffc3 (patch) | |
tree | e0454dae2c92873d193e8f9d8afeb920e3b0576a /drivers/acpi/pci_link.c | |
parent | d57d39431924d1628ac9b93a2de7f806fc80680a (diff) | |
parent | fc723957801465c4a911d0a509709f0f8b91aa8a (diff) |
Merge tag 'acpi-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI updates from Rafael Wysocki:
"The new features here are ACPI 6.1 support (and some previously
missing bits of ACPI 6.0 support) in ACPICA and two new drivers, a
driver for the ACPI Generic Event Device (GED) feature introduced by
ACPI 6.1 and the INT3406 thermal driver for display thermal
management. Also the value returned by the _HRV (hardware revision)
ACPI object will be exported to user space via sysfs now.
In addition to that, ACPI on ARM64 will not depend on EXPERT any more.
The rest is mostly fixes and cleanups and some code reorganization.
Specifics:
- In-kernel ACPICA code update to the upstream release 20160422
adding support for ACPI 6.1 along with some previously missing bits
of ACPI 6.0 support, making a fair amount of fixes and cleanups and
reducing divergences between the upstream ACPICA and the in-kernel
code (Bob Moore, Lv Zheng, Al Stone, Aleksey Makarov, Will Miles)
- ACPI Generic Event Device (GED) support and a fix for it (Sinan
Kaya, Paul Gortmaker)
- INT3406 thermal driver for display thermal management and ACPI
backlight support code reorganization related to it (Aaron Lu, Arnd
Bergmann)
- Support for exporting the value returned by the _HRV (hardware
revision) ACPI object via sysfs (Betty Dall)
- Removal of the EXPERT dependency for ACPI on ARM64 (Mark Brown)
- Rework of the handling of ACPI _OSI mechanism allowing the
_OSI("Darwin") support to be overridden from the kernel command
line among other things (Lv Zheng, Chen Yu)
- Rework of the ACPI tables override mechanism to prepare it for the
introduction of overlays support going forward (Lv Zheng, Rafael
Wysocki)
- Fixes related to the ECDT support and module-level execution of AML
(Lv Zheng)
- ACPI PCI interrupts management update to make it work better on
ARM64 mostly (Sinan Kaya)
- ACPI SRAT handling update to make the code process all entires in
the table order regardless of the entry type (Lukasz Anaczkowski)
- EFI power off support for full-hardware ACPI platforms that don't
support ACPI S5 (Chen Yu)
- Fixes and cleanups related to the ACPI core's sysfs interface (Dan
Carpenter, Betty Dall)
- acpi_dev_present() API rework to reduce possible confusion related
to it (Lukas Wunner)
- Removal of CLK_IS_ROOT from two ACPI drivers (Stephen Boyd)"
* tag 'acpi-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (82 commits)
ACPI / video: mark acpi_video_get_levels() inline
Thermal / ACPI / video: add INT3406 thermal driver
ACPI / GED: make evged.c explicitly non-modular
ACPI / tables: Fix DSDT override mechanism
ACPI / sysfs: fix error code in get_status()
ACPICA: Update version to 20160422
ACPICA: Move all ASCII utilities to a common file
ACPICA: ACPI 2.0, Hardware: Add access_width/bit_offset support for acpi_hw_write()
ACPICA: ACPI 2.0, Hardware: Add access_width/bit_offset support in acpi_hw_read()
ACPICA: Executer: Introduce a set of macros to handle bit width mask generation
ACPICA: Hardware: Add optimized access bit width support
ACPICA: Utilities: Add ACPI_IS_ALIGNED() macro
ACPICA: Renamed some #defined flag constants for clarity
ACPICA: ACPI 6.0, tools/iasl: Add support for new resource descriptors
ACPICA: ACPI 6.0: Update _BIX support for new package element
ACPICA: ACPI 6.1: Support for new PCCT subtable
ACPICA: Refactor evaluate_object to reduce nesting
ACPICA: Divergence: remove unwanted spaces for typedef
ACPI,PCI,IRQ: remove SCI penalize function
ACPI,PCI,IRQ: remove redundant code in acpi_irq_penalty_init()
..
Diffstat (limited to 'drivers/acpi/pci_link.c')
-rw-r--r-- | drivers/acpi/pci_link.c | 131 |
1 files changed, 65 insertions, 66 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index ededa909df2f..8fc7323ed3e8 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -36,6 +36,7 @@ #include <linux/mutex.h> #include <linux/slab.h> #include <linux/acpi.h> +#include <linux/irq.h> #include "internal.h" @@ -437,17 +438,15 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) * enabled system. */ -#define ACPI_MAX_IRQS 256 -#define ACPI_MAX_ISA_IRQ 16 +#define ACPI_MAX_ISA_IRQS 16 -#define PIRQ_PENALTY_PCI_AVAILABLE (0) #define PIRQ_PENALTY_PCI_POSSIBLE (16*16) #define PIRQ_PENALTY_PCI_USING (16*16*16) #define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) -static int acpi_irq_penalty[ACPI_MAX_IRQS] = { +static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = { PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ @@ -457,9 +456,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ - PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ + 0, /* IRQ9 PCI, often acpi */ + 0, /* IRQ10 PCI */ + 0, /* IRQ11 PCI */ PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ @@ -467,39 +466,58 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { /* >IRQ15 */ }; -int __init acpi_irq_penalty_init(void) +static int acpi_irq_pci_sharing_penalty(int irq) { struct acpi_pci_link *link; - int i; + int penalty = 0; - /* - * Update penalties to facilitate IRQ balancing. - */ list_for_each_entry(link, &acpi_link_list, list) { - /* - * reflect the possible and active irqs in the penalty table -- - * useful for breaking ties. + * If a link is active, penalize its IRQ heavily + * so we try to choose a different IRQ. */ - 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_IRQ) - acpi_irq_penalty[link->irq. - possible[i]] += - penalty; - } - - } else if (link->irq.active) { - acpi_irq_penalty[link->irq.active] += - PIRQ_PENALTY_PCI_POSSIBLE; + if (link->irq.active && link->irq.active == irq) + penalty += PIRQ_PENALTY_PCI_USING; + else { + int i; + + /* + * If a link is inactive, penalize the IRQs it + * might use, but not as severely. + */ + for (i = 0; i < link->irq.possible_count; i++) + if (link->irq.possible[i] == irq) + penalty += PIRQ_PENALTY_PCI_POSSIBLE / + link->irq.possible_count; } } - return 0; + return penalty; +} + +static int acpi_irq_get_penalty(int irq) +{ + int penalty = 0; + + if (irq < ACPI_MAX_ISA_IRQS) + penalty += acpi_isa_irq_penalty[irq]; + + /* + * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict + * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be + * use for PCI IRQs. + */ + if (irq == acpi_gbl_FADT.sci_interrupt) { + u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK; + + if (type != IRQ_TYPE_LEVEL_LOW) + penalty += PIRQ_PENALTY_ISA_ALWAYS; + else + penalty += PIRQ_PENALTY_PCI_USING; + } + + penalty += acpi_irq_pci_sharing_penalty(irq); + return penalty; } static int acpi_irq_balance = -1; /* 0: static, 1: balance */ @@ -547,12 +565,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * the use of IRQs 9, 10, 11, and >15. */ for (i = (link->irq.possible_count - 1); i >= 0; i--) { - if (acpi_irq_penalty[irq] > - acpi_irq_penalty[link->irq.possible[i]]) + if (acpi_irq_get_penalty(irq) > + acpi_irq_get_penalty(link->irq.possible[i])) irq = link->irq.possible[i]; } } - if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { + 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), @@ -568,7 +586,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) acpi_device_bid(link->device)); return -ENODEV; } else { - acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); @@ -778,7 +795,7 @@ static void acpi_pci_link_remove(struct acpi_device *device) } /* - * modify acpi_irq_penalty[] from cmdline + * modify acpi_isa_irq_penalty[] from cmdline */ static int __init acpi_irq_penalty_update(char *str, int used) { @@ -787,23 +804,24 @@ static int __init acpi_irq_penalty_update(char *str, int used) for (i = 0; i < 16; i++) { int retval; int irq; + int new_penalty; retval = get_option(&str, &irq); if (!retval) break; /* no number found */ - if (irq < 0) - continue; - - if (irq >= ARRAY_SIZE(acpi_irq_penalty)) + /* see if this is a ISA IRQ */ + if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS)) continue; if (used) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + new_penalty = acpi_irq_get_penalty(irq) + + PIRQ_PENALTY_ISA_USED; else - acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; + new_penalty = 0; + acpi_isa_irq_penalty[irq] = new_penalty; if (retval != 2) /* no next number */ break; } @@ -819,34 +837,15 @@ static int __init acpi_irq_penalty_update(char *str, int used) */ void acpi_penalize_isa_irq(int irq, int active) { - if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { - if (active) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; - else - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; - } + if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty))) + acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) + + active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING; } bool acpi_isa_irq_available(int irq) { - return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || - acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); -} - -/* - * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with - * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for - * PCI IRQs. - */ -void acpi_penalize_sci_irq(int irq, int trigger, int polarity) -{ - if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { - if (trigger != ACPI_MADT_TRIGGER_LEVEL || - polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS; - else - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; - } + return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) || + acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); } /* |