diff options
Diffstat (limited to 'drivers/media/video/ivtv/ivtvfb.c')
-rw-r--r-- | drivers/media/video/ivtv/ivtvfb.c | 78 |
1 files changed, 38 insertions, 40 deletions
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index bdfda48e56bf..8a4a150b12fb 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -275,7 +275,6 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, int size_in_bytes) { DEFINE_WAIT(wait); - int ret = 0; int got_sig = 0; mutex_lock(&itv->udma.lock); @@ -316,7 +315,7 @@ static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv, return -EINTR; } - return ret; + return 0; } static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, @@ -368,11 +367,12 @@ static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source, } static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { unsigned long p = *ppos; void *dst; int err = 0; + int dma_err; unsigned long total_size; struct ivtv *itv = (struct ivtv *) info->par; unsigned long dma_offset = @@ -399,7 +399,6 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, if (count + p > total_size) { if (!err) err = -ENOSPC; - count = total_size - p; } @@ -408,39 +407,34 @@ static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf, if (info->fbops->fb_sync) info->fbops->fb_sync(info); - if (!access_ok(VERIFY_READ, buf, count)) { - IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n", - (unsigned long)buf); - err = -EFAULT; - } - - if (!err) { - /* If transfer size > threshold and both src/dst - addresses are aligned, use DMA */ - if (count >= 4096 && - ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { - /* Odd address = can't DMA. Align */ - if ((unsigned long)dst & 3) { - lead = 4 - ((unsigned long)dst & 3); - memcpy(dst, buf, lead); - buf += lead; - dst += lead; - } - /* DMA resolution is 32 bits */ - if ((count - lead) & 3) - tail = (count - lead) & 3; - /* DMA the data */ - dma_size = count - lead - tail; - err = ivtvfb_prep_dec_dma_to_device(itv, - p + lead + dma_offset, (void *)buf, dma_size); - dst += dma_size; - buf += dma_size; - /* Copy any leftover data */ - if (tail) - memcpy(dst, buf, tail); - } else { - memcpy(dst, buf, count); + /* If transfer size > threshold and both src/dst + addresses are aligned, use DMA */ + if (count >= 4096 && + ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) { + /* Odd address = can't DMA. Align */ + if ((unsigned long)dst & 3) { + lead = 4 - ((unsigned long)dst & 3); + if (copy_from_user(dst, buf, lead)) + return -EFAULT; + buf += lead; + dst += lead; } + /* DMA resolution is 32 bits */ + if ((count - lead) & 3) + tail = (count - lead) & 3; + /* DMA the data */ + dma_size = count - lead - tail; + dma_err = ivtvfb_prep_dec_dma_to_device(itv, + p + lead + dma_offset, (void __user *)buf, dma_size); + if (dma_err) + return dma_err; + dst += dma_size; + buf += dma_size; + /* Copy any leftover data */ + if (tail && copy_from_user(dst, buf, tail)) + return -EFAULT; + } else if (copy_from_user(dst, buf, count)) { + return -EFAULT; } if (!err) @@ -463,9 +457,12 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; trace = read_reg(0x028c0) >> 16; - if (itv->is_50hz && trace > 312) trace -= 312; - else if (itv->is_60hz && trace > 262) trace -= 262; - if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING; + if (itv->is_50hz && trace > 312) + trace -= 312; + else if (itv->is_60hz && trace > 262) + trace -= 262; + if (trace == 1) + vblank.flags |= FB_VBLANK_VSYNCING; vblank.count = itv->last_vsync_field; vblank.vcount = trace; vblank.hcount = 0; @@ -476,7 +473,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar case FBIO_WAITFORVSYNC: prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE); - if (!schedule_timeout(msecs_to_jiffies(50))) rc = -ETIMEDOUT; + if (!schedule_timeout(msecs_to_jiffies(50))) + rc = -ETIMEDOUT; finish_wait(&itv->vsync_waitq, &wait); return rc; |