diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 0c80c68..a32ad9d 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -3840,9 +3840,6 @@ static int con_font_get(struct vc_data *vc, struct console_font_op *op)
 	int rc = -EINVAL;
 	int c;
 
-	if (vc->vc_mode != KD_TEXT)
-		return -EINVAL;
-
 	if (op->data) {
 		font.data = kmalloc(max_font_size, GFP_KERNEL);
 		if (!font.data)
@@ -3895,8 +3892,6 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op)
 	int rc = -EINVAL;
 	int size;
 
-	if (vc->vc_mode != KD_TEXT)
-		return -EINVAL;
 	if (!op->data)
 		return -EINVAL;
 	if (op->charcount > 512)
@@ -3953,9 +3948,6 @@ static int con_font_default(struct vc_data *vc, struct console_font_op *op)
 	char *s = name;
 	int rc;
 
-	if (vc->vc_mode != KD_TEXT)
-		return -EINVAL;
-
 	if (!op->data)
 		s = NULL;
 	else if (strncpy_from_user(name, op->data, MAX_FONT_NAME - 1) < 0)
@@ -3981,9 +3973,6 @@ static int con_font_copy(struct vc_data *vc, struct console_font_op *op)
 	int con = op->height;
 	int rc;
 
-	if (vc->vc_mode != KD_TEXT)
-		return -EINVAL;
-
 	acquire_console_sem();
 	if (!vc->vc_sw->con_font_copy)
 		rc = -ENOSYS;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 73aff4c..10e31e0 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1602,29 +1602,8 @@ static void complete_change_console(struct vc_data *vc)
 	 */
 	old_vc_mode = oldvc->vc_mode;
 
-#if defined(CONFIG_VGA_CONSOLE)
-	if (old_vc_mode == KD_TEXT && oldvc->vc_sw == &vga_con &&
-	    oldvc->vc_sw->con_font_get) {
-		if (!oldvc->vc_font.data)
-			oldvc->vc_font.data = kmalloc(max_font_size, 
-						      GFP_KERNEL);
-		lock_kernel();
-		oldvc->vc_sw->con_font_get(oldvc, &oldvc->vc_font);
-		unlock_kernel();
-	}
-#endif
 	switch_screen(vc);
 
-#if defined(CONFIG_VGA_CONSOLE)
-	if (vc->vc_mode == KD_TEXT && vc->vc_sw == &vga_con &&
-	    vc->vc_sw->con_font_set) {
-		if (vc->vc_font.data) {
-			lock_kernel();
-			vc->vc_sw->con_font_set(vc, &vc->vc_font, 0);
-			unlock_kernel();
-		}
-	}
-#endif
 	/*
 	 * This can't appear below a successful kill_pid().  If it did,
 	 * then the *blank_screen operation could occur while X, having
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index da55cca..613c2cd 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -70,6 +70,11 @@ static struct vgastate state;
  */
 #undef TRIDENT_GLITCH
 #define VGA_FONTWIDTH       8   /* VGA does not support fontwidths != 8 */
+
+/* Font; borrowed from fbcon.c */
+#define REFCOUNT(fd)	(((int *)(fd))[-1])
+#define FONT_EXTRA_WORDS 1
+
 /*
  *  Interface used by the world
  */
@@ -80,6 +85,8 @@ static void vgacon_deinit(struct vc_data *c);
 static void vgacon_cursor(struct vc_data *c, int mode);
 static int vgacon_switch(struct vc_data *c);
 static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
+static int vgacon_do_font_op(struct vgastate *state, char *arg, int set,
+			     int ch512);
 static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);
 static int vgacon_scrolldelta(struct vc_data *c, int lines);
 static int vgacon_set_origin(struct vc_data *c);
@@ -103,6 +110,9 @@ static unsigned int	vga_default_font_height __read_mostly;	/* Height of default
 static unsigned char	vga_video_type		__read_mostly;	/* Card type */
 static unsigned char	vga_hardscroll_enabled	__read_mostly;
 static unsigned char	vga_hardscroll_user_enable __read_mostly = 1;
+#if defined(CAN_LOAD_EGA_FONTS) && defined(BROKEN_GRAPHICS_PROGRAMS)
+static unsigned char *	vga_default_font;
+#endif
 static unsigned char	vga_font_is_default = 1;
 static int		vga_vesa_blanked;
 static int 		vga_palette_blanked;
@@ -546,6 +556,21 @@ static const char *vgacon_startup(void)
 	vgacon_xres = screen_info.orig_video_cols * VGA_FONTWIDTH;
 	vgacon_yres = vga_scan_lines;
 
+#if defined(CAN_LOAD_EGA_FONTS) && defined(BROKEN_GRAPHICS_PROGRAMS)
+	/* Remember the default font so that we can restore it.  Otherwise,
+	 * switching VC from one with a custom font to one with the default
+	 * font will fail.
+	 */
+	/* Default font is always 256 characters */
+	vga_default_font = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + 256 * 32,
+				   GFP_USER);
+	if (vga_default_font) {
+		vga_default_font += FONT_EXTRA_WORDS * sizeof(int);
+		REFCOUNT(vga_default_font) = 1; /* should never go to 0 */
+		vgacon_do_font_op(&state, vga_default_font, 0, 0);
+	}
+#endif
+
 	if (!vga_init_done) {
 		vgacon_scrollback_startup();
 		vga_init_done = 1;
@@ -574,6 +599,13 @@ static void vgacon_init(struct vc_data *c, int init)
 
 	c->vc_scan_lines = vga_scan_lines;
 	c->vc_font.height = vga_video_font_height;
+	c->vc_font.charcount = 256;
+#if defined(CAN_LOAD_EGA_FONTS) && defined(BROKEN_GRAPHICS_PROGRAMS)
+	c->vc_font.data = vga_default_font;
+	REFCOUNT(vga_default_font)++;
+#else
+	c->vc_font.data = NULL;
+#endif
 	c->vc_complement_mask = 0x7700;
 	if (vga_512_chars)
 		c->vc_hi_font_mask = 0x0800;
@@ -587,6 +619,13 @@ static void vgacon_init(struct vc_data *c, int init)
 		con_set_default_unimap(c);
 }
 
+static void vgacon_free_font(struct vc_data *c)
+{
+	if (c->vc_font.data && --REFCOUNT(c->vc_font.data) == 0)
+		kfree(c->vc_font.data - FONT_EXTRA_WORDS * sizeof(int));
+	c->vc_font.data = NULL;
+}
+
 static void vgacon_deinit(struct vc_data *c)
 {
 	/* When closing the active console, reset video origin */
@@ -599,6 +638,8 @@ static void vgacon_deinit(struct vc_data *c)
 		con_free_unimap(c);
 	c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
 	con_set_default_unimap(c);
+
+	vgacon_free_font(c);
 }
 
 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
@@ -838,6 +879,13 @@ static int vgacon_switch(struct vc_data *c)
 		     vga_video_num_columns <= screen_info.orig_video_cols &&
 		     vga_video_num_lines <= rows))
 			vgacon_doresize(c, c->vc_cols, c->vc_rows);
+
+#ifdef CAN_LOAD_EGA_FONTS
+		lock_kernel();
+		vgacon_do_font_op(&state, c->vc_font.data, 1,
+				  c->vc_font.charcount == 512);
+		unlock_kernel();
+#endif
 	}
 
 	vgacon_scrollback_init(c->vc_size_row);
@@ -1076,15 +1124,20 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
 		beg = 0x0a;
 	}
 
+	if (set) {
+		vga_font_is_default = !arg;
+		if (!arg)
+			ch512 = 0;	/* Default font is always 256 */
+	}
+
 #ifdef BROKEN_GRAPHICS_PROGRAMS
 	/*
 	 * All fonts are loaded in slot 0 (0:1 for 512 ch)
 	 */
 
-	if (!arg)
-		return -EINVAL;	/* Return to default font not supported */
+	if (!arg && set)
+		arg = vga_default_font; /* Return to default font */
 
-	vga_font_is_default = 0;
 	font_select = ch512 ? 0x04 : 0x00;
 #else
 	/*
@@ -1092,12 +1145,8 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
 	 * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch)
 	 */
 
-	if (set) {
-		vga_font_is_default = !arg;
-		if (!arg)
-			ch512 = 0;	/* Default font is always 256 */
+	if (set)
 		font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00;
-	}
 
 	if (!vga_font_is_default)
 		charmap += 4 * cmapsz;
@@ -1169,12 +1218,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
 
 	/* if 512 char mode is already enabled don't re-enable it. */
 	if ((set) && (ch512 != vga_512_chars)) {
-		/* attribute controller */
-		for (i = 0; i < MAX_NR_CONSOLES; i++) {
-			struct vc_data *c = vc_cons[i].d;
-			if (c && c->vc_sw == &vga_con)
-				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
-		}
 		vga_512_chars = ch512;
 		/* 256-char: enable intensity bit
 		   512-char: disable intensity bit */
@@ -1197,7 +1240,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
 static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
 {
 	unsigned char ovr, vde, fsr;
-	int rows, maxscan, i;
+	int rows, maxscan;
 
 	rows = vc->vc_scan_lines / fontheight;	/* Number of video rows we end up with */
 	maxscan = rows * fontheight - 1;	/* Scan lines to actually display-1 */
@@ -1234,27 +1277,16 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
 	spin_unlock_irq(&vga_lock);
 	vga_video_font_height = fontheight;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		struct vc_data *c = vc_cons[i].d;
-
-		if (c && c->vc_sw == &vga_con) {
-			if (CON_IS_VISIBLE(c)) {
-			        /* void size to cause regs to be rewritten */
-				cursor_size_lastfrom = 0;
-				cursor_size_lastto = 0;
-				c->vc_sw->con_cursor(c, CM_DRAW);
-			}
-			c->vc_font.height = fontheight;
-			vc_resize(c, 0, rows);	/* Adjust console size */
-		}
-	}
 	return 0;
 }
 
 static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigned flags)
 {
 	unsigned charcount = font->charcount;
-	int rc;
+	int h = font->height;
+	int i;
+	u8 *new_data, *data = font->data;
+	int rc = 0;
 
 	if (vga_video_type < VIDEO_TYPE_EGAM)
 		return -EINVAL;
@@ -1263,26 +1295,78 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne
 	    (charcount != 256 && charcount != 512))
 		return -EINVAL;
 
-	rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512);
-	if (rc)
-		return rc;
+	new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + charcount * 32,
+			   GFP_USER);
+	if (!new_data)
+		return -ENOMEM;
+
+	new_data += FONT_EXTRA_WORDS * sizeof(int);
+	REFCOUNT(new_data) = 0;	/* usage counter */
+	memcpy(new_data, data, charcount * 32);
+
+	/* Check if the same font is on some other console already */
+	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		struct vc_data *other = vc_cons[i].d;
+		if (i != c->vc_num && other &&
+		    other->vc_font.height == h &&
+		    other->vc_font.charcount == charcount &&
+		    !memcmp(other->vc_font.data, new_data, charcount * 32)) {
+			kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
+			new_data = (u8 *)other->vc_font.data;
+			break;
+		}
+	}
+
+	if (CON_IS_VISIBLE(c)) {
+		rc = vgacon_do_font_op(&state, new_data, 1, charcount == 512);
+		if (rc)
+			return rc;
+	}
+
+	c->vc_font.height = h;
+	c->vc_font.charcount = charcount;
+	c->vc_font.data = new_data;
+	REFCOUNT(new_data)++;
+	/* attribute controller */
+	c->vc_hi_font_mask = (charcount == 512) ? 0x0800 : 0;
 
 	if (!(flags & KD_FONT_FLAG_DONT_RECALC))
 		rc = vgacon_adjust_height(c, font->height);
+	if (CON_IS_VISIBLE(c)) {
+		/* void size to cause regs to be rewritten */
+		cursor_size_lastfrom = 0;
+		cursor_size_lastto = 0;
+		c->vc_sw->con_cursor(c, CM_DRAW);
+	}
+	/* Adjust console size */
+	vc_resize(c, 0, c->vc_scan_lines / font->height);
 	return rc;
 }
 
 static int vgacon_font_get(struct vc_data *c, struct console_font *font)
 {
+	u8 *fontdata = c->vc_font.data;
+	u8 *data = font->data;
+	int i, j;
+
 	if (vga_video_type < VIDEO_TYPE_EGAM)
 		return -EINVAL;
 
 	font->width = VGA_FONTWIDTH;
 	font->height = c->vc_font.height;
-	font->charcount = vga_512_chars ? 512 : 256;
-	if (!font->data)
+	font->charcount = c->vc_font.charcount;
+	if (fontdata) {
+		j = font->height;
+		for (i = 0; i < font->charcount; i++) {
+			memcpy(data, fontdata, j);
+			memset(data + j, 0, 32 - j);
+			data += 32;
+			fontdata += j;
+		}
 		return 0;
-	return vgacon_do_font_op(&state, font->data, 0, vga_512_chars);
+	} else
+		return vgacon_do_font_op(&state, font->data, 0,
+					 font->charcount);
 }
 
 #else
