[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:
Antonino A. Daplas 2006-01-09 20:53:38 -08:00 committed by Linus Torvalds
parent 0a484a3af9
commit af5d0f7e2b
1 changed files with 68 additions and 58 deletions

View File

@ -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)