[PATCH] fbdev: Reduce stack usage
calc_mode_timings() and fb_get_mode() are using more than 500 bytes off the stack. Fix. Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
0a484a3af9
commit
af5d0f7e2b
1 changed files with 68 additions and 58 deletions
|
@ -317,26 +317,29 @@ static int edid_is_monitor_block(unsigned char *block)
|
|||
static void calc_mode_timings(int xres, int yres, int refresh,
|
||||
struct fb_videomode *mode)
|
||||
{
|
||||
struct fb_var_screeninfo var;
|
||||
struct fb_info info;
|
||||
struct fb_var_screeninfo *var;
|
||||
|
||||
memset(&var, 0, sizeof(struct fb_var_screeninfo));
|
||||
var.xres = xres;
|
||||
var.yres = yres;
|
||||
fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
|
||||
refresh, &var, &info);
|
||||
mode->xres = xres;
|
||||
mode->yres = yres;
|
||||
mode->pixclock = var.pixclock;
|
||||
mode->refresh = refresh;
|
||||
mode->left_margin = var.left_margin;
|
||||
mode->right_margin = var.right_margin;
|
||||
mode->upper_margin = var.upper_margin;
|
||||
mode->lower_margin = var.lower_margin;
|
||||
mode->hsync_len = var.hsync_len;
|
||||
mode->vsync_len = var.vsync_len;
|
||||
mode->vmode = 0;
|
||||
mode->sync = 0;
|
||||
var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
|
||||
|
||||
if (var) {
|
||||
var->xres = xres;
|
||||
var->yres = yres;
|
||||
fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
|
||||
refresh, var, NULL);
|
||||
mode->xres = xres;
|
||||
mode->yres = yres;
|
||||
mode->pixclock = var->pixclock;
|
||||
mode->refresh = refresh;
|
||||
mode->left_margin = var->left_margin;
|
||||
mode->right_margin = var->right_margin;
|
||||
mode->upper_margin = var->upper_margin;
|
||||
mode->lower_margin = var->lower_margin;
|
||||
mode->hsync_len = var->hsync_len;
|
||||
mode->vsync_len = var->vsync_len;
|
||||
mode->vmode = 0;
|
||||
mode->sync = 0;
|
||||
kfree(var);
|
||||
}
|
||||
}
|
||||
|
||||
static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
|
||||
|
@ -1105,15 +1108,21 @@ static void fb_timings_dclk(struct __fb_timings *timings)
|
|||
*/
|
||||
int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct __fb_timings timings;
|
||||
struct __fb_timings *timings;
|
||||
u32 interlace = 1, dscan = 1;
|
||||
u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
|
||||
u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
|
||||
|
||||
|
||||
timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
|
||||
|
||||
if (!timings)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* If monspecs are invalid, use values that are enough
|
||||
* for 640x480@60
|
||||
*/
|
||||
if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
|
||||
if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
|
||||
!info->monspecs.dclkmax ||
|
||||
info->monspecs.hfmax < info->monspecs.hfmin ||
|
||||
info->monspecs.vfmax < info->monspecs.vfmin ||
|
||||
|
@ -1130,65 +1139,66 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
|
|||
dclkmax = info->monspecs.dclkmax;
|
||||
}
|
||||
|
||||
memset(&timings, 0, sizeof(struct __fb_timings));
|
||||
timings.hactive = var->xres;
|
||||
timings.vactive = var->yres;
|
||||
timings->hactive = var->xres;
|
||||
timings->vactive = var->yres;
|
||||
if (var->vmode & FB_VMODE_INTERLACED) {
|
||||
timings.vactive /= 2;
|
||||
timings->vactive /= 2;
|
||||
interlace = 2;
|
||||
}
|
||||
if (var->vmode & FB_VMODE_DOUBLE) {
|
||||
timings.vactive *= 2;
|
||||
timings->vactive *= 2;
|
||||
dscan = 2;
|
||||
}
|
||||
|
||||
switch (flags & ~FB_IGNOREMON) {
|
||||
case FB_MAXTIMINGS: /* maximize refresh rate */
|
||||
timings.hfreq = hfmax;
|
||||
fb_timings_hfreq(&timings);
|
||||
if (timings.vfreq > vfmax) {
|
||||
timings.vfreq = vfmax;
|
||||
fb_timings_vfreq(&timings);
|
||||
timings->hfreq = hfmax;
|
||||
fb_timings_hfreq(timings);
|
||||
if (timings->vfreq > vfmax) {
|
||||
timings->vfreq = vfmax;
|
||||
fb_timings_vfreq(timings);
|
||||
}
|
||||
if (timings.dclk > dclkmax) {
|
||||
timings.dclk = dclkmax;
|
||||
fb_timings_dclk(&timings);
|
||||
if (timings->dclk > dclkmax) {
|
||||
timings->dclk = dclkmax;
|
||||
fb_timings_dclk(timings);
|
||||
}
|
||||
break;
|
||||
case FB_VSYNCTIMINGS: /* vrefresh driven */
|
||||
timings.vfreq = val;
|
||||
fb_timings_vfreq(&timings);
|
||||
timings->vfreq = val;
|
||||
fb_timings_vfreq(timings);
|
||||
break;
|
||||
case FB_HSYNCTIMINGS: /* hsync driven */
|
||||
timings.hfreq = val;
|
||||
fb_timings_hfreq(&timings);
|
||||
timings->hfreq = val;
|
||||
fb_timings_hfreq(timings);
|
||||
break;
|
||||
case FB_DCLKTIMINGS: /* pixelclock driven */
|
||||
timings.dclk = PICOS2KHZ(val) * 1000;
|
||||
fb_timings_dclk(&timings);
|
||||
timings->dclk = PICOS2KHZ(val) * 1000;
|
||||
fb_timings_dclk(timings);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
err = -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
if (!(flags & FB_IGNOREMON) &&
|
||||
(timings.vfreq < vfmin || timings.vfreq > vfmax ||
|
||||
timings.hfreq < hfmin || timings.hfreq > hfmax ||
|
||||
timings.dclk < dclkmin || timings.dclk > dclkmax))
|
||||
return -EINVAL;
|
||||
|
||||
var->pixclock = KHZ2PICOS(timings.dclk/1000);
|
||||
var->hsync_len = (timings.htotal * 8)/100;
|
||||
var->right_margin = (timings.hblank/2) - var->hsync_len;
|
||||
var->left_margin = timings.hblank - var->right_margin - var->hsync_len;
|
||||
if (err || (!(flags & FB_IGNOREMON) &&
|
||||
(timings->vfreq < vfmin || timings->vfreq > vfmax ||
|
||||
timings->hfreq < hfmin || timings->hfreq > hfmax ||
|
||||
timings->dclk < dclkmin || timings->dclk > dclkmax))) {
|
||||
err = -EINVAL;
|
||||
} else {
|
||||
var->pixclock = KHZ2PICOS(timings->dclk/1000);
|
||||
var->hsync_len = (timings->htotal * 8)/100;
|
||||
var->right_margin = (timings->hblank/2) - var->hsync_len;
|
||||
var->left_margin = timings->hblank - var->right_margin -
|
||||
var->hsync_len;
|
||||
var->vsync_len = (3 * interlace)/dscan;
|
||||
var->lower_margin = (1 * interlace)/dscan;
|
||||
var->upper_margin = (timings->vblank * interlace)/dscan -
|
||||
(var->vsync_len + var->lower_margin);
|
||||
}
|
||||
|
||||
var->vsync_len = (3 * interlace)/dscan;
|
||||
var->lower_margin = (1 * interlace)/dscan;
|
||||
var->upper_margin = (timings.vblank * interlace)/dscan -
|
||||
(var->vsync_len + var->lower_margin);
|
||||
|
||||
return 0;
|
||||
kfree(timings);
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
|
||||
|
|
Loading…
Reference in a new issue