diff mbox

[v4,7/8] DSS2: OMAPFB: Make lockdep happy

Message ID 1268865983-16270-8-git-send-email-ville.syrjala@nokia.com (mailing list archive)
State New, archived
Delegated to: Tomi Valkeinen
Headers show

Commit Message

ville.syrjala@nokia.com March 17, 2010, 10:46 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 4d5e5af..a3681da 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -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;
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index aa22f7b..1b7cf57 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -445,7 +445,7 @@  static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	rg = ofbi->region;
 
-	down_write(&rg->lock);
+	down_write_nested(&rg->lock, rg->id);
 
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 195a760..676b55d 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -165,7 +165,7 @@  static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
 static inline struct omapfb2_mem_region *
 omapfb_get_mem_region(struct omapfb2_mem_region *rg)
 {
-	down_read(&rg->lock);
+	down_read_nested(&rg->lock, rg->id);
 	return rg;
 }