Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Modernise slhci. Many thanks to rkujawa@ for test...
details: https://anonhg.NetBSD.org/src/rev/bf52a47dd8f3
branches: trunk
changeset: 790305:bf52a47dd8f3
user: skrll <skrll%NetBSD.org@localhost>
date: Wed Oct 02 22:55:04 2013 +0000
description:
Modernise slhci. Many thanks to rkujawa@ for testing.
diffstat:
sys/dev/ic/sl811hs.c | 467 +++++++++++++++++++----------------------------
sys/dev/ic/sl811hsvar.h | 7 +-
2 files changed, 190 insertions(+), 284 deletions(-)
diffs (truncated from 1031 to 300 lines):
diff -r d8a55d9da5f4 -r bf52a47dd8f3 sys/dev/ic/sl811hs.c
--- a/sys/dev/ic/sl811hs.c Wed Oct 02 22:53:23 2013 +0000
+++ b/sys/dev/ic/sl811hs.c Wed Oct 02 22:55:04 2013 +0000
@@ -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 @@
#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 @@
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 @@
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 @@
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_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_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 @@
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 @@
#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 @@
.freem = slhci_freem,
.allocx = slhci_allocx,
.freex = slhci_freex,
- .get_lock = NULL,
+ .get_lock = slhci_get_lock,
NULL, /* new_device */
};
@@ -760,7 +732,6 @@
#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 @@
{
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 @@
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 @@
*/
/*
- * 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_entry(sc, spipe);
+ mutex_exit(&sc->sc_lock);
+
return USBD_IN_PROGRESS;
}
@@ -1189,10 +1169,9 @@
#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 @@
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)";
Home |
Main Index |
Thread Index |
Old Index