On Tue, Jan 10, 2017 at 10:41 AM, Borislav Petkov <bp@xxxxxxxxx> wrote: > On Tue, Jan 10, 2017 at 02:27:16AM +0100, Rafael J. Wysocki wrote: >> Well, if the https://patchwork.kernel.org/patch/9504277/ patch from Lv >> worked, the attached one should work too (please test), but it can be >> justified in a slightly more convincing way. > > No workie: > > diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c > index 57fb5f4..acb6118 100644 > --- a/drivers/acpi/osl.c > +++ b/drivers/acpi/osl.c > @@ -378,7 +378,11 @@ static void acpi_os_drop_map_ref(struct acpi_ioremap *map) > static void acpi_os_map_cleanup(struct acpi_ioremap *map) > { > if (!map->refcount) { > - synchronize_rcu_expedited(); > + if (acpi_os_initialized) { > + pr_err("%s: acpi_os_initialized\n", __func__); > + synchronize_rcu_expedited(); > + } > + > acpi_unmap(map->phys, map->virt); > kfree(map); > } > > The pr_err() gets issued before the box hangs. > > Lv's version which set the bool in acpi_os_map_generic_address() did > work though. Well, it would if nothing mapped by acpi_os_map_generic_address() was in the memory address space, for example, but then it would never use the RCU synchronization as well (not good). Basically, we need to find a point during the initialization such that acpi_os_read/write_memory() is not invoked earlier and set a flag in there. Let's try the attached one. BTW, I'm going to travel to the LCA starting tomorrow, so I guess I will be a bit unresponsive during the next few days. Thanks, Rafael
--- drivers/acpi/bus.c | 6 ++++++ drivers/acpi/osl.c | 9 ++++++++- include/acpi/acpi_io.h | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) Index: linux-pm/drivers/acpi/bus.c =================================================================== --- linux-pm.orig/drivers/acpi/bus.c +++ linux-pm/drivers/acpi/bus.c @@ -1191,6 +1191,12 @@ static int __init acpi_init(void) acpi_kobj = NULL; } + /* + * acpi_os_read_memory()/acpi_os_write_memory() should not be invoked + * before this point. + */ + acpi_sync_memory_unmap = true; + init_acpi_device_notify(); result = acpi_bus_init(); if (result) { Index: linux-pm/drivers/acpi/osl.c =================================================================== --- linux-pm.orig/drivers/acpi/osl.c +++ linux-pm/drivers/acpi/osl.c @@ -77,6 +77,7 @@ static struct workqueue_struct *kacpi_ho static bool acpi_os_initialized; unsigned int acpi_sci_irq = INVALID_ACPI_IRQ; bool acpi_permanent_mmap = false; +bool acpi_sync_memory_unmap; /* * This list of permanent mappings is for memory that may be accessed from @@ -378,7 +379,9 @@ static void acpi_os_drop_map_ref(struct static void acpi_os_map_cleanup(struct acpi_ioremap *map) { if (!map->refcount) { - synchronize_rcu_expedited(); + if (acpi_sync_memory_unmap) + synchronize_rcu_expedited(); + acpi_unmap(map->phys, map->virt); kfree(map); } @@ -671,6 +674,8 @@ acpi_os_read_memory(acpi_physical_addres bool unmap = false; u64 dummy; + WARN_ON_ONCE(!acpi_sync_memory_unmap); + rcu_read_lock(); virt_addr = acpi_map_vaddr_lookup(phys_addr, size); if (!virt_addr) { @@ -716,6 +721,8 @@ acpi_os_write_memory(acpi_physical_addre unsigned int size = width / 8; bool unmap = false; + WARN_ON_ONCE(!acpi_sync_memory_unmap); + rcu_read_lock(); virt_addr = acpi_map_vaddr_lookup(phys_addr, size); if (!virt_addr) { Index: linux-pm/include/acpi/acpi_io.h =================================================================== --- linux-pm.orig/include/acpi/acpi_io.h +++ linux-pm/include/acpi/acpi_io.h @@ -14,6 +14,7 @@ static inline void __iomem *acpi_os_iore #endif extern bool acpi_permanent_mmap; +extern bool acpi_sync_memory_unmap; void __iomem *__ref acpi_os_map_iomem(acpi_physical_address phys, acpi_size size);