aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2/omapfb/omapfb-sysfs.c
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-12-04 07:55:18 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-12-07 09:55:03 -0500
commitb41deecbda70067b26a3a7704fdf967a7940935b (patch)
tree5d609dc0469c58a29f18cd8e3eb427e427e9cca3 /drivers/video/omap2/omapfb/omapfb-sysfs.c
parent636f4e1b45c6204c6912cefa2bdbe22e00784a43 (diff)
OMAPFB: simplify locking
Kernel lock verification code has lately detected possible circular locking in omapfb. The exact problem is unclear, but omapfb's current locking seems to be overly complex. This patch simplifies the locking in the following ways: - Remove explicit omapfb mem region locking. I couldn't figure out the need for this, as long as we take care to take omapfb lock. - Get omapfb lock always, even if the operation is possibly only related to one fb_info. Better safe than sorry, and normally there's only one user for the fb so this shouldn't matter. - Make sure fb_info lock is taken first, then omapfb lock. With this patch the warnings about possible circular locking does not happen anymore. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Diffstat (limited to 'drivers/video/omap2/omapfb/omapfb-sysfs.c')
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c87
1 files changed, 60 insertions, 27 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 18fa9e1d0033..be5eb074b7d3 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -49,6 +49,7 @@ 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;
52 struct omapfb2_mem_region *rg; 53 struct omapfb2_mem_region *rg;
53 int rot_type; 54 int rot_type;
54 int r; 55 int r;
@@ -62,12 +63,13 @@ static ssize_t store_rotate_type(struct device *dev,
62 63
63 if (!lock_fb_info(fbi)) 64 if (!lock_fb_info(fbi))
64 return -ENODEV; 65 return -ENODEV;
66 omapfb_lock(fbdev);
65 67
66 r = 0; 68 r = 0;
67 if (rot_type == ofbi->rotation_type) 69 if (rot_type == ofbi->rotation_type)
68 goto out; 70 goto out;
69 71
70 rg = omapfb_get_mem_region(ofbi->region); 72 rg = ofbi->region;
71 73
72 if (rg->size) { 74 if (rg->size) {
73 r = -EBUSY; 75 r = -EBUSY;
@@ -81,8 +83,8 @@ static ssize_t store_rotate_type(struct device *dev,
81 * need to do any further parameter checking at this point. 83 * need to do any further parameter checking at this point.
82 */ 84 */
83put_region: 85put_region:
84 omapfb_put_mem_region(rg);
85out: 86out:
87 omapfb_unlock(fbdev);
86 unlock_fb_info(fbi); 88 unlock_fb_info(fbi);
87 89
88 return r ? r : count; 90 return r ? r : count;
@@ -104,6 +106,7 @@ static ssize_t store_mirror(struct device *dev,
104{ 106{
105 struct fb_info *fbi = dev_get_drvdata(dev); 107 struct fb_info *fbi = dev_get_drvdata(dev);
106 struct omapfb_info *ofbi = FB2OFB(fbi); 108 struct omapfb_info *ofbi = FB2OFB(fbi);
109 struct omapfb2_device *fbdev = ofbi->fbdev;
107 bool mirror; 110 bool mirror;
108 int r; 111 int r;
109 struct fb_var_screeninfo new_var; 112 struct fb_var_screeninfo new_var;
@@ -114,11 +117,10 @@ static ssize_t store_mirror(struct device *dev,
114 117
115 if (!lock_fb_info(fbi)) 118 if (!lock_fb_info(fbi))
116 return -ENODEV; 119 return -ENODEV;
120 omapfb_lock(fbdev);
117 121
118 ofbi->mirror = mirror; 122 ofbi->mirror = mirror;
119 123
120 omapfb_get_mem_region(ofbi->region);
121
122 memcpy(&new_var, &fbi->var, sizeof(new_var)); 124 memcpy(&new_var, &fbi->var, sizeof(new_var));
123 r = check_fb_var(fbi, &new_var); 125 r = check_fb_var(fbi, &new_var);
124 if (r) 126 if (r)
@@ -133,8 +135,7 @@ static ssize_t store_mirror(struct device *dev,
133 135
134 r = count; 136 r = count;
135out: 137out:
136 omapfb_put_mem_region(ofbi->region); 138 omapfb_unlock(fbdev);
137
138 unlock_fb_info(fbi); 139 unlock_fb_info(fbi);
139 140
140 return r; 141 return r;
@@ -273,15 +274,11 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
273 274
274 DBG("detaching %d\n", ofbi->overlays[i]->id); 275 DBG("detaching %d\n", ofbi->overlays[i]->id);
275 276
276 omapfb_get_mem_region(ofbi->region);
277
278 omapfb_overlay_enable(ovl, 0); 277 omapfb_overlay_enable(ovl, 0);
279 278
280 if (ovl->manager) 279 if (ovl->manager)
281 ovl->manager->apply(ovl->manager); 280 ovl->manager->apply(ovl->manager);
282 281
283 omapfb_put_mem_region(ofbi->region);
284
285 for (t = i + 1; t < ofbi->num_overlays; t++) { 282 for (t = i + 1; t < ofbi->num_overlays; t++) {
286 ofbi->rotation[t-1] = ofbi->rotation[t]; 283 ofbi->rotation[t-1] = ofbi->rotation[t];
287 ofbi->overlays[t-1] = ofbi->overlays[t]; 284 ofbi->overlays[t-1] = ofbi->overlays[t];
@@ -314,12 +311,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
314 } 311 }
315 312
316 if (added) { 313 if (added) {
317 omapfb_get_mem_region(ofbi->region);
318
319 r = omapfb_apply_changes(fbi, 0); 314 r = omapfb_apply_changes(fbi, 0);
320 315
321 omapfb_put_mem_region(ofbi->region);
322
323 if (r) 316 if (r)
324 goto out; 317 goto out;
325 } 318 }
@@ -337,11 +330,13 @@ static ssize_t show_overlays_rotate(struct device *dev,
337{ 330{
338 struct fb_info *fbi = dev_get_drvdata(dev); 331 struct fb_info *fbi = dev_get_drvdata(dev);
339 struct omapfb_info *ofbi = FB2OFB(fbi); 332 struct omapfb_info *ofbi = FB2OFB(fbi);
333 struct omapfb2_device *fbdev = ofbi->fbdev;
340 ssize_t l = 0; 334 ssize_t l = 0;
341 int t; 335 int t;
342 336
343 if (!lock_fb_info(fbi)) 337 if (!lock_fb_info(fbi))
344 return -ENODEV; 338 return -ENODEV;
339 omapfb_lock(fbdev);
345 340
346 for (t = 0; t < ofbi->num_overlays; t++) { 341 for (t = 0; t < ofbi->num_overlays; t++) {
347 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", 342 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
@@ -350,6 +345,7 @@ static ssize_t show_overlays_rotate(struct device *dev,
350 345
351 l += snprintf(buf + l, PAGE_SIZE - l, "\n"); 346 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
352 347
348 omapfb_unlock(fbdev);
353 unlock_fb_info(fbi); 349 unlock_fb_info(fbi);
354 350
355 return l; 351 return l;
@@ -360,6 +356,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
360{ 356{
361 struct fb_info *fbi = dev_get_drvdata(dev); 357 struct fb_info *fbi = dev_get_drvdata(dev);
362 struct omapfb_info *ofbi = FB2OFB(fbi); 358 struct omapfb_info *ofbi = FB2OFB(fbi);
359 struct omapfb2_device *fbdev = ofbi->fbdev;
363 int num_ovls = 0, r, i; 360 int num_ovls = 0, r, i;
364 int len; 361 int len;
365 bool changed = false; 362 bool changed = false;
@@ -371,6 +368,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
371 368
372 if (!lock_fb_info(fbi)) 369 if (!lock_fb_info(fbi))
373 return -ENODEV; 370 return -ENODEV;
371 omapfb_lock(fbdev);
374 372
375 if (len > 0) { 373 if (len > 0) {
376 char *p = (char *)buf; 374 char *p = (char *)buf;
@@ -407,12 +405,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
407 for (i = 0; i < num_ovls; ++i) 405 for (i = 0; i < num_ovls; ++i)
408 ofbi->rotation[i] = rotation[i]; 406 ofbi->rotation[i] = rotation[i];
409 407
410 omapfb_get_mem_region(ofbi->region);
411
412 r = omapfb_apply_changes(fbi, 0); 408 r = omapfb_apply_changes(fbi, 0);
413
414 omapfb_put_mem_region(ofbi->region);
415
416 if (r) 409 if (r)
417 goto out; 410 goto out;
418 411
@@ -421,6 +414,7 @@ static ssize_t store_overlays_rotate(struct device *dev,
421 414
422 r = count; 415 r = count;
423out: 416out:
417 omapfb_unlock(fbdev);
424 unlock_fb_info(fbi); 418 unlock_fb_info(fbi);
425 419
426 return r; 420 return r;
@@ -431,8 +425,19 @@ static ssize_t show_size(struct device *dev,
431{ 425{
432 struct fb_info *fbi = dev_get_drvdata(dev); 426 struct fb_info *fbi = dev_get_drvdata(dev);
433 struct omapfb_info *ofbi = FB2OFB(fbi); 427 struct omapfb_info *ofbi = FB2OFB(fbi);
428 struct omapfb2_device *fbdev = ofbi->fbdev;
429 int r;
434 430
435 return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); 431 if (!lock_fb_info(fbi))
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;
436} 441}
437 442
438static ssize_t store_size(struct device *dev, struct device_attribute *attr, 443static ssize_t store_size(struct device *dev, struct device_attribute *attr,
@@ -455,14 +460,14 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
455 460
456 if (!lock_fb_info(fbi)) 461 if (!lock_fb_info(fbi))
457 return -ENODEV; 462 return -ENODEV;
463 omapfb_lock(fbdev);
458 464
459 if (display && display->driver->sync) 465 if (display && display->driver->sync)
460 display->driver->sync(display); 466 display->driver->sync(display);
461 467
462 rg = ofbi->region; 468 mutex_lock(&fbi->mm_lock);
463 469
464 down_write_nested(&rg->lock, rg->id); 470 rg = ofbi->region;
465 atomic_inc(&rg->lock_count);
466 471
467 if (atomic_read(&rg->map_count)) { 472 if (atomic_read(&rg->map_count)) {
468 r = -EBUSY; 473 r = -EBUSY;
@@ -496,9 +501,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
496 501
497 r = count; 502 r = count;
498out: 503out:
499 atomic_dec(&rg->lock_count); 504 mutex_unlock(&fbi->mm_lock);
500 up_write(&rg->lock); 505 omapfb_unlock(fbdev);
501
502 unlock_fb_info(fbi); 506 unlock_fb_info(fbi);
503 507
504 return r; 508 return r;
@@ -509,8 +513,19 @@ static ssize_t show_phys(struct device *dev,
509{ 513{
510 struct fb_info *fbi = dev_get_drvdata(dev); 514 struct fb_info *fbi = dev_get_drvdata(dev);
511 struct omapfb_info *ofbi = FB2OFB(fbi); 515 struct omapfb_info *ofbi = FB2OFB(fbi);
516 struct omapfb2_device *fbdev = ofbi->fbdev;
517 int r;
512 518
513 return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); 519 if (!lock_fb_info(fbi))
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;
514} 529}
515 530
516static ssize_t show_virt(struct device *dev, 531static ssize_t show_virt(struct device *dev,
@@ -526,11 +541,20 @@ static ssize_t show_upd_mode(struct device *dev,
526 struct device_attribute *attr, char *buf) 541 struct device_attribute *attr, char *buf)
527{ 542{
528 struct fb_info *fbi = dev_get_drvdata(dev); 543 struct fb_info *fbi = dev_get_drvdata(dev);
544 struct omapfb_info *ofbi = FB2OFB(fbi);
545 struct omapfb2_device *fbdev = ofbi->fbdev;
529 enum omapfb_update_mode mode; 546 enum omapfb_update_mode mode;
530 int r; 547 int r;
531 548
549 if (!lock_fb_info(fbi))
550 return -ENODEV;
551 omapfb_lock(fbdev);
552
532 r = omapfb_get_update_mode(fbi, &mode); 553 r = omapfb_get_update_mode(fbi, &mode);
533 554
555 omapfb_unlock(fbdev);
556 unlock_fb_info(fbi);
557
534 if (r) 558 if (r)
535 return r; 559 return r;
536 560
@@ -541,6 +565,8 @@ static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
541 const char *buf, size_t count) 565 const char *buf, size_t count)
542{ 566{
543 struct fb_info *fbi = dev_get_drvdata(dev); 567 struct fb_info *fbi = dev_get_drvdata(dev);
568 struct omapfb_info *ofbi = FB2OFB(fbi);
569 struct omapfb2_device *fbdev = ofbi->fbdev;
544 unsigned mode; 570 unsigned mode;
545 int r; 571 int r;
546 572
@@ -548,10 +574,17 @@ static ssize_t store_upd_mode(struct device *dev, struct device_attribute *attr,
548 if (r) 574 if (r)
549 return r; 575 return r;
550 576
577 if (!lock_fb_info(fbi))
578 return -ENODEV;
579 omapfb_lock(fbdev);
580
551 r = omapfb_set_update_mode(fbi, mode); 581 r = omapfb_set_update_mode(fbi, mode);
552 if (r) 582 if (r)
553 return r; 583 return r;
554 584
585 omapfb_unlock(fbdev);
586 unlock_fb_info(fbi);
587
555 return count; 588 return count;
556} 589}
557 590