diff options
author | Ville Syrjälä <ville.syrjala@nokia.com> | 2010-03-17 20:43:23 +0200 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@nokia.com> | 2010-08-03 15:18:46 +0300 |
commit | 430571d59a0b51c6541c153ad8b08e72fef26098 (patch) | |
tree | 8ad99c778576b985f5fbe6de57d1ea4dea0981c3 /drivers/video/omap2/omapfb/omapfb-main.c | |
parent | 078ff546a806b2c2ab74c25c8edd4c6d4680656a (diff) | |
download | lwn-430571d59a0b51c6541c153ad8b08e72fef26098.tar.gz lwn-430571d59a0b51c6541c153ad8b08e72fef26098.zip |
OMAP: DSS2: OMAPFB: Add locking for memory regions
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>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
Diffstat (limited to 'drivers/video/omap2/omapfb/omapfb-main.c')
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4a0588022b33..eb4338bbaa2b 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1019,36 +1019,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; @@ -1064,8 +1076,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; } @@ -1073,14 +1089,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 = { @@ -1096,6 +1116,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; @@ -1103,14 +1124,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; @@ -1122,11 +1143,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 @@ -1897,6 +1930,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 : @@ -1927,7 +1961,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; @@ -1948,7 +1988,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; |