ps3fb: Use fb_info.par properly
Subsystems (3)
PATCH 6/15 ps3fb: Use fb_info.par properly
From: Geert Uytterhoeven <[email protected]>
ps3fb: Use fb_info.par properly:
o Move mode-specific fields into struct ps3fb_par
o Allocate struct ps3fb_par using framebuffer_alloc()
o Protect access to ps3fb_par in ps3fb_sync() using the console semaphore (this semaphore is already held when ps3fb_set_par() is called)
o Avoid calling ps3av_set_video_mode() if the actual video mode hasn't changed
---
drivers/video/ps3fb.c | 92 ++++++++++++++++++++++++++++++------------------- 1 files changed, 57 insertions(+), 35 deletions(-)
drivers/video/ps3fb.c +57 -35
@@ -119,12 +119,10 @@ struct ps3fb_priv {void *xdr_ea;size_t xdr_size;struct gpu_driver_info *dinfo; -u32 res_index;u64 vblank_count;/* frame count */ wait_queue_head_t wait_vsync; -u32 num_frames;/* num of frame buffers */ atomic_t ext_flip;/* on/off flip with vsync */ atomic_t f_count;/* fb_open count */ int is_blanked;
@@ -133,6 +131,13 @@ struct ps3fb_priv { };static struct ps3fb_priv ps3fb; +struct ps3fb_par { +u32 pseudo_palette[16 ]; +int mode_id, new_mode_id; +int res_index; +unsigned int num_frames;/* num of frame buffers */ +}; +struct ps3fb_res_table {u32 xres;u32 yres;
@@ -361,18 +366,17 @@ static unsigned int ps3fb_find_mode(conspr_debug ("ps3fb_find_mode: mode not found\n" );return 0 ; - } -static const struct fb_videomode *ps3fb_default_mode (void ) +static const struct fb_videomode *ps3fb_default_mode (int id) { -u32 mode = ps3fb_mode &PS3AV_MODE_MASK ; +u32 mode = id &PS3AV_MODE_MASK ;u32 flags;if (mode <1 || mode >13 )return NULL ; - flags = ps3fb_mode & ~PS3AV_MODE_MASK ; + flags = id & ~PS3AV_MODE_MASK ;if (mode <=10 && flags &PS3FB_FULL_MODE_BIT ) {/* Full broadcast mode */
@@ -384,18 +388,22 @@ static const struct fb_videomode *ps3fb_static int ps3fb_sync (struct fb_info *info,u32 frame) { -int i, status; +struct ps3fb_par *par = info->par; +int i, status, error =0 ;u32 xres, yres;u64 fb_ioif, offset; - i = ps3fb.res_index; +acquire_console_sem (); + + i = par->res_index; xres = ps3fb_res[i].xres; yres = ps3fb_res[i].yres; -if (frame > ps3fb.num_frames -1 ) { +if (frame > par->num_frames -1 ) {dev_dbg (info->device,"%s: invalid frame number (%u)\n" , __func__, frame); -return -EINVAL ; + error = -EINVAL ; + goto out; } offset = xres * yres *BPP * frame;
@@ -428,7 +436,10 @@ #ifdef HEAD_B"%s: lv1_gpu_context_attribute FLIP failed: %d\n" , __func__, status);#endif -return 0 ; + +out: +release_console_sem (); +return error; }
@@ -547,6 +558,7 @@ static int ps3fb_check_var(struct fb_varstatic int ps3fb_set_par (struct fb_info *info) { +struct ps3fb_par *par = info->par;unsigned int mode;int i;unsigned long offset;
@@ -560,7 +572,7 @@ static int ps3fb_set_par(struct fb_inforeturn -EINVAL ; i =ps3fb_get_res_table (info->var.xres, info->var.yres, mode); - ps3fb.res_index = i; + par->res_index = i; offset =VFB_OFF (i); info->fix.smem_start =virt_to_abs (ps3fb.xdr_ea) + offset;
@@ -568,14 +580,19 @@ static int ps3fb_set_par(struct fb_info info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset;memset (ps3fb.xdr_ea,0 , ps3fb.xdr_size); - ps3fb.num_frames = info->fix.smem_len/ - (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP ); + par->num_frames = info->fix.smem_len/ + (ps3fb_res[i].xres*ps3fb_res[i].yres*BPP );/* Keep the special bits we cannot set using fb_var_screeninfo */ - ps3fb_mode = (ps3fb_mode & ~PS3AV_MODE_MASK ) | mode; + par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK ) | mode; -if (ps3av_set_video_mode (ps3fb_mode)) -return -EINVAL ; +if (par->new_mode_id != par->mode_id) { +if (ps3av_set_video_mode (par->new_mode_id)) { + par->new_mode_id = par->mode_id; +return -EINVAL ; + } + par->mode_id = par->new_mode_id; + }return 0 ; }
@@ -694,7 +711,7 @@ static int ps3fb_ioctl(struct fb_info *i unsigned long arg) {void __user *argp = (void __user *)arg; -u32 val, old_mode; +u32 val;int retval = -EFAULT ;switch (cmd) {
@@ -724,6 +741,7 @@ static int ps3fb_ioctl(struct fb_info *icase PS3FB_IOCTL_SETMODE : { +struct ps3fb_par *par = info->par;const struct fb_videomode *mode;struct fb_var_screeninfo var;
@@ -737,9 +755,7 @@ static int ps3fb_ioctl(struct fb_info *i }dev_dbg (info->device,"PS3FB_IOCTL_SETMODE:%x\n" , val); retval = -EINVAL ; - old_mode = ps3fb_mode; - ps3fb_mode = val; - mode =ps3fb_default_mode (); + mode =ps3fb_default_mode (val);if (mode) { var = info->var;fb_videomode_to_var (&var, mode);
@@ -747,12 +763,11 @@ static int ps3fb_ioctl(struct fb_info *i info->flags |=FBINFO_MISC_USEREVENT ;/* Force, in case only special bits changed */ var.activate |=FB_ACTIVATE_FORCE ; + par->new_mode_id = val; retval =fb_set_var (info, &var); info->flags &= ~FBINFO_MISC_USEREVENT ;release_console_sem (); } -if (retval) - ps3fb_mode = old_mode;break ; }
@@ -765,14 +780,15 @@ static int ps3fb_ioctl(struct fb_info *icase PS3FB_IOCTL_SCREENINFO : { +struct ps3fb_par *par = info->par;struct ps3fb_ioctl_res res; -int i = ps3fb.res_index; +int i = par->res_index;dev_dbg (info->device,"PS3FB_IOCTL_SCREENINFO:\n" ); res.xres = ps3fb_res[i].xres; res.yres = ps3fb_res[i].yres; res.xoff = ps3fb_res[i].xoff; res.yoff = ps3fb_res[i].yoff; - res.num_frames = ps3fb.num_frames; + res.num_frames = par->num_frames;if (!copy_to_user (argp, &res,sizeof (res))) retval =0 ;break ;
@@ -979,6 +995,7 @@ #endifstatic int __devinit ps3fb_probe (struct ps3_system_bus_device *dev) {struct fb_info *info; +struct ps3fb_par *par;int retval = -ENOMEM ;u32 xres, yres;u64 ddr_lpar =0 ;
@@ -987,7 +1004,7 @@ static int __devinit ps3fb_probe(structu64 lpar_reports =0 ;u64 lpar_reports_size =0 ;u64 xdr_lpar; -int status; +int status, res_index;unsigned long offset;struct task_struct *task;
@@ -1004,15 +1021,14 @@ static int __devinit ps3fb_probe(structif (ps3fb_mode >0 && !ps3av_video_mode2res (ps3fb_mode, &xres, &yres)) { - ps3fb.res_index =ps3fb_get_res_table (xres, yres, ps3fb_mode); -dev_dbg (&dev->core,"res_index:%d\n" , ps3fb.res_index); + res_index =ps3fb_get_res_table (xres, yres, ps3fb_mode); +dev_dbg (&dev->core,"res_index:%d\n" , res_index); }else - ps3fb.res_index =GPU_RES_INDEX ; + res_index =GPU_RES_INDEX ;atomic_set (&ps3fb.f_count,-1 );/* fbcon opens ps3fb */ atomic_set (&ps3fb.ext_flip,0 );/* for flip with vsync */ init_waitqueue_head (&ps3fb.wait_vsync); - ps3fb.num_frames =1 ;ps3fb_set_sync (&dev->core);
@@ -1062,19 +1078,24 @@ static int __devinit ps3fb_probe(structif (retval) goto err_free_irq; - info =framebuffer_alloc (sizeof (u32) *16 , &dev->core); + info =framebuffer_alloc (sizeof (struct ps3fb_par ), &dev->core);if (!info) goto err_free_irq; - offset =VFB_OFF (ps3fb.res_index); + par = info->par; + par->mode_id = ~ps3fb_mode;/* != ps3fb_mode, to trigger change */ + par->new_mode_id = ps3fb_mode; + par->res_index = res_index; + par->num_frames =1 ; + + offset =VFB_OFF (res_index); info->screen_base = (char __iomem *)ps3fb.xdr_ea + offset; info->fbops = &ps3fb_ops; info->fix = ps3fb_fix; info->fix.smem_start =virt_to_abs (ps3fb.xdr_ea) + offset; info->fix.smem_len = ps3fb.xdr_size - offset; - info->pseudo_palette = info->par; - info->par =NULL ; + info->pseudo_palette = par->pseudo_palette; info->flags =FBINFO_DEFAULT |FBINFO_READS_FAST ; retval =fb_alloc_cmap (&info->cmap,256 ,0 );
@@ -1082,7 +1103,8 @@ static int __devinit ps3fb_probe(struct goto err_framebuffer_release;if (!fb_find_mode (&info->var, info, mode_option, ps3fb_modedb, -ARRAY_SIZE (ps3fb_modedb),ps3fb_default_mode (),32 )) { +ARRAY_SIZE (ps3fb_modedb), +ps3fb_default_mode (par->new_mode_id),32 )) { retval = -EINVAL ; goto err_fb_dealloc; }
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/