Commit 811496c9 authored by Kieran Bingham's avatar Kieran Bingham Committed by Mauro Carvalho Chehab

media: uvcvideo: Refactor URB descriptors

We currently store three separate arrays for each URB reference we hold.

Objectify the data needed to track URBs into a single uvc_urb structure,
allowing better object management and tracking of the URB.

All accesses to the data pointers through stream, are converted to use a
uvc_urb pointer for consistency.
Signed-off-by: default avatarKieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 9b90dc85
...@@ -1506,14 +1506,16 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream) ...@@ -1506,14 +1506,16 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
unsigned int i; unsigned int i;
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
if (stream->urb_buffer[i]) { struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
if (uvc_urb->buffer) {
#ifndef CONFIG_DMA_NONCOHERENT #ifndef CONFIG_DMA_NONCOHERENT
usb_free_coherent(stream->dev->udev, stream->urb_size, usb_free_coherent(stream->dev->udev, stream->urb_size,
stream->urb_buffer[i], stream->urb_dma[i]); uvc_urb->buffer, uvc_urb->dma);
#else #else
kfree(stream->urb_buffer[i]); kfree(uvc_urb->buffer);
#endif #endif
stream->urb_buffer[i] = NULL; uvc_urb->buffer = NULL;
} }
} }
...@@ -1551,16 +1553,18 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, ...@@ -1551,16 +1553,18 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
/* Retry allocations until one succeed. */ /* Retry allocations until one succeed. */
for (; npackets > 1; npackets /= 2) { for (; npackets > 1; npackets /= 2) {
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
stream->urb_size = psize * npackets; stream->urb_size = psize * npackets;
#ifndef CONFIG_DMA_NONCOHERENT #ifndef CONFIG_DMA_NONCOHERENT
stream->urb_buffer[i] = usb_alloc_coherent( uvc_urb->buffer = usb_alloc_coherent(
stream->dev->udev, stream->urb_size, stream->dev->udev, stream->urb_size,
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]); gfp_flags | __GFP_NOWARN, &uvc_urb->dma);
#else #else
stream->urb_buffer[i] = uvc_urb->buffer =
kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN); kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
#endif #endif
if (!stream->urb_buffer[i]) { if (!uvc_urb->buffer) {
uvc_free_urb_buffers(stream); uvc_free_urb_buffers(stream);
break; break;
} }
...@@ -1590,13 +1594,15 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) ...@@ -1590,13 +1594,15 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
uvc_video_stats_stop(stream); uvc_video_stats_stop(stream);
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
urb = stream->urb[i]; struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
urb = uvc_urb->urb;
if (urb == NULL) if (urb == NULL)
continue; continue;
usb_kill_urb(urb); usb_kill_urb(urb);
usb_free_urb(urb); usb_free_urb(urb);
stream->urb[i] = NULL; uvc_urb->urb = NULL;
} }
if (free_buffers) if (free_buffers)
...@@ -1651,6 +1657,8 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, ...@@ -1651,6 +1657,8 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
size = npackets * psize; size = npackets * psize;
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
urb = usb_alloc_urb(npackets, gfp_flags); urb = usb_alloc_urb(npackets, gfp_flags);
if (urb == NULL) { if (urb == NULL) {
uvc_uninit_video(stream, 1); uvc_uninit_video(stream, 1);
...@@ -1663,12 +1671,12 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, ...@@ -1663,12 +1671,12 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
ep->desc.bEndpointAddress); ep->desc.bEndpointAddress);
#ifndef CONFIG_DMA_NONCOHERENT #ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = stream->urb_dma[i]; urb->transfer_dma = uvc_urb->dma;
#else #else
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP;
#endif #endif
urb->interval = ep->desc.bInterval; urb->interval = ep->desc.bInterval;
urb->transfer_buffer = stream->urb_buffer[i]; urb->transfer_buffer = uvc_urb->buffer;
urb->complete = uvc_video_complete; urb->complete = uvc_video_complete;
urb->number_of_packets = npackets; urb->number_of_packets = npackets;
urb->transfer_buffer_length = size; urb->transfer_buffer_length = size;
...@@ -1678,7 +1686,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, ...@@ -1678,7 +1686,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
urb->iso_frame_desc[j].length = psize; urb->iso_frame_desc[j].length = psize;
} }
stream->urb[i] = urb; uvc_urb->urb = urb;
} }
return 0; return 0;
...@@ -1717,21 +1725,22 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, ...@@ -1717,21 +1725,22 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
size = 0; size = 0;
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
urb = usb_alloc_urb(0, gfp_flags); urb = usb_alloc_urb(0, gfp_flags);
if (urb == NULL) { if (urb == NULL) {
uvc_uninit_video(stream, 1); uvc_uninit_video(stream, 1);
return -ENOMEM; return -ENOMEM;
} }
usb_fill_bulk_urb(urb, stream->dev->udev, pipe, usb_fill_bulk_urb(urb, stream->dev->udev, pipe, uvc_urb->buffer,
stream->urb_buffer[i], size, uvc_video_complete, size, uvc_video_complete, stream);
stream);
#ifndef CONFIG_DMA_NONCOHERENT #ifndef CONFIG_DMA_NONCOHERENT
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
urb->transfer_dma = stream->urb_dma[i]; urb->transfer_dma = uvc_urb->dma;
#endif #endif
stream->urb[i] = urb; uvc_urb->urb = urb;
} }
return 0; return 0;
...@@ -1822,7 +1831,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) ...@@ -1822,7 +1831,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
/* Submit the URBs. */ /* Submit the URBs. */
for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < UVC_URBS; ++i) {
ret = usb_submit_urb(stream->urb[i], gfp_flags); struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
ret = usb_submit_urb(uvc_urb->urb, gfp_flags);
if (ret < 0) { if (ret < 0) {
uvc_printk(KERN_ERR, "Failed to submit URB %u " uvc_printk(KERN_ERR, "Failed to submit URB %u "
"(%d).\n", i, ret); "(%d).\n", i, ret);
......
...@@ -490,6 +490,20 @@ struct uvc_stats_stream { ...@@ -490,6 +490,20 @@ struct uvc_stats_stream {
#define UVC_METATADA_BUF_SIZE 1024 #define UVC_METATADA_BUF_SIZE 1024
/**
* struct uvc_urb - URB context management structure
*
* @urb: the URB described by this context structure
* @buffer: memory storage for the URB
* @dma: DMA coherent addressing for the urb_buffer
*/
struct uvc_urb {
struct urb *urb;
char *buffer;
dma_addr_t dma;
};
struct uvc_streaming { struct uvc_streaming {
struct list_head list; struct list_head list;
struct uvc_device *dev; struct uvc_device *dev;
...@@ -538,9 +552,7 @@ struct uvc_streaming { ...@@ -538,9 +552,7 @@ struct uvc_streaming {
u32 max_payload_size; u32 max_payload_size;
} bulk; } bulk;
struct urb *urb[UVC_URBS]; struct uvc_urb uvc_urb[UVC_URBS];
char *urb_buffer[UVC_URBS];
dma_addr_t urb_dma[UVC_URBS];
unsigned int urb_size; unsigned int urb_size;
u32 sequence; u32 sequence;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment