Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7ed18e2d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents c09230f3 b6d90158
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -396,6 +396,7 @@ int __init pci_acpi_init(void)
		return -ENODEV;

	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
	acpi_irq_penalty_init();
	pcibios_enable_irq = acpi_pci_irq_enable;
	pcibios_disable_irq = acpi_pci_irq_disable;
	x86_init.pci.init_irq = x86_init_noop;
+2 −2
Original line number Diff line number Diff line
@@ -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);
	ret = n;
out:
	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !ret);
	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, ret >= 0);
	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);
	ret = n;
out:
	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !ret);
	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0);
	return n;
}

+6 −1
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include "acnamesp.h"
#include "acdispat.h"
#include "actables.h"
#include "acinterp.h"

#define _COMPONENT          ACPI_NAMESPACE
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_ex_enter_interpreter();

	/*
	 * Parse the table and load the namespace with all named
	 * 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);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
		goto unlock_interp;
	}

	/* 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:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
unlock_interp:
	(void)acpi_ex_exit_interpreter();

	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
+2 −7
Original line number Diff line number Diff line
@@ -47,7 +47,6 @@
#include "acparser.h"
#include "acdispat.h"
#include "actables.h"
#include "acinterp.h"

#define _COMPONENT          ACPI_NAMESPACE
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_ex_enter_interpreter();

	/*
	 * 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,
					    table_index, start_node);
	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,
					    table_index, start_node);
	if (ACPI_FAILURE(status)) {
		goto error_exit;
		return_ACPI_STATUS(status);
	}

error_exit:
	acpi_ex_exit_interpreter();
	return_ACPI_STATUS(status);
}
+48 −15
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@ static int acpi_irq_pci_sharing_penalty(int irq)
{
	struct acpi_pci_link *link;
	int penalty = 0;
	int i;

	list_for_each_entry(link, &acpi_link_list, list) {
		/*
@@ -478,19 +479,15 @@ static int acpi_irq_pci_sharing_penalty(int irq)
		 */
		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.
		 * penalize the IRQs PCI 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 penalty;
}
@@ -499,9 +496,6 @@ 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
@@ -516,10 +510,49 @@ static int acpi_irq_get_penalty(int irq)
			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);
	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_pci_link_allocate(struct acpi_pci_link *link)
Loading