diff options
Diffstat (limited to 'drivers/usb/gadget/function')
21 files changed, 277 insertions, 348 deletions
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 2fa1e80a3ce7..a30766ca4226 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -685,7 +685,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function, - acm_ss_function); + acm_ss_function, NULL); if (status) goto fail; @@ -777,10 +777,10 @@ static ssize_t f_acm_port_num_show(struct config_item *item, char *page) return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num); } -CONFIGFS_ATTR_RO(f_acm_port_, num); +CONFIGFS_ATTR_RO(f_acm_, port_num); static struct configfs_attribute *acm_attrs[] = { - &f_acm_port_attr_num, + &f_acm_attr_port_num, NULL, }; diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 7ad60ee41914..4c488d15b6f6 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -786,7 +786,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) fs_ecm_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function, - ecm_ss_function); + ecm_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index cad35a502d3f..d58bfc32be9e 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -309,7 +309,7 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function, - eem_ss_function); + eem_ss_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index cf43e9e18368..8cfce105c7ee 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -684,44 +684,38 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) { struct ffs_epfile *epfile = file->private_data; + struct usb_request *req; struct ffs_ep *ep; char *data = NULL; ssize_t ret, data_len = -EINVAL; int halt; /* Are we still active? */ - if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { - ret = -ENODEV; - goto error; - } + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) + return -ENODEV; /* Wait for endpoint to be enabled */ ep = epfile->ep; if (!ep) { - if (file->f_flags & O_NONBLOCK) { - ret = -EAGAIN; - goto error; - } + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); - if (ret) { - ret = -EINTR; - goto error; - } + if (ret) + return -EINTR; } /* Do we halt? */ halt = (!io_data->read == !epfile->in); - if (halt && epfile->isoc) { - ret = -EINVAL; - goto error; - } + if (halt && epfile->isoc) + return -EINVAL; /* Allocate & copy */ if (!halt) { /* * if we _do_ wait above, the epfile->ffs->gadget might be NULL - * before the waiting completes, so do not assign to 'gadget' earlier + * before the waiting completes, so do not assign to 'gadget' + * earlier */ struct usb_gadget *gadget = epfile->ffs->gadget; size_t copied; @@ -763,17 +757,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) if (epfile->ep != ep) { /* In the meantime, endpoint got disabled or changed. */ ret = -ESHUTDOWN; - spin_unlock_irq(&epfile->ffs->eps_lock); } else if (halt) { /* Halt */ if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep)) usb_ep_set_halt(ep->ep); - spin_unlock_irq(&epfile->ffs->eps_lock); ret = -EBADMSG; - } else { - /* Fire the request */ - struct usb_request *req; - + } else if (unlikely(data_len == -EINVAL)) { /* * Sanity Check: even though data_len can't be used * uninitialized at the time I write this comment, some @@ -785,80 +774,80 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * For such reason, we're adding this redundant sanity check * here. */ - if (unlikely(data_len == -EINVAL)) { - WARN(1, "%s: data_len == -EINVAL\n", __func__); - ret = -EINVAL; - goto error_lock; - } - - if (io_data->aio) { - req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); - if (unlikely(!req)) - goto error_lock; - - req->buf = data; - req->length = data_len; + WARN(1, "%s: data_len == -EINVAL\n", __func__); + ret = -EINVAL; + } else if (!io_data->aio) { + DECLARE_COMPLETION_ONSTACK(done); + bool interrupted = false; - io_data->buf = data; - io_data->ep = ep->ep; - io_data->req = req; - io_data->ffs = epfile->ffs; + req = ep->req; + req->buf = data; + req->length = data_len; - req->context = io_data; - req->complete = ffs_epfile_async_io_complete; + req->context = &done; + req->complete = ffs_epfile_io_complete; - ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); - if (unlikely(ret)) { - usb_ep_free_request(ep->ep, req); - goto error_lock; - } - ret = -EIOCBQUEUED; + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + if (unlikely(ret < 0)) + goto error_lock; - spin_unlock_irq(&epfile->ffs->eps_lock); - } else { - DECLARE_COMPLETION_ONSTACK(done); + spin_unlock_irq(&epfile->ffs->eps_lock); - req = ep->req; - req->buf = data; - req->length = data_len; + if (unlikely(wait_for_completion_interruptible(&done))) { + /* + * To avoid race condition with ffs_epfile_io_complete, + * dequeue the request first then check + * status. usb_ep_dequeue API should guarantee no race + * condition with req->complete callback. + */ + usb_ep_dequeue(ep->ep, req); + interrupted = ep->status < 0; + } - req->context = &done; - req->complete = ffs_epfile_io_complete; + /* + * XXX We may end up silently droping data here. Since data_len + * (i.e. req->length) may be bigger than len (after being + * rounded up to maxpacketsize), we may end up with more data + * then user space has space for. + */ + ret = interrupted ? -EINTR : ep->status; + if (io_data->read && ret > 0) { + ret = copy_to_iter(data, ret, &io_data->data); + if (!ret) + ret = -EFAULT; + } + goto error_mutex; + } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_KERNEL))) { + ret = -ENOMEM; + } else { + req->buf = data; + req->length = data_len; - ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + io_data->buf = data; + io_data->ep = ep->ep; + io_data->req = req; + io_data->ffs = epfile->ffs; - spin_unlock_irq(&epfile->ffs->eps_lock); + req->context = io_data; + req->complete = ffs_epfile_async_io_complete; - if (unlikely(ret < 0)) { - /* nop */ - } else if (unlikely( - wait_for_completion_interruptible(&done))) { - ret = -EINTR; - usb_ep_dequeue(ep->ep, req); - } else { - /* - * XXX We may end up silently droping data - * here. Since data_len (i.e. req->length) may - * be bigger than len (after being rounded up - * to maxpacketsize), we may end up with more - * data then user space has space for. - */ - ret = ep->status; - if (io_data->read && ret > 0) { - ret = copy_to_iter(data, ret, &io_data->data); - if (!ret) - ret = -EFAULT; - } - } - kfree(data); + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + if (unlikely(ret)) { + usb_ep_free_request(ep->ep, req); + goto error_lock; } - } - mutex_unlock(&epfile->mutex); - return ret; + ret = -EIOCBQUEUED; + /* + * Do not kfree the buffer in this function. It will be freed + * by ffs_user_copy_worker. + */ + data = NULL; + } error_lock: spin_unlock_irq(&epfile->ffs->eps_lock); +error_mutex: mutex_unlock(&epfile->mutex); error: kfree(data); diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 99285b416308..51980c50546d 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -646,7 +646,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) hidg_fs_out_ep_desc.bEndpointAddress; status = usb_assign_descriptors(f, hidg_fs_descriptors, - hidg_hs_descriptors, NULL); + hidg_hs_descriptors, NULL, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index ddc3aad886b7..3a9f8f9c77bd 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -211,7 +211,7 @@ autoconf_fail: ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs, - ss_loopback_descs); + ss_loopback_descs, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 223ccf89d226..acf210f16328 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -3093,7 +3093,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function, - fsg_ss_function); + fsg_ss_function, fsg_ss_function); if (ret) goto autoconf_fail; @@ -3484,12 +3484,12 @@ static struct usb_function_instance *fsg_alloc_inst(void) opts->lun0.lun = opts->common->luns[0]; opts->lun0.lun_id = 0; - config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); - opts->default_groups[0] = &opts->lun0.group; - opts->func_inst.group.default_groups = opts->default_groups; config_group_init_type_name(&opts->func_inst.group, "", &fsg_func_type); + config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); + configfs_add_default_group(&opts->lun0.group, &opts->func_inst.group); + return &opts->func_inst; release_buffers: diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index fb1fe96d3215..84c0ee5ebd1e 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -56,7 +56,7 @@ static const char f_midi_longname[] = "MIDI Gadget"; * USB <- IN endpoint <- rawmidi */ struct gmidi_in_port { - struct f_midi *midi; + struct snd_rawmidi_substream *substream; int active; uint8_t cable; uint8_t state; @@ -78,9 +78,7 @@ struct f_midi { struct snd_rawmidi *rmidi; u8 ms_id; - struct snd_rawmidi_substream *in_substream[MAX_PORTS]; struct snd_rawmidi_substream *out_substream[MAX_PORTS]; - struct gmidi_in_port *in_port[MAX_PORTS]; unsigned long out_triggered; struct tasklet_struct tasklet; @@ -92,6 +90,8 @@ struct f_midi { /* This fifo is used as a buffer ring for pre-allocated IN usb_requests */ DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *); unsigned int in_last_port; + + struct gmidi_in_port in_ports_array[/* in_ports */]; }; static inline struct f_midi *func_to_midi(struct usb_function *f) @@ -518,98 +518,95 @@ static void f_midi_drop_out_substreams(struct f_midi *midi) { unsigned int i; - for (i = 0; i < MAX_PORTS; i++) { - struct gmidi_in_port *port = midi->in_port[i]; - struct snd_rawmidi_substream *substream = midi->in_substream[i]; - - if (!port) - break; - - if (!port->active || !substream) - continue; - - snd_rawmidi_drop_output(substream); + for (i = 0; i < midi->in_ports; i++) { + struct gmidi_in_port *port = midi->in_ports_array + i; + struct snd_rawmidi_substream *substream = port->substream; + if (port->active && substream) + snd_rawmidi_drop_output(substream); } } -static void f_midi_transmit(struct f_midi *midi) +static int f_midi_do_transmit(struct f_midi *midi, struct usb_ep *ep) { - struct usb_ep *ep = midi->in_ep; - bool active; - - /* We only care about USB requests if IN endpoint is enabled */ - if (!ep || !ep->enabled) - goto drop_out; + struct usb_request *req = NULL; + unsigned int len, i; + bool active = false; + int err; - do { - struct usb_request *req = NULL; - unsigned int len, i; + /* + * We peek the request in order to reuse it if it fails to enqueue on + * its endpoint + */ + len = kfifo_peek(&midi->in_req_fifo, &req); + if (len != 1) { + ERROR(midi, "%s: Couldn't get usb request\n", __func__); + return -1; + } - active = false; + /* + * If buffer overrun, then we ignore this transmission. + * IMPORTANT: This will cause the user-space rawmidi device to block + * until a) usb requests have been completed or b) snd_rawmidi_write() + * times out. + */ + if (req->length > 0) + return 0; - /* We peek the request in order to reuse it if it fails - * to enqueue on its endpoint */ - len = kfifo_peek(&midi->in_req_fifo, &req); - if (len != 1) { - ERROR(midi, "%s: Couldn't get usb request\n", __func__); - goto drop_out; - } + for (i = midi->in_last_port; i < midi->in_ports; ++i) { + struct gmidi_in_port *port = midi->in_ports_array + i; + struct snd_rawmidi_substream *substream = port->substream; - /* If buffer overrun, then we ignore this transmission. - * IMPORTANT: This will cause the user-space rawmidi device to block until a) usb - * requests have been completed or b) snd_rawmidi_write() times out. */ - if (req->length > 0) - return; + if (!port->active || !substream) + continue; - for (i = midi->in_last_port; i < MAX_PORTS; i++) { - struct gmidi_in_port *port = midi->in_port[i]; - struct snd_rawmidi_substream *substream = midi->in_substream[i]; + while (req->length + 3 < midi->buflen) { + uint8_t b; - if (!port) { - /* Reset counter when we reach the last available port */ - midi->in_last_port = 0; + if (snd_rawmidi_transmit(substream, &b, 1) != 1) { + port->active = 0; break; } + f_midi_transmit_byte(req, port, b); + } - if (!port->active || !substream) - continue; + active = !!port->active; + if (active) + break; + } + midi->in_last_port = active ? i : 0; - while (req->length + 3 < midi->buflen) { - uint8_t b; + if (req->length <= 0) + goto done; - if (snd_rawmidi_transmit(substream, &b, 1) != 1) { - port->active = 0; - break; - } - f_midi_transmit_byte(req, port, b); - } + err = usb_ep_queue(ep, req, GFP_ATOMIC); + if (err < 0) { + ERROR(midi, "%s failed to queue req: %d\n", + midi->in_ep->name, err); + req->length = 0; /* Re-use request next time. */ + } else { + /* Upon success, put request at the back of the queue. */ + kfifo_skip(&midi->in_req_fifo); + kfifo_put(&midi->in_req_fifo, req); + } - active = !!port->active; - /* Check if last port is still active, which means that - * there is still data on that substream but this current - * request run out of space. */ - if (active) { - midi->in_last_port = i; - /* There is no need to re-iterate though midi ports. */ - break; - } - } +done: + return active; +} - if (req->length > 0) { - int err; +static void f_midi_transmit(struct f_midi *midi) +{ + struct usb_ep *ep = midi->in_ep; + int ret; - err = usb_ep_queue(ep, req, GFP_ATOMIC); - if (err < 0) { - ERROR(midi, "%s failed to queue req: %d\n", - midi->in_ep->name, err); - req->length = 0; /* Re-use request next time. */ - } else { - /* Upon success, put request at the back of the queue. */ - kfifo_skip(&midi->in_req_fifo); - kfifo_put(&midi->in_req_fifo, req); - } - } - } while (active); + /* We only care about USB requests if IN endpoint is enabled */ + if (!ep || !ep->enabled) + goto drop_out; + + do { + ret = f_midi_do_transmit(midi, ep); + if (ret < 0) + goto drop_out; + } while (ret); return; @@ -626,13 +623,15 @@ static void f_midi_in_tasklet(unsigned long data) static int f_midi_in_open(struct snd_rawmidi_substream *substream) { struct f_midi *midi = substream->rmidi->private_data; + struct gmidi_in_port *port; - if (!midi->in_port[substream->number]) + if (substream->number >= midi->in_ports) return -EINVAL; VDBG(midi, "%s()\n", __func__); - midi->in_substream[substream->number] = substream; - midi->in_port[substream->number]->state = STATE_UNKNOWN; + port = midi->in_ports_array + substream->number; + port->substream = substream; + port->state = STATE_UNKNOWN; return 0; } @@ -648,11 +647,11 @@ static void f_midi_in_trigger(struct snd_rawmidi_substream *substream, int up) { struct f_midi *midi = substream->rmidi->private_data; - if (!midi->in_port[substream->number]) + if (substream->number >= midi->in_ports) return; VDBG(midi, "%s() %d\n", __func__, up); - midi->in_port[substream->number]->active = up; + midi->in_ports_array[substream->number].active = up; if (up) tasklet_hi_schedule(&midi->tasklet); } @@ -1128,14 +1127,11 @@ static void f_midi_free(struct usb_function *f) { struct f_midi *midi; struct f_midi_opts *opts; - int i; midi = func_to_midi(f); opts = container_of(f->fi, struct f_midi_opts, func_inst); kfree(midi->id); mutex_lock(&opts->lock); - for (i = opts->in_ports - 1; i >= 0; --i) - kfree(midi->in_port[i]); kfifo_free(&midi->in_req_fifo); kfree(midi); --opts->refcnt; @@ -1163,7 +1159,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) { - struct f_midi *midi; + struct f_midi *midi = NULL; struct f_midi_opts *opts; int status, i; @@ -1172,37 +1168,26 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) mutex_lock(&opts->lock); /* sanity check */ if (opts->in_ports > MAX_PORTS || opts->out_ports > MAX_PORTS) { - mutex_unlock(&opts->lock); - return ERR_PTR(-EINVAL); + status = -EINVAL; + goto setup_fail; } /* allocate and initialize one new instance */ - midi = kzalloc(sizeof(*midi), GFP_KERNEL); + midi = kzalloc( + sizeof(*midi) + opts->in_ports * sizeof(*midi->in_ports_array), + GFP_KERNEL); if (!midi) { - mutex_unlock(&opts->lock); - return ERR_PTR(-ENOMEM); + status = -ENOMEM; + goto setup_fail; } - for (i = 0; i < opts->in_ports; i++) { - struct gmidi_in_port *port = kzalloc(sizeof(*port), GFP_KERNEL); - - if (!port) { - status = -ENOMEM; - mutex_unlock(&opts->lock); - goto setup_fail; - } - - port->midi = midi; - port->active = 0; - port->cable = i; - midi->in_port[i] = port; - } + for (i = 0; i < opts->in_ports; i++) + midi->in_ports_array[i].cable = i; /* set up ALSA midi devices */ midi->id = kstrdup(opts->id, GFP_KERNEL); if (opts->id && !midi->id) { status = -ENOMEM; - mutex_unlock(&opts->lock); goto setup_fail; } midi->in_ports = opts->in_ports; @@ -1229,8 +1214,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) return &midi->func; setup_fail: - for (--i; i >= 0; i--) - kfree(midi->in_port[i]); + mutex_unlock(&opts->lock); kfree(midi); return ERR_PTR(status); } diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 7ad798ace1e5..97f0a9bc84df 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -1432,7 +1432,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) fs_ncm_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function, - NULL); + NULL, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index d6396e0909ee..d43e86cea74f 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -364,7 +364,8 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) obex_hs_ep_out_desc.bEndpointAddress = obex_fs_ep_out_desc.bEndpointAddress; - status = usb_assign_descriptors(f, fs_function, hs_function, NULL); + status = usb_assign_descriptors(f, fs_function, hs_function, NULL, + NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 157441dbfeba..0473d619d5bf 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -541,7 +541,7 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) /* Do not try to bind Phonet twice... */ status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function, - NULL); + NULL, NULL); if (status) goto err; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 26ccad5d8680..c45104e3a64b 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -1051,7 +1051,7 @@ autoconf_fail: ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_printer_function, - hs_printer_function, ss_printer_function); + hs_printer_function, ss_printer_function, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index e587767e374c..c8005823b190 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -783,7 +783,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress; status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function, - eth_ss_function); + eth_ss_function, NULL); if (status) goto fail; @@ -889,7 +889,6 @@ static void rndis_free_inst(struct usb_function_instance *f) free_netdev(opts->net); } - kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */ kfree(opts); } @@ -916,10 +915,10 @@ static struct usb_function_instance *rndis_alloc_inst(void) descs[0] = &opts->rndis_os_desc; names[0] = "rndis"; - usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, - names, THIS_MODULE); config_group_init_type_name(&opts->func_inst.group, "", &rndis_func_type); + usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, + names, THIS_MODULE); return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 6bb44d613bab..cb00ada21d9c 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -236,7 +236,7 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f) gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function, - gser_ss_function); + gser_ss_function, NULL); if (status) goto fail; dev_dbg(&cdev->gadget->dev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 242ba5caffe5..df0189ddfdd5 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -437,7 +437,7 @@ no_iso: ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_source_sink_descs, - hs_source_sink_descs, ss_source_sink_descs); + hs_source_sink_descs, ss_source_sink_descs, NULL); if (ret) return ret; diff --git a/drivers/usb/gadget/function/f_subset.c b/drivers/usb/gadget/function/f_subset.c index 829c78de9eba..434b983f3b4c 100644 --- a/drivers/usb/gadget/function/f_subset.c +++ b/drivers/usb/gadget/function/f_subset.c @@ -362,7 +362,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) fs_subset_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function, - ss_eth_function); + ss_eth_function, NULL); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index bad007b5a190..dfb733047a4c 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -2098,7 +2098,7 @@ static int tcm_bind(struct usb_configuration *c, struct usb_function *f) uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; ret = usb_assign_descriptors(f, uasp_fs_function_desc, - uasp_hs_function_desc, uasp_ss_function_desc); + uasp_hs_function_desc, uasp_ss_function_desc, NULL); if (ret) goto ep_fail; diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 6a2346b99f55..f2ac0cbc29a4 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -721,7 +721,8 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) status = -ENOMEM; /* copy descriptors, and track endpoint copies */ - status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL); + status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL, + NULL); if (status) goto fail; return 0; diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 044ca79d3cb5..186d4b162524 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -1100,7 +1100,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); + ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL, + NULL); if (ret) goto err; diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 70d3917cc003..943c21aafd3b 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -914,7 +914,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED; params->resp_avail = resp_avail; params->v = v; - INIT_LIST_HEAD(&(params->resp_queue)); + INIT_LIST_HEAD(¶ms->resp_queue); pr_debug("%s: configNr = %d\n", __func__, i); return params; @@ -1006,13 +1006,10 @@ EXPORT_SYMBOL_GPL(rndis_add_hdr); void rndis_free_response(struct rndis_params *params, u8 *buf) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); - if (r && r->buf == buf) { + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { + if (r->buf == buf) { list_del(&r->list); kfree(r); } @@ -1022,14 +1019,11 @@ EXPORT_SYMBOL_GPL(rndis_free_response); u8 *rndis_get_next_response(struct rndis_params *params, u32 *length) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; if (!length) return NULL; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (!r->send) { r->send = 1; *length = r->length; @@ -1053,7 +1047,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length) r->length = length; r->send = 0; - list_add_tail(&r->list, &(params->resp_queue)); + list_add_tail(&r->list, ¶ms->resp_queue); return r; } diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index ad8c9b05572d..66753ba7a42e 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -272,11 +272,6 @@ static struct config_item_type uvcg_default_processing_type = { /* struct uvcg_processing {}; */ -static struct config_group *uvcg_processing_default_groups[] = { - &uvcg_default_processing.group, - NULL, -}; - /* control/processing */ static struct uvcg_processing_grp { struct config_group group; @@ -394,11 +389,6 @@ static struct config_item_type uvcg_default_camera_type = { /* struct uvcg_camera {}; */ -static struct config_group *uvcg_camera_default_groups[] = { - &uvcg_default_camera.group, - NULL, -}; - /* control/terminal/camera */ static struct uvcg_camera_grp { struct config_group group; @@ -477,11 +467,6 @@ static struct config_item_type uvcg_default_output_type = { /* struct uvcg_output {}; */ -static struct config_group *uvcg_output_default_groups[] = { - &uvcg_default_output.group, - NULL, -}; - /* control/terminal/output */ static struct uvcg_output_grp { struct config_group group; @@ -491,12 +476,6 @@ static struct config_item_type uvcg_output_grp_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_terminal_default_groups[] = { - &uvcg_camera_grp.group, - &uvcg_output_grp.group, - NULL, -}; - /* control/terminal */ static struct uvcg_terminal_grp { struct config_group group; @@ -619,12 +598,6 @@ static struct config_item_type uvcg_control_class_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_control_class_default_groups[] = { - &uvcg_control_class_fs.group, - &uvcg_control_class_ss.group, - NULL, -}; - /* control/class */ static struct uvcg_control_class_grp { struct config_group group; @@ -634,14 +607,6 @@ static struct config_item_type uvcg_control_class_grp_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_control_default_groups[] = { - &uvcg_control_header_grp.group, - &uvcg_processing_grp.group, - &uvcg_terminal_grp.group, - &uvcg_control_class_grp.group, - NULL, -}; - /* control */ static struct uvcg_control_grp { struct config_group group; @@ -1780,11 +1745,6 @@ static struct config_item_type uvcg_default_color_matching_type = { /* struct uvcg_color_matching {}; */ -static struct config_group *uvcg_color_matching_default_groups[] = { - &uvcg_default_color_matching.group, - NULL, -}; - /* streaming/color_matching */ static struct uvcg_color_matching_grp { struct config_group group; @@ -2145,13 +2105,6 @@ static struct config_item_type uvcg_streaming_class_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_streaming_class_default_groups[] = { - &uvcg_streaming_class_fs.group, - &uvcg_streaming_class_hs.group, - &uvcg_streaming_class_ss.group, - NULL, -}; - /* streaming/class */ static struct uvcg_streaming_class_grp { struct config_group group; @@ -2161,15 +2114,6 @@ static struct config_item_type uvcg_streaming_class_grp_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_streaming_default_groups[] = { - &uvcg_streaming_header_grp.group, - &uvcg_uncompressed_grp.group, - &uvcg_mjpeg_grp.group, - &uvcg_color_matching_grp.group, - &uvcg_streaming_class_grp.group, - NULL, -}; - /* streaming */ static struct uvcg_streaming_grp { struct config_group group; @@ -2179,12 +2123,6 @@ static struct config_item_type uvcg_streaming_grp_type = { .ct_owner = THIS_MODULE, }; -static struct config_group *uvcg_default_groups[] = { - &uvcg_control_grp.group, - &uvcg_streaming_grp.group, - NULL, -}; - 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, @@ -2273,59 +2211,64 @@ static struct config_item_type uvc_func_type = { .ct_owner = THIS_MODULE, }; -static inline void uvcg_init_group(struct config_group *g, - struct config_group **default_groups, - const char *name, - struct config_item_type *type) -{ - g->default_groups = default_groups; - config_group_init_type_name(g, name, type); -} - int uvcg_attach_configfs(struct f_uvc_opts *opts) { config_group_init_type_name(&uvcg_control_header_grp.group, "header", &uvcg_control_header_grp_type); + config_group_init_type_name(&uvcg_default_processing.group, - "default", - &uvcg_default_processing_type); - uvcg_init_group(&uvcg_processing_grp.group, - uvcg_processing_default_groups, - "processing", - &uvcg_processing_grp_type); + "default", &uvcg_default_processing_type); + config_group_init_type_name(&uvcg_processing_grp.group, + "processing", &uvcg_processing_grp_type); + configfs_add_default_group(&uvcg_default_processing.group, + &uvcg_processing_grp.group); + config_group_init_type_name(&uvcg_default_camera.group, - "default", - &uvcg_default_camera_type); - uvcg_init_group(&uvcg_camera_grp.group, - uvcg_camera_default_groups, - "camera", - &uvcg_camera_grp_type); + "default", &uvcg_default_camera_type); + config_group_init_type_name(&uvcg_camera_grp.group, + "camera", &uvcg_camera_grp_type); + configfs_add_default_group(&uvcg_default_camera.group, + &uvcg_camera_grp.group); + config_group_init_type_name(&uvcg_default_output.group, - "default", - &uvcg_default_output_type); - uvcg_init_group(&uvcg_output_grp.group, - uvcg_output_default_groups, - "output", - &uvcg_output_grp_type); - uvcg_init_group(&uvcg_terminal_grp.group, - uvcg_terminal_default_groups, - "terminal", - &uvcg_terminal_grp_type); + "default", &uvcg_default_output_type); + config_group_init_type_name(&uvcg_output_grp.group, + "output", &uvcg_output_grp_type); + configfs_add_default_group(&uvcg_default_output.group, + &uvcg_output_grp.group); + + config_group_init_type_name(&uvcg_terminal_grp.group, + "terminal", &uvcg_terminal_grp_type); + configfs_add_default_group(&uvcg_camera_grp.group, + &uvcg_terminal_grp.group); + configfs_add_default_group(&uvcg_output_grp.group, + &uvcg_terminal_grp.group); + config_group_init_type_name(&uvcg_control_class_fs.group, - "fs", - &uvcg_control_class_type); + "fs", &uvcg_control_class_type); config_group_init_type_name(&uvcg_control_class_ss.group, - "ss", - &uvcg_control_class_type); - uvcg_init_group(&uvcg_control_class_grp.group, - uvcg_control_class_default_groups, + "ss", &uvcg_control_class_type); + config_group_init_type_name(&uvcg_control_class_grp.group, "class", &uvcg_control_class_grp_type); - uvcg_init_group(&uvcg_control_grp.group, - uvcg_control_default_groups, + configfs_add_default_group(&uvcg_control_class_fs.group, + &uvcg_control_class_grp.group); + configfs_add_default_group(&uvcg_control_class_ss.group, + &uvcg_control_class_grp.group); + + config_group_init_type_name(&uvcg_control_grp.group, "control", &uvcg_control_grp_type); + configfs_add_default_group(&uvcg_control_header_grp.group, + &uvcg_control_grp.group); + configfs_add_default_group(&uvcg_processing_grp.group, + &uvcg_control_grp.group); + configfs_add_default_group(&uvcg_terminal_grp.group, + &uvcg_control_grp.group); + configfs_add_default_group(&uvcg_control_class_grp.group, + &uvcg_control_grp.group); + config_group_init_type_name(&uvcg_streaming_header_grp.group, "header", &uvcg_streaming_header_grp_type); @@ -2338,30 +2281,47 @@ int uvcg_attach_configfs(struct f_uvc_opts *opts) config_group_init_type_name(&uvcg_default_color_matching.group, "default", &uvcg_default_color_matching_type); - uvcg_init_group(&uvcg_color_matching_grp.group, - uvcg_color_matching_default_groups, + config_group_init_type_name(&uvcg_color_matching_grp.group, "color_matching", &uvcg_color_matching_grp_type); + configfs_add_default_group(&uvcg_default_color_matching.group, + &uvcg_color_matching_grp.group); + config_group_init_type_name(&uvcg_streaming_class_fs.group, - "fs", - &uvcg_streaming_class_type); + "fs", &uvcg_streaming_class_type); config_group_init_type_name(&uvcg_streaming_class_hs.group, - "hs", - &uvcg_streaming_class_type); + "hs", &uvcg_streaming_class_type); config_group_init_type_name(&uvcg_streaming_class_ss.group, - "ss", - &uvcg_streaming_class_type); - uvcg_init_group(&uvcg_streaming_class_grp.group, - uvcg_streaming_class_default_groups, - "class", - &uvcg_streaming_class_grp_type); - uvcg_init_group(&uvcg_streaming_grp.group, - uvcg_streaming_default_groups, - "streaming", - &uvcg_streaming_grp_type); - uvcg_init_group(&opts->func_inst.group, - uvcg_default_groups, + "ss", &uvcg_streaming_class_type); + config_group_init_type_name(&uvcg_streaming_class_grp.group, + "class", &uvcg_streaming_class_grp_type); + configfs_add_default_group(&uvcg_streaming_class_fs.group, + &uvcg_streaming_class_grp.group); + configfs_add_default_group(&uvcg_streaming_class_hs.group, + &uvcg_streaming_class_grp.group); + configfs_add_default_group(&uvcg_streaming_class_ss.group, + &uvcg_streaming_class_grp.group); + + config_group_init_type_name(&uvcg_streaming_grp.group, + "streaming", &uvcg_streaming_grp_type); + configfs_add_default_group(&uvcg_streaming_header_grp.group, + &uvcg_streaming_grp.group); + configfs_add_default_group(&uvcg_uncompressed_grp.group, + &uvcg_streaming_grp.group); + configfs_add_default_group(&uvcg_mjpeg_grp.group, + &uvcg_streaming_grp.group); + configfs_add_default_group(&uvcg_color_matching_grp.group, + &uvcg_streaming_grp.group); + configfs_add_default_group(&uvcg_streaming_class_grp.group, + &uvcg_streaming_grp.group); + + config_group_init_type_name(&opts->func_inst.group, "", &uvc_func_type); + configfs_add_default_group(&uvcg_control_grp.group, + &opts->func_inst.group); + configfs_add_default_group(&uvcg_streaming_grp.group, + &opts->func_inst.group); + return 0; } |