Skip to content

Commit

Permalink
i810fb: fix stack exploding
Browse files Browse the repository at this point in the history
Alan Cox has found that the i810fb function "uses a whopping 2.5K of stack".

Signed-off-by: Krzysztof Helt <[email protected]>
Reported-by: Alan Cox <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Krzysztof-H authored and torvalds committed Dec 16, 2009
1 parent 8a8e6b9 commit b689a9e
Showing 1 changed file with 29 additions and 24 deletions.
53 changes: 29 additions & 24 deletions drivers/video/i810/i810_dvt.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,24 +212,29 @@ inline void round_off_yres(u32 *xres, u32 *yres)
*yres = (*xres * 3) >> 2;
}

void i810fb_encode_registers(const struct fb_var_screeninfo *var,
struct i810fb_par *par, u32 xres, u32 yres)
static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock)
{
u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0;
u8 hfl;
u8 hfl = (u8) ((xres >> 3) - 1);

hfl = (u8) ((xres >> 3) - 1);
for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
if (std_modes[i].cr01 == hfl) {
if (std_modes[i].pixclock <= par->regs.pixclock)
diff = par->regs.pixclock -
std_modes[i].pixclock;
if (std_modes[i].pixclock <= pixclock)
diff = pixclock - std_modes[i].pixclock;
if (diff < diff_best) {
i_best = i;
diff_best = diff;
}
}
}
return i_best;
}

void i810fb_encode_registers(const struct fb_var_screeninfo *var,
struct i810fb_par *par, u32 xres, u32 yres)
{
u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock);

par->regs = std_modes[i_best];

/* overlay */
Expand All @@ -239,36 +244,36 @@ void i810fb_encode_registers(const struct fb_var_screeninfo *var,

void i810fb_fill_var_timings(struct fb_var_screeninfo *var)
{
struct i810fb_par par;
u32 total, xres, yres;
u32 mode, pixclock;

xres = var->xres;
yres = var->yres;

par.regs.pixclock = 1000000000/var->pixclock;
i810fb_encode_registers(var, &par, xres, yres);
pixclock = 1000000000 / var->pixclock;
mode = i810fb_find_best_mode(xres, yres, pixclock);

total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3;
total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3;
total <<= 3;

var->pixclock = 1000000000/par.regs.pixclock;
var->right_margin = (par.regs.cr04 << 3) - xres;
var->hsync_len = ((par.regs.cr05 & 0x1F) -
(par.regs.cr04 & 0x1F)) << 3;
var->pixclock = 1000000000 / std_modes[mode].pixclock;
var->right_margin = (std_modes[mode].cr04 << 3) - xres;
var->hsync_len = ((std_modes[mode].cr05 & 0x1F) -
(std_modes[mode].cr04 & 0x1F)) << 3;
var->left_margin = (total - (xres + var->right_margin +
var->hsync_len));
var->sync = FB_SYNC_ON_GREEN;
if (~(par.regs.msr & (1 << 6)))
if (~(std_modes[mode].msr & (1 << 6)))
var->sync |= FB_SYNC_HOR_HIGH_ACT;
if (~(par.regs.msr & (1 << 7)))
if (~(std_modes[mode].msr & (1 << 7)))
var->sync |= FB_SYNC_VERT_HIGH_ACT;


total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2;
var->lower_margin = (par.regs.cr10 |
(par.regs.cr32 & 0x0F) << 8) - yres;
var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F);
var->upper_margin = total - (yres + var->lower_margin +
var->vsync_len);
total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF) << 8) + 2;
var->lower_margin = (std_modes[mode].cr10 |
(std_modes[mode].cr32 & 0x0F) << 8) - yres;
var->vsync_len = (std_modes[mode].cr11 & 0x0F) -
(var->lower_margin & 0x0F);
var->upper_margin = total - (yres + var->lower_margin + var->vsync_len);
}

u32 i810_get_watermark(struct fb_var_screeninfo *var,
Expand Down

0 comments on commit b689a9e

Please sign in to comment.