diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2009-06-30 14:41:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-30 21:56:00 -0400 |
commit | 537a1bf059fa312355696fa6db80726e655e7f17 (patch) | |
tree | 4f5b3c6917311cfefad21eaf3dd92978334282de /drivers/video/mx3fb.c | |
parent | 70d6027ff2bc8bab180273b77e7ab3e8a62cca51 (diff) |
fbdev: add mutex for fb_mmap locking
Add a mutex to avoid a circular locking problem between the mm layer
semaphore and fbdev ioctl mutex through the fb_mmap() call.
Also, add mutex to all places where smem_start and smem_len fields change
so the mutex inside the fb_mmap() is actually used. Changing of these
fields before calling the framebuffer_register() are not mutexed.
This is 2.6.31 material. It removes one lockdep (fb_mmap() and
register_framebuffer()) but there is still another one (fb_release() and
register_framebuffer()). It also cleans up handling of the smem_start and
smem_len fields used by mutexed section of the fb_mmap().
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/mx3fb.c')
-rw-r--r-- | drivers/video/mx3fb.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index b7af5256e887..567fb944bd2a 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
@@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp) | |||
669 | } | 669 | } |
670 | 670 | ||
671 | static int mx3fb_blank(int blank, struct fb_info *fbi); | 671 | static int mx3fb_blank(int blank, struct fb_info *fbi); |
672 | static int mx3fb_map_video_memory(struct fb_info *fbi); | 672 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len); |
673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); | 673 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); |
674 | 674 | ||
675 | /** | 675 | /** |
@@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi) | |||
742 | if (fbi->fix.smem_start) | 742 | if (fbi->fix.smem_start) |
743 | mx3fb_unmap_video_memory(fbi); | 743 | mx3fb_unmap_video_memory(fbi); |
744 | 744 | ||
745 | fbi->fix.smem_len = mem_len; | 745 | if (mx3fb_map_video_memory(fbi, mem_len) < 0) { |
746 | if (mx3fb_map_video_memory(fbi) < 0) { | ||
747 | mutex_unlock(&mx3_fbi->mutex); | 746 | mutex_unlock(&mx3_fbi->mutex); |
748 | return -ENOMEM; | 747 | return -ENOMEM; |
749 | } | 748 | } |
@@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
1198 | /** | 1197 | /** |
1199 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. | 1198 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. |
1200 | * @fbi: framebuffer information pointer | 1199 | * @fbi: framebuffer information pointer |
1200 | * @mem_len: length of mapped memory | ||
1201 | * @return: Error code indicating success or failure | 1201 | * @return: Error code indicating success or failure |
1202 | * | 1202 | * |
1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to | 1203 | * This buffer is remapped into a non-cached, non-buffered, memory region to |
@@ -1205,23 +1205,26 @@ static int mx3fb_resume(struct platform_device *pdev) | |||
1205 | * area is remapped, all virtual memory access to the video memory should occur | 1205 | * area is remapped, all virtual memory access to the video memory should occur |
1206 | * at the new region. | 1206 | * at the new region. |
1207 | */ | 1207 | */ |
1208 | static int mx3fb_map_video_memory(struct fb_info *fbi) | 1208 | static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len) |
1209 | { | 1209 | { |
1210 | int retval = 0; | 1210 | int retval = 0; |
1211 | dma_addr_t addr; | 1211 | dma_addr_t addr; |
1212 | 1212 | ||
1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, | 1213 | fbi->screen_base = dma_alloc_writecombine(fbi->device, |
1214 | fbi->fix.smem_len, | 1214 | mem_len, |
1215 | &addr, GFP_DMA); | 1215 | &addr, GFP_DMA); |
1216 | 1216 | ||
1217 | if (!fbi->screen_base) { | 1217 | if (!fbi->screen_base) { |
1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", | 1218 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", |
1219 | fbi->fix.smem_len); | 1219 | mem_len); |
1220 | retval = -EBUSY; | 1220 | retval = -EBUSY; |
1221 | goto err0; | 1221 | goto err0; |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | mutex_lock(&fbi->mm_lock); | ||
1224 | fbi->fix.smem_start = addr; | 1225 | fbi->fix.smem_start = addr; |
1226 | fbi->fix.smem_len = mem_len; | ||
1227 | mutex_unlock(&fbi->mm_lock); | ||
1225 | 1228 | ||
1226 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", | 1229 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", |
1227 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); | 1230 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); |
@@ -1251,8 +1254,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi) | |||
1251 | fbi->screen_base, fbi->fix.smem_start); | 1254 | fbi->screen_base, fbi->fix.smem_start); |
1252 | 1255 | ||
1253 | fbi->screen_base = 0; | 1256 | fbi->screen_base = 0; |
1257 | mutex_lock(&fbi->mm_lock); | ||
1254 | fbi->fix.smem_start = 0; | 1258 | fbi->fix.smem_start = 0; |
1255 | fbi->fix.smem_len = 0; | 1259 | fbi->fix.smem_len = 0; |
1260 | mutex_unlock(&fbi->mm_lock); | ||
1256 | return 0; | 1261 | return 0; |
1257 | } | 1262 | } |
1258 | 1263 | ||