Commit 537a1bf0 authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Linus Torvalds

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: default avatarKrzysztof 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 70d6027f
...@@ -2414,7 +2414,10 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) ...@@ -2414,7 +2414,10 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
if (err) if (err)
return err; return err;
memset(fix, 0, sizeof(struct fb_fix_screeninfo)); memset(fix, 0, sizeof(struct fb_fix_screeninfo));
return fbhw->encode_fix(fix, &par); mutex_lock(&info->mm_lock);
err = fbhw->encode_fix(fix, &par);
mutex_unlock(&info->mm_lock);
return err;
} }
static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info) 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,7 +2746,9 @@ static int atafb_set_par(struct fb_info *info)
/* Decode wanted screen parameters */ /* Decode wanted screen parameters */
fbhw->decode_var(&info->var, par); fbhw->decode_var(&info->var, par);
mutex_lock(&info->mm_lock);
fbhw->encode_fix(&info->fix, par); fbhw->encode_fix(&info->fix, par);
mutex_unlock(&info->mm_lock);
/* Set new videomode */ /* Set new videomode */
ata_set_par(par); ata_set_par(par);
......
...@@ -270,7 +270,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo) ...@@ -270,7 +270,9 @@ static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
smem_len = (var->xres_virtual * var->yres_virtual smem_len = (var->xres_virtual * var->yres_virtual
* ((var->bits_per_pixel + 7) / 8)); * ((var->bits_per_pixel + 7) / 8));
mutex_lock(&info->mm_lock);
info->fix.smem_len = max(smem_len, sinfo->smem_len); info->fix.smem_len = max(smem_len, sinfo->smem_len);
mutex_unlock(&info->mm_lock);
info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len, info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL); (dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
......
...@@ -1310,8 +1310,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, ...@@ -1310,8 +1310,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
static int static int
fb_mmap(struct file *file, struct vm_area_struct * vma) fb_mmap(struct file *file, struct vm_area_struct * vma)
__acquires(&info->lock)
__releases(&info->lock)
{ {
int fbidx = iminor(file->f_path.dentry->d_inode); int fbidx = iminor(file->f_path.dentry->d_inode);
struct fb_info *info = registered_fb[fbidx]; struct fb_info *info = registered_fb[fbidx];
...@@ -1325,16 +1323,14 @@ __releases(&info->lock) ...@@ -1325,16 +1323,14 @@ __releases(&info->lock)
off = vma->vm_pgoff << PAGE_SHIFT; off = vma->vm_pgoff << PAGE_SHIFT;
if (!fb) if (!fb)
return -ENODEV; return -ENODEV;
mutex_lock(&info->mm_lock);
if (fb->fb_mmap) { if (fb->fb_mmap) {
int res; int res;
mutex_lock(&info->lock);
res = fb->fb_mmap(info, vma); res = fb->fb_mmap(info, vma);
mutex_unlock(&info->lock); mutex_unlock(&info->mm_lock);
return res; return res;
} }
mutex_lock(&info->lock);
/* frame buffer memory */ /* frame buffer memory */
start = info->fix.smem_start; start = info->fix.smem_start;
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
...@@ -1342,13 +1338,13 @@ __releases(&info->lock) ...@@ -1342,13 +1338,13 @@ __releases(&info->lock)
/* memory mapped io */ /* memory mapped io */
off -= len; off -= len;
if (info->var.accel_flags) { if (info->var.accel_flags) {
mutex_unlock(&info->lock); mutex_unlock(&info->mm_lock);
return -EINVAL; return -EINVAL;
} }
start = info->fix.mmio_start; start = info->fix.mmio_start;
len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
} }
mutex_unlock(&info->lock); mutex_unlock(&info->mm_lock);
start &= PAGE_MASK; start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len) if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL; return -EINVAL;
...@@ -1518,6 +1514,7 @@ register_framebuffer(struct fb_info *fb_info) ...@@ -1518,6 +1514,7 @@ register_framebuffer(struct fb_info *fb_info)
break; break;
fb_info->node = i; fb_info->node = i;
mutex_init(&fb_info->lock); mutex_init(&fb_info->lock);
mutex_init(&fb_info->mm_lock);
fb_info->dev = device_create(fb_class, fb_info->device, fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), NULL, "fb%d", i); MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
......
...@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info) ...@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info)
static int map_video_memory(struct fb_info *info) static int map_video_memory(struct fb_info *info)
{ {
phys_addr_t phys; phys_addr_t phys;
u32 smem_len = info->fix.line_length * info->var.yres_virtual;
pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
pr_debug("info->fix.line_length = %d\n", info->fix.line_length); pr_debug("info->fix.line_length = %d\n", info->fix.line_length);
pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len);
info->fix.smem_len = info->fix.line_length * info->var.yres_virtual; info->screen_base = fsl_diu_alloc(smem_len, &phys);
pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys);
if (info->screen_base == NULL) { if (info->screen_base == NULL) {
printk(KERN_ERR "Unable to allocate fb memory\n"); printk(KERN_ERR "Unable to allocate fb memory\n");
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&info->mm_lock);
info->fix.smem_start = (unsigned long) phys; info->fix.smem_start = (unsigned long) phys;
info->fix.smem_len = smem_len;
mutex_unlock(&info->mm_lock);
info->screen_size = info->fix.smem_len; info->screen_size = info->fix.smem_len;
pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
info->fix.smem_start, info->fix.smem_start, info->fix.smem_len);
info->fix.smem_len);
pr_debug("screen base %p\n", info->screen_base); pr_debug("screen base %p\n", info->screen_base);
return 0; return 0;
...@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info) ...@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info)
static void unmap_video_memory(struct fb_info *info) static void unmap_video_memory(struct fb_info *info)
{ {
fsl_diu_free(info->screen_base, info->fix.smem_len); fsl_diu_free(info->screen_base, info->fix.smem_len);
mutex_lock(&info->mm_lock);
info->screen_base = NULL; info->screen_base = NULL;
info->fix.smem_start = 0; info->fix.smem_start = 0;
info->fix.smem_len = 0; info->fix.smem_len = 0;
mutex_unlock(&info->mm_lock);
} }
/* /*
......
...@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) ...@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
memset(fix, 0, sizeof(struct fb_fix_screeninfo)); memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "I810"); strcpy(fix->id, "I810");
mutex_lock(&info->mm_lock);
fix->smem_start = par->fb.physical; fix->smem_start = par->fb.physical;
fix->smem_len = par->fb.size; fix->smem_len = par->fb.size;
mutex_unlock(&info->mm_lock);
fix->type = FB_TYPE_PACKED_PIXELS; fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0; fix->type_aux = 0;
fix->xpanstep = 8; fix->xpanstep = 8;
......
...@@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2) ...@@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2)
struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix; struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
DBG(__func__) DBG(__func__)
mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock);
fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock);
} }
static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 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,6 +2083,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
spin_lock_init(&ACCESS_FBINFO(lock.accel)); spin_lock_init(&ACCESS_FBINFO(lock.accel));
init_rwsem(&ACCESS_FBINFO(crtc2.lock)); init_rwsem(&ACCESS_FBINFO(crtc2.lock));
init_rwsem(&ACCESS_FBINFO(altout.lock)); init_rwsem(&ACCESS_FBINFO(altout.lock));
mutex_init(&ACCESS_FBINFO(fbcon).mm_lock);
ACCESS_FBINFO(irq_flags) = 0; ACCESS_FBINFO(irq_flags) = 0;
init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait)); init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait));
init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait)); init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait));
......
...@@ -289,13 +289,16 @@ static int matroxfb_dh_release(struct fb_info* info, int user) { ...@@ -289,13 +289,16 @@ static int matroxfb_dh_release(struct fb_info* info, int user) {
#undef m2info #undef m2info
} }
static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) { static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
{
struct fb_fix_screeninfo *fix = &m2info->fbcon.fix; struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
strcpy(fix->id, "MATROX DH"); strcpy(fix->id, "MATROX DH");
mutex_lock(&m2info->fbcon.mm_lock);
fix->smem_start = m2info->video.base; fix->smem_start = m2info->video.base;
fix->smem_len = m2info->video.len_usable; fix->smem_len = m2info->video.len_usable;
mutex_unlock(&m2info->fbcon.mm_lock);
fix->ypanstep = 1; fix->ypanstep = 1;
fix->ywrapstep = 0; fix->ywrapstep = 0;
fix->xpanstep = 8; /* TBD */ fix->xpanstep = 8; /* TBD */
......
...@@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp) ...@@ -669,7 +669,7 @@ static uint32_t bpp_to_pixfmt(int bpp)
} }
static int mx3fb_blank(int blank, struct fb_info *fbi); static int mx3fb_blank(int blank, struct fb_info *fbi);
static int mx3fb_map_video_memory(struct fb_info *fbi); static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len);
static int mx3fb_unmap_video_memory(struct fb_info *fbi); static int mx3fb_unmap_video_memory(struct fb_info *fbi);
/** /**
...@@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi) ...@@ -742,8 +742,7 @@ static int mx3fb_set_par(struct fb_info *fbi)
if (fbi->fix.smem_start) if (fbi->fix.smem_start)
mx3fb_unmap_video_memory(fbi); mx3fb_unmap_video_memory(fbi);
fbi->fix.smem_len = mem_len; if (mx3fb_map_video_memory(fbi, mem_len) < 0) {
if (mx3fb_map_video_memory(fbi) < 0) {
mutex_unlock(&mx3_fbi->mutex); mutex_unlock(&mx3_fbi->mutex);
return -ENOMEM; return -ENOMEM;
} }
...@@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev) ...@@ -1198,6 +1197,7 @@ static int mx3fb_resume(struct platform_device *pdev)
/** /**
* mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
* @fbi: framebuffer information pointer * @fbi: framebuffer information pointer
* @mem_len: length of mapped memory
* @return: Error code indicating success or failure * @return: Error code indicating success or failure
* *
* This buffer is remapped into a non-cached, non-buffered, memory region to * 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,23 +1205,26 @@ static int mx3fb_resume(struct platform_device *pdev)
* area is remapped, all virtual memory access to the video memory should occur * area is remapped, all virtual memory access to the video memory should occur
* at the new region. * at the new region.
*/ */
static int mx3fb_map_video_memory(struct fb_info *fbi) static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len)
{ {
int retval = 0; int retval = 0;
dma_addr_t addr; dma_addr_t addr;
fbi->screen_base = dma_alloc_writecombine(fbi->device, fbi->screen_base = dma_alloc_writecombine(fbi->device,
fbi->fix.smem_len, mem_len,
&addr, GFP_DMA); &addr, GFP_DMA);
if (!fbi->screen_base) { if (!fbi->screen_base) {
dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
fbi->fix.smem_len); mem_len);
retval = -EBUSY; retval = -EBUSY;
goto err0; goto err0;
} }
mutex_lock(&fbi->mm_lock);
fbi->fix.smem_start = addr; fbi->fix.smem_start = addr;
fbi->fix.smem_len = mem_len;
mutex_unlock(&fbi->mm_lock);
dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
(uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); (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,8 +1254,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi)
fbi->screen_base, fbi->fix.smem_start); fbi->screen_base, fbi->fix.smem_start);
fbi->screen_base = 0; fbi->screen_base = 0;
mutex_lock(&fbi->mm_lock);
fbi->fix.smem_start = 0; fbi->fix.smem_start = 0;
fbi->fix.smem_len = 0; fbi->fix.smem_len = 0;
mutex_unlock(&fbi->mm_lock);
return 0; return 0;
} }
......
...@@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi) ...@@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi)
rg = &plane->fbdev->mem_desc.region[plane->idx]; rg = &plane->fbdev->mem_desc.region[plane->idx];
fbi->screen_base = rg->vaddr; fbi->screen_base = rg->vaddr;
mutex_lock(&fbi->mm_lock);
fix->smem_start = rg->paddr; fix->smem_start = rg->paddr;
fix->smem_len = rg->size; fix->smem_len = rg->size;
mutex_unlock(&fbi->mm_lock);
fix->type = FB_TYPE_PACKED_PIXELS; fix->type = FB_TYPE_PACKED_PIXELS;
bpp = var->bits_per_pixel; bpp = var->bits_per_pixel;
...@@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ...@@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
* plane memory is dealloce'd, the other * plane memory is dealloce'd, the other
* screen parameters in var / fix are invalid. * screen parameters in var / fix are invalid.
*/ */
mutex_lock(&fbi->mm_lock);
fbi->fix.smem_start = 0; fbi->fix.smem_start = 0;
fbi->fix.smem_len = 0; fbi->fix.smem_len = 0;
mutex_unlock(&fbi->mm_lock);
} }
} }
} }
......
...@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info) ...@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info)
offset = 0x10; offset = 0x10;
info->screen_base = pinfo->frame_buffer + init->fb_offset + offset; info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
mutex_lock(&info->mm_lock);
info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset; info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
mutex_unlock(&info->mm_lock);
info->fix.visual = (pinfo->cmode == CMODE_8) ? info->fix.visual = (pinfo->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode) info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
......
...@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) ...@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
ofb->video_mem_phys = virt_to_phys(ofb->video_mem); ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
ofb->video_mem_size = size; ofb->video_mem_size = size;
mutex_lock(&ofb->fb.mm_lock);
ofb->fb.fix.smem_start = ofb->video_mem_phys; ofb->fb.fix.smem_start = ofb->video_mem_phys;
ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual;
mutex_unlock(&ofb->fb.mm_lock);
ofb->fb.screen_base = ofb->video_mem; ofb->fb.screen_base = ofb->video_mem;
return 0; return 0;
} }
......
...@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno, ...@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno,
return 0; return 0;
} }
static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
unsigned long stride)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "sh7760-lcdc");
fix->smem_start = (unsigned long)info->screen_base;
fix->smem_len = info->screen_size;
fix->line_length = stride;
}
static int sh7760fb_get_color_info(struct device *dev, static int sh7760fb_get_color_info(struct device *dev,
u16 lddfr, int *bpp, int *gray) u16 lddfr, int *bpp, int *gray)
{ {
...@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info) ...@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info)
iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */ iowrite32(ldsarl, par->base + LDSARL); /* mem for lower half of DSTN */
encode_fix(&info->fix, info, stride); info->fix.line_length = stride;
sh7760fb_check_var(&info->var, info); sh7760fb_check_var(&info->var, info);
sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */ sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
...@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info) ...@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info)
info->screen_base = fbmem; info->screen_base = fbmem;
info->screen_size = vram; info->screen_size = vram;
info->fix.smem_start = (unsigned long)info->screen_base;
info->fix.smem_len = info->screen_size;
return 0; return 0;
} }
...@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev) ...@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev)
info->var.transp.length = 0; info->var.transp.length = 0;
info->var.transp.msb_right = 0; info->var.transp.msb_right = 0;
strcpy(info->fix.id, "sh7760-lcdc");
/* set the DON2 bit now, before cmap allocation, as it will randomize /* set the DON2 bit now, before cmap allocation, as it will randomize
* palette memory. * palette memory.
*/ */
......
...@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) ...@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
strcpy(fix->id, ivideo->myid); strcpy(fix->id, ivideo->myid);
mutex_lock(&info->mm_lock);
fix->smem_start = ivideo->video_base + ivideo->video_offset; fix->smem_start = ivideo->video_base + ivideo->video_offset;
fix->smem_len = ivideo->sisfb_mem; fix->smem_len = ivideo->sisfb_mem;
mutex_unlock(&info->mm_lock);
fix->type = FB_TYPE_PACKED_PIXELS; fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0; fix->type_aux = 0;
fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
......
...@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) ...@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
#define SM501_MEMF_ACCEL (8) #define SM501_MEMF_ACCEL (8)
static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
unsigned int why, size_t size) unsigned int why, size_t size, u32 smem_len)
{ {
struct sm501fb_par *par; struct sm501fb_par *par;
struct fb_info *fbi; struct fb_info *fbi;
...@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, ...@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
if (ptr > 0) if (ptr > 0)
ptr &= ~(PAGE_SIZE - 1); ptr &= ~(PAGE_SIZE - 1);
if (fbi && ptr < fbi->fix.smem_len) if (fbi && ptr < smem_len)
return -ENOMEM; return -ENOMEM;
break; break;
...@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, ...@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
case SM501_MEMF_ACCEL: case SM501_MEMF_ACCEL:
fbi = inf->fb[HEAD_CRT]; fbi = inf->fb[HEAD_CRT];
ptr = fbi ? fbi->fix.smem_len : 0; ptr = fbi ? smem_len : 0;
fbi = inf->fb[HEAD_PANEL]; fbi = inf->fb[HEAD_PANEL];
if (fbi) { if (fbi) {
...@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info, ...@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info,
unsigned int mem_type; unsigned int mem_type;
unsigned int clock_type; unsigned int clock_type;
unsigned int head_addr; unsigned int head_addr;
unsigned int smem_len;
dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
__func__, var->xres, var->yres, var->bits_per_pixel, __func__, var->xres, var->yres, var->bits_per_pixel,
...@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info, ...@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info,
/* allocate fb memory within 501 */ /* allocate fb memory within 501 */
info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
info->fix.smem_len = info->fix.line_length * var->yres_virtual; smem_len = info->fix.line_length * var->yres_virtual;
dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
info->fix.line_length); info->fix.line_length);
if (sm501_alloc_mem(fbi, &par->screen, mem_type, if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) {
info->fix.smem_len)) {
dev_err(fbi->dev, "no memory available\n"); dev_err(fbi->dev, "no memory available\n");
return -ENOMEM; return -ENOMEM;
} }
mutex_lock(&info->mm_lock);
info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
info->fix.smem_len = smem_len;
mutex_unlock(&info->mm_lock);
info->screen_base = fbi->fbmem + par->screen.sm_addr; info->screen_base = fbi->fbmem + par->screen.sm_addr;
info->screen_size = info->fix.smem_len; info->screen_size = info->fix.smem_len;
...@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info) ...@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info)
if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
/* the head is displaying panel data... */ /* the head is displaying panel data... */
sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0,
info->fix.smem_len);
goto out_update; goto out_update;
} }
...@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) ...@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
par->cursor_regs = info->regs + reg_base; par->cursor_regs = info->regs + reg_base;
ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024); ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024,
fbi->fix.smem_len);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info) ...@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info)
info->fix.ywrapstep = 0; info->fix.ywrapstep = 0;
info->fix.line_length = par->xres * BITS_PER_PIXEL / 8; info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
mutex_lock(&info->mm_lock);
if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) { if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
par->extmem_active = 1; par->extmem_active = 1;
info->fix.smem_len = par->mach->mem->size+1; info->fix.smem_len = par->mach->mem->size+1;
...@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info) ...@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info)
par->extmem_active = 0; par->extmem_active = 0;
info->fix.smem_len = MEM_INT_SIZE+1; info->fix.smem_len = MEM_INT_SIZE+1;
} }
mutex_unlock(&info->mm_lock);
w100fb_activate_var(par); w100fb_activate_var(par);
} }
......
...@@ -819,6 +819,7 @@ struct fb_info { ...@@ -819,6 +819,7 @@ struct fb_info {
int node; int node;
int flags; int flags;
struct mutex lock; /* Lock for open/release/ioctl funcs */ struct mutex lock; /* Lock for open/release/ioctl funcs */
struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
struct fb_var_screeninfo var; /* Current var */ struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */ struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */ struct fb_monspecs monspecs; /* Current Monitor specs */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment