Commit bb134ff5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm+acpi-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management and ACPI fixes from Rafael Wysocki:
 "These are two reverts of recent PCI-related ACPI core changes (one of
  which caused some systems to crash on boot and the other was a cleanup
  on top of it) and a devfreq fix for Tegra.

  Specifics:

   - Revert an ACPI core change related to IRQ management in PCI that
     introduced code relying on the use of kmalloc() which turned out to
     also run during early init when that's not available yet and caused
     some systems to crash on boot for this reason along with a cleanup
     on top of it (Rafael Wysocki).

   - Prevent devfreq from flooding the kernel log with useless messages
     on Tegra (which started to happen after some recent changes in the
     devfreq core) by fixing the driver to follow the documentation and
     the core's expectations in its ->target callback (Tomeu Vizoso)"

* tag 'pm+acpi-4.5-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Revert "ACPI, PCI, irq: remove interrupt count restriction"
  Revert "ACPI / PCI: Simplify acpi_penalize_isa_irq()"
  PM / devfreq: tegra: Set freq in rate callback
parents 34d47a77 1711fd9c
......@@ -4,7 +4,6 @@
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
......@@ -438,6 +437,7 @@ 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 PIRQ_PENALTY_PCI_AVAILABLE (0)
......@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
#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_isa_penalty[ACPI_MAX_ISA_IRQ] = {
static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
......@@ -464,68 +464,9 @@ static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
/* >IRQ15 */
};
struct irq_penalty_info {
int irq;
int penalty;
struct list_head node;
};
static LIST_HEAD(acpi_irq_penalty_list);
static int acpi_irq_get_penalty(int irq)
{
struct irq_penalty_info *irq_info;
if (irq < ACPI_MAX_ISA_IRQ)
return acpi_irq_isa_penalty[irq];
list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
if (irq_info->irq == irq)
return irq_info->penalty;
}
return 0;
}
static int acpi_irq_set_penalty(int irq, int new_penalty)
{
struct irq_penalty_info *irq_info;
/* see if this is a ISA IRQ */
if (irq < ACPI_MAX_ISA_IRQ) {
acpi_irq_isa_penalty[irq] = new_penalty;
return 0;
}
/* next, try to locate from the dynamic list */
list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
if (irq_info->irq == irq) {
irq_info->penalty = new_penalty;
return 0;
}
}
/* nope, let's allocate a slot for this IRQ */
irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
if (!irq_info)
return -ENOMEM;
irq_info->irq = irq;
irq_info->penalty = new_penalty;
list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
return 0;
}
static void acpi_irq_add_penalty(int irq, int penalty)
{
int curpen = acpi_irq_get_penalty(irq);
acpi_irq_set_penalty(irq, curpen + penalty);
}
int __init acpi_irq_penalty_init(void)
{
struct acpi_pci_link *link;
......@@ -546,16 +487,15 @@ int __init acpi_irq_penalty_init(void)
link->irq.possible_count;
for (i = 0; i < link->irq.possible_count; i++) {
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
int irqpos = link->irq.possible[i];
acpi_irq_add_penalty(irqpos, penalty);
}
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
acpi_irq_penalty[link->irq.
possible[i]] +=
penalty;
}
} else if (link->irq.active) {
acpi_irq_add_penalty(link->irq.active,
PIRQ_PENALTY_PCI_POSSIBLE);
acpi_irq_penalty[link->irq.active] +=
PIRQ_PENALTY_PCI_POSSIBLE;
}
}
......@@ -607,12 +547,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_get_penalty(irq) >
acpi_irq_get_penalty(link->irq.possible[i]))
if (acpi_irq_penalty[irq] >
acpi_irq_penalty[link->irq.possible[i]])
irq = link->irq.possible[i];
}
}
if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
if (acpi_irq_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),
......@@ -628,8 +568,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
acpi_device_bid(link->device));
return -ENODEV;
} else {
acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
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);
......@@ -839,7 +778,7 @@ static void acpi_pci_link_remove(struct acpi_device *device)
}
/*
* modify penalty from cmdline
* modify acpi_irq_penalty[] from cmdline
*/
static int __init acpi_irq_penalty_update(char *str, int used)
{
......@@ -857,10 +796,13 @@ static int __init acpi_irq_penalty_update(char *str, int used)
if (irq < 0)
continue;
if (irq >= ARRAY_SIZE(acpi_irq_penalty))
continue;
if (used)
acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
else
acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
if (retval != 2) /* no next number */
break;
......@@ -877,15 +819,18 @@ static int __init acpi_irq_penalty_update(char *str, int used)
*/
void acpi_penalize_isa_irq(int irq, int active)
{
if (irq >= 0)
acpi_irq_add_penalty(irq, active ?
PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
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;
}
}
bool acpi_isa_irq_available(int irq)
{
return irq >= 0 &&
(acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
}
/*
......@@ -895,18 +840,13 @@ bool acpi_isa_irq_available(int irq)
*/
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
{
int penalty;
if (irq < 0)
return;
if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
penalty = PIRQ_PENALTY_ISA_ALWAYS;
else
penalty = PIRQ_PENALTY_PCI_USING;
acpi_irq_add_penalty(irq, penalty);
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;
}
}
/*
......
......@@ -500,6 +500,8 @@ static int tegra_devfreq_target(struct device *dev, unsigned long *freq,
clk_set_min_rate(tegra->emc_clock, rate);
clk_set_rate(tegra->emc_clock, 0);
*freq = rate;
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment