Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/nick-nhusb]: src/sys/dev/usb Split xhci_handle_event() into 3 functions....
details: https://anonhg.NetBSD.org/src/rev/92c97113b707
branches: nick-nhusb
changeset: 804382:92c97113b707
user: skrll <skrll%NetBSD.org@localhost>
date: Sun Sep 13 06:50:09 2015 +0000
description:
Split xhci_handle_event() into 3 functions. Whitespace.
>From t-hash.
diffstat:
sys/dev/usb/xhci.c | 349 +++++++++++++++++++++++++++++-----------------------
1 files changed, 196 insertions(+), 153 deletions(-)
diffs (truncated from 399 to 300 lines):
diff -r f0e010f0e91e -r 92c97113b707 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c Sun Sep 13 06:48:03 2015 +0000
+++ b/sys/dev/usb/xhci.c Sun Sep 13 06:50:09 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xhci.c,v 1.28.2.35 2015/09/13 06:48:03 skrll Exp $ */
+/* $NetBSD: xhci.c,v 1.28.2.36 2015/09/13 06:50:09 skrll Exp $ */
/*
* Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.35 2015/09/13 06:48:03 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.36 2015/09/13 06:50:09 skrll Exp $");
#include "opt_usb.h"
@@ -1677,9 +1677,7 @@
#endif /* XXX experimental */
-/*
- * Notify roothub port status/change to uhub_intr.
- */
+/* Process roothub port status/change events and notify to uhub_intr. */
static void
xhci_rhpsc(struct xhci_softc * const sc, u_int port)
{
@@ -1704,11 +1702,180 @@
usb_transfer_complete(xfer);
}
+/* Process Transfer Events */
+static void
+xhci_event_transfer(struct xhci_softc * const sc,
+ const struct xhci_trb * const trb)
+{
+ uint64_t trb_0;
+ uint32_t trb_2, trb_3;
+ uint8_t trbcode;
+ u_int slot, dci;
+ struct xhci_slot *xs;
+ struct xhci_ring *xr;
+ struct xhci_xfer *xx;
+ struct usbd_xfer *xfer;
+ usbd_status err;
+
+ XHCIHIST_FUNC(); XHCIHIST_CALLED();
+
+ trb_0 = le64toh(trb->trb_0);
+ trb_2 = le32toh(trb->trb_2);
+ trb_3 = le32toh(trb->trb_3);
+ trbcode = XHCI_TRB_2_ERROR_GET(trb_2);
+ slot = XHCI_TRB_3_SLOT_GET(trb_3);
+ dci = XHCI_TRB_3_EP_GET(trb_3);
+ xs = &sc->sc_slots[slot];
+ xr = &xs->xs_ep[dci].xe_tr;
+
+ /* sanity check */
+ if (xs->xs_idx == 0 || xs->xs_idx >= sc->sc_maxslots) {
+ DPRINTFN(1, "invalid slot %u", xs->xs_idx, 0, 0, 0);
+ return;
+ }
+
+ if ((trb_3 & XHCI_TRB_3_ED_BIT) == 0) {
+ bus_addr_t trbp = xhci_ring_trbp(xr, 0);
+
+ /* trb_0 range sanity check */
+ if (trb_0 < trbp ||
+ (trb_0 - trbp) % sizeof(struct xhci_trb) != 0 ||
+ (trb_0 - trbp) / sizeof(struct xhci_trb) >=
+ xr->xr_ntrb) {
+ DPRINTFN(1, "invalid trb_0 0x%"PRIx64" trbp 0x%"PRIx64,
+ trb_0, trbp, 0, 0);
+ return;
+ }
+ int idx = (trb_0 - trbp) / sizeof(struct xhci_trb);
+ xx = xr->xr_cookies[idx];
+ } else {
+ xx = (void *)(uintptr_t)(trb_0 & ~0x3);
+ }
+ /* XXX this may not happen */
+ if (xx == NULL) {
+ DPRINTFN(1, "xfer done: xx is NULL", 0, 0, 0, 0);
+ return;
+ }
+ xfer = &xx->xx_xfer;
+ /* XXX this may happen when detaching */
+ if (xfer == NULL) {
+ DPRINTFN(1, "xfer done: xfer is NULL", 0, 0, 0, 0);
+ return;
+ }
+ DPRINTFN(14, "xfer %p", xfer, 0, 0, 0);
+ /* XXX I dunno why this happens */
+ KASSERT(xfer->ux_pipe != NULL);
+
+ if (!xfer->ux_pipe->up_repeat &&
+ SIMPLEQ_EMPTY(&xfer->ux_pipe->up_queue)) {
+ DPRINTFN(1, "xfer done: xfer not started", 0, 0, 0, 0);
+ return;
+ }
+
+ if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
+ DPRINTFN(14, "transfer event data: "
+ "0x%016"PRIx64" 0x%08"PRIx32" %02x",
+ trb_0, XHCI_TRB_2_REM_GET(trb_2),
+ XHCI_TRB_2_ERROR_GET(trb_2), 0);
+ if ((trb_0 & 0x3) == 0x3) {
+ xfer->ux_actlen = XHCI_TRB_2_REM_GET(trb_2);
+ }
+ }
+
+ switch (trbcode) {
+ case XHCI_TRB_ERROR_SHORT_PKT:
+ case XHCI_TRB_ERROR_SUCCESS:
+ xfer->ux_actlen =
+ xfer->ux_length - XHCI_TRB_2_REM_GET(trb_2);
+ err = USBD_NORMAL_COMPLETION;
+ break;
+ case XHCI_TRB_ERROR_STALL:
+ case XHCI_TRB_ERROR_BABBLE:
+ DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
+ trbcode, slot, dci, 0);
+ xr->is_halted = true;
+ err = USBD_STALLED;
+#if 1 /* XXX experimental */
+ /*
+ * Stalled endpoints can be recoverd by issuing
+ * command TRB TYPE_RESET_EP on xHCI instead of
+ * issuing request CLEAR_PORT_FEATURE UF_ENDPOINT_HALT
+ * on the endpoint. However, this function may be
+ * called from softint context (e.g. from umass),
+ * in that case driver gets KASSERT in cv_timedwait
+ * in xhci_do_command.
+ * To avoid this, this runs reset_endpoint and
+ * usb_transfer_complete in usb task thread
+ * asynchronously (and then umass issues clear
+ * UF_ENDPOINT_HALT).
+ */
+ xfer->ux_status = err;
+ xhci_clear_endpoint_stall_async(xfer);
+ return;
+#else
+ break;
+#endif
+ case XHCI_TRB_ERROR_CMD_ABORTED:
+ case XHCI_TRB_ERROR_STOPPED:
+ err = USBD_CANCELLED;
+ break;
+ case XHCI_TRB_ERROR_NO_SLOTS:
+ err = USBD_NO_ADDR;
+ break;
+ default:
+ DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
+ trbcode, slot, dci, 0);
+ err = USBD_IOERROR;
+ break;
+ }
+ xfer->ux_status = err;
+
+ //mutex_enter(&sc->sc_lock); /* XXX ??? */
+ if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
+ if ((trb_0 & 0x3) == 0x0) {
+ usb_transfer_complete(xfer);
+ }
+ } else {
+ usb_transfer_complete(xfer);
+ }
+ //mutex_exit(&sc->sc_lock); /* XXX ??? */
+}
+
+/* Process Command complete events */
+static void
+xhci_event_cmd(struct xhci_softc * const sc,
+ const struct xhci_trb * const trb)
+{
+ uint64_t trb_0;
+ uint32_t trb_2, trb_3;
+
+ XHCIHIST_FUNC(); XHCIHIST_CALLED();
+
+ trb_0 = le64toh(trb->trb_0);
+ trb_2 = le32toh(trb->trb_2);
+ trb_3 = le32toh(trb->trb_3);
+
+ if (trb_0 == sc->sc_command_addr) {
+ sc->sc_result_trb.trb_0 = trb_0;
+ sc->sc_result_trb.trb_2 = trb_2;
+ sc->sc_result_trb.trb_3 = trb_3;
+ if (XHCI_TRB_2_ERROR_GET(trb_2) !=
+ XHCI_TRB_ERROR_SUCCESS) {
+ DPRINTFN(1, "command completion "
+ "failure: 0x%016"PRIx64" 0x%08"PRIx32" "
+ "0x%08"PRIx32, trb_0, trb_2, trb_3, 0);
+ }
+ cv_signal(&sc->sc_command_cv);
+ } else {
+ DPRINTFN(1, "spurious event: %p 0x%016"PRIx64" "
+ "0x%08"PRIx32" 0x%08"PRIx32, trb, trb_0,
+ trb_2, trb_3);
+ }
+}
+
/*
- * Process events:
- * + Transfer comeplete
- * + Command complete
- * + Roothub Port status/change
+ * Process events.
+ * called from xhci_softintr
*/
static void
xhci_handle_event(struct xhci_softc * const sc,
@@ -1716,164 +1883,40 @@
{
uint64_t trb_0;
uint32_t trb_2, trb_3;
- uint8_t trberr;
XHCIHIST_FUNC(); XHCIHIST_CALLED();
+ KASSERT(mutex_owned(&sc->sc_lock));
+
trb_0 = le64toh(trb->trb_0);
trb_2 = le32toh(trb->trb_2);
trb_3 = le32toh(trb->trb_3);
- trberr = XHCI_TRB_2_ERROR_GET(trb_2);
DPRINTFN(14, "event: %p 0x%016"PRIx64" 0x%08"PRIx32" 0x%08"PRIx32,
trb, trb_0, trb_2, trb_3);
- switch (XHCI_TRB_3_TYPE_GET(trb_3)) {
- case XHCI_TRB_EVENT_TRANSFER: {
- u_int slot, dci;
- struct xhci_slot *xs;
- struct xhci_ring *xr;
- struct xhci_xfer *xx;
- struct usbd_xfer *xfer;
- usbd_status err;
-
- slot = XHCI_TRB_3_SLOT_GET(trb_3);
- dci = XHCI_TRB_3_EP_GET(trb_3);
-
- xs = &sc->sc_slots[slot];
- xr = &xs->xs_ep[dci].xe_tr;
- /* sanity check */
- if (xs->xs_idx == 0 || xs->xs_idx >= sc->sc_maxslots) {
- DPRINTFN(1, "invalid slot %u", xs->xs_idx, 0, 0, 0);
- break;
- }
-
- if ((trb_3 & XHCI_TRB_3_ED_BIT) == 0) {
- bus_addr_t trbp = xhci_ring_trbp(xr, 0);
-
- /* trb_0 range sanity check */
- if (trb_0 < trbp ||
- (trb_0 - trbp) % sizeof(struct xhci_trb) != 0 ||
- (trb_0 - trbp) / sizeof(struct xhci_trb) >=
- xr->xr_ntrb) {
- DPRINTFN(1,
- "invalid trb_0 0x%"PRIx64" trbp 0x%"PRIx64,
- trb_0, trbp, 0, 0);
- break;
- }
- int idx = (trb_0 - trbp) / sizeof(struct xhci_trb);
- xx = xr->xr_cookies[idx];
- } else {
- xx = (void *)(uintptr_t)(trb_0 & ~0x3);
- }
- /* XXX this may not happen */
- if (xx == NULL) {
- DPRINTFN(1, "xfer done: xx is NULL", 0, 0, 0, 0);
- break;
- }
- xfer = &xx->xx_xfer;
- /* XXX this may happen when detaching */
- if (xfer == NULL) {
- DPRINTFN(1, "xfer done: xfer is NULL", 0, 0, 0, 0);
- break;
- }
- DPRINTFN(14, "xfer %p", xfer, 0, 0, 0);
- /* XXX I dunno why this happens */
- KASSERT(xfer->ux_pipe != NULL);
-
- if (!xfer->ux_pipe->up_repeat &&
- SIMPLEQ_EMPTY(&xfer->ux_pipe->up_queue)) {
- DPRINTFN(1, "xfer done: xfer not started", 0, 0, 0, 0);
- break;
- }
-
- if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
- DPRINTFN(14, "transfer event data: "
- "0x%016"PRIx64" 0x%08"PRIx32" %02x",
- trb_0, XHCI_TRB_2_REM_GET(trb_2),
- XHCI_TRB_2_ERROR_GET(trb_2), 0);
- if ((trb_0 & 0x3) == 0x3) {
- xfer->ux_actlen = XHCI_TRB_2_REM_GET(trb_2);
- }
- }
Home |
Main Index |
Thread Index |
Old Index