diff options
Diffstat (limited to 'drivers/video/fbmem.c')
| -rw-r--r-- | drivers/video/fbmem.c | 135 |
1 files changed, 69 insertions, 66 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 756efeb91abc..cfd9dce1ce0b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 1013 | struct fb_var_screeninfo var; | 1013 | struct fb_var_screeninfo var; |
| 1014 | struct fb_fix_screeninfo fix; | 1014 | struct fb_fix_screeninfo fix; |
| 1015 | struct fb_con2fbmap con2fb; | 1015 | struct fb_con2fbmap con2fb; |
| 1016 | struct fb_cmap cmap_from; | ||
| 1016 | struct fb_cmap_user cmap; | 1017 | struct fb_cmap_user cmap; |
| 1017 | struct fb_event event; | 1018 | struct fb_event event; |
| 1018 | void __user *argp = (void __user *)arg; | 1019 | void __user *argp = (void __user *)arg; |
| 1019 | long ret = 0; | 1020 | long ret = 0; |
| 1020 | 1021 | ||
| 1021 | fb = info->fbops; | ||
| 1022 | if (!fb) | ||
| 1023 | return -ENODEV; | ||
| 1024 | |||
| 1025 | switch (cmd) { | 1022 | switch (cmd) { |
| 1026 | case FBIOGET_VSCREENINFO: | 1023 | case FBIOGET_VSCREENINFO: |
| 1027 | ret = copy_to_user(argp, &info->var, | 1024 | if (!lock_fb_info(info)) |
| 1028 | sizeof(var)) ? -EFAULT : 0; | 1025 | return -ENODEV; |
| 1026 | var = info->var; | ||
| 1027 | unlock_fb_info(info); | ||
| 1028 | |||
| 1029 | ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0; | ||
| 1029 | break; | 1030 | break; |
| 1030 | case FBIOPUT_VSCREENINFO: | 1031 | case FBIOPUT_VSCREENINFO: |
| 1031 | if (copy_from_user(&var, argp, sizeof(var))) { | 1032 | if (copy_from_user(&var, argp, sizeof(var))) |
| 1032 | ret = -EFAULT; | 1033 | return -EFAULT; |
| 1033 | break; | 1034 | if (!lock_fb_info(info)) |
| 1034 | } | 1035 | return -ENODEV; |
| 1035 | acquire_console_sem(); | 1036 | acquire_console_sem(); |
| 1036 | info->flags |= FBINFO_MISC_USEREVENT; | 1037 | info->flags |= FBINFO_MISC_USEREVENT; |
| 1037 | ret = fb_set_var(info, &var); | 1038 | ret = fb_set_var(info, &var); |
| 1038 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1039 | info->flags &= ~FBINFO_MISC_USEREVENT; |
| 1039 | release_console_sem(); | 1040 | release_console_sem(); |
| 1040 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | 1041 | unlock_fb_info(info); |
| 1042 | if (!ret && copy_to_user(argp, &var, sizeof(var))) | ||
| 1041 | ret = -EFAULT; | 1043 | ret = -EFAULT; |
| 1042 | break; | 1044 | break; |
| 1043 | case FBIOGET_FSCREENINFO: | 1045 | case FBIOGET_FSCREENINFO: |
| 1044 | ret = copy_to_user(argp, &info->fix, | 1046 | if (!lock_fb_info(info)) |
| 1045 | sizeof(fix)) ? -EFAULT : 0; | 1047 | return -ENODEV; |
| 1048 | fix = info->fix; | ||
| 1049 | unlock_fb_info(info); | ||
| 1050 | |||
| 1051 | ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0; | ||
| 1046 | break; | 1052 | break; |
| 1047 | case FBIOPUTCMAP: | 1053 | case FBIOPUTCMAP: |
| 1048 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1054 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
| 1049 | ret = -EFAULT; | 1055 | return -EFAULT; |
| 1050 | else | 1056 | ret = fb_set_user_cmap(&cmap, info); |
| 1051 | ret = fb_set_user_cmap(&cmap, info); | ||
| 1052 | break; | 1057 | break; |
| 1053 | case FBIOGETCMAP: | 1058 | case FBIOGETCMAP: |
| 1054 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1059 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
| 1055 | ret = -EFAULT; | 1060 | return -EFAULT; |
| 1056 | else | 1061 | if (!lock_fb_info(info)) |
| 1057 | ret = fb_cmap_to_user(&info->cmap, &cmap); | 1062 | return -ENODEV; |
| 1063 | cmap_from = info->cmap; | ||
| 1064 | unlock_fb_info(info); | ||
| 1065 | ret = fb_cmap_to_user(&cmap_from, &cmap); | ||
| 1058 | break; | 1066 | break; |
| 1059 | case FBIOPAN_DISPLAY: | 1067 | case FBIOPAN_DISPLAY: |
| 1060 | if (copy_from_user(&var, argp, sizeof(var))) { | 1068 | if (copy_from_user(&var, argp, sizeof(var))) |
| 1061 | ret = -EFAULT; | 1069 | return -EFAULT; |
| 1062 | break; | 1070 | if (!lock_fb_info(info)) |
| 1063 | } | 1071 | return -ENODEV; |
| 1064 | acquire_console_sem(); | 1072 | acquire_console_sem(); |
| 1065 | ret = fb_pan_display(info, &var); | 1073 | ret = fb_pan_display(info, &var); |
| 1066 | release_console_sem(); | 1074 | release_console_sem(); |
| 1075 | unlock_fb_info(info); | ||
| 1067 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | 1076 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) |
| 1068 | ret = -EFAULT; | 1077 | return -EFAULT; |
| 1069 | break; | 1078 | break; |
| 1070 | case FBIO_CURSOR: | 1079 | case FBIO_CURSOR: |
| 1071 | ret = -EINVAL; | 1080 | ret = -EINVAL; |
| 1072 | break; | 1081 | break; |
| 1073 | case FBIOGET_CON2FBMAP: | 1082 | case FBIOGET_CON2FBMAP: |
| 1074 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1083 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
| 1075 | ret = -EFAULT; | 1084 | return -EFAULT; |
| 1076 | else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | 1085 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
| 1077 | ret = -EINVAL; | 1086 | return -EINVAL; |
| 1078 | else { | 1087 | con2fb.framebuffer = -1; |
| 1079 | con2fb.framebuffer = -1; | 1088 | event.data = &con2fb; |
| 1080 | event.info = info; | 1089 | |
| 1081 | event.data = &con2fb; | 1090 | if (!lock_fb_info(info)) |
| 1082 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, | 1091 | return -ENODEV; |
| 1083 | &event); | 1092 | event.info = info; |
| 1084 | ret = copy_to_user(argp, &con2fb, | 1093 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); |
| 1085 | sizeof(con2fb)) ? -EFAULT : 0; | 1094 | unlock_fb_info(info); |
| 1086 | } | 1095 | |
| 1096 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | ||
| 1087 | break; | 1097 | break; |
| 1088 | case FBIOPUT_CON2FBMAP: | 1098 | case FBIOPUT_CON2FBMAP: |
| 1089 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) { | 1099 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
| 1090 | ret = -EFAULT; | 1100 | return -EFAULT; |
| 1091 | break; | 1101 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
| 1092 | } | 1102 | return -EINVAL; |
| 1093 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) { | 1103 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) |
| 1094 | ret = -EINVAL; | 1104 | return -EINVAL; |
| 1095 | break; | ||
| 1096 | } | ||
| 1097 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { | ||
| 1098 | ret = -EINVAL; | ||
| 1099 | break; | ||
| 1100 | } | ||
| 1101 | if (!registered_fb[con2fb.framebuffer]) | 1105 | if (!registered_fb[con2fb.framebuffer]) |
| 1102 | request_module("fb%d", con2fb.framebuffer); | 1106 | request_module("fb%d", con2fb.framebuffer); |
| 1103 | if (!registered_fb[con2fb.framebuffer]) { | 1107 | if (!registered_fb[con2fb.framebuffer]) { |
| 1104 | ret = -EINVAL; | 1108 | ret = -EINVAL; |
| 1105 | break; | 1109 | break; |
| 1106 | } | 1110 | } |
| 1107 | event.info = info; | ||
| 1108 | event.data = &con2fb; | 1111 | event.data = &con2fb; |
| 1112 | if (!lock_fb_info(info)) | ||
| 1113 | return -ENODEV; | ||
| 1114 | event.info = info; | ||
| 1109 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | 1115 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, |
| 1110 | &event); | 1116 | &event); |
| 1117 | unlock_fb_info(info); | ||
| 1111 | break; | 1118 | break; |
| 1112 | case FBIOBLANK: | 1119 | case FBIOBLANK: |
| 1120 | if (!lock_fb_info(info)) | ||
| 1121 | return -ENODEV; | ||
| 1113 | acquire_console_sem(); | 1122 | acquire_console_sem(); |
| 1114 | info->flags |= FBINFO_MISC_USEREVENT; | 1123 | info->flags |= FBINFO_MISC_USEREVENT; |
| 1115 | ret = fb_blank(info, arg); | 1124 | ret = fb_blank(info, arg); |
| 1116 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1125 | info->flags &= ~FBINFO_MISC_USEREVENT; |
| 1117 | release_console_sem(); | 1126 | release_console_sem(); |
| 1118 | break;; | 1127 | unlock_fb_info(info); |
| 1128 | break; | ||
| 1119 | default: | 1129 | default: |
| 1120 | if (fb->fb_ioctl == NULL) | 1130 | if (!lock_fb_info(info)) |
| 1121 | ret = -ENOTTY; | 1131 | return -ENODEV; |
| 1122 | else | 1132 | fb = info->fbops; |
| 1133 | if (fb->fb_ioctl) | ||
| 1123 | ret = fb->fb_ioctl(info, cmd, arg); | 1134 | ret = fb->fb_ioctl(info, cmd, arg); |
| 1135 | else | ||
| 1136 | ret = -ENOTTY; | ||
| 1137 | unlock_fb_info(info); | ||
| 1124 | } | 1138 | } |
| 1125 | return ret; | 1139 | return ret; |
| 1126 | } | 1140 | } |
| 1127 | 1141 | ||
| 1128 | static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1142 | static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 1129 | __acquires(&info->lock) | ||
| 1130 | __releases(&info->lock) | ||
| 1131 | { | 1143 | { |
| 1132 | struct inode *inode = file->f_path.dentry->d_inode; | 1144 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1133 | int fbidx = iminor(inode); | 1145 | int fbidx = iminor(inode); |
| 1134 | struct fb_info *info; | 1146 | struct fb_info *info = registered_fb[fbidx]; |
| 1135 | long ret; | ||
| 1136 | 1147 | ||
| 1137 | info = registered_fb[fbidx]; | 1148 | return do_fb_ioctl(info, cmd, arg); |
| 1138 | mutex_lock(&info->lock); | ||
| 1139 | ret = do_fb_ioctl(info, cmd, arg); | ||
| 1140 | mutex_unlock(&info->lock); | ||
| 1141 | return ret; | ||
| 1142 | } | 1149 | } |
| 1143 | 1150 | ||
| 1144 | #ifdef CONFIG_COMPAT | 1151 | #ifdef CONFIG_COMPAT |
| @@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, | |||
| 1257 | 1264 | ||
| 1258 | static long fb_compat_ioctl(struct file *file, unsigned int cmd, | 1265 | static long fb_compat_ioctl(struct file *file, unsigned int cmd, |
| 1259 | unsigned long arg) | 1266 | unsigned long arg) |
| 1260 | __acquires(&info->lock) | ||
| 1261 | __releases(&info->lock) | ||
| 1262 | { | 1267 | { |
| 1263 | struct inode *inode = file->f_path.dentry->d_inode; | 1268 | struct inode *inode = file->f_path.dentry->d_inode; |
| 1264 | int fbidx = iminor(inode); | 1269 | int fbidx = iminor(inode); |
| @@ -1266,7 +1271,6 @@ __releases(&info->lock) | |||
| 1266 | struct fb_ops *fb = info->fbops; | 1271 | struct fb_ops *fb = info->fbops; |
| 1267 | long ret = -ENOIOCTLCMD; | 1272 | long ret = -ENOIOCTLCMD; |
| 1268 | 1273 | ||
| 1269 | mutex_lock(&info->lock); | ||
| 1270 | switch(cmd) { | 1274 | switch(cmd) { |
| 1271 | case FBIOGET_VSCREENINFO: | 1275 | case FBIOGET_VSCREENINFO: |
| 1272 | case FBIOPUT_VSCREENINFO: | 1276 | case FBIOPUT_VSCREENINFO: |
| @@ -1292,7 +1296,6 @@ __releases(&info->lock) | |||
| 1292 | ret = fb->fb_compat_ioctl(info, cmd, arg); | 1296 | ret = fb->fb_compat_ioctl(info, cmd, arg); |
| 1293 | break; | 1297 | break; |
| 1294 | } | 1298 | } |
| 1295 | mutex_unlock(&info->lock); | ||
| 1296 | return ret; | 1299 | return ret; |
| 1297 | } | 1300 | } |
| 1298 | #endif | 1301 | #endif |
