diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-12-04 07:55:18 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-12-07 09:55:03 -0500 |
commit | b41deecbda70067b26a3a7704fdf967a7940935b (patch) | |
tree | 5d609dc0469c58a29f18cd8e3eb427e427e9cca3 /drivers/video/omap2/omapfb/omapfb-sysfs.c | |
parent | 636f4e1b45c6204c6912cefa2bdbe22e00784a43 (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.c | 87 |
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 | */ |
83 | put_region: | 85 | put_region: |
84 | omapfb_put_mem_region(rg); | ||
85 | out: | 86 | out: |
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; |
135 | out: | 137 | out: |
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; |
423 | out: | 416 | out: |
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 | ||
438 | static ssize_t store_size(struct device *dev, struct device_attribute *attr, | 443 | static 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; |
498 | out: | 503 | out: |
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 | ||
516 | static ssize_t show_virt(struct device *dev, | 531 | static 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 | ||