Module Name: src
Committed By: skrll
Date: Wed Oct 2 22:55:04 UTC 2013
Modified Files:
src/sys/dev/ic: sl811hs.c sl811hsvar.h
Log Message:
Modernise slhci. Many thanks to rkujawa@ for testing.
To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/dev/ic/sl811hs.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/ic/sl811hsvar.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/sl811hs.c
diff -u src/sys/dev/ic/sl811hs.c:1.40 src/sys/dev/ic/sl811hs.c:1.41
--- src/sys/dev/ic/sl811hs.c:1.40 Mon Sep 23 11:27:45 2013
+++ src/sys/dev/ic/sl811hs.c Wed Oct 2 22:55:04 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: sl811hs.c,v 1.40 2013/09/23 11:27:45 skrll Exp $ */
+/* $NetBSD: sl811hs.c,v 1.41 2013/10/02 22:55:04 skrll Exp $ */
/*
* Not (c) 2007 Matthew Orgass
@@ -55,23 +55,6 @@
*
* Since this driver attaches to pcmcia, card removal at any point should be
* expected and not cause panics or infinite loops.
- *
- * This driver does fine grained locking for its own data structures, however
- * the general USB code does not yet have locks, some of which would need to
- * be used in this driver. This is mostly for debug use on single processor
- * systems.
- *
- * The theory of the wait lock is that start is the only function that would
- * be frequently called from arbitrary processors, so it should not need to
- * wait for the rest to be completed. However, once entering the lock as much
- * device access as possible is done, so any other CPU that tries to service
- * an interrupt would be blocked. Ideally, the hard and soft interrupt could
- * be assigned to the same CPU and start would normally just put work on the
- * wait queue and generate a soft interrupt.
- *
- * Any use of the main lock must check the wait lock before returning. The
- * aquisition order is main lock then wait lock, but the wait lock must be
- * released last when clearing the wait queue.
*/
/*
@@ -85,7 +68,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.40 2013/09/23 11:27:45 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.41 2013/10/02 22:55:04 skrll Exp $");
#include "opt_slhci.h"
@@ -98,7 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/gcq.h>
-#include <sys/simplelock.h>
#include <sys/intr.h>
#include <sys/cpu.h>
#include <sys/bus.h>
@@ -313,10 +295,6 @@ struct slhci_pipe {
uint8_t ptype; /* Pipe type */
};
-#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
-#define SLHCI_WAITLOCK 1
-#endif
-
#ifdef SLHCI_PROFILE_TRANSFER
#if defined(__mips__)
/*
@@ -449,6 +427,7 @@ usbd_status slhci_allocm(struct usbd_bus
void slhci_freem(struct usbd_bus *, usb_dma_t *);
struct usbd_xfer * slhci_allocx(struct usbd_bus *);
void slhci_freex(struct usbd_bus *, struct usbd_xfer *);
+static void slhci_get_lock(struct usbd_bus *, kmutex_t **);
usbd_status slhci_transfer(struct usbd_xfer *);
usbd_status slhci_start(struct usbd_xfer *);
@@ -478,11 +457,11 @@ usbd_status slhci_lock_call(struct slhci
struct slhci_pipe *, struct usbd_xfer *);
void slhci_start_entry(struct slhci_softc *, struct slhci_pipe *);
void slhci_callback_entry(void *arg);
-void slhci_do_callback(struct slhci_softc *, struct usbd_xfer *, int *);
+void slhci_do_callback(struct slhci_softc *, struct usbd_xfer *);
/* slhci_intr */
-void slhci_main(struct slhci_softc *, int *);
+void slhci_main(struct slhci_softc *);
/* in lock functions */
@@ -497,11 +476,9 @@ static void slhci_abdone(struct slhci_so
static void slhci_tstart(struct slhci_softc *);
static void slhci_dotransfer(struct slhci_softc *);
-static void slhci_callback(struct slhci_softc *, int *);
+static void slhci_callback(struct slhci_softc *);
static void slhci_enter_xfer(struct slhci_softc *, struct slhci_pipe *);
-#ifdef SLHCI_WAITLOCK
static void slhci_enter_xfers(struct slhci_softc *);
-#endif
static void slhci_queue_timed(struct slhci_softc *, struct slhci_pipe *);
static void slhci_xfer_timer(struct slhci_softc *, struct slhci_pipe *);
@@ -509,7 +486,7 @@ static void slhci_do_repeat(struct slhci
static void slhci_callback_schedule(struct slhci_softc *);
static void slhci_do_callback_schedule(struct slhci_softc *);
#if 0
-void slhci_pollxfer(struct slhci_softc *, struct usbd_xfer *, int *); /* XXX */
+void slhci_pollxfer(struct slhci_softc *, struct usbd_xfer *); /* XXX */
#endif
static usbd_status slhci_do_poll(struct slhci_softc *, struct slhci_pipe *,
@@ -524,8 +501,6 @@ static usbd_status slhci_close_pipe(stru
struct usbd_xfer *);
static usbd_status slhci_do_abort(struct slhci_softc *, struct slhci_pipe *,
struct usbd_xfer *);
-static usbd_status slhci_do_attach(struct slhci_softc *, struct slhci_pipe *,
- struct usbd_xfer *);
static usbd_status slhci_halt(struct slhci_softc *, struct slhci_pipe *,
struct usbd_xfer *);
@@ -678,9 +653,6 @@ DDOLOGBUF(uint8_t *buf, unsigned int len
#define DLOGBUF(x, b, l) ((void)0)
#endif /* SLHCI_DEBUG */
-#define SLHCI_MAINLOCKASSERT(sc) ((void)0)
-#define SLHCI_LOCKASSERT(sc, main, wait) ((void)0)
-
#ifdef DIAGNOSTIC
#define LK_SLASSERT(exp, sc, spipe, xfer, ext) do { \
if (!(exp)) { \
@@ -715,7 +687,7 @@ const struct usbd_bus_methods slhci_bus_
.freem = slhci_freem,
.allocx = slhci_allocx,
.freex = slhci_freex,
- .get_lock = NULL,
+ .get_lock = slhci_get_lock,
NULL, /* new_device */
};
@@ -760,7 +732,6 @@ const struct usbd_pipe_methods slhci_roo
#define FIND_TIMED(var, t, tvar, cond) \
GCQ_FIND_TYPED(var, &(t)->timed, tvar, struct slhci_pipe, xq, cond)
-#ifdef SLHCI_WAITLOCK
#define DEQUEUED_WAITQ(tvar, sc) \
GCQ_DEQUEUED_FIRST_TYPED(tvar, &(sc)->sc_waitq, struct slhci_pipe, xq)
@@ -769,7 +740,6 @@ enter_waitq(struct slhci_softc *sc, stru
{
gcq_insert_tail(&sc->sc_waitq, &spipe->xq);
}
-#endif
static inline void
enter_q(struct slhci_transfers *t, struct slhci_pipe *spipe, int i)
@@ -883,17 +853,27 @@ slhci_freex(struct usbd_bus *bus, struct
free(xfer, M_USB);
}
+static void
+slhci_get_lock(struct usbd_bus *bus, kmutex_t **lock)
+{
+ struct slhci_softc *sc = bus->hci_private;
+
+ *lock = &sc->sc_lock;
+}
+
usbd_status
slhci_transfer(struct usbd_xfer *xfer)
{
+ struct slhci_softc *sc = xfer->pipe->device->bus->hci_private;
usbd_status error;
- int s;
DLOG(D_TRACE, "%s transfer xfer %p spipe %p ",
pnames(SLHCI_XFER_TYPE(xfer)), xfer, xfer->pipe,0);
/* Insert last in queue */
+ mutex_enter(&sc->sc_lock);
error = usb_insert_transfer(xfer);
+ mutex_exit(&sc->sc_lock);
if (error) {
if (error != USBD_IN_PROGRESS)
DLOG(D_ERR, "usb_insert_transfer returns %d!", error,
@@ -907,32 +887,30 @@ slhci_transfer(struct usbd_xfer *xfer)
*/
/*
- * Start next is always done at splusb, so we do this here so
- * start functions are always called at softusb. XXX
+ * Start will take the lock.
*/
- s = splusb();
error = xfer->pipe->methods->start(SIMPLEQ_FIRST(&xfer->pipe->queue));
- splx(s);
return error;
}
+#define DWC_OTG_BUS2SC(bus) ((bus)->hci_private)
+
+#define DWC_OTG_PIPE2SC(pipe) DWC_OTG_BUS2SC((pipe)->device->bus)
+
+#define DWC_OTG_XFER2SC(xfer) DWC_OTG_PIPE2SC((xfer)->pipe)
/* It is not safe for start to return anything other than USBD_INPROG. */
usbd_status
slhci_start(struct usbd_xfer *xfer)
{
- struct slhci_softc *sc;
- struct usbd_pipe *pipe;
- struct slhci_pipe *spipe;
- struct slhci_transfers *t;
- usb_endpoint_descriptor_t *ed;
+ struct slhci_softc *sc = xfer->pipe->device->bus->hci_private;
+ struct usbd_pipe *pipe = xfer->pipe;
+ struct slhci_pipe *spipe = (struct slhci_pipe *)pipe;
+ struct slhci_transfers *t = &sc->sc_transfers;
+; usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
unsigned int max_packet;
- pipe = xfer->pipe;
- sc = pipe->device->bus->hci_private;
- spipe = (struct slhci_pipe *)xfer->pipe;
- t = &sc->sc_transfers;
- ed = pipe->endpoint->edesc;
+ mutex_enter(&sc->sc_lock);
max_packet = UGETW(ed->wMaxPacketSize);
@@ -1049,6 +1027,8 @@ slhci_start(struct usbd_xfer *xfer)
slhci_start_entry(sc, spipe);
+ mutex_exit(&sc->sc_lock);
+
return USBD_IN_PROGRESS;
}
@@ -1189,10 +1169,9 @@ slhci_preinit(struct slhci_softc *sc, Po
#ifdef SLHCI_DEBUG
KERNHIST_INIT_STATIC(slhcihist, slhci_he);
#endif
- simple_lock_init(&sc->sc_lock);
-#ifdef SLHCI_WAITLOCK
- simple_lock_init(&sc->sc_wait_lock);
-#endif
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
+ mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED);
+
/* sc->sc_ier = 0; */
/* t->rootintr = NULL; */
t->flags = F_NODEV|F_UDISABLED;
@@ -1214,17 +1193,86 @@ slhci_preinit(struct slhci_softc *sc, Po
gcq_init_head(&t->timed);
gcq_init_head(&t->to);
gcq_init_head(&t->ap);
-#ifdef SLHCI_WAITLOCK
gcq_init_head(&sc->sc_waitq);
-#endif
}
int
slhci_attach(struct slhci_softc *sc)
{
- if (slhci_lock_call(sc, &slhci_do_attach, NULL, NULL) !=
- USBD_NORMAL_COMPLETION)
+ struct slhci_transfers *t;
+ const char *rev;
+
+ t = &sc->sc_transfers;
+
+ /* Detect and check the controller type */
+ t->sltype = SL11_GET_REV(slhci_read(sc, SL11_REV));
+
+ /* SL11H not supported */
+ if (!slhci_supported_rev(t->sltype)) {
+ if (t->sltype == SLTYPE_SL11H)
+ printf("%s: SL11H unsupported or bus error!\n",
+ SC_NAME(sc));
+ else
+ printf("%s: Unknown chip revision!\n", SC_NAME(sc));
return -1;
+ }
+
+ callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
+ callout_setfunc(&sc->sc_timer, slhci_reset_entry, sc);
+
+ /*
+ * It is not safe to call the soft interrupt directly as
+ * usb_schedsoftintr does in the use_polling case (due to locking).
+ */
+ sc->sc_cb_softintr = softint_establish(SOFTINT_NET,
+ slhci_callback_entry, sc);
+
+#ifdef SLHCI_DEBUG
+ ssc = sc;
+#ifdef USB_DEBUG
+ if (slhci_usbdebug >= 0)
+ usbdebug = slhci_usbdebug;
+#endif
+#endif
+
+ if (t->sltype == SLTYPE_SL811HS_R12)
+ rev = " (rev 1.2)";
+ else if (t->sltype == SLTYPE_SL811HS_R14)
+ rev = " (rev 1.4 or 1.5)";
+ else
+ rev = " (unknown revision)";
+
+ aprint_normal("%s: ScanLogic SL811HS/T USB Host Controller %s\n",
+ SC_NAME(sc), rev);
+
+ aprint_normal("%s: Max Current %u mA (value by code, not by probe)\n",
+ SC_NAME(sc), t->max_current * 2);
+
+#if defined(SLHCI_DEBUG) || defined(SLHCI_NO_OVERTIME) || \
+ defined(SLHCI_TRY_LSVH) || defined(SLHCI_PROFILE_TRANSFER)
+ aprint_normal("%s: driver options:"
+#ifdef SLHCI_DEBUG
+ " SLHCI_DEBUG"
+#endif
+#ifdef SLHCI_TRY_LSVH
+ " SLHCI_TRY_LSVH"
+#endif
+#ifdef SLHCI_NO_OVERTIME
+ " SLHCI_NO_OVERTIME"
+#endif
+#ifdef SLHCI_PROFILE_TRANSFER
+ " SLHCI_PROFILE_TRANSFER"
+#endif
+ "\n", SC_NAME(sc));
+#endif
+ sc->sc_bus.usbrev = USBREV_1_1;
+ sc->sc_bus.methods = __UNCONST(&slhci_bus_methods);
+ sc->sc_bus.pipe_size = sizeof(struct slhci_pipe);
+
+ if (!sc->sc_enable_power)
+ t->flags |= F_REALPOWER;
+
+ t->flags |= F_ACTIVE;
/* Attach usb and uhub. */
sc->sc_child = config_found(SC_DEV(sc), &sc->sc_bus, usbctlprint);
@@ -1257,6 +1305,9 @@ slhci_detach(struct slhci_softc *sc, int
softint_disestablish(sc->sc_cb_softintr);
+ mutex_destroy(&sc->sc_lock);
+ mutex_destroy(&sc->sc_intr_lock);
+
ret = 0;
if (sc->sc_child)
@@ -1294,6 +1345,8 @@ slhci_abort(struct usbd_xfer *xfer)
struct slhci_softc *sc;
struct slhci_pipe *spipe;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
spipe = (struct slhci_pipe *)xfer->pipe;
if (spipe == NULL)
@@ -1308,7 +1361,7 @@ slhci_abort(struct usbd_xfer *xfer)
callback:
xfer->status = USBD_CANCELLED;
- /* Abort happens at splusb. */
+ /* Abort happens at IPL_USB. */
usb_transfer_complete(xfer);
}
@@ -1385,24 +1438,18 @@ slhci_mem_use(struct usbd_bus *bus, int
struct slhci_softc *sc = bus->hci_private;
int s;
- s = splhardusb();
- simple_lock(&sc->sc_wait_lock);
+ mutex_enter(&sc->sc_intr_lock);
sc->sc_mem_use += val;
- simple_unlock(&sc->sc_wait_lock);
- splx(s);
+ mutex_exit(&sc->sc_intr_lock);
}
#endif
void
slhci_reset_entry(void *arg)
{
- struct slhci_softc *sc;
- int s;
+ struct slhci_softc *sc = arg;
- sc = (struct slhci_softc *)arg;
-
- s = splhardusb();
- simple_lock(&sc->sc_lock);
+ mutex_enter(&sc->sc_intr_lock);
slhci_reset(sc);
/*
* We cannot call the callback directly since we could then be reset
@@ -1412,8 +1459,7 @@ slhci_reset_entry(void *arg)
* set. The callback code will check the wait queue.
*/
slhci_callback_schedule(sc);
- simple_unlock(&sc->sc_lock);
- splx(s);
+ mutex_exit(&sc->sc_intr_lock);
}
usbd_status
@@ -1421,15 +1467,11 @@ slhci_lock_call(struct slhci_softc *sc,
*spipe, struct usbd_xfer *xfer)
{
usbd_status ret;
- int x, s;
- x = splusb();
- s = splhardusb();
- simple_lock(&sc->sc_lock);
+ mutex_enter(&sc->sc_intr_lock);
ret = (*lcf)(sc, spipe, xfer);
- slhci_main(sc, &s);
- splx(s);
- splx(x);
+ slhci_main(sc);
+ mutex_exit(&sc->sc_intr_lock);
return ret;
}
@@ -1438,28 +1480,18 @@ void
slhci_start_entry(struct slhci_softc *sc, struct slhci_pipe *spipe)
{
struct slhci_transfers *t;
- int s;
+ mutex_enter(&sc->sc_intr_lock);
t = &sc->sc_transfers;
- s = splhardusb();
-#ifdef SLHCI_WAITLOCK
- if (simple_lock_try(&sc->sc_lock))
-#else
- simple_lock(&sc->sc_lock);
-#endif
- {
+ if (!(t->flags & (F_AINPROG|F_BINPROG))) {
slhci_enter_xfer(sc, spipe);
slhci_dotransfer(sc);
- slhci_main(sc, &s);
-#ifdef SLHCI_WAITLOCK
+ slhci_main(sc);
} else {
- simple_lock(&sc->sc_wait_lock);
enter_waitq(sc, spipe);
- simple_unlock(&sc->sc_wait_lock);
-#endif
}
- splx(s);
+ mutex_exit(&sc->sc_intr_lock);
}
void
@@ -1467,60 +1499,45 @@ slhci_callback_entry(void *arg)
{
struct slhci_softc *sc;
struct slhci_transfers *t;
- int s, x;
-
sc = (struct slhci_softc *)arg;
- x = splusb();
- s = splhardusb();
- simple_lock(&sc->sc_lock);
+ KASSERT(mutex_owned(&sc->sc_lock));
+
+ mutex_enter(&sc->sc_intr_lock);
t = &sc->sc_transfers;
DLOG(D_SOFT, "callback_entry flags %#x", t->flags, 0,0,0);
-#ifdef SLHCI_WAITLOCK
repeat:
-#endif
- slhci_callback(sc, &s);
+ slhci_callback(sc);
-#ifdef SLHCI_WAITLOCK
- simple_lock(&sc->sc_wait_lock);
if (!gcq_empty(&sc->sc_waitq)) {
slhci_enter_xfers(sc);
- simple_unlock(&sc->sc_wait_lock);
slhci_dotransfer(sc);
slhci_waitintr(sc, 0);
goto repeat;
}
t->flags &= ~F_CALLBACK;
- simple_unlock(&sc->sc_lock);
- simple_unlock(&sc->sc_wait_lock);
-#else
- t->flags &= ~F_CALLBACK;
- simple_unlock(&sc->sc_lock);
-#endif
- splx(s);
- splx(x);
+ mutex_exit(&sc->sc_intr_lock);
}
void
-slhci_do_callback(struct slhci_softc *sc, struct usbd_xfer *xfer, int *s)
+slhci_do_callback(struct slhci_softc *sc, struct usbd_xfer *xfer)
{
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
int repeat;
start_cc_time(&t_callback, (u_int)xfer);
- simple_unlock(&sc->sc_lock);
- splx(*s);
+ mutex_exit(&sc->sc_intr_lock);
+ mutex_enter(&sc->sc_lock);
repeat = xfer->pipe->repeat;
-
usb_transfer_complete(xfer);
+ mutex_exit(&sc->sc_lock);
- *s = splhardusb();
- simple_lock(&sc->sc_lock);
+ mutex_enter(&sc->sc_intr_lock);
stop_cc_time(&t_callback);
if (repeat && !sc->sc_bus.use_polling)
@@ -1530,16 +1547,15 @@ slhci_do_callback(struct slhci_softc *sc
int
slhci_intr(void *arg)
{
- struct slhci_softc *sc;
+ struct slhci_softc *sc = arg;
int ret;
- sc = (struct slhci_softc *)arg;
-
start_cc_time(&t_hard_int, (unsigned int)arg);
- simple_lock(&sc->sc_lock);
+ mutex_enter(&sc->sc_intr_lock);
ret = slhci_dointr(sc);
- slhci_main(sc, NULL);
+ slhci_main(sc);
+ mutex_exit(&sc->sc_intr_lock);
stop_cc_time(&t_hard_int);
return ret;
@@ -1547,56 +1563,38 @@ slhci_intr(void *arg)
/* called with main lock only held, returns with locks released. */
void
-slhci_main(struct slhci_softc *sc, int *s)
+slhci_main(struct slhci_softc *sc)
{
struct slhci_transfers *t;
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
-#ifdef SLHCI_WAITLOCK
waitcheck:
-#endif
slhci_waitintr(sc, slhci_wait_time);
-
/*
- * XXX Directly calling the callback anytime s != NULL
- * causes panic:sbdrop with aue (simultaneously using umass).
- * Doing that affects process accounting, but is supposed to work as
- * far as I can tell.
- *
* The direct call is needed in the use_polling and disabled cases
* since the soft interrupt is not available. In the disabled case,
* this code can be reached from the usb detach, after the reaping of
- * the soft interrupt. That test could be !F_ACTIVE (in which case
- * s != NULL could be an assertion), but there is no reason not to
- * make the callbacks directly in the other DISABLED cases.
+ * the soft interrupt. That test could be !F_ACTIVE, but there is no
+ * reason not to make the callbacks directly in the other DISABLED
+ * cases.
*/
if ((t->flags & F_ROOTINTR) || !gcq_empty(&t->q[Q_CALLBACKS])) {
- if (__predict_false(sc->sc_bus.use_polling || t->flags &
- F_DISABLED) && s != NULL)
- slhci_callback(sc, s);
+ if (__predict_false(sc->sc_bus.use_polling ||
+ t->flags & F_DISABLED))
+ slhci_callback(sc);
else
slhci_callback_schedule(sc);
}
-#ifdef SLHCI_WAITLOCK
- simple_lock(&sc->sc_wait_lock);
-
if (!gcq_empty(&sc->sc_waitq)) {
slhci_enter_xfers(sc);
- simple_unlock(&sc->sc_wait_lock);
slhci_dotransfer(sc);
goto waitcheck;
}
-
- simple_unlock(&sc->sc_lock);
- simple_unlock(&sc->sc_wait_lock);
-#else
- simple_unlock(&sc->sc_lock);
-#endif
}
/* End lock entry functions. Start in lock function. */
@@ -1755,7 +1753,7 @@ slhci_waitintr(struct slhci_softc *sc, i
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (__predict_false(sc->sc_bus.use_polling))
wait_time = 12000;
@@ -1779,7 +1777,7 @@ slhci_dointr(struct slhci_softc *sc)
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (sc->sc_ier == 0)
return 0;
@@ -1827,7 +1825,6 @@ slhci_dointr(struct slhci_softc *sc)
slhci_write(sc, SL11_ISR, r);
BSB_SYNC(sc->iot, sc->ioh, sc->pst, sc->psz);
-
/* If we have an insertion event we do not care about anything else. */
if (__predict_false(r & SL11_ISR_INSERT)) {
slhci_insert(sc);
@@ -1956,7 +1953,7 @@ slhci_abdone(struct slhci_softc *sc, int
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
DLOG(D_TRACE, "ABDONE flags %#x", t->flags, 0,0,0);
@@ -2251,11 +2248,10 @@ slhci_tstart(struct slhci_softc *sc)
struct slhci_transfers *t;
struct slhci_pipe *spipe;
int remaining_bustime;
- int s;
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (!(t->flags & (F_AREADY|F_BREADY)))
return;
@@ -2269,7 +2265,6 @@ slhci_tstart(struct slhci_softc *sc)
* signal transfer complete. This leaves no time for any other
* interrupts.
*/
- s = splhigh();
remaining_bustime = (int)(slhci_read(sc, SL811_CSOF)) << 6;
remaining_bustime -= SLHCI_END_BUSTIME;
@@ -2306,7 +2301,6 @@ pend:
t->pend = spipe->bustime;
}
}
- splx(s);
}
static void
@@ -2318,7 +2312,7 @@ slhci_dotransfer(struct slhci_softc *sc)
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
while ((t->len[A] == -1 || t->len[B] == -1) &&
(GOT_FIRST_TIMED_COND(spipe, t, spipe->frame <= t->frame) ||
@@ -2388,10 +2382,9 @@ slhci_dotransfer(struct slhci_softc *sc)
/*
* slhci_callback is called after the lock is taken from splusb.
- * s is pointer to old spl (splusb).
*/
static void
-slhci_callback(struct slhci_softc *sc, int *s)
+slhci_callback(struct slhci_softc *sc)
{
struct slhci_transfers *t;
struct slhci_pipe *spipe;
@@ -2399,7 +2392,7 @@ slhci_callback(struct slhci_softc *sc, i
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
DLOG(D_SOFT, "CB flags %#x", t->flags, 0,0,0);
for (;;) {
@@ -2428,7 +2421,7 @@ slhci_callback(struct slhci_softc *sc, i
"type %s", xfer->length, xfer->actlen, spipe,
pnames(spipe->ptype));
do_callback:
- slhci_do_callback(sc, xfer, s);
+ slhci_do_callback(sc, xfer);
}
}
@@ -2439,7 +2432,7 @@ slhci_enter_xfer(struct slhci_softc *sc,
t = &sc->sc_transfers;
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
if (__predict_false(t->flags & F_DISABLED) ||
__predict_false(spipe->pflags & PF_GONE)) {
@@ -2460,18 +2453,16 @@ slhci_enter_xfer(struct slhci_softc *sc,
enter_callback(t, spipe);
}
-#ifdef SLHCI_WAITLOCK
static void
slhci_enter_xfers(struct slhci_softc *sc)
{
struct slhci_pipe *spipe;
- SLHCI_LOCKASSERT(sc, locked, locked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
while (DEQUEUED_WAITQ(spipe, sc))
slhci_enter_xfer(sc, spipe);
}
-#endif
static void
slhci_queue_timed(struct slhci_softc *sc, struct slhci_pipe *spipe)
@@ -2482,7 +2473,7 @@ slhci_queue_timed(struct slhci_softc *sc
t = &sc->sc_transfers;
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
FIND_TIMED(q, t, spp, spp->frame > spipe->frame);
gcq_insert_before(q, &spipe->xq);
@@ -2497,7 +2488,7 @@ slhci_xfer_timer(struct slhci_softc *sc,
t = &sc->sc_transfers;
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
FIND_TO(q, t, spp, spp->to_frame >= spipe->to_frame);
gcq_insert_before(q, &spipe->to);
@@ -2533,7 +2524,7 @@ slhci_callback_schedule(struct slhci_sof
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (t->flags & F_ACTIVE)
slhci_do_callback_schedule(sc);
@@ -2546,7 +2537,7 @@ slhci_do_callback_schedule(struct slhci_
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (!(t->flags & F_CALLBACK)) {
t->flags |= F_CALLBACK;
@@ -2555,16 +2546,16 @@ slhci_do_callback_schedule(struct slhci_
}
#if 0
-/* must be called with lock taken from splusb */
+/* must be called with lock taken from IPL_USB */
/* XXX static */ void
-slhci_pollxfer(struct slhci_softc *sc, struct usbd_xfer *xfer, int *s)
+slhci_pollxfer(struct slhci_softc *sc, struct usbd_xfer *xfer)
{
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
slhci_dotransfer(sc);
do {
slhci_dointr(sc);
} while (xfer->status == USBD_IN_PROGRESS);
- slhci_do_callback(sc, xfer, s);
+ slhci_do_callback(sc, xfer);
}
#endif
@@ -2657,7 +2648,7 @@ slhci_do_abort(struct slhci_softc *sc, s
t = &sc->sc_transfers;
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
if (spipe->xfer == xfer) {
if (spipe->ptype == PT_ROOT_INTR) {
@@ -2687,92 +2678,8 @@ slhci_do_abort(struct slhci_softc *sc, s
return USBD_NORMAL_COMPLETION;
}
-static usbd_status
-slhci_do_attach(struct slhci_softc *sc, struct slhci_pipe *spipe, struct
- usbd_xfer *xfer)
-{
- struct slhci_transfers *t;
- const char *rev;
-
- t = &sc->sc_transfers;
-
- SLHCI_LOCKASSERT(sc, locked, unlocked);
-
- /* Detect and check the controller type */
- t->sltype = SL11_GET_REV(slhci_read(sc, SL11_REV));
-
- /* SL11H not supported */
- if (!slhci_supported_rev(t->sltype)) {
- if (t->sltype == SLTYPE_SL11H)
- printf("%s: SL11H unsupported or bus error!\n",
- SC_NAME(sc));
- else
- printf("%s: Unknown chip revision!\n", SC_NAME(sc));
- return USBD_INVAL;
- }
-
- callout_init(&sc->sc_timer, CALLOUT_MPSAFE);
- callout_setfunc(&sc->sc_timer, slhci_reset_entry, sc);
-
- /*
- * It is not safe to call the soft interrupt directly as
- * usb_schedsoftintr does in the use_polling case (due to locking).
- */
- sc->sc_cb_softintr = softint_establish(SOFTINT_NET,
- slhci_callback_entry, sc);
-
-#ifdef SLHCI_DEBUG
- ssc = sc;
-#ifdef USB_DEBUG
- if (slhci_usbdebug >= 0)
- usbdebug = slhci_usbdebug;
-#endif
-#endif
-
- if (t->sltype == SLTYPE_SL811HS_R12)
- rev = " (rev 1.2)";
- else if (t->sltype == SLTYPE_SL811HS_R14)
- rev = " (rev 1.4 or 1.5)";
- else
- rev = " (unknown revision)";
-
- aprint_normal("%s: ScanLogic SL811HS/T USB Host Controller %s\n",
- SC_NAME(sc), rev);
-
- aprint_normal("%s: Max Current %u mA (value by code, not by probe)\n",
- SC_NAME(sc), t->max_current * 2);
-
-#if defined(SLHCI_DEBUG) || defined(SLHCI_NO_OVERTIME) || \
- defined(SLHCI_TRY_LSVH) || defined(SLHCI_PROFILE_TRANSFER)
- aprint_normal("%s: driver options:"
-#ifdef SLHCI_DEBUG
- " SLHCI_DEBUG"
-#endif
-#ifdef SLHCI_TRY_LSVH
- " SLHCI_TRY_LSVH"
-#endif
-#ifdef SLHCI_NO_OVERTIME
- " SLHCI_NO_OVERTIME"
-#endif
-#ifdef SLHCI_PROFILE_TRANSFER
- " SLHCI_PROFILE_TRANSFER"
-#endif
- "\n", SC_NAME(sc));
-#endif
- sc->sc_bus.usbrev = USBREV_1_1;
- sc->sc_bus.methods = __UNCONST(&slhci_bus_methods);
- sc->sc_bus.pipe_size = sizeof(struct slhci_pipe);
-
- if (!sc->sc_enable_power)
- t->flags |= F_REALPOWER;
-
- t->flags |= F_ACTIVE;
-
- return USBD_NORMAL_COMPLETION;
-}
-
/*
- * Called to deactivate or stop use of the controller instead of panicing.
+ * Called to deactivate or stop use of the controller instead of panicking.
* Will cancel the xfer correctly even when not on a list.
*/
static usbd_status
@@ -2781,7 +2688,7 @@ slhci_halt(struct slhci_softc *sc, struc
{
struct slhci_transfers *t;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
t = &sc->sc_transfers;
@@ -2830,7 +2737,7 @@ slhci_halt(struct slhci_softc *sc, struc
static void
slhci_intrchange(struct slhci_softc *sc, uint8_t new_ier)
{
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
if (sc->sc_ier != new_ier) {
sc->sc_ier = new_ier;
slhci_write(sc, SL11_IER, new_ier);
@@ -2850,7 +2757,7 @@ slhci_drain(struct slhci_softc *sc)
struct gcq *q;
int i;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
t = &sc->sc_transfers;
@@ -2909,7 +2816,7 @@ slhci_reset(struct slhci_softc *sc)
uint8_t r, pol, ctrl;
t = &sc->sc_transfers;
- SLHCI_MAINLOCKASSERT(sc);
+ KASSERT(mutex_owned(&sc->sc_intr_lock));
stop_cc_time(&t_delay);
@@ -3013,7 +2920,7 @@ slhci_reserve_bustime(struct slhci_softc
struct slhci_transfers *t;
int bustime, max_packet;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
t = &sc->sc_transfers;
max_packet = UGETW(spipe->pipe.endpoint->edesc->wMaxPacketSize);
@@ -3070,7 +2977,7 @@ slhci_insert(struct slhci_softc *sc)
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (t->flags & F_NODEV)
slhci_intrchange(sc, 0);
@@ -3160,7 +3067,7 @@ slhci_clear_feature(struct slhci_softc *
t = &sc->sc_transfers;
error = USBD_NORMAL_COMPLETION;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (what == UHF_PORT_POWER) {
DLOG(D_MSG, "POWER_OFF", 0,0,0,0);
@@ -3196,7 +3103,7 @@ slhci_set_feature(struct slhci_softc *sc
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (what == UHF_PORT_RESET) {
if (!(t->flags & F_ACTIVE)) {
@@ -3267,7 +3174,7 @@ slhci_get_status(struct slhci_softc *sc,
t = &sc->sc_transfers;
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
/*
* We do not have a way to detect over current or bable and
@@ -3313,7 +3220,7 @@ slhci_root(struct slhci_softc *sc, struc
USBD_CANCELLED);
DLOG(D_TRACE, "%s start", pnames(SLHCI_XFER_TYPE(xfer)), 0,0,0);
- SLHCI_LOCKASSERT(sc, locked, unlocked);
+ KASSERT(mutex_locked(&sc->sc_intr_lock));
if (spipe->ptype == PT_ROOT_INTR) {
LK_SLASSERT(t->rootintr == NULL, sc, spipe, xfer, return
Index: src/sys/dev/ic/sl811hsvar.h
diff -u src/sys/dev/ic/sl811hsvar.h:1.10 src/sys/dev/ic/sl811hsvar.h:1.11
--- src/sys/dev/ic/sl811hsvar.h:1.10 Sun Sep 22 06:54:35 2013
+++ src/sys/dev/ic/sl811hsvar.h Wed Oct 2 22:55:04 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: sl811hsvar.h,v 1.10 2013/09/22 06:54:35 skrll Exp $ */
+/* $NetBSD: sl811hsvar.h,v 1.11 2013/10/02 22:55:04 skrll Exp $ */
/*
* Not (c) 2007 Matthew Orgass
@@ -14,7 +14,6 @@
*/
#include <sys/gcq.h>
-#include <sys/simplelock.h>
#define SC_DEV(sc) ((sc)->sc_dev)
#define SC_NAME(sc) (device_xname(SC_DEV(sc)))
@@ -55,8 +54,8 @@ struct slhci_softc {
device_t sc_dev;
struct usbd_bus sc_bus;
- struct simplelock sc_lock;
- struct simplelock sc_wait_lock;
+ kmutex_t sc_lock;
+ kmutex_t sc_intr_lock;
struct slhci_transfers sc_transfers; /* Info useful in transfers. */