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