linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* omapfb mem_idx patchset
@ 2010-03-17 22:46 ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 1/8] DSS2: OMAPFB: Refactor overlay address calculations ville.syrjala
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen; +Cc: Imre Deak, linux-fbdev, linux-omap

This patchset is based on the v3 monolithic patch.

These are the changes from v3:
* split up into smaller chunks
* OMAPFB_MEM_IDX defines fixed to use the full byte
* unnecessary changes removed
* converted to use rwsems
* further modified further to make lockdep happy
* some debug WARN_ON()s added

The add locking + convert to rwsem patches could be squashed together
if you don't want the intermediate step in the tree.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v4 1/8] DSS2: OMAPFB: Refactor overlay address calculations
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 2/8] DSS2: OMAPFB: Check var even if there isn't memory ville.syrjala
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

Split the overlay address calculations into their own function.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |   63 ++++++++++++++++++------------
 1 files changed, 38 insertions(+), 25 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 4a76917..ea619a9 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -821,6 +821,40 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
 	return offset;
 }
 
+static void omapfb_calc_addr(const struct omapfb_info *ofbi,
+			     const struct fb_var_screeninfo *var,
+			     const struct fb_fix_screeninfo *fix,
+			     int rotation, u32 *paddr, void __iomem **vaddr)
+{
+	u32 data_start_p;
+	void __iomem *data_start_v;
+	int offset;
+
+	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB) {
+		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
+		data_start_v = NULL;
+	} else {
+		data_start_p = omapfb_get_region_paddr(ofbi);
+		data_start_v = omapfb_get_region_vaddr(ofbi);
+	}
+
+	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB)
+		offset = calc_rotation_offset_vrfb(var, fix, rotation);
+	else
+		offset = calc_rotation_offset_dma(var, fix, rotation);
+
+	data_start_p += offset;
+	data_start_v += offset;
+
+	if (offset)
+		DBG("offset %d, %d = %d\n",
+		    var->xoffset, var->yoffset, offset);
+
+	DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+
+	*paddr = data_start_p;
+	*vaddr = data_start_v;
+}
 
 /* setup overlay according to the fb */
 static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
@@ -831,9 +865,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 	struct fb_var_screeninfo *var = &fbi->var;
 	struct fb_fix_screeninfo *fix = &fbi->fix;
 	enum omap_color_mode mode = 0;
-	int offset;
-	u32 data_start_p;
-	void __iomem *data_start_v;
+	u32 data_start_p = 0;
+	void __iomem *data_start_v = NULL;
 	struct omap_overlay_info info;
 	int xres, yres;
 	int screen_width;
@@ -860,28 +893,8 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 		yres = var->yres;
 	}
 
-
-	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB) {
-		data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
-		data_start_v = NULL;
-	} else {
-		data_start_p = omapfb_get_region_paddr(ofbi);
-		data_start_v = omapfb_get_region_vaddr(ofbi);
-	}
-
-	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB)
-		offset = calc_rotation_offset_vrfb(var, fix, rotation);
-	else
-		offset = calc_rotation_offset_dma(var, fix, rotation);
-
-	data_start_p += offset;
-	data_start_v += offset;
-
-	if (offset)
-		DBG("offset %d, %d = %d\n",
-				var->xoffset, var->yoffset, offset);
-
-	DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
+	omapfb_calc_addr(ofbi, var, fix, rotation,
+			 &data_start_p, &data_start_v);
 
 	r = fb_mode_to_dss_mode(var, &mode);
 	if (r) {
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 2/8] DSS2: OMAPFB: Check var even if there isn't memory
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 1/8] DSS2: OMAPFB: Refactor overlay address calculations ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 3/8] DSS2: OMAPFB: Skip unnecessary set_overlay_info() ville.syrjala
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

If video memory hasn't been allocate have check_fb_var() still check
most of the settings, just skip the ones involving the size of the
memory region. Also skip the memory address calculations in
omapfb_setup_overlay() if there's no memory.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-main.c |   11 +++++------
 1 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ea619a9..7351e96 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -667,9 +667,6 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 
 	DBG("check_fb_var %d\n", ofbi->id);
 
-	if (ofbi->region.size = 0)
-		return 0;
-
 	r = fb_mode_to_dss_mode(var, &mode);
 	if (r) {
 		DBG("cannot convert var to omap dss mode\n");
@@ -689,7 +686,8 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 	if (check_fb_res_bounds(var))
 		return -EINVAL;
 
-	if (check_fb_size(ofbi, var))
+	/* When no memory is allocated ignore the size check */
+	if (ofbi->region.size != 0 && check_fb_size(ofbi, var))
 		return -EINVAL;
 
 	if (var->xres + var->xoffset > var->xres_virtual)
@@ -893,8 +891,9 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 		yres = var->yres;
 	}
 
-	omapfb_calc_addr(ofbi, var, fix, rotation,
-			 &data_start_p, &data_start_v);
+	if (ofbi->region.size)
+		omapfb_calc_addr(ofbi, var, fix, rotation,
+				 &data_start_p, &data_start_v);
 
 	r = fb_mode_to_dss_mode(var, &mode);
 	if (r) {
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 3/8] DSS2: OMAPFB: Skip unnecessary set_overlay_info()
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 1/8] DSS2: OMAPFB: Refactor overlay address calculations ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 2/8] DSS2: OMAPFB: Check var even if there isn't memory ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 4/8] DSS2: OMAPFB: Add support for switching memory regions ville.syrjala
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

In omapfb_enable_overlay() if the overlay state is already what we want
skip the set_overlay_info().

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index cd54fdb..c9866be 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -148,6 +148,8 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
 	struct omap_overlay_info info;
 
 	ovl->get_overlay_info(ovl, &info);
+	if (info.enabled = enable)
+		return 0;
 	info.enabled = enable;
 	return ovl->set_overlay_info(ovl, &info);
 }
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 4/8] DSS2: OMAPFB: Add support for switching memory regions
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
                   ` (2 preceding siblings ...)
  2010-03-17 22:46 ` [PATCH v4 3/8] DSS2: OMAPFB: Skip unnecessary set_overlay_info() ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 5/8] DSS2: OMAPFB: Add locking for " ville.syrjala
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

Separate the memory region from the framebuffer device a little bit.
It's now possible to select the memory region used by the framebuffer
device using the new mem_idx parameter of omapfb_plane_info. If the
mem_idx is specified it will be interpreted as an index into the
memory regions array, if it's not specified the framebuffer's index is
used instead. So by default each framebuffer keeps using it's own
memory region which preserves backwards compatibility.

This allows cloning the same memory region to several overlays and yet
each overlay can be controlled independently since they can be
associated with separate framebuffer devices.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-ioctl.c |  125 +++++++++++++++++++++++-----
 drivers/video/omap2/omapfb/omapfb-main.c  |   71 ++++++++++-------
 drivers/video/omap2/omapfb/omapfb-sysfs.c |   37 ++++++---
 drivers/video/omap2/omapfb/omapfb.h       |    9 ++-
 include/linux/omapfb.h                    |    5 +-
 5 files changed, 183 insertions(+), 64 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 1ffa760..a160a3e 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -34,12 +34,37 @@
 
 #include "omapfb.h"
 
+static u8 get_mem_idx(struct omapfb_info *ofbi)
+{
+	if (ofbi->id = ofbi->region->id)
+		return 0;
+
+	return OMAPFB_MEM_IDX_ENABLED | ofbi->region->id;
+}
+
+static struct omapfb2_mem_region *get_mem_region(struct omapfb_info *ofbi,
+						 u8 mem_idx)
+{
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+
+	if (mem_idx & OMAPFB_MEM_IDX_ENABLED)
+		mem_idx &= OMAPFB_MEM_IDX_MASK;
+	else
+		mem_idx = ofbi->id;
+
+	if (mem_idx >= fbdev->num_fbs)
+		return NULL;
+
+	return &fbdev->regions[mem_idx];
+}
+
 static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omap_overlay *ovl;
-	struct omap_overlay_info info;
+	struct omap_overlay_info old_info;
+	struct omapfb2_mem_region *old_rg, *new_rg;
 	int r = 0;
 
 	DBG("omapfb_setup_plane\n");
@@ -52,7 +77,14 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 	/* XXX uses only the first overlay */
 	ovl = ofbi->overlays[0];
 
-	if (pi->enabled && !ofbi->region.size) {
+	old_rg = ofbi->region;
+	new_rg = get_mem_region(ofbi, pi->mem_idx);
+	if (!new_rg) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	if (pi->enabled && !new_rg->size) {
 		/*
 		 * This plane's memory was freed, can't enable it
 		 * until it's reallocated.
@@ -61,27 +93,60 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 		goto out;
 	}
 
-	ovl->get_overlay_info(ovl, &info);
+	ovl->get_overlay_info(ovl, &old_info);
 
-	info.pos_x = pi->pos_x;
-	info.pos_y = pi->pos_y;
-	info.out_width = pi->out_width;
-	info.out_height = pi->out_height;
-	info.enabled = pi->enabled;
+	if (old_rg != new_rg) {
+		ofbi->region = new_rg;
+		set_fb_fix(fbi);
+	}
 
-	r = ovl->set_overlay_info(ovl, &info);
-	if (r)
-		goto out;
+	if (pi->enabled) {
+		struct omap_overlay_info info;
+
+		r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
+			pi->out_width, pi->out_height);
+		if (r)
+			goto undo;
 
-	if (ovl->manager) {
-		r = ovl->manager->apply(ovl->manager);
+		ovl->get_overlay_info(ovl, &info);
+
+		if (!info.enabled) {
+			info.enabled = pi->enabled;
+			r = ovl->set_overlay_info(ovl, &info);
+			if (r)
+				goto undo;
+		}
+	} else {
+		struct omap_overlay_info info;
+
+		ovl->get_overlay_info(ovl, &info);
+
+		info.enabled = pi->enabled;
+		info.pos_x = pi->pos_x;
+		info.pos_y = pi->pos_y;
+		info.out_width = pi->out_width;
+		info.out_height = pi->out_height;
+
+		r = ovl->set_overlay_info(ovl, &info);
 		if (r)
-			goto out;
+			goto undo;
 	}
 
-out:
-	if (r)
-		dev_err(fbdev->dev, "setup_plane failed\n");
+	if (ovl->manager)
+		ovl->manager->apply(ovl->manager);
+
+	return 0;
+
+ undo:
+	if (old_rg != new_rg) {
+		ofbi->region = old_rg;
+		set_fb_fix(fbi);
+	}
+
+	ovl->set_overlay_info(ovl, &old_info);
+ out:
+	dev_err(fbdev->dev, "setup_plane failed\n");
+
 	return r;
 }
 
@@ -92,8 +157,8 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 	if (ofbi->num_overlays != 1) {
 		memset(pi, 0, sizeof(*pi));
 	} else {
-		struct omap_overlay_info *ovli;
 		struct omap_overlay *ovl;
+		struct omap_overlay_info *ovli;
 
 		ovl = ofbi->overlays[0];
 		ovli = &ovl->info;
@@ -103,6 +168,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 		pi->enabled = ovli->enabled;
 		pi->channel_out = 0; /* xxx */
 		pi->mirror = 0;
+		pi->mem_idx = get_mem_idx(ofbi);
 		pi->out_width = ovli->out_width;
 		pi->out_height = ovli->out_height;
 	}
@@ -123,11 +189,24 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
 	size = PAGE_ALIGN(mi->size);
 
-	rg = &ofbi->region;
+	rg = ofbi->region;
 
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		if (ofbi->overlays[i]->info.enabled)
-			return -EBUSY;
+	if (atomic_read(&rg->map_count))
+		return -EBUSY;
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		if (ofbi2->region != rg)
+			continue;
+
+		for (j = 0; j < ofbi2->num_overlays; j++) {
+			if (ofbi2->overlays[j]->info.enabled) {
+				r = -EBUSY;
+				return r;
+			}
+		}
 	}
 
 	if (rg->size != size || rg->type != mi->type) {
@@ -146,7 +225,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_mem_region *rg;
 
-	rg = &ofbi->region;
+	rg = ofbi->region;
 	memset(mi, 0, sizeof(*mi));
 
 	mi->size = rg->size;
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 7351e96..ceb7d92 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -156,7 +156,7 @@ static void fill_fb(struct fb_info *fbi)
 
 static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
 {
-	const struct vrfb *vrfb = &ofbi->region.vrfb;
+	const struct vrfb *vrfb = &ofbi->region->vrfb;
 	unsigned offset;
 
 	switch (rot) {
@@ -184,27 +184,27 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
 static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
 {
 	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB) {
-		return ofbi->region.vrfb.paddr[rot]
+		return ofbi->region->vrfb.paddr[rot]
 			+ omapfb_get_vrfb_offset(ofbi, rot);
 	} else {
-		return ofbi->region.paddr;
+		return ofbi->region->paddr;
 	}
 }
 
 static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
 {
 	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB)
-		return ofbi->region.vrfb.paddr[0];
+		return ofbi->region->vrfb.paddr[0];
 	else
-		return ofbi->region.paddr;
+		return ofbi->region->paddr;
 }
 
 static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
 {
 	if (ofbi->rotation_type = OMAP_DSS_ROT_VRFB)
-		return ofbi->region.vrfb.vaddr[0];
+		return ofbi->region->vrfb.vaddr[0];
 	else
-		return ofbi->region.vaddr;
+		return ofbi->region->vaddr;
 }
 
 static struct omapfb_colormode omapfb_colormodes[] = {
@@ -449,7 +449,7 @@ static int check_vrfb_fb_size(unsigned long region_size,
 static int check_fb_size(const struct omapfb_info *ofbi,
 		struct fb_var_screeninfo *var)
 {
-	unsigned long max_frame_size = ofbi->region.size;
+	unsigned long max_frame_size = ofbi->region->size;
 	int bytespp = var->bits_per_pixel >> 3;
 	unsigned long line_size = var->xres_virtual * bytespp;
 
@@ -496,7 +496,7 @@ static int check_fb_size(const struct omapfb_info *ofbi,
 static int setup_vrfb_rotation(struct fb_info *fbi)
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg = &ofbi->region;
+	struct omapfb2_mem_region *rg = ofbi->region;
 	struct vrfb *vrfb = &rg->vrfb;
 	struct fb_var_screeninfo *var = &fbi->var;
 	struct fb_fix_screeninfo *fix = &fbi->fix;
@@ -557,9 +557,9 @@ static int setup_vrfb_rotation(struct fb_info *fbi)
 		return r;
 
 	/* used by open/write in fbmem.c */
-	fbi->screen_base = ofbi->region.vrfb.vaddr[0];
+	fbi->screen_base = ofbi->region->vrfb.vaddr[0];
 
-	fix->smem_start = ofbi->region.vrfb.paddr[0];
+	fix->smem_start = ofbi->region->vrfb.paddr[0];
 
 	switch (var->nonstd) {
 	case OMAPFB_COLOR_YUV422:
@@ -598,7 +598,7 @@ void set_fb_fix(struct fb_info *fbi)
 	struct fb_fix_screeninfo *fix = &fbi->fix;
 	struct fb_var_screeninfo *var = &fbi->var;
 	struct omapfb_info *ofbi = FB2OFB(fbi);
-	struct omapfb2_mem_region *rg = &ofbi->region;
+	struct omapfb2_mem_region *rg = ofbi->region;
 
 	DBG("set_fb_fix\n");
 
@@ -687,7 +687,7 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 		return -EINVAL;
 
 	/* When no memory is allocated ignore the size check */
-	if (ofbi->region.size != 0 && check_fb_size(ofbi, var))
+	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
 		return -EINVAL;
 
 	if (var->xres + var->xoffset > var->xres_virtual)
@@ -855,7 +855,7 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
 }
 
 /* setup overlay according to the fb */
-static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 		u16 posx, u16 posy, u16 outw, u16 outh)
 {
 	int r = 0;
@@ -891,7 +891,7 @@ static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 		yres = var->yres;
 	}
 
-	if (ofbi->region.size)
+	if (ofbi->region->size)
 		omapfb_calc_addr(ofbi, var, fix, rotation,
 				 &data_start_p, &data_start_v);
 
@@ -970,7 +970,7 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
 
 		DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id);
 
-		if (ofbi->region.size = 0) {
+		if (ofbi->region->size = 0) {
 			/* the fb is not available. disable the overlay */
 			omapfb_overlay_enable(ovl, 0);
 			if (!init && ovl->manager)
@@ -1070,16 +1070,16 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
 
 static void mmap_user_open(struct vm_area_struct *vma)
 {
-	struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+	struct omapfb2_mem_region *rg = vma->vm_private_data;
 
-	atomic_inc(&ofbi->map_count);
+	atomic_inc(&rg->map_count);
 }
 
 static void mmap_user_close(struct vm_area_struct *vma)
 {
-	struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data;
+	struct omapfb2_mem_region *rg = vma->vm_private_data;
 
-	atomic_dec(&ofbi->map_count);
+	atomic_dec(&rg->map_count);
 }
 
 static struct vm_operations_struct mmap_user_ops = {
@@ -1091,6 +1091,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 {
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct omapfb2_mem_region *rg;
 	unsigned long off;
 	unsigned long start;
 	u32 len;
@@ -1101,6 +1102,8 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 		return -EINVAL;
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
+	rg = ofbi->region;
+
 	start = omapfb_get_region_paddr(ofbi);
 	len = fix->smem_len;
 	if (off >= len)
@@ -1116,12 +1119,12 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 	vma->vm_flags |= VM_IO | VM_RESERVED;
 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 	vma->vm_ops = &mmap_user_ops;
-	vma->vm_private_data = ofbi;
+	vma->vm_private_data = rg;
 	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
 	/* vm_ops.open won't be called for mmap itself. */
-	atomic_inc(&ofbi->map_count);
+	atomic_inc(&rg->map_count);
 	return 0;
 }
 
@@ -1311,7 +1314,9 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_mem_region *rg;
 
-	rg = &ofbi->region;
+	rg = ofbi->region;
+
+	WARN_ON(atomic_read(&rg->map_count));
 
 	if (rg->paddr)
 		if (omap_vram_free(rg->paddr, rg->size))
@@ -1366,8 +1371,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
 	void __iomem *vaddr;
 	int r;
 
-	rg = &ofbi->region;
-	memset(rg, 0, sizeof(*rg));
+	rg = ofbi->region;
+
+	rg->paddr = 0;
+	rg->vaddr = NULL;
+	memset(&rg->vrfb, 0, sizeof rg->vrfb);
+	rg->size = 0;
+	rg->type = 0;
+	rg->alloc = false;
+	rg->map = false;
 
 	size = PAGE_ALIGN(size);
 
@@ -1620,7 +1632,7 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
 	for (i = 0; i < fbdev->num_fbs; i++) {
 		struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
 		struct omapfb2_mem_region *rg;
-		rg = &ofbi->region;
+		rg = ofbi->region;
 
 		DBG("region%d phys %08x virt %p size=%lu\n",
 				i,
@@ -1637,7 +1649,7 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omap_dss_device *display = fb2display(fbi);
-	struct omapfb2_mem_region *rg = &ofbi->region;
+	struct omapfb2_mem_region *rg = ofbi->region;
 	unsigned long old_size = rg->size;
 	unsigned long old_paddr = rg->paddr;
 	int old_type = rg->type;
@@ -1720,7 +1732,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
 	fbi->flags = FBINFO_FLAG_DEFAULT;
 	fbi->pseudo_palette = fbdev->pseudo_palette;
 
-	if (ofbi->region.size = 0) {
+	if (ofbi->region->size = 0) {
 		clear_fb_info(fbi);
 		return 0;
 	}
@@ -1882,6 +1894,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 		ofbi->fbdev = fbdev;
 		ofbi->id = i;
 
+		ofbi->region = &fbdev->regions[i];
+		ofbi->region->id = i;
+
 		/* assign these early, so that fb alloc can use them */
 		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
 			OMAP_DSS_ROT_DMA;
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 62bb88f..6fbe39a 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -63,7 +63,7 @@ static ssize_t store_rotate_type(struct device *dev,
 	if (rot_type = ofbi->rotation_type)
 		goto out;
 
-	if (ofbi->region.size) {
+	if (ofbi->region->size) {
 		r = -EBUSY;
 		goto out;
 	}
@@ -402,7 +402,7 @@ static ssize_t show_size(struct device *dev,
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 
-	return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size);
+	return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
 }
 
 static ssize_t store_size(struct device *dev, struct device_attribute *attr,
@@ -410,6 +410,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 {
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_device *fbdev = ofbi->fbdev;
+	struct omapfb2_mem_region *rg;
 	unsigned long size;
 	int r;
 	int i;
@@ -418,15 +420,30 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	lock_fb_info(fbi);
 
-	for (i = 0; i < ofbi->num_overlays; i++) {
-		if (ofbi->overlays[i]->info.enabled) {
-			r = -EBUSY;
-			goto out;
+	rg = ofbi->region;
+
+	if (atomic_read(&rg->map_count)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		if (ofbi2->region != rg)
+			continue;
+
+		for (j = 0; j < ofbi2->num_overlays; j++) {
+			if (ofbi2->overlays[j]->info.enabled) {
+				r = -EBUSY;
+				goto out;
+			}
 		}
 	}
 
-	if (size != ofbi->region.size) {
-		r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type);
+	if (size != ofbi->region->size) {
+		r = omapfb_realloc_fbmem(fbi, size, ofbi->region->type);
 		if (r) {
 			dev_err(dev, "realloc fbmem failed\n");
 			goto out;
@@ -446,7 +463,7 @@ static ssize_t show_phys(struct device *dev,
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 
-	return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr);
+	return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
 }
 
 static ssize_t show_virt(struct device *dev,
@@ -455,7 +472,7 @@ static ssize_t show_virt(struct device *dev,
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 
-	return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
+	return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
 }
 
 static struct device_attribute omapfb_attrs[] = {
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index c9866be..02f1ba9 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -44,6 +44,7 @@ extern unsigned int omapfb_debug;
 #define OMAPFB_MAX_OVL_PER_FB 3
 
 struct omapfb2_mem_region {
+	int             id;
 	u32		paddr;
 	void __iomem	*vaddr;
 	struct vrfb	vrfb;
@@ -51,13 +52,13 @@ struct omapfb2_mem_region {
 	u8		type;		/* OMAPFB_PLANE_MEM_* */
 	bool		alloc;		/* allocated by the driver */
 	bool		map;		/* kernel mapped by the driver */
+	atomic_t	map_count;
 };
 
 /* appended to fb_info */
 struct omapfb_info {
 	int id;
-	struct omapfb2_mem_region region;
-	atomic_t map_count;
+	struct omapfb2_mem_region *region;
 	int num_overlays;
 	struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB];
 	struct omapfb2_device *fbdev;
@@ -76,6 +77,7 @@ struct omapfb2_device {
 
 	unsigned num_fbs;
 	struct fb_info *fbs[10];
+	struct omapfb2_mem_region regions[10];
 
 	unsigned num_displays;
 	struct omap_dss_device *displays[10];
@@ -117,6 +119,9 @@ int omapfb_update_window(struct fb_info *fbi,
 int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
 			struct fb_var_screeninfo *var);
 
+int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
+		u16 posx, u16 posy, u16 outw, u16 outh);
+
 /* find the display connected to this fb, if any */
 static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
 {
diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h
index 9bdd914..0ecf731 100644
--- a/include/linux/omapfb.h
+++ b/include/linux/omapfb.h
@@ -85,6 +85,9 @@
 #define OMAPFB_MEMTYPE_SRAM		1
 #define OMAPFB_MEMTYPE_MAX		1
 
+#define OMAPFB_MEM_IDX_ENABLED	0x80
+#define OMAPFB_MEM_IDX_MASK	0x7f
+
 enum omapfb_color_format {
 	OMAPFB_COLOR_RGB565 = 0,
 	OMAPFB_COLOR_YUV422,
@@ -136,7 +139,7 @@ struct omapfb_plane_info {
 	__u8  enabled;
 	__u8  channel_out;
 	__u8  mirror;
-	__u8  reserved1;
+	__u8  mem_idx;
 	__u32 out_width;
 	__u32 out_height;
 	__u32 reserved2[12];
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 5/8] DSS2: OMAPFB: Add locking for memory regions
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
                   ` (3 preceding siblings ...)
  2010-03-17 22:46 ` [PATCH v4 4/8] DSS2: OMAPFB: Add support for switching memory regions ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 6/8] DSS2: OMAPFB: Convert the memory region locking to rwsem ville.syrjala
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

Add locking to the memory regions to make sure the memory region size
won't be changed while some other piece of code is performing some
checks or setup based on that information.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   44 +++++++++++++++-----
 drivers/video/omap2/omapfb/omapfb-main.c  |   62 +++++++++++++++++++++++++----
 drivers/video/omap2/omapfb/omapfb-sysfs.c |   37 ++++++++++++++++-
 drivers/video/omap2/omapfb/omapfb.h       |   18 ++++++++
 4 files changed, 140 insertions(+), 21 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index a160a3e..f02b1b0 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 &fbdev->regions[mem_idx];
+	return omapfb_get_mem_region(&fbdev->regions[mem_idx]);
 }
 
 static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
@@ -77,11 +77,11 @@ 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 = ofbi->region;
+	old_rg = omapfb_get_mem_region(ofbi->region);
 	new_rg = get_mem_region(ofbi, pi->mem_idx);
 	if (!new_rg) {
 		r = -EINVAL;
-		goto out;
+		goto put_old;
 	}
 
 	if (pi->enabled && !new_rg->size) {
@@ -90,7 +90,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
 		 * until it's reallocated.
 		 */
 		r = -EINVAL;
-		goto out;
+		goto put_new;
 	}
 
 	ovl->get_overlay_info(ovl, &old_info);
@@ -135,6 +135,9 @@ 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);
+
 	return 0;
 
  undo:
@@ -144,6 +147,10 @@ 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);
  out:
 	dev_err(fbdev->dev, "setup_plane failed\n");
 
@@ -181,7 +188,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_device *fbdev = ofbi->fbdev;
 	struct omapfb2_mem_region *rg;
-	int r, i;
+	int r = 0, i;
 	size_t size;
 
 	if (mi->type > OMAPFB_MEMTYPE_MAX)
@@ -191,8 +198,18 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
 	rg = ofbi->region;
 
-	if (atomic_read(&rg->map_count))
-		return -EBUSY;
+	/* FIXME probably should be a rwsem ... */
+	mutex_lock(&rg->mtx);
+	while (rg->ref) {
+		mutex_unlock(&rg->mtx);
+		schedule();
+		mutex_lock(&rg->mtx);
+	}
+
+	if (atomic_read(&rg->map_count)) {
+		r = -EBUSY;
+		goto out;
+	}
 
 	for (i = 0; i < fbdev->num_fbs; i++) {
 		struct omapfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
@@ -204,7 +221,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 		for (j = 0; j < ofbi2->num_overlays; j++) {
 			if (ofbi2->overlays[j]->info.enabled) {
 				r = -EBUSY;
-				return r;
+				goto out;
 			}
 		}
 	}
@@ -213,11 +230,14 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 		r = omapfb_realloc_fbmem(fbi, size, mi->type);
 		if (r) {
 			dev_err(fbdev->dev, "realloc fbmem failed\n");
-			return r;
+			goto out;
 		}
 	}
 
-	return 0;
+ out:
+	mutex_unlock(&rg->mtx);
+
+	return r;
 }
 
 static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
@@ -225,12 +245,14 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct omapfb2_mem_region *rg;
 
-	rg = ofbi->region;
+	rg = omapfb_get_mem_region(ofbi->region);
 	memset(mi, 0, sizeof(*mi));
 
 	mi->size = rg->size;
 	mi->type = rg->type;
 
+	omapfb_put_mem_region(rg);
+
 	return 0;
 }
 
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ceb7d92..d330032 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1018,36 +1018,48 @@ err:
  * DO NOT MODIFY PAR */
 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
 {
+	struct omapfb_info *ofbi = FB2OFB(fbi);
 	int r;
 
 	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
 
+	omapfb_get_mem_region(ofbi->region);
+
 	r = check_fb_var(fbi, var);
 
+	omapfb_put_mem_region(ofbi->region);
+
 	return r;
 }
 
 /* set the video mode according to info->var */
 static int omapfb_set_par(struct fb_info *fbi)
 {
+	struct omapfb_info *ofbi = FB2OFB(fbi);
 	int r;
 
 	DBG("set_par(%d)\n", FB2OFB(fbi)->id);
 
+	omapfb_get_mem_region(ofbi->region);
+
 	set_fb_fix(fbi);
 
 	r = setup_vrfb_rotation(fbi);
 	if (r)
-		return r;
+		goto out;
 
 	r = omapfb_apply_changes(fbi, 0);
 
+ out:
+	omapfb_put_mem_region(ofbi->region);
+
 	return r;
 }
 
 static int omapfb_pan_display(struct fb_var_screeninfo *var,
 		struct fb_info *fbi)
 {
+	struct omapfb_info *ofbi = FB2OFB(fbi);
 	struct fb_var_screeninfo new_var;
 	int r;
 
@@ -1063,8 +1075,12 @@ static int omapfb_pan_display(struct fb_var_screeninfo *var,
 
 	fbi->var = new_var;
 
+	omapfb_get_mem_region(ofbi->region);
+
 	r = omapfb_apply_changes(fbi, 0);
 
+	omapfb_put_mem_region(ofbi->region);
+
 	return r;
 }
 
@@ -1072,14 +1088,18 @@ static void mmap_user_open(struct vm_area_struct *vma)
 {
 	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 = {
@@ -1095,6 +1115,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 	unsigned long off;
 	unsigned long start;
 	u32 len;
+	int r = -EINVAL;
 
 	if (vma->vm_end - vma->vm_start = 0)
 		return 0;
@@ -1102,14 +1123,14 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 		return -EINVAL;
 	off = vma->vm_pgoff << PAGE_SHIFT;
 
-	rg = ofbi->region;
+	rg = omapfb_get_mem_region(ofbi->region);
 
 	start = omapfb_get_region_paddr(ofbi);
 	len = fix->smem_len;
 	if (off >= len)
-		return -EINVAL;
+		goto error;
 	if ((vma->vm_end - vma->vm_start + off) > len)
-		return -EINVAL;
+		goto error;
 
 	off += start;
 
@@ -1121,11 +1142,23 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
 	vma->vm_ops = &mmap_user_ops;
 	vma->vm_private_data = rg;
 	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
-			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot)) {
+		r = -EAGAIN;
+		goto error;
+	}
+
 	/* 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;
 }
 
 /* Store a single color palette entry into a pseudo palette or the hardware
@@ -1896,6 +1929,7 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 
 		ofbi->region = &fbdev->regions[i];
 		ofbi->region->id = i;
+		mutex_init(&ofbi->region->mtx);
 
 		/* assign these early, so that fb alloc can use them */
 		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
@@ -1926,7 +1960,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 
 	/* setup fb_infos */
 	for (i = 0; i < fbdev->num_fbs; i++) {
-		r = omapfb_fb_init(fbdev, fbdev->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;
@@ -1947,7 +1987,13 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 	DBG("framebuffers registered\n");
 
 	for (i = 0; i < fbdev->num_fbs; i++) {
-		r = omapfb_apply_changes(fbdev->fbs[i], 1);
+		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;
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 6fbe39a..6aee279 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,
 {
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct omapfb_info *ofbi = FB2OFB(fbi);
+	struct omapfb2_mem_region *rg;
 	enum omap_dss_rotation_type rot_type;
 	int r;
 
@@ -63,9 +64,11 @@ static ssize_t store_rotate_type(struct device *dev,
 	if (rot_type = ofbi->rotation_type)
 		goto out;
 
-	if (ofbi->region->size) {
+	rg = omapfb_get_mem_region(ofbi->region);
+
+	if (rg->size) {
 		r = -EBUSY;
-		goto out;
+		goto put_region;
 	}
 
 	ofbi->rotation_type = rot_type;
@@ -74,6 +77,8 @@ static ssize_t store_rotate_type(struct device *dev,
 	 * Since the VRAM for this FB is not allocated at the moment we don't
 	 * need to do any further parameter checking at this point.
 	 */
+put_region:
+	omapfb_put_mem_region(rg);
 out:
 	unlock_fb_info(fbi);
 
@@ -109,6 +114,8 @@ static ssize_t store_mirror(struct device *dev,
 
 	ofbi->mirror = mirror;
 
+	omapfb_get_mem_region(ofbi->region);
+
 	memcpy(&new_var, &fbi->var, sizeof(new_var));
 	r = check_fb_var(fbi, &new_var);
 	if (r)
@@ -123,6 +130,8 @@ static ssize_t store_mirror(struct device *dev,
 
 	r = count;
 out:
+	omapfb_put_mem_region(ofbi->region);
+
 	unlock_fb_info(fbi);
 
 	return r;
@@ -259,11 +268,15 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
 
 		DBG("detaching %d\n", ofbi->overlays[i]->id);
 
+		omapfb_get_mem_region(ofbi->region);
+
 		omapfb_overlay_enable(ovl, 0);
 
 		if (ovl->manager)
 			ovl->manager->apply(ovl->manager);
 
+		omapfb_put_mem_region(ofbi->region);
+
 		for (t = i + 1; t < ofbi->num_overlays; t++) {
 			ofbi->rotation[t-1] = ofbi->rotation[t];
 			ofbi->overlays[t-1] = ofbi->overlays[t];
@@ -296,7 +309,12 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
 	}
 
 	if (added) {
+		omapfb_get_mem_region(ofbi->region);
+
 		r = omapfb_apply_changes(fbi, 0);
+
+		omapfb_put_mem_region(ofbi->region);
+
 		if (r)
 			goto out;
 	}
@@ -382,7 +400,12 @@ static ssize_t store_overlays_rotate(struct device *dev,
 		for (i = 0; i < num_ovls; ++i)
 			ofbi->rotation[i] = rotation[i];
 
+		omapfb_get_mem_region(ofbi->region);
+
 		r = omapfb_apply_changes(fbi, 0);
+
+		omapfb_put_mem_region(ofbi->region);
+
 		if (r)
 			goto out;
 
@@ -422,6 +445,14 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	rg = ofbi->region;
 
+	/* FIXME probably should be a rwsem ... */
+	mutex_lock(&rg->mtx);
+	while (rg->ref) {
+		mutex_unlock(&rg->mtx);
+		schedule();
+		mutex_lock(&rg->mtx);
+	}
+
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
 		goto out;
@@ -452,6 +483,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	r = count;
 out:
+	mutex_unlock(&rg->mtx);
+
 	unlock_fb_info(fbi);
 
 	return r;
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 02f1ba9..db3aef5 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -52,6 +52,8 @@ struct omapfb2_mem_region {
 	u8		type;		/* OMAPFB_PLANE_MEM_* */
 	bool		alloc;		/* allocated by the driver */
 	bool		map;		/* kernel mapped by the driver */
+	struct mutex    mtx;
+	unsigned int    ref;
 	atomic_t	map_count;
 };
 
@@ -159,4 +161,20 @@ static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
 	return ovl->set_overlay_info(ovl, &info);
 }
 
+static inline struct omapfb2_mem_region *
+omapfb_get_mem_region(struct omapfb2_mem_region *rg)
+{
+	mutex_lock(&rg->mtx);
+	rg->ref++;
+	mutex_unlock(&rg->mtx);
+	return rg;
+}
+
+static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
+{
+	mutex_lock(&rg->mtx);
+	rg->ref--;
+	mutex_unlock(&rg->mtx);
+}
+
 #endif
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 6/8] DSS2: OMAPFB: Convert the memory region locking to rwsem
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
                   ` (4 preceding siblings ...)
  2010-03-17 22:46 ` [PATCH v4 5/8] DSS2: OMAPFB: Add locking for " ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 7/8] DSS2: OMAPFB: Make lockdep happy ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 8/8] DSS2: OMAPFB: Add some locking debug checks ville.syrjala
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

R/W semaphore is a goof fit for the memory region locking pattern.
So use it.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   10 ++--------
 drivers/video/omap2/omapfb/omapfb-main.c  |    2 +-
 drivers/video/omap2/omapfb/omapfb-sysfs.c |   10 ++--------
 drivers/video/omap2/omapfb/omapfb.h       |   13 +++++--------
 4 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index f02b1b0..4d5e5af 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -198,13 +198,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 
 	rg = ofbi->region;
 
-	/* FIXME probably should be a rwsem ... */
-	mutex_lock(&rg->mtx);
-	while (rg->ref) {
-		mutex_unlock(&rg->mtx);
-		schedule();
-		mutex_lock(&rg->mtx);
-	}
+	down_write(&rg->lock);
 
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
@@ -235,7 +229,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	}
 
  out:
-	mutex_unlock(&rg->mtx);
+	up_write(&rg->lock);
 
 	return r;
 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index d330032..2bd5b42 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1929,7 +1929,7 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
 
 		ofbi->region = &fbdev->regions[i];
 		ofbi->region->id = i;
-		mutex_init(&ofbi->region->mtx);
+		init_rwsem(&ofbi->region->lock);
 
 		/* assign these early, so that fb alloc can use them */
 		ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB :
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 6aee279..aa22f7b 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -445,13 +445,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	rg = ofbi->region;
 
-	/* FIXME probably should be a rwsem ... */
-	mutex_lock(&rg->mtx);
-	while (rg->ref) {
-		mutex_unlock(&rg->mtx);
-		schedule();
-		mutex_lock(&rg->mtx);
-	}
+	down_write(&rg->lock);
 
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
@@ -483,7 +477,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	r = count;
 out:
-	mutex_unlock(&rg->mtx);
+	up_write(&rg->lock);
 
 	unlock_fb_info(fbi);
 
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index db3aef5..195a760 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -27,6 +27,8 @@
 #define DEBUG
 #endif
 
+#include <linux/rwsem.h>
+
 #include <plat/display.h>
 
 #ifdef DEBUG
@@ -52,9 +54,8 @@ struct omapfb2_mem_region {
 	u8		type;		/* OMAPFB_PLANE_MEM_* */
 	bool		alloc;		/* allocated by the driver */
 	bool		map;		/* kernel mapped by the driver */
-	struct mutex    mtx;
-	unsigned int    ref;
 	atomic_t	map_count;
+	struct rw_semaphore lock;
 };
 
 /* appended to fb_info */
@@ -164,17 +165,13 @@ 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)
 {
-	mutex_lock(&rg->mtx);
-	rg->ref++;
-	mutex_unlock(&rg->mtx);
+	down_read(&rg->lock);
 	return rg;
 }
 
 static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
 {
-	mutex_lock(&rg->mtx);
-	rg->ref--;
-	mutex_unlock(&rg->mtx);
+	up_read(&rg->lock);
 }
 
 #endif
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 7/8] DSS2: OMAPFB: Make lockdep happy
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
                   ` (5 preceding siblings ...)
  2010-03-17 22:46 ` [PATCH v4 6/8] DSS2: OMAPFB: Convert the memory region locking to rwsem ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  2010-03-17 22:46 ` [PATCH v4 8/8] DSS2: OMAPFB: Add some locking debug checks ville.syrjala
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

When more than one memory region needs to be lockd at the same time use
the memory region id to fix the order in which the locks are taken. Also
one needs to use the _nested() versions of the locking primitives. The
memory region id can serve as the lock class there as well.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-ioctl.c |   45 ++++++++++++++++++++++-------
 drivers/video/omap2/omapfb/omapfb-sysfs.c |    2 +-
 drivers/video/omap2/omapfb/omapfb.h       |    2 +-
 3 files changed, 36 insertions(+), 13 deletions(-)

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;
 }
 
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v4 8/8] DSS2: OMAPFB: Add some locking debug checks
  2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
                   ` (6 preceding siblings ...)
  2010-03-17 22:46 ` [PATCH v4 7/8] DSS2: OMAPFB: Make lockdep happy ville.syrjala
@ 2010-03-17 22:46 ` ville.syrjala
  7 siblings, 0 replies; 9+ messages in thread
From: ville.syrjala @ 2010-03-17 22:46 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Imre Deak, linux-fbdev, linux-omap, Ville Syrjälä

From: Ville Syrj채l채 <ville.syrjala@nokia.com>

Trigger WARN_ON() messages from various places in the code in case the
memory region is not currently locked.

Signed-off-by: Ville Syrj채l채 <ville.syrjala@nokia.com>
---
 drivers/video/omap2/omapfb/omapfb-ioctl.c |    2 ++
 drivers/video/omap2/omapfb/omapfb-main.c  |    6 ++++++
 drivers/video/omap2/omapfb/omapfb-sysfs.c |    2 ++
 drivers/video/omap2/omapfb/omapfb.h       |    3 +++
 4 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index a3681da..64e70e0 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -222,6 +222,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	rg = ofbi->region;
 
 	down_write_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
 
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
@@ -252,6 +253,7 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
 	}
 
  out:
+	atomic_dec(&rg->lock_count);
 	up_write(&rg->lock);
 
 	return r;
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 2bd5b42..ac7625d 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -667,6 +667,8 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
 
 	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");
@@ -872,6 +874,8 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
 	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;
@@ -965,6 +969,8 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
 		fill_fb(fbi);
 #endif
 
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
 	for (i = 0; i < ofbi->num_overlays; i++) {
 		ovl = ofbi->overlays[i];
 
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 1b7cf57..cf2f478 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -446,6 +446,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 	rg = ofbi->region;
 
 	down_write_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
 
 	if (atomic_read(&rg->map_count)) {
 		r = -EBUSY;
@@ -477,6 +478,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
 
 	r = count;
 out:
+	atomic_dec(&rg->lock_count);
 	up_write(&rg->lock);
 
 	unlock_fb_info(fbi);
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 676b55d..1305fc9 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -56,6 +56,7 @@ struct omapfb2_mem_region {
 	bool		map;		/* kernel mapped by the driver */
 	atomic_t	map_count;
 	struct rw_semaphore lock;
+	atomic_t	lock_count;
 };
 
 /* appended to fb_info */
@@ -166,11 +167,13 @@ static inline struct omapfb2_mem_region *
 omapfb_get_mem_region(struct omapfb2_mem_region *rg)
 {
 	down_read_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
 	return rg;
 }
 
 static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg)
 {
+	atomic_dec(&rg->lock_count);
 	up_read(&rg->lock);
 }
 
-- 
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2010-03-17 22:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-17 22:46 omapfb mem_idx patchset ville.syrjala
2010-03-17 22:46 ` [PATCH v4 1/8] DSS2: OMAPFB: Refactor overlay address calculations ville.syrjala
2010-03-17 22:46 ` [PATCH v4 2/8] DSS2: OMAPFB: Check var even if there isn't memory ville.syrjala
2010-03-17 22:46 ` [PATCH v4 3/8] DSS2: OMAPFB: Skip unnecessary set_overlay_info() ville.syrjala
2010-03-17 22:46 ` [PATCH v4 4/8] DSS2: OMAPFB: Add support for switching memory regions ville.syrjala
2010-03-17 22:46 ` [PATCH v4 5/8] DSS2: OMAPFB: Add locking for " ville.syrjala
2010-03-17 22:46 ` [PATCH v4 6/8] DSS2: OMAPFB: Convert the memory region locking to rwsem ville.syrjala
2010-03-17 22:46 ` [PATCH v4 7/8] DSS2: OMAPFB: Make lockdep happy ville.syrjala
2010-03-17 22:46 ` [PATCH v4 8/8] DSS2: OMAPFB: Add some locking debug checks ville.syrjala

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).