From owner-p4-projects@FreeBSD.ORG Sun Aug 1 09:46:43 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 77F081065678; Sun, 1 Aug 2010 09:46:43 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3BD051065672 for ; Sun, 1 Aug 2010 09:46:43 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 28B368FC19 for ; Sun, 1 Aug 2010 09:46:43 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.4/8.14.4) with ESMTP id o719kgZb061050 for ; Sun, 1 Aug 2010 09:46:42 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.4/8.14.4/Submit) id o719kg3G061048 for perforce@freebsd.org; Sun, 1 Aug 2010 09:46:42 GMT (envelope-from hselasky@FreeBSD.org) Date: Sun, 1 Aug 2010 09:46:42 GMT Message-Id: <201008010946.o719kg3G061048@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 181670 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 01 Aug 2010 09:46:43 -0000 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 */