aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/fbmem.c141
1 files changed, 86 insertions, 55 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 217c5118ae9e..2a0f013dc37b 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1002,101 +1002,132 @@ fb_blank(struct fb_info *info, int blank)
1002 return ret; 1002 return ret;
1003} 1003}
1004 1004
1005static int 1005static long
1006fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 1006fb_ioctl(struct file *file, unsigned int cmd,
1007 unsigned long arg) 1007 unsigned long arg)
1008{ 1008{
1009 struct inode *inode = file->f_path.dentry->d_inode;
1009 int fbidx = iminor(inode); 1010 int fbidx = iminor(inode);
1010 struct fb_info *info = registered_fb[fbidx]; 1011 struct fb_info *info;
1011 struct fb_ops *fb = info->fbops; 1012 struct fb_ops *fb;
1012 struct fb_var_screeninfo var; 1013 struct fb_var_screeninfo var;
1013 struct fb_fix_screeninfo fix; 1014 struct fb_fix_screeninfo fix;
1014 struct fb_con2fbmap con2fb; 1015 struct fb_con2fbmap con2fb;
1015 struct fb_cmap_user cmap; 1016 struct fb_cmap_user cmap;
1016 struct fb_event event; 1017 struct fb_event event;
1017 void __user *argp = (void __user *)arg; 1018 void __user *argp = (void __user *)arg;
1018 int i; 1019 long ret = 0;
1019 1020
1020 if (!fb) 1021 lock_kernel();
1022 info = registered_fb[fbidx];
1023 fb = info->fbops;
1024
1025 if (!fb) {
1026 unlock_kernel();
1021 return -ENODEV; 1027 return -ENODEV;
1028 }
1022 switch (cmd) { 1029 switch (cmd) {
1023 case FBIOGET_VSCREENINFO: 1030 case FBIOGET_VSCREENINFO:
1024 return copy_to_user(argp, &info->var, 1031 ret = copy_to_user(argp, &info->var,
1025 sizeof(var)) ? -EFAULT : 0; 1032 sizeof(var)) ? -EFAULT : 0;
1033 break;
1026 case FBIOPUT_VSCREENINFO: 1034 case FBIOPUT_VSCREENINFO:
1027 if (copy_from_user(&var, argp, sizeof(var))) 1035 if (copy_from_user(&var, argp, sizeof(var))) {
1028 return -EFAULT; 1036 ret = -EFAULT;
1037 break;
1038 }
1029 acquire_console_sem(); 1039 acquire_console_sem();
1030 info->flags |= FBINFO_MISC_USEREVENT; 1040 info->flags |= FBINFO_MISC_USEREVENT;
1031 i = fb_set_var(info, &var); 1041 ret = fb_set_var(info, &var);
1032 info->flags &= ~FBINFO_MISC_USEREVENT; 1042 info->flags &= ~FBINFO_MISC_USEREVENT;
1033 release_console_sem(); 1043 release_console_sem();
1034 if (i) return i; 1044 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
1035 if (copy_to_user(argp, &var, sizeof(var))) 1045 ret = -EFAULT;
1036 return -EFAULT; 1046 break;
1037 return 0;
1038 case FBIOGET_FSCREENINFO: 1047 case FBIOGET_FSCREENINFO:
1039 return copy_to_user(argp, &info->fix, 1048 ret = copy_to_user(argp, &info->fix,
1040 sizeof(fix)) ? -EFAULT : 0; 1049 sizeof(fix)) ? -EFAULT : 0;
1050 break;
1041 case FBIOPUTCMAP: 1051 case FBIOPUTCMAP:
1042 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1052 if (copy_from_user(&cmap, argp, sizeof(cmap)))
1043 return -EFAULT; 1053 ret = -EFAULT;
1044 return (fb_set_user_cmap(&cmap, info)); 1054 else
1055 ret = fb_set_user_cmap(&cmap, info);
1056 break;
1045 case FBIOGETCMAP: 1057 case FBIOGETCMAP:
1046 if (copy_from_user(&cmap, argp, sizeof(cmap))) 1058 if (copy_from_user(&cmap, argp, sizeof(cmap)))
1047 return -EFAULT; 1059 ret = -EFAULT;
1048 return fb_cmap_to_user(&info->cmap, &cmap); 1060 else
1061 ret = fb_cmap_to_user(&info->cmap, &cmap);
1062 break;
1049 case FBIOPAN_DISPLAY: 1063 case FBIOPAN_DISPLAY:
1050 if (copy_from_user(&var, argp, sizeof(var))) 1064 if (copy_from_user(&var, argp, sizeof(var))) {
1051 return -EFAULT; 1065 ret = -EFAULT;
1066 break;
1067 }
1052 acquire_console_sem(); 1068 acquire_console_sem();
1053 i = fb_pan_display(info, &var); 1069 ret = fb_pan_display(info, &var);
1054 release_console_sem(); 1070 release_console_sem();
1055 if (i) 1071 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
1056 return i; 1072 ret = -EFAULT;
1057 if (copy_to_user(argp, &var, sizeof(var))) 1073 break;
1058 return -EFAULT;
1059 return 0;
1060 case FBIO_CURSOR: 1074 case FBIO_CURSOR:
1061 return -EINVAL; 1075 ret = -EINVAL;
1076 break;
1062 case FBIOGET_CON2FBMAP: 1077 case FBIOGET_CON2FBMAP:
1063 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1078 if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
1064 return -EFAULT; 1079 ret = -EFAULT;
1065 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1080 else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
1066 return -EINVAL; 1081 ret = -EINVAL;
1067 con2fb.framebuffer = -1; 1082 else {
1068 event.info = info; 1083 con2fb.framebuffer = -1;
1069 event.data = &con2fb; 1084 event.info = info;
1070 fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); 1085 event.data = &con2fb;
1071 return copy_to_user(argp, &con2fb, 1086 fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
1087 &event);
1088 ret = copy_to_user(argp, &con2fb,
1072 sizeof(con2fb)) ? -EFAULT : 0; 1089 sizeof(con2fb)) ? -EFAULT : 0;
1090 }
1091 break;
1073 case FBIOPUT_CON2FBMAP: 1092 case FBIOPUT_CON2FBMAP:
1074 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) 1093 if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
1075 return - EFAULT; 1094 ret = -EFAULT;
1076 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) 1095 break;
1077 return -EINVAL; 1096 }
1078 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) 1097 if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
1079 return -EINVAL; 1098 ret = -EINVAL;
1080 if (!registered_fb[con2fb.framebuffer]) 1099 break;
1081 request_module("fb%d", con2fb.framebuffer); 1100 }
1101 if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
1102 ret = -EINVAL;
1103 break;
1104 }
1082 if (!registered_fb[con2fb.framebuffer]) 1105 if (!registered_fb[con2fb.framebuffer])
1083 return -EINVAL; 1106 request_module("fb%d", con2fb.framebuffer);
1107 if (!registered_fb[con2fb.framebuffer]) {
1108 ret = -EINVAL;
1109 break;
1110 }
1084 event.info = info; 1111 event.info = info;
1085 event.data = &con2fb; 1112 event.data = &con2fb;
1086 return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, 1113 ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
1087 &event); 1114 &event);
1115 break;
1088 case FBIOBLANK: 1116 case FBIOBLANK:
1089 acquire_console_sem(); 1117 acquire_console_sem();
1090 info->flags |= FBINFO_MISC_USEREVENT; 1118 info->flags |= FBINFO_MISC_USEREVENT;
1091 i = fb_blank(info, arg); 1119 ret = fb_blank(info, arg);
1092 info->flags &= ~FBINFO_MISC_USEREVENT; 1120 info->flags &= ~FBINFO_MISC_USEREVENT;
1093 release_console_sem(); 1121 release_console_sem();
1094 return i; 1122 break;;
1095 default: 1123 default:
1096 if (fb->fb_ioctl == NULL) 1124 if (fb->fb_ioctl == NULL)
1097 return -EINVAL; 1125 ret = -ENOTTY;
1098 return fb->fb_ioctl(info, cmd, arg); 1126 else
1127 ret = fb->fb_ioctl(info, cmd, arg);
1099 } 1128 }
1129 unlock_kernel();
1130 return ret;
1100} 1131}
1101 1132
1102#ifdef CONFIG_COMPAT 1133#ifdef CONFIG_COMPAT
@@ -1150,7 +1181,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file,
1150 put_user(compat_ptr(data), &cmap->transp)) 1181 put_user(compat_ptr(data), &cmap->transp))
1151 return -EFAULT; 1182 return -EFAULT;
1152 1183
1153 err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); 1184 err = fb_ioctl(file, cmd, (unsigned long) cmap);
1154 1185
1155 if (!err) { 1186 if (!err) {
1156 if (copy_in_user(&cmap32->start, 1187 if (copy_in_user(&cmap32->start,
@@ -1204,7 +1235,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
1204 1235
1205 old_fs = get_fs(); 1236 old_fs = get_fs();
1206 set_fs(KERNEL_DS); 1237 set_fs(KERNEL_DS);
1207 err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); 1238 err = fb_ioctl(file, cmd, (unsigned long) &fix);
1208 set_fs(old_fs); 1239 set_fs(old_fs);
1209 1240
1210 if (!err) 1241 if (!err)
@@ -1231,7 +1262,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1231 case FBIOPUT_CON2FBMAP: 1262 case FBIOPUT_CON2FBMAP:
1232 arg = (unsigned long) compat_ptr(arg); 1263 arg = (unsigned long) compat_ptr(arg);
1233 case FBIOBLANK: 1264 case FBIOBLANK:
1234 ret = fb_ioctl(inode, file, cmd, arg); 1265 ret = fb_ioctl(file, cmd, arg);
1235 break; 1266 break;
1236 1267
1237 case FBIOGET_FSCREENINFO: 1268 case FBIOGET_FSCREENINFO:
@@ -1358,7 +1389,7 @@ static const struct file_operations fb_fops = {
1358 .owner = THIS_MODULE, 1389 .owner = THIS_MODULE,
1359 .read = fb_read, 1390 .read = fb_read,
1360 .write = fb_write, 1391 .write = fb_write,
1361 .ioctl = fb_ioctl, 1392 .unlocked_ioctl = fb_ioctl,
1362#ifdef CONFIG_COMPAT 1393#ifdef CONFIG_COMPAT
1363 .compat_ioctl = fb_compat_ioctl, 1394 .compat_ioctl = fb_compat_ioctl,
1364#endif 1395#endif