NetBSD-Bugs archive

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

Re: kern/56739: Hang during boot since recent USB changes



The following reply was made to PR kern/56739; it has been noted by GNATS.

From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: Andreas Gustafsson <gson%gson.org@localhost>
Cc: gnats-bugs%NetBSD.org@localhost
Subject: Re: kern/56739: Hang during boot since recent USB changes
Date: Wed, 9 Mar 2022 12:19:07 +0000

 This is a multi-part message in MIME format.
 --=_La7nkjIJilZyzQ04m7iYdJZjSuvrF8DG
 
 Can you try the attached patch?
 
 --=_La7nkjIJilZyzQ04m7iYdJZjSuvrF8DG
 Content-Type: text/plain; charset="ISO-8859-1"; name="usbroothub"
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment; filename="usbroothub.patch"
 
 From 9aa011ffacd2e0f57490342446173233d6231ae9 Mon Sep 17 00:00:00 2001
 From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
 Date: Wed, 9 Mar 2022 11:37:27 +0000
 Subject: [PATCH] usb: Provisionally release bus lock around ubm_rhctrl.
 
 This isn't quite correct, but it avoids a deadlock:
 
 - *_roothub_ctrl holds bus lock, waits in usb_delay_ms for kpause
 - softint waits for bus lock, holds up kpause wakeup
 
 The deadlock is new since recent changes to hold the bus lock over
 upm_start/upm_transfer.  Making this change regresses to other
 problems:
 
 - *_suspend/resume and *_roothub_ctrl often touch the same portsc
    registers
 
 - roothub_ctrl_abort needs to wait for ubm_rhctrl to complete.
 
   When the bus lock was held across both, a noop served here, but we
   can't hold the bus lock across both, so that doesn't work.
 
 However, these problems -- which we've had for a long time -- seem to
 be less bad than the deadlock.  So let's avoid the deadlock for now
 and then work out another way to serialize suspend/resume/rhctrl and
 aborts.
 
 Candidate fix for PR kern/56739.
 ---
  sys/arch/mips/adm5120/dev/ahci.c |  2 --
  sys/dev/ic/sl811hs.c             |  2 --
  sys/dev/usb/ehci.c               |  8 +++++++-
  sys/dev/usb/motg.c               |  2 --
  sys/dev/usb/ohci.c               |  2 --
  sys/dev/usb/uhci.c               |  2 --
  sys/dev/usb/usbdivar.h           |  2 +-
  sys/dev/usb/usbroothub.c         | 12 ++++++++++++
  sys/dev/usb/xhci.c               |  2 --
  9 files changed, 20 insertions(+), 14 deletions(-)
 
 diff --git a/sys/arch/mips/adm5120/dev/ahci.c b/sys/arch/mips/adm5120/dev/a=
 hci.c
 index ca53af493e9b..7bc3a9fd0008 100644
 --- a/sys/arch/mips/adm5120/dev/ahci.c
 +++ b/sys/arch/mips/adm5120/dev/ahci.c
 @@ -569,8 +569,6 @@ ahci_roothub_ctrl(struct usbd_bus *bus, usb_device_requ=
 est_t *req,
 =20
  	DPRINTF(D_TRACE, ("SLRCstart "));
 =20
 -	KASSERT(bus->ub_polling || mutex_owned(bus->ub_lock));
 -
  	len =3D UGETW(req->wLength);
  	value =3D UGETW(req->wValue);
  	index =3D UGETW(req->wIndex);
 diff --git a/sys/dev/ic/sl811hs.c b/sys/dev/ic/sl811hs.c
 index 2a10911f3066..76db51573d95 100644
 --- a/sys/dev/ic/sl811hs.c
 +++ b/sys/dev/ic/sl811hs.c
 @@ -3195,8 +3195,6 @@ slhci_roothub_ctrl(struct usbd_bus *bus, usb_device_r=
 equest_t *req,
  	uint8_t type;
  	int actlen =3D 0;
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 -
  	len =3D UGETW(req->wLength);
  	value =3D UGETW(req->wValue);
  	index =3D UGETW(req->wIndex);
 diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
 index 5efa069a37af..4765b744d0e4 100644
 --- a/sys/dev/usb/ehci.c
 +++ b/sys/dev/usb/ehci.c
 @@ -1438,6 +1438,9 @@ ehci_activate(device_t self, enum devact act)
   *
   * Note that this power handler isn't to be registered directly; the
   * bus glue needs to call out to it.
 + *
 + * XXX This should be serialized with ehci_roothub_ctrl's access to the
 + * portsc registers.
   */
  bool
  ehci_suspend(device_t dv, const pmf_qual_t *qual)
 @@ -2369,7 +2372,10 @@ ehci_roothub_ctrl(struct usbd_bus *bus, usb_device_r=
 equest_t *req,
 =20
  	EHCIHIST_FUNC(); EHCIHIST_CALLED();
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 +	/*
 +	 * XXX This should be serialized with ehci_suspend/resume's
 +	 * access to the portsc registers.
 +	 */
 =20
  	if (sc->sc_dying)
  		return -1;
 diff --git a/sys/dev/usb/motg.c b/sys/dev/usb/motg.c
 index 36da0575b148..aba2ab1b4090 100644
 --- a/sys/dev/usb/motg.c
 +++ b/sys/dev/usb/motg.c
 @@ -806,8 +806,6 @@ motg_roothub_ctrl(struct usbd_bus *bus, usb_device_requ=
 est_t *req,
 =20
  	MOTGHIST_FUNC(); MOTGHIST_CALLED();
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 -
  	if (sc->sc_dying)
  		return -1;
 =20
 diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
 index c55078e8217f..c13ec53b5688 100644
 --- a/sys/dev/usb/ohci.c
 +++ b/sys/dev/usb/ohci.c
 @@ -2431,8 +2431,6 @@ ohci_roothub_ctrl(struct usbd_bus *bus, usb_device_re=
 quest_t *req,
 =20
  	OHCIHIST_FUNC(); OHCIHIST_CALLED();
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 -
  	if (sc->sc_dying)
  		return -1;
 =20
 diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
 index 99409084944f..fa80f49d6e6c 100644
 --- a/sys/dev/usb/uhci.c
 +++ b/sys/dev/usb/uhci.c
 @@ -3589,8 +3589,6 @@ uhci_roothub_ctrl(struct usbd_bus *bus, usb_device_re=
 quest_t *req,
 =20
  	UHCIHIST_FUNC(); UHCIHIST_CALLED();
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 -
  	if (sc->sc_dying)
  		return -1;
 =20
 diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
 index 5a5d94f26ccf..1be0236e49d2 100644
 --- a/sys/dev/usb/usbdivar.h
 +++ b/sys/dev/usb/usbdivar.h
 @@ -51,7 +51,7 @@
   *	ubm_abortx		x	must not release/reacquire lock
   *	ubm_getlock 		-	Called at attach time
   *	ubm_newdev		-	Will take lock
 - *	ubm_rhctrl              x
 + *	ubm_rhctrl              -
   *
   *	PIPE METHOD		LOCK	NOTES
   *	----------------------- -------	-------------------------
 diff --git a/sys/dev/usb/usbroothub.c b/sys/dev/usb/usbroothub.c
 index 6425d9cf21c7..74d42266725e 100644
 --- a/sys/dev/usb/usbroothub.c
 +++ b/sys/dev/usb/usbroothub.c
 @@ -549,7 +549,19 @@ roothub_ctrl_start(struct usbd_xfer *xfer)
  		break;
  	}
 =20
 +	/*
 +	 * XXX This needs some mechanism for concurrent
 +	 * roothub_ctrl_abort to wait for ubm_rhctrl to finish.  We
 +	 * can't use the bus lock because many ubm_rhctrl methods do
 +	 * usb_delay_ms and many bus locks are taken in softint
 +	 * context, leading to deadlock in the softclock needed to wake
 +	 * up usb_delay_ms.
 +	 */
 +	if (!bus->ub_usepolling)
 +		mutex_exit(bus->ub_lock);
  	actlen =3D bus->ub_methods->ubm_rhctrl(bus, req, buf, buflen);
 +	if (!bus->ub_usepolling)
 +		mutex_enter(bus->ub_lock);
  	if (actlen < 0)
  		goto fail;
 =20
 diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
 index 96663025878c..885bbc0af378 100644
 --- a/sys/dev/usb/xhci.c
 +++ b/sys/dev/usb/xhci.c
 @@ -3856,8 +3856,6 @@ xhci_roothub_ctrl(struct usbd_bus *bus, usb_device_re=
 quest_t *req,
 =20
  	XHCIHIST_FUNC();
 =20
 -	KASSERT(bus->ub_usepolling || mutex_owned(bus->ub_lock));
 -
  	if (sc->sc_dying)
  		return -1;
 =20
 
 --=_La7nkjIJilZyzQ04m7iYdJZjSuvrF8DG--
 


Home | Main Index | Thread Index | Old Index