mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-13 05:54:23 +08:00
Power management and ACPI fixes for v4.5-rc6
- 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). / -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABCAAGBQJW0E8vAAoJEILEb/54YlRxpWsP/3UCPBf+ZNkbUbEmLSi+KVoG Ypa1To8w+J4TxsKwtf6wMew7clKQXzbicNRaetylMgwXMhGil6LcQ7Kzbny4Hzft hga4r95GJM85qI5BvMVvI5Wh3d9ro8LWP1VdPKlNl/yuru3tXGUTI4xij0wcctMH 9bJFTMaMq53H6H1zn7I9qdSP78ysfLNX3FnJ5bfA3svikTZW6ZtXrqzF2utbtvzN IOEbRFSxjDsMVOZ/WRPKAKn7ZCmdRaxSY0cCJbJp0h8fUqBL5Rovf38KQa6lbINu 4W1n9iZ0Ds5pGX4TbwZMNQIYIIjgnq7bd6Il3ebSzH5mbA3F/0OSf94utnAx4qjx HqOIM9Hzs6uCBtHagcacuAApN5PEORKosxTYsxcjAt9D5kIMMgbIbL8ImUWM2WlC rnECNzNhHfCTq1THbjkhH7byz+H1b0sf7RrJZTr+/Zf2ent+J/iLh4HKhZFwUhYZ V5XR0cu8Jj+MObX13mc3ALETWYdLoUhjvWbUJ1KgJqDRog7F05XnXEEgXmcy4cic PgnokgH9XwW6GNbQgKRpoo5x+g7T6KP1VSguVAIB+vzXUoMYECDmMeL4m3s052lp I0gxYcozwkmZcpgb7ProIN08qq5vvnT0QSre2YQIV/oLWMK0L5vD8KaJbKMbRjWQ QPj+Dlt8U2WHr2Xo+P2A =SW0x -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
bb134ff507
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user