• Tony Camuso's avatar
    xhci - correct comp_mode_recovery_timer on return from hibernate · 77df9e0b
    Tony Camuso authored
    Commit 71c731a2 (usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP
    Hardware) was a workaround for systems using the SN65LVPE502CP,
    controller, but it introduced a bug in resume from hibernate.
    
    The fix created a timer, comp_mode_recovery_timer, which is deleted from
    a timer list when xhci_suspend() is called. However, the hibernate image,
    including the timer list containing the comp_mode_recovery_timer, had
    already been saved before the timer was deleted.
    
    Upon resume from hibernate, the list containing the comp_mode_recovery_timer
    is restored from the image saved to disk, and xhci_resume(), assuming that
    the timer had been deleted by xhci_suspend(), makes a call to
    compliance_mode_recoery_timer_init(), which creates a new instance of the
    comp_mode_recovery_timer and attempts to place it into the same list in which
    it is already active, thus corrupting the list during the list_add() call.
    
    At this point, a call trace is emitted indicating the list corruption.
    Soon afterward, the system locks up, the watchdog times out, and the
    ensuing NMI crashes the system.
    
    The problem did not occur when resuming from suspend. In suspend, the
    image in RAM remains exactly as it was when xhci_suspend() deleted the
    comp_mode_recovery_timer, so there is no problem when xhci_resume()
    creates a new instance of this timer and places it in the still empty
    list.
    
    This patch avoids the problem by deleting the timer in xhci_resume()
    when resuming from hibernate. Now xhci_resume() can safely make the
    call to create a new instance of this timer, whether returning from
    suspend or hibernate.
    
    Thanks to Alan Stern for his help with understanding the problem.
    
    [Sarah reworked this patch to cover the case where the xHCI restore
    register operation fails, and (temp & STS_SRE) is true (and we re-init
    the host, including re-init for the compliance mode), but hibernate is
    false.  The original patch would have caused list corruption in this
    case.]
    
    This patch should be backported to kernels as old as 3.2, that
    contain the commit 71c731a2 "usb: host:
    xhci: Fix Compliance Mode on SN65LVPE502CP Hardware"
    Signed-off-by: default avatarTony Camuso <tcamuso@redhat.com>
    Tested-by: default avatarTony Camuso <tcamuso@redhat.com>
    Acked-by: default avatarDon Zickus <dzickus@redhat.com>
    Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
    Cc: stable@vger.kernel.org
    77df9e0b
xhci.c 143 KB