usb/181159: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Tue Oct 1 08:40:01 UTC 2013


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

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: usb/181159: commit references a PR
Date: Tue,  1 Oct 2013 08:39:01 +0000 (UTC)

 Author: hselasky
 Date: Tue Oct  1 08:38:47 2013
 New Revision: 255965
 URL: http://svnweb.freebsd.org/changeset/base/255965
 
 Log:
   MFC r255768:
   Stability fixes for Intel LynxPoint XHCI controllers. Disable XHCI port
   routing if we get certain errors. Poll for command completion upon
   command timeouts. The XHCI error events might not generate interrupts.
   
   PR:		usb/181159
 
 Modified:
   stable/9/sys/dev/usb/controller/xhci.c
   stable/9/sys/dev/usb/controller/xhci.h
   stable/9/sys/dev/usb/controller/xhci_pci.c
 Directory Properties:
   stable/9/sys/   (props changed)
   stable/9/sys/dev/   (props changed)
 
 Modified: stable/9/sys/dev/usb/controller/xhci.c
 ==============================================================================
 --- stable/9/sys/dev/usb/controller/xhci.c	Tue Oct  1 07:22:04 2013	(r255964)
 +++ stable/9/sys/dev/usb/controller/xhci.c	Tue Oct  1 08:38:47 2013	(r255965)
 @@ -94,6 +94,8 @@ TUNABLE_INT("hw.usb.xhci.debug", &xhcide
  SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN,
      &xhciroute, 0, "Routing bitmap for switching EHCI ports to XHCI controller");
  TUNABLE_INT("hw.usb.xhci.xhci_port_route", &xhciroute);
 +#else
 +#define	xhciroute 0
  #endif
  
  #define	XHCI_INTR_ENDPT 1
 @@ -179,16 +181,6 @@ xhci_dump_device(struct xhci_softc *sc, 
  }
  #endif
  
 -uint32_t
 -xhci_get_port_route(void)
 -{
 -#ifdef USB_DEBUG
 -	return (0xFFFFFFFFU ^ ((uint32_t)xhciroute));
 -#else
 -	return (0xFFFFFFFFU);
 -#endif
 -}
 -
  static void
  xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
  {
 @@ -480,6 +472,11 @@ xhci_start_controller(struct xhci_softc 
  	/* catch any lost interrupts */
  	xhci_do_poll(&sc->sc_bus);
  
 +	if (sc->sc_port_route != NULL) {
 +		/* Route all ports to the XHCI by default */
 +		sc->sc_port_route(sc->sc_bus.parent,
 +		    ~xhciroute, xhciroute);
 +	}
  	return (0);
  }
  
 @@ -917,7 +914,7 @@ xhci_check_transfer(struct xhci_softc *s
  	}
  }
  
 -static void
 +static int
  xhci_check_command(struct xhci_softc *sc, struct xhci_trb *trb)
  {
  	if (sc->sc_cmd_addr == trb->qwTrb0) {
 @@ -925,16 +922,19 @@ xhci_check_command(struct xhci_softc *sc
  		sc->sc_cmd_result[0] = trb->dwTrb2;
  		sc->sc_cmd_result[1] = trb->dwTrb3;
  		cv_signal(&sc->sc_cmd_cv);
 +		return (1);	/* command match */
  	}
 +	return (0);
  }
  
 -static void
 +static int
  xhci_interrupt_poll(struct xhci_softc *sc)
  {
  	struct usb_page_search buf_res;
  	struct xhci_hw_root *phwr;
  	uint64_t addr;
  	uint32_t temp;
 +	int retval = 0;
  	uint16_t i;
  	uint8_t event;
  	uint8_t j;
 @@ -974,7 +974,7 @@ xhci_interrupt_poll(struct xhci_softc *s
  			xhci_check_transfer(sc, &phwr->hwr_events[i]);
  			break;
  		case XHCI_TRB_EVENT_CMD_COMPLETE:
 -			xhci_check_command(sc, &phwr->hwr_events[i]);
 +			retval |= xhci_check_command(sc, &phwr->hwr_events[i]);
  			break;
  		default:
  			DPRINTF("Unhandled event = %u\n", event);
 @@ -1011,6 +1011,8 @@ xhci_interrupt_poll(struct xhci_softc *s
  
  	XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr);
  	XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
 +
 +	return (retval);
  }
  
  static usb_error_t
 @@ -1098,7 +1100,15 @@ xhci_do_command(struct xhci_softc *sc, s
  	err = cv_timedwait(&sc->sc_cmd_cv, &sc->sc_bus.bus_mtx,
  	    USB_MS_TO_TICKS(timeout_ms));
  
 -	if (err) {
 +	/*
 +	 * In some error cases event interrupts are not generated.
 +	 * Poll one time to see if the command has completed.
 +	 */
 +	if (err != 0 && xhci_interrupt_poll(sc) != 0) {
 +		DPRINTF("Command was completed when polling\n");
 +		err = 0;
 +	}
 +	if (err != 0) {
  		DPRINTFN(0, "Command timeout!\n");
  		err = USB_ERR_TIMEOUT;
  		trb->dwTrb2 = 0;
 @@ -1277,6 +1287,14 @@ xhci_set_address(struct usb_device *udev
  		    (address == 0), index);
  
  		if (err != 0) {
 +			temp = le32toh(sc->sc_cmd_result[0]);
 +			if (address == 0 && sc->sc_port_route != NULL &&
 +			    XHCI_TRB_2_ERROR_GET(temp) ==
 +			    XHCI_TRB_ERROR_PARAMETER) {
 +				/* LynxPoint XHCI - ports are not switchable */
 +				/* Un-route all ports from the XHCI */
 +				sc->sc_port_route(sc->sc_bus.parent, 0, ~0);
 +			}
  			DPRINTF("Could not set address "
  			    "for slot %u.\n", index);
  			if (address != 0)
 
 Modified: stable/9/sys/dev/usb/controller/xhci.h
 ==============================================================================
 --- stable/9/sys/dev/usb/controller/xhci.h	Tue Oct  1 07:22:04 2013	(r255964)
 +++ stable/9/sys/dev/usb/controller/xhci.h	Tue Oct  1 08:38:47 2013	(r255965)
 @@ -421,6 +421,8 @@ union xhci_hub_desc {
  	uint8_t				temp[128];
  };
  
 +typedef int (xhci_port_route_t)(device_t, uint32_t, uint32_t);
 +
  struct xhci_softc {
  	struct xhci_hw_softc	sc_hw;
  	/* base device */
 @@ -429,6 +431,8 @@ struct xhci_softc {
  	struct usb_process	sc_config_proc;
  	struct usb_bus_msg	sc_config_msg[2];
  
 +	xhci_port_route_t	*sc_port_route;
 +
  	union xhci_hub_desc	sc_hub_desc;
  
  	struct cv		sc_cmd_cv;
 @@ -491,7 +495,6 @@ struct xhci_softc {
  
  /* prototypes */
  
 -uint32_t	xhci_get_port_route(void);
  usb_error_t xhci_halt_controller(struct xhci_softc *);
  usb_error_t xhci_init(struct xhci_softc *, device_t);
  usb_error_t xhci_start_controller(struct xhci_softc *);
 
 Modified: stable/9/sys/dev/usb/controller/xhci_pci.c
 ==============================================================================
 --- stable/9/sys/dev/usb/controller/xhci_pci.c	Tue Oct  1 07:22:04 2013	(r255964)
 +++ stable/9/sys/dev/usb/controller/xhci_pci.c	Tue Oct  1 08:38:47 2013	(r255965)
 @@ -136,6 +136,25 @@ static int xhci_use_msi = 1;
  TUNABLE_INT("hw.usb.xhci.msi", &xhci_use_msi);
  
  static int
 +xhci_pci_port_route(device_t self, uint32_t set, uint32_t clear)
 +{
 +	uint32_t temp;
 +
 +	temp = pci_read_config(self, PCI_XHCI_INTEL_USB3_PSSEN, 4) |
 +	    pci_read_config(self, PCI_XHCI_INTEL_XUSB2PR, 4);
 +
 +	temp |= set;
 +	temp &= ~clear;
 +
 +	pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
 +	pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
 +
 +	device_printf(self, "Port routing mask set to 0x%08x\n", temp);
 +
 +	return (0);
 +}
 +
 +static int
  xhci_pci_attach(device_t self)
  {
  	struct xhci_softc *sc = device_get_softc(self);
 @@ -200,6 +219,16 @@ xhci_pci_attach(device_t self)
  		sc->sc_intr_hdl = NULL;
  		goto error;
  	}
 +	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
 +	switch (pci_get_devid(self)) {
 +	case 0x1e318086:	/* Panther Point */
 +	case 0x8c318086:	/* Lynx Point */
 +		sc->sc_port_route = &xhci_pci_port_route;
 +		break;
 +	default:
 +		break;
 +	}
 +
  	xhci_pci_take_controller(self);
  
  	err = xhci_halt_controller(sc);
 @@ -266,7 +295,6 @@ static int
  xhci_pci_take_controller(device_t self)
  {
  	struct xhci_softc *sc = device_get_softc(self);
 -	uint32_t device_id = pci_get_devid(self);
  	uint32_t cparams;
  	uint32_t eecp;
  	uint32_t eec;
 @@ -307,13 +335,5 @@ xhci_pci_take_controller(device_t self)
  			usb_pause_mtx(NULL, hz / 100);	/* wait 10ms */
  		}
  	}
 -
 -	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
 -	if (device_id == 0x1e318086 /* Panther Point */ ||
 -	    device_id == 0x8c318086 /* Lynx Point */) {
 -		uint32_t temp = xhci_get_port_route();
 -		pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
 -		pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
 -	}
  	return (0);
  }
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-usb mailing list