• James Morse's avatar
    firmware: arm_sdei: fix double-lock on hibernate with shared events · 6ded0b61
    James Morse authored
    SDEI has private events that must be registered on each CPU. When
    CPUs come and go they must re-register and re-enable their private
    events. Each event has flags to indicate whether this should happen
    to protect against an event being registered on a CPU coming online,
    while all the others are unregistering the event.
    
    These flags are protected by the sdei_list_lock spinlock, because
    the cpuhp callbacks can't take the mutex.
    
    Hibernate needs to unregister all events, but keep the in-memory
    re-register and re-enable as they are. sdei_unregister_shared()
    takes the spinlock to walk the list, then calls _sdei_event_unregister()
    on each shared event. _sdei_event_unregister() tries to take the
    same spinlock to update re-register and re-enable. This doesn't go
    so well.
    
    Push the re-register and re-enable updates out to their callers.
    sdei_unregister_shared() doesn't want these values updated, so
    doesn't need to do anything.
    
    This also fixes shared events getting lost over hibernate as this
    path made them look unregistered.
    
    Fixes: da351827 ("firmware: arm_sdei: Add support for CPU and system power states")
    Reported-by: default avatarLiguang Zhang <zhangliguang@linux.alibaba.com>
    Signed-off-by: default avatarJames Morse <james.morse@arm.com>
    Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    6ded0b61
arm_sdei.c 24.7 KB