diff options
Diffstat (limited to 'drivers/usb/gadget')
23 files changed, 402 insertions, 327 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2eaeaae96759..403563c06477 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2505,7 +2505,7 @@ int usb_composite_probe(struct usb_composite_driver *driver) gadget_driver->driver.name = driver->name; gadget_driver->max_speed = driver->max_speed; - return usb_gadget_probe_driver(gadget_driver); + return usb_gadget_register_driver(gadget_driver); } EXPORT_SYMBOL_GPL(usb_composite_probe); diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 84b73cb03f87..3a6b4926193e 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -284,7 +284,7 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, goto err; } gi->composite.gadget_driver.udc_name = name; - ret = usb_gadget_probe_driver(&gi->composite.gadget_driver); + ret = usb_gadget_register_driver(&gi->composite.gadget_driver); if (ret) { gi->composite.gadget_driver.udc_name = NULL; goto err; diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 349945e064bb..411eb489e0ff 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -333,6 +333,8 @@ static void acm_complete_set_line_coding(struct usb_ep *ep, } } +static int acm_send_break(struct gserial *port, int duration); + static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { struct f_acm *acm = func_to_acm(f); @@ -391,6 +393,14 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) acm->port_handshake_bits = w_value; break; + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SEND_BREAK: + if (w_index != acm->ctrl_id) + goto invalid; + + acm_send_break(&acm->port, w_value); + break; + default: invalid: dev_vdbg(&cdev->gadget->dev, diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index d37965867b23..d3feeeb50841 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -24,7 +24,6 @@ #include <media/v4l2-dev.h> #include <media/v4l2-event.h> -#include "u_uvc.h" #include "uvc.h" #include "uvc_configfs.h" #include "uvc_v4l2.h" @@ -44,7 +43,7 @@ MODULE_PARM_DESC(trace, "Trace level bitmask"); #define UVC_STRING_STREAMING_IDX 1 static struct usb_string uvc_en_us_strings[] = { - [UVC_STRING_CONTROL_IDX].s = "UVC Camera", + /* [UVC_STRING_CONTROL_IDX].s = DYNAMIC, */ [UVC_STRING_STREAMING_IDX].s = "Video Streaming", { } }; @@ -676,6 +675,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->function_name; us = usb_gstrings_attach(cdev, uvc_function_strings, ARRAY_SIZE(uvc_en_us_strings)); if (IS_ERR(us)) { @@ -866,6 +866,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) opts->streaming_interval = 1; opts->streaming_maxpacket = 1024; + snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); ret = uvcg_attach_configfs(opts); if (ret < 0) { diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 2bb569895a90..c1f62e91b012 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -1179,8 +1179,8 @@ int g_audio_setup(struct g_audio *g_audio, const char *pcm_name, if (c_chmask) { struct uac_rtd_params *prm = &uac->c_prm; - spin_lock_init(&prm->lock); - uac->c_prm.uac = uac; + spin_lock_init(&prm->lock); + uac->c_prm.uac = uac; prm->max_psize = g_audio->out_ep_maxpsize; prm->srate = params->c_srates[0]; diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 9a01a7d4f17f..24b8681b0d6f 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -27,6 +27,7 @@ struct f_uvc_opts { unsigned int control_interface; unsigned int streaming_interface; + char function_name[32]; /* * Control descriptors array pointers for full-/high-speed and diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 886103a1fe9b..58e383afdd44 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -80,6 +80,7 @@ struct uvc_request { struct uvc_video *video; struct sg_table sgt; u8 header[UVCG_REQUEST_HEADER_LEN]; + struct uvc_buffer *last_buf; }; struct uvc_video { diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 77d64031aa9c..e5a6b6e36b3d 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -10,17 +10,14 @@ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com> */ -#include <linux/sort.h> - -#include "u_uvc.h" #include "uvc_configfs.h" +#include <linux/sort.h> + /* ----------------------------------------------------------------------------- * Global Utility Structures and Macros */ -#define UVCG_STREAMING_CONTROL_SIZE 1 - #define UVC_ATTR(prefix, cname, aname) \ static struct configfs_attribute prefix##attr_##cname = { \ .ca_name = __stringify(aname), \ @@ -49,12 +46,6 @@ static int uvcg_config_compare_u32(const void *l, const void *r) return li < ri ? -1 : li == ri ? 0 : 1; } -static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item) -{ - return container_of(to_config_group(item), struct f_uvc_opts, - func_inst.group); -} - struct uvcg_config_group_type { struct config_item_type type; const char *name; @@ -125,19 +116,6 @@ static void uvcg_config_remove_children(struct config_group *group) * control/header */ -DECLARE_UVC_HEADER_DESCRIPTOR(1); - -struct uvcg_control_header { - struct config_item item; - struct UVC_HEADER_DESCRIPTOR(1) desc; - unsigned linked; -}; - -static struct uvcg_control_header *to_uvcg_control_header(struct config_item *item) -{ - return container_of(item, struct uvcg_control_header, item); -} - #define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \ static ssize_t uvcg_control_header_##cname##_show( \ struct config_item *item, char *page) \ @@ -769,24 +747,6 @@ static const char * const uvcg_format_names[] = { "mjpeg", }; -enum uvcg_format_type { - UVCG_UNCOMPRESSED = 0, - UVCG_MJPEG, -}; - -struct uvcg_format { - struct config_group group; - enum uvcg_format_type type; - unsigned linked; - unsigned num_frames; - __u8 bmaControls[UVCG_STREAMING_CONTROL_SIZE]; -}; - -static struct uvcg_format *to_uvcg_format(struct config_item *item) -{ - return container_of(to_config_group(item), struct uvcg_format, group); -} - static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page) { struct f_uvc_opts *opts; @@ -845,29 +805,11 @@ end: return ret; } -struct uvcg_format_ptr { - struct uvcg_format *fmt; - struct list_head entry; -}; - /* ----------------------------------------------------------------------------- * streaming/header/<NAME> * streaming/header */ -struct uvcg_streaming_header { - struct config_item item; - struct uvc_input_header_descriptor desc; - unsigned linked; - struct list_head formats; - unsigned num_fmt; -}; - -static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item) -{ - return container_of(item, struct uvcg_streaming_header, item); -} - static void uvcg_format_set_indices(struct config_group *fmt); static int uvcg_streaming_header_allow_link(struct config_item *src, @@ -1059,31 +1001,6 @@ static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = { * streaming/<mode>/<format>/<NAME> */ -struct uvcg_frame { - struct config_item item; - enum uvcg_format_type fmt_type; - struct { - u8 b_length; - u8 b_descriptor_type; - u8 b_descriptor_subtype; - u8 b_frame_index; - u8 bm_capabilities; - u16 w_width; - u16 w_height; - u32 dw_min_bit_rate; - u32 dw_max_bit_rate; - u32 dw_max_video_frame_buffer_size; - u32 dw_default_frame_interval; - u8 b_frame_interval_type; - } __attribute__((packed)) frame; - u32 *dw_frame_interval; -}; - -static struct uvcg_frame *to_uvcg_frame(struct config_item *item) -{ - return container_of(item, struct uvcg_frame, item); -} - #define UVCG_FRAME_ATTR(cname, aname, bits) \ static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\ { \ @@ -1345,6 +1262,7 @@ static struct config_item *uvcg_frame_make(struct config_group *group, struct uvcg_format *fmt; struct f_uvc_opts *opts; struct config_item *opts_item; + struct uvcg_frame_ptr *frame_ptr; h = kzalloc(sizeof(*h), GFP_KERNEL); if (!h) @@ -1375,6 +1293,16 @@ static struct config_item *uvcg_frame_make(struct config_group *group, kfree(h); return ERR_PTR(-EINVAL); } + + frame_ptr = kzalloc(sizeof(*frame_ptr), GFP_KERNEL); + if (!frame_ptr) { + mutex_unlock(&opts->lock); + kfree(h); + return ERR_PTR(-ENOMEM); + } + + frame_ptr->frm = h; + list_add_tail(&frame_ptr->entry, &fmt->frames); ++fmt->num_frames; mutex_unlock(&opts->lock); @@ -1388,13 +1316,23 @@ static void uvcg_frame_drop(struct config_group *group, struct config_item *item struct uvcg_format *fmt; struct f_uvc_opts *opts; struct config_item *opts_item; + struct uvcg_frame *target_frm = NULL; + struct uvcg_frame_ptr *frame_ptr, *tmp; opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; opts = to_f_uvc_opts(opts_item); mutex_lock(&opts->lock); + target_frm = container_of(item, struct uvcg_frame, item); fmt = to_uvcg_format(&group->cg_item); - --fmt->num_frames; + + list_for_each_entry_safe(frame_ptr, tmp, &fmt->frames, entry) + if (frame_ptr->frm == target_frm) { + list_del(&frame_ptr->entry); + kfree(frame_ptr); + --fmt->num_frames; + break; + } mutex_unlock(&opts->lock); config_item_put(item); @@ -1420,18 +1358,6 @@ static void uvcg_format_set_indices(struct config_group *fmt) * streaming/uncompressed/<NAME> */ -struct uvcg_uncompressed { - struct uvcg_format fmt; - struct uvc_format_uncompressed desc; -}; - -static struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item) -{ - return container_of( - container_of(to_config_group(item), struct uvcg_format, group), - struct uvcg_uncompressed, fmt); -} - static struct configfs_group_operations uvcg_uncompressed_group_ops = { .make_item = uvcg_frame_make, .drop_item = uvcg_frame_drop, @@ -1565,6 +1491,12 @@ uvcg_uncompressed_##cname##_store(struct config_item *item, \ if (ret) \ goto end; \ \ + /* index values in uvc are never 0 */ \ + if (!num) { \ + ret = -EINVAL; \ + goto end; \ + } \ + \ u->desc.aname = num; \ ret = len; \ end: \ @@ -1645,6 +1577,7 @@ static struct config_group *uvcg_uncompressed_make(struct config_group *group, h->desc.bmInterfaceFlags = 0; h->desc.bCopyProtect = 0; + INIT_LIST_HEAD(&h->fmt.frames); h->fmt.type = UVCG_UNCOMPRESSED; config_group_init_type_name(&h->fmt.group, name, &uvcg_uncompressed_type); @@ -1669,18 +1602,6 @@ static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = { * streaming/mjpeg/<NAME> */ -struct uvcg_mjpeg { - struct uvcg_format fmt; - struct uvc_format_mjpeg desc; -}; - -static struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item) -{ - return container_of( - container_of(to_config_group(item), struct uvcg_format, group), - struct uvcg_mjpeg, fmt); -} - static struct configfs_group_operations uvcg_mjpeg_group_ops = { .make_item = uvcg_frame_make, .drop_item = uvcg_frame_drop, @@ -1758,6 +1679,12 @@ uvcg_mjpeg_##cname##_store(struct config_item *item, \ if (ret) \ goto end; \ \ + /* index values in uvc are never 0 */ \ + if (!num) { \ + ret = -EINVAL; \ + goto end; \ + } \ + \ u->desc.aname = num; \ ret = len; \ end: \ @@ -1831,6 +1758,7 @@ static struct config_group *uvcg_mjpeg_make(struct config_group *group, h->desc.bmInterfaceFlags = 0; h->desc.bCopyProtect = 0; + INIT_LIST_HEAD(&h->fmt.frames); h->fmt.type = UVCG_MJPEG; config_group_init_type_name(&h->fmt.group, name, &uvcg_mjpeg_type); @@ -2425,10 +2353,51 @@ UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15); #undef UVCG_OPTS_ATTR +#define UVCG_OPTS_STRING_ATTR(cname, aname) \ +static ssize_t f_uvc_opts_string_##cname##_show(struct config_item *item,\ + char *page) \ +{ \ + struct f_uvc_opts *opts = to_f_uvc_opts(item); \ + int result; \ + \ + mutex_lock(&opts->lock); \ + result = snprintf(page, sizeof(opts->aname), "%s", opts->aname);\ + mutex_unlock(&opts->lock); \ + \ + return result; \ +} \ + \ +static ssize_t f_uvc_opts_string_##cname##_store(struct config_item *item,\ + const char *page, size_t len) \ +{ \ + struct f_uvc_opts *opts = to_f_uvc_opts(item); \ + int ret = 0; \ + \ + mutex_lock(&opts->lock); \ + if (opts->refcnt) { \ + ret = -EBUSY; \ + goto end; \ + } \ + \ + ret = snprintf(opts->aname, min(sizeof(opts->aname), len), \ + "%s", page); \ + \ +end: \ + mutex_unlock(&opts->lock); \ + return ret; \ +} \ + \ +UVC_ATTR(f_uvc_opts_string_, cname, aname) + +UVCG_OPTS_STRING_ATTR(function_name, function_name); + +#undef UVCG_OPTS_STRING_ATTR + static struct configfs_attribute *uvc_attrs[] = { &f_uvc_opts_attr_streaming_interval, &f_uvc_opts_attr_streaming_maxpacket, &f_uvc_opts_attr_streaming_maxburst, + &f_uvc_opts_string_attr_function_name, NULL, }; diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h index 7e1d7ca29bf2..ad2ec8c4c78c 100644 --- a/drivers/usb/gadget/function/uvc_configfs.h +++ b/drivers/usb/gadget/function/uvc_configfs.h @@ -12,7 +12,125 @@ #ifndef UVC_CONFIGFS_H #define UVC_CONFIGFS_H -struct f_uvc_opts; +#include <linux/configfs.h> + +#include "u_uvc.h" + +static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_uvc_opts, + func_inst.group); +} + +#define UVCG_STREAMING_CONTROL_SIZE 1 + +DECLARE_UVC_HEADER_DESCRIPTOR(1); + +struct uvcg_control_header { + struct config_item item; + struct UVC_HEADER_DESCRIPTOR(1) desc; + unsigned linked; +}; + +static inline struct uvcg_control_header *to_uvcg_control_header(struct config_item *item) +{ + return container_of(item, struct uvcg_control_header, item); +} + +enum uvcg_format_type { + UVCG_UNCOMPRESSED = 0, + UVCG_MJPEG, +}; + +struct uvcg_format { + struct config_group group; + enum uvcg_format_type type; + unsigned linked; + struct list_head frames; + unsigned num_frames; + __u8 bmaControls[UVCG_STREAMING_CONTROL_SIZE]; +}; + +struct uvcg_format_ptr { + struct uvcg_format *fmt; + struct list_head entry; +}; + +static inline struct uvcg_format *to_uvcg_format(struct config_item *item) +{ + return container_of(to_config_group(item), struct uvcg_format, group); +} + +struct uvcg_streaming_header { + struct config_item item; + struct uvc_input_header_descriptor desc; + unsigned linked; + struct list_head formats; + unsigned num_fmt; +}; + +static inline struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item *item) +{ + return container_of(item, struct uvcg_streaming_header, item); +} + +struct uvcg_frame_ptr { + struct uvcg_frame *frm; + struct list_head entry; +}; + +struct uvcg_frame { + struct config_item item; + enum uvcg_format_type fmt_type; + struct { + u8 b_length; + u8 b_descriptor_type; + u8 b_descriptor_subtype; + u8 b_frame_index; + u8 bm_capabilities; + u16 w_width; + u16 w_height; + u32 dw_min_bit_rate; + u32 dw_max_bit_rate; + u32 dw_max_video_frame_buffer_size; + u32 dw_default_frame_interval; + u8 b_frame_interval_type; + } __attribute__((packed)) frame; + u32 *dw_frame_interval; +}; + +static inline struct uvcg_frame *to_uvcg_frame(struct config_item *item) +{ + return container_of(item, struct uvcg_frame, item); +} + +/* ----------------------------------------------------------------------------- + * streaming/uncompressed/<NAME> + */ + +struct uvcg_uncompressed { + struct uvcg_format fmt; + struct uvc_format_uncompressed desc; +}; + +static inline struct uvcg_uncompressed *to_uvcg_uncompressed(struct config_item *item) +{ + return container_of(to_uvcg_format(item), struct uvcg_uncompressed, fmt); +} + +/* ----------------------------------------------------------------------------- + * streaming/mjpeg/<NAME> + */ + +struct uvcg_mjpeg { + struct uvcg_format fmt; + struct uvc_format_mjpeg desc; +}; + +static inline struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item) +{ + return container_of(to_uvcg_format(item), struct uvcg_mjpeg, fmt); +} int uvcg_attach_configfs(struct f_uvc_opts *opts); diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 2cda982f3765..d25edc3d2174 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -185,18 +185,7 @@ int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) { - unsigned long flags; - int ret; - - ret = vb2_qbuf(&queue->queue, NULL, buf); - if (ret < 0) - return ret; - - spin_lock_irqsave(&queue->irqlock, flags); - ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; - queue->flags &= ~UVC_QUEUE_PAUSED; - spin_unlock_irqrestore(&queue->irqlock, flags); - return ret; + return vb2_qbuf(&queue->queue, NULL, buf); } /* @@ -328,33 +317,22 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) } /* called with &queue_irqlock held.. */ -struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue, +void uvcg_complete_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { - struct uvc_buffer *nextbuf; - if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && buf->length != buf->bytesused) { buf->state = UVC_BUF_STATE_QUEUED; vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); - return buf; + return; } - list_del(&buf->queue); - if (!list_empty(&queue->irqqueue)) - nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - else - nextbuf = NULL; - buf->buf.field = V4L2_FIELD_NONE; buf->buf.sequence = queue->sequence++; buf->buf.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused); vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE); - - return nextbuf; } struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue) @@ -364,8 +342,6 @@ struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue) if (!list_empty(&queue->irqqueue)) buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); - else - queue->flags |= UVC_QUEUE_PAUSED; return buf; } diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 05360a0767f6..41f87b917f6b 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h @@ -43,7 +43,6 @@ struct uvc_buffer { #define UVC_QUEUE_DISCONNECTED (1 << 0) #define UVC_QUEUE_DROP_INCOMPLETE (1 << 1) -#define UVC_QUEUE_PAUSED (1 << 2) struct uvc_video_queue { struct vb2_queue queue; @@ -93,7 +92,7 @@ void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect); int uvcg_queue_enable(struct uvc_video_queue *queue, int enable); -struct uvc_buffer *uvcg_queue_next_buffer(struct uvc_video_queue *queue, +void uvcg_complete_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf); struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue); diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 7f59a0c47402..a9bb4553db84 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -112,7 +112,8 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, if (buf->bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; - uvcg_queue_next_buffer(&video->queue, buf); + list_del(&buf->queue); + uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; video->payload_size = 0; @@ -154,7 +155,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, sg = sg_next(sg); for_each_sg(sg, iter, ureq->sgt.nents - 1, i) { - if (!len || !buf->sg) + if (!len || !buf->sg || !sg_dma_len(buf->sg)) break; sg_left = sg_dma_len(buf->sg) - buf->offset; @@ -183,8 +184,9 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; buf->offset = 0; - uvcg_queue_next_buffer(&video->queue, buf); + list_del(&buf->queue); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; } } @@ -210,7 +212,8 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, if (buf->bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; - uvcg_queue_next_buffer(&video->queue, buf); + list_del(&buf->queue); + uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; } } @@ -264,6 +267,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) uvcg_queue_cancel(queue, 0); } + if (ureq->last_buf) { + uvcg_complete_buffer(&video->queue, ureq->last_buf); + ureq->last_buf = NULL; + } + spin_lock_irqsave(&video->req_lock, flags); list_add_tail(&req->list, &video->req_free); spin_unlock_irqrestore(&video->req_lock, flags); @@ -332,6 +340,7 @@ uvc_video_alloc_requests(struct uvc_video *video) video->ureq[i].req->complete = uvc_video_complete; video->ureq[i].req->context = &video->ureq[i]; video->ureq[i].video = video; + video->ureq[i].last_buf = NULL; list_add_tail(&video->ureq[i].req->list, &video->req_free); /* req_size/PAGE_SIZE + 1 for overruns and + 1 for header */ diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index 6bcbad382580..b62e45235e8e 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -422,7 +422,7 @@ static struct usb_gadget_driver dbgp_driver = { static int __init dbgp_init(void) { - return usb_gadget_probe_driver(&dbgp_driver); + return usb_gadget_register_driver(&dbgp_driver); } static void __exit dbgp_exit(void) diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 0c01e749f9ea..79990597c39f 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1873,7 +1873,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) else gadgetfs_driver.max_speed = USB_SPEED_FULL; - value = usb_gadget_probe_driver(&gadgetfs_driver); + value = usb_gadget_register_driver(&gadgetfs_driver); if (value != 0) { spin_lock_irq(&dev->lock); goto fail; diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c index e9440f7bf019..241740024c50 100644 --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -512,12 +512,12 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value) dev->state = STATE_DEV_REGISTERING; spin_unlock_irqrestore(&dev->lock, flags); - ret = usb_gadget_probe_driver(&dev->driver); + ret = usb_gadget_register_driver(&dev->driver); spin_lock_irqsave(&dev->lock, flags); if (ret) { dev_err(dev->dev, - "fail, usb_gadget_probe_driver returned %d\n", ret); + "fail, usb_gadget_register_driver returned %d\n", ret); dev->state = STATE_DEV_FAILED; goto out_unlock; } diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 85b194011a16..7886497253cc 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/list.h> +#include <linux/idr.h> #include <linux/err.h> #include <linux/dma-mapping.h> #include <linux/sched/task_stack.h> @@ -23,6 +24,10 @@ #include "trace.h" +static DEFINE_IDA(gadget_id_numbers); + +static struct bus_type gadget_bus_type; + /** * struct usb_udc - describes one usb device controller * @driver: the gadget driver pointer. For use by the class code @@ -47,11 +52,9 @@ struct usb_udc { static struct class *udc_class; static LIST_HEAD(udc_list); -static LIST_HEAD(gadget_driver_pending_list); -static DEFINE_MUTEX(udc_lock); -static int udc_bind_to_driver(struct usb_udc *udc, - struct usb_gadget_driver *driver); +/* Protects udc_list, udc->driver, driver->is_bound, and related calls */ +static DEFINE_MUTEX(udc_lock); /* ------------------------------------------------------------------------- */ @@ -1238,38 +1241,16 @@ static void usb_udc_nop_release(struct device *dev) dev_vdbg(dev, "%s\n", __func__); } -/* should be called with udc_lock held */ -static int check_pending_gadget_drivers(struct usb_udc *udc) -{ - struct usb_gadget_driver *driver; - int ret = 0; - - list_for_each_entry(driver, &gadget_driver_pending_list, pending) - if (!driver->udc_name || strcmp(driver->udc_name, - dev_name(&udc->dev)) == 0) { - ret = udc_bind_to_driver(udc, driver); - if (ret != -EPROBE_DEFER) - list_del_init(&driver->pending); - break; - } - - return ret; -} - /** * usb_initialize_gadget - initialize a gadget and its embedded struct device * @parent: the parent device to this udc. Usually the controller driver's * device. * @gadget: the gadget to be initialized. * @release: a gadget release function. - * - * Returns zero on success, negative errno otherwise. - * Calls the gadget release function in the latter case. */ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget, void (*release)(struct device *dev)) { - dev_set_name(&gadget->dev, "gadget"); INIT_WORK(&gadget->work, usb_gadget_state_work); gadget->dev.parent = parent; @@ -1279,6 +1260,7 @@ void usb_initialize_gadget(struct device *parent, struct usb_gadget *gadget, gadget->dev.release = usb_udc_nop_release; device_initialize(&gadget->dev); + gadget->dev.bus = &gadget_bus_type; } EXPORT_SYMBOL_GPL(usb_initialize_gadget); @@ -1308,10 +1290,6 @@ int usb_add_gadget(struct usb_gadget *gadget) if (ret) goto err_put_udc; - ret = device_add(&gadget->dev); - if (ret) - goto err_put_udc; - udc->gadget = gadget; gadget->udc = udc; @@ -1319,6 +1297,7 @@ int usb_add_gadget(struct usb_gadget *gadget) mutex_lock(&udc_lock); list_add_tail(&udc->list, &udc_list); + mutex_unlock(&udc_lock); ret = device_add(&udc->dev); if (ret) @@ -1327,25 +1306,30 @@ int usb_add_gadget(struct usb_gadget *gadget) usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); udc->vbus = true; - /* pick up one of pending gadget drivers */ - ret = check_pending_gadget_drivers(udc); - if (ret) + ret = ida_alloc(&gadget_id_numbers, GFP_KERNEL); + if (ret < 0) goto err_del_udc; + gadget->id_number = ret; + dev_set_name(&gadget->dev, "gadget.%d", ret); - mutex_unlock(&udc_lock); + ret = device_add(&gadget->dev); + if (ret) + goto err_free_id; return 0; + err_free_id: + ida_free(&gadget_id_numbers, gadget->id_number); + err_del_udc: flush_work(&gadget->work); device_del(&udc->dev); err_unlist_udc: + mutex_lock(&udc_lock); list_del(&udc->list); mutex_unlock(&udc_lock); - device_del(&gadget->dev); - err_put_udc: put_device(&udc->dev); @@ -1421,30 +1405,11 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) } EXPORT_SYMBOL_GPL(usb_add_gadget_udc); -static void usb_gadget_remove_driver(struct usb_udc *udc) -{ - dev_dbg(&udc->dev, "unregistering UDC driver [%s]\n", - udc->driver->function); - - kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); - - usb_gadget_disconnect(udc->gadget); - usb_gadget_disable_async_callbacks(udc); - if (udc->gadget->irq) - synchronize_irq(udc->gadget->irq); - udc->driver->unbind(udc->gadget); - usb_gadget_udc_stop(udc); - - udc->driver = NULL; - udc->gadget->dev.driver = NULL; -} - /** - * usb_del_gadget - deletes @udc from udc_list - * @gadget: the gadget to be removed. + * usb_del_gadget - deletes a gadget and unregisters its udc + * @gadget: the gadget to be deleted. * - * This will call usb_gadget_unregister_driver() if - * the @udc is still busy. + * This will unbind @gadget, if it is bound. * It will not do a final usb_put_gadget(). */ void usb_del_gadget(struct usb_gadget *gadget) @@ -1458,25 +1423,19 @@ void usb_del_gadget(struct usb_gadget *gadget) mutex_lock(&udc_lock); list_del(&udc->list); - - if (udc->driver) { - struct usb_gadget_driver *driver = udc->driver; - - usb_gadget_remove_driver(udc); - list_add(&driver->pending, &gadget_driver_pending_list); - } mutex_unlock(&udc_lock); kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); flush_work(&gadget->work); - device_unregister(&udc->dev); device_del(&gadget->dev); + ida_free(&gadget_id_numbers, gadget->id_number); + device_unregister(&udc->dev); } EXPORT_SYMBOL_GPL(usb_del_gadget); /** - * usb_del_gadget_udc - deletes @udc from udc_list - * @gadget: the gadget to be removed. + * usb_del_gadget_udc - unregisters a gadget + * @gadget: the gadget to be unregistered. * * Calls usb_del_gadget() and does a final usb_put_gadget(). */ @@ -1489,123 +1448,147 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc); /* ------------------------------------------------------------------------- */ -static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *driver) +static int gadget_match_driver(struct device *dev, struct device_driver *drv) { - int ret; + struct usb_gadget *gadget = dev_to_usb_gadget(dev); + struct usb_udc *udc = gadget->udc; + struct usb_gadget_driver *driver = container_of(drv, + struct usb_gadget_driver, driver); - dev_dbg(&udc->dev, "registering UDC driver [%s]\n", - driver->function); + /* If the driver specifies a udc_name, it must match the UDC's name */ + if (driver->udc_name && + strcmp(driver->udc_name, dev_name(&udc->dev)) != 0) + return 0; + + /* If the driver is already bound to a gadget, it doesn't match */ + if (driver->is_bound) + return 0; + + /* Otherwise any gadget driver matches any UDC */ + return 1; +} +static int gadget_bind_driver(struct device *dev) +{ + struct usb_gadget *gadget = dev_to_usb_gadget(dev); + struct usb_udc *udc = gadget->udc; + struct usb_gadget_driver *driver = container_of(dev->driver, + struct usb_gadget_driver, driver); + int ret = 0; + + mutex_lock(&udc_lock); + if (driver->is_bound) { + mutex_unlock(&udc_lock); + return -ENXIO; /* Driver binds to only one gadget */ + } + driver->is_bound = true; udc->driver = driver; - udc->gadget->dev.driver = &driver->driver; + mutex_unlock(&udc_lock); + + dev_dbg(&udc->dev, "binding gadget driver [%s]\n", driver->function); usb_gadget_udc_set_speed(udc, driver->max_speed); + mutex_lock(&udc_lock); ret = driver->bind(udc->gadget, driver); if (ret) - goto err1; + goto err_bind; + ret = usb_gadget_udc_start(udc); - if (ret) { - driver->unbind(udc->gadget); - goto err1; - } + if (ret) + goto err_start; usb_gadget_enable_async_callbacks(udc); usb_udc_connect_control(udc); + mutex_unlock(&udc_lock); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; -err1: + + err_start: + driver->unbind(udc->gadget); + + err_bind: if (ret != -EISNAM) dev_err(&udc->dev, "failed to start %s: %d\n", - udc->driver->function, ret); + driver->function, ret); + udc->driver = NULL; - udc->gadget->dev.driver = NULL; + driver->is_bound = false; + mutex_unlock(&udc_lock); + return ret; } -int usb_gadget_probe_driver(struct usb_gadget_driver *driver) +static void gadget_unbind_driver(struct device *dev) { - struct usb_udc *udc = NULL, *iter; - int ret = -ENODEV; + struct usb_gadget *gadget = dev_to_usb_gadget(dev); + struct usb_udc *udc = gadget->udc; + struct usb_gadget_driver *driver = udc->driver; + + dev_dbg(&udc->dev, "unbinding gadget driver [%s]\n", driver->function); + + kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); + + mutex_lock(&udc_lock); + usb_gadget_disconnect(gadget); + usb_gadget_disable_async_callbacks(udc); + if (gadget->irq) + synchronize_irq(gadget->irq); + udc->driver->unbind(gadget); + usb_gadget_udc_stop(udc); + + driver->is_bound = false; + udc->driver = NULL; + mutex_unlock(&udc_lock); +} + +/* ------------------------------------------------------------------------- */ + +int usb_gadget_register_driver_owner(struct usb_gadget_driver *driver, + struct module *owner, const char *mod_name) +{ + int ret; if (!driver || !driver->bind || !driver->setup) return -EINVAL; + driver->driver.bus = &gadget_bus_type; + driver->driver.owner = owner; + driver->driver.mod_name = mod_name; + ret = driver_register(&driver->driver); + if (ret) { + pr_warn("%s: driver registration failed: %d\n", + driver->function, ret); + return ret; + } + mutex_lock(&udc_lock); - if (driver->udc_name) { - list_for_each_entry(iter, &udc_list, list) { - ret = strcmp(driver->udc_name, dev_name(&iter->dev)); - if (ret) - continue; - udc = iter; - break; - } - if (ret) - ret = -ENODEV; - else if (udc->driver) + if (!driver->is_bound) { + if (driver->match_existing_only) { + pr_warn("%s: couldn't find an available UDC or it's busy\n", + driver->function); ret = -EBUSY; - else - goto found; - } else { - list_for_each_entry(iter, &udc_list, list) { - /* For now we take the first one */ - if (iter->driver) - continue; - udc = iter; - goto found; + } else { + pr_info("%s: couldn't find an available UDC\n", + driver->function); + ret = 0; } } - - if (!driver->match_existing_only) { - list_add_tail(&driver->pending, &gadget_driver_pending_list); - pr_info("couldn't find an available UDC - added [%s] to list of pending drivers\n", - driver->function); - ret = 0; - } - mutex_unlock(&udc_lock); + if (ret) - pr_warn("couldn't find an available UDC or it's busy: %d\n", ret); - return ret; -found: - ret = udc_bind_to_driver(udc, driver); - mutex_unlock(&udc_lock); + driver_unregister(&driver->driver); return ret; } -EXPORT_SYMBOL_GPL(usb_gadget_probe_driver); +EXPORT_SYMBOL_GPL(usb_gadget_register_driver_owner); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { - struct usb_udc *udc = NULL; - int ret = -ENODEV; - if (!driver || !driver->unbind) return -EINVAL; - mutex_lock(&udc_lock); - list_for_each_entry(udc, &udc_list, list) { - if (udc->driver == driver) { - usb_gadget_remove_driver(udc); - usb_gadget_set_state(udc->gadget, - USB_STATE_NOTATTACHED); - - /* Maybe there is someone waiting for this UDC? */ - check_pending_gadget_drivers(udc); - /* - * For now we ignore bind errors as probably it's - * not a valid reason to fail other's gadget unbind - */ - ret = 0; - break; - } - } - - if (ret) { - list_del(&driver->pending); - ret = 0; - } - mutex_unlock(&udc_lock); - return ret; + driver_unregister(&driver->driver); + return 0; } EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver); @@ -1757,8 +1740,17 @@ static int usb_udc_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static struct bus_type gadget_bus_type = { + .name = "gadget", + .probe = gadget_bind_driver, + .remove = gadget_unbind_driver, + .match = gadget_match_driver, +}; + static int __init usb_udc_init(void) { + int rc; + udc_class = class_create(THIS_MODULE, "udc"); if (IS_ERR(udc_class)) { pr_err("failed to create udc class --> %ld\n", @@ -1767,12 +1759,17 @@ static int __init usb_udc_init(void) } udc_class->dev_uevent = usb_udc_uevent; - return 0; + + rc = bus_register(&gadget_bus_type); + if (rc) + class_destroy(udc_class); + return rc; } subsys_initcall(usb_udc_init); static void __exit usb_udc_exit(void) { + bus_unregister(&gadget_bus_type); class_destroy(udc_class); } module_exit(usb_udc_exit); diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 6a8884632273..c97cd4bc817c 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -71,7 +71,7 @@ static ushort dma_ep = 1; module_param(dma_ep, ushort, 0644); /* - * dma_mode: net2272 dma mode setting (see LOCCTL1 definiton): + * dma_mode: net2272 dma mode setting (see LOCCTL1 definition): * mode 0 == Slow DREQ mode * mode 1 == Fast DREQ mode * mode 2 == Burst mode @@ -97,7 +97,7 @@ module_param(fifo_mode, ushort, 0644); /* * enable_suspend: When enabled, the driver will respond to * USB suspend requests by powering down the NET2272. Otherwise, - * USB suspend requests will be ignored. This is acceptible for + * USB suspend requests will be ignored. This is acceptable for * self-powered devices. For bus powered devices set this to 1. */ static ushort enable_suspend = 0; @@ -288,7 +288,7 @@ static void net2272_ep_reset(struct net2272_ep *ep) | (1 << LOCAL_OUT_ZLP) | (1 << BUFFER_FLUSH)); - /* fifo size is handled seperately */ + /* fifo size is handled separately */ } static int net2272_disable(struct usb_ep *_ep) diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 051d024b369e..d6a68631354a 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -932,19 +932,11 @@ static void start_dma(struct net2280_ep *ep, struct net2280_request *req) static inline void queue_dma(struct net2280_ep *ep, struct net2280_request *req, int valid) { - struct net2280_dma *end; - dma_addr_t tmp; - /* swap new dummy for old, link; fill and maybe activate */ - end = ep->dummy; - ep->dummy = req->td; - req->td = end; - - tmp = ep->td_dma; - ep->td_dma = req->td_dma; - req->td_dma = tmp; + swap(ep->dummy, req->td); + swap(ep->td_dma, req->td_dma); - end->dmadesc = cpu_to_le32 (ep->td_dma); + req->td->dmadesc = cpu_to_le32 (ep->td_dma); fill_dma_desc(ep, req, valid); } diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 5096d24915ce..61cabb9de6ae 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -1470,7 +1470,7 @@ static void ep0_irq(struct omap_udc *udc, u16 irq_src) if (!udc->ep0_in) { stat = 0; /* read next OUT packet of request, maybe - * reactiviting the fifo; stall on errors. + * reactivating the fifo; stall on errors. */ stat = read_fifo(ep0, req); if (!req || stat < 0) { @@ -2609,6 +2609,8 @@ static void omap_udc_release(struct device *dev) if (udc->dc_clk) { if (udc->clk_requested) omap_udc_enable_clock(0); + clk_unprepare(udc->hhc_clk); + clk_unprepare(udc->dc_clk); clk_put(udc->hhc_clk); clk_put(udc->dc_clk); } @@ -2773,8 +2775,8 @@ static int omap_udc_probe(struct platform_device *pdev) hhc_clk = clk_get(&pdev->dev, "usb_hhc_ck"); BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); /* can't use omap_udc_enable_clock yet */ - clk_enable(dc_clk); - clk_enable(hhc_clk); + clk_prepare_enable(dc_clk); + clk_prepare_enable(hhc_clk); udelay(100); } @@ -2783,8 +2785,8 @@ static int omap_udc_probe(struct platform_device *pdev) hhc_clk = clk_get(&pdev->dev, "l3_ocpi_ck"); BUG_ON(IS_ERR(dc_clk) || IS_ERR(hhc_clk)); /* can't use omap_udc_enable_clock yet */ - clk_enable(dc_clk); - clk_enable(hhc_clk); + clk_prepare_enable(dc_clk); + clk_prepare_enable(hhc_clk); udelay(100); } @@ -2932,8 +2934,8 @@ cleanup0: usb_put_phy(xceiv); if (cpu_is_omap16xx() || cpu_is_omap7xx()) { - clk_disable(hhc_clk); - clk_disable(dc_clk); + clk_disable_unprepare(hhc_clk); + clk_disable_unprepare(dc_clk); clk_put(hhc_clk); clk_put(dc_clk); } diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index 0a6bc18a1264..31bf79ce931c 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h @@ -326,7 +326,7 @@ struct udc_usb_ep { * @addr: usb endpoint number * @config: configuration in which this endpoint is active * @interface: interface in which this endpoint is active - * @alternate: altsetting in which this endpoitn is active + * @alternate: altsetting in which this endpoint is active * @fifo_size: max packet size in the endpoint fifo * @type: endpoint type (bulk, iso, int, ...) * @udccsr_value: save register of UDCCSR0 for suspend/resume diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index bf803e013458..4b7eb7701470 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -126,7 +126,7 @@ struct s3c_hsudc_req { /** * struct s3c_hsudc - Driver's abstraction of the device controller. * @gadget: Instance of usb_gadget which is referenced by gadget driver. - * @driver: Reference to currenty active gadget driver. + * @driver: Reference to currently active gadget driver. * @dev: The device reference used by probe function. * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed). * @regs: Remapped base address of controller's register space. @@ -633,7 +633,7 @@ static void s3c_hsudc_process_setup(struct s3c_hsudc *hsudc) } /** s3c_hsudc_handle_ep0_intr - Handle endpoint 0 interrupt. - * @hsudc: Device controller on which endpoint 0 interrupt has occured. + * @hsudc: Device controller on which endpoint 0 interrupt has occurred. * * Handle endpoint 0 interrupt when it occurs. EP0 interrupt could occur * when a stall handshake is sent to host or data is sent/received on diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index d9c406bdb680..6d31ccf6aee5 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -1434,7 +1434,7 @@ __tegra_xudc_ep_dequeue(struct tegra_xudc_ep *ep, return 0; } - /* Halt DMA for this endpiont. */ + /* Halt DMA for this endpoint. */ if (ep_ctx_read_state(ep->context) == EP_STATE_RUNNING) { ep_pause(xudc, ep->index); ep_wait_for_inactive(xudc, ep->index); @@ -3423,7 +3423,7 @@ static void tegra_xudc_device_params_init(struct tegra_xudc *xudc) } /* - * Compliacne suite appears to be violating polling LFPS tBurst max + * Compliance suite appears to be violating polling LFPS tBurst max * of 1.4us. Send 1.45us instead. */ val = xudc_readl(xudc, SSPX_CORE_CNT32); diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index 428c755cf2e1..4827e3cd3834 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -632,7 +632,7 @@ top: dev_dbg(udc->dev, "read %s, %d bytes%s req %p %d/%d\n", ep->ep_usb.name, count, is_short ? "/S" : "", req, req->usb_req.actual, req->usb_req.length); - bufferspace -= count; + /* Completion */ if ((req->usb_req.actual == req->usb_req.length) || is_short) { if (udc->dma_enabled && req->usb_req.length) |