Loading drivers/media/usb/uvc/uvc_driver.c +71 −0 Original line number Diff line number Diff line Loading @@ -2093,6 +2093,71 @@ struct uvc_device_info { u32 meta_format; }; /* ------------------------------------------------------------------------ * set urb queue size and urb packet size * */ static ssize_t store_urb_config(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { struct uvc_streaming *stream; struct usb_interface *intf = to_usb_interface(dev); struct uvc_device *udev = usb_get_intfdata(intf); long max_urb, max_urb_packets; int ret; char *arr, *tmp; arr = kstrdup(buff, GFP_KERNEL); if (!arr) return -ENOMEM; tmp = strsep(&arr, ":"); if (!tmp) return -EINVAL; ret = kstrtol(tmp, 10, &max_urb); if (ret < 0) return ret; tmp = strsep(&arr, ":"); if (!tmp) return -EINVAL; ret = kstrtol(tmp, 10, &max_urb_packets); if (ret < 0) return ret; if (max_urb <= 0 || max_urb > 128 || max_urb_packets <= 0 || max_urb_packets > 128) return -EINVAL; list_for_each_entry(stream, &udev->streams, list) { if (stream->refcnt) continue; stream->max_urb = max_urb; stream->max_urb_packets = max_urb_packets; } return count; } static ssize_t show_urb_config(struct device *dev, struct device_attribute *attr, char *buff) { return 0; } static struct device_attribute urb_config_attr = { .attr = { .name = "urb_config", .mode = 00660, }, .show = show_urb_config, .store = store_urb_config, }; static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) { Loading Loading @@ -2225,6 +2290,12 @@ static int uvc_probe(struct usb_interface *intf, uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); usb_enable_autosuspend(udev); /* sysfs file for dynamically setting urb configs */ ret = sysfs_create_file(&dev->intf->dev.kobj, &urb_config_attr.attr); if (ret != 0) pr_info("Unable to initialize urb configuration: %d\n", ret); return 0; error: Loading drivers/media/usb/uvc/uvc_video.c +28 −12 Original line number Diff line number Diff line Loading @@ -1515,7 +1515,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream) { unsigned int i; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { if (stream->urb_buffer[i]) { #ifndef CONFIG_DMA_NONCOHERENT usb_free_coherent(stream->dev->udev, stream->urb_size, Loading Loading @@ -1555,12 +1555,22 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, * payloads across multiple URBs. */ npackets = DIV_ROUND_UP(size, psize); if (npackets > UVC_MAX_PACKETS) npackets = UVC_MAX_PACKETS; if (npackets > stream->max_urb_packets) npackets = stream->max_urb_packets; /* Allocate memory for storing URB pointers */ stream->urb = kcalloc(stream->max_urb, sizeof(struct urb *), gfp_flags | __GFP_NOWARN); stream->urb_buffer = kcalloc(stream->max_urb, sizeof(char *), gfp_flags | __GFP_NOWARN); stream->urb_dma = kcalloc(stream->max_urb, sizeof(dma_addr_t), gfp_flags | __GFP_NOWARN); /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { stream->urb_size = psize * npackets; #ifndef CONFIG_DMA_NONCOHERENT stream->urb_buffer[i] = usb_alloc_coherent( Loading @@ -1576,10 +1586,10 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, } } if (i == UVC_URBS) { uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " "of %ux%u bytes each.\n", UVC_URBS, npackets, psize); if (i == stream->max_urb) { uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers of %ux%u bytes each.\n", stream->max_urb, npackets, psize); return npackets; } } Loading @@ -1599,7 +1609,7 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) uvc_video_stats_stop(stream); for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = stream->urb[i]; if (urb == NULL) continue; Loading @@ -1611,6 +1621,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) if (free_buffers) uvc_free_urb_buffers(stream); stream->refcnt--; } /* Loading Loading @@ -1660,7 +1672,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, size = npackets * psize; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); Loading Loading @@ -1726,7 +1738,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) size = 0; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); Loading Loading @@ -1831,7 +1843,8 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) return ret; /* Submit the URBs. */ for (i = 0; i < UVC_URBS; ++i) { stream->refcnt++; for (i = 0; i < stream->max_urb; ++i) { ret = usb_submit_urb(stream->urb[i], gfp_flags); if (ret < 0) { uvc_printk(KERN_ERR, "Failed to submit URB %u " Loading Loading @@ -1992,6 +2005,9 @@ int uvc_video_init(struct uvc_streaming *stream) stream->cur_format = format; stream->cur_frame = frame; stream->max_urb = UVC_URBS; stream->max_urb_packets = UVC_MAX_PACKETS; /* Select the video decoding function */ if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) Loading drivers/media/usb/uvc/uvcvideo.h +12 −3 Original line number Diff line number Diff line Loading @@ -535,9 +535,9 @@ 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 urb **urb; char **urb_buffer; dma_addr_t *urb_dma; unsigned int urb_size; u32 sequence; Loading Loading @@ -570,6 +570,15 @@ struct uvc_streaming { spinlock_t lock; } clock; /* Maximum number of URBs that can be submitted */ u32 max_urb; /* Maximum number of packets per URB */ u32 max_urb_packets; /*set if stream in progress */ u8 refcnt; }; struct uvc_device { Loading Loading
drivers/media/usb/uvc/uvc_driver.c +71 −0 Original line number Diff line number Diff line Loading @@ -2093,6 +2093,71 @@ struct uvc_device_info { u32 meta_format; }; /* ------------------------------------------------------------------------ * set urb queue size and urb packet size * */ static ssize_t store_urb_config(struct device *dev, struct device_attribute *attr, const char *buff, size_t count) { struct uvc_streaming *stream; struct usb_interface *intf = to_usb_interface(dev); struct uvc_device *udev = usb_get_intfdata(intf); long max_urb, max_urb_packets; int ret; char *arr, *tmp; arr = kstrdup(buff, GFP_KERNEL); if (!arr) return -ENOMEM; tmp = strsep(&arr, ":"); if (!tmp) return -EINVAL; ret = kstrtol(tmp, 10, &max_urb); if (ret < 0) return ret; tmp = strsep(&arr, ":"); if (!tmp) return -EINVAL; ret = kstrtol(tmp, 10, &max_urb_packets); if (ret < 0) return ret; if (max_urb <= 0 || max_urb > 128 || max_urb_packets <= 0 || max_urb_packets > 128) return -EINVAL; list_for_each_entry(stream, &udev->streams, list) { if (stream->refcnt) continue; stream->max_urb = max_urb; stream->max_urb_packets = max_urb_packets; } return count; } static ssize_t show_urb_config(struct device *dev, struct device_attribute *attr, char *buff) { return 0; } static struct device_attribute urb_config_attr = { .attr = { .name = "urb_config", .mode = 00660, }, .show = show_urb_config, .store = store_urb_config, }; static int uvc_probe(struct usb_interface *intf, const struct usb_device_id *id) { Loading Loading @@ -2225,6 +2290,12 @@ static int uvc_probe(struct usb_interface *intf, uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); usb_enable_autosuspend(udev); /* sysfs file for dynamically setting urb configs */ ret = sysfs_create_file(&dev->intf->dev.kobj, &urb_config_attr.attr); if (ret != 0) pr_info("Unable to initialize urb configuration: %d\n", ret); return 0; error: Loading
drivers/media/usb/uvc/uvc_video.c +28 −12 Original line number Diff line number Diff line Loading @@ -1515,7 +1515,7 @@ static void uvc_free_urb_buffers(struct uvc_streaming *stream) { unsigned int i; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { if (stream->urb_buffer[i]) { #ifndef CONFIG_DMA_NONCOHERENT usb_free_coherent(stream->dev->udev, stream->urb_size, Loading Loading @@ -1555,12 +1555,22 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, * payloads across multiple URBs. */ npackets = DIV_ROUND_UP(size, psize); if (npackets > UVC_MAX_PACKETS) npackets = UVC_MAX_PACKETS; if (npackets > stream->max_urb_packets) npackets = stream->max_urb_packets; /* Allocate memory for storing URB pointers */ stream->urb = kcalloc(stream->max_urb, sizeof(struct urb *), gfp_flags | __GFP_NOWARN); stream->urb_buffer = kcalloc(stream->max_urb, sizeof(char *), gfp_flags | __GFP_NOWARN); stream->urb_dma = kcalloc(stream->max_urb, sizeof(dma_addr_t), gfp_flags | __GFP_NOWARN); /* Retry allocations until one succeed. */ for (; npackets > 1; npackets /= 2) { for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { stream->urb_size = psize * npackets; #ifndef CONFIG_DMA_NONCOHERENT stream->urb_buffer[i] = usb_alloc_coherent( Loading @@ -1576,10 +1586,10 @@ static int uvc_alloc_urb_buffers(struct uvc_streaming *stream, } } if (i == UVC_URBS) { uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers " "of %ux%u bytes each.\n", UVC_URBS, npackets, psize); if (i == stream->max_urb) { uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers of %ux%u bytes each.\n", stream->max_urb, npackets, psize); return npackets; } } Loading @@ -1599,7 +1609,7 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) uvc_video_stats_stop(stream); for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = stream->urb[i]; if (urb == NULL) continue; Loading @@ -1611,6 +1621,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) if (free_buffers) uvc_free_urb_buffers(stream); stream->refcnt--; } /* Loading Loading @@ -1660,7 +1672,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream, size = npackets * psize; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); Loading Loading @@ -1726,7 +1738,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) size = 0; for (i = 0; i < UVC_URBS; ++i) { for (i = 0; i < stream->max_urb; ++i) { urb = usb_alloc_urb(0, gfp_flags); if (urb == NULL) { uvc_uninit_video(stream, 1); Loading Loading @@ -1831,7 +1843,8 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) return ret; /* Submit the URBs. */ for (i = 0; i < UVC_URBS; ++i) { stream->refcnt++; for (i = 0; i < stream->max_urb; ++i) { ret = usb_submit_urb(stream->urb[i], gfp_flags); if (ret < 0) { uvc_printk(KERN_ERR, "Failed to submit URB %u " Loading Loading @@ -1992,6 +2005,9 @@ int uvc_video_init(struct uvc_streaming *stream) stream->cur_format = format; stream->cur_frame = frame; stream->max_urb = UVC_URBS; stream->max_urb_packets = UVC_MAX_PACKETS; /* Select the video decoding function */ if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) Loading
drivers/media/usb/uvc/uvcvideo.h +12 −3 Original line number Diff line number Diff line Loading @@ -535,9 +535,9 @@ 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 urb **urb; char **urb_buffer; dma_addr_t *urb_dma; unsigned int urb_size; u32 sequence; Loading Loading @@ -570,6 +570,15 @@ struct uvc_streaming { spinlock_t lock; } clock; /* Maximum number of URBs that can be submitted */ u32 max_urb; /* Maximum number of packets per URB */ u32 max_urb_packets; /*set if stream in progress */ u8 refcnt; }; struct uvc_device { Loading