svn commit: r220307 - stable/8/sys/dev/usb/controller

Hans Petter Selasky hselasky at FreeBSD.org
Sun Apr 3 21:12:16 UTC 2011


Author: hselasky
Date: Sun Apr  3 21:12:16 2011
New Revision: 220307
URL: http://svn.freebsd.org/changeset/base/220307

Log:
  MFC r217374
  Add support for 64-byte contexts to XHCI driver.
  
  Approved by:	thompsa (mentor)

Modified:
  stable/8/sys/dev/usb/controller/xhci.c
  stable/8/sys/dev/usb/controller/xhci.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/dev/usb/controller/xhci.c
==============================================================================
--- stable/8/sys/dev/usb/controller/xhci.c	Sun Apr  3 21:01:36 2011	(r220306)
+++ stable/8/sys/dev/usb/controller/xhci.c	Sun Apr  3 21:12:16 2011	(r220307)
@@ -134,6 +134,12 @@ static usb_error_t xhci_configure_mask(s
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
 		    uint64_t, uint8_t);
 static void xhci_endpoint_doorbell(struct usb_xfer *);
+static void xhci_ctx_set_le32(struct xhci_softc *sc, volatile uint32_t *ptr, uint32_t val);
+static uint32_t xhci_ctx_get_le32(struct xhci_softc *sc, volatile uint32_t *ptr);
+static void xhci_ctx_set_le64(struct xhci_softc *sc, volatile uint64_t *ptr, uint64_t val);
+#ifdef USB_DEBUG
+static uint64_t xhci_ctx_get_le64(struct xhci_softc *sc, volatile uint64_t *ptr);
+#endif
 
 extern struct usb_bus_methods xhci_bus_methods;
 
@@ -148,26 +154,26 @@ xhci_dump_trb(struct xhci_trb *trb)
 }
 
 static void
-xhci_dump_endpoint(struct xhci_endp_ctx *pep)
+xhci_dump_endpoint(struct xhci_softc *sc, struct xhci_endp_ctx *pep)
 {
 	DPRINTFN(5, "pep = %p\n", pep);
-	DPRINTFN(5, "dwEpCtx0=0x%08x\n", pep->dwEpCtx0);
-	DPRINTFN(5, "dwEpCtx1=0x%08x\n", pep->dwEpCtx1);
-	DPRINTFN(5, "qwEpCtx2=0x%016llx\n", (long long)pep->qwEpCtx2);
-	DPRINTFN(5, "dwEpCtx4=0x%08x\n", pep->dwEpCtx4);
-	DPRINTFN(5, "dwEpCtx5=0x%08x\n", pep->dwEpCtx5);
-	DPRINTFN(5, "dwEpCtx6=0x%08x\n", pep->dwEpCtx6);
-	DPRINTFN(5, "dwEpCtx7=0x%08x\n", pep->dwEpCtx7);
+	DPRINTFN(5, "dwEpCtx0=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx0));
+	DPRINTFN(5, "dwEpCtx1=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx1));
+	DPRINTFN(5, "qwEpCtx2=0x%016llx\n", (long long)xhci_ctx_get_le64(sc, &pep->qwEpCtx2));
+	DPRINTFN(5, "dwEpCtx4=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx4));
+	DPRINTFN(5, "dwEpCtx5=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx5));
+	DPRINTFN(5, "dwEpCtx6=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx6));
+	DPRINTFN(5, "dwEpCtx7=0x%08x\n", xhci_ctx_get_le32(sc, &pep->dwEpCtx7));
 }
 
 static void
-xhci_dump_device(struct xhci_slot_ctx *psl)
+xhci_dump_device(struct xhci_softc *sc, struct xhci_slot_ctx *psl)
 {
 	DPRINTFN(5, "psl = %p\n", psl);
-	DPRINTFN(5, "dwSctx0=0x%08x\n", psl->dwSctx0);
-	DPRINTFN(5, "dwSctx1=0x%08x\n", psl->dwSctx1);
-	DPRINTFN(5, "dwSctx2=0x%08x\n", psl->dwSctx2);
-	DPRINTFN(5, "dwSctx3=0x%08x\n", psl->dwSctx3);
+	DPRINTFN(5, "dwSctx0=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx0));
+	DPRINTFN(5, "dwSctx1=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx1));
+	DPRINTFN(5, "dwSctx2=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx2));
+	DPRINTFN(5, "dwSctx3=0x%08x\n", xhci_ctx_get_le32(sc, &psl->dwSctx3));
 }
 #endif
 
@@ -189,6 +195,60 @@ xhci_iterate_hw_softc(struct usb_bus *bu
 	}
 }
 
+static void
+xhci_ctx_set_le32(struct xhci_softc *sc, volatile uint32_t *ptr, uint32_t val)
+{
+	if (sc->sc_ctx_is_64_byte) {
+		uint32_t offset;
+		/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
+		/* all contexts are initially 32-bytes */
+		offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
+		ptr = (volatile uint32_t *)(((volatile uint8_t *)ptr) + offset);
+	}
+	*ptr = htole32(val);
+}
+
+static uint32_t
+xhci_ctx_get_le32(struct xhci_softc *sc, volatile uint32_t *ptr)
+{
+	if (sc->sc_ctx_is_64_byte) {
+		uint32_t offset;
+		/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
+		/* all contexts are initially 32-bytes */
+		offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
+		ptr = (volatile uint32_t *)(((volatile uint8_t *)ptr) + offset);
+	}
+	return (le32toh(*ptr));
+}
+
+static void
+xhci_ctx_set_le64(struct xhci_softc *sc, volatile uint64_t *ptr, uint64_t val)
+{
+	if (sc->sc_ctx_is_64_byte) {
+		uint32_t offset;
+		/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
+		/* all contexts are initially 32-bytes */
+		offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
+		ptr = (volatile uint64_t *)(((volatile uint8_t *)ptr) + offset);
+	}
+	*ptr = htole64(val);
+}
+
+#ifdef USB_DEBUG
+static uint64_t
+xhci_ctx_get_le64(struct xhci_softc *sc, volatile uint64_t *ptr)
+{
+	if (sc->sc_ctx_is_64_byte) {
+		uint32_t offset;
+		/* exploit the fact that our structures are XHCI_PAGE_SIZE aligned */
+		/* all contexts are initially 32-bytes */
+		offset = ((uintptr_t)ptr) & ((XHCI_PAGE_SIZE - 1) & ~(31U));
+		ptr = (volatile uint64_t *)(((volatile uint8_t *)ptr) + offset);
+	}
+	return (le64toh(*ptr));
+}
+#endif
+
 usb_error_t
 xhci_start_controller(struct xhci_softc *sc)
 {
@@ -222,9 +282,11 @@ xhci_start_controller(struct xhci_softc 
 	DPRINTF("HCS0 = 0x%08x\n", temp);
 
 	if (XHCI_HCS0_CSZ(temp)) {
-		device_printf(sc->sc_bus.parent, "Driver does not "
-		    "support 64-byte contexts.");
-		return (USB_ERR_IOERROR);
+		sc->sc_ctx_is_64_byte = 1;
+		device_printf(sc->sc_bus.parent, "64 byte context size.\n");
+	} else {
+		sc->sc_ctx_is_64_byte = 0;
+		device_printf(sc->sc_bus.parent, "32 byte context size.\n");
 	}
 
 	/* Reset controller */
@@ -1127,6 +1189,7 @@ xhci_set_address(struct usb_device *udev
 	struct xhci_hw_dev *hdev;
 	struct xhci_dev_ctx *pdev;
 	struct xhci_endpoint_ext *pepext;
+	uint32_t temp;
 	uint16_t mps;
 	usb_error_t err;
 	uint8_t index;
@@ -1204,7 +1267,9 @@ xhci_set_address(struct usb_device *udev
 		usbd_get_page(&hdev->device_pc, 0, &buf_dev);
 		pdev = buf_dev.buffer;
 		usb_pc_cpu_invalidate(&hdev->device_pc);
-		udev->address = XHCI_SCTX_3_DEV_ADDR_GET(pdev->ctx_slot.dwSctx3);
+
+		temp = xhci_ctx_get_le32(sc, &pdev->ctx_slot.dwSctx3);
+		udev->address = XHCI_SCTX_3_DEV_ADDR_GET(temp);
 
 		/* update device state to new value */
 
@@ -1964,11 +2029,11 @@ xhci_configure_mask(struct usb_device *u
 
 	if (drop) {
 		mask &= XHCI_INCTX_NON_CTRL_MASK;
-		pinp->ctx_input.dwInCtx0 = htole32(mask);
-		pinp->ctx_input.dwInCtx1 = 0;
+		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
+		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
 	} else {
-		pinp->ctx_input.dwInCtx0 = 0;
-		pinp->ctx_input.dwInCtx1 = htole32(mask);
+		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
+		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
 	}
 	return (0);
 }
@@ -2050,7 +2115,7 @@ xhci_configure_endpoint(struct usb_devic
 		break;
 	}
 
-	pinp->ctx_ep[epno - 1].dwEpCtx0 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx0, temp);
 
 	temp =
 	    XHCI_EPCTX_1_HID_SET(0) |
@@ -2081,11 +2146,11 @@ xhci_configure_endpoint(struct usb_devic
 	if (epno & 1)
 		temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
 
-	pinp->ctx_ep[epno - 1].dwEpCtx1 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp);
 
 	ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
 
-	pinp->ctx_ep[epno - 1].qwEpCtx2 = htole64(ring_addr);
+	xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr);
 
 	switch (edesc->bmAttributes & UE_XFERTYPE) {
 	case UE_INTERRUPT:
@@ -2102,10 +2167,10 @@ xhci_configure_endpoint(struct usb_devic
 		break;
 	}
 
-	pinp->ctx_ep[epno - 1].dwEpCtx4 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx4, temp);
 
 #ifdef USB_DEBUG
-	xhci_dump_endpoint(&pinp->ctx_ep[epno - 1]);
+	xhci_dump_endpoint(sc, &pinp->ctx_ep[epno - 1]);
 #endif
 	usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc);
 
@@ -2138,12 +2203,9 @@ static usb_error_t
 xhci_configure_device(struct usb_device *udev)
 {
 	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
-	struct usb_page_search buf_dev;
 	struct usb_page_search buf_inp;
-	struct usb_page_cache *pcdev;
 	struct usb_page_cache *pcinp;
 	struct xhci_input_dev_ctx *pinp;
-	struct xhci_dev_ctx *pdev;
 	struct usb_device *hubdev;
 	uint32_t temp;
 	uint32_t route;
@@ -2155,13 +2217,10 @@ xhci_configure_device(struct usb_device 
 
 	DPRINTF("index=%u\n", index);
 
-	pcdev = &sc->sc_hw.devs[index].device_pc;
 	pcinp = &sc->sc_hw.devs[index].input_pc;
 
-	usbd_get_page(pcdev, 0, &buf_dev);
 	usbd_get_page(pcinp, 0, &buf_inp);
 
-	pdev = buf_dev.buffer;
 	pinp = buf_inp.buffer;
 
 	rh_port = 0;
@@ -2232,7 +2291,7 @@ xhci_configure_device(struct usb_device 
 #endif
 	}
 
-	pinp->ctx_slot.dwSctx0 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
 
 	temp = XHCI_SCTX_1_RH_PORT_SET(rh_port);
 
@@ -2258,7 +2317,7 @@ xhci_configure_device(struct usb_device 
 		break;
 	}
 
-	pinp->ctx_slot.dwSctx1 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx1, temp);
 
 	temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
 
@@ -2282,15 +2341,15 @@ xhci_configure_device(struct usb_device 
 		break;
 	}
 
-	pinp->ctx_slot.dwSctx2 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx2, temp);
 
 	temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
 	    XHCI_SCTX_3_SLOT_STATE_SET(0);
 
-	pinp->ctx_slot.dwSctx3 = htole32(temp);
+	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx3, temp);
 
 #ifdef USB_DEBUG
-	xhci_dump_device(&pinp->ctx_slot);
+	xhci_dump_device(sc, &pinp->ctx_slot);
 #endif
 	usb_pc_cpu_flush(pcinp);
 
@@ -2318,7 +2377,9 @@ xhci_alloc_device_ext(struct usb_device 
 	/* need to initialize the page cache */
 	pc->tag_parent = sc->sc_bus.dma_parent_tag;
 
-	if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_ctx), XHCI_PAGE_SIZE))
+	if (usb_pc_alloc_mem(pc, pg, sc->sc_ctx_is_64_byte ?
+	    (2 * sizeof(struct xhci_dev_ctx)) :
+	    sizeof(struct xhci_dev_ctx), XHCI_PAGE_SIZE))
 		goto error;
 
 	usbd_get_page(pc, 0, &buf_dev);
@@ -2329,7 +2390,9 @@ xhci_alloc_device_ext(struct usb_device 
 	/* need to initialize the page cache */
 	pc->tag_parent = sc->sc_bus.dma_parent_tag;
 
-	if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_input_dev_ctx), XHCI_PAGE_SIZE))
+	if (usb_pc_alloc_mem(pc, pg, sc->sc_ctx_is_64_byte ?
+	    (2 * sizeof(struct xhci_input_dev_ctx)) :
+	     sizeof(struct xhci_input_dev_ctx), XHCI_PAGE_SIZE))
 		goto error;
 
 	pc = &sc->sc_hw.devs[index].endpoint_pc;
@@ -3348,13 +3411,10 @@ static usb_error_t
 xhci_configure_reset_endpoint(struct usb_xfer *xfer)
 {
 	struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
-	struct usb_page_search buf_dev;
 	struct usb_page_search buf_inp;
 	struct usb_device *udev;
 	struct xhci_endpoint_ext *pepext;
 	struct usb_endpoint_descriptor *edesc;
-	struct xhci_dev_ctx *pdctx;
-	struct usb_page_cache *pcdev;
 	struct usb_page_cache *pcinp;
 	usb_error_t err;
 	uint8_t index;
@@ -3366,14 +3426,10 @@ xhci_configure_reset_endpoint(struct usb
 	udev = xfer->xroot->udev;
 	index = udev->controller_slot_id;
 
-	pcdev = &sc->sc_hw.devs[index].device_pc;
 	pcinp = &sc->sc_hw.devs[index].input_pc;
 
-	usbd_get_page(pcdev, 0, &buf_dev);
 	usbd_get_page(pcinp, 0, &buf_inp);
 
-	pdctx = buf_dev.buffer;
-
 	edesc = xfer->endpoint->edesc;
 
 	epno = edesc->bEndpointAddress;

Modified: stable/8/sys/dev/usb/controller/xhci.h
==============================================================================
--- stable/8/sys/dev/usb/controller/xhci.h	Sun Apr  3 21:01:36 2011	(r220306)
+++ stable/8/sys/dev/usb/controller/xhci.h	Sun Apr  3 21:12:16 2011	(r220307)
@@ -477,6 +477,9 @@ struct xhci_softc {
 	uint8_t			sc_conf;
 	uint8_t			sc_hub_idata[2];
 
+	/* size of context */
+	uint8_t			sc_ctx_is_64_byte;
+
 	/* vendor string for root HUB */
 	char			sc_vendor[16];
 };


More information about the svn-src-stable mailing list