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>
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 85130fa..708f2cf 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -672,8 +672,6 @@
DBG("check_fb_var %d\n", ofbi->id);
- WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
r = fb_mode_to_dss_mode(var, &mode);
if (r) {
DBG("cannot convert var to omap dss mode\n");
@@ -855,8 +853,6 @@
int rotation = var->rotate;
int i;
- WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
for (i = 0; i < ofbi->num_overlays; i++) {
if (ovl != ofbi->overlays[i])
continue;
@@ -948,8 +944,6 @@
fill_fb(fbi);
#endif
- WARN_ON(!atomic_read(&ofbi->region->lock_count));
-
for (i = 0; i < ofbi->num_overlays; i++) {
ovl = ofbi->overlays[i];
@@ -1008,15 +1002,16 @@
static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
int r;
DBG("check_var(%d)\n", FB2OFB(fbi)->id);
- omapfb_get_mem_region(ofbi->region);
+ omapfb_lock(fbdev);
r = check_fb_var(fbi, var);
- omapfb_put_mem_region(ofbi->region);
+ omapfb_unlock(fbdev);
return r;
}
@@ -1025,11 +1020,12 @@
static int omapfb_set_par(struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
int r;
DBG("set_par(%d)\n", FB2OFB(fbi)->id);
- omapfb_get_mem_region(ofbi->region);
+ omapfb_lock(fbdev);
set_fb_fix(fbi);
@@ -1040,7 +1036,7 @@
r = omapfb_apply_changes(fbi, 0);
out:
- omapfb_put_mem_region(ofbi->region);
+ omapfb_unlock(fbdev);
return r;
}
@@ -1049,6 +1045,7 @@
struct fb_info *fbi)
{
struct omapfb_info *ofbi = FB2OFB(fbi);
+ struct omapfb2_device *fbdev = ofbi->fbdev;
struct fb_var_screeninfo new_var;
int r;
@@ -1064,11 +1061,11 @@
fbi->var = new_var;
- omapfb_get_mem_region(ofbi->region);
+ omapfb_lock(fbdev);
r = omapfb_apply_changes(fbi, 0);
- omapfb_put_mem_region(ofbi->region);
+ omapfb_unlock(fbdev);
return r;
}
@@ -1077,18 +1074,14 @@
{
struct omapfb2_mem_region *rg = vma->vm_private_data;
- omapfb_get_mem_region(rg);
atomic_inc(&rg->map_count);
- omapfb_put_mem_region(rg);
}
static void mmap_user_close(struct vm_area_struct *vma)
{
struct omapfb2_mem_region *rg = vma->vm_private_data;
- omapfb_get_mem_region(rg);
atomic_dec(&rg->map_count);
- omapfb_put_mem_region(rg);
}
static struct vm_operations_struct mmap_user_ops = {
@@ -1112,7 +1105,7 @@
return -EINVAL;
off = vma->vm_pgoff << PAGE_SHIFT;
- rg = omapfb_get_mem_region(ofbi->region);
+ rg = ofbi->region;
start = omapfb_get_region_paddr(ofbi);
len = fix->smem_len;
@@ -1140,13 +1133,9 @@
/* vm_ops.open won't be called for mmap itself. */
atomic_inc(&rg->map_count);
- omapfb_put_mem_region(rg);
-
return 0;
error:
- omapfb_put_mem_region(ofbi->region);
-
return r;
}
@@ -1914,7 +1903,6 @@
ofbi->region = &fbdev->regions[i];
ofbi->region->id = i;
- init_rwsem(&ofbi->region->lock);
/* assign these early, so that fb alloc can use them */
ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
@@ -1946,12 +1934,8 @@
/* setup fb_infos */
for (i = 0; i < fbdev->num_fbs; i++) {
struct fb_info *fbi = fbdev->fbs[i];
- struct omapfb_info *ofbi = FB2OFB(fbi);
- omapfb_get_mem_region(ofbi->region);
r = omapfb_fb_init(fbdev, fbi);
- omapfb_put_mem_region(ofbi->region);
-
if (r) {
dev_err(fbdev->dev, "failed to setup fb_info\n");
return r;
@@ -1983,12 +1967,8 @@
for (i = 0; i < fbdev->num_fbs; i++) {
struct fb_info *fbi = fbdev->fbs[i];
- struct omapfb_info *ofbi = FB2OFB(fbi);
- omapfb_get_mem_region(ofbi->region);
r = omapfb_apply_changes(fbi, 1);
- omapfb_put_mem_region(ofbi->region);
-
if (r) {
dev_err(fbdev->dev, "failed to change mode\n");
return r;