Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Aug 2010 09:46:42 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 181670 for review
Message-ID:  <201008010946.o719kg3G061048@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181670?ac=10

Change 181670 by hselasky@hselasky_laptop001 on 2010/08/01 09:46:06

	USB controller (XHCI):
		- add command queue logic
		- remove XHCI QH structure

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#8 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#5 (text+ko) ====

@@ -146,6 +146,8 @@
 
 	sc->sc_event_ccs = 1;
 	sc->sc_event_idx = 0;
+	sc->sc_command_ccs = 1;
+	sc->sc_command_idx = 0;
 
 	DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
 
@@ -258,9 +260,21 @@
 
 	addr = (uint64_t)buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[0];
 
-	XWRITE4(sc, oper, XHCI_CRCR_LO, (uint32_t)addr);
+	XWRITE4(sc, oper, XHCI_CRCR_LO, ((uint32_t)addr) | XHCI_CRCR_LO_RCS);
 	XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
 
+	/*
+	 * We only need the 32-lower bits of the command dequeue
+	 * pointer to keep track of the TRBs:
+	 */
+	sc->sc_cmd_dp = (uint32_t)addr;
+
+	phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].qwTrb0 = htole64(addr);
+	phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].dwTrb2 = htole32(0);
+	phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].dwTrb3 = htole32(
+		XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
+		XHCI_TRB_3_IOC_BIT | XHCI_TRB_3_TC_BIT);
+
 	usb_bus_mem_flush_all(&sc->sc_bus, &xhci_iterate_hw_softc);
 
 	/* Go! */
@@ -322,6 +336,8 @@
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
 
+	TAILQ_INIT(&sc->sc_cmd_head);
+
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
 	    USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) {
@@ -556,8 +572,10 @@
 {
 	struct usb_page_search buf_res;
 	struct xhci_hw_root *phwr;
+	struct xhci_command *pcmd;
 	uint32_t temp;
 	uint16_t i;
+	uint8_t event;
 	uint8_t j;
 	uint8_t k;
 	uint8_t t;
@@ -566,6 +584,8 @@
 
 	phwr = buf_res.buffer;
 
+	/* 1) Receive any events */
+
 	usb_pc_cpu_invalidate(&sc->sc_hw.root_pc);
 
 	i = sc->sc_event_idx;
@@ -580,13 +600,16 @@
 		if (j != k)
 			break;
 
-		switch (XHCI_TRB_3_TYPE_GET(temp)) {
+		event = XHCI_TRB_3_TYPE_GET(temp);
+
+		DPRINTFN(10, "event[%u] = %u\n", i, event);
+
+		switch (event) {
 		case XHCI_TRB_EVENT_TRANSFER:
 			xhci_check_transfer(sc, &phwr->hwr_events[i]);
 			break;
 		default:
-			DPRINTF("Received event = 0x%x\n", 
-			    XHCI_TRB_3_TYPE_GET(temp));
+			DPRINTF("Received event = 0x%x\n", event);
 			break;
 		}
 
@@ -610,6 +633,59 @@
 
 	sc->sc_event_idx = i;
 	sc->sc_event_ccs = j;
+
+	/* 2) Queue any commands */
+
+	i = sc->sc_command_idx;
+	j = sc->sc_command_ccs;
+
+	while (1) {
+
+		k = (phwr->hwr_events[i].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT)) ? 1 : 0;
+
+		temp = (uint32_t)buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[i];
+
+		/* check if we need to wait for XHCI to process commands */
+		if ((sc->sc_cmd_dp == temp) && (j == k))
+			break;
+
+		/* check if there are any commands on the queue */
+		pcmd = TAILQ_FIRST(&sc->sc_cmd_head);
+		if (pcmd == NULL)
+			break;
+
+		TAILQ_REMOVE(&sc->sc_cmd_head, pcmd, entry);
+		pcmd->entry.tqe_prev = NULL;
+
+		phwr->hwr_events[i].qwTrb0 = pcmd->trb.qwTrb0;
+		phwr->hwr_events[i].dwTrb2 = pcmd->trb.dwTrb2;
+
+		usb_pc_cpu_flush(&sc->sc_hw.root_pc);
+
+		temp = pcmd->trb.dwTrb3 | htole32(XHCI_TRB_3_IOC_BIT);
+
+		if (j)
+			temp |= htole32(XHCI_TRB_3_CYCLE_BIT);
+		else
+			temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
+
+		phwr->hwr_events[i].dwTrb3 = temp;
+
+		usb_pc_cpu_flush(&sc->sc_hw.root_pc);
+
+		DPRINTFN(10, "command[%u] = %u\n", i,
+		    XHCI_TRB_3_TYPE_GET(le32toh(temp)));
+
+		i++;
+
+		if (i == (XHCI_MAX_COMMANDS - 1)) {
+			i = 0;
+			j ^= 1;
+		}
+	}
+
+	sc->sc_command_idx = i;
+	sc->sc_command_ccs = j;
 }
 
 /*------------------------------------------------------------------------*
@@ -1726,7 +1802,6 @@
 	struct usb_xfer *xfer;
 	void *last_obj;
 	uint32_t ntd;
-	uint32_t nqh;
 	uint32_t n;
 
 	sc = XHCI_BUS2SC(parm->udev->bus);
@@ -1768,8 +1843,6 @@
 
 	usbd_transfer_setup_sub(parm);
 
-	nqh = 1;
-
 	if (xfer->flags_int.isochronous_xfr) {
 		ntd = ((1 * xfer->nframes)
 		    + (xfer->max_data_length / xfer->max_hc_frame_size));
@@ -1817,34 +1890,6 @@
 	}
 	xfer->td_start[xfer->flags_int.curr_dma_set] = last_obj;
 
-	last_obj = NULL;
-
-	if (usbd_transfer_setup_sub_malloc(
-	    parm, &pc, sizeof(struct xhci_qh),
-	    XHCI_QH_ALIGN, nqh)) {
-		parm->err = USB_ERR_NOMEM;
-		return;
-	}
-	if (parm->buf) {
-		for (n = 0; n != nqh; n++) {
-			struct xhci_qh *qh;
-
-			usbd_get_page(pc + n, 0, &page_info);
-
-			qh = page_info.buffer;
-
-			/* init QH */
-			qh->qh_self = htole64((uint64_t)page_info.physaddr);
-			qh->obj_next = last_obj;
-			qh->page_cache = pc + n;
-
-			last_obj = qh;
-
-			usb_pc_cpu_flush(pc + n);
-		}
-	}
-	xfer->qh_start[xfer->flags_int.curr_dma_set] = last_obj;
-
 	if (!xfer->flags_int.curr_dma_set) {
 		xfer->flags_int.curr_dma_set = 1;
 		goto alloc_dma_set;

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#8 (text+ko) ====

@@ -189,6 +189,7 @@
 #define	XHCI_TRB_3_TYPE_GET(x)		(((x) >> 10) & 0x3F)
 #define	XHCI_TRB_3_TYPE_SET(x)		(((x) & 0x3F) << 10)
 #define	XHCI_TRB_3_CYCLE_BIT		(1U << 0)
+#define	XHCI_TRB_3_TC_BIT		(1U << 1)
 #define	XHCI_TRB_3_ENT_BIT		(1U << 1)
 #define	XHCI_TRB_3_ISP_BIT		(1U << 2)
 #define	XHCI_TRB_3_NSNOOP_BIT		(1U << 3)
@@ -304,13 +305,9 @@
 
 } __aligned(XHCI_TRB_ALIGN);
 
-struct xhci_qh {
+struct xhci_command {
 	struct xhci_trb trb;
-
-	TAILQ_ENTRY(xhci_qh) entry;
-	uint64_t td_self;
-	struct xhci_qh *obj_next;
-	struct usb_page_cache *page_cache;
+	TAILQ_ENTRY(xhci_command) entry;
 };
 
 struct xhci_event_ring_seg {
@@ -385,6 +382,8 @@
 
 	union xhci_hub_desc sc_hub_desc;
 
+	TAILQ_HEAD(, xhci_command) sc_cmd_head;
+
 	struct usb_device *sc_devices[XHCI_MAX_DEVICES];
 	struct resource *sc_io_res;
 	struct resource *sc_irq_res;
@@ -395,6 +394,7 @@
 	bus_space_handle_t sc_io_hdl;
 
 	uint32_t sc_cmd;		/* copy of cmd register */
+	uint32_t sc_cmd_dp;		/* copy of command dequeue pointer */
 
 	uint32_t sc_oper_off;		/* offset to operational registers */
 	uint32_t sc_capa_off;		/* offset to capability registers */
@@ -404,8 +404,10 @@
 	uint16_t sc_flags;		/* chip specific flags */
 	uint16_t sc_erst_max;
 	uint16_t sc_event_idx;
+	uint16_t sc_command_idx;
 
 	uint8_t sc_event_ccs;
+	uint8_t sc_command_ccs;
 	uint8_t	sc_nodev;		/* number of devices on root HUB */
 	uint8_t	sc_noport;		/* number of ports on root HUB */
 	uint8_t	sc_addr;		/* root HUB device address */



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