Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Mar 2004 12:59:10 -0500
From:      Ken Smith <kensmith@cse.Buffalo.EDU>
To:        freebsd-current@freebsd.org
Subject:   Testing a patch to syscons(4)
Message-ID:  <20040331175910.GF21402@electra.cse.Buffalo.EDU>

next in thread | raw e-mail | index | archive | help

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
@@ -99,6 +99,8 @@
 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;
@@ -151,6 +153,7 @@
 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
@@ -331,7 +334,7 @@
 
     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;
 
@@ -388,6 +391,9 @@
 		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
@@ -497,7 +503,7 @@
 
     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))
@@ -519,7 +525,7 @@
     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();
@@ -682,7 +688,7 @@
 	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;
@@ -1015,7 +1021,7 @@
 	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,
@@ -1353,7 +1359,7 @@
     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))
@@ -1417,7 +1423,7 @@
     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__ */
 
@@ -1475,7 +1481,7 @@
     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);
 }
@@ -2312,7 +2318,7 @@
     ++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;
 	/*
@@ -2624,7 +2630,7 @@
     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);
@@ -2642,9 +2648,6 @@
      * 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
@@ -2727,11 +2730,12 @@
 	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,
@@ -2748,8 +2752,8 @@
 	        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__
@@ -2879,7 +2883,7 @@
 	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)
@@ -3412,7 +3416,7 @@
 {
     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);
@@ -3620,4 +3624,12 @@
 	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@cse.buffalo.edu
  there, funny things are everywhere.   |
                      - Theodore Geisel |



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040331175910.GF21402>