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