Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jan 2020 08:51:58 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r356781 - stable/12/sys/dev/usb/controller
Message-ID:  <202001160851.00G8pwTa083434@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Thu Jan 16 08:51:58 2020
New Revision: 356781
URL: https://svnweb.freebsd.org/changeset/base/356781

Log:
  MFC r356545:
  Fix a XHCI driver issue with Intel's Gemini Lake SOC.
  
  Do not configure any endpoint twice, but instead keep track of which
  endpoints are configured on a per device basis, and use an evaluate
  endpoint context command instead. When changing the configuration make
  sure all endpoints get deconfigured and the configured endpoint mask
  is reset.
  
  This fixes an issue where an endpoint might stop working if there is
  an error and the endpoint needs to be reconfigured as a part of the
  error recovery mechanism in the FreeBSD USB stack.
  
  Tested by:	Shichun.Ma@dell.com
  Sponsored by:	Mellanox Technologies

Modified:
  stable/12/sys/dev/usb/controller/xhci.c
  stable/12/sys/dev/usb/controller/xhci.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/usb/controller/xhci.c
==============================================================================
--- stable/12/sys/dev/usb/controller/xhci.c	Thu Jan 16 08:27:30 2020	(r356780)
+++ stable/12/sys/dev/usb/controller/xhci.c	Thu Jan 16 08:51:58 2020	(r356781)
@@ -3838,6 +3838,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
 	struct usb_page_cache *pcinp;
 	usb_error_t err;
 	usb_stream_t stream_id;
+	uint32_t mask;
 	uint8_t index;
 	uint8_t epno;
 
@@ -3903,16 +3904,20 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
 	 * endpoint context state diagram in the XHCI specification:
 	 */
 
-	xhci_configure_mask(udev, (1U << epno) | 1U, 0);
+	mask = (1U << epno);
+	xhci_configure_mask(udev, mask | 1U, 0);
 
-	if (epno > 1)
+	if (!(sc->sc_hw.devs[index].ep_configured & mask)) {
+		sc->sc_hw.devs[index].ep_configured |= mask;
 		err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
-	else
+	} else {
 		err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+	}
 
-	if (err != 0)
-		DPRINTF("Could not configure endpoint %u\n", epno);
-
+	if (err != 0) {
+		DPRINTF("Could not configure "
+		    "endpoint %u at slot %u.\n", epno, index);
+	}
 	XHCI_CMD_UNLOCK(sc);
 
 	return (0);
@@ -4273,6 +4278,7 @@ xhci_device_state_change(struct usb_device *udev)
 
 		/* set default state */
 		sc->sc_hw.devs[index].state = XHCI_ST_DEFAULT;
+		sc->sc_hw.devs[index].ep_configured = 3U;
 
 		/* reset number of contexts */
 		sc->sc_hw.devs[index].context_num = 0;
@@ -4290,6 +4296,7 @@ xhci_device_state_change(struct usb_device *udev)
 			break;
 
 		sc->sc_hw.devs[index].state = XHCI_ST_ADDRESSED;
+		sc->sc_hw.devs[index].ep_configured = 3U;
 
 		/* set configure mask to slot only */
 		xhci_configure_mask(udev, 1, 0);
@@ -4304,11 +4311,19 @@ xhci_device_state_change(struct usb_device *udev)
 		break;
 
 	case USB_STATE_CONFIGURED:
-		if (sc->sc_hw.devs[index].state == XHCI_ST_CONFIGURED)
-			break;
+		if (sc->sc_hw.devs[index].state == XHCI_ST_CONFIGURED) {
+			/* deconfigure all endpoints, except EP0 */
+			err = xhci_cmd_configure_ep(sc, 0, 1, index);
 
+			if (err) {
+				DPRINTF("Failed to deconfigure "
+				    "slot %u.\n", index);
+			}
+		}
+
 		/* set configured state */
 		sc->sc_hw.devs[index].state = XHCI_ST_CONFIGURED;
+		sc->sc_hw.devs[index].ep_configured = 3U;
 
 		/* reset number of contexts */
 		sc->sc_hw.devs[index].context_num = 0;

Modified: stable/12/sys/dev/usb/controller/xhci.h
==============================================================================
--- stable/12/sys/dev/usb/controller/xhci.h	Thu Jan 16 08:27:30 2020	(r356780)
+++ stable/12/sys/dev/usb/controller/xhci.h	Thu Jan 16 08:51:58 2020	(r356781)
@@ -408,6 +408,8 @@ struct xhci_hw_dev {
 
 	struct xhci_endpoint_ext endp[XHCI_MAX_ENDPOINTS];
 
+	uint32_t		ep_configured;
+
 	uint8_t			state;
 	uint8_t			nports;
 	uint8_t			tt;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001160851.00G8pwTa083434>