diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-12-13 06:19:05 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-12-13 06:19:05 -0500 |
commit | 3ed37d9aba486dece93e05d68f691b80ee100900 (patch) | |
tree | 3e391eb45694c948c608a9c5ce99bc2cc0b52164 /drivers/video/omap2/omapfb | |
parent | c7e1eae537652330cec3fbf5f8f50000b2f24269 (diff) |
Revert "OMAPFB: simplify locking"
This reverts commit b41deecbda70067b26a3a7704fdf967a7940935b.
The simpler locking causes huge latencies when two processes use the
omapfb, even if they use different framebuffers.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2/omapfb')
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-ioctl.c | 68 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 40 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-sysfs.c | 87 | ||||
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb.h | 16 |
4 files changed, 132 insertions, 79 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index dccb158b0d0b..d30b45d72649 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
@@ -85,6 +85,16 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
85 | goto out; | 85 | goto out; |
86 | } | 86 | } |
87 | 87 | ||
88 | /* Take the locks in a specific order to keep lockdep happy */ | ||
89 | if (old_rg->id < new_rg->id) { | ||
90 | omapfb_get_mem_region(old_rg); | ||
91 | omapfb_get_mem_region(new_rg); | ||
92 | } else if (new_rg->id < old_rg->id) { | ||
93 | omapfb_get_mem_region(new_rg); | ||
94 | omapfb_get_mem_region(old_rg); | ||
95 | } else | ||
96 | omapfb_get_mem_region(old_rg); | ||
97 | |||
88 | if (pi->enabled && !new_rg->size) { | 98 | if (pi->enabled && !new_rg->size) { |
89 | /* | 99 | /* |
90 | * This plane's memory was freed, can't enable it | 100 | * This plane's memory was freed, can't enable it |
@@ -136,6 +146,16 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
136 | goto undo; | 146 | goto undo; |
137 | } | 147 | } |
138 | 148 | ||
149 | /* Release the locks in a specific order to keep lockdep happy */ | ||
150 | if (old_rg->id > new_rg->id) { | ||
151 | omapfb_put_mem_region(old_rg); | ||
152 | omapfb_put_mem_region(new_rg); | ||
153 | } else if (new_rg->id > old_rg->id) { | ||
154 | omapfb_put_mem_region(new_rg); | ||
155 | omapfb_put_mem_region(old_rg); | ||
156 | } else | ||
157 | omapfb_put_mem_region(old_rg); | ||
158 | |||
139 | return 0; | 159 | return 0; |
140 | 160 | ||
141 | undo: | 161 | undo: |
@@ -146,6 +166,15 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
146 | 166 | ||
147 | ovl->set_overlay_info(ovl, &old_info); | 167 | ovl->set_overlay_info(ovl, &old_info); |
148 | put_mem: | 168 | put_mem: |
169 | /* Release the locks in a specific order to keep lockdep happy */ | ||
170 | if (old_rg->id > new_rg->id) { | ||
171 | omapfb_put_mem_region(old_rg); | ||
172 | omapfb_put_mem_region(new_rg); | ||
173 | } else if (new_rg->id > old_rg->id) { | ||
174 | omapfb_put_mem_region(new_rg); | ||
175 | omapfb_put_mem_region(old_rg); | ||
176 | } else | ||
177 | omapfb_put_mem_region(old_rg); | ||
149 | out: | 178 | out: |
150 | dev_err(fbdev->dev, "setup_plane failed\n"); | 179 | dev_err(fbdev->dev, "setup_plane failed\n"); |
151 | 180 | ||
@@ -195,10 +224,11 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
195 | if (display && display->driver->sync) | 224 | if (display && display->driver->sync) |
196 | display->driver->sync(display); | 225 | display->driver->sync(display); |
197 | 226 | ||
198 | mutex_lock(&fbi->mm_lock); | ||
199 | |||
200 | rg = ofbi->region; | 227 | rg = ofbi->region; |
201 | 228 | ||
229 | down_write_nested(&rg->lock, rg->id); | ||
230 | atomic_inc(&rg->lock_count); | ||
231 | |||
202 | if (rg->size == size && rg->type == mi->type) | 232 | if (rg->size == size && rg->type == mi->type) |
203 | goto out; | 233 | goto out; |
204 | 234 | ||
@@ -231,7 +261,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
231 | } | 261 | } |
232 | 262 | ||
233 | out: | 263 | out: |
234 | mutex_unlock(&fbi->mm_lock); | 264 | atomic_dec(&rg->lock_count); |
265 | up_write(&rg->lock); | ||
266 | |||
235 | return r; | 267 | return r; |
236 | } | 268 | } |
237 | 269 | ||
@@ -240,12 +272,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
240 | struct omapfb_info *ofbi = FB2OFB(fbi); | 272 | struct omapfb_info *ofbi = FB2OFB(fbi); |
241 | struct omapfb2_mem_region *rg; | 273 | struct omapfb2_mem_region *rg; |
242 | 274 | ||
243 | rg = ofbi->region; | 275 | rg = omapfb_get_mem_region(ofbi->region); |
244 | memset(mi, 0, sizeof(*mi)); | 276 | memset(mi, 0, sizeof(*mi)); |
245 | 277 | ||
246 | mi->size = rg->size; | 278 | mi->size = rg->size; |
247 | mi->type = rg->type; | 279 | mi->type = rg->type; |
248 | 280 | ||
281 | omapfb_put_mem_region(rg); | ||
282 | |||
249 | return 0; | 283 | return 0; |
250 | } | 284 | } |
251 | 285 | ||
@@ -284,10 +318,14 @@ int omapfb_set_update_mode(struct fb_info *fbi, | |||
284 | if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) | 318 | if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) |
285 | return -EINVAL; | 319 | return -EINVAL; |
286 | 320 | ||
321 | omapfb_lock(fbdev); | ||
322 | |||
287 | d = get_display_data(fbdev, display); | 323 | d = get_display_data(fbdev, display); |
288 | 324 | ||
289 | if (d->update_mode == mode) | 325 | if (d->update_mode == mode) { |
326 | omapfb_unlock(fbdev); | ||
290 | return 0; | 327 | return 0; |
328 | } | ||
291 | 329 | ||
292 | r = 0; | 330 | r = 0; |
293 | 331 | ||
@@ -303,6 +341,8 @@ int omapfb_set_update_mode(struct fb_info *fbi, | |||
303 | r = -EINVAL; | 341 | r = -EINVAL; |
304 | } | 342 | } |
305 | 343 | ||
344 | omapfb_unlock(fbdev); | ||
345 | |||
306 | return r; | 346 | return r; |
307 | } | 347 | } |
308 | 348 | ||
@@ -317,10 +357,14 @@ int omapfb_get_update_mode(struct fb_info *fbi, | |||
317 | if (!display) | 357 | if (!display) |
318 | return -EINVAL; | 358 | return -EINVAL; |
319 | 359 | ||
360 | omapfb_lock(fbdev); | ||
361 | |||
320 | d = get_display_data(fbdev, display); | 362 | d = get_display_data(fbdev, display); |
321 | 363 | ||
322 | *mode = d->update_mode; | 364 | *mode = d->update_mode; |
323 | 365 | ||
366 | omapfb_unlock(fbdev); | ||
367 | |||
324 | return 0; | 368 | return 0; |
325 | } | 369 | } |
326 | 370 | ||
@@ -380,10 +424,13 @@ static int omapfb_set_color_key(struct fb_info *fbi, | |||
380 | struct omapfb_color_key *ck) | 424 | struct omapfb_color_key *ck) |
381 | { | 425 | { |
382 | struct omapfb_info *ofbi = FB2OFB(fbi); | 426 | struct omapfb_info *ofbi = FB2OFB(fbi); |
427 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
383 | int r; | 428 | int r; |
384 | int i; | 429 | int i; |
385 | struct omap_overlay_manager *mgr = NULL; | 430 | struct omap_overlay_manager *mgr = NULL; |
386 | 431 | ||
432 | omapfb_lock(fbdev); | ||
433 | |||
387 | for (i = 0; i < ofbi->num_overlays; i++) { | 434 | for (i = 0; i < ofbi->num_overlays; i++) { |
388 | if (ofbi->overlays[i]->manager) { | 435 | if (ofbi->overlays[i]->manager) { |
389 | mgr = ofbi->overlays[i]->manager; | 436 | mgr = ofbi->overlays[i]->manager; |
@@ -398,6 +445,8 @@ static int omapfb_set_color_key(struct fb_info *fbi, | |||
398 | 445 | ||
399 | r = _omapfb_set_color_key(mgr, ck); | 446 | r = _omapfb_set_color_key(mgr, ck); |
400 | err: | 447 | err: |
448 | omapfb_unlock(fbdev); | ||
449 | |||
401 | return r; | 450 | return r; |
402 | } | 451 | } |
403 | 452 | ||
@@ -405,10 +454,13 @@ static int omapfb_get_color_key(struct fb_info *fbi, | |||
405 | struct omapfb_color_key *ck) | 454 | struct omapfb_color_key *ck) |
406 | { | 455 | { |
407 | struct omapfb_info *ofbi = FB2OFB(fbi); | 456 | struct omapfb_info *ofbi = FB2OFB(fbi); |
457 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
408 | struct omap_overlay_manager *mgr = NULL; | 458 | struct omap_overlay_manager *mgr = NULL; |
409 | int r = 0; | 459 | int r = 0; |
410 | int i; | 460 | int i; |
411 | 461 | ||
462 | omapfb_lock(fbdev); | ||
463 | |||
412 | for (i = 0; i < ofbi->num_overlays; i++) { | 464 | for (i = 0; i < ofbi->num_overlays; i++) { |
413 | if (ofbi->overlays[i]->manager) { | 465 | if (ofbi->overlays[i]->manager) { |
414 | mgr = ofbi->overlays[i]->manager; | 466 | mgr = ofbi->overlays[i]->manager; |
@@ -423,6 +475,8 @@ static int omapfb_get_color_key(struct fb_info *fbi, | |||
423 | 475 | ||
424 | *ck = omapfb_color_keys[mgr->id]; | 476 | *ck = omapfb_color_keys[mgr->id]; |
425 | err: | 477 | err: |
478 | omapfb_unlock(fbdev); | ||
479 | |||
426 | return r; | 480 | return r; |
427 | } | 481 | } |
428 | 482 | ||
@@ -549,8 +603,6 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
549 | 603 | ||
550 | int r = 0; | 604 | int r = 0; |
551 | 605 | ||
552 | omapfb_lock(fbdev); | ||
553 | |||
554 | switch (cmd) { | 606 | switch (cmd) { |
555 | case OMAPFB_SYNC_GFX: | 607 | case OMAPFB_SYNC_GFX: |
556 | DBG("ioctl SYNC_GFX\n"); | 608 | DBG("ioctl SYNC_GFX\n"); |
@@ -856,8 +908,6 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) | |||
856 | r = -EINVAL; | 908 | r = -EINVAL; |
857 | } | 909 | } |
858 | 910 | ||
859 | omapfb_unlock(fbdev); | ||
860 | |||
861 | if (r < 0) | 911 | if (r < 0) |
862 | DBG("ioctl failed: %d\n", r); | 912 | DBG("ioctl failed: %d\n", r); |
863 | 913 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 948dfb9f3e9b..ca585ef37f25 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -672,6 +672,8 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) | |||
672 | 672 | ||
673 | DBG("check_fb_var %d\n", ofbi->id); | 673 | DBG("check_fb_var %d\n", ofbi->id); |
674 | 674 | ||
675 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
676 | |||
675 | r = fb_mode_to_dss_mode(var, &mode); | 677 | r = fb_mode_to_dss_mode(var, &mode); |
676 | if (r) { | 678 | if (r) { |
677 | DBG("cannot convert var to omap dss mode\n"); | 679 | DBG("cannot convert var to omap dss mode\n"); |
@@ -853,6 +855,8 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
853 | int rotation = var->rotate; | 855 | int rotation = var->rotate; |
854 | int i; | 856 | int i; |
855 | 857 | ||
858 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
859 | |||
856 | for (i = 0; i < ofbi->num_overlays; i++) { | 860 | for (i = 0; i < ofbi->num_overlays; i++) { |
857 | if (ovl != ofbi->overlays[i]) | 861 | if (ovl != ofbi->overlays[i]) |
858 | continue; | 862 | continue; |
@@ -944,6 +948,8 @@ int omapfb_apply_changes(struct fb_info *fbi, int init) | |||
944 | fill_fb(fbi); | 948 | fill_fb(fbi); |
945 | #endif | 949 | #endif |
946 | 950 | ||
951 | WARN_ON(!atomic_read(&ofbi->region->lock_count)); | ||
952 | |||
947 | for (i = 0; i < ofbi->num_overlays; i++) { | 953 | for (i = 0; i < ofbi->num_overlays; i++) { |
948 | ovl = ofbi->overlays[i]; | 954 | ovl = ofbi->overlays[i]; |
949 | 955 | ||
@@ -1002,16 +1008,15 @@ err: | |||
1002 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | 1008 | static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) |
1003 | { | 1009 | { |
1004 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1010 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1005 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
1006 | int r; | 1011 | int r; |
1007 | 1012 | ||
1008 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); | 1013 | DBG("check_var(%d)\n", FB2OFB(fbi)->id); |
1009 | 1014 | ||
1010 | omapfb_lock(fbdev); | 1015 | omapfb_get_mem_region(ofbi->region); |
1011 | 1016 | ||
1012 | r = check_fb_var(fbi, var); | 1017 | r = check_fb_var(fbi, var); |
1013 | 1018 | ||
1014 | omapfb_unlock(fbdev); | 1019 | omapfb_put_mem_region(ofbi->region); |
1015 | 1020 | ||
1016 | return r; | 1021 | return r; |
1017 | } | 1022 | } |
@@ -1020,12 +1025,11 @@ static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | |||
1020 | static int omapfb_set_par(struct fb_info *fbi) | 1025 | static int omapfb_set_par(struct fb_info *fbi) |
1021 | { | 1026 | { |
1022 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1027 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1023 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
1024 | int r; | 1028 | int r; |
1025 | 1029 | ||
1026 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); | 1030 | DBG("set_par(%d)\n", FB2OFB(fbi)->id); |
1027 | 1031 | ||
1028 | omapfb_lock(fbdev); | 1032 | omapfb_get_mem_region(ofbi->region); |
1029 | 1033 | ||
1030 | set_fb_fix(fbi); | 1034 | set_fb_fix(fbi); |
1031 | 1035 | ||
@@ -1036,7 +1040,7 @@ static int omapfb_set_par(struct fb_info *fbi) | |||
1036 | r = omapfb_apply_changes(fbi, 0); | 1040 | r = omapfb_apply_changes(fbi, 0); |
1037 | 1041 | ||
1038 | out: | 1042 | out: |
1039 | omapfb_unlock(fbdev); | 1043 | omapfb_put_mem_region(ofbi->region); |
1040 | 1044 | ||
1041 | return r; | 1045 | return r; |
1042 | } | 1046 | } |
@@ -1045,7 +1049,6 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var, | |||
1045 | struct fb_info *fbi) | 1049 | struct fb_info *fbi) |
1046 | { | 1050 | { |
1047 | struct omapfb_info *ofbi = FB2OFB(fbi); | 1051 | struct omapfb_info *ofbi = FB2OFB(fbi); |
1048 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
1049 | struct fb_var_screeninfo new_var; | 1052 | struct fb_var_screeninfo new_var; |
1050 | int r; | 1053 | int r; |
1051 | 1054 | ||
@@ -1061,11 +1064,11 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var, | |||
1061 | 1064 | ||
1062 | fbi->var = new_var; | 1065 | fbi->var = new_var; |
1063 | 1066 | ||
1064 | omapfb_lock(fbdev); | 1067 | omapfb_get_mem_region(ofbi->region); |
1065 | 1068 | ||
1066 | r = omapfb_apply_changes(fbi, 0); | 1069 | r = omapfb_apply_changes(fbi, 0); |
1067 | 1070 | ||
1068 | omapfb_unlock(fbdev); | 1071 | omapfb_put_mem_region(ofbi->region); |
1069 | 1072 | ||
1070 | return r; | 1073 | return r; |
1071 | } | 1074 | } |
@@ -1074,14 +1077,18 @@ static void mmap_user_open(struct vm_area_struct *vma) | |||
1074 | { | 1077 | { |
1075 | struct omapfb2_mem_region *rg = vma->vm_private_data; | 1078 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1076 | 1079 | ||
1080 | omapfb_get_mem_region(rg); | ||
1077 | atomic_inc(&rg->map_count); | 1081 | atomic_inc(&rg->map_count); |
1082 | omapfb_put_mem_region(rg); | ||
1078 | } | 1083 | } |
1079 | 1084 | ||
1080 | static void mmap_user_close(struct vm_area_struct *vma) | 1085 | static void mmap_user_close(struct vm_area_struct *vma) |
1081 | { | 1086 | { |
1082 | struct omapfb2_mem_region *rg = vma->vm_private_data; | 1087 | struct omapfb2_mem_region *rg = vma->vm_private_data; |
1083 | 1088 | ||
1089 | omapfb_get_mem_region(rg); | ||
1084 | atomic_dec(&rg->map_count); | 1090 | atomic_dec(&rg->map_count); |
1091 | omapfb_put_mem_region(rg); | ||
1085 | } | 1092 | } |
1086 | 1093 | ||
1087 | static struct vm_operations_struct mmap_user_ops = { | 1094 | static struct vm_operations_struct mmap_user_ops = { |
@@ -1105,7 +1112,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1105 | return -EINVAL; | 1112 | return -EINVAL; |
1106 | off = vma->vm_pgoff << PAGE_SHIFT; | 1113 | off = vma->vm_pgoff << PAGE_SHIFT; |
1107 | 1114 | ||
1108 | rg = ofbi->region; | 1115 | rg = omapfb_get_mem_region(ofbi->region); |
1109 | 1116 | ||
1110 | start = omapfb_get_region_paddr(ofbi); | 1117 | start = omapfb_get_region_paddr(ofbi); |
1111 | len = fix->smem_len; | 1118 | len = fix->smem_len; |
@@ -1133,9 +1140,13 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
1133 | /* vm_ops.open won't be called for mmap itself. */ | 1140 | /* vm_ops.open won't be called for mmap itself. */ |
1134 | atomic_inc(&rg->map_count); | 1141 | atomic_inc(&rg->map_count); |
1135 | 1142 | ||
1143 | omapfb_put_mem_region(rg); | ||
1144 | |||
1136 | return 0; | 1145 | return 0; |
1137 | 1146 | ||
1138 | error: | 1147 | error: |
1148 | omapfb_put_mem_region(ofbi->region); | ||
1149 | |||
1139 | return r; | 1150 | return r; |
1140 | } | 1151 | } |
1141 | 1152 | ||
@@ -1902,6 +1913,7 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1902 | 1913 | ||
1903 | ofbi->region = &fbdev->regions[i]; | 1914 | ofbi->region = &fbdev->regions[i]; |
1904 | ofbi->region->id = i; | 1915 | ofbi->region->id = i; |
1916 | init_rwsem(&ofbi->region->lock); | ||
1905 | 1917 | ||
1906 | /* assign these early, so that fb alloc can use them */ | 1918 | /* assign these early, so that fb alloc can use them */ |
1907 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : | 1919 | ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : |
@@ -1933,8 +1945,12 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1933 | /* setup fb_infos */ | 1945 | /* setup fb_infos */ |
1934 | for (i = 0; i < fbdev->num_fbs; i++) { | 1946 | for (i = 0; i < fbdev->num_fbs; i++) { |
1935 | struct fb_info *fbi = fbdev->fbs[i]; | 1947 | struct fb_info *fbi = fbdev->fbs[i]; |
1948 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1936 | 1949 | ||
1950 | omapfb_get_mem_region(ofbi->region); | ||
1937 | r = omapfb_fb_init(fbdev, fbi); | 1951 | r = omapfb_fb_init(fbdev, fbi); |
1952 | omapfb_put_mem_region(ofbi->region); | ||
1953 | |||
1938 | if (r) { | 1954 | if (r) { |
1939 | dev_err(fbdev->dev, "failed to setup fb_info\n"); | 1955 | dev_err(fbdev->dev, "failed to setup fb_info\n"); |
1940 | return r; | 1956 | return r; |
@@ -1966,8 +1982,12 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) | |||
1966 | 1982 | ||
1967 | for (i = 0; i < fbdev->num_fbs; i++) { | 1983 | for (i = 0; i < fbdev->num_fbs; i++) { |
1968 | struct fb_info *fbi = fbdev->fbs[i]; | 1984 | struct fb_info *fbi = fbdev->fbs[i]; |
1985 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
1969 | 1986 | ||
1987 | omapfb_get_mem_region(ofbi->region); | ||
1970 | r = omapfb_apply_changes(fbi, 1); | 1988 | r = omapfb_apply_changes(fbi, 1); |
1989 | omapfb_put_mem_region(ofbi->region); | ||
1990 | |||
1971 | if (r) { | 1991 | if (r) { |
1972 | dev_err(fbdev->dev, "failed to change mode\n"); | 1992 | dev_err(fbdev->dev, "failed to change mode\n"); |
1973 | return r; | 1993 | return r; |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index be5eb074b7d3..18fa9e1d0033 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
@@ -49,7 +49,6 @@ static ssize_t store_rotate_type(struct device *dev, | |||
49 | { | 49 | { |
50 | struct fb_info *fbi = dev_get_drvdata(dev); | 50 | struct fb_info *fbi = dev_get_drvdata(dev); |
51 | struct omapfb_info *ofbi = FB2OFB(fbi); | 51 | struct omapfb_info *ofbi = FB2OFB(fbi); |
52 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
53 | struct omapfb2_mem_region *rg; | 52 | struct omapfb2_mem_region *rg; |
54 | int rot_type; | 53 | int rot_type; |
55 | int r; | 54 | int r; |
@@ -63,13 +62,12 @@ static ssize_t store_rotate_type(struct device *dev, | |||
63 | 62 | ||
64 | if (!lock_fb_info(fbi)) | 63 | if (!lock_fb_info(fbi)) |
65 | return -ENODEV; | 64 | return -ENODEV; |
66 | omapfb_lock(fbdev); | ||
67 | 65 | ||
68 | r = 0; | 66 | r = 0; |
69 | if (rot_type == ofbi->rotation_type) | 67 | if (rot_type == ofbi->rotation_type) |
70 | goto out; | 68 | goto out; |
71 | 69 | ||
72 | rg = ofbi->region; | 70 | rg = omapfb_get_mem_region(ofbi->region); |
73 | 71 | ||
74 | if (rg->size) { | 72 | if (rg->size) { |
75 | r = -EBUSY; | 73 | r = -EBUSY; |
@@ -83,8 +81,8 @@ static ssize_t store_rotate_type(struct device *dev, | |||
83 | * need to do any further parameter checking at this point. | 81 | * need to do any further parameter checking at this point. |
84 | */ | 82 | */ |
85 | put_region: | 83 | put_region: |
84 | omapfb_put_mem_region(rg); | ||
86 | out: | 85 | out: |
87 | omapfb_unlock(fbdev); | ||
88 | unlock_fb_info(fbi); | 86 | unlock_fb_info(fbi); |
89 | 87 | ||
90 | return r ? r : count; | 88 | return r ? r : count; |
@@ -106,7 +104,6 @@ static ssize_t store_mirror(struct device *dev, | |||
106 | { | 104 | { |
107 | struct fb_info *fbi = dev_get_drvdata(dev); | 105 | struct fb_info *fbi = dev_get_drvdata(dev); |
108 | struct omapfb_info *ofbi = FB2OFB(fbi); | 106 | struct omapfb_info *ofbi = FB2OFB(fbi); |
109 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
110 | bool mirror; | 107 | bool mirror; |
111 | int r; | 108 | int r; |
112 | struct fb_var_screeninfo new_var; | 109 | struct fb_var_screeninfo new_var; |
@@ -117,10 +114,11 @@ static ssize_t store_mirror(struct device *dev, | |||
117 | 114 | ||
118 | if (!lock_fb_info(fbi)) | 115 | if (!lock_fb_info(fbi)) |
119 | return -ENODEV; | 116 | return -ENODEV; |
120 | omapfb_lock(fbdev); | ||
121 | 117 | ||
122 | ofbi->mirror = mirror; | 118 | ofbi->mirror = mirror; |
123 | 119 | ||
120 | omapfb_get_mem_region(ofbi->region); | ||
121 | |||
124 | memcpy(&new_var, &fbi->var, sizeof(new_var)); | 122 | memcpy(&new_var, &fbi->var, sizeof(new_var)); |
125 | r = check_fb_var(fbi, &new_var); | 123 | r = check_fb_var(fbi, &new_var); |
126 | if (r) | 124 | if (r) |
@@ -135,7 +133,8 @@ static ssize_t store_mirror(struct device *dev, | |||
135 | 133 | ||
136 | r = count; | 134 | r = count; |
137 | out: | 135 | out: |
138 | omapfb_unlock(fbdev); | 136 | omapfb_put_mem_region(ofbi->region); |
137 | |||
139 | unlock_fb_info(fbi); | 138 | unlock_fb_info(fbi); |
140 | 139 | ||
141 | return r; | 140 | return r; |
@@ -274,11 +273,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
274 | 273 | ||
275 | DBG("detaching %d\n", ofbi->overlays[i]->id); | 274 | DBG("detaching %d\n", ofbi->overlays[i]->id); |
276 | 275 | ||
276 | omapfb_get_mem_region(ofbi->region); | ||
277 | |||
277 | omapfb_overlay_enable(ovl, 0); | 278 | omapfb_overlay_enable(ovl, 0); |
278 | 279 | ||
279 | if (ovl->manager) | 280 | if (ovl->manager) |
280 | ovl->manager->apply(ovl->manager); | 281 | ovl->manager->apply(ovl->manager); |
281 | 282 | ||
283 | omapfb_put_mem_region(ofbi->region); | ||
284 | |||
282 | for (t = i + 1; t < ofbi->num_overlays; t++) { | 285 | for (t = i + 1; t < ofbi->num_overlays; t++) { |
283 | ofbi->rotation[t-1] = ofbi->rotation[t]; | 286 | ofbi->rotation[t-1] = ofbi->rotation[t]; |
284 | ofbi->overlays[t-1] = ofbi->overlays[t]; | 287 | ofbi->overlays[t-1] = ofbi->overlays[t]; |
@@ -311,8 +314,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, | |||
311 | } | 314 | } |
312 | 315 | ||
313 | if (added) { | 316 | if (added) { |
317 | omapfb_get_mem_region(ofbi->region); | ||
318 | |||
314 | r = omapfb_apply_changes(fbi, 0); | 319 | r = omapfb_apply_changes(fbi, 0); |
315 | 320 | ||
321 | omapfb_put_mem_region(ofbi->region); | ||
322 | |||
316 | if (r) | 323 | if (r) |
317 | goto out; | 324 | goto out; |
318 | } | 325 | } |
@@ -330,13 +337,11 @@ static ssize_t show_overlays_rotate(struct device *dev, | |||
330 | { | 337 | { |
331 | struct fb_info *fbi = dev_get_drvdata(dev); | 338 | struct fb_info *fbi = dev_get_drvdata(dev); |
332 | struct omapfb_info *ofbi = FB2OFB(fbi); | 339 | struct omapfb_info *ofbi = FB2OFB(fbi); |
333 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
334 | ssize_t l = 0; | 340 | ssize_t l = 0; |
335 | int t; | 341 | int t; |
336 | 342 | ||
337 | if (!lock_fb_info(fbi)) | 343 | if (!lock_fb_info(fbi)) |
338 | return -ENODEV; | 344 | return -ENODEV; |
339 | omapfb_lock(fbdev); | ||
340 | 345 | ||
341 | for (t = 0; t < ofbi->num_overlays; t++) { | 346 | for (t = 0; t < ofbi->num_overlays; t++) { |
342 | l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", | 347 | l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", |
@@ -345,7 +350,6 @@ static ssize_t show_overlays_rotate(struct device *dev, | |||
345 | 350 | ||
346 | l += snprintf(buf + l, PAGE_SIZE - l, "\n"); | 351 | l += snprintf(buf + l, PAGE_SIZE - l, "\n"); |
347 | 352 | ||
348 | omapfb_unlock(fbdev); | ||
349 | unlock_fb_info(fbi); | 353 | unlock_fb_info(fbi); |
350 | 354 | ||
351 | return l; | 355 | return l; |
@@ -356,7 +360,6 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
356 | { | 360 | { |
357 | struct fb_info *fbi = dev_get_drvdata(dev); | 361 | struct fb_info *fbi = dev_get_drvdata(dev); |
358 | struct omapfb_info *ofbi = FB2OFB(fbi); | 362 | struct omapfb_info *ofbi = FB2OFB(fbi); |
359 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
360 | int num_ovls = 0, r, i; | 363 | int num_ovls = 0, r, i; |
361 | int len; | 364 | int len; |
362 | bool changed = false; | 365 | bool changed = false; |
@@ -368,7 +371,6 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
368 | 371 | ||
369 | if (!lock_fb_info(fbi)) | 372 | if (!lock_fb_info(fbi)) |
370 | return -ENODEV; | 373 | return -ENODEV; |
371 | omapfb_lock(fbdev); | ||
372 | 374 | ||
373 | if (len > 0) { | 375 | if (len > 0) { |
374 | char *p = (char *)buf; | 376 | char *p = (char *)buf; |
@@ -405,7 +407,12 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
405 | for (i = 0; i < num_ovls; ++i) | 407 | for (i = 0; i < num_ovls; ++i) |
406 | ofbi->rotation[i] = rotation[i]; | 408 | ofbi->rotation[i] = rotation[i]; |
407 | 409 | ||
410 | omapfb_get_mem_region(ofbi->region); | ||
411 | |||
408 | r = omapfb_apply_changes(fbi, 0); | 412 | r = omapfb_apply_changes(fbi, 0); |
413 | |||
414 | omapfb_put_mem_region(ofbi->region); | ||
415 | |||
409 | if (r) | 416 | if (r) |
410 | goto out; | 417 | goto out; |
411 | 418 | ||
@@ -414,7 +421,6 @@ static ssize_t store_overlays_rotate(struct device *dev, | |||
414 | 421 | ||
415 | r = count; | 422 | r = count; |
416 | out: | 423 | out: |
417 | omapfb_unlock(fbdev); | ||
418 | unlock_fb_info(fbi); | 424 | unlock_fb_info(fbi); |
419 | 425 | ||
420 | return r; | 426 | return r; |
@@ -425,19 +431,8 @@ static ssize_t show_size(struct device *dev, | |||
425 | { | 431 | { |
426 | struct fb_info *fbi = dev_get_drvdata(dev); | 432 | struct fb_info *fbi = dev_get_drvdata(dev); |
427 | struct omapfb_info *ofbi = FB2OFB(fbi); | 433 | struct omapfb_info *ofbi = FB2OFB(fbi); |
428 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
429 | int r; | ||
430 | 434 | ||
431 | if (!lock_fb_info(fbi)) | 435 | return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); |
432 | return -ENODEV; | ||
433 | omapfb_lock(fbdev); | ||
434 | |||
435 | r = snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); | ||
436 | |||
437 | omapfb_unlock(fbdev); | ||
438 | unlock_fb_info(fbi); | ||
439 | |||
440 | return r; | ||
441 | } | 436 | } |
442 | 437 | ||
443 | static ssize_t store_size(struct device *dev, struct device_attribute *attr, | 438 | static ssize_t store_size(struct device *dev, struct device_attribute *attr, |
@@ -460,15 +455,15 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
460 | 455 | ||
461 | if (!lock_fb_info(fbi)) | 456 | if (!lock_fb_info(fbi)) |
462 | return -ENODEV; | 457 | return -ENODEV; |
463 | omapfb_lock(fbdev); | ||
464 | 458 | ||
465 | if (display && display->driver->sync) | 459 | if (display && display->driver->sync) |
466 | display->driver->sync(display); | 460 | display->driver->sync(display); |
467 | 461 | ||
468 | mutex_lock(&fbi->mm_lock); | ||
469 | |||
470 | rg = ofbi->region; | 462 | rg = ofbi->region; |
471 | 463 | ||
464 | down_write_nested(&rg->lock, rg->id); | ||
465 | atomic_inc(&rg->lock_count); | ||
466 | |||
472 | if (atomic_read(&rg->map_count)) { | 467 | if (atomic_read(&rg->map_count)) { |
473 | r = -EBUSY; | 468 | r = -EBUSY; |
474 | goto out; | 469 | goto out; |
@@ -501,8 +496,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, | |||
501 | 496 | ||
502 | r = count; | 497 | r = count; |
503 | out: | 498 | out: |
504 | mutex_unlock(&fbi->mm_lock); | 499 | atomic_dec(&rg->lock_count); |
505 | omapfb_unlock(fbdev); | 500 | up_write(&rg->lock); |
501 | |||
506 | unlock_fb_info(fbi); | 502 | unlock_fb_info(fbi); |
507 | 503 | ||
508 | return r; | 504 | return r; |
@@ -513,19 +509,8 @@ static ssize_t show_phys(struct device *dev, | |||
513 | { | 509 | { |
514 | struct fb_info *fbi = dev_get_drvdata(dev); | 510 | struct fb_info *fbi = dev_get_drvdata(dev); |
515 | struct omapfb_info *ofbi = FB2OFB(fbi); | 511 | struct omapfb_info *ofbi = FB2OFB(fbi); |
516 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
517 | int r; | ||
518 | 512 | ||
519 | if (!lock_fb_info(fbi)) | 513 | return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); |
520 | return -ENODEV; | ||
521 | omapfb_lock(fbdev); | ||
522 | |||
523 | r = snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); | ||
524 | |||
525 | omapfb_unlock(fbdev); | ||
526 | unlock_fb_info(fbi); | ||
527 | |||
528 | return r; | ||
529 | } | 514 | } |
530 | 515 | ||
531 | static ssize_t show_virt(struct device *dev, | 516 | static ssize_t show_virt(struct device *dev, |
@@ -541,20 +526,11 @@ static ssize_t show_upd_mode(struct device *dev, | |||
541 | struct device_attribute *attr, char *buf) | 526 | struct device_attribute *attr, char *buf) |
542 | { | 527 | { |
543 | struct fb_info *fbi = dev_get_drvdata(dev); | 528 | struct fb_info *fbi = dev_get_drvdata(dev); |
544 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
545 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
546 | enum omapfb_update_mode mode; | 529 | enum omapfb_update_mode mode; |
547 | int r; | 530 | int r; |
548 | 531 | ||
549 | if (!lock_fb_info(fbi)) | ||
550 | return -ENODEV; | ||
551 | omapfb_lock(fbdev); | ||
552 | |||
553 | r = omapfb_get_update_mode(fbi, &mode); | 532 | r = omapfb_get_update_mode(fbi, &mode); |
554 | 533 | ||
555 | omapfb_unlock(fbdev); | ||
556 | unlock_fb_info(fbi); | ||
557 | |||
558 | if (r) | 534 | if (r) |
559 | return r; | 535 | return r; |
560 | 536 | ||
@@ -565,8 +541,6 @@ static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr, | |||
565 | const char *buf, size_t count) | 541 | const char *buf, size_t count) |
566 | { | 542 | { |
567 | struct fb_info *fbi = dev_get_drvdata(dev); | 543 | struct fb_info *fbi = dev_get_drvdata(dev); |
568 | struct omapfb_info *ofbi = FB2OFB(fbi); | ||
569 | struct omapfb2_device *fbdev = ofbi->fbdev; | ||
570 | unsigned mode; | 544 | unsigned mode; |
571 | int r; | 545 | int r; |
572 | 546 | ||
@@ -574,17 +548,10 @@ static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr, | |||
574 | if (r) | 548 | if (r) |
575 | return r; | 549 | return r; |
576 | 550 | ||
577 | if (!lock_fb_info(fbi)) | ||
578 | return -ENODEV; | ||
579 | omapfb_lock(fbdev); | ||
580 | |||
581 | r = omapfb_set_update_mode(fbi, mode); | 551 | r = omapfb_set_update_mode(fbi, mode); |
582 | if (r) | 552 | if (r) |
583 | return r; | 553 | return r; |
584 | 554 | ||
585 | omapfb_unlock(fbdev); | ||
586 | unlock_fb_info(fbi); | ||
587 | |||
588 | return count; | 555 | return count; |
589 | } | 556 | } |
590 | 557 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 2b5264475ed4..623cd872a367 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h | |||
@@ -62,6 +62,8 @@ struct omapfb2_mem_region { | |||
62 | bool alloc; /* allocated by the driver */ | 62 | bool alloc; /* allocated by the driver */ |
63 | bool map; /* kernel mapped by the driver */ | 63 | bool map; /* kernel mapped by the driver */ |
64 | atomic_t map_count; | 64 | atomic_t map_count; |
65 | struct rw_semaphore lock; | ||
66 | atomic_t lock_count; | ||
65 | }; | 67 | }; |
66 | 68 | ||
67 | /* appended to fb_info */ | 69 | /* appended to fb_info */ |
@@ -189,4 +191,18 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl, | |||
189 | return ovl->disable(ovl); | 191 | return ovl->disable(ovl); |
190 | } | 192 | } |
191 | 193 | ||
194 | static inline struct omapfb2_mem_region * | ||
195 | omapfb_get_mem_region(struct omapfb2_mem_region *rg) | ||
196 | { | ||
197 | down_read_nested(&rg->lock, rg->id); | ||
198 | atomic_inc(&rg->lock_count); | ||
199 | return rg; | ||
200 | } | ||
201 | |||
202 | static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg) | ||
203 | { | ||
204 | atomic_dec(&rg->lock_count); | ||
205 | up_read(&rg->lock); | ||
206 | } | ||
207 | |||
192 | #endif | 208 | #endif |