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: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
9b90dc85c7
commit
811496c967
@ -1506,14 +1506,16 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream)
|
||||
unsigned int 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
|
||||
usb_free_coherent(stream->dev->udev, stream->urb_size,
|
||||
stream->urb_buffer[i], stream->urb_dma[i]);
|
||||
uvc_urb->buffer, uvc_urb->dma);
|
||||
#else
|
||||
kfree(stream->urb_buffer[i]);
|
||||
kfree(uvc_urb->buffer);
|
||||
#endif
|
||||
stream->urb_buffer[i] = NULL;
|
||||
uvc_urb->buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1551,16 +1553,18 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
|
||||
/* Retry allocations until one succeed. */
|
||||
for (; npackets > 1; npackets /= 2) {
|
||||
for (i = 0; i < UVC_URBS; ++i) {
|
||||
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
|
||||
|
||||
stream->urb_size = psize * npackets;
|
||||
#ifndef CONFIG_DMA_NONCOHERENT
|
||||
stream->urb_buffer[i] = usb_alloc_coherent(
|
||||
uvc_urb->buffer = usb_alloc_coherent(
|
||||
stream->dev->udev, stream->urb_size,
|
||||
gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
|
||||
gfp_flags | __GFP_NOWARN, &uvc_urb->dma);
|
||||
#else
|
||||
stream->urb_buffer[i] =
|
||||
uvc_urb->buffer =
|
||||
kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
|
||||
#endif
|
||||
if (!stream->urb_buffer[i]) {
|
||||
if (!uvc_urb->buffer) {
|
||||
uvc_free_urb_buffers(stream);
|
||||
break;
|
||||
}
|
||||
@ -1590,13 +1594,15 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
|
||||
uvc_video_stats_stop(stream);
|
||||
|
||||
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)
|
||||
continue;
|
||||
|
||||
usb_kill_urb(urb);
|
||||
usb_free_urb(urb);
|
||||
stream->urb[i] = NULL;
|
||||
uvc_urb->urb = NULL;
|
||||
}
|
||||
|
||||
if (free_buffers)
|
||||
@ -1651,6 +1657,8 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
|
||||
size = npackets * psize;
|
||||
|
||||
for (i = 0; i < UVC_URBS; ++i) {
|
||||
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
|
||||
|
||||
urb = usb_alloc_urb(npackets, gfp_flags);
|
||||
if (urb == NULL) {
|
||||
uvc_uninit_video(stream, 1);
|
||||
@ -1663,12 +1671,12 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
|
||||
ep->desc.bEndpointAddress);
|
||||
#ifndef CONFIG_DMA_NONCOHERENT
|
||||
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
|
||||
urb->transfer_flags = URB_ISO_ASAP;
|
||||
#endif
|
||||
urb->interval = ep->desc.bInterval;
|
||||
urb->transfer_buffer = stream->urb_buffer[i];
|
||||
urb->transfer_buffer = uvc_urb->buffer;
|
||||
urb->complete = uvc_video_complete;
|
||||
urb->number_of_packets = npackets;
|
||||
urb->transfer_buffer_length = size;
|
||||
@ -1678,7 +1686,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
|
||||
urb->iso_frame_desc[j].length = psize;
|
||||
}
|
||||
|
||||
stream->urb[i] = urb;
|
||||
uvc_urb->urb = urb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1717,21 +1725,22 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
|
||||
size = 0;
|
||||
|
||||
for (i = 0; i < UVC_URBS; ++i) {
|
||||
struct uvc_urb *uvc_urb = &stream->uvc_urb[i];
|
||||
|
||||
urb = usb_alloc_urb(0, gfp_flags);
|
||||
if (urb == NULL) {
|
||||
uvc_uninit_video(stream, 1);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
|
||||
stream->urb_buffer[i], size, uvc_video_complete,
|
||||
stream);
|
||||
usb_fill_bulk_urb(urb, stream->dev->udev, pipe, uvc_urb->buffer,
|
||||
size, uvc_video_complete, stream);
|
||||
#ifndef CONFIG_DMA_NONCOHERENT
|
||||
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
|
||||
urb->transfer_dma = stream->urb_dma[i];
|
||||
urb->transfer_dma = uvc_urb->dma;
|
||||
#endif
|
||||
|
||||
stream->urb[i] = urb;
|
||||
uvc_urb->urb = urb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1822,7 +1831,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
|
||||
|
||||
/* Submit the URBs. */
|
||||
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) {
|
||||
uvc_printk(KERN_ERR, "Failed to submit URB %u "
|
||||
"(%d).\n", i, ret);
|
||||
|
@ -490,6 +490,20 @@ struct uvc_stats_stream {
|
||||
|
||||
#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 list_head list;
|
||||
struct uvc_device *dev;
|
||||
@ -538,9 +552,7 @@ struct uvc_streaming {
|
||||
u32 max_payload_size;
|
||||
} bulk;
|
||||
|
||||
struct urb *urb[UVC_URBS];
|
||||
char *urb_buffer[UVC_URBS];
|
||||
dma_addr_t urb_dma[UVC_URBS];
|
||||
struct uvc_urb uvc_urb[UVC_URBS];
|
||||
unsigned int urb_size;
|
||||
|
||||
u32 sequence;
|
||||
|
Loading…
Reference in New Issue
Block a user