Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb xhci(4): Avoid crash in suspend/resume/resume if...



details:   https://anonhg.NetBSD.org/src/rev/95629e91e423
branches:  trunk
changeset: 374197:95629e91e423
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sun Apr 09 20:41:28 2023 +0000

description:
xhci(4): Avoid crash in suspend/resume/resume if first resume fails.

Rather than try to recover from this, just make new commands fail so
at least we don't deadlock.

XXX pullup-9
XXX pullup-10

diffstat:

 sys/dev/usb/xhci.c    |  23 ++++++++++++++++++++---
 sys/dev/usb/xhcivar.h |   3 ++-
 2 files changed, 22 insertions(+), 4 deletions(-)

diffs (94 lines):

diff -r e5e3de2a178c -r 95629e91e423 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c        Sun Apr 09 17:24:48 2023 +0000
+++ b/sys/dev/usb/xhci.c        Sun Apr 09 20:41:28 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhci.c,v 1.176 2023/04/07 09:39:48 riastradh Exp $     */
+/*     $NetBSD: xhci.c,v 1.177 2023/04/09 20:41:28 riastradh Exp $     */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.176 2023/04/07 09:39:48 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.177 2023/04/09 20:41:28 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -700,6 +700,7 @@ xhci_suspend(device_t self, const pmf_qu
         */
        mutex_enter(&sc->sc_lock);
        KASSERT(sc->sc_suspender == NULL);
+       KASSERT(!sc->sc_suspendresume_failed);
        sc->sc_suspender = curlwp;
        while (sc->sc_command_addr != 0)
                cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock);
@@ -895,11 +896,13 @@ xhci_suspend(device_t self, const pmf_qu
 out:   mutex_exit(&sc->sc_rhlock);
        if (!ok) {
                /*
-                * If suspend failed, resume command issuance.
+                * If suspend failed, stop holding up command issuance
+                * and make it fail instead.
                 */
                mutex_enter(&sc->sc_lock);
                KASSERT(sc->sc_suspender == curlwp);
                sc->sc_suspender = NULL;
+               sc->sc_suspendresume_failed = true;
                cv_broadcast(&sc->sc_cmdbusy_cv);
                mutex_exit(&sc->sc_lock);
        }
@@ -917,7 +920,18 @@ xhci_resume(device_t self, const pmf_qua
 
        XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
+       /*
+        * If resume had previously failed, just try again.  Can't make
+        * things worse, probably.
+        */
+       mutex_enter(&sc->sc_lock);
+       if (sc->sc_suspendresume_failed) {
+               KASSERT(sc->sc_suspender == NULL);
+               sc->sc_suspender = curlwp;
+               sc->sc_suspendresume_failed = false;
+       }
        KASSERT(sc->sc_suspender);
+       mutex_exit(&sc->sc_lock);
 
        /*
         * Block roothub xfers which might touch portsc registers until
@@ -1111,6 +1125,7 @@ out:      /*
        mutex_enter(&sc->sc_lock);
        KASSERT(sc->sc_suspender);
        sc->sc_suspender = NULL;
+       sc->sc_suspendresume_failed = !ok;
        cv_broadcast(&sc->sc_cmdbusy_cv);
        mutex_exit(&sc->sc_lock);
 
@@ -3217,6 +3232,8 @@ xhci_do_command_locked(struct xhci_softc
        while (sc->sc_command_addr != 0 ||
            (sc->sc_suspender != NULL && sc->sc_suspender != curlwp))
                cv_wait(&sc->sc_cmdbusy_cv, &sc->sc_lock);
+       if (sc->sc_suspendresume_failed)
+               return USBD_IOERROR;
 
        /*
         * If enqueue pointer points at last of ring, it's Link TRB,
diff -r e5e3de2a178c -r 95629e91e423 sys/dev/usb/xhcivar.h
--- a/sys/dev/usb/xhcivar.h     Sun Apr 09 17:24:48 2023 +0000
+++ b/sys/dev/usb/xhcivar.h     Sun Apr 09 20:41:28 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: xhcivar.h,v 1.23 2023/04/07 09:39:48 riastradh Exp $   */
+/*     $NetBSD: xhcivar.h,v 1.24 2023/04/09 20:41:29 riastradh Exp $   */
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -140,6 +140,7 @@ struct xhci_softc {
        bool sc_resultpending;
 
        bool sc_dying;
+       bool sc_suspendresume_failed;
        struct lwp *sc_suspender;
 
        void (*sc_vendor_init)(struct xhci_softc *);



Home | Main Index | Thread Index | Old Index