PERFORCE change 182090 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Aug 8 14:59:20 UTC 2010
http://p4web.freebsd.org/@@182090?ac=10
Change 182090 by hselasky at hselasky_laptop001 on 2010/08/08 14:58:42
USB controller (XHCI):
- more bugfixes
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#17 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#17 (text+ko) ====
@@ -652,7 +652,7 @@
status = XHCI_TRB_2_ERROR_GET(temp);
temp = le32toh(trb->dwTrb3);
- epno = XHCI_TRB_3_EP_GET(temp) + 1;
+ epno = XHCI_TRB_3_EP_GET(temp);
index = XHCI_TRB_3_SLOT_GET(temp);
/* check if error means halted */
@@ -667,9 +667,7 @@
return;
}
- epno++;
-
- if (epno >= XHCI_MAX_ENDPOINTS) {
+ if ((epno == 0) || (epno >= XHCI_MAX_ENDPOINTS)) {
DPRINTF("Invalid endpoint.\n");
return;
}
@@ -688,14 +686,15 @@
td = xfer->td_transfer_cache;
- DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx)\n",
+ DPRINTFN(5, "Checking if 0x%016llx == (0x%016llx .. 0x%016llx +/- 16)\n",
(long long)td_event,
(long long)td->td_self,
(long long)td->td_event_last);
if ((td_event == td->td_event_last) ||
+ (td_event == (td->td_event_last - 16)) ||
(halted && (td_event >= td->td_self) &&
- (td_event < td->td_event_last))) {
+ (td_event <= td->td_event_last))) {
usb_pc_cpu_invalidate(td->page_cache);
@@ -1066,17 +1065,18 @@
switch (hdev->state) {
case XHCI_ST_ADDRESSED:
+ case XHCI_ST_CONFIGURED:
err = 0;
break;
- case XHCI_ST_ENABLED:
+ case XHCI_ST_DEFAULT:
if (address == 0) {
err = 0;
break;
}
/* FALLTHROUGH */
- case XHCI_ST_DEFAULT:
+ case XHCI_ST_ENABLED:
/* set configure mask to slot and EP0 */
xhci_configure_mask(udev, 3, 0);
@@ -1149,7 +1149,6 @@
return (err);
}
-#if 0
static usb_error_t
xhci_cmd_configure_ep(struct xhci_softc *sc, uint64_t input_ctx,
uint8_t deconfigure, uint8_t slot_id)
@@ -1171,7 +1170,6 @@
return (xhci_do_command(sc, &trb, 50 /* ms */));
}
-#endif
static usb_error_t
xhci_cmd_evaluate_ctx(struct xhci_softc *sc, uint64_t input_ctx,
@@ -1546,7 +1544,7 @@
/* compute event pointer */
addr = td->td_self;
- addr += (x - 1) * sizeof(struct xhci_trb);
+ addr += x * sizeof(struct xhci_trb);
td->td_event_last = addr;
/* fill out link TRB */
@@ -2046,8 +2044,16 @@
route |= rh_port;
}
- temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1) |
- XHCI_SCTX_0_ROUTE_SET(route);
+ temp = XHCI_SCTX_0_ROUTE_SET(route);
+
+ switch (sc->sc_hw.devs[index].state) {
+ case XHCI_ST_CONFIGURED:
+ temp |= XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1);
+ break;
+ default:
+ temp = XHCI_SCTX_0_CTX_NUM_SET(1);
+ break;
+ }
switch (udev->speed) {
case USB_SPEED_LOW:
@@ -2298,10 +2304,15 @@
uint64_t addr;
uint8_t i;
uint8_t inext;
+ uint8_t trb_limit;
+
+ DPRINTFN(8, "\n");
/* check if already inserted */
- if (xfer->flags_int.bandwidth_reclaimed)
+ if (xfer->flags_int.bandwidth_reclaimed) {
+ DPRINTFN(8, "Already in schedule\n");
return (0);
+ }
pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
xfer->endpoint->edesc);
@@ -2310,7 +2321,19 @@
td_last = xfer->td_transfer_last;
addr = pepext->physaddr;
- if (pepext->trb_used >= (XHCI_MAX_TRANSFERS - 1)) {
+ switch (xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_CONTROL:
+ case UE_INTERRUPT:
+ /* single buffered */
+ trb_limit = 1;
+ break;
+ default:
+ /* multi buffered */
+ trb_limit = (XHCI_MAX_TRANSFERS - 2);
+ break;
+ }
+
+ if (pepext->trb_used >= trb_limit) {
DPRINTFN(8, "Too many TDs queued.\n");
return (USB_ERR_NOMEM);
}
@@ -2331,6 +2354,8 @@
if (pepext->trb_running == 0) {
struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
+ DPRINTFN(8, "Not running\n");
+
/* start configuration */
(void)usb_proc_msignal(&sc->sc_config_proc,
&sc->sc_config_msg[0], &sc->sc_config_msg[1]);
@@ -2386,6 +2411,8 @@
usb_pc_cpu_flush(pepext->page_cache);
+ DPRINTF("qh_pos = %u\n", i);
+
pepext->xfer[i] = xfer;
xfer->qh_pos = i;
@@ -2396,6 +2423,10 @@
xhci_endpoint_doorbell(xfer);
+ /* start timeout, if any */
+ if (xfer->timeout != 0)
+ usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
+
return (0);
}
@@ -2482,14 +2513,7 @@
DPRINTF("\n");
/* try to insert xfer on HW queue */
- if (xhci_transfer_insert(xfer) != 0) {
- DPRINTFN(0, "Failed to insert "
- "transfer %p into HW queue.\n", xfer);
- }
-
- /* start timeout, if any */
- if (xfer->timeout != 0)
- usbd_transfer_timeout_ms(xfer, &xhci_timeout, xfer->timeout);
+ xhci_transfer_insert(xfer);
}
struct usb_pipe_methods xhci_device_generic_methods =
@@ -3181,6 +3205,8 @@
struct usb_page_search buf_hub;
+ DPRINTF("Configure HUB\n");
+
usbd_get_page(&sc->sc_hw.devs[
hub->controller_slot_id].input_pc, 0, &buf_hub);
@@ -3203,17 +3229,42 @@
err = xhci_configure_endpoint_by_xfer(xfer);
if (err == 0) {
- err = xhci_cmd_stop_ep(sc, 0, epno - 1, index);
+
+ err = xhci_cmd_reset_ep(sc, 0, epno, index);
if (err != 0)
- DPRINTF("Could not stop endpoint\n");
+ DPRINTF("Could not reset endpoint %u\n", epno);
+
+ if (epno > 1) {
+
+ err = xhci_cmd_stop_ep(sc, 0, epno, index);
+
+ if (err != 0)
+ DPRINTF("Could not stop endpoint %u\n", epno);
+
+ if (sc->sc_hw.devs[index].state != XHCI_ST_CONFIGURED) {
+ sc->sc_hw.devs[index].state = XHCI_ST_CONFIGURED;
+
+ xhci_configure_mask(udev, 1, 0);
+
+ err = xhci_configure_device(udev);
+
+ if (err != 0)
+ DPRINTF("Could not deconfigure device\n");
+
+ err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+
+ if (err != 0)
+ DPRINTF("Could not evaluate device\n");
+ }
- xhci_configure_mask(udev, 1U << epno, 1);
+ xhci_configure_mask(udev, 1U << epno, 1);
- err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+ err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
- if (err != 0)
- DPRINTF("Could not deconfigure endpoint %u\n", epno);
+ if (err != 0)
+ DPRINTF("Could not deconfigure endpoint %u\n", epno);
+ }
xhci_configure_mask(udev, 1U << epno, 0);
@@ -3221,20 +3272,20 @@
if (err != 0)
DPRINTF("Could not configure endpoint %u\n", epno);
+
+ err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+
+ if (err != 0)
+ DPRINTF("Could not configure endpoint %u\n", epno);
}
/* reset endpoint */
if (err == 0) {
- if ((edesc->bmAttributes & UE_XFERTYPE) == UE_BULK)
- err = xhci_cmd_reset_ep(sc, 0, epno - 1, index);
+ err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr |
+ XHCI_EPCTX_2_DCS_SET(1), 0, epno, index);
if (err != 0)
- DPRINTF("Could not reset endpoint %u\n", epno);
-
- err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr, 0, epno - 1, index);
-
- if (err != 0)
DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno);
}
XHCI_CMD_UNLOCK(sc);
@@ -3302,7 +3353,7 @@
/* check if halted is still cleared */
if (pepext->trb_halted == 0) {
pepext->trb_running = 1;
- pepext->trb_index = 1;
+ pepext->trb_index = 0;
}
goto restart;
}
@@ -3317,7 +3368,6 @@
/* queue changed - restart */
goto restart;
-
}
}
More information about the p4-projects
mailing list