diff options
Diffstat (limited to 'drivers/media/usb/stk1160/stk1160-video.c')
| -rw-r--r-- | drivers/media/usb/stk1160/stk1160-video.c | 83 |
1 files changed, 35 insertions, 48 deletions
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 4e966f6bf608..f4baf9263286 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -99,7 +99,7 @@ void stk1160_buffer_done(struct stk1160 *dev) static inline void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) { - int linesdone, lineoff, lencopy; + int linesdone, lineoff, lencopy, offset; int bytesperline = dev->width * 2; struct stk1160_buffer *buf = dev->isoc_ctl.buf; u8 *dst = buf->mem; @@ -107,8 +107,7 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) /* * TODO: These stk1160_dbg are very spammy! - * We should 1) check why we are getting them - * and 2) add ratelimit. + * We should check why we are getting them. * * UPDATE: One of the reasons (the only one?) for getting these * is incorrect standard (mismatch between expected and configured). @@ -131,17 +130,19 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) dst += linesdone * bytesperline * 2 + lineoff; /* Copy the remaining of current line */ - if (remain < (bytesperline - lineoff)) - lencopy = remain; - else - lencopy = bytesperline - lineoff; + lencopy = min(remain, bytesperline - lineoff); /* * Check if we have enough space left in the buffer. * In that case, we force loop exit after copy. */ - if (lencopy > buf->bytesused - buf->length) { - lencopy = buf->bytesused - buf->length; + offset = dst - (u8 *)buf->mem; + if (offset > buf->length) { + dev_warn_ratelimited(dev->dev, "out of bounds offset\n"); + return; + } + if (lencopy > buf->length - offset) { + lencopy = buf->length - offset; remain = lencopy; } @@ -151,7 +152,7 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) /* Let the bug hunt begin! sanity checks! */ if (lencopy < 0) { - stk1160_dbg("copy skipped: negative lencopy\n"); + printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n"); return; } @@ -174,17 +175,19 @@ void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) src += lencopy; /* Copy one line at a time */ - if (remain < bytesperline) - lencopy = remain; - else - lencopy = bytesperline; + lencopy = min(remain, bytesperline); /* * Check if we have enough space left in the buffer. * In that case, we force loop exit after copy. */ - if (lencopy > buf->bytesused - buf->length) { - lencopy = buf->bytesused - buf->length; + offset = dst - (u8 *)buf->mem; + if (offset > buf->length) { + dev_warn_ratelimited(dev->dev, "offset out of bounds\n"); + return; + } + if (lencopy > buf->length - offset) { + lencopy = buf->length - offset; remain = lencopy; } @@ -295,9 +298,7 @@ static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) static void stk1160_isoc_irq(struct urb *urb) { int i, rc; - struct stk1160_urb *stk_urb = urb->context; - struct stk1160 *dev = stk_urb->dev; - struct device *dma_dev = stk1160_get_dmadev(dev); + struct stk1160 *dev = urb->context; switch (urb->status) { case 0: @@ -312,10 +313,6 @@ static void stk1160_isoc_irq(struct urb *urb) return; } - invalidate_kernel_vmap_range(stk_urb->transfer_buffer, - urb->transfer_buffer_length); - dma_sync_sgtable_for_cpu(dma_dev, stk_urb->sgt, DMA_FROM_DEVICE); - stk1160_process_isoc(dev, urb); /* Reset urb buffers */ @@ -324,7 +321,6 @@ static void stk1160_isoc_irq(struct urb *urb) urb->iso_frame_desc[i].actual_length = 0; } - dma_sync_sgtable_for_device(dma_dev, stk_urb->sgt, DMA_FROM_DEVICE); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc) stk1160_err("urb re-submit failed (%d)\n", rc); @@ -362,11 +358,9 @@ void stk1160_cancel_isoc(struct stk1160 *dev) static void stk_free_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb) { - struct device *dma_dev = stk1160_get_dmadev(dev); - - dma_vunmap_noncontiguous(dma_dev, stk_urb->transfer_buffer); - dma_free_noncontiguous(dma_dev, stk_urb->urb->transfer_buffer_length, - stk_urb->sgt, DMA_FROM_DEVICE); + usb_free_noncoherent(dev->udev, stk_urb->urb->transfer_buffer_length, + stk_urb->transfer_buffer, DMA_FROM_DEVICE, + stk_urb->sgt); usb_free_urb(stk_urb->urb); stk_urb->transfer_buffer = NULL; @@ -407,32 +401,24 @@ void stk1160_uninit_isoc(struct stk1160 *dev) static int stk1160_fill_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb, int sb_size, int max_packets) { - struct device *dma_dev = stk1160_get_dmadev(dev); - stk_urb->urb = usb_alloc_urb(max_packets, GFP_KERNEL); if (!stk_urb->urb) return -ENOMEM; - stk_urb->sgt = dma_alloc_noncontiguous(dma_dev, sb_size, - DMA_FROM_DEVICE, GFP_KERNEL, 0); - /* - * If the buffer allocation failed, we exit but return 0 since - * we allow the driver working with less buffers - */ - if (!stk_urb->sgt) + stk_urb->transfer_buffer = usb_alloc_noncoherent(dev->udev, sb_size, + GFP_KERNEL, &stk_urb->dma, + DMA_FROM_DEVICE, &stk_urb->sgt); + if (!stk_urb->transfer_buffer) { + /* + * If the buffer allocation failed, we exit but return 0 since + * we allow the driver working with less buffers. + */ goto free_urb; + } - stk_urb->transfer_buffer = dma_vmap_noncontiguous(dma_dev, sb_size, - stk_urb->sgt); - if (!stk_urb->transfer_buffer) - goto free_sgt; - - stk_urb->dma = stk_urb->sgt->sgl->dma_address; stk_urb->dev = dev; return 0; -free_sgt: - dma_free_noncontiguous(dma_dev, sb_size, stk_urb->sgt, DMA_FROM_DEVICE); - stk_urb->sgt = NULL; + free_urb: usb_free_urb(stk_urb->urb); stk_urb->urb = NULL; @@ -491,12 +477,13 @@ int stk1160_alloc_isoc(struct stk1160 *dev) urb->transfer_buffer = dev->isoc_ctl.urb_ctl[i].transfer_buffer; urb->transfer_buffer_length = sb_size; urb->complete = stk1160_isoc_irq; - urb->context = &dev->isoc_ctl.urb_ctl[i]; + urb->context = dev; urb->interval = 1; urb->start_frame = 0; urb->number_of_packets = max_packets; urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->transfer_dma = dev->isoc_ctl.urb_ctl[i].dma; + urb->sgt = dev->isoc_ctl.urb_ctl[i].sgt; k = 0; for (j = 0; j < max_packets; j++) { |
