Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci From Tom Ivar Helbekkmo:



details:   https://anonhg.NetBSD.org/src/rev/d0b1f24c86f5
branches:  trunk
changeset: 336459:d0b1f24c86f5
user:      christos <christos%NetBSD.org@localhost>
date:      Mon Mar 02 15:26:57 2015 +0000

description:
>From Tom Ivar Helbekkmo:

- Use mutexes and condvars instead of spl() calls.
- Add a couple of bugfixes from FreeBSD (the easily observed ones).
- Add a simple watchdog thread for the newer versions of the hardware,
  that tickles the controller at task submission time if it seems not ready
  (from FreeBSD).
- Add a buffer allocation size hack to the ioctl handler, to work around
  a firmware bug in some versions of the controller (also from FreeBSD).
- Rearrange the bus_dmamap_sync() calls to make the use match the
  documentation.

diffstat:

 sys/dev/pci/amr.c    |  280 ++++++++++++++++++++++++++++++++++++--------------
 sys/dev/pci/amrvar.h |    6 +-
 sys/dev/pci/ld_amr.c |   10 +-
 3 files changed, 206 insertions(+), 90 deletions(-)

diffs (truncated from 691 to 300 lines):

diff -r c138415381c9 -r d0b1f24c86f5 sys/dev/pci/amr.c
--- a/sys/dev/pci/amr.c Mon Mar 02 14:17:06 2015 +0000
+++ b/sys/dev/pci/amr.c Mon Mar 02 15:26:57 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: amr.c,v 1.58 2014/07/25 08:10:38 dholland Exp $        */
+/*     $NetBSD: amr.c,v 1.59 2015/03/02 15:26:57 christos Exp $        */
 
 /*-
  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.58 2014/07/25 08:10:38 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amr.c,v 1.59 2015/03/02 15:26:57 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -77,6 +77,8 @@
 #include <sys/conf.h>
 #include <sys/kthread.h>
 #include <sys/kauth.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
 
 #include <machine/endian.h>
 #include <sys/bus.h>
@@ -100,7 +102,8 @@
 static int     amr_print(void *, const char *);
 static void    amr_shutdown(void *);
 static void    amr_teardown(struct amr_softc *);
-static void    amr_thread(void *);
+static void    amr_quartz_thread(void *);
+static void    amr_std_thread(void *);
 
 static int     amr_quartz_get_work(struct amr_softc *,
                                    struct amr_mailbox_resp *);
@@ -186,13 +189,15 @@
 
 static void    *amr_sdh;
 
+static kcondvar_t thread_cv;
+static kmutex_t        thread_mutex;
+
 static int     amr_max_segs;
 int            amr_max_xfer;
 
 static inline u_int8_t
 amr_inb(struct amr_softc *amr, int off)
 {
-
        bus_space_barrier(amr->amr_iot, amr->amr_ioh, off, 1,
            BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ);
        return (bus_space_read_1(amr->amr_iot, amr->amr_ioh, off));
@@ -201,7 +206,6 @@
 static inline u_int32_t
 amr_inl(struct amr_softc *amr, int off)
 {
-
        bus_space_barrier(amr->amr_iot, amr->amr_ioh, off, 4,
            BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ);
        return (bus_space_read_4(amr->amr_iot, amr->amr_ioh, off));
@@ -210,7 +214,6 @@
 static inline void
 amr_outb(struct amr_softc *amr, int off, u_int8_t val)
 {
-
        bus_space_write_1(amr->amr_iot, amr->amr_ioh, off, val);
        bus_space_barrier(amr->amr_iot, amr->amr_ioh, off, 1,
            BUS_SPACE_BARRIER_WRITE);
@@ -219,7 +222,6 @@
 static inline void
 amr_outl(struct amr_softc *amr, int off, u_int32_t val)
 {
-
        bus_space_write_4(amr->amr_iot, amr->amr_ioh, off, val);
        bus_space_barrier(amr->amr_iot, amr->amr_ioh, off, 4,
            BUS_SPACE_BARRIER_WRITE);
@@ -282,6 +284,9 @@
 
        amr = device_private(self);
        amr->amr_dv = self;
+
+       mutex_init(&amr->amr_mutex, MUTEX_DEFAULT, IPL_BIO);
+
        pa = (struct pci_attach_args *)aux;
        pc = pa->pa_pc;
 
@@ -303,7 +308,6 @@
                        if (PCI_MAPREG_IO_SIZE(reg) != 0)
                                ioreg = i;
                        break;
-
                }
        }
 
@@ -424,6 +428,8 @@
                        break;
 
                ac->ac_ident = i;
+               cv_init(&ac->ac_cv, "amr1ccb");
+               mutex_init(&ac->ac_mutex, MUTEX_DEFAULT, IPL_NONE);
                amr_ccb_free(amr, ac);
        }
        if (i != AMR_MAX_CMDS) {
@@ -491,16 +497,23 @@
 
        SIMPLEQ_INIT(&amr->amr_ccb_queue);
 
-       /* XXX This doesn't work for newer boards yet. */
+       cv_init(&thread_cv, "amrwdog");
+       mutex_init(&thread_mutex, MUTEX_DEFAULT, IPL_NONE);
+
        if ((apt->apt_flags & AT_QUARTZ) == 0) {
-               rv = kthread_create(PRI_NONE, 0, NULL, amr_thread, amr,
-                   &amr->amr_thread, "%s", device_xname(amr->amr_dv));
-               if (rv != 0)
-                       aprint_error_dev(amr->amr_dv, "unable to create thread (%d)",
-                           rv);
-               else
-                       amr->amr_flags |= AMRF_THREAD;
+               rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
+                                   amr_std_thread, amr, &amr->amr_thread,
+                                   "%s", device_xname(amr->amr_dv));
+       } else {
+               rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
+                                   amr_quartz_thread, amr, &amr->amr_thread,
+                                   "%s", device_xname(amr->amr_dv));
        }
+       if (rv != 0)
+               aprint_error_dev(amr->amr_dv, "unable to create thread (%d)",
+                   rv);
+       else
+               amr->amr_flags |= AMRF_THREAD;
 }
 
 /*
@@ -516,9 +529,14 @@
 
        if ((fl & AMRF_THREAD) != 0) {
                amr->amr_flags |= AMRF_THREAD_EXIT;
-               wakeup(amr_thread);
-               while ((amr->amr_flags & AMRF_THREAD_EXIT) != 0)
-                       tsleep(&amr->amr_flags, PWAIT, "amrexit", 0);
+               mutex_enter(&thread_mutex);
+               cv_broadcast(&thread_cv);
+               mutex_exit(&thread_mutex);
+               while ((amr->amr_flags & AMRF_THREAD_EXIT) != 0) {
+                       mutex_enter(&thread_mutex);
+                       cv_wait(&thread_cv, &thread_mutex);
+                       mutex_exit(&thread_mutex);
+               }
        }
        if ((fl & AMRF_CCBS) != 0) {
                SLIST_FOREACH(ac, &amr->amr_ccb_freelist, ac_chain.slist) {
@@ -743,7 +761,7 @@
        extern struct cfdriver amr_cd;
        struct amr_softc *amr;
        struct amr_ccb *ac;
-       int i, rv, s;
+       int i, rv;
 
        for (i = 0; i < amr_cd.cd_ndevs; i++) {
                if ((amr = device_lookup_private(&amr_cd, i)) == NULL)
@@ -751,9 +769,7 @@
 
                if ((rv = amr_ccb_alloc(amr, &ac)) == 0) {
                        ac->ac_cmd.mb_command = AMR_CMD_FLUSH;
-                       s = splbio();
                        rv = amr_ccb_poll(amr, ac, 30000);
-                       splx(s);
                        amr_ccb_free(amr, ac);
                }
                if (rv != 0)
@@ -775,6 +791,8 @@
        amr = cookie;
        forus = 0;
 
+       mutex_spin_enter(&amr->amr_mutex);
+
        while ((*amr->amr_get_work)(amr, &mbox) == 0) {
                /* Iterate over completed commands in this result. */
                for (i = 0; i < mbox.mb_nstatus; i++) {
@@ -803,14 +821,21 @@
                                    device_xname(amr->amr_dv), ac->ac_ident);
 
                        /* Pass notification to upper layers. */
-                       if (ac->ac_handler != NULL)
+                       mutex_spin_exit(&amr->amr_mutex);
+                       if (ac->ac_handler != NULL) {
                                (*ac->ac_handler)(ac);
-                       else
-                               wakeup(ac);
+                       } else {
+                               mutex_enter(&ac->ac_mutex);
+                               cv_signal(&ac->ac_cv);
+                               mutex_exit(&ac->ac_mutex);
+                       }
+                       mutex_spin_enter(&amr->amr_mutex);
                }
                forus = 1;
        }
 
+       mutex_spin_exit(&amr->amr_mutex);
+
        if (forus)
                amr_ccb_enqueue(amr, NULL);
 
@@ -821,28 +846,30 @@
  * Watchdog thread.
  */
 static void
-amr_thread(void *cookie)
+amr_quartz_thread(void *cookie)
 {
        struct amr_softc *amr;
        struct amr_ccb *ac;
-       struct amr_logdrive *al;
-       struct amr_enquiry *ae;
-       int rv, i, s;
 
        amr = cookie;
-       ae = amr->amr_enqbuf;
 
        for (;;) {
-               tsleep(amr_thread, PWAIT, "amrwdog", AMR_WDOG_TICKS);
+               mutex_enter(&thread_mutex);
+               cv_timedwait(&thread_cv, &thread_mutex, AMR_WDOG_TICKS);
+               mutex_exit(&thread_mutex);
 
                if ((amr->amr_flags & AMRF_THREAD_EXIT) != 0) {
                        amr->amr_flags ^= AMRF_THREAD_EXIT;
-                       wakeup(&amr->amr_flags);
+                       mutex_enter(&thread_mutex);
+                       cv_signal(&thread_cv);
+                       mutex_exit(&thread_mutex);
                        kthread_exit(0);
                }
 
-               s = splbio();
-               amr_intr(cookie);
+               if (amr_intr(amr) == 0)
+                       amr_ccb_enqueue(amr, NULL);
+
+               mutex_spin_enter(&amr->amr_mutex);
                ac = TAILQ_FIRST(&amr->amr_ccb_active);
                while (ac != NULL) {
                        if (ac->ac_start_time + AMR_TIMEOUT > time_uptime)
@@ -855,7 +882,52 @@
                        }
                        ac = TAILQ_NEXT(ac, ac_chain.tailq);
                }
-               splx(s);
+               mutex_spin_exit(&amr->amr_mutex);
+       }
+}
+
+static void
+amr_std_thread(void *cookie)
+{
+       struct amr_softc *amr;
+       struct amr_ccb *ac;
+       struct amr_logdrive *al;
+       struct amr_enquiry *ae;
+       int rv, i;
+
+       amr = cookie;
+       ae = amr->amr_enqbuf;
+
+       for (;;) {
+               mutex_enter(&thread_mutex);
+               cv_timedwait(&thread_cv, &thread_mutex, AMR_WDOG_TICKS);
+               mutex_exit(&thread_mutex);
+
+               if ((amr->amr_flags & AMRF_THREAD_EXIT) != 0) {
+                       amr->amr_flags ^= AMRF_THREAD_EXIT;
+                       mutex_enter(&thread_mutex);
+                       cv_signal(&thread_cv);
+                       mutex_exit(&thread_mutex);
+                       kthread_exit(0);
+               }
+
+               if (amr_intr(amr) == 0)
+                       amr_ccb_enqueue(amr, NULL);
+
+               mutex_spin_enter(&amr->amr_mutex);
+               ac = TAILQ_FIRST(&amr->amr_ccb_active);
+               while (ac != NULL) {
+                       if (ac->ac_start_time + AMR_TIMEOUT > time_uptime)
+                               break;
+                       if ((ac->ac_flags & AC_MOAN) == 0) {
+                               printf("%s: ccb %d timed out; mailbox:\n",
+                                   device_xname(amr->amr_dv), ac->ac_ident);
+                               amr_ccb_dump(amr, ac);
+                               ac->ac_flags |= AC_MOAN;
+                       }
+                       ac = TAILQ_NEXT(ac, ac_chain.tailq);
+               }
+               mutex_spin_exit(&amr->amr_mutex);
 



Home | Main Index | Thread Index | Old Index