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/fsl-diu-fb.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/fsl-diu-fb.c')
-rw-r--r-- | drivers/video/fsl-diu-fb.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index f153c581cbd..0bf2190928d 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info) | |||
750 | static int map_video_memory(struct fb_info *info) | 750 | static int map_video_memory(struct fb_info *info) |
751 | { | 751 | { |
752 | phys_addr_t phys; | 752 | phys_addr_t phys; |
753 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; | ||
753 | 754 | ||
754 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | 755 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); |
755 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | 756 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); |
756 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | 757 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); |
758 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); | ||
757 | 759 | ||
758 | info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; | 760 | info->screen_base = fsl_diu_alloc(smem_len, &phys); |
759 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len); | ||
760 | info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys); | ||
761 | if (info->screen_base == NULL) { | 761 | if (info->screen_base == NULL) { |
762 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 762 | printk(KERN_ERR "Unable to allocate fb memory\n"); |
763 | return -ENOMEM; | 763 | return -ENOMEM; |
764 | } | 764 | } |
765 | mutex_lock(&info->mm_lock); | ||
765 | info->fix.smem_start = (unsigned long) phys; | 766 | info->fix.smem_start = (unsigned long) phys; |
767 | info->fix.smem_len = smem_len; | ||
768 | mutex_unlock(&info->mm_lock); | ||
766 | info->screen_size = info->fix.smem_len; | 769 | info->screen_size = info->fix.smem_len; |
767 | 770 | ||
768 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | 771 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", |
769 | info->fix.smem_start, | 772 | info->fix.smem_start, info->fix.smem_len); |
770 | info->fix.smem_len); | ||
771 | pr_debug("screen base %p\n", info->screen_base); | 773 | pr_debug("screen base %p\n", info->screen_base); |
772 | 774 | ||
773 | return 0; | 775 | return 0; |
@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info) | |||
776 | static void unmap_video_memory(struct fb_info *info) | 778 | static void unmap_video_memory(struct fb_info *info) |
777 | { | 779 | { |
778 | fsl_diu_free(info->screen_base, info->fix.smem_len); | 780 | fsl_diu_free(info->screen_base, info->fix.smem_len); |
781 | mutex_lock(&info->mm_lock); | ||
779 | info->screen_base = NULL; | 782 | info->screen_base = NULL; |
780 | info->fix.smem_start = 0; | 783 | info->fix.smem_start = 0; |
781 | info->fix.smem_len = 0; | 784 | info->fix.smem_len = 0; |
785 | mutex_unlock(&info->mm_lock); | ||
782 | } | 786 | } |
783 | 787 | ||
784 | /* | 788 | /* |