Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-6]: src/sys/dev/usb Pull up following revision(s) (requested by s...
details: https://anonhg.NetBSD.org/src/rev/ace44aa2d6dc
branches: netbsd-6
changeset: 775707:ace44aa2d6dc
user: riz <riz%NetBSD.org@localhost>
date: Mon Feb 18 18:13:05 2013 +0000
description:
Pull up following revision(s) (requested by skrll in ticket #827):
sys/dev/usb/dwc_otg.c: revision 1.46
sys/dev/usb/dwc_otgvar.h: revision 1.12
Track transfer state better to avoid races between the workqueue and
aborting.
diffstat:
sys/dev/usb/dwc_otg.c | 60 +++++++++++++++++++++++++++++++++--------------
sys/dev/usb/dwc_otgvar.h | 12 +++++++--
2 files changed, 51 insertions(+), 21 deletions(-)
diffs (177 lines):
diff -r 8268313c897a -r ace44aa2d6dc sys/dev/usb/dwc_otg.c
--- a/sys/dev/usb/dwc_otg.c Mon Feb 18 18:10:58 2013 +0000
+++ b/sys/dev/usb/dwc_otg.c Mon Feb 18 18:13:05 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_otg.c,v 1.45.2.3 2013/02/15 08:21:21 msaitoh Exp $ */
+/* $NetBSD: dwc_otg.c,v 1.45.2.4 2013/02/18 18:13:05 riz Exp $ */
/*-
* Copyright (c) 2012 Hans Petter Selasky. All rights reserved.
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_otg.c,v 1.45.2.3 2013/02/15 08:21:21 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_otg.c,v 1.45.2.4 2013/02/18 18:13:05 riz Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -411,13 +411,20 @@
mutex_spin_enter(&sc->sc_intr_lock);
while ((dxfer = TAILQ_FIRST(&sc->sc_complete)) != NULL) {
- TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext);
-
+ KASSERT(dxfer->state == DXFER_COMPLETING);
+
+ /*
+ * dwc_otg_abort_xfer will remove this transfer from the
+ * sc_complete queue
+ */
if (dxfer->xfer.hcflags & UXFER_ABORTING) {
wakeup(&dxfer->xfer.hcflags);
continue;
}
+ TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext);
+ dxfer->state = DXFER_DONE;
+
mutex_spin_exit(&sc->sc_intr_lock);
usb_transfer_complete(&dxfer->xfer);
mutex_spin_enter(&sc->sc_intr_lock);
@@ -616,9 +623,23 @@
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
- if (dxfer->active) {
+ switch (dxfer->state) {
+ case DXFER_INIT:
+ dxfer->state = DXFER_ABORTING;
+ break;
+ case DXFER_WORKQ:
+ /* Give the workqueue a chance */
+ break;
+ case DXFER_ACTIVE:
TAILQ_REMOVE(&sc->sc_active, dxfer, xnext);
- dxfer->active = false;
+ dxfer->state = DXFER_ABORTING;
+ break;
+ case DXFER_COMPLETING:
+ TAILQ_REMOVE(&sc->sc_complete, dxfer, xnext);
+ dxfer->state = DXFER_ABORTING;
+ break;
+ default:
+ KASSERT(false);
}
mutex_spin_exit(&sc->sc_intr_lock);
@@ -626,10 +647,11 @@
dwc_otg_host_channel_free(dxfer->td_transfer_cache);
}
- while (dxfer->queued) {
- wakeup(&xfer->hcflags);
+ while (dxfer->state != DXFER_ABORTING) {
+ tsleep(&xfer->hcflags, PZERO, "dotgxw", 0);
}
+ dxfer->state = DXFER_DONE;
/*
* Step 2: Execute callback.
*/
@@ -1598,15 +1620,15 @@
dwc_otg_timer(sc);
} else {
KASSERT(dwork->xfer != NULL);
- KASSERT(dxfer->queued == true);
+ KASSERT(dxfer->state == DXFER_WORKQ);
if (!(xfer->hcflags & UXFER_ABORTING)) {
dwc_otg_start_standard_chain(xfer);
+ } else {
+ dxfer->state = DXFER_ABORTING;
+ wakeup(&xfer->hcflags);
}
- dxfer->queued = false;
- wakeup(&xfer->hcflags);
}
-
}
int dwc_otg_intr(void *p)
@@ -3778,7 +3800,7 @@
// DPRINTF(("%s: xfer->length %d\n", __func__, xfer->length));
- dxfer->queued = false;
+ dxfer->state = DXFER_INIT;
/* get first again */
td = dxfer->td_transfer_first;
@@ -3887,11 +3909,13 @@
/* poll one time - will turn on interrupts */
mutex_spin_enter(&sc->sc_intr_lock);
+ dxfer->state = DXFER_STARTED;
+
if (dwc_otg_xfer_do_fifo(xfer)) {
/* put transfer on interrupt queue */
- dxfer->active = true;
+ dxfer->state = DXFER_ACTIVE;
TAILQ_INSERT_TAIL(&sc->sc_active, dxfer, xnext);
/* start timeout, if any */
@@ -3980,12 +4004,12 @@
dwc_otg_host_channel_free(td);
xfer->status = err;
- if (dxfer->active) {
+ if (dxfer->state == DXFER_ACTIVE) {
TAILQ_REMOVE(&sc->sc_active, dxfer, xnext);
- dxfer->active = false;
}
callout_stop(&xfer->timeout_handle);
+ dxfer->state = DXFER_COMPLETING;
TAILQ_INSERT_TAIL(&sc->sc_complete, dxfer, xnext);
usb_schedsoftintr(&sc->sc_bus);
@@ -4324,8 +4348,8 @@
if (sc->sc_bus.use_polling) {
dwc_otg_start_standard_chain(xfer);
} else {
- KASSERT(dxfer->queued == false);
- dxfer->queued = true;
+ KASSERT(dxfer->state == DXFER_INIT);
+ dxfer->state = DXFER_WORKQ;
workqueue_enqueue(sc->sc_wq, (struct work *)&dxfer->work, NULL);
}
}
diff -r 8268313c897a -r ace44aa2d6dc sys/dev/usb/dwc_otgvar.h
--- a/sys/dev/usb/dwc_otgvar.h Mon Feb 18 18:10:58 2013 +0000
+++ b/sys/dev/usb/dwc_otgvar.h Mon Feb 18 18:13:05 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_otgvar.h,v 1.11.2.3 2013/02/14 21:50:41 riz Exp $ */
+/* $NetBSD: dwc_otgvar.h,v 1.11.2.4 2013/02/18 18:13:05 riz Exp $ */
/* $FreeBSD: src/sys/dev/usb/controller/dwc_otg.h,v 1.12 2012/09/27 15:23:38 hselasky Exp $ */
/*-
@@ -158,8 +158,14 @@
struct usbd_xfer xfer; /* Needs to be first */
struct usb_task abort_task;
TAILQ_ENTRY(dwc_otg_xfer) xnext; /* list of active/complete xfers */
- bool queued; /* pending workqueue */
- bool active; /* still active */
+ int state;
+#define DXFER_INIT 0
+#define DXFER_WORKQ 1
+#define DXFER_STARTED 2
+#define DXFER_ACTIVE 3
+#define DXFER_COMPLETING 4
+#define DXFER_ABORTING 5
+#define DXFER_DONE 6
void *td_start[1];
dwc_otg_td_t *td_transfer_first;
Home |
Main Index |
Thread Index |
Old Index