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

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
Loading
Loading
Loading
Loading
+30 −19
Original line number Diff line number Diff line
@@ -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);
+15 −3
Original line number Diff line number Diff line
@@ -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;