tech-kern archive

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

Re: 5.99.30 sparc panic during startup



> > > Somebody should fix the driver so that zshard() does not call
> > > device_lookup_private().  It seems entirely unnecessary.
> > 
> > There is a dumb hack in sun3 derived zs driver.
> > 
> > All zs devices on sun machines have the same interrupt sources
> > so ancient zs drivers tried to reduce overhead on interrupts
> > by sharing one interrupt handler among all zs devices.
> > 
> > We can simpley fix it to make it call softint_establish() and
> > bus_intr_establish() per each zs device, as macppc and news68k etc. do.
> 
> i don't understand.
> 
> the macppc and news68k zshard()'s get the actual zsc_softc * as
> the (void *arg), but sparc does not.

So we should make sparc zs do so.

It looks multiple interrupt handlers against the same interrupt level
are properly queued and handled in sparc/intr.c:ih_insert(), so
no need to prepare own queue in zs.c.

The attached patch works on tme-0.8 emulating SS2.
(Hehe, a comment still says "autovectored" derived from sun3 ;-)

---
Index: dev/zs.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/dev/zs.c,v
retrieving revision 1.118
diff -u -r1.118 zs.c
--- dev/zs.c    4 Jun 2010 06:04:15 -0000       1.118
+++ dev/zs.c    20 Jun 2010 01:58:29 -0000
@@ -171,12 +171,8 @@
 
 extern struct cfdriver zs_cd;
 
-/* softintr(9) cookie, shared by all instances of this driver */
-static void *zs_sicookie;
-
 /* Interrupt handlers. */
 static int zshard(void *);
-static void zssoft(void *);
 
 static int zs_get_speed(struct zs_chanstate *);
 
@@ -396,7 +392,6 @@
        struct zsc_attach_args zsc_args;
        struct zs_chanstate *cs;
        int channel;
-       static int didintr, prevpri;
 #if (NKBD > 0) || (NMS > 0)
        int ch0_is_cons = 0;
 #endif
@@ -407,12 +402,11 @@
                return;
        }
 
-       if (!didintr) {
-               zs_sicookie = softint_establish(SOFTINT_SERIAL, zssoft, NULL);
-               if (zs_sicookie == NULL) {
-                       aprint_error(": cannot establish soft int handler\n");
-                       return;
-               }
+       zsc->zsc_sicookie = softint_establish(SOFTINT_SERIAL,
+           (void (*)(void *))zsc_intr_soft, zsc);
+       if (zsc->zsc_sicookie == NULL) {
+               aprint_error(": cannot establish soft int handler\n");
+               return;
        }
        aprint_normal(" softpri %d\n", IPL_SOFTSERIAL);
 
@@ -566,17 +560,9 @@
        }
 
        /*
-        * Now safe to install interrupt handlers.  Note the arguments
-        * to the interrupt handlers aren't used.  Note, we only do this
-        * once since both SCCs interrupt at the same level and vector.
+        * Now safe to install interrupt handlers.
         */
-       if (!didintr) {
-               didintr = 1;
-               prevpri = pri;
-               bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL,
-                                  zshard, NULL);
-       } else if (pri != prevpri)
-               panic("broken zs interrupt scheme");
+       bus_intr_establish(zsc->zsc_bustag, pri, IPL_SERIAL, zshard, zsc);
 
        evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL,
            device_xname(zsc->zsc_dev), "intr");
@@ -625,81 +611,29 @@
 static volatile int zssoftpending;
 
 /*
- * Our ZS chips all share a common, autovectored interrupt,
- * so we have to look at all of them on each interrupt.
+ * Our ZS chips all share a common interrupt level,
+ * but we establish zshard handler per each ZS chips
+ * to avoid holding unnecessary locks in interrupt context.
  */
 static int
 zshard(void *arg)
 {
-       struct zsc_softc *zsc;
-       int unit, rr3, rval, softreq;
-
-       rval = softreq = 0;
-       for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
-               struct zs_chanstate *cs;
+       struct zsc_softc *zsc = arg;
+       int rr3, rval;
 
-               zsc = device_lookup_private(&zs_cd, unit);
-               if (zsc == NULL)
-                       continue;
-               rr3 = zsc_intr_hard(zsc);
-               /* Count up the interrupts. */
-               if (rr3) {
-                       rval |= rr3;
-                       zsc->zsc_intrcnt.ev_count++;
-               }
-               if ((cs = zsc->zsc_cs[0]) != NULL)
-                       softreq |= cs->cs_softreq;
-               if ((cs = zsc->zsc_cs[1]) != NULL)
-                       softreq |= cs->cs_softreq;
-       }
-
-       /* We are at splzs here, so no need to lock. */
-       if (softreq && (zssoftpending == 0)) {
-               zssoftpending = 1;
-               softint_schedule(zs_sicookie);
+       rval = 0;
+       rr3 = zsc_intr_hard(zsc);
+       /* Count up the interrupts. */
+       if (rr3) {
+               rval = rr3;
+               zsc->zsc_intrcnt.ev_count++;
        }
+       if (zsc->zsc_cs[0]->cs_softreq || zsc->zsc_cs[1]->cs_softreq)
+               softint_schedule(zsc->zsc_sicookie);
        return (rval);
 }
 
 /*
- * Similar scheme as for zshard (look at all of them)
- */
-static void
-zssoft(void *arg)
-{
-       struct zsc_softc *zsc;
-       int unit;
-
-       /* This is not the only ISR on this IPL. */
-       if (zssoftpending == 0)
-               return;
-
-       /*
-        * The soft intr. bit will be set by zshard only if
-        * the variable zssoftpending is zero.  The order of
-        * these next two statements prevents our clearing
-        * the soft intr bit just after zshard has set it.
-        */
-       /* ienab_bic(IE_ZSSOFT); */
-       zssoftpending = 0;
-
-#if 0 /* not yet */
-       /* Make sure we call the tty layer with tty_lock held. */
-       mutex_spin_enter(&tty_lock);
-#endif
-       for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
-               zsc = device_lookup_private(&zs_cd, unit);
-               if (zsc == NULL)
-                       continue;
-               (void)zsc_intr_soft(zsc);
-       }
-#if 0 /* not yet */
-       mutex_spin_exit(&tty_lock);
-#endif
-}
-
-
-/*
  * Compute the current baud rate given a ZS channel.
  */
 static int
Index: include/z8530var.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc/include/z8530var.h,v
retrieving revision 1.9
diff -u -r1.9 z8530var.h
--- include/z8530var.h  29 Mar 2008 19:15:35 -0000      1.9
+++ include/z8530var.h  20 Jun 2010 01:58:29 -0000
@@ -54,6 +54,7 @@
        int                     zsc_node;       /* PROM node, if any */
        struct evcnt            zsc_intrcnt;    /* count interrupts */
        struct zs_chanstate     zsc_cs_store[2];
+       void                    *zsc_sicookie;  /* softint(9) cookie */
 };
 
 /*

---
Izumi Tsutsui



Home | Main Index | Thread Index | Old Index