• Jiri Kosina's avatar
    ACPI / cpuidle: fix deadlock between cpuidle_lock and cpu_hotplug.lock · d1c06203
    Jiri Kosina authored
    commit 6726655d upstream.
    
    There is a following AB-BA dependency between cpu_hotplug.lock and
    cpuidle_lock:
    
    1) cpu_hotplug.lock -> cpuidle_lock
    enable_nonboot_cpus()
     _cpu_up()
      cpu_hotplug_begin()
       LOCK(cpu_hotplug.lock)
     cpu_notify()
      ...
      acpi_processor_hotplug()
       cpuidle_pause_and_lock()
        LOCK(cpuidle_lock)
    
    2) cpuidle_lock -> cpu_hotplug.lock
    acpi_os_execute_deferred() workqueue
     ...
     acpi_processor_cst_has_changed()
      cpuidle_pause_and_lock()
       LOCK(cpuidle_lock)
      get_online_cpus()
       LOCK(cpu_hotplug.lock)
    
    Fix this by reversing the order acpi_processor_cst_has_changed() does
    thigs -- let it first execute the protection against CPU hotplug by
    calling get_online_cpus() and obtain the cpuidle lock only after that (and
    perform the symmentric change when allowing CPUs hotplug again and
    dropping cpuidle lock).
    
    Spotted by lockdep.
    Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    d1c06203
processor_idle.c 30.4 KB