Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: OSL: Allow Notify () handlers to run on all CPUs

Notify () handlers, like GPE handlers, are only allowed to run on CPU0
now out of the concern that they might trigger an SMM trap leading to
memory corruption. Namely, in some cases, SMM code might corrupt memory
if not run on CPU0.

However, Notify () handlers are registered by kernel code and they
are not likely to evaluate AML that would trigger an SMM trap. In
fact, many of them don't even evaluate any AML at all and even if
they do, that AML may as well be evaluated in other code paths. In
other words, they are not special from the AML evaluation perspective,
so there is no real reason to treat them in any special way.

Accordingly, allow Notify () handlers, unlike GPE handlers, to be
executed by all CPUs in the system.

Also adjust the allocation of the "notify" workqueue to allow multiple
handlers to be executed at the same time, because they need not be
serialized.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

+10 -13
+10 -13
drivers/acpi/osl.c
··· 1061 1061 acpi_osd_exec_callback function, void *context) 1062 1062 { 1063 1063 struct acpi_os_dpc *dpc; 1064 - struct workqueue_struct *queue; 1065 1064 int ret; 1066 1065 1067 1066 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, ··· 1100 1101 */ 1101 1102 switch (type) { 1102 1103 case OSL_NOTIFY_HANDLER: 1103 - queue = kacpi_notify_wq; 1104 + ret = queue_work(kacpi_notify_wq, &dpc->work); 1104 1105 break; 1105 1106 case OSL_GPE_HANDLER: 1106 - queue = kacpid_wq; 1107 + /* 1108 + * On some machines, a software-initiated SMI causes corruption 1109 + * unless the SMI runs on CPU 0. An SMI can be initiated by 1110 + * any AML, but typically it's done in GPE-related methods that 1111 + * are run via workqueues, so we can avoid the known corruption 1112 + * cases by always queueing on CPU 0. 1113 + */ 1114 + ret = queue_work_on(0, kacpid_wq, &dpc->work); 1107 1115 break; 1108 1116 default: 1109 1117 pr_err("Unsupported os_execute type %d.\n", type); 1110 1118 goto err; 1111 1119 } 1112 - 1113 - /* 1114 - * On some machines, a software-initiated SMI causes corruption unless 1115 - * the SMI runs on CPU 0. An SMI can be initiated by any AML, but 1116 - * typically it's done in GPE-related methods that are run via 1117 - * workqueues, so we can avoid the known corruption cases by always 1118 - * queueing on CPU 0. 1119 - */ 1120 - ret = queue_work_on(0, queue, &dpc->work); 1121 1120 if (!ret) { 1122 1121 pr_err("Unable to queue work\n"); 1123 1122 goto err; ··· 1665 1668 acpi_status __init acpi_os_initialize1(void) 1666 1669 { 1667 1670 kacpid_wq = alloc_workqueue("kacpid", 0, 1); 1668 - kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); 1671 + kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 0); 1669 1672 kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); 1670 1673 BUG_ON(!kacpid_wq); 1671 1674 BUG_ON(!kacpi_notify_wq);