aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2009-09-22 19:47:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:56 -0400
commit0fcf6ada2b8eb42d132c0846384f1299889609e3 (patch)
treeb6b9e2996eb621d6ab03d1d8ac5e00ce070cea76 /drivers/video
parent360fa58828784f307c3977d5ff4c8e400f074a56 (diff)
fb: do not ignore fb_set_par errors
At the moment about half of the framebuffer drivers can return an error code in fb_set_par. Until now it would be silently ignored by fbmem.c and fbcon.c. This patch fixes fbmem.c to return the error code and restore var on error. But it is not clear in which video mode the device is when fb_set_par fails. It would be good and reasonable if it were in the old state but there is no guarantee that this is true for all existing drivers. Additionally print a message if a failing fb_set_par is detected in fbmem.c or fbcon.c. Although most errors should be caught by the previous fb_check_var some errors can't as they are dynamic (memory allocations, ...) and can only be detected while performing the operations which is forbidden in fb_check_var. This patch shouldn't have a negative impact on normal operation as all drivers return 0 on success. The impact in case of error depends heavily on the driver and caller but it's expected to be better than before. Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/console/fbcon.c48
-rw-r--r--drivers/video/fbmem.c15
2 files changed, 50 insertions, 13 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3a44695b9c09..4bee7c2e6313 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -725,7 +725,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
725 int oldidx, int found) 725 int oldidx, int found)
726{ 726{
727 struct fbcon_ops *ops = oldinfo->fbcon_par; 727 struct fbcon_ops *ops = oldinfo->fbcon_par;
728 int err = 0; 728 int err = 0, ret;
729 729
730 if (oldinfo->fbops->fb_release && 730 if (oldinfo->fbops->fb_release &&
731 oldinfo->fbops->fb_release(oldinfo, 0)) { 731 oldinfo->fbops->fb_release(oldinfo, 0)) {
@@ -752,8 +752,14 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
752 newinfo in an undefined state. Thus, a call to 752 newinfo in an undefined state. Thus, a call to
753 fb_set_par() may be needed for the newinfo. 753 fb_set_par() may be needed for the newinfo.
754 */ 754 */
755 if (newinfo->fbops->fb_set_par) 755 if (newinfo->fbops->fb_set_par) {
756 newinfo->fbops->fb_set_par(newinfo); 756 ret = newinfo->fbops->fb_set_par(newinfo);
757
758 if (ret)
759 printk(KERN_ERR "con2fb_release_oldinfo: "
760 "detected unhandled fb_set_par error, "
761 "error code %d\n", ret);
762 }
757 } 763 }
758 764
759 return err; 765 return err;
@@ -763,11 +769,18 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
763 int unit, int show_logo) 769 int unit, int show_logo)
764{ 770{
765 struct fbcon_ops *ops = info->fbcon_par; 771 struct fbcon_ops *ops = info->fbcon_par;
772 int ret;
766 773
767 ops->currcon = fg_console; 774 ops->currcon = fg_console;
768 775
769 if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) 776 if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) {
770 info->fbops->fb_set_par(info); 777 ret = info->fbops->fb_set_par(info);
778
779 if (ret)
780 printk(KERN_ERR "con2fb_init_display: detected "
781 "unhandled fb_set_par error, "
782 "error code %d\n", ret);
783 }
771 784
772 ops->flags |= FBCON_FLAGS_INIT; 785 ops->flags |= FBCON_FLAGS_INIT;
773 ops->graphics = 0; 786 ops->graphics = 0;
@@ -1006,7 +1019,7 @@ static void fbcon_init(struct vc_data *vc, int init)
1006 struct vc_data *svc = *default_mode; 1019 struct vc_data *svc = *default_mode;
1007 struct display *t, *p = &fb_display[vc->vc_num]; 1020 struct display *t, *p = &fb_display[vc->vc_num];
1008 int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; 1021 int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
1009 int cap; 1022 int cap, ret;
1010 1023
1011 if (info_idx == -1 || info == NULL) 1024 if (info_idx == -1 || info == NULL)
1012 return; 1025 return;
@@ -1092,8 +1105,15 @@ static void fbcon_init(struct vc_data *vc, int init)
1092 */ 1105 */
1093 if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { 1106 if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
1094 if (info->fbops->fb_set_par && 1107 if (info->fbops->fb_set_par &&
1095 !(ops->flags & FBCON_FLAGS_INIT)) 1108 !(ops->flags & FBCON_FLAGS_INIT)) {
1096 info->fbops->fb_set_par(info); 1109 ret = info->fbops->fb_set_par(info);
1110
1111 if (ret)
1112 printk(KERN_ERR "fbcon_init: detected "
1113 "unhandled fb_set_par error, "
1114 "error code %d\n", ret);
1115 }
1116
1097 ops->flags |= FBCON_FLAGS_INIT; 1117 ops->flags |= FBCON_FLAGS_INIT;
1098 } 1118 }
1099 1119
@@ -2119,7 +2139,7 @@ static int fbcon_switch(struct vc_data *vc)
2119 struct fbcon_ops *ops; 2139 struct fbcon_ops *ops;
2120 struct display *p = &fb_display[vc->vc_num]; 2140 struct display *p = &fb_display[vc->vc_num];
2121 struct fb_var_screeninfo var; 2141 struct fb_var_screeninfo var;
2122 int i, prev_console, charcnt = 256; 2142 int i, ret, prev_console, charcnt = 256;
2123 2143
2124 info = registered_fb[con2fb_map[vc->vc_num]]; 2144 info = registered_fb[con2fb_map[vc->vc_num]];
2125 ops = info->fbcon_par; 2145 ops = info->fbcon_par;
@@ -2174,8 +2194,14 @@ static int fbcon_switch(struct vc_data *vc)
2174 2194
2175 if (old_info != NULL && (old_info != info || 2195 if (old_info != NULL && (old_info != info ||
2176 info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { 2196 info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
2177 if (info->fbops->fb_set_par) 2197 if (info->fbops->fb_set_par) {
2178 info->fbops->fb_set_par(info); 2198 ret = info->fbops->fb_set_par(info);
2199
2200 if (ret)
2201 printk(KERN_ERR "fbcon_switch: detected "
2202 "unhandled fb_set_par error, "
2203 "error code %d\n", ret);
2204 }
2179 2205
2180 if (old_info != info) 2206 if (old_info != info)
2181 fbcon_del_cursor_timer(old_info); 2207 fbcon_del_cursor_timer(old_info);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 346f257215a7..a1f2e7ce730b 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -954,6 +954,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
954 goto done; 954 goto done;
955 955
956 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 956 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
957 struct fb_var_screeninfo old_var;
957 struct fb_videomode mode; 958 struct fb_videomode mode;
958 959
959 if (info->fbops->fb_get_caps) { 960 if (info->fbops->fb_get_caps) {
@@ -963,10 +964,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
963 goto done; 964 goto done;
964 } 965 }
965 966
967 old_var = info->var;
966 info->var = *var; 968 info->var = *var;
967 969
968 if (info->fbops->fb_set_par) 970 if (info->fbops->fb_set_par) {
969 info->fbops->fb_set_par(info); 971 ret = info->fbops->fb_set_par(info);
972
973 if (ret) {
974 info->var = old_var;
975 printk(KERN_WARNING "detected "
976 "fb_set_par error, "
977 "error code: %d\n", ret);
978 goto done;
979 }
980 }
970 981
971 fb_pan_display(info, &info->var); 982 fb_pan_display(info, &info->var);
972 fb_set_cmap(&info->cmap, info); 983 fb_set_cmap(&info->cmap, info);