Commit af5d0f7e authored by Antonino A. Daplas's avatar Antonino A. Daplas Committed by Linus Torvalds
Browse files

[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: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0a484a3a
Loading
Loading
Loading
Loading
+68 −58
Original line number Diff line number Diff line
@@ -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;
	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, &info);
			    refresh, var, NULL);
		mode->xres = xres;
		mode->yres = yres;
	mode->pixclock = var.pixclock;
		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->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->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)