OMAP: DSS2: OMAPFB: Make lockdep happy
[pandora-kernel.git] / drivers / video / omap2 / omapfb / omapfb-ioctl.c
index 3a10146..7975a99 100644 (file)
@@ -55,7 +55,7 @@ static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
        if (mem_idx >= fbdev->num_fbs)
                return NULL;
 
-       return omapfb_get_mem_region(&fbdev->regions[mem_idx]);
+       return &fbdev->regions[mem_idx];
 }
 
 static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
@@ -77,20 +77,30 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
        /* XXX uses only the first overlay */
        ovl = ofbi->overlays[0];
 
-       old_rg = omapfb_get_mem_region(ofbi->region);
+       old_rg = ofbi->region;
        new_rg = get_mem_region(ofbi, pi->mem_idx);
        if (!new_rg) {
                r = -EINVAL;
-               goto put_old;
+               goto out;
        }
 
+       /* Take the locks in a specific order to keep lockdep happy */
+       if (old_rg->id < new_rg->id) {
+               omapfb_get_mem_region(old_rg);
+               omapfb_get_mem_region(new_rg);
+       } else if (new_rg->id < old_rg->id) {
+               omapfb_get_mem_region(new_rg);
+               omapfb_get_mem_region(old_rg);
+       } else
+               omapfb_get_mem_region(old_rg);
+
        if (pi->enabled && !new_rg->size) {
                /*
                 * This plane's memory was freed, can't enable it
                 * until it's reallocated.
                 */
                r = -EINVAL;
-               goto put_new;
+               goto put_mem;
        }
 
        ovl->get_overlay_info(ovl, &old_info);
@@ -135,8 +145,15 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
        if (ovl->manager)
                ovl->manager->apply(ovl->manager);
 
-       omapfb_put_mem_region(new_rg);
-       omapfb_put_mem_region(old_rg);
+       /* Release the locks in a specific order to keep lockdep happy */
+       if (old_rg->id > new_rg->id) {
+               omapfb_put_mem_region(old_rg);
+               omapfb_put_mem_region(new_rg);
+       } else if (new_rg->id > old_rg->id) {
+               omapfb_put_mem_region(new_rg);
+               omapfb_put_mem_region(old_rg);
+       } else
+               omapfb_put_mem_region(old_rg);
 
        return 0;
 
@@ -147,10 +164,16 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
        }
 
        ovl->set_overlay_info(ovl, &old_info);
- put_new:
-       omapfb_put_mem_region(new_rg);
- put_old:
-       omapfb_put_mem_region(old_rg);
+ put_mem:
+       /* Release the locks in a specific order to keep lockdep happy */
+       if (old_rg->id > new_rg->id) {
+               omapfb_put_mem_region(old_rg);
+               omapfb_put_mem_region(new_rg);
+       } else if (new_rg->id > old_rg->id) {
+               omapfb_put_mem_region(new_rg);
+               omapfb_put_mem_region(old_rg);
+       } else
+               omapfb_put_mem_region(old_rg);
  out:
        dev_err(fbdev->dev, "setup_plane failed\n");
 
@@ -198,7 +221,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
        rg = ofbi->region;
 
-       down_write(&rg->lock);
+       down_write_nested(&rg->lock, rg->id);
 
        if (atomic_read(&rg->map_count)) {
                r = -EBUSY;