All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: James Simmons <jsimmons@infradead.org>
Cc: Linux Fbdev development list <linux-fbdev-devel@lists.sourceforge.net>
Subject: [PATCH] Fix switch from XFree
Date: Tue, 10 Feb 2004 21:36:42 +1100	[thread overview]
Message-ID: <1076409397.873.6.camel@gaston> (raw)

Hi James !

(This patch includes the one adding the lock around the notifier
registration so you can drop that previous one)

Currently, there is a problem when switching from XFree to a console
that became especially annoying now that we have some accelerations
in radeonfb 2.6. XFree leaves the accel engine in a state that is
incorrect for our accel operations. This problem is generic with most
drivers, we can't expect X to leave the accel engine in the right
state, that's simply unrealistic.

The approach I've taken is from fbcon_switch, to check wether we
are switching from KD_GRAPHICS to a KD_TEXT console, and in this
case, cause fb_set_var with an additional flag I defined,
FB_ACTIVATE_FORCE, which will just bypass the comparison on the
var structure, forcing set_par to be called again.

That works for normal switches. That doesn't quite deal with a
console beeing switched from KD_GRAPHICS to KD_TEXT, there is
no consw hook for that, so one would have to be added for this
purpose I suspect... But that part of the problem is much less
annoying in practice.

The patch also include a couple of leftover fixes from my tree,
it's too late for me to split things up ;) Mostly dealing with
the cursor when the fb is sleeping

(Oh, and that FB_PIXMAP_IO seemed wrong, I switched back to
_DEFAULT, as it's not mapped into card space afaik)

Ben.

diff -urN fbdev-2.5/drivers/video/console/fbcon.c linuxppc-2.5-benh/drivers/video/console/fbcon.c
--- fbdev-2.5/drivers/video/console/fbcon.c	2004-02-09 14:48:31.000000000 +1100
+++ linuxppc-2.5-benh/drivers/video/console/fbcon.c	2004-02-10 21:05:25.000000000 +1100
@@ -196,7 +196,7 @@
 {
 	struct fb_info *info = (struct fb_info *) private;
 
-	if (!info)
+	if (!info || info->state != FBINFO_STATE_RUNNING)
 		return;
 	info->cursor.enable ^= 1;
 	info->fbops->fb_cursor(info, &info->cursor);
@@ -602,7 +602,6 @@
 
 	/* on which frame buffer will we open this console? */
 	info = registered_fb[(int) con2fb_map[unit]];
-	
 	if (info->var.accel_flags)
 		fb_display[unit].scrollmode = SCROLL_YNOMOVE;
 	else
@@ -1564,8 +1563,8 @@
 			height, width);
 }
 
-static int fbcon_resize(struct vc_data *vc, unsigned int width, 
-			unsigned int height)
+static int fbcon_do_resize(struct vc_data *vc, unsigned int width, 
+			   unsigned int height, int force)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
@@ -1573,13 +1572,14 @@
 	int err; int x_diff, y_diff;
 	int fw = vc->vc_font.width;
 	int fh = vc->vc_font.height;
+	int rc = 0;
 
 	var.xres = width * fw;
 	var.yres = height * fh;
 	x_diff = info->var.xres - var.xres;
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > fw ||
-	   (y_diff < 0 || y_diff > fh)) {
+	   (y_diff < 0 || y_diff > fh) || force) {
 		var.activate = FB_ACTIVATE_FIND;
 		err = fb_set_var(info, &var);
 		if (err || width > var.xres/fw ||
@@ -1587,6 +1587,8 @@
 			return -EINVAL;
        		DPRINTK("resize now %ix%i\n", var.xres, var.yres);
 		var.activate = FB_ACTIVATE_NOW;
+		if (force)
+			var.activate |= FB_ACTIVATE_FORCE;
 		/* This flag is enough for now as we are supposed to hold
 		 * the console semaphore at this point. I agree it's a bit
 		 * ugly but it does the job until some better solution is
@@ -1595,17 +1597,25 @@
 		console_resizing = 1;
 		fb_set_var(info, &var);
 		console_resizing = 0;
+		rc = 1;
 	}
 	p->vrows = var.yres_virtual/fh;
 	if (var.yres > (fh * (height + 1)))
 		p->vrows -= (var.yres - (fh * height)) / fh;
-	return 0;
+	return rc;
+}
+
+static int fbcon_resize(struct vc_data *vc, unsigned int width, 
+			unsigned int height)
+{
+	return fbcon_do_resize(vc, width, height, 0);
 }
 
 static int fbcon_switch(struct vc_data *vc)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+	int gfx_to_text = 0;
 
 	if (softback_top) {
 		int l = fbcon_softback_size / vc->vc_size_row;
@@ -1633,12 +1643,17 @@
 	if (info)
 		info->var.yoffset = p->yscroll = 0;
 
+	if (info->currcon == -1 ||
+	    (vt_cons[info->currcon]->vc_mode != KD_TEXT &&
+	     vt_cons[vc->vc_num]->vc_mode == KD_TEXT))
+		gfx_to_text = 1;
+
 	/* Set currcon before fbcon_resize or we'll do bad things
 	 * when fbdev calls us back on mode changed notification
 	 */
 	info->currcon = vc->vc_num;
 
-        fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
+        fbcon_do_resize(vc, vc->vc_cols, vc->vc_rows, gfx_to_text);
 	switch (p->scrollmode & __SCROLL_YMASK) {
 	case __SCROLL_YWRAP:
 		scrollback_phys_max = p->vrows - vc->vc_rows;
@@ -2247,24 +2262,31 @@
 
 static void fbcon_suspended(struct fb_info *info)
 {
-	/* Here, we should do something to properly erase the
-	 * cursor and synchronize with the cursor interrupt on
-	 * SMP... (may not be that critical though...)
-	 */
+	/* Clear cursor, restore saved data */
+	info->cursor.enable = 0;
+	info->fbops->fb_cursor(info, &info->cursor);
 }
 
 static void fbcon_resumed(struct fb_info *info)
 {
-	struct vc_data *vc = vc_cons[info->currcon].d;
+	struct vc_data *vc;
+
+	if (info->currcon < 0)
+		return;
+	vc = vc_cons[info->currcon].d;
 
 	update_screen(vc->vc_num);
 }
 
 static void fbcon_mode_changed(struct fb_info *info)
 {
-	struct vc_data *vc = vc_cons[info->currcon].d;
+	struct vc_data *vc;
 	int rows, cols;
 
+	if (info->currcon < 0)
+		return;
+	vc = vc_cons[info->currcon].d;
+
 	/* This isn't perfect yet. If we change one console, we
 	 * don't change them all and we switch back to the wrong
 	 * mode on next console switch. We need to either keep a
@@ -2339,6 +2361,7 @@
 	.notifier_call	= fbcon_event_notify,
 };
 
+static int fbcon_event_notifier_registered;
 
 int __init fb_console_init(void)
 {
@@ -2349,14 +2372,24 @@
 	take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
 	info = registered_fb[num_registered_fb-1];	
 
-	fb_register_client(&fbcon_event_notifer);
+	acquire_console_sem();
+	if (!fbcon_event_notifier_registered) {
+		fb_register_client(&fbcon_event_notifer);
+		fbcon_event_notifier_registered = 1;
+	} 
+	release_console_sem();
 
 	return 0;
 }
 
 void __exit fb_console_exit(void)
 {
-	fb_unregister_client(&fbcon_event_notifer);
+	acquire_console_sem();
+	if (fbcon_event_notifier_registered) {
+		fb_unregister_client(&fbcon_event_notifer);
+		fbcon_event_notifier_registered = 0;
+	}
+	release_console_sem();
 	give_up_console(&fb_con);
 }	
 
diff -urN fbdev-2.5/drivers/video/fbmem.c linuxppc-2.5-benh/drivers/video/fbmem.c
--- fbdev-2.5/drivers/video/fbmem.c	2004-02-10 21:15:18.000000000 +1100
+++ linuxppc-2.5-benh/drivers/video/fbmem.c	2004-02-10 21:01:47.000000000 +1100
@@ -965,7 +965,8 @@
 {
 	int err;
 
-	if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
+	if ((var->activate & FB_ACTIVATE_FORCE) ||
+	    memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
 		if (!info->fbops->fb_check_var) {
 			*var = info->var;
 			return 0;
@@ -1023,7 +1024,7 @@
 	struct fb_con2fbmap con2fb;
 #endif
 	struct fb_cmap cmap;
-	int i;
+	int i, rc;
 	
 	if (!fb)
 		return -ENODEV;
@@ -1064,7 +1065,10 @@
 			return -EFAULT;
 		return 0;
 	case FBIO_CURSOR:
-		return (fb_cursor(info, (struct fb_cursor *) arg));
+		acquire_console_sem();
+		rc = fb_cursor(info, (struct fb_cursor *) arg);
+		release_console_sem();
+		return rc;
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
@@ -1304,7 +1308,7 @@
 			fb_info->sprite.size = FBPIXMAPSIZE;
 			fb_info->sprite.buf_align = sizeof(unsigned long);
 			fb_info->sprite.scan_align = sizeof(unsigned long);
-			fb_info->sprite.flags = FB_PIXMAP_IO;
+			fb_info->sprite.flags = FB_PIXMAP_DEFAULT;
 		}
 	}	
 	fb_info->sprite.offset = 0;
@@ -1411,7 +1415,7 @@
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
 
 	class_register(&fb_class);
-	
+
 #ifdef CONFIG_FB_OF
 	if (ofonly) {
 		offb_init();
diff -urN fbdev-2.5/include/linux/fb.h linuxppc-2.5-benh/include/linux/fb.h
--- fbdev-2.5/include/linux/fb.h	2004-02-10 21:15:19.000000000 +1100
+++ linuxppc-2.5-benh/include/linux/fb.h	2004-02-10 20:58:22.000000000 +1100
@@ -153,6 +153,7 @@
 #define FB_ACTIVATE_VBL	       16	/* activate values on next vbl  */
 #define FB_CHANGE_CMAP_VBL     32	/* change colormap on vbl	*/
 #define FB_ACTIVATE_ALL	       64	/* change all VCs on this fb	*/
+#define FB_ACTIVATE_FORCE     128	/* force apply even when no change*/
 
 #define FB_ACCELF_TEXT		1	/* text mode acceleration */
 
@@ -391,10 +392,10 @@
 #include <linux/notifier.h>
 #include <asm/io.h>
 
-struct vm_area_struct;
 struct fb_info;
-struct device;
+struct vm_area_struct;
 struct file;
+struct device;
 
 /*
  * Register/unregister for framebuffer events
@@ -418,9 +419,9 @@
  * Pixmap structure definition
  *
  * The purpose of this structure is to translate data
- * from the hardware independent format of fbdev to what 
+ * from the hardware independent format of fbdev to what
  * format the hardware needs.
- */ 
+ */
 
 #define FB_PIXMAP_DEFAULT 1     /* used internally by fbcon */
 #define FB_PIXMAP_SYSTEM  2     /* memory is in system RAM  */




-------------------------------------------------------
The SF.Net email is sponsored by EclipseCon 2004
Premiere Conference on Open Tools Development and Integration
See the breadth of Eclipse activity. February 3-5 in Anaheim, CA.
http://www.eclipsecon.org/osdn

             reply	other threads:[~2004-02-10 10:36 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-10 10:36 Benjamin Herrenschmidt [this message]
2004-02-10 11:06 ` [PATCH] Fix switch from XFree Sven Luther
2004-02-10 11:17   ` Benjamin Herrenschmidt
2004-02-10 11:28     ` Sven Luther
2004-02-10 11:31       ` Benjamin Herrenschmidt
2004-02-10 12:34         ` Geert Uytterhoeven
2004-02-10 22:13           ` Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1076409397.873.6.camel@gaston \
    --to=benh@kernel.crashing.org \
    --cc=jsimmons@infradead.org \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.