diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2009-12-15 19:46:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:02 -0500 |
commit | b689a9e8362ed909045f99517b735c7c60835f7c (patch) | |
tree | 6860a06fc12d2f0940e7a3b95b6d6dd3c1f7a727 /drivers/video/i810 | |
parent | 8a8e6b9d554d3889ca062cf9fea0a664231e0774 (diff) |
i810fb: fix stack exploding
Alan Cox has found that the i810fb function "uses a whopping 2.5K of stack".
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Reported-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/i810')
-rw-r--r-- | drivers/video/i810/i810_dvt.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c index 27fa703a2e0..b4b3670667a 100644 --- a/drivers/video/i810/i810_dvt.c +++ b/drivers/video/i810/i810_dvt.c | |||
@@ -212,24 +212,29 @@ inline void round_off_yres(u32 *xres, u32 *yres) | |||
212 | *yres = (*xres * 3) >> 2; | 212 | *yres = (*xres * 3) >> 2; |
213 | } | 213 | } |
214 | 214 | ||
215 | void i810fb_encode_registers(const struct fb_var_screeninfo *var, | 215 | static int i810fb_find_best_mode(u32 xres, u32 yres, u32 pixclock) |
216 | struct i810fb_par *par, u32 xres, u32 yres) | ||
217 | { | 216 | { |
218 | u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; | 217 | u32 diff = 0, diff_best = 0xFFFFFFFF, i = 0, i_best = 0; |
219 | u8 hfl; | 218 | u8 hfl = (u8) ((xres >> 3) - 1); |
220 | 219 | ||
221 | hfl = (u8) ((xres >> 3) - 1); | ||
222 | for (i = 0; i < ARRAY_SIZE(std_modes); i++) { | 220 | for (i = 0; i < ARRAY_SIZE(std_modes); i++) { |
223 | if (std_modes[i].cr01 == hfl) { | 221 | if (std_modes[i].cr01 == hfl) { |
224 | if (std_modes[i].pixclock <= par->regs.pixclock) | 222 | if (std_modes[i].pixclock <= pixclock) |
225 | diff = par->regs.pixclock - | 223 | diff = pixclock - std_modes[i].pixclock; |
226 | std_modes[i].pixclock; | ||
227 | if (diff < diff_best) { | 224 | if (diff < diff_best) { |
228 | i_best = i; | 225 | i_best = i; |
229 | diff_best = diff; | 226 | diff_best = diff; |
230 | } | 227 | } |
231 | } | 228 | } |
232 | } | 229 | } |
230 | return i_best; | ||
231 | } | ||
232 | |||
233 | void i810fb_encode_registers(const struct fb_var_screeninfo *var, | ||
234 | struct i810fb_par *par, u32 xres, u32 yres) | ||
235 | { | ||
236 | u32 i_best = i810fb_find_best_mode(xres, yres, par->regs.pixclock); | ||
237 | |||
233 | par->regs = std_modes[i_best]; | 238 | par->regs = std_modes[i_best]; |
234 | 239 | ||
235 | /* overlay */ | 240 | /* overlay */ |
@@ -239,36 +244,36 @@ void i810fb_encode_registers(const struct fb_var_screeninfo *var, | |||
239 | 244 | ||
240 | void i810fb_fill_var_timings(struct fb_var_screeninfo *var) | 245 | void i810fb_fill_var_timings(struct fb_var_screeninfo *var) |
241 | { | 246 | { |
242 | struct i810fb_par par; | ||
243 | u32 total, xres, yres; | 247 | u32 total, xres, yres; |
248 | u32 mode, pixclock; | ||
244 | 249 | ||
245 | xres = var->xres; | 250 | xres = var->xres; |
246 | yres = var->yres; | 251 | yres = var->yres; |
247 | 252 | ||
248 | par.regs.pixclock = 1000000000/var->pixclock; | 253 | pixclock = 1000000000 / var->pixclock; |
249 | i810fb_encode_registers(var, &par, xres, yres); | 254 | mode = i810fb_find_best_mode(xres, yres, pixclock); |
250 | 255 | ||
251 | total = ((par.regs.cr00 | (par.regs.cr35 & 1) << 8) + 3) << 3; | 256 | total = (std_modes[mode].cr00 | (std_modes[mode].cr35 & 1) << 8) + 3; |
257 | total <<= 3; | ||
252 | 258 | ||
253 | var->pixclock = 1000000000/par.regs.pixclock; | 259 | var->pixclock = 1000000000 / std_modes[mode].pixclock; |
254 | var->right_margin = (par.regs.cr04 << 3) - xres; | 260 | var->right_margin = (std_modes[mode].cr04 << 3) - xres; |
255 | var->hsync_len = ((par.regs.cr05 & 0x1F) - | 261 | var->hsync_len = ((std_modes[mode].cr05 & 0x1F) - |
256 | (par.regs.cr04 & 0x1F)) << 3; | 262 | (std_modes[mode].cr04 & 0x1F)) << 3; |
257 | var->left_margin = (total - (xres + var->right_margin + | 263 | var->left_margin = (total - (xres + var->right_margin + |
258 | var->hsync_len)); | 264 | var->hsync_len)); |
259 | var->sync = FB_SYNC_ON_GREEN; | 265 | var->sync = FB_SYNC_ON_GREEN; |
260 | if (~(par.regs.msr & (1 << 6))) | 266 | if (~(std_modes[mode].msr & (1 << 6))) |
261 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 267 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
262 | if (~(par.regs.msr & (1 << 7))) | 268 | if (~(std_modes[mode].msr & (1 << 7))) |
263 | var->sync |= FB_SYNC_VERT_HIGH_ACT; | 269 | var->sync |= FB_SYNC_VERT_HIGH_ACT; |
264 | 270 | ||
265 | 271 | total = (std_modes[mode].cr06 | (std_modes[mode].cr30 & 0xF) << 8) + 2; | |
266 | total = ((par.regs.cr06 | (par.regs.cr30 & 0x0F) << 8)) + 2; | 272 | var->lower_margin = (std_modes[mode].cr10 | |
267 | var->lower_margin = (par.regs.cr10 | | 273 | (std_modes[mode].cr32 & 0x0F) << 8) - yres; |
268 | (par.regs.cr32 & 0x0F) << 8) - yres; | 274 | var->vsync_len = (std_modes[mode].cr11 & 0x0F) - |
269 | var->vsync_len = (par.regs.cr11 & 0x0F) - (var->lower_margin & 0x0F); | 275 | (var->lower_margin & 0x0F); |
270 | var->upper_margin = total - (yres + var->lower_margin + | 276 | var->upper_margin = total - (yres + var->lower_margin + var->vsync_len); |
271 | var->vsync_len); | ||
272 | } | 277 | } |
273 | 278 | ||
274 | u32 i810_get_watermark(struct fb_var_screeninfo *var, | 279 | u32 i810_get_watermark(struct fb_var_screeninfo *var, |