Testing a patch to syscons(4)

From: Ken Smith <kensmith_at_cse.Buffalo.EDU>
Date: Wed, 31 Mar 2004 12:59:10 -0500
The motivation for this patch comes from an issue on sparc64 but it
applies to code that's used by any of the architectures that includes
syscons so it would be good if this got some reasonable testing before
it got committed.

The issue crept in with the recent-ish devfs megapatches, and is caused
by the same thing that caused some problems with other console drivers.
You can't call make_dev() too soon in the boot process because it needs
mutexes to be functional.  So prospective console devices may need to
procrastinate on the call to make_dev() on some architectures, depending
on when it would be best for that architecture to call cninit() and
when enough of the baseline hardware is set up that mutexes can become
functional.

This patch arranges for syscons(4) to wait longer than its console
initialization routines before it calls make_dev().  If I don't get
any feedback about this patch I'll commit it some time this weekend.
I would appreciate it if other folks could give it a try before then.
I've tested it on sparc64 and briefly on i386.  I don't have access
to anything else that can use syscons as its console driver, any other
architecture machines I can get to use serial port consoles.

This patch is for src/sys/dev/syscons/syscons.c

Thanks...

Index: syscons.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/syscons/syscons.c,v
retrieving revision 1.417
diff -u -r1.417 syscons.c
--- syscons.c	18 Mar 2004 21:07:54 -0000	1.417
+++ syscons.c	31 Mar 2004 08:02:48 -0000
_at__at_ -99,6 +99,8 _at__at_
 static	struct tty	*sc_console_tty;
 static  struct consdev	*sc_consptr;
 static	void		*kernel_console_ts;
+static	scr_stat	main_console;
+static	dev_t		main_devs[MAXCONS];
 
 static  char        	init_done = COLD;
 static  char		shutdown_in_progress = FALSE;
_at__at_ -151,6 +153,7 _at__at_
 static int scparam(struct tty *tp, struct termios *t);
 static void scstart(struct tty *tp);
 static void scinit(int unit, int flags);
+static scr_stat *sc_get_stat(dev_t devptr);
 #if !__alpha__
 static void scterm(int unit, int flags);
 #endif
_at__at_ -331,7 +334,7 _at__at_
 
     sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
     sc->config = flags;
-    scp = SC_STAT(sc->dev[0]);
+    scp = sc_get_stat(sc->dev[0]);
     if (sc_console == NULL)	/* sc_console_unit < 0 */
 	sc_console = scp;
 
_at__at_ -388,6 +391,9 _at__at_
 		dev = make_dev(&sc_cdevsw, vc + unit * MAXCONS,
 		    UID_ROOT, GID_WHEEL, 0600, "ttyv%r", vc + unit * MAXCONS);
 		sc->dev[vc] = dev;
+	    	sc->dev[vc]->si_tty = ttymalloc(sc->dev[vc]->si_tty);
+		if (vc == 0 && sc->dev == main_devs)
+			SC_STAT(sc->dev[0]) = &main_console;
 	}
 	/*
 	 * The first vty already has struct tty and scr_stat initialized
_at__at_ -497,7 +503,7 _at__at_
 
     error = (*linesw[tp->t_line].l_open)(dev, tp);
 
-    scp = SC_STAT(dev);
+    scp = sc_get_stat(dev);
     if (scp == NULL) {
 	scp = SC_STAT(dev) = alloc_scp(sc, SC_VTY(dev));
 	if (ISGRAPHSC(scp))
_at__at_ -519,7 +525,7 _at__at_
     int s;
 
     if (SC_VTY(dev) != SC_CONSOLECTL) {
-	scp = SC_STAT(tp->t_dev);
+	scp = sc_get_stat(tp->t_dev);
 	/* were we in the middle of the VT switching process? */
 	DPRINTF(5, ("sc%d: scclose(), ", scp->sc->unit));
 	s = spltty();
_at__at_ -682,7 +688,7 _at__at_
 	return error;
 #endif
 
-    scp = SC_STAT(tp->t_dev);
+    scp = sc_get_stat(tp->t_dev);
     /* assert(scp != NULL) */
     /* scp is sc_console, if SC_VTY(dev) == SC_CONSOLECTL. */
     sc = scp->sc;
_at__at_ -1015,7 +1021,7 _at__at_
 	splx(s);
 	if (error)
 	    return error;
-	scp = SC_STAT(SC_DEV(sc, i));
+	scp = sc_get_stat(SC_DEV(sc, i));
 	if (scp == scp->sc->cur_scp)
 	    return 0;
 	while ((error=tsleep(&scp->smode, PZERO|PCATCH,
_at__at_ -1353,7 +1359,7 _at__at_
     struct clist *rbp;
     int s, len;
     u_char buf[PCBURST];
-    scr_stat *scp = SC_STAT(tp->t_dev);
+    scr_stat *scp = sc_get_stat(tp->t_dev);
 
     if (scp->status & SLKED ||
 	(scp == scp->sc->cur_scp && scp->sc->blink_in_progress))
_at__at_ -1417,7 +1423,7 _at__at_
     sc_get_cons_priority(&unit, &flags);
     scinit(unit, flags | SC_KERNEL_CONSOLE);
     sc_console_unit = unit;
-    sc_console = SC_STAT(sc_get_softc(unit, SC_KERNEL_CONSOLE)->dev[0]);
+    sc_console = sc_get_stat(sc_get_softc(unit, SC_KERNEL_CONSOLE)->dev[0]);
     sc_consptr = cp;
 #endif /* !__alpha__ */
 
_at__at_ -1475,7 +1481,7 _at__at_
     scinit(unit, flags | SC_KERNEL_CONSOLE);
     sc_console_unit = unit;
     sc_consptr = &consdev;
-    sc_console = SC_STAT(sc_get_softc(unit, SC_KERNEL_CONSOLE)->dev[0]);
+    sc_console = sc_get_stat(sc_get_softc(unit, SC_KERNEL_CONSOLE)->dev[0]);
     sprintf(consdev.cn_name, "ttyv%r", 0);
     cnadd(&consdev);
 }
_at__at_ -2312,7 +2318,7 _at__at_
     ++sc->switch_in_progress;
     sc->delayed_next_scr = 0;
     sc->old_scp = cur_scp;
-    sc->new_scp = SC_STAT(SC_DEV(sc, next_scr));
+    sc->new_scp = sc_get_stat(SC_DEV(sc, next_scr));
     if (sc->new_scp == sc->old_scp) {
 	sc->switch_in_progress = 0;
 	/*
_at__at_ -2624,7 +2630,7 _at__at_
     for (i = sc->first_vty; i < sc->first_vty + sc->vtys; ++i) {
 	if ((dev = SC_DEV(sc, i)) == NODEV)
 	    continue;
-	if ((scp = SC_STAT(dev)) == NULL)
+	if ((scp = sc_get_stat(dev)) == NULL)
 	    continue;
 	scp->dflt_curs_attr = sc->curs_attr;
 	change_cursor_shape(scp, CONS_RESET_CURSOR, -1, -1);
_at__at_ -2642,9 +2648,6 _at__at_
      * static buffers for the console.  This is less than ideal, 
      * but is necessry evil for the time being.  XXX
      */
-    static scr_stat main_console;
-    static dev_t main_devs[MAXCONS];
-    static struct tty main_tty;
 #ifdef PC98
     static u_short sc_buffer[ROW*COL*2];/* XXX */
 #else
_at__at_ -2727,11 +2730,12 _at__at_
 	sc->first_vty = unit*MAXCONS;
 	sc->vtys = MAXCONS;		/* XXX: should be configurable */
 	if (flags & SC_KERNEL_CONSOLE) {
+	    /*
+	     * Set up devs structure but don't use it yet, calling make_dev()
+	     * might panic kernel.  Wait for sc_attach_unit() to actually
+	     * create the devices.
+	     */
 	    sc->dev = main_devs;
-	    sc->dev[0] = make_dev(&sc_cdevsw, unit * MAXCONS,
-	        UID_ROOT, GID_WHEEL, 0600, "ttyv%r", unit * MAXCONS);
-	    sc->dev[0]->si_tty = &main_tty;
-	    ttyregister(&main_tty);
 	    scp = &main_console;
 	    init_scp(sc, sc->first_vty, scp);
 	    sc_vtb_init(&scp->vtb, VTB_MEMORY, scp->xsize, scp->ysize,
_at__at_ -2748,8 +2752,8 _at__at_
 	        UID_ROOT, GID_WHEEL, 0600, "ttyv%r", unit * MAXCONS);
 	    sc->dev[0]->si_tty = ttymalloc(sc->dev[0]->si_tty);
 	    scp = alloc_scp(sc, sc->first_vty);
+	    SC_STAT(sc->dev[0]) = scp;
 	}
-	SC_STAT(sc->dev[0]) = scp;
 	sc->cur_scp = scp;
 
 #ifndef __sparc64__
_at__at_ -2879,7 +2883,7 _at__at_
 	vid_release(sc->adp, &sc->adapter);
 
     /* stop the terminal emulator, if any */
-    scp = SC_STAT(sc->dev[0]);
+    scp = sc_get_stat(sc->dev[0]);
     if (scp->tsw)
 	(*scp->tsw->te_term)(scp, &scp->ts);
     if (scp->ts != NULL)
_at__at_ -3412,7 +3416,7 _at__at_
 {
     scr_stat *scp;
 
-    scp = SC_STAT(dev);
+    scp = sc_get_stat(dev);
     if (scp != scp->sc->cur_scp)
 	return -1;
     return (*vidsw[scp->sc->adapter]->mmap)(scp->sc->adp, offset, paddr, nprot);
_at__at_ -3620,4 +3624,12 _at__at_
 	scp->sc->blink_in_progress--;
 	timeout(blink_screen, scp, hz / 10);
     }
+}
+
+static scr_stat *
+sc_get_stat(dev_t devptr)
+{
+	if (devptr == NULL)
+		return (&main_console);
+	return (SC_STAT(devptr));
 }


-- 
						Ken Smith
- From there to here, from here to      |       kensmith_at_cse.buffalo.edu
  there, funny things are everywhere.   |
                      - Theodore Geisel |
Received on Wed Mar 31 2004 - 07:59:12 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:49 UTC