ACPI fixes for v4.7-rc7

- Fix a lock ordering issue in ACPICA introduced by a recent commit
    that attempted to fix a deadlock in the dynamic table loading code
    which in turn appeared after changes related to the handling of
    module-level AML also made in this cycle (Lv Zheng).
 
  - Fix a recent regression in the ACPI IRQ management code that may
    cause PCI drivers to be unable to register an IRQ if that IRQ
    happens to be shared with a device on the ISA bus, like the
    parallel port, by reverting one commit entirely and restoring the
    previous behavior in two other places (Sinan Kaya).
 
  - Fix a recent regression in the ACPI AML debugger introduced by
    the commit that removed incorrect usage of IS_ERR_VALUE() from
    multiple places (Lv Zheng).
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCAAGBQJXfuIeAAoJEILEb/54YlRxWbIP/iLT8J15RhFOoRYX4HXyULym
 UxeqEHVySKaqQLYhkBRz0opclW6sJQ7GaKYpVR31V4eeoll1+iQeYBYWdyuezjwp
 em3LvtLXTiLWWfRVNHg9AUOv4wc4q41m98MZ5ZScgTsUcexv2R1tt0KzLE/HNy1T
 NU/7JyWBEF4AiFsfYBuqtknWudV7JF3/siJO+Q1o+HSA9DW5cdqR0K9oM+Sl9pTD
 3yLpVY8DNJGLSA/7MyJlyLmZ6eJmTQbxcLO7oCQliqJ9jjBKkC4r3fgfQcOcoltT
 S6O7ODcJwvqCA1sv271VyOckkhJmyT7zJi/L/yJOgiGRU1//0Vfyg6iRVou9OZmE
 VcQT79W+6W6saWucoNDX1CLm6GzLIHP2e6leooL710nNmtTUgrSc6C4FT1KGGs0R
 UTNPYKYtiaK54krsa48XonSCdGFIszeK8sa3DIjf6C/5AYX/eGBuGFm5dZlU/qzs
 BNv+GyT/Vt/Cu3cNJUrsMugwDL5sp31u44mfM1c99LMXmnwzkPylRGR1aaO4TYOy
 jE5LDwMryi5gpAF8/Es0AiU4Xa8O3p+AlD7PjZIUSEyMd9zr3fdpvF6dZwaiHP26
 FX6paRbXi10mkXYGnRCbTOBV8i3PuNiplaZUT+XotHlEXOvAyMhVCVSM2XCAo1Wm
 3IWSGzc5gwq1Pl4fihWi
 =vKn9
 -----END PGP SIGNATURE-----

Merge tag 'acpi-4.7-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI fixes from Rafael Wysocki:
 "All of these fix recent regressions in ACPICA, in the ACPI PCI IRQ
  management code and in the ACPI AML debugger.

  Specifics:

   - Fix a lock ordering issue in ACPICA introduced by a recent commit
     that attempted to fix a deadlock in the dynamic table loading code
     which in turn appeared after changes related to the handling of
     module-level AML also made in this cycle (Lv Zheng).

   - Fix a recent regression in the ACPI IRQ management code that may
     cause PCI drivers to be unable to register an IRQ if that IRQ
     happens to be shared with a device on the ISA bus, like the
     parallel port, by reverting one commit entirely and restoring the
     previous behavior in two other places (Sinan Kaya).

   - Fix a recent regression in the ACPI AML debugger introduced by the
     commit that removed incorrect usage of IS_ERR_VALUE() from multiple
     places (Lv Zheng)"

* tag 'acpi-4.7-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / debugger: Fix regression introduced by IS_ERR_VALUE() removal
  ACPICA: Namespace: Fix namespace/interpreter lock ordering
  ACPI,PCI,IRQ: separate ISA penalty calculation
  Revert "ACPI, PCI, IRQ: remove redundant code in acpi_irq_penalty_init()"
  ACPI,PCI,IRQ: factor in PCI possible
This commit is contained in:
Linus Torvalds 2016-07-07 20:49:41 -07:00
commit 7ed18e2d1b
6 changed files with 59 additions and 24 deletions

View File

@ -396,6 +396,7 @@ int __init pci_acpi_init(void)
return -ENODEV; return -ENODEV;
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n"); printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
acpi_irq_penalty_init();
pcibios_enable_irq = acpi_pci_irq_enable; pcibios_enable_irq = acpi_pci_irq_enable;
pcibios_disable_irq = acpi_pci_irq_disable; pcibios_disable_irq = acpi_pci_irq_disable;
x86_init.pci.init_irq = x86_init_noop; x86_init.pci.init_irq = x86_init_noop;

View File

@ -602,7 +602,7 @@ static int acpi_aml_read_user(char __user *buf, int len)
crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1); crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
ret = n; ret = n;
out: out:
acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !ret); acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, ret >= 0);
return ret; return ret;
} }
@ -672,7 +672,7 @@ static int acpi_aml_write_user(const char __user *buf, int len)
crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1); crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
ret = n; ret = n;
out: out:
acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !ret); acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0);
return n; return n;
} }

View File

@ -46,6 +46,7 @@
#include "acnamesp.h" #include "acnamesp.h"
#include "acdispat.h" #include "acdispat.h"
#include "actables.h" #include "actables.h"
#include "acinterp.h"
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsload") ACPI_MODULE_NAME("nsload")
@ -78,6 +79,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
ACPI_FUNCTION_TRACE(ns_load_table); ACPI_FUNCTION_TRACE(ns_load_table);
acpi_ex_enter_interpreter();
/* /*
* Parse the table and load the namespace with all named * Parse the table and load the namespace with all named
* objects found within. Control methods are NOT parsed * objects found within. Control methods are NOT parsed
@ -89,7 +92,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
*/ */
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); goto unlock_interp;
} }
/* If table already loaded into namespace, just return */ /* If table already loaded into namespace, just return */
@ -130,6 +133,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
unlock: unlock:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
unlock_interp:
(void)acpi_ex_exit_interpreter();
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);

View File

@ -47,7 +47,6 @@
#include "acparser.h" #include "acparser.h"
#include "acdispat.h" #include "acdispat.h"
#include "actables.h" #include "actables.h"
#include "acinterp.h"
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsparse") ACPI_MODULE_NAME("nsparse")
@ -171,8 +170,6 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
ACPI_FUNCTION_TRACE(ns_parse_table); ACPI_FUNCTION_TRACE(ns_parse_table);
acpi_ex_enter_interpreter();
/* /*
* AML Parse, pass 1 * AML Parse, pass 1
* *
@ -188,7 +185,7 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
table_index, start_node); table_index, start_node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; return_ACPI_STATUS(status);
} }
/* /*
@ -204,10 +201,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2,
table_index, start_node); table_index, start_node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
goto error_exit; return_ACPI_STATUS(status);
} }
error_exit:
acpi_ex_exit_interpreter();
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }

View File

@ -470,6 +470,7 @@ static int acpi_irq_pci_sharing_penalty(int irq)
{ {
struct acpi_pci_link *link; struct acpi_pci_link *link;
int penalty = 0; int penalty = 0;
int i;
list_for_each_entry(link, &acpi_link_list, list) { list_for_each_entry(link, &acpi_link_list, list) {
/* /*
@ -478,18 +479,14 @@ static int acpi_irq_pci_sharing_penalty(int irq)
*/ */
if (link->irq.active && link->irq.active == irq) if (link->irq.active && link->irq.active == irq)
penalty += PIRQ_PENALTY_PCI_USING; penalty += PIRQ_PENALTY_PCI_USING;
else {
int i;
/* /*
* If a link is inactive, penalize the IRQs it * penalize the IRQs PCI might use, but not as severely.
* might use, but not as severely. */
*/ for (i = 0; i < link->irq.possible_count; i++)
for (i = 0; i < link->irq.possible_count; i++) if (link->irq.possible[i] == irq)
if (link->irq.possible[i] == irq) penalty += PIRQ_PENALTY_PCI_POSSIBLE /
penalty += PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count;
link->irq.possible_count;
}
} }
return penalty; return penalty;
@ -499,9 +496,6 @@ static int acpi_irq_get_penalty(int irq)
{ {
int penalty = 0; 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 * 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 * with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
@ -516,10 +510,49 @@ static int acpi_irq_get_penalty(int irq)
penalty += PIRQ_PENALTY_PCI_USING; penalty += PIRQ_PENALTY_PCI_USING;
} }
if (irq < ACPI_MAX_ISA_IRQS)
return penalty + acpi_isa_irq_penalty[irq];
penalty += acpi_irq_pci_sharing_penalty(irq); penalty += acpi_irq_pci_sharing_penalty(irq);
return penalty; return penalty;
} }
int __init acpi_irq_penalty_init(void)
{
struct acpi_pci_link *link;
int i;
/*
* 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 (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_IRQS)
acpi_isa_irq_penalty[link->irq.
possible[i]] +=
penalty;
}
} else if (link->irq.active &&
(link->irq.active < ACPI_MAX_ISA_IRQS)) {
acpi_isa_irq_penalty[link->irq.active] +=
PIRQ_PENALTY_PCI_POSSIBLE;
}
}
return 0;
}
static int acpi_irq_balance = -1; /* 0: static, 1: balance */ static int acpi_irq_balance = -1; /* 0: static, 1: balance */
static int acpi_pci_link_allocate(struct acpi_pci_link *link) static int acpi_pci_link_allocate(struct acpi_pci_link *link)

View File

@ -78,6 +78,7 @@
/* ACPI PCI Interrupt Link (pci_link.c) */ /* ACPI PCI Interrupt Link (pci_link.c) */
int acpi_irq_penalty_init(void);
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
int *polarity, char **name); int *polarity, char **name);
int acpi_pci_link_free_irq(acpi_handle handle); int acpi_pci_link_free_irq(acpi_handle handle);