Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'topic/remove-fbcon-notifiers' into drm-misc-next

topic/remove-fbcon-notifiers:
- remove fbdev notifier usage for fbcon, as prep work to clean up the fbcon locking
- assorted locking checks in vt/console code
- assorted notifier and cleanups in fbdev and backlight code

This is the pull request that was sent out, plus the compile fix for
sh4 reported by kbuild.

Acked-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>

+401 -786
+11 -2
arch/arm/mach-pxa/am200epd.c
··· 347 347 { 348 348 int ret; 349 349 350 - /* before anything else, we request notification for any fb 351 - * creation events */ 350 + /* 351 + * Before anything else, we request notification for any fb 352 + * creation events. 353 + * 354 + * FIXME: This is terrible and needs to be nuked. The notifier is used 355 + * to get at the fb base address from the boot splash fb driver, which 356 + * is then passed to metronomefb. Instaed of metronomfb or this board 357 + * support file here figuring this out on their own. 358 + * 359 + * See also the #ifdef in fbmem.c. 360 + */ 352 361 fb_register_client(&am200_fb_notif); 353 362 354 363 pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config));
+3 -8
drivers/gpu/vga/vga_switcheroo.c
··· 35 35 #include <linux/debugfs.h> 36 36 #include <linux/fb.h> 37 37 #include <linux/fs.h> 38 + #include <linux/fbcon.h> 38 39 #include <linux/module.h> 39 40 #include <linux/pci.h> 40 41 #include <linux/pm_domain.h> ··· 735 734 if (!active->driver_power_control) 736 735 set_audio_state(active->id, VGA_SWITCHEROO_OFF); 737 736 738 - if (new_client->fb_info) { 739 - struct fb_event event; 740 - 741 - console_lock(); 742 - event.info = new_client->fb_info; 743 - fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); 744 - console_unlock(); 745 - } 737 + if (new_client->fb_info) 738 + fbcon_remap_all(new_client->fb_info); 746 739 747 740 mutex_lock(&vgasr_priv.mux_hw_lock); 748 741 ret = vgasr_priv.handler->switchto(new_client->id);
+1 -5
drivers/media/pci/ivtv/ivtvfb.c
··· 1246 1246 struct osd_info *oi = itv->osd_info; 1247 1247 1248 1248 if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { 1249 - if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) { 1250 - IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", 1251 - itv->instance); 1252 - return 0; 1253 - } 1249 + unregister_framebuffer(&itv->osd_info->ivtvfb_info); 1254 1250 IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance); 1255 1251 itv->ivtvfb_restore = NULL; 1256 1252 ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
+3 -1
drivers/staging/fbtft/fbtft-core.c
··· 891 891 if (par->fbtftops.unregister_backlight) 892 892 par->fbtftops.unregister_backlight(par); 893 893 fbtft_sysfs_exit(par); 894 - return unregister_framebuffer(fb_info); 894 + unregister_framebuffer(fb_info); 895 + 896 + return 0; 895 897 } 896 898 EXPORT_SYMBOL(fbtft_unregister_framebuffer); 897 899
+7
drivers/staging/olpc_dcon/TODO
··· 1 1 TODO: 2 + - complete rewrite: 3 + 1. The underlying fbdev drivers need to be converted into drm kernel 4 + modesetting drivers. 5 + 2. The dcon low-power display mode can then be integrated using the 6 + drm damage tracking and self-refresh helpers. 7 + This bolted-on self-refresh support that digs around in fbdev 8 + internals, but isn't properly integrated, is not the correct solution. 2 9 - see if vx855 gpio API can be made similar enough to cs5535 so we can 3 10 share more code 4 11 - convert all uses of the old GPIO API from <linux/gpio.h> to the
+1 -5
drivers/staging/olpc_dcon/olpc_dcon.c
··· 250 250 int err; 251 251 252 252 console_lock(); 253 - if (!lock_fb_info(dcon->fbinfo)) { 254 - console_unlock(); 255 - dev_err(&dcon->client->dev, "unable to lock framebuffer\n"); 256 - return false; 257 - } 253 + lock_fb_info(dcon->fbinfo); 258 254 259 255 dcon->ignore_fb_events = true; 260 256 err = fb_blank(dcon->fbinfo,
+18
drivers/tty/vt/vt.c
··· 3822 3822 { 3823 3823 int i, bound = 0; 3824 3824 3825 + WARN_CONSOLE_UNLOCKED(); 3826 + 3825 3827 for (i = 0; i < MAX_NR_CONSOLES; i++) { 3826 3828 if (con_driver_map[i] == csw) { 3827 3829 bound = 1; ··· 3834 3832 return bound; 3835 3833 } 3836 3834 EXPORT_SYMBOL(con_is_bound); 3835 + 3836 + /** 3837 + * con_is_visible - checks whether the current console is visible 3838 + * @vc: virtual console 3839 + * 3840 + * RETURNS: zero if not visible, nonzero if visible 3841 + */ 3842 + bool con_is_visible(const struct vc_data *vc) 3843 + { 3844 + WARN_CONSOLE_UNLOCKED(); 3845 + 3846 + return *vc->vc_display_fg == vc; 3847 + } 3848 + EXPORT_SYMBOL(con_is_visible); 3837 3849 3838 3850 /** 3839 3851 * con_debug_enter - prepare the console for the kernel debugger ··· 4181 4165 { 4182 4166 struct vc_data *vc = vc_cons[fg_console].d; 4183 4167 int i; 4168 + 4169 + might_sleep(); 4184 4170 4185 4171 WARN_CONSOLE_UNLOCKED(); 4186 4172
+1 -1
drivers/video/backlight/backlight.c
··· 47 47 int fb_blank = 0; 48 48 49 49 /* If we aren't interested in this event, skip it immediately ... */ 50 - if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) 50 + if (event != FB_EVENT_BLANK) 51 51 return 0; 52 52 53 53 bd = container_of(self, struct backlight_device, fb_notif);
-12
drivers/video/backlight/lcd.c
··· 30 30 struct lcd_device *ld; 31 31 struct fb_event *evdata = data; 32 32 33 - /* If we aren't interested in this event, skip it immediately ... */ 34 - switch (event) { 35 - case FB_EVENT_BLANK: 36 - case FB_EVENT_MODE_CHANGE: 37 - case FB_EVENT_MODE_CHANGE_ALL: 38 - case FB_EARLY_EVENT_BLANK: 39 - case FB_R_EARLY_EVENT_BLANK: 40 - break; 41 - default: 42 - return 0; 43 - } 44 - 45 33 ld = container_of(self, struct lcd_device, fb_notif); 46 34 if (!ld->ops) 47 35 return 0;
+6
drivers/video/console/dummycon.c
··· 34 34 35 35 void dummycon_register_output_notifier(struct notifier_block *nb) 36 36 { 37 + WARN_CONSOLE_UNLOCKED(); 38 + 37 39 raw_notifier_chain_register(&dummycon_output_nh, nb); 38 40 39 41 if (dummycon_putc_called) ··· 44 42 45 43 void dummycon_unregister_output_notifier(struct notifier_block *nb) 46 44 { 45 + WARN_CONSOLE_UNLOCKED(); 46 + 47 47 raw_notifier_chain_unregister(&dummycon_output_nh, nb); 48 48 } 49 49 50 50 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) 51 51 { 52 + WARN_CONSOLE_UNLOCKED(); 53 + 52 54 dummycon_putc_called = true; 53 55 raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); 54 56 }
-64
drivers/video/fbdev/aty/aty128fb.c
··· 2350 2350 return -EINVAL; 2351 2351 } 2352 2352 2353 - #if 0 2354 - /* 2355 - * Accelerated functions 2356 - */ 2357 - 2358 - static inline void aty128_rectcopy(int srcx, int srcy, int dstx, int dsty, 2359 - u_int width, u_int height, 2360 - struct fb_info_aty128 *par) 2361 - { 2362 - u32 save_dp_datatype, save_dp_cntl, dstval; 2363 - 2364 - if (!width || !height) 2365 - return; 2366 - 2367 - dstval = depth_to_dst(par->current_par.crtc.depth); 2368 - if (dstval == DST_24BPP) { 2369 - srcx *= 3; 2370 - dstx *= 3; 2371 - width *= 3; 2372 - } else if (dstval == -EINVAL) { 2373 - printk("aty128fb: invalid depth or RGBA\n"); 2374 - return; 2375 - } 2376 - 2377 - wait_for_fifo(2, par); 2378 - save_dp_datatype = aty_ld_le32(DP_DATATYPE); 2379 - save_dp_cntl = aty_ld_le32(DP_CNTL); 2380 - 2381 - wait_for_fifo(6, par); 2382 - aty_st_le32(SRC_Y_X, (srcy << 16) | srcx); 2383 - aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT); 2384 - aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); 2385 - aty_st_le32(DP_DATATYPE, save_dp_datatype | dstval | SRC_DSTCOLOR); 2386 - 2387 - aty_st_le32(DST_Y_X, (dsty << 16) | dstx); 2388 - aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width); 2389 - 2390 - par->blitter_may_be_busy = 1; 2391 - 2392 - wait_for_fifo(2, par); 2393 - aty_st_le32(DP_DATATYPE, save_dp_datatype); 2394 - aty_st_le32(DP_CNTL, save_dp_cntl); 2395 - } 2396 - 2397 - 2398 - /* 2399 - * Text mode accelerated functions 2400 - */ 2401 - 2402 - static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, 2403 - int dx, int height, int width) 2404 - { 2405 - sx *= fontwidth(p); 2406 - sy *= fontheight(p); 2407 - dx *= fontwidth(p); 2408 - dy *= fontheight(p); 2409 - width *= fontwidth(p); 2410 - height *= fontheight(p); 2411 - 2412 - aty128_rectcopy(sx, sy, dx, dy, width, height, 2413 - (struct fb_info_aty128 *)p->fb_info); 2414 - } 2415 - #endif /* 0 */ 2416 - 2417 2353 static void aty128_set_suspend(struct aty128fb_par *par, int suspend) 2418 2354 { 2419 2355 u32 pmgt;
+1 -2
drivers/video/fbdev/aty/atyfb_base.c
··· 3916 3916 if (!reboot_info) 3917 3917 goto out; 3918 3918 3919 - if (!lock_fb_info(reboot_info)) 3920 - goto out; 3919 + lock_fb_info(reboot_info); 3921 3920 3922 3921 par = reboot_info->par; 3923 3922
+1 -5
drivers/video/fbdev/core/fbcmap.c
··· 285 285 goto out; 286 286 } 287 287 umap.start = cmap->start; 288 - if (!lock_fb_info(info)) { 289 - rc = -ENODEV; 290 - goto out; 291 - } 292 - 288 + lock_fb_info(info); 293 289 rc = fb_set_cmap(&umap, info); 294 290 unlock_fb_info(info); 295 291 out:
+134 -180
drivers/video/fbdev/core/fbcon.c
··· 76 76 #include <linux/init.h> 77 77 #include <linux/interrupt.h> 78 78 #include <linux/crc32.h> /* For counting font checksums */ 79 + #include <linux/uaccess.h> 79 80 #include <asm/fb.h> 80 81 #include <asm/irq.h> 81 82 ··· 88 87 # define DPRINTK(fmt, args...) 89 88 #endif 90 89 90 + /* 91 + * FIXME: Locking 92 + * 93 + * - fbcon state itself is protected by the console_lock, and the code does a 94 + * pretty good job at making sure that lock is held everywhere it's needed. 95 + * 96 + * - access to the registered_fb array is entirely unprotected. This should use 97 + * proper object lifetime handling, i.e. get/put_fb_info. This also means 98 + * switching from indices to proper pointers for fb_info everywhere. 99 + * 100 + * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it 101 + * means concurrent access to the same fbdev from both fbcon and userspace 102 + * will blow up. To fix this all fbcon calls from fbmem.c need to be moved out 103 + * of fb_lock/unlock protected sections, since otherwise we'll recurse and 104 + * deadlock eventually. Aside: Due to these deadlock issues the fbdev code in 105 + * fbmem.c cannot use locking asserts, and there's lots of callers which get 106 + * the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too. 107 + */ 108 + 91 109 enum { 92 110 FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ 93 111 FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ 94 112 FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ 95 113 }; 96 114 97 - static struct display fb_display[MAX_NR_CONSOLES]; 115 + static struct fbcon_display fb_display[MAX_NR_CONSOLES]; 98 116 99 117 static signed char con2fb_map[MAX_NR_CONSOLES]; 100 118 static signed char con2fb_map_boot[MAX_NR_CONSOLES]; ··· 132 112 static int first_fb_vc; 133 113 static int last_fb_vc = MAX_NR_CONSOLES - 1; 134 114 static int fbcon_is_default = 1; 135 - static int fbcon_has_exited; 136 115 static int primary_device = -1; 137 116 static int fbcon_has_console_bind; 138 117 ··· 204 185 static __inline__ void ywrap_down(struct vc_data *vc, int count); 205 186 static __inline__ void ypan_up(struct vc_data *vc, int count); 206 187 static __inline__ void ypan_down(struct vc_data *vc, int count); 207 - static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, 188 + static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, 208 189 int dy, int dx, int height, int width, u_int y_break); 209 190 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, 210 191 int unit); 211 - static void fbcon_redraw_move(struct vc_data *vc, struct display *p, 192 + static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, 212 193 int line, int count, int dy); 213 194 static void fbcon_modechanged(struct fb_info *info); 214 195 static void fbcon_set_all_vcs(struct fb_info *info); ··· 239 220 fb_info = registered_fb[con2fb_map[ops->currcon]]; 240 221 241 222 if (info == fb_info) { 242 - struct display *p = &fb_display[ops->currcon]; 223 + struct fbcon_display *p = &fb_display[ops->currcon]; 243 224 244 225 if (rotate < 4) 245 226 p->con_rotate = rotate; ··· 254 235 { 255 236 struct fbcon_ops *ops = info->fbcon_par; 256 237 struct vc_data *vc; 257 - struct display *p; 238 + struct fbcon_display *p; 258 239 int i; 259 240 260 241 if (!ops || ops->currcon < 0 || rotate > 3) ··· 919 900 * Low Level Operations 920 901 */ 921 902 /* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */ 922 - static int var_to_display(struct display *disp, 903 + static int var_to_display(struct fbcon_display *disp, 923 904 struct fb_var_screeninfo *var, 924 905 struct fb_info *info) 925 906 { ··· 944 925 } 945 926 946 927 static void display_to_var(struct fb_var_screeninfo *var, 947 - struct display *disp) 928 + struct fbcon_display *disp) 948 929 { 949 930 fb_videomode_to_var(var, disp->mode); 950 931 var->xres_virtual = disp->xres_virtual; ··· 965 946 static const char *fbcon_startup(void) 966 947 { 967 948 const char *display_desc = "frame buffer device"; 968 - struct display *p = &fb_display[fg_console]; 949 + struct fbcon_display *p = &fb_display[fg_console]; 969 950 struct vc_data *vc = vc_cons[fg_console].d; 970 951 const struct font_desc *font = NULL; 971 952 struct module *owner; ··· 1069 1050 info->var.bits_per_pixel); 1070 1051 1071 1052 fbcon_add_cursor_timer(info); 1072 - fbcon_has_exited = 0; 1073 1053 return display_desc; 1074 1054 } 1075 1055 1076 1056 static void fbcon_init(struct vc_data *vc, int init) 1077 1057 { 1078 - struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1058 + struct fb_info *info; 1079 1059 struct fbcon_ops *ops; 1080 1060 struct vc_data **default_mode = vc->vc_display_fg; 1081 1061 struct vc_data *svc = *default_mode; 1082 - struct display *t, *p = &fb_display[vc->vc_num]; 1062 + struct fbcon_display *t, *p = &fb_display[vc->vc_num]; 1083 1063 int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; 1084 1064 int cap, ret; 1085 1065 1086 - if (info_idx == -1 || info == NULL) 1066 + if (WARN_ON(info_idx == -1)) 1087 1067 return; 1088 1068 1069 + if (con2fb_map[vc->vc_num] == -1) 1070 + con2fb_map[vc->vc_num] = info_idx; 1071 + 1072 + info = registered_fb[con2fb_map[vc->vc_num]]; 1089 1073 cap = info->flags; 1090 1074 1091 1075 if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET) ··· 1225 1203 ops->p = &fb_display[fg_console]; 1226 1204 } 1227 1205 1228 - static void fbcon_free_font(struct display *p, bool freefont) 1206 + static void fbcon_free_font(struct fbcon_display *p, bool freefont) 1229 1207 { 1230 1208 if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) 1231 1209 kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); ··· 1237 1215 1238 1216 static void fbcon_deinit(struct vc_data *vc) 1239 1217 { 1240 - struct display *p = &fb_display[vc->vc_num]; 1218 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1241 1219 struct fb_info *info; 1242 1220 struct fbcon_ops *ops; 1243 1221 int idx; ··· 1310 1288 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1311 1289 struct fbcon_ops *ops = info->fbcon_par; 1312 1290 1313 - struct display *p = &fb_display[vc->vc_num]; 1291 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1314 1292 u_int y_break; 1315 1293 1316 1294 if (fbcon_is_inactive(vc, info)) ··· 1346 1324 int count, int ypos, int xpos) 1347 1325 { 1348 1326 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1349 - struct display *p = &fb_display[vc->vc_num]; 1327 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1350 1328 struct fbcon_ops *ops = info->fbcon_par; 1351 1329 1352 1330 if (!fbcon_is_inactive(vc, info)) ··· 1410 1388 static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, 1411 1389 int unit) 1412 1390 { 1413 - struct display *p, *t; 1391 + struct fbcon_display *p, *t; 1414 1392 struct vc_data **default_mode, *vc; 1415 1393 struct vc_data *svc; 1416 1394 struct fbcon_ops *ops = info->fbcon_par; ··· 1479 1457 { 1480 1458 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1481 1459 struct fbcon_ops *ops = info->fbcon_par; 1482 - struct display *p = &fb_display[vc->vc_num]; 1460 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1483 1461 1484 1462 p->yscroll += count; 1485 1463 if (p->yscroll >= p->vrows) /* Deal with wrap */ ··· 1498 1476 { 1499 1477 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1500 1478 struct fbcon_ops *ops = info->fbcon_par; 1501 - struct display *p = &fb_display[vc->vc_num]; 1479 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1502 1480 1503 1481 p->yscroll -= count; 1504 1482 if (p->yscroll < 0) /* Deal with wrap */ ··· 1516 1494 static __inline__ void ypan_up(struct vc_data *vc, int count) 1517 1495 { 1518 1496 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1519 - struct display *p = &fb_display[vc->vc_num]; 1497 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1520 1498 struct fbcon_ops *ops = info->fbcon_par; 1521 1499 1522 1500 p->yscroll += count; ··· 1541 1519 { 1542 1520 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1543 1521 struct fbcon_ops *ops = info->fbcon_par; 1544 - struct display *p = &fb_display[vc->vc_num]; 1522 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1545 1523 1546 1524 p->yscroll += count; 1547 1525 ··· 1564 1542 static __inline__ void ypan_down(struct vc_data *vc, int count) 1565 1543 { 1566 1544 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1567 - struct display *p = &fb_display[vc->vc_num]; 1545 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1568 1546 struct fbcon_ops *ops = info->fbcon_par; 1569 1547 1570 1548 p->yscroll -= count; ··· 1589 1567 { 1590 1568 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1591 1569 struct fbcon_ops *ops = info->fbcon_par; 1592 - struct display *p = &fb_display[vc->vc_num]; 1570 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1593 1571 1594 1572 p->yscroll -= count; 1595 1573 ··· 1609 1587 scrollback_current = 0; 1610 1588 } 1611 1589 1612 - static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, 1590 + static void fbcon_redraw_softback(struct vc_data *vc, struct fbcon_display *p, 1613 1591 long delta) 1614 1592 { 1615 1593 int count = vc->vc_rows; ··· 1702 1680 } 1703 1681 } 1704 1682 1705 - static void fbcon_redraw_move(struct vc_data *vc, struct display *p, 1683 + static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, 1706 1684 int line, int count, int dy) 1707 1685 { 1708 1686 unsigned short *s = (unsigned short *) ··· 1737 1715 } 1738 1716 1739 1717 static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, 1740 - struct display *p, int line, int count, int ycount) 1718 + struct fbcon_display *p, int line, int count, int ycount) 1741 1719 { 1742 1720 int offset = ycount * vc->vc_cols; 1743 1721 unsigned short *d = (unsigned short *) ··· 1786 1764 } 1787 1765 } 1788 1766 1789 - static void fbcon_redraw(struct vc_data *vc, struct display *p, 1767 + static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p, 1790 1768 int line, int count, int offset) 1791 1769 { 1792 1770 unsigned short *d = (unsigned short *) ··· 1870 1848 enum con_scroll dir, unsigned int count) 1871 1849 { 1872 1850 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 1873 - struct display *p = &fb_display[vc->vc_num]; 1851 + struct fbcon_display *p = &fb_display[vc->vc_num]; 1874 1852 int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; 1875 1853 1876 1854 if (fbcon_is_inactive(vc, info)) ··· 2074 2052 int height, int width) 2075 2053 { 2076 2054 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 2077 - struct display *p = &fb_display[vc->vc_num]; 2055 + struct fbcon_display *p = &fb_display[vc->vc_num]; 2078 2056 2079 2057 if (fbcon_is_inactive(vc, info)) 2080 2058 return; ··· 2093 2071 p->vrows - p->yscroll); 2094 2072 } 2095 2073 2096 - static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx, 2074 + static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int sx, 2097 2075 int dy, int dx, int height, int width, u_int y_break) 2098 2076 { 2099 2077 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; ··· 2135 2113 height, width); 2136 2114 } 2137 2115 2138 - static void updatescrollmode(struct display *p, 2116 + static void updatescrollmode(struct fbcon_display *p, 2139 2117 struct fb_info *info, 2140 2118 struct vc_data *vc) 2141 2119 { ··· 2187 2165 { 2188 2166 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 2189 2167 struct fbcon_ops *ops = info->fbcon_par; 2190 - struct display *p = &fb_display[vc->vc_num]; 2168 + struct fbcon_display *p = &fb_display[vc->vc_num]; 2191 2169 struct fb_var_screeninfo var = info->var; 2192 2170 int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; 2193 2171 ··· 2232 2210 { 2233 2211 struct fb_info *info, *old_info = NULL; 2234 2212 struct fbcon_ops *ops; 2235 - struct display *p = &fb_display[vc->vc_num]; 2213 + struct fbcon_display *p = &fb_display[vc->vc_num]; 2236 2214 struct fb_var_screeninfo var; 2237 2215 int i, ret, prev_console, charcnt = 256; 2238 2216 ··· 2370 2348 static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, 2371 2349 int blank) 2372 2350 { 2373 - struct fb_event event; 2374 - 2375 2351 if (blank) { 2376 2352 unsigned short charmask = vc->vc_hi_font_mask ? 2377 2353 0x1ff : 0xff; ··· 2380 2360 fbcon_clear(vc, 0, 0, vc->vc_rows, vc->vc_cols); 2381 2361 vc->vc_video_erase_char = oldc; 2382 2362 } 2383 - 2384 - 2385 - if (!lock_fb_info(info)) 2386 - return; 2387 - event.info = info; 2388 - event.data = &blank; 2389 - fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); 2390 - unlock_fb_info(info); 2391 2363 } 2392 2364 2393 2365 static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) ··· 2406 2394 fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); 2407 2395 ops->cursor_flash = (!blank); 2408 2396 2409 - if (!(info->flags & FBINFO_MISC_USEREVENT)) 2410 - if (fb_blank(info, blank)) 2411 - fbcon_generic_blank(vc, info, blank); 2397 + if (fb_blank(info, blank)) 2398 + fbcon_generic_blank(vc, info, blank); 2412 2399 } 2413 2400 2414 2401 if (!blank) ··· 2564 2553 { 2565 2554 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; 2566 2555 struct fbcon_ops *ops = info->fbcon_par; 2567 - struct display *p = &fb_display[vc->vc_num]; 2556 + struct fbcon_display *p = &fb_display[vc->vc_num]; 2568 2557 int resize; 2569 2558 int cnt; 2570 2559 char *old_data = NULL; ··· 2612 2601 2613 2602 static int fbcon_copy_font(struct vc_data *vc, int con) 2614 2603 { 2615 - struct display *od = &fb_display[con]; 2604 + struct fbcon_display *od = &fb_display[con]; 2616 2605 struct console_font *f = &vc->vc_font; 2617 2606 2618 2607 if (od->fontdata == f->data) ··· 2837 2826 { 2838 2827 struct fb_info *info = registered_fb[con2fb_map[fg_console]]; 2839 2828 struct fbcon_ops *ops = info->fbcon_par; 2840 - struct display *disp = &fb_display[fg_console]; 2829 + struct fbcon_display *disp = &fb_display[fg_console]; 2841 2830 int offset, limit, scrollback_old; 2842 2831 2843 2832 if (softback_top) { ··· 2929 2918 return 0; 2930 2919 } 2931 2920 2932 - static void fbcon_suspended(struct fb_info *info) 2921 + void fbcon_suspended(struct fb_info *info) 2933 2922 { 2934 2923 struct vc_data *vc = NULL; 2935 2924 struct fbcon_ops *ops = info->fbcon_par; ··· 2942 2931 fbcon_cursor(vc, CM_ERASE); 2943 2932 } 2944 2933 2945 - static void fbcon_resumed(struct fb_info *info) 2934 + void fbcon_resumed(struct fb_info *info) 2946 2935 { 2947 2936 struct vc_data *vc; 2948 2937 struct fbcon_ops *ops = info->fbcon_par; ··· 2958 2947 { 2959 2948 struct fbcon_ops *ops = info->fbcon_par; 2960 2949 struct vc_data *vc; 2961 - struct display *p; 2950 + struct fbcon_display *p; 2962 2951 int rows, cols; 2963 2952 2964 2953 if (!ops || ops->currcon < 0) ··· 2998 2987 { 2999 2988 struct fbcon_ops *ops = info->fbcon_par; 3000 2989 struct vc_data *vc; 3001 - struct display *p; 2990 + struct fbcon_display *p; 3002 2991 int i, rows, cols, fg = -1; 3003 2992 3004 2993 if (!ops || ops->currcon < 0) ··· 3029 3018 fbcon_modechanged(info); 3030 3019 } 3031 3020 3032 - static int fbcon_mode_deleted(struct fb_info *info, 3033 - struct fb_videomode *mode) 3021 + 3022 + void fbcon_update_vcs(struct fb_info *info, bool all) 3023 + { 3024 + if (all) 3025 + fbcon_set_all_vcs(info); 3026 + else 3027 + fbcon_modechanged(info); 3028 + } 3029 + EXPORT_SYMBOL(fbcon_update_vcs); 3030 + 3031 + int fbcon_mode_deleted(struct fb_info *info, 3032 + struct fb_videomode *mode) 3034 3033 { 3035 3034 struct fb_info *fb_info; 3036 - struct display *p; 3035 + struct fbcon_display *p; 3037 3036 int i, j, found = 0; 3038 3037 3039 3038 /* before deletion, ensure that mode is not in use */ ··· 3066 3045 } 3067 3046 3068 3047 #ifdef CONFIG_VT_HW_CONSOLE_BINDING 3069 - static int fbcon_unbind(void) 3048 + static void fbcon_unbind(void) 3070 3049 { 3071 3050 int ret; 3072 3051 ··· 3075 3054 3076 3055 if (!ret) 3077 3056 fbcon_has_console_bind = 0; 3078 - 3079 - return ret; 3080 3057 } 3081 3058 #else 3082 - static inline int fbcon_unbind(void) 3083 - { 3084 - return -EINVAL; 3085 - } 3059 + static inline void fbcon_unbind(void) {} 3086 3060 #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ 3087 3061 3088 3062 /* called with console_lock held */ 3089 - static int fbcon_fb_unbind(int idx) 3063 + void fbcon_fb_unbind(struct fb_info *info) 3090 3064 { 3091 3065 int i, new_idx = -1, ret = 0; 3066 + int idx = info->node; 3092 3067 3093 3068 WARN_CONSOLE_UNLOCKED(); 3094 3069 3095 3070 if (!fbcon_has_console_bind) 3096 - return 0; 3071 + return; 3097 3072 3098 3073 for (i = first_fb_vc; i <= last_fb_vc; i++) { 3099 3074 if (con2fb_map[i] != idx && ··· 3122 3105 idx, 0); 3123 3106 if (ret) { 3124 3107 con2fb_map[i] = idx; 3125 - return ret; 3108 + return; 3126 3109 } 3127 3110 } 3128 3111 } 3129 3112 } 3130 - ret = fbcon_unbind(); 3113 + fbcon_unbind(); 3131 3114 } 3132 - 3133 - return ret; 3134 3115 } 3135 3116 3136 3117 /* called with console_lock held */ 3137 - static int fbcon_fb_unregistered(struct fb_info *info) 3118 + void fbcon_fb_unregistered(struct fb_info *info) 3138 3119 { 3139 3120 int i, idx; 3140 3121 3141 3122 WARN_CONSOLE_UNLOCKED(); 3142 3123 3143 3124 if (deferred_takeover) 3144 - return 0; 3125 + return; 3145 3126 3146 3127 idx = info->node; 3147 3128 for (i = first_fb_vc; i <= last_fb_vc; i++) { ··· 3168 3153 3169 3154 if (!num_registered_fb) 3170 3155 do_unregister_con_driver(&fb_con); 3171 - 3172 - return 0; 3173 3156 } 3174 3157 3175 - /* called with console_lock held */ 3176 - static void fbcon_remap_all(int idx) 3158 + void fbcon_remap_all(struct fb_info *info) 3177 3159 { 3178 - int i; 3160 + int i, idx = info->node; 3179 3161 3180 - WARN_CONSOLE_UNLOCKED(); 3181 - 3162 + console_lock(); 3182 3163 if (deferred_takeover) { 3183 3164 for (i = first_fb_vc; i <= last_fb_vc; i++) 3184 3165 con2fb_map_boot[i] = idx; 3185 3166 fbcon_map_override(); 3167 + console_unlock(); 3186 3168 return; 3187 3169 } 3188 3170 ··· 3192 3180 first_fb_vc + 1, last_fb_vc + 1); 3193 3181 info_idx = idx; 3194 3182 } 3183 + console_unlock(); 3195 3184 } 3196 3185 3197 3186 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY ··· 3226 3213 #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ 3227 3214 3228 3215 /* called with console_lock held */ 3229 - static int fbcon_fb_registered(struct fb_info *info) 3216 + int fbcon_fb_registered(struct fb_info *info) 3230 3217 { 3231 3218 int ret = 0, i, idx; 3232 3219 ··· 3260 3247 return ret; 3261 3248 } 3262 3249 3263 - static void fbcon_fb_blanked(struct fb_info *info, int blank) 3250 + void fbcon_fb_blanked(struct fb_info *info, int blank) 3264 3251 { 3265 3252 struct fbcon_ops *ops = info->fbcon_par; 3266 3253 struct vc_data *vc; ··· 3282 3269 ops->blank_state = blank; 3283 3270 } 3284 3271 3285 - static void fbcon_new_modelist(struct fb_info *info) 3272 + void fbcon_new_modelist(struct fb_info *info) 3286 3273 { 3287 3274 int i; 3288 3275 struct vc_data *vc; ··· 3303 3290 } 3304 3291 } 3305 3292 3306 - static void fbcon_get_requirement(struct fb_info *info, 3307 - struct fb_blit_caps *caps) 3293 + void fbcon_get_requirement(struct fb_info *info, 3294 + struct fb_blit_caps *caps) 3308 3295 { 3309 3296 struct vc_data *vc; 3310 - struct display *p; 3297 + struct fbcon_display *p; 3311 3298 3312 3299 if (caps->flags) { 3313 3300 int i, charcnt; ··· 3339 3326 } 3340 3327 } 3341 3328 3342 - static int fbcon_event_notify(struct notifier_block *self, 3343 - unsigned long action, void *data) 3329 + int fbcon_set_con2fb_map_ioctl(void __user *argp) 3344 3330 { 3345 - struct fb_event *event = data; 3346 - struct fb_info *info = event->info; 3347 - struct fb_videomode *mode; 3348 - struct fb_con2fbmap *con2fb; 3349 - struct fb_blit_caps *caps; 3350 - int idx, ret = 0; 3331 + struct fb_con2fbmap con2fb; 3332 + int ret; 3351 3333 3352 - /* 3353 - * ignore all events except driver registration and deregistration 3354 - * if fbcon is not active 3355 - */ 3356 - if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED || 3357 - action == FB_EVENT_FB_UNREGISTERED)) 3358 - goto done; 3359 - 3360 - switch(action) { 3361 - case FB_EVENT_SUSPEND: 3362 - fbcon_suspended(info); 3363 - break; 3364 - case FB_EVENT_RESUME: 3365 - fbcon_resumed(info); 3366 - break; 3367 - case FB_EVENT_MODE_CHANGE: 3368 - fbcon_modechanged(info); 3369 - break; 3370 - case FB_EVENT_MODE_CHANGE_ALL: 3371 - fbcon_set_all_vcs(info); 3372 - break; 3373 - case FB_EVENT_MODE_DELETE: 3374 - mode = event->data; 3375 - ret = fbcon_mode_deleted(info, mode); 3376 - break; 3377 - case FB_EVENT_FB_UNBIND: 3378 - idx = info->node; 3379 - ret = fbcon_fb_unbind(idx); 3380 - break; 3381 - case FB_EVENT_FB_REGISTERED: 3382 - ret = fbcon_fb_registered(info); 3383 - break; 3384 - case FB_EVENT_FB_UNREGISTERED: 3385 - ret = fbcon_fb_unregistered(info); 3386 - break; 3387 - case FB_EVENT_SET_CONSOLE_MAP: 3388 - /* called with console lock held */ 3389 - con2fb = event->data; 3390 - ret = set_con2fb_map(con2fb->console - 1, 3391 - con2fb->framebuffer, 1); 3392 - break; 3393 - case FB_EVENT_GET_CONSOLE_MAP: 3394 - con2fb = event->data; 3395 - con2fb->framebuffer = con2fb_map[con2fb->console - 1]; 3396 - break; 3397 - case FB_EVENT_BLANK: 3398 - fbcon_fb_blanked(info, *(int *)event->data); 3399 - break; 3400 - case FB_EVENT_NEW_MODELIST: 3401 - fbcon_new_modelist(info); 3402 - break; 3403 - case FB_EVENT_GET_REQ: 3404 - caps = event->data; 3405 - fbcon_get_requirement(info, caps); 3406 - break; 3407 - case FB_EVENT_REMAP_ALL_CONSOLE: 3408 - idx = info->node; 3409 - fbcon_remap_all(idx); 3410 - break; 3334 + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 3335 + return -EFAULT; 3336 + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 3337 + return -EINVAL; 3338 + if (con2fb.framebuffer >= FB_MAX) 3339 + return -EINVAL; 3340 + if (!registered_fb[con2fb.framebuffer]) 3341 + request_module("fb%d", con2fb.framebuffer); 3342 + if (!registered_fb[con2fb.framebuffer]) { 3343 + return -EINVAL; 3411 3344 } 3412 - done: 3345 + 3346 + console_lock(); 3347 + ret = set_con2fb_map(con2fb.console - 1, 3348 + con2fb.framebuffer, 1); 3349 + console_unlock(); 3350 + 3413 3351 return ret; 3352 + } 3353 + 3354 + int fbcon_get_con2fb_map_ioctl(void __user *argp) 3355 + { 3356 + struct fb_con2fbmap con2fb; 3357 + 3358 + if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 3359 + return -EFAULT; 3360 + if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 3361 + return -EINVAL; 3362 + 3363 + console_lock(); 3364 + con2fb.framebuffer = con2fb_map[con2fb.console - 1]; 3365 + console_unlock(); 3366 + 3367 + return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; 3414 3368 } 3415 3369 3416 3370 /* ··· 3411 3431 .con_debug_leave = fbcon_debug_leave, 3412 3432 }; 3413 3433 3414 - static struct notifier_block fbcon_event_notifier = { 3415 - .notifier_call = fbcon_event_notify, 3416 - }; 3417 - 3418 3434 static ssize_t store_rotate(struct device *device, 3419 3435 struct device_attribute *attr, const char *buf, 3420 3436 size_t count) ··· 3418 3442 struct fb_info *info; 3419 3443 int rotate, idx; 3420 3444 char **last = NULL; 3421 - 3422 - if (fbcon_has_exited) 3423 - return count; 3424 3445 3425 3446 console_lock(); 3426 3447 idx = con2fb_map[fg_console]; ··· 3441 3468 int rotate, idx; 3442 3469 char **last = NULL; 3443 3470 3444 - if (fbcon_has_exited) 3445 - return count; 3446 - 3447 3471 console_lock(); 3448 3472 idx = con2fb_map[fg_console]; 3449 3473 ··· 3461 3491 struct fb_info *info; 3462 3492 int rotate = 0, idx; 3463 3493 3464 - if (fbcon_has_exited) 3465 - return 0; 3466 - 3467 3494 console_lock(); 3468 3495 idx = con2fb_map[fg_console]; 3469 3496 ··· 3480 3513 struct fb_info *info; 3481 3514 struct fbcon_ops *ops; 3482 3515 int idx, blink = -1; 3483 - 3484 - if (fbcon_has_exited) 3485 - return 0; 3486 3516 3487 3517 console_lock(); 3488 3518 idx = con2fb_map[fg_console]; ··· 3506 3542 struct fb_info *info; 3507 3543 int blink, idx; 3508 3544 char **last = NULL; 3509 - 3510 - if (fbcon_has_exited) 3511 - return count; 3512 3545 3513 3546 console_lock(); 3514 3547 idx = con2fb_map[fg_console]; ··· 3629 3668 struct fb_info *info; 3630 3669 int i, j, mapped; 3631 3670 3632 - if (fbcon_has_exited) 3633 - return; 3634 - 3635 3671 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER 3636 3672 if (deferred_takeover) { 3637 3673 dummycon_unregister_output_notifier(&fbcon_output_nb); ··· 3653 3695 for (j = first_fb_vc; j <= last_fb_vc; j++) { 3654 3696 if (con2fb_map[j] == i) { 3655 3697 mapped = 1; 3656 - break; 3698 + con2fb_map[j] = -1; 3657 3699 } 3658 3700 } 3659 3701 ··· 3676 3718 info->queue.func = NULL; 3677 3719 } 3678 3720 } 3679 - 3680 - fbcon_has_exited = 1; 3681 3721 } 3682 3722 3683 3723 void __init fb_console_init(void) ··· 3683 3727 int i; 3684 3728 3685 3729 console_lock(); 3686 - fb_register_client(&fbcon_event_notifier); 3687 3730 fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, 3688 3731 "fbcon"); 3689 3732 ··· 3718 3763 void __exit fb_console_exit(void) 3719 3764 { 3720 3765 console_lock(); 3721 - fb_unregister_client(&fbcon_event_notifier); 3722 3766 fbcon_deinit_device(); 3723 3767 device_destroy(fb_class, MKDEV(0, 0)); 3724 3768 fbcon_exit();
+3 -3
drivers/video/fbdev/core/fbcon.h
··· 25 25 * low-level frame buffer device 26 26 */ 27 27 28 - struct display { 28 + struct fbcon_display { 29 29 /* Filled in by the low-level console driver */ 30 30 const u_char *fontdata; 31 31 int userfont; /* != 0 if fontdata kmalloc()ed */ ··· 68 68 struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ 69 69 struct timer_list cursor_timer; /* Cursor timer */ 70 70 struct fb_cursor cursor_state; 71 - struct display *p; 71 + struct fbcon_display *p; 72 72 struct fb_info *info; 73 73 int currcon; /* Current VC. */ 74 74 int cur_blink_jiffies; ··· 225 225 #define FBCON_ATTRIBUTE_REVERSE 2 226 226 #define FBCON_ATTRIBUTE_BOLD 4 227 227 228 - static inline int real_y(struct display *p, int ypos) 228 + static inline int real_y(struct fbcon_display *p, int ypos) 229 229 { 230 230 int rows = p->vrows; 231 231
+149 -258
drivers/video/fbdev/core/fbmem.c
··· 80 80 fb_info->fbops->fb_destroy(fb_info); 81 81 } 82 82 83 - int lock_fb_info(struct fb_info *info) 84 - { 85 - mutex_lock(&info->lock); 86 - if (!info->fbops) { 87 - mutex_unlock(&info->lock); 88 - return 0; 89 - } 90 - return 1; 91 - } 92 - EXPORT_SYMBOL(lock_fb_info); 93 - 94 83 /* 95 84 * Helpers 96 85 */ ··· 932 943 static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, 933 944 u32 activate) 934 945 { 935 - struct fb_event event; 936 946 struct fb_blit_caps caps, fbcaps; 937 947 int err = 0; 938 948 939 949 memset(&caps, 0, sizeof(caps)); 940 950 memset(&fbcaps, 0, sizeof(fbcaps)); 941 951 caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0; 942 - event.info = info; 943 - event.data = &caps; 944 - fb_notifier_call_chain(FB_EVENT_GET_REQ, &event); 952 + fbcon_get_requirement(info, &caps); 945 953 info->fbops->fb_get_caps(info, &fbcaps, var); 946 954 947 955 if (((fbcaps.x ^ caps.x) & caps.x) || ··· 954 968 { 955 969 int flags = info->flags; 956 970 int ret = 0; 971 + u32 activate; 972 + struct fb_var_screeninfo old_var; 973 + struct fb_videomode mode; 974 + struct fb_event event; 957 975 958 976 if (var->activate & FB_ACTIVATE_INV_MODE) { 959 977 struct fb_videomode mode1, mode2; ··· 967 977 /* make sure we don't delete the videomode of current var */ 968 978 ret = fb_mode_is_equal(&mode1, &mode2); 969 979 970 - if (!ret) { 971 - struct fb_event event; 972 - 973 - event.info = info; 974 - event.data = &mode1; 975 - ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); 976 - } 980 + if (!ret) 981 + fbcon_mode_deleted(info, &mode1); 977 982 978 983 if (!ret) 979 - fb_delete_videomode(&mode1, &info->modelist); 984 + fb_delete_videomode(&mode1, &info->modelist); 980 985 981 986 982 - ret = (ret) ? -EINVAL : 0; 983 - goto done; 987 + return ret ? -EINVAL : 0; 984 988 } 985 989 986 - if ((var->activate & FB_ACTIVATE_FORCE) || 987 - memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { 988 - u32 activate = var->activate; 990 + if (!(var->activate & FB_ACTIVATE_FORCE) && 991 + !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) 992 + return 0; 989 993 990 - /* When using FOURCC mode, make sure the red, green, blue and 991 - * transp fields are set to 0. 992 - */ 993 - if ((info->fix.capabilities & FB_CAP_FOURCC) && 994 - var->grayscale > 1) { 995 - if (var->red.offset || var->green.offset || 996 - var->blue.offset || var->transp.offset || 997 - var->red.length || var->green.length || 998 - var->blue.length || var->transp.length || 999 - var->red.msb_right || var->green.msb_right || 1000 - var->blue.msb_right || var->transp.msb_right) 1001 - return -EINVAL; 1002 - } 994 + activate = var->activate; 1003 995 1004 - if (!info->fbops->fb_check_var) { 1005 - *var = info->var; 1006 - goto done; 1007 - } 996 + /* When using FOURCC mode, make sure the red, green, blue and 997 + * transp fields are set to 0. 998 + */ 999 + if ((info->fix.capabilities & FB_CAP_FOURCC) && 1000 + var->grayscale > 1) { 1001 + if (var->red.offset || var->green.offset || 1002 + var->blue.offset || var->transp.offset || 1003 + var->red.length || var->green.length || 1004 + var->blue.length || var->transp.length || 1005 + var->red.msb_right || var->green.msb_right || 1006 + var->blue.msb_right || var->transp.msb_right) 1007 + return -EINVAL; 1008 + } 1008 1009 1009 - ret = info->fbops->fb_check_var(var, info); 1010 + if (!info->fbops->fb_check_var) { 1011 + *var = info->var; 1012 + return 0; 1013 + } 1014 + 1015 + ret = info->fbops->fb_check_var(var, info); 1016 + 1017 + if (ret) 1018 + return ret; 1019 + 1020 + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) 1021 + return 0; 1022 + 1023 + if (info->fbops->fb_get_caps) { 1024 + ret = fb_check_caps(info, var, activate); 1010 1025 1011 1026 if (ret) 1012 - goto done; 1027 + return ret; 1028 + } 1013 1029 1014 - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 1015 - struct fb_var_screeninfo old_var; 1016 - struct fb_videomode mode; 1030 + old_var = info->var; 1031 + info->var = *var; 1017 1032 1018 - if (info->fbops->fb_get_caps) { 1019 - ret = fb_check_caps(info, var, activate); 1033 + if (info->fbops->fb_set_par) { 1034 + ret = info->fbops->fb_set_par(info); 1020 1035 1021 - if (ret) 1022 - goto done; 1023 - } 1024 - 1025 - old_var = info->var; 1026 - info->var = *var; 1027 - 1028 - if (info->fbops->fb_set_par) { 1029 - ret = info->fbops->fb_set_par(info); 1030 - 1031 - if (ret) { 1032 - info->var = old_var; 1033 - printk(KERN_WARNING "detected " 1034 - "fb_set_par error, " 1035 - "error code: %d\n", ret); 1036 - goto done; 1037 - } 1038 - } 1039 - 1040 - fb_pan_display(info, &info->var); 1041 - fb_set_cmap(&info->cmap, info); 1042 - fb_var_to_videomode(&mode, &info->var); 1043 - 1044 - if (info->modelist.prev && info->modelist.next && 1045 - !list_empty(&info->modelist)) 1046 - ret = fb_add_videomode(&mode, &info->modelist); 1047 - 1048 - if (!ret && (flags & FBINFO_MISC_USEREVENT)) { 1049 - struct fb_event event; 1050 - int evnt = (activate & FB_ACTIVATE_ALL) ? 1051 - FB_EVENT_MODE_CHANGE_ALL : 1052 - FB_EVENT_MODE_CHANGE; 1053 - 1054 - info->flags &= ~FBINFO_MISC_USEREVENT; 1055 - event.info = info; 1056 - event.data = &mode; 1057 - fb_notifier_call_chain(evnt, &event); 1058 - } 1036 + if (ret) { 1037 + info->var = old_var; 1038 + printk(KERN_WARNING "detected " 1039 + "fb_set_par error, " 1040 + "error code: %d\n", ret); 1041 + return ret; 1059 1042 } 1060 1043 } 1061 1044 1062 - done: 1063 - return ret; 1045 + fb_pan_display(info, &info->var); 1046 + fb_set_cmap(&info->cmap, info); 1047 + fb_var_to_videomode(&mode, &info->var); 1048 + 1049 + if (info->modelist.prev && info->modelist.next && 1050 + !list_empty(&info->modelist)) 1051 + ret = fb_add_videomode(&mode, &info->modelist); 1052 + 1053 + if (ret) 1054 + return ret; 1055 + 1056 + event.info = info; 1057 + event.data = &mode; 1058 + fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); 1059 + 1060 + if (flags & FBINFO_MISC_USEREVENT) 1061 + fbcon_update_vcs(info, activate & FB_ACTIVATE_ALL); 1062 + 1063 + return 0; 1064 1064 } 1065 1065 EXPORT_SYMBOL(fb_set_var); 1066 1066 ··· 1092 1112 struct fb_ops *fb; 1093 1113 struct fb_var_screeninfo var; 1094 1114 struct fb_fix_screeninfo fix; 1095 - struct fb_con2fbmap con2fb; 1096 1115 struct fb_cmap cmap_from; 1097 1116 struct fb_cmap_user cmap; 1098 - struct fb_event event; 1099 1117 void __user *argp = (void __user *)arg; 1100 1118 long ret = 0; 1101 1119 1102 1120 switch (cmd) { 1103 1121 case FBIOGET_VSCREENINFO: 1104 - if (!lock_fb_info(info)) 1105 - return -ENODEV; 1122 + lock_fb_info(info); 1106 1123 var = info->var; 1107 1124 unlock_fb_info(info); 1108 1125 ··· 1109 1132 if (copy_from_user(&var, argp, sizeof(var))) 1110 1133 return -EFAULT; 1111 1134 console_lock(); 1112 - if (!lock_fb_info(info)) { 1113 - console_unlock(); 1114 - return -ENODEV; 1115 - } 1135 + lock_fb_info(info); 1116 1136 info->flags |= FBINFO_MISC_USEREVENT; 1117 1137 ret = fb_set_var(info, &var); 1118 1138 info->flags &= ~FBINFO_MISC_USEREVENT; ··· 1119 1145 ret = -EFAULT; 1120 1146 break; 1121 1147 case FBIOGET_FSCREENINFO: 1122 - if (!lock_fb_info(info)) 1123 - return -ENODEV; 1148 + lock_fb_info(info); 1124 1149 fix = info->fix; 1125 1150 if (info->flags & FBINFO_HIDE_SMEM_START) 1126 1151 fix.smem_start = 0; ··· 1135 1162 case FBIOGETCMAP: 1136 1163 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1137 1164 return -EFAULT; 1138 - if (!lock_fb_info(info)) 1139 - return -ENODEV; 1165 + lock_fb_info(info); 1140 1166 cmap_from = info->cmap; 1141 1167 unlock_fb_info(info); 1142 1168 ret = fb_cmap_to_user(&cmap_from, &cmap); ··· 1144 1172 if (copy_from_user(&var, argp, sizeof(var))) 1145 1173 return -EFAULT; 1146 1174 console_lock(); 1147 - if (!lock_fb_info(info)) { 1148 - console_unlock(); 1149 - return -ENODEV; 1150 - } 1175 + lock_fb_info(info); 1151 1176 ret = fb_pan_display(info, &var); 1152 1177 unlock_fb_info(info); 1153 1178 console_unlock(); ··· 1155 1186 ret = -EINVAL; 1156 1187 break; 1157 1188 case FBIOGET_CON2FBMAP: 1158 - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1159 - return -EFAULT; 1160 - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1161 - return -EINVAL; 1162 - con2fb.framebuffer = -1; 1163 - event.data = &con2fb; 1164 - if (!lock_fb_info(info)) 1165 - return -ENODEV; 1166 - event.info = info; 1167 - fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); 1168 - unlock_fb_info(info); 1169 - ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; 1189 + ret = fbcon_get_con2fb_map_ioctl(argp); 1170 1190 break; 1171 1191 case FBIOPUT_CON2FBMAP: 1172 - if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1173 - return -EFAULT; 1174 - if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1175 - return -EINVAL; 1176 - if (con2fb.framebuffer >= FB_MAX) 1177 - return -EINVAL; 1178 - if (!registered_fb[con2fb.framebuffer]) 1179 - request_module("fb%d", con2fb.framebuffer); 1180 - if (!registered_fb[con2fb.framebuffer]) { 1181 - ret = -EINVAL; 1182 - break; 1183 - } 1184 - event.data = &con2fb; 1185 - console_lock(); 1186 - if (!lock_fb_info(info)) { 1187 - console_unlock(); 1188 - return -ENODEV; 1189 - } 1190 - event.info = info; 1191 - ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); 1192 - unlock_fb_info(info); 1193 - console_unlock(); 1192 + ret = fbcon_set_con2fb_map_ioctl(argp); 1194 1193 break; 1195 1194 case FBIOBLANK: 1196 1195 console_lock(); 1197 - if (!lock_fb_info(info)) { 1198 - console_unlock(); 1199 - return -ENODEV; 1200 - } 1201 - info->flags |= FBINFO_MISC_USEREVENT; 1196 + lock_fb_info(info); 1202 1197 ret = fb_blank(info, arg); 1203 - info->flags &= ~FBINFO_MISC_USEREVENT; 1198 + /* might again call into fb_blank */ 1199 + fbcon_fb_blanked(info, arg); 1204 1200 unlock_fb_info(info); 1205 1201 console_unlock(); 1206 1202 break; 1207 1203 default: 1208 - if (!lock_fb_info(info)) 1209 - return -ENODEV; 1204 + lock_fb_info(info); 1210 1205 fb = info->fbops; 1211 1206 if (fb->fb_ioctl) 1212 1207 ret = fb->fb_ioctl(info, cmd, arg); ··· 1290 1357 { 1291 1358 struct fb_fix_screeninfo fix; 1292 1359 1293 - if (!lock_fb_info(info)) 1294 - return -ENODEV; 1360 + lock_fb_info(info); 1295 1361 fix = info->fix; 1296 1362 if (info->flags & FBINFO_HIDE_SMEM_START) 1297 1363 fix.smem_start = 0; ··· 1350 1418 if (!info) 1351 1419 return -ENODEV; 1352 1420 fb = info->fbops; 1353 - if (!fb) 1354 - return -ENODEV; 1355 1421 mutex_lock(&info->mm_lock); 1356 1422 if (fb->fb_mmap) { 1357 1423 int res; ··· 1413 1483 if (IS_ERR(info)) 1414 1484 return PTR_ERR(info); 1415 1485 1416 - mutex_lock(&info->lock); 1486 + lock_fb_info(info); 1417 1487 if (!try_module_get(info->fbops->owner)) { 1418 1488 res = -ENODEV; 1419 1489 goto out; ··· 1429 1499 fb_deferred_io_open(info, inode, file); 1430 1500 #endif 1431 1501 out: 1432 - mutex_unlock(&info->lock); 1502 + unlock_fb_info(info); 1433 1503 if (res) 1434 1504 put_fb_info(info); 1435 1505 return res; ··· 1442 1512 { 1443 1513 struct fb_info * const info = file->private_data; 1444 1514 1445 - mutex_lock(&info->lock); 1515 + lock_fb_info(info); 1446 1516 if (info->fbops->fb_release) 1447 1517 info->fbops->fb_release(info,1); 1448 1518 module_put(info->fbops->owner); 1449 - mutex_unlock(&info->lock); 1519 + unlock_fb_info(info); 1450 1520 put_fb_info(info); 1451 1521 return 0; 1452 1522 } ··· 1551 1621 return false; 1552 1622 } 1553 1623 1554 - static int do_unregister_framebuffer(struct fb_info *fb_info); 1624 + static void do_unregister_framebuffer(struct fb_info *fb_info); 1555 1625 1556 1626 #define VGA_FB_PHYS 0xA0000 1557 - static int do_remove_conflicting_framebuffers(struct apertures_struct *a, 1558 - const char *name, bool primary) 1627 + static void do_remove_conflicting_framebuffers(struct apertures_struct *a, 1628 + const char *name, bool primary) 1559 1629 { 1560 - int i, ret; 1630 + int i; 1561 1631 1562 1632 /* check all firmware fbs and kick off if the base addr overlaps */ 1563 1633 for_each_registered_fb(i) { ··· 1573 1643 1574 1644 printk(KERN_INFO "fb%d: switching to %s from %s\n", 1575 1645 i, name, registered_fb[i]->fix.id); 1576 - ret = do_unregister_framebuffer(registered_fb[i]); 1577 - if (ret) 1578 - return ret; 1646 + do_unregister_framebuffer(registered_fb[i]); 1579 1647 } 1580 1648 } 1581 - 1582 - return 0; 1583 1649 } 1584 1650 1585 1651 static bool lockless_register_fb; ··· 1586 1660 static int do_register_framebuffer(struct fb_info *fb_info) 1587 1661 { 1588 1662 int i, ret; 1589 - struct fb_event event; 1590 1663 struct fb_videomode mode; 1591 1664 1592 1665 if (fb_check_foreignness(fb_info)) 1593 1666 return -ENOSYS; 1594 1667 1595 - ret = do_remove_conflicting_framebuffers(fb_info->apertures, 1596 - fb_info->fix.id, 1597 - fb_is_primary_device(fb_info)); 1598 - if (ret) 1599 - return ret; 1668 + do_remove_conflicting_framebuffers(fb_info->apertures, 1669 + fb_info->fix.id, 1670 + fb_is_primary_device(fb_info)); 1600 1671 1601 1672 if (num_registered_fb == FB_MAX) 1602 1673 return -ENXIO; ··· 1646 1723 fb_add_videomode(&mode, &fb_info->modelist); 1647 1724 registered_fb[i] = fb_info; 1648 1725 1649 - event.info = fb_info; 1726 + #ifdef CONFIG_GUMSTIX_AM200EPD 1727 + { 1728 + struct fb_event event; 1729 + event.info = fb_info; 1730 + fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); 1731 + } 1732 + #endif 1733 + 1650 1734 if (!lockless_register_fb) 1651 1735 console_lock(); 1652 1736 else 1653 1737 atomic_inc(&ignore_console_lock_warning); 1654 - if (!lock_fb_info(fb_info)) { 1655 - ret = -ENODEV; 1656 - goto unlock_console; 1657 - } 1658 - ret = 0; 1659 - 1660 - fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); 1738 + lock_fb_info(fb_info); 1739 + ret = fbcon_fb_registered(fb_info); 1661 1740 unlock_fb_info(fb_info); 1662 - unlock_console: 1741 + 1663 1742 if (!lockless_register_fb) 1664 1743 console_unlock(); 1665 1744 else ··· 1669 1744 return ret; 1670 1745 } 1671 1746 1672 - static int unbind_console(struct fb_info *fb_info) 1747 + static void unbind_console(struct fb_info *fb_info) 1673 1748 { 1674 - struct fb_event event; 1675 - int ret; 1676 1749 int i = fb_info->node; 1677 1750 1678 - if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) 1679 - return -EINVAL; 1751 + if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) 1752 + return; 1680 1753 1681 1754 console_lock(); 1682 - if (!lock_fb_info(fb_info)) { 1683 - console_unlock(); 1684 - return -ENODEV; 1685 - } 1686 - 1687 - event.info = fb_info; 1688 - ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); 1755 + lock_fb_info(fb_info); 1756 + fbcon_fb_unbind(fb_info); 1689 1757 unlock_fb_info(fb_info); 1690 1758 console_unlock(); 1691 - 1692 - return ret; 1693 1759 } 1694 1760 1695 - static int __unlink_framebuffer(struct fb_info *fb_info); 1696 - 1697 - static int do_unregister_framebuffer(struct fb_info *fb_info) 1761 + void unlink_framebuffer(struct fb_info *fb_info) 1698 1762 { 1699 - struct fb_event event; 1700 - int ret; 1763 + int i; 1701 1764 1702 - ret = unbind_console(fb_info); 1765 + i = fb_info->node; 1766 + if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)) 1767 + return; 1703 1768 1704 - if (ret) 1705 - return -EINVAL; 1769 + if (!fb_info->dev) 1770 + return; 1771 + 1772 + device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1706 1773 1707 1774 pm_vt_switch_unregister(fb_info->dev); 1708 1775 1709 - __unlink_framebuffer(fb_info); 1776 + unbind_console(fb_info); 1777 + 1778 + fb_info->dev = NULL; 1779 + } 1780 + EXPORT_SYMBOL(unlink_framebuffer); 1781 + 1782 + static void do_unregister_framebuffer(struct fb_info *fb_info) 1783 + { 1784 + unlink_framebuffer(fb_info); 1710 1785 if (fb_info->pixmap.addr && 1711 1786 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1712 1787 kfree(fb_info->pixmap.addr); ··· 1714 1789 registered_fb[fb_info->node] = NULL; 1715 1790 num_registered_fb--; 1716 1791 fb_cleanup_device(fb_info); 1717 - event.info = fb_info; 1792 + #ifdef CONFIG_GUMSTIX_AM200EPD 1793 + { 1794 + struct fb_event event; 1795 + event.info = fb_info; 1796 + fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1797 + } 1798 + #endif 1718 1799 console_lock(); 1719 - fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1800 + fbcon_fb_unregistered(fb_info); 1720 1801 console_unlock(); 1721 1802 1722 1803 /* this may free fb info */ 1723 1804 put_fb_info(fb_info); 1724 - return 0; 1725 1805 } 1726 - 1727 - static int __unlink_framebuffer(struct fb_info *fb_info) 1728 - { 1729 - int i; 1730 - 1731 - i = fb_info->node; 1732 - if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) 1733 - return -EINVAL; 1734 - 1735 - if (fb_info->dev) { 1736 - device_destroy(fb_class, MKDEV(FB_MAJOR, i)); 1737 - fb_info->dev = NULL; 1738 - } 1739 - 1740 - return 0; 1741 - } 1742 - 1743 - int unlink_framebuffer(struct fb_info *fb_info) 1744 - { 1745 - int ret; 1746 - 1747 - ret = __unlink_framebuffer(fb_info); 1748 - if (ret) 1749 - return ret; 1750 - 1751 - unbind_console(fb_info); 1752 - 1753 - return 0; 1754 - } 1755 - EXPORT_SYMBOL(unlink_framebuffer); 1756 1806 1757 1807 /** 1758 1808 * remove_conflicting_framebuffers - remove firmware-configured framebuffers ··· 1742 1842 int remove_conflicting_framebuffers(struct apertures_struct *a, 1743 1843 const char *name, bool primary) 1744 1844 { 1745 - int ret; 1746 1845 bool do_free = false; 1747 1846 1748 1847 if (!a) { ··· 1755 1856 } 1756 1857 1757 1858 mutex_lock(&registration_lock); 1758 - ret = do_remove_conflicting_framebuffers(a, name, primary); 1859 + do_remove_conflicting_framebuffers(a, name, primary); 1759 1860 mutex_unlock(&registration_lock); 1760 1861 1761 1862 if (do_free) 1762 1863 kfree(a); 1763 1864 1764 - return ret; 1865 + return 0; 1765 1866 } 1766 1867 EXPORT_SYMBOL(remove_conflicting_framebuffers); 1767 1868 ··· 1858 1959 * that the driver implements fb_open() and fb_release() to 1859 1960 * check that no processes are using the device. 1860 1961 */ 1861 - int 1962 + void 1862 1963 unregister_framebuffer(struct fb_info *fb_info) 1863 1964 { 1864 - int ret; 1865 - 1866 1965 mutex_lock(&registration_lock); 1867 - ret = do_unregister_framebuffer(fb_info); 1966 + do_unregister_framebuffer(fb_info); 1868 1967 mutex_unlock(&registration_lock); 1869 - 1870 - return ret; 1871 1968 } 1872 1969 EXPORT_SYMBOL(unregister_framebuffer); 1873 1970 ··· 1878 1983 */ 1879 1984 void fb_set_suspend(struct fb_info *info, int state) 1880 1985 { 1881 - struct fb_event event; 1986 + WARN_CONSOLE_UNLOCKED(); 1882 1987 1883 - event.info = info; 1884 1988 if (state) { 1885 - fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); 1989 + fbcon_suspended(info); 1886 1990 info->state = FBINFO_STATE_SUSPENDED; 1887 1991 } else { 1888 1992 info->state = FBINFO_STATE_RUNNING; 1889 - fb_notifier_call_chain(FB_EVENT_RESUME, &event); 1993 + fbcon_resumed(info); 1890 1994 } 1891 1995 } 1892 1996 EXPORT_SYMBOL(fb_set_suspend); ··· 1953 2059 1954 2060 int fb_new_modelist(struct fb_info *info) 1955 2061 { 1956 - struct fb_event event; 1957 2062 struct fb_var_screeninfo var = info->var; 1958 2063 struct list_head *pos, *n; 1959 2064 struct fb_modelist *modelist; ··· 1972 2079 } 1973 2080 } 1974 2081 1975 - err = 1; 2082 + if (list_empty(&info->modelist)) 2083 + return 1; 1976 2084 1977 - if (!list_empty(&info->modelist)) { 1978 - event.info = info; 1979 - err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); 1980 - } 2085 + fbcon_new_modelist(info); 1981 2086 1982 - return err; 2087 + return 0; 1983 2088 } 1984 2089 1985 2090 MODULE_LICENSE("GPL");
+8 -12
drivers/video/fbdev/core/fbsysfs.c
··· 14 14 #include <linux/kernel.h> 15 15 #include <linux/slab.h> 16 16 #include <linux/fb.h> 17 + #include <linux/fbcon.h> 17 18 #include <linux/console.h> 18 19 #include <linux/module.h> 19 20 ··· 176 175 return -EINVAL; 177 176 178 177 console_lock(); 179 - if (!lock_fb_info(fb_info)) { 180 - console_unlock(); 181 - return -ENODEV; 182 - } 178 + lock_fb_info(fb_info); 183 179 184 180 list_splice(&fb_info->modelist, &old_list); 185 181 fb_videomode_to_modelist((const struct fb_videomode *)buf, i, ··· 302 304 { 303 305 struct fb_info *fb_info = dev_get_drvdata(device); 304 306 char *last = NULL; 305 - int err; 307 + int err, arg; 306 308 309 + arg = simple_strtoul(buf, &last, 0); 307 310 console_lock(); 308 - fb_info->flags |= FBINFO_MISC_USEREVENT; 309 - err = fb_blank(fb_info, simple_strtoul(buf, &last, 0)); 310 - fb_info->flags &= ~FBINFO_MISC_USEREVENT; 311 + err = fb_blank(fb_info, arg); 312 + /* might again call into fb_blank */ 313 + fbcon_fb_blanked(fb_info, arg); 311 314 console_unlock(); 312 315 if (err < 0) 313 316 return err; ··· 404 405 state = simple_strtoul(buf, &last, 0); 405 406 406 407 console_lock(); 407 - if (!lock_fb_info(fb_info)) { 408 - console_unlock(); 409 - return -ENODEV; 410 - } 408 + lock_fb_info(fb_info); 411 409 412 410 fb_set_suspend(fb_info, (int)state); 413 411
-1
drivers/video/fbdev/cyber2000fb.c
··· 61 61 struct cfb_info { 62 62 struct fb_info fb; 63 63 struct display_switch *dispsw; 64 - struct display *display; 65 64 unsigned char __iomem *region; 66 65 unsigned char __iomem *regs; 67 66 u_int id;
+1 -8
drivers/video/fbdev/neofb.c
··· 2122 2122 DBG("neofb_remove"); 2123 2123 2124 2124 if (info) { 2125 - /* 2126 - * If unregister_framebuffer fails, then 2127 - * we will be leaving hooks that could cause 2128 - * oopsen laying around. 2129 - */ 2130 - if (unregister_framebuffer(info)) 2131 - printk(KERN_WARNING 2132 - "neofb: danger danger! Oopsen imminent!\n"); 2125 + unregister_framebuffer(info); 2133 2126 2134 2127 neo_unmap_video(info); 2135 2128 fb_destroy_modedb(info->monspecs.modedb);
+7 -14
drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c
··· 60 60 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) 61 61 return -EINVAL; 62 62 63 - if (!lock_fb_info(fbi)) 64 - return -ENODEV; 63 + lock_fb_info(fbi); 65 64 66 65 r = 0; 67 66 if (rot_type == ofbi->rotation_type) ··· 111 112 if (r) 112 113 return r; 113 114 114 - if (!lock_fb_info(fbi)) 115 - return -ENODEV; 115 + lock_fb_info(fbi); 116 116 117 117 ofbi->mirror = mirror; 118 118 ··· 147 149 ssize_t l = 0; 148 150 int t; 149 151 150 - if (!lock_fb_info(fbi)) 151 - return -ENODEV; 152 + lock_fb_info(fbi); 152 153 omapfb_lock(fbdev); 153 154 154 155 for (t = 0; t < ofbi->num_overlays; t++) { ··· 205 208 if (buf[len - 1] == '\n') 206 209 len = len - 1; 207 210 208 - if (!lock_fb_info(fbi)) 209 - return -ENODEV; 211 + lock_fb_info(fbi); 210 212 omapfb_lock(fbdev); 211 213 212 214 if (len > 0) { ··· 336 340 ssize_t l = 0; 337 341 int t; 338 342 339 - if (!lock_fb_info(fbi)) 340 - return -ENODEV; 343 + lock_fb_info(fbi); 341 344 342 345 for (t = 0; t < ofbi->num_overlays; t++) { 343 346 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ··· 364 369 if (buf[len - 1] == '\n') 365 370 len = len - 1; 366 371 367 - if (!lock_fb_info(fbi)) 368 - return -ENODEV; 372 + lock_fb_info(fbi); 369 373 370 374 if (len > 0) { 371 375 char *p = (char *)buf; ··· 447 453 448 454 size = PAGE_ALIGN(size); 449 455 450 - if (!lock_fb_info(fbi)) 451 - return -ENODEV; 456 + lock_fb_info(fbi); 452 457 453 458 if (display && display->driver->sync) 454 459 display->driver->sync(display);
-25
drivers/video/fbdev/sa1100fb.c
··· 974 974 */ 975 975 static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) 976 976 { 977 - #if 0 978 - unsigned int min_period = (unsigned int)-1; 979 - int i; 980 - 981 - for (i = 0; i < MAX_NR_CONSOLES; i++) { 982 - struct display *disp = &fb_display[i]; 983 - unsigned int period; 984 - 985 - /* 986 - * Do we own this display? 987 - */ 988 - if (disp->fb_info != &fbi->fb) 989 - continue; 990 - 991 - /* 992 - * Ok, calculate its DMA period 993 - */ 994 - period = sa1100fb_display_dma_period(&disp->var); 995 - if (period < min_period) 996 - min_period = period; 997 - } 998 - 999 - return min_period; 1000 - #else 1001 977 /* 1002 978 * FIXME: we need to verify _all_ consoles. 1003 979 */ 1004 980 return sa1100fb_display_dma_period(&fbi->fb.var); 1005 - #endif 1006 981 } 1007 982 1008 983 /*
+1 -8
drivers/video/fbdev/savage/savagefb_driver.c
··· 2333 2333 DBG("savagefb_remove"); 2334 2334 2335 2335 if (info) { 2336 - /* 2337 - * If unregister_framebuffer fails, then 2338 - * we will be leaving hooks that could cause 2339 - * oopsen laying around. 2340 - */ 2341 - if (unregister_framebuffer(info)) 2342 - printk(KERN_WARNING "savagefb: danger danger! " 2343 - "Oopsen imminent!\n"); 2336 + unregister_framebuffer(info); 2344 2337 2345 2338 #ifdef CONFIG_FB_SAVAGE_I2C 2346 2339 savagefb_delete_i2c_busses(info);
+2 -130
drivers/video/fbdev/sh_mobile_lcdcfb.c
··· 15 15 #include <linux/ctype.h> 16 16 #include <linux/dma-mapping.h> 17 17 #include <linux/delay.h> 18 + #include <linux/fbcon.h> 18 19 #include <linux/gpio.h> 19 20 #include <linux/init.h> 20 21 #include <linux/interrupt.h> ··· 214 213 struct sh_mobile_lcdc_chan ch[2]; 215 214 struct sh_mobile_lcdc_overlay overlays[4]; 216 215 217 - struct notifier_block notifier; 218 216 int started; 219 217 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ 220 218 }; ··· 534 534 ch->tx_dev->ops->display_off(ch->tx_dev); 535 535 } 536 536 537 - static bool 538 - sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, 539 - const struct fb_videomode *new_mode) 540 - { 541 - dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n", 542 - ch->display.mode.xres, ch->display.mode.yres, 543 - new_mode->xres, new_mode->yres); 544 - 545 - /* It can be a different monitor with an equal video-mode */ 546 - if (fb_mode_is_equal(&ch->display.mode, new_mode)) 547 - return false; 548 - 549 - dev_dbg(ch->info->dev, "Switching %u -> %u lines\n", 550 - ch->display.mode.yres, new_mode->yres); 551 - ch->display.mode = *new_mode; 552 - 553 - return true; 554 - } 555 - 556 537 static int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 557 538 struct fb_info *info); 558 - 559 - static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, 560 - enum sh_mobile_lcdc_entity_event event, 561 - const struct fb_videomode *mode, 562 - const struct fb_monspecs *monspec) 563 - { 564 - struct fb_info *info = ch->info; 565 - struct fb_var_screeninfo var; 566 - int ret = 0; 567 - 568 - switch (event) { 569 - case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: 570 - /* HDMI plug in */ 571 - console_lock(); 572 - if (lock_fb_info(info)) { 573 - 574 - 575 - ch->display.width = monspec->max_x * 10; 576 - ch->display.height = monspec->max_y * 10; 577 - 578 - if (!sh_mobile_lcdc_must_reconfigure(ch, mode) && 579 - info->state == FBINFO_STATE_RUNNING) { 580 - /* First activation with the default monitor. 581 - * Just turn on, if we run a resume here, the 582 - * logo disappears. 583 - */ 584 - info->var.width = ch->display.width; 585 - info->var.height = ch->display.height; 586 - sh_mobile_lcdc_display_on(ch); 587 - } else { 588 - /* New monitor or have to wake up */ 589 - fb_set_suspend(info, 0); 590 - } 591 - 592 - 593 - unlock_fb_info(info); 594 - } 595 - console_unlock(); 596 - break; 597 - 598 - case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: 599 - /* HDMI disconnect */ 600 - console_lock(); 601 - if (lock_fb_info(info)) { 602 - fb_set_suspend(info, 1); 603 - unlock_fb_info(info); 604 - } 605 - console_unlock(); 606 - break; 607 - 608 - case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: 609 - /* Validate a proposed new mode */ 610 - fb_videomode_to_var(&var, mode); 611 - var.bits_per_pixel = info->var.bits_per_pixel; 612 - var.grayscale = info->var.grayscale; 613 - ret = sh_mobile_lcdc_check_var(&var, info); 614 - break; 615 - } 616 - 617 - return ret; 618 - } 619 539 620 540 /* ----------------------------------------------------------------------------- 621 541 * Format helpers ··· 1758 1838 struct sh_mobile_lcdc_chan *ch = info->par; 1759 1839 struct fb_var_screeninfo var; 1760 1840 struct fb_videomode mode; 1761 - struct fb_event event; 1762 - int evnt = FB_EVENT_MODE_CHANGE_ALL; 1763 1841 1764 1842 if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) 1765 1843 /* More framebuffer users are active */ ··· 1779 1861 /* Couldn't reconfigure, hopefully, can continue as before */ 1780 1862 return; 1781 1863 1782 - /* 1783 - * fb_set_var() calls the notifier change internally, only if 1784 - * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a 1785 - * user event, we have to call the chain ourselves. 1786 - */ 1787 - event.info = info; 1788 - event.data = &ch->display.mode; 1789 - fb_notifier_call_chain(evnt, &event); 1864 + fbcon_update_vcs(info, true); 1790 1865 } 1791 1866 1792 1867 /* ··· 2230 2319 * Framebuffer notifier 2231 2320 */ 2232 2321 2233 - /* locking: called with info->lock held */ 2234 - static int sh_mobile_lcdc_notify(struct notifier_block *nb, 2235 - unsigned long action, void *data) 2236 - { 2237 - struct fb_event *event = data; 2238 - struct fb_info *info = event->info; 2239 - struct sh_mobile_lcdc_chan *ch = info->par; 2240 - 2241 - if (&ch->lcdc->notifier != nb) 2242 - return NOTIFY_DONE; 2243 - 2244 - dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 2245 - __func__, action, event->data); 2246 - 2247 - switch(action) { 2248 - case FB_EVENT_SUSPEND: 2249 - sh_mobile_lcdc_display_off(ch); 2250 - sh_mobile_lcdc_stop(ch->lcdc); 2251 - break; 2252 - case FB_EVENT_RESUME: 2253 - mutex_lock(&ch->open_lock); 2254 - sh_mobile_fb_reconfig(info); 2255 - mutex_unlock(&ch->open_lock); 2256 - 2257 - sh_mobile_lcdc_display_on(ch); 2258 - sh_mobile_lcdc_start(ch->lcdc); 2259 - } 2260 - 2261 - return NOTIFY_OK; 2262 - } 2263 - 2264 2322 /* ----------------------------------------------------------------------------- 2265 2323 * Probe/remove and driver init/exit 2266 2324 */ ··· 2256 2376 { 2257 2377 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 2258 2378 unsigned int i; 2259 - 2260 - fb_unregister_client(&priv->notifier); 2261 2379 2262 2380 for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) 2263 2381 sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); ··· 2417 2539 unsigned int num_modes; 2418 2540 unsigned int max_size; 2419 2541 unsigned int i; 2420 - 2421 - ch->notify = sh_mobile_lcdc_display_notify; 2422 2542 2423 2543 /* Validate the format. */ 2424 2544 format = sh_mobile_format_info(cfg->fourcc); ··· 2645 2769 if (error) 2646 2770 goto err1; 2647 2771 } 2648 - 2649 - /* Failure ignored */ 2650 - priv->notifier.notifier_call = sh_mobile_lcdc_notify; 2651 - fb_register_client(&priv->notifier); 2652 2772 2653 2773 return 0; 2654 2774 err1:
-5
drivers/video/fbdev/sh_mobile_lcdcfb.h
··· 87 87 unsigned long base_addr_c; 88 88 unsigned int line_size; 89 89 90 - int (*notify)(struct sh_mobile_lcdc_chan *ch, 91 - enum sh_mobile_lcdc_entity_event event, 92 - const struct fb_videomode *mode, 93 - const struct fb_monspecs *monspec); 94 - 95 90 /* Backlight */ 96 91 struct backlight_device *bl; 97 92 unsigned int bl_brightness;
+1 -4
include/linux/console_struct.h
··· 168 168 169 169 #define CUR_DEFAULT CUR_UNDERLINE 170 170 171 - static inline bool con_is_visible(const struct vc_data *vc) 172 - { 173 - return *vc->vc_display_fg == vc; 174 - } 171 + bool con_is_visible(const struct vc_data *vc); 175 172 176 173 #endif /* _LINUX_CONSOLE_STRUCT_H */
+12 -33
include/linux/fb.h
··· 126 126 127 127 /* The resolution of the passed in fb_info about to change */ 128 128 #define FB_EVENT_MODE_CHANGE 0x01 129 - /* The display on this fb_info is being suspended, no access to the 130 - * framebuffer is allowed any more after that call returns 131 - */ 132 - #define FB_EVENT_SUSPEND 0x02 133 - /* The display on this fb_info was resumed, you can restore the display 134 - * if you own it 135 - */ 136 - #define FB_EVENT_RESUME 0x03 137 - /* An entry from the modelist was removed */ 138 - #define FB_EVENT_MODE_DELETE 0x04 139 - /* A driver registered itself */ 129 + 130 + #ifdef CONFIG_GUMSTIX_AM200EPD 131 + /* only used by mach-pxa/am200epd.c */ 140 132 #define FB_EVENT_FB_REGISTERED 0x05 141 - /* A driver unregistered itself */ 142 133 #define FB_EVENT_FB_UNREGISTERED 0x06 143 - /* CONSOLE-SPECIFIC: get console to framebuffer mapping */ 144 - #define FB_EVENT_GET_CONSOLE_MAP 0x07 145 - /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ 146 - #define FB_EVENT_SET_CONSOLE_MAP 0x08 147 - /* A hardware display blank change occurred */ 134 + #endif 135 + 136 + /* A display blank is requested */ 148 137 #define FB_EVENT_BLANK 0x09 149 - /* Private modelist is to be replaced */ 150 - #define FB_EVENT_NEW_MODELIST 0x0A 151 - /* The resolution of the passed in fb_info about to change and 152 - all vc's should be changed */ 153 - #define FB_EVENT_MODE_CHANGE_ALL 0x0B 154 - /* A software display blank change occurred */ 155 - #define FB_EVENT_CONBLANK 0x0C 156 - /* Get drawing requirements */ 157 - #define FB_EVENT_GET_REQ 0x0D 158 - /* Unbind from the console if possible */ 159 - #define FB_EVENT_FB_UNBIND 0x0E 160 - /* CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */ 161 - #define FB_EVENT_REMAP_ALL_CONSOLE 0x0F 162 138 /* A hardware display blank early change occurred */ 163 139 #define FB_EARLY_EVENT_BLANK 0x10 164 140 /* A hardware display blank revert early change occurred */ ··· 609 633 610 634 /* drivers/video/fbmem.c */ 611 635 extern int register_framebuffer(struct fb_info *fb_info); 612 - extern int unregister_framebuffer(struct fb_info *fb_info); 613 - extern int unlink_framebuffer(struct fb_info *fb_info); 636 + extern void unregister_framebuffer(struct fb_info *fb_info); 637 + extern void unlink_framebuffer(struct fb_info *fb_info); 614 638 extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, 615 639 const char *name); 616 640 extern int remove_conflicting_framebuffers(struct apertures_struct *a, ··· 636 660 for (i = 0; i < FB_MAX; i++) \ 637 661 if (!registered_fb[i]) {} else 638 662 639 - extern int lock_fb_info(struct fb_info *info); 663 + static inline void lock_fb_info(struct fb_info *info) 664 + { 665 + mutex_lock(&info->lock); 666 + } 640 667 641 668 static inline void unlock_fb_info(struct fb_info *info) 642 669 {
+30
include/linux/fbcon.h
··· 4 4 #ifdef CONFIG_FRAMEBUFFER_CONSOLE 5 5 void __init fb_console_init(void); 6 6 void __exit fb_console_exit(void); 7 + int fbcon_fb_registered(struct fb_info *info); 8 + void fbcon_fb_unregistered(struct fb_info *info); 9 + void fbcon_fb_unbind(struct fb_info *info); 10 + void fbcon_suspended(struct fb_info *info); 11 + void fbcon_resumed(struct fb_info *info); 12 + int fbcon_mode_deleted(struct fb_info *info, 13 + struct fb_videomode *mode); 14 + void fbcon_new_modelist(struct fb_info *info); 15 + void fbcon_get_requirement(struct fb_info *info, 16 + struct fb_blit_caps *caps); 17 + void fbcon_fb_blanked(struct fb_info *info, int blank); 18 + void fbcon_update_vcs(struct fb_info *info, bool all); 19 + void fbcon_remap_all(struct fb_info *info); 20 + int fbcon_set_con2fb_map_ioctl(void __user *argp); 21 + int fbcon_get_con2fb_map_ioctl(void __user *argp); 7 22 #else 8 23 static inline void fb_console_init(void) {} 9 24 static inline void fb_console_exit(void) {} 25 + static inline int fbcon_fb_registered(struct fb_info *info) { return 0; } 26 + static inline void fbcon_fb_unregistered(struct fb_info *info) {} 27 + static inline void fbcon_fb_unbind(struct fb_info *info) {} 28 + static inline void fbcon_suspended(struct fb_info *info) {} 29 + static inline void fbcon_resumed(struct fb_info *info) {} 30 + static inline int fbcon_mode_deleted(struct fb_info *info, 31 + struct fb_videomode *mode) { return 0; } 32 + static inline void fbcon_new_modelist(struct fb_info *info) {} 33 + static inline void fbcon_get_requirement(struct fb_info *info, 34 + struct fb_blit_caps *caps) {} 35 + static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {} 36 + static inline void fbcon_update_vcs(struct fb_info *info, bool all) {} 37 + static inline void fbcon_remap_all(struct fb_info *info) {} 38 + static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; } 39 + static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; } 10 40 #endif 11 41 12 42 #endif /* _LINUX_FBCON_H */