]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/video/console/fbcon.c
[PATCH] autofs4: fix another race between mount and expire
[linux-2.6-omap-h63xx.git] / drivers / video / console / fbcon.c
index 050856e09e8726ffea147b9afdcb9485fbf8460c..0429fd2cece09cff24a3e3f849a9894bac3056cb 100644 (file)
@@ -60,7 +60,6 @@
 
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>       /* MSch: for IRQ probe */
@@ -133,6 +132,7 @@ static int info_idx = -1;
 
 /* console rotation */
 static int rotate;
+static int fbcon_has_sysfs;
 
 static const struct consw fb_con;
 
@@ -203,7 +203,7 @@ static struct class_device *fbcon_class_device;
  */
 static int vbl_detected;
 
-static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t fb_vbl_detect(int irq, void *dummy)
 {
        vbl_detected++;
        return IRQ_HANDLED;
@@ -382,9 +382,9 @@ static void fbcon_update_softback(struct vc_data *vc)
                softback_top = 0;
 }
 
-static void fb_flashcursor(void *private)
+static void fb_flashcursor(struct work_struct *work)
 {
-       struct fb_info *info = private;
+       struct fb_info *info = container_of(work, struct fb_info, queue);
        struct fbcon_ops *ops = info->fbcon_par;
        struct display *p;
        struct vc_data *vc = NULL;
@@ -396,9 +396,8 @@ static void fb_flashcursor(void *private)
                vc = vc_cons[ops->currcon].d;
 
        if (!vc || !CON_IS_VISIBLE(vc) ||
-           fbcon_is_inactive(vc, info) ||
            registered_fb[con2fb_map[vc->vc_num]] != info ||
-           vc_cons[ops->currcon].d->vc_deccm != 1) {
+           vc->vc_deccm != 1) {
                release_console_sem();
                return;
        }
@@ -414,7 +413,7 @@ static void fb_flashcursor(void *private)
 
 #if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
 static int cursor_blink_rate;
-static irqreturn_t fb_vbl_handler(int irq, void *dev_id, struct pt_regs *fp)
+static irqreturn_t fb_vbl_handler(int irq, void *dev_id)
 {
        struct fb_info *info = dev_id;
 
@@ -442,7 +441,7 @@ static void fbcon_add_cursor_timer(struct fb_info *info)
        if ((!info->queue.func || info->queue.func == fb_flashcursor) &&
            !(ops->flags & FBCON_FLAGS_CURSOR_TIMER)) {
                if (!info->queue.func)
-                       INIT_WORK(&info->queue, fb_flashcursor, info);
+                       INIT_WORK(&info->queue, fb_flashcursor);
 
                init_timer(&ops->cursor_timer);
                ops->cursor_timer.function = cursor_timer_handler;
@@ -2071,7 +2070,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
        y_diff = info->var.yres - var.yres;
        if (x_diff < 0 || x_diff > virt_fw ||
            y_diff < 0 || y_diff > virt_fh) {
-               struct fb_videomode *mode;
+               const struct fb_videomode *mode;
 
                DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
                mode = fb_find_best_mode(&var, &info->modelist);
@@ -2166,7 +2165,12 @@ static int fbcon_switch(struct vc_data *vc)
                        fbcon_del_cursor_timer(old_info);
        }
 
-       fbcon_add_cursor_timer(info);
+       if (fbcon_is_inactive(vc, info) ||
+           ops->blank_state != FB_BLANK_UNBLANK)
+               fbcon_del_cursor_timer(info);
+       else
+               fbcon_add_cursor_timer(info);
+
        set_blitting_type(vc, info);
        ops->cursor_reset = 1;
 
@@ -2229,6 +2233,8 @@ static int fbcon_switch(struct vc_data *vc)
 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                                int blank)
 {
+       struct fb_event event;
+
        if (blank) {
                unsigned short charmask = vc->vc_hi_font_mask ?
                        0x1ff : 0xff;
@@ -2239,6 +2245,11 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
                fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols);
                vc->vc_video_erase_char = oldc;
        }
+
+
+       event.info = info;
+       event.data = &blank;
+       fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
 }
 
 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
@@ -2276,10 +2287,11 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
                        update_screen(vc);
        }
 
-       if (!blank)
-               fbcon_add_cursor_timer(info);
-       else
+       if (fbcon_is_inactive(vc, info) ||
+           ops->blank_state != FB_BLANK_UNBLANK)
                fbcon_del_cursor_timer(info);
+       else
+               fbcon_add_cursor_timer(info);
 
        return 0;
 }
@@ -2969,7 +2981,7 @@ static void fbcon_new_modelist(struct fb_info *info)
        int i;
        struct vc_data *vc;
        struct fb_var_screeninfo var;
-       struct fb_videomode *mode;
+       const struct fb_videomode *mode;
 
        for (i = first_fb_vc; i <= last_fb_vc; i++) {
                if (registered_fb[con2fb_map[i]] != info)
@@ -3161,11 +3173,26 @@ static struct class_device_attribute class_device_attrs[] = {
 
 static int fbcon_init_class_device(void)
 {
-       int i;
+       int i, error = 0;
+
+       fbcon_has_sysfs = 1;
+
+       for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
+               error = class_device_create_file(fbcon_class_device,
+                                                &class_device_attrs[i]);
+
+               if (error)
+                       break;
+       }
+
+       if (error) {
+               while (--i >= 0)
+                       class_device_remove_file(fbcon_class_device,
+                                                &class_device_attrs[i]);
+
+               fbcon_has_sysfs = 0;
+       }
 
-       for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-               class_device_create_file(fbcon_class_device,
-                                        &class_device_attrs[i]);
        return 0;
 }
 
@@ -3274,9 +3301,13 @@ static void __exit fbcon_deinit_class_device(void)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
-               class_device_remove_file(fbcon_class_device,
-                                        &class_device_attrs[i]);
+       if (fbcon_has_sysfs) {
+               for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+                       class_device_remove_file(fbcon_class_device,
+                                                &class_device_attrs[i]);
+
+               fbcon_has_sysfs = 0;
+       }
 }
 
 static void __exit fb_console_exit(void)