Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/jmcneill-usbmp]: src/sys/dev/usb adapt ohci, from mrg with some changes ...



details:   https://anonhg.NetBSD.org/src/rev/e58c7e324bef
branches:  jmcneill-usbmp
changeset: 771766:e58c7e324bef
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Dec 04 21:02:27 2011 +0000

description:
adapt ohci, from mrg with some changes by me

diffstat:

 sys/dev/usb/ohci.c    |  355 ++++++++++++++++++++++++++++++-------------------
 sys/dev/usb/ohcivar.h |    9 +-
 2 files changed, 225 insertions(+), 139 deletions(-)

diffs (truncated from 1224 to 300 lines):

diff -r b2fe66350ed9 -r e58c7e324bef sys/dev/usb/ohci.c
--- a/sys/dev/usb/ohci.c        Sun Dec 04 19:22:56 2011 +0000
+++ b/sys/dev/usb/ohci.c        Sun Dec 04 21:02:27 2011 +0000
@@ -1,13 +1,14 @@
-/*     $NetBSD: ohci.c,v 1.218.6.1 2011/12/04 13:23:16 jmcneill Exp $  */
+/*     $NetBSD: ohci.c,v 1.218.6.2 2011/12/04 21:02:27 jmcneill Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
 
 /*
- * Copyright (c) 1998, 2004, 2005 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2004, 2005, 2011 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Lennart Augustsson (lennart%augustsson.net@localhost) at
- * Carlstedt Research & Technology.
+ * Carlstedt Research & Technology, Jared D. McNeill (jmcneill%invisible.ca@localhost)
+ * and Matthew R. Green.
  * This code is derived from software contributed to The NetBSD Foundation
  * by Charles M. Hannum.
  *
@@ -41,13 +42,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.1 2011/12/04 13:23:16 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.2 2011/12/04 21:02:27 jmcneill Exp $");
 
 #include "opt_usb.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/select.h>
@@ -113,6 +114,7 @@
 Static void            ohci_softintr(void *);
 Static void            ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
 Static void            ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
+Static void            ohci_rhsc_softint(void *arg);
 
 Static usbd_status     ohci_device_request(usbd_xfer_handle xfer);
 Static void            ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *,
@@ -134,6 +136,8 @@
 
 Static usbd_xfer_handle        ohci_allocx(struct usbd_bus *);
 Static void            ohci_freex(struct usbd_bus *, usbd_xfer_handle);
+Static void            ohci_get_locks(struct usbd_bus *, kmutex_t **,
+                                      kmutex_t **);
 
 Static usbd_status     ohci_root_ctrl_transfer(usbd_xfer_handle);
 Static usbd_status     ohci_root_ctrl_start(usbd_xfer_handle);
@@ -274,7 +278,7 @@
        ohci_freem,
        ohci_allocx,
        ohci_freex,
-       NULL, /* ohci_get_locks */
+       ohci_get_locks,
 };
 
 Static const struct usbd_pipe_methods ohci_root_ctrl_methods = {
@@ -371,11 +375,18 @@
        usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
        callout_destroy(&sc->sc_tmo_rhsc);
 
+       softint_disestablish(sc->sc_rhsc_si);
+
+       cv_destroy(&sc->sc_softwake_cv);
+
+       mutex_destroy(&sc->sc_lock);
+       mutex_destroy(&sc->sc_intr_lock);
+
        if (sc->sc_hcca != NULL)
                usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
        while((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) {
                SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
-               free(xfer, M_USB);
+               kmem_free(xfer, sizeof(struct ohci_xfer));
        }
 
        return (rv);
@@ -426,7 +437,6 @@
        usbd_status err;
        int i, offs;
        usb_dma_t dma;
-       int s;
 
        if (sc->sc_freetds == NULL) {
                DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
@@ -434,7 +444,6 @@
                          OHCI_TD_ALIGN, &dma);
                if (err)
                        return (NULL);
-               s = splusb();
                for(i = 0; i < OHCI_STD_CHUNK; i++) {
                        offs = i * OHCI_STD_SIZE;
                        std = KERNADDR(&dma, offs);
@@ -444,17 +453,14 @@
                        std->nexttd = sc->sc_freetds;
                        sc->sc_freetds = std;
                }
-               splx(s);
        }
 
-       s = splusb();
        std = sc->sc_freetds;
        sc->sc_freetds = std->nexttd;
        memset(&std->td, 0, sizeof(ohci_td_t));
        std->nexttd = NULL;
        std->xfer = NULL;
        ohci_hash_add_td(sc, std);
-       splx(s);
 
        return (std);
 }
@@ -462,13 +468,10 @@
 void
 ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std)
 {
-       int s;
-
-       s = splusb();
+
        ohci_hash_rem_td(sc, std);
        std->nexttd = sc->sc_freetds;
        sc->sc_freetds = std;
-       splx(s);
 }
 
 usbd_status
@@ -485,6 +488,8 @@
 
        DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
 
+       KASSERT(mutex_owned(&sc->sc_lock));
+
        len = alen;
        cur = sp;
        dataphys = DMAADDR(dma, 0);
@@ -590,7 +595,7 @@
 {
        ohci_soft_itd_t *sitd;
        usbd_status err;
-       int i, s, offs;
+       int i, offs;
        usb_dma_t dma;
 
        if (sc->sc_freeitds == NULL) {
@@ -599,7 +604,6 @@
                          OHCI_ITD_ALIGN, &dma);
                if (err)
                        return (NULL);
-               s = splusb();
                for(i = 0; i < OHCI_SITD_CHUNK; i++) {
                        offs = i * OHCI_SITD_SIZE;
                        sitd = KERNADDR(&dma, offs);
@@ -609,17 +613,14 @@
                        sitd->nextitd = sc->sc_freeitds;
                        sc->sc_freeitds = sitd;
                }
-               splx(s);
        }
 
-       s = splusb();
        sitd = sc->sc_freeitds;
        sc->sc_freeitds = sitd->nextitd;
        memset(&sitd->itd, 0, sizeof(ohci_itd_t));
        sitd->nextitd = NULL;
        sitd->xfer = NULL;
        ohci_hash_add_itd(sc, sitd);
-       splx(s);
 
 #ifdef DIAGNOSTIC
        sitd->isdone = 0;
@@ -631,7 +632,6 @@
 void
 ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
 {
-       int s;
 
        DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd));
 
@@ -644,11 +644,9 @@
        sitd->isdone = 0;
 #endif
 
-       s = splusb();
        ohci_hash_rem_itd(sc, sitd);
        sitd->nextitd = sc->sc_freeitds;
        sc->sc_freeitds = sitd;
-       splx(s);
 }
 
 usbd_status
@@ -663,7 +661,14 @@
        aprint_normal_dev(sc->sc_dev, "");
 
        sc->sc_hcca = NULL;
-       callout_init(&sc->sc_tmo_rhsc, 0);
+       callout_init(&sc->sc_tmo_rhsc, CALLOUT_MPSAFE);
+
+       mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
+       mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB);
+       cv_init(&sc->sc_softwake_cv, "ohciab");
+
+       sc->sc_rhsc_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE,
+           ohci_rhsc_softint, sc);
 
        for (i = 0; i < OHCI_HASH_SIZE; i++)
                LIST_INIT(&sc->sc_hash_tds[i]);
@@ -959,7 +964,7 @@
                }
 #endif
        } else {
-               xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT);
+               xfer = kmem_alloc(sizeof(struct ohci_xfer), KM_SLEEP);
        }
        if (xfer != NULL) {
                memset(xfer, 0, sizeof (struct ohci_xfer));
@@ -985,6 +990,15 @@
        SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
 }
 
+Static void
+ohci_get_locks(struct usbd_bus *bus, kmutex_t **intr, kmutex_t **thread)
+{
+       struct ohci_softc *sc = bus->hci_private;
+
+       *intr = &sc->sc_intr_lock;
+       *thread = &sc->sc_lock;
+}
+
 /*
  * Shut down the controller when the system is going down.
  */
@@ -1003,10 +1017,11 @@
 {
        ohci_softc_t *sc = device_private(dv);
        uint32_t ctl;
-       int s;
-
-       s = splhardusb();
+
+       mutex_spin_enter(&sc->sc_intr_lock);
        sc->sc_bus.use_polling++;
+       mutex_spin_exit(&sc->sc_intr_lock);
+
        /* Some broken BIOSes do not recover these values */
        OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
        OWRITE4(sc, OHCI_CONTROL_HEAD_ED,
@@ -1027,8 +1042,10 @@
        OWRITE4(sc, OHCI_CONTROL, ctl);
        usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
        sc->sc_control = sc->sc_intre = 0;
+
+       mutex_spin_enter(&sc->sc_intr_lock);
        sc->sc_bus.use_polling--;
-       splx(s);
+       mutex_spin_exit(&sc->sc_intr_lock);
 
        return true;
 }
@@ -1038,10 +1055,11 @@
 {
        ohci_softc_t *sc = device_private(dv);
        uint32_t ctl;
-       int s;
-
-       s = splhardusb();
+
+       mutex_spin_enter(&sc->sc_intr_lock);
        sc->sc_bus.use_polling++;
+       mutex_spin_exit(&sc->sc_intr_lock);
+
        ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
        if (sc->sc_control == 0) {
                /*
@@ -1055,8 +1073,10 @@
        ctl |= OHCI_HCFS_SUSPEND;
        OWRITE4(sc, OHCI_CONTROL, ctl);
        usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
+
+       mutex_spin_enter(&sc->sc_intr_lock);
        sc->sc_bus.use_polling--;
-       splx(s);
+       mutex_spin_exit(&sc->sc_intr_lock);
 
        return true;
 }
@@ -1108,10 +1128,16 @@
 ohci_intr(void *p)
 {
        ohci_softc_t *sc = p;
-
-       if (sc == NULL || sc->sc_dying || !device_has_power(sc->sc_dev))
+       int ret = 0;
+
+       if (sc == NULL)



Home | Main Index | Thread Index | Old Index