diff options
author | Jaya Kumar <jayakumar.lkml@gmail.com> | 2008-04-28 05:15:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:41 -0400 |
commit | 963654a9c919d18f8b9137f8ffd9d2d30a139269 (patch) | |
tree | 737e3ba0a3a7f824b71750e5dded33ad8d9a20d0 /drivers/video/hecubafb.c | |
parent | 555514fabc1c24fac69ff46feac384180828182c (diff) |
fbdev: hecubafb bugfix
This patch is a bugfix for hecubafb_write which would return an incorrect
error value for the bytecount from framebuffer writes.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: "Antonino A. Daplas" <adaplas@pol.net>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/hecubafb.c')
-rw-r--r-- | drivers/video/hecubafb.c | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/drivers/video/hecubafb.c b/drivers/video/hecubafb.c index 94e0df8a6f60..b77d033665da 100644 --- a/drivers/video/hecubafb.c +++ b/drivers/video/hecubafb.c | |||
@@ -270,41 +270,43 @@ static void hecubafb_imageblit(struct fb_info *info, | |||
270 | static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf, | 270 | static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf, |
271 | size_t count, loff_t *ppos) | 271 | size_t count, loff_t *ppos) |
272 | { | 272 | { |
273 | unsigned long p; | 273 | struct hecubafb_par *par = info->par; |
274 | int err=-EINVAL; | 274 | unsigned long p = *ppos; |
275 | struct hecubafb_par *par; | 275 | void *dst; |
276 | unsigned int xres; | 276 | int err = 0; |
277 | unsigned int fbmemlength; | 277 | unsigned long total_size; |
278 | 278 | ||
279 | p = *ppos; | 279 | if (info->state != FBINFO_STATE_RUNNING) |
280 | par = info->par; | 280 | return -EPERM; |
281 | xres = info->var.xres; | ||
282 | fbmemlength = (xres * info->var.yres)/8; | ||
283 | 281 | ||
284 | if (p > fbmemlength) | 282 | total_size = info->fix.smem_len; |
285 | return -ENOSPC; | ||
286 | 283 | ||
287 | err = 0; | 284 | if (p > total_size) |
288 | if ((count + p) > fbmemlength) { | 285 | return -EFBIG; |
289 | count = fbmemlength - p; | 286 | |
290 | err = -ENOSPC; | 287 | if (count > total_size) { |
288 | err = -EFBIG; | ||
289 | count = total_size; | ||
291 | } | 290 | } |
292 | 291 | ||
293 | if (count) { | 292 | if (count + p > total_size) { |
294 | char *base_addr; | 293 | if (!err) |
294 | err = -ENOSPC; | ||
295 | 295 | ||
296 | base_addr = (char __force *)info->screen_base; | 296 | count = total_size - p; |
297 | count -= copy_from_user(base_addr + p, buf, count); | ||
298 | *ppos += count; | ||
299 | err = -EFAULT; | ||
300 | } | 297 | } |
301 | 298 | ||
302 | hecubafb_dpy_update(par); | 299 | dst = (void __force *) (info->screen_base + p); |
300 | |||
301 | if (copy_from_user(dst, buf, count)) | ||
302 | err = -EFAULT; | ||
303 | 303 | ||
304 | if (count) | 304 | if (!err) |
305 | return count; | 305 | *ppos += count; |
306 | |||
307 | hecubafb_dpy_update(par); | ||
306 | 308 | ||
307 | return err; | 309 | return (err) ? err : count; |
308 | } | 310 | } |
309 | 311 | ||
310 | static struct fb_ops hecubafb_ops = { | 312 | static struct fb_ops hecubafb_ops = { |