• Duoming Zhou's avatar
    usb: chipidea: fix deadlock in ci_otg_del_timer · 7a58b8d6
    Duoming Zhou authored
    There is a deadlock in ci_otg_del_timer(), the process is
    shown below:
    
        (thread 1)                  |        (thread 2)
    ci_otg_del_timer()              | ci_otg_hrtimer_func()
      ...                           |
      spin_lock_irqsave() //(1)     |  ...
      ...                           |
      hrtimer_cancel()              |  spin_lock_irqsave() //(2)
      (block forever)
    
    We hold ci->lock in position (1) and use hrtimer_cancel() to
    wait ci_otg_hrtimer_func() to stop, but ci_otg_hrtimer_func()
    also need ci->lock in position (2). As a result, the
    hrtimer_cancel() in ci_otg_del_timer() will be blocked forever.
    
    This patch extracts hrtimer_cancel() from the protection of
    spin_lock_irqsave() in order that the ci_otg_hrtimer_func()
    could obtain the ci->lock.
    
    What`s more, there will be no race happen. Because the
    "next_timer" is always under the protection of
    spin_lock_irqsave() and we only check whether "next_timer"
    equals to NUM_OTG_FSM_TIMERS in the following code.
    
    Fixes: 3a316ec4 ("usb: chipidea: use hrtimer for otg fsm timers")
    Cc: stable <stable@kernel.org>
    Signed-off-by: default avatarDuoming Zhou <duoming@zju.edu.cn>
    Link: https://lore.kernel.org/r/20220918033312.94348-1-duoming@zju.edu.cnSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    7a58b8d6
otg_fsm.c 19.4 KB