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 | |
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>
-rw-r--r-- | drivers/video/atafb.c | 7 | ||||
-rw-r--r-- | drivers/video/atmel_lcdfb.c | 2 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 13 | ||||
-rw-r--r-- | drivers/video/fsl-diu-fb.c | 14 | ||||
-rw-r--r-- | drivers/video/i810/i810_main.c | 2 | ||||
-rw-r--r-- | drivers/video/matrox/matroxfb_base.c | 3 | ||||
-rw-r--r-- | drivers/video/matrox/matroxfb_crtc2.c | 5 | ||||
-rw-r--r-- | drivers/video/mx3fb.c | 17 | ||||
-rw-r--r-- | drivers/video/omap/omapfb_main.c | 4 | ||||
-rw-r--r-- | drivers/video/platinumfb.c | 2 | ||||
-rw-r--r-- | drivers/video/pxafb.c | 2 | ||||
-rw-r--r-- | drivers/video/sh7760fb.c | 19 | ||||
-rw-r--r-- | drivers/video/sis/sis_main.c | 2 | ||||
-rw-r--r-- | drivers/video/sm501fb.c | 21 | ||||
-rw-r--r-- | drivers/video/w100fb.c | 2 | ||||
-rw-r--r-- | include/linux/fb.h | 1 |
16 files changed, 74 insertions, 42 deletions
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index 018850c116c6..497ff8af03ed 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c | |||
@@ -2414,7 +2414,10 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
2414 | if (err) | 2414 | if (err) |
2415 | return err; | 2415 | return err; |
2416 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 2416 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
2417 | return fbhw->encode_fix(fix, &par); | 2417 | mutex_lock(&info->mm_lock); |
2418 | err = fbhw->encode_fix(fix, &par); | ||
2419 | mutex_unlock(&info->mm_lock); | ||
2420 | return err; | ||
2418 | } | 2421 | } |
2419 | 2422 | ||
2420 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) | 2423 | static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -2743,7 +2746,9 @@ static int atafb_set_par(struct fb_info *info) | |||
2743 | 2746 | ||
2744 | /* Decode wanted screen parameters */ | 2747 | /* Decode wanted screen parameters */ |
2745 | fbhw->decode_var(&info->var, par); | 2748 | fbhw->decode_var(&info->var, par); |
2749 | mutex_lock(&info->mm_lock); | ||
2746 | fbhw->encode_fix(&info->fix, par); | 2750 | fbhw->encode_fix(&info->fix, par); |
2751 | mutex_unlock(&info->mm_lock); | ||
2747 | 2752 | ||
2748 | /* Set new videomode */ | 2753 | /* Set new videomode */ |
2749 | ata_set_par(par); | 2754 | ata_set_par(par); |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 5afd64482f55..cb88394ba995 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -270,7 +270,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) | |||
270 | 270 | ||
271 | smem_len = (var->xres_virtual * var->yres_virtual | 271 | smem_len = (var->xres_virtual * var->yres_virtual |
272 | * ((var->bits_per_pixel + 7) / 8)); | 272 | * ((var->bits_per_pixel + 7) / 8)); |
273 | mutex_lock(&info->mm_lock); | ||
273 | info->fix.smem_len = max(smem_len, sinfo->smem_len); | 274 | info->fix.smem_len = max(smem_len, sinfo->smem_len); |
275 | mutex_unlock(&info->mm_lock); | ||
274 | 276 | ||
275 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, | 277 | info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, |
276 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); | 278 | (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index f8a09bf8d0cd..53ea05645ff8 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1310,8 +1310,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, | |||
1310 | 1310 | ||
1311 | static int | 1311 | static int |
1312 | fb_mmap(struct file *file, struct vm_area_struct * vma) | 1312 | fb_mmap(struct file *file, struct vm_area_struct * vma) |
1313 | __acquires(&info->lock) | ||
1314 | __releases(&info->lock) | ||
1315 | { | 1313 | { |
1316 | int fbidx = iminor(file->f_path.dentry->d_inode); | 1314 | int fbidx = iminor(file->f_path.dentry->d_inode); |
1317 | struct fb_info *info = registered_fb[fbidx]; | 1315 | struct fb_info *info = registered_fb[fbidx]; |
@@ -1325,16 +1323,14 @@ __releases(&info->lock) | |||
1325 | off = vma->vm_pgoff << PAGE_SHIFT; | 1323 | off = vma->vm_pgoff << PAGE_SHIFT; |
1326 | if (!fb) | 1324 | if (!fb) |
1327 | return -ENODEV; | 1325 | return -ENODEV; |
1326 | mutex_lock(&info->mm_lock); | ||
1328 | if (fb->fb_mmap) { | 1327 | if (fb->fb_mmap) { |
1329 | int res; | 1328 | int res; |
1330 | mutex_lock(&info->lock); | ||
1331 | res = fb->fb_mmap(info, vma); | 1329 | res = fb->fb_mmap(info, vma); |
1332 | mutex_unlock(&info->lock); | 1330 | mutex_unlock(&info->mm_lock); |
1333 | return res; | 1331 | return res; |
1334 | } | 1332 | } |
1335 | 1333 | ||
1336 | mutex_lock(&info->lock); | ||
1337 | |||
1338 | /* frame buffer memory */ | 1334 | /* frame buffer memory */ |
1339 | start = info->fix.smem_start; | 1335 | start = info->fix.smem_start; |
1340 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); | 1336 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); |
@@ -1342,13 +1338,13 @@ __releases(&info->lock) | |||
1342 | /* memory mapped io */ | 1338 | /* memory mapped io */ |
1343 | off -= len; | 1339 | off -= len; |
1344 | if (info->var.accel_flags) { | 1340 | if (info->var.accel_flags) { |
1345 | mutex_unlock(&info->lock); | 1341 | mutex_unlock(&info->mm_lock); |
1346 | return -EINVAL; | 1342 | return -EINVAL; |
1347 | } | 1343 | } |
1348 | start = info->fix.mmio_start; | 1344 | start = info->fix.mmio_start; |
1349 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); | 1345 | len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); |
1350 | } | 1346 | } |
1351 | mutex_unlock(&info->lock); | 1347 | mutex_unlock(&info->mm_lock); |
1352 | start &= PAGE_MASK; | 1348 | start &= PAGE_MASK; |
1353 | if ((vma->vm_end - vma->vm_start + off) > len) | 1349 | if ((vma->vm_end - vma->vm_start + off) > len) |
1354 | return -EINVAL; | 1350 | return -EINVAL; |
@@ -1518,6 +1514,7 @@ register_framebuffer(struct fb_info *fb_info) | |||
1518 | break; | 1514 | break; |
1519 | fb_info->node = i; | 1515 | fb_info->node = i; |
1520 | mutex_init(&fb_info->lock); | 1516 | mutex_init(&fb_info->lock); |
1517 | mutex_init(&fb_info->mm_lock); | ||
1521 | 1518 | ||
1522 | fb_info->dev = device_create(fb_class, fb_info->device, | 1519 | fb_info->dev = device_create(fb_class, fb_info->device, |
1523 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); | 1520 | MKDEV(FB_MAJOR, i), NULL, "fb%d", i); |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index f153c581cbd7..0bf2190928d0 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 | /* |
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 2e940199fc89..71960672d721 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) | |||
1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | 1090 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); |
1091 | 1091 | ||
1092 | strcpy(fix->id, "I810"); | 1092 | strcpy(fix->id, "I810"); |
1093 | mutex_lock(&info->mm_lock); | ||
1093 | fix->smem_start = par->fb.physical; | 1094 | fix->smem_start = par->fb.physical; |
1094 | fix->smem_len = par->fb.size; | 1095 | fix->smem_len = par->fb.size; |
1096 | mutex_unlock(&info->mm_lock); | ||
1095 | fix->type = FB_TYPE_PACKED_PIXELS; | 1097 | fix->type = FB_TYPE_PACKED_PIXELS; |
1096 | fix->type_aux = 0; | 1098 | fix->type_aux = 0; |
1097 | fix->xpanstep = 8; | 1099 | fix->xpanstep = 8; |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 8e7a275df50c..59c3a2e14913 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2) | |||
724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; | 724 | struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; |
725 | DBG(__func__) | 725 | DBG(__func__) |
726 | 726 | ||
727 | mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
727 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); | 728 | fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); |
728 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); | 729 | fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); |
730 | mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock); | ||
729 | } | 731 | } |
730 | 732 | ||
731 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 733 | static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
@@ -2081,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm | |||
2081 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); | 2083 | spin_lock_init(&ACCESS_FBINFO(lock.accel)); |
2082 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); | 2084 | init_rwsem(&ACCESS_FBINFO(crtc2.lock)); |
2083 | init_rwsem(&ACCESS_FBINFO(altout.lock)); | 2085 | init_rwsem(&ACCESS_FBINFO(altout.lock)); |
2086 | mutex_init(&ACCESS_FBINFO(fbcon).mm_lock); | ||
2084 | ACCESS_FBINFO(irq_flags) = 0; | 2087 | ACCESS_FBINFO(irq_flags) = 0; |
2085 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); | 2088 | init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); |
2086 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); | 2089 | init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); |
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 7ac4c5f6145d..909e10a11898 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c | |||
@@ -289,13 +289,16 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { | |||
289 | #undef m2info | 289 | #undef m2info |
290 | } | 290 | } |
291 | 291 | ||
292 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { | 292 | static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) |
293 | { | ||
293 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; | 294 | struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; |
294 | 295 | ||
295 | strcpy(fix->id, "MATROX DH"); | 296 | strcpy(fix->id, "MATROX DH"); |
296 | 297 | ||
298 | mutex_lock(&m2info->fbcon.mm_lock); | ||
297 | fix->smem_start = m2info->video.base; | 299 | fix->smem_start = m2info->video.base; |
298 | fix->smem_len = m2info->video.len_usable; | 300 | fix->smem_len = m2info->video.len_usable; |
301 | mutex_unlock(&m2info->fbcon.mm_lock); | ||
299 | fix->ypanstep = 1; | 302 | fix->ypanstep = 1; |
300 | fix->ywrapstep = 0; | 303 | fix->ywrapstep = 0; |
301 | fix->xpanstep = 8; /* TBD */ | 304 | fix->xpanstep = 8; /* TBD */ |
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 | ||
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 060d72fe57cb..4ea99bfc37b4 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi) | |||
393 | 393 | ||
394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; | 394 | rg = &plane->fbdev->mem_desc.region[plane->idx]; |
395 | fbi->screen_base = rg->vaddr; | 395 | fbi->screen_base = rg->vaddr; |
396 | mutex_lock(&fbi->mm_lock); | ||
396 | fix->smem_start = rg->paddr; | 397 | fix->smem_start = rg->paddr; |
397 | fix->smem_len = rg->size; | 398 | fix->smem_len = rg->size; |
399 | mutex_unlock(&fbi->mm_lock); | ||
398 | 400 | ||
399 | fix->type = FB_TYPE_PACKED_PIXELS; | 401 | fix->type = FB_TYPE_PACKED_PIXELS; |
400 | bpp = var->bits_per_pixel; | 402 | bpp = var->bits_per_pixel; |
@@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) | |||
886 | * plane memory is dealloce'd, the other | 888 | * plane memory is dealloce'd, the other |
887 | * screen parameters in var / fix are invalid. | 889 | * screen parameters in var / fix are invalid. |
888 | */ | 890 | */ |
891 | mutex_lock(&fbi->mm_lock); | ||
889 | fbi->fix.smem_start = 0; | 892 | fbi->fix.smem_start = 0; |
890 | fbi->fix.smem_len = 0; | 893 | fbi->fix.smem_len = 0; |
894 | mutex_unlock(&fbi->mm_lock); | ||
891 | } | 895 | } |
892 | } | 896 | } |
893 | } | 897 | } |
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 03b3670130a0..bacfabd9ce16 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info) | |||
141 | offset = 0x10; | 141 | offset = 0x10; |
142 | 142 | ||
143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; | 143 | info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; |
144 | mutex_lock(&info->mm_lock); | ||
144 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; | 145 | info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; |
146 | mutex_unlock(&info->mm_lock); | ||
145 | info->fix.visual = (pinfo->cmode == CMODE_8) ? | 147 | info->fix.visual = (pinfo->cmode == CMODE_8) ? |
146 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; | 148 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; |
147 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) | 149 | info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0889d50c3288..6506117c134b 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) | |||
815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); | 815 | ofb->video_mem_phys = virt_to_phys(ofb->video_mem); |
816 | ofb->video_mem_size = size; | 816 | ofb->video_mem_size = size; |
817 | 817 | ||
818 | mutex_lock(&ofb->fb.mm_lock); | ||
818 | ofb->fb.fix.smem_start = ofb->video_mem_phys; | 819 | ofb->fb.fix.smem_start = ofb->video_mem_phys; |
819 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; | 820 | ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; |
821 | mutex_unlock(&ofb->fb.mm_lock); | ||
820 | ofb->fb.screen_base = ofb->video_mem; | 822 | ofb->fb.screen_base = ofb->video_mem; |
821 | return 0; | 823 | return 0; |
822 | } | 824 | } |
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c index 653bdfee3057..9f6d6e61f0cc 100644 --- a/drivers/video/sh7760fb.c +++ b/drivers/video/sh7760fb.c | |||
@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno, | |||
120 | return 0; | 120 | return 0; |
121 | } | 121 | } |
122 | 122 | ||
123 | static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info, | ||
124 | unsigned long stride) | ||
125 | { | ||
126 | memset(fix, 0, sizeof(struct fb_fix_screeninfo)); | ||
127 | strcpy(fix->id, "sh7760-lcdc"); | ||
128 | |||
129 | fix->smem_start = (unsigned long)info->screen_base; | ||
130 | fix->smem_len = info->screen_size; | ||
131 | |||
132 | fix->line_length = stride; | ||
133 | } | ||
134 | |||
135 | static int sh7760fb_get_color_info(struct device *dev, | 123 | static int sh7760fb_get_color_info(struct device *dev, |
136 | u16 lddfr, int *bpp, int *gray) | 124 | u16 lddfr, int *bpp, int *gray) |
137 | { | 125 | { |
@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info) | |||
334 | 322 | ||
335 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ | 323 | iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ |
336 | 324 | ||
337 | encode_fix(&info->fix, info, stride); | 325 | info->fix.line_length = stride; |
326 | |||
338 | sh7760fb_check_var(&info->var, info); | 327 | sh7760fb_check_var(&info->var, info); |
339 | 328 | ||
340 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ | 329 | sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ |
@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info) | |||
435 | 424 | ||
436 | info->screen_base = fbmem; | 425 | info->screen_base = fbmem; |
437 | info->screen_size = vram; | 426 | info->screen_size = vram; |
427 | info->fix.smem_start = (unsigned long)info->screen_base; | ||
428 | info->fix.smem_len = info->screen_size; | ||
438 | 429 | ||
439 | return 0; | 430 | return 0; |
440 | } | 431 | } |
@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) | |||
520 | info->var.transp.length = 0; | 511 | info->var.transp.length = 0; |
521 | info->var.transp.msb_right = 0; | 512 | info->var.transp.msb_right = 0; |
522 | 513 | ||
514 | strcpy(info->fix.id, "sh7760-lcdc"); | ||
515 | |||
523 | /* set the DON2 bit now, before cmap allocation, as it will randomize | 516 | /* set the DON2 bit now, before cmap allocation, as it will randomize |
524 | * palette memory. | 517 | * palette memory. |
525 | */ | 518 | */ |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 7072d19080d5..fd33455389b8 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) | |||
1847 | 1847 | ||
1848 | strcpy(fix->id, ivideo->myid); | 1848 | strcpy(fix->id, ivideo->myid); |
1849 | 1849 | ||
1850 | mutex_lock(&info->mm_lock); | ||
1850 | fix->smem_start = ivideo->video_base + ivideo->video_offset; | 1851 | fix->smem_start = ivideo->video_base + ivideo->video_offset; |
1851 | fix->smem_len = ivideo->sisfb_mem; | 1852 | fix->smem_len = ivideo->sisfb_mem; |
1853 | mutex_unlock(&info->mm_lock); | ||
1852 | fix->type = FB_TYPE_PACKED_PIXELS; | 1854 | fix->type = FB_TYPE_PACKED_PIXELS; |
1853 | fix->type_aux = 0; | 1855 | fix->type_aux = 0; |
1854 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 1856 | fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index eb5d73a06702..98f24f0ec00d 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
145 | #define SM501_MEMF_ACCEL (8) | 145 | #define SM501_MEMF_ACCEL (8) |
146 | 146 | ||
147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, |
148 | unsigned int why, size_t size) | 148 | unsigned int why, size_t size, u32 smem_len) |
149 | { | 149 | { |
150 | struct sm501fb_par *par; | 150 | struct sm501fb_par *par; |
151 | struct fb_info *fbi; | 151 | struct fb_info *fbi; |
@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
172 | if (ptr > 0) | 172 | if (ptr > 0) |
173 | ptr &= ~(PAGE_SIZE - 1); | 173 | ptr &= ~(PAGE_SIZE - 1); |
174 | 174 | ||
175 | if (fbi && ptr < fbi->fix.smem_len) | 175 | if (fbi && ptr < smem_len) |
176 | return -ENOMEM; | 176 | return -ENOMEM; |
177 | 177 | ||
178 | break; | 178 | break; |
@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | |||
197 | 197 | ||
198 | case SM501_MEMF_ACCEL: | 198 | case SM501_MEMF_ACCEL: |
199 | fbi = inf->fb[HEAD_CRT]; | 199 | fbi = inf->fb[HEAD_CRT]; |
200 | ptr = fbi ? fbi->fix.smem_len : 0; | 200 | ptr = fbi ? smem_len : 0; |
201 | 201 | ||
202 | fbi = inf->fb[HEAD_PANEL]; | 202 | fbi = inf->fb[HEAD_PANEL]; |
203 | if (fbi) { | 203 | if (fbi) { |
@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
413 | unsigned int mem_type; | 413 | unsigned int mem_type; |
414 | unsigned int clock_type; | 414 | unsigned int clock_type; |
415 | unsigned int head_addr; | 415 | unsigned int head_addr; |
416 | unsigned int smem_len; | ||
416 | 417 | ||
417 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", | 418 | dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", |
418 | __func__, var->xres, var->yres, var->bits_per_pixel, | 419 | __func__, var->xres, var->yres, var->bits_per_pixel, |
@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info, | |||
453 | 454 | ||
454 | /* allocate fb memory within 501 */ | 455 | /* allocate fb memory within 501 */ |
455 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; | 456 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; |
456 | info->fix.smem_len = info->fix.line_length * var->yres_virtual; | 457 | smem_len = info->fix.line_length * var->yres_virtual; |
457 | 458 | ||
458 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, | 459 | dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, |
459 | info->fix.line_length); | 460 | info->fix.line_length); |
460 | 461 | ||
461 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, | 462 | if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) { |
462 | info->fix.smem_len)) { | ||
463 | dev_err(fbi->dev, "no memory available\n"); | 463 | dev_err(fbi->dev, "no memory available\n"); |
464 | return -ENOMEM; | 464 | return -ENOMEM; |
465 | } | 465 | } |
466 | 466 | ||
467 | mutex_lock(&info->mm_lock); | ||
467 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; | 468 | info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; |
469 | info->fix.smem_len = smem_len; | ||
470 | mutex_unlock(&info->mm_lock); | ||
468 | 471 | ||
469 | info->screen_base = fbi->fbmem + par->screen.sm_addr; | 472 | info->screen_base = fbi->fbmem + par->screen.sm_addr; |
470 | info->screen_size = info->fix.smem_len; | 473 | info->screen_size = info->fix.smem_len; |
@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info) | |||
637 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { | 640 | if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { |
638 | /* the head is displaying panel data... */ | 641 | /* the head is displaying panel data... */ |
639 | 642 | ||
640 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); | 643 | sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0, |
644 | info->fix.smem_len); | ||
641 | goto out_update; | 645 | goto out_update; |
642 | } | 646 | } |
643 | 647 | ||
@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) | |||
1289 | 1293 | ||
1290 | par->cursor_regs = info->regs + reg_base; | 1294 | par->cursor_regs = info->regs + reg_base; |
1291 | 1295 | ||
1292 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); | 1296 | ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024, |
1297 | fbi->fix.smem_len); | ||
1293 | if (ret < 0) | 1298 | if (ret < 0) |
1294 | return ret; | 1299 | return ret; |
1295 | 1300 | ||
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index d0674f1e3f10..8a141c2c637b 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
523 | info->fix.ywrapstep = 0; | 523 | info->fix.ywrapstep = 0; |
524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; | 524 | info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; |
525 | 525 | ||
526 | mutex_lock(&info->mm_lock); | ||
526 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { | 527 | if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { |
527 | par->extmem_active = 1; | 528 | par->extmem_active = 1; |
528 | info->fix.smem_len = par->mach->mem->size+1; | 529 | info->fix.smem_len = par->mach->mem->size+1; |
@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info) | |||
530 | par->extmem_active = 0; | 531 | par->extmem_active = 0; |
531 | info->fix.smem_len = MEM_INT_SIZE+1; | 532 | info->fix.smem_len = MEM_INT_SIZE+1; |
532 | } | 533 | } |
534 | mutex_unlock(&info->mm_lock); | ||
533 | 535 | ||
534 | w100fb_activate_var(par); | 536 | w100fb_activate_var(par); |
535 | } | 537 | } |
diff --git a/include/linux/fb.h b/include/linux/fb.h index dd68358996b7..f847df9e99b6 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -819,6 +819,7 @@ struct fb_info { | |||
819 | int node; | 819 | int node; |
820 | int flags; | 820 | int flags; |
821 | struct mutex lock; /* Lock for open/release/ioctl funcs */ | 821 | struct mutex lock; /* Lock for open/release/ioctl funcs */ |
822 | struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ | ||
822 | struct fb_var_screeninfo var; /* Current var */ | 823 | struct fb_var_screeninfo var; /* Current var */ |
823 | struct fb_fix_screeninfo fix; /* Current fix */ | 824 | struct fb_fix_screeninfo fix; /* Current fix */ |
824 | struct fb_monspecs monspecs; /* Current Monitor specs */ | 825 | struct fb_monspecs monspecs; /* Current Monitor specs */ |