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>
This commit is contained in:
parent
70d6027ff2
commit
537a1bf059
|
@ -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)
|
||||||
|
|
||||||
/* 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)
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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
|
||||||
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) {
|
||||||
#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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
* 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)
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
#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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue