Loading drivers/usb/gadget/function/f_fs.c +99 −18 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ struct ffs_epfile { /* Protects ep->ep and ep->req. */ struct mutex mutex; wait_queue_head_t wait; atomic_t error; struct ffs_data *ffs; struct ffs_ep *ep; /* P: ffs->eps_lock */ Loading Loading @@ -538,6 +539,10 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) if (unlikely(ffs->state == FFS_CLOSING)) return -EBUSY; smp_mb__before_atomic(); if (atomic_read(&ffs->opened)) return -EBUSY; file->private_data = ffs; ffs_data_opened(ffs); Loading Loading @@ -630,8 +635,12 @@ static const struct file_operations ffs_ep0_operations = { static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) { struct ffs_ep *ep = _ep->driver_data; ENTER(); if (likely(req->context)) { /* req may be freed during unbind */ if (ep && ep->req && likely(req->context)) { struct ffs_ep *ep = _ep->driver_data; ep->status = req->status ? req->status : req->actual; /* Set is_busy false to indicate completion of last request */ Loading Loading @@ -705,6 +714,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ssize_t ret, data_len = -EINVAL; int halt; pr_debug("%s: len %zu, read %d\n", __func__, io_data->len, io_data->read); if (atomic_read(&epfile->error)) return -ENODEV; /* Are we still active? */ if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { ret = -ENODEV; Loading @@ -719,9 +734,24 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) goto error; } ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); if (ret) { ret = -EINTR; /* Don't wait on write if device is offline */ if (!io_data->read) { ret = -ENODEV; goto error; } /* * if ep is disabled, this fails all current IOs * and wait for next epfile open to happen */ if (!atomic_read(&epfile->error)) { ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); if (ret < 0) goto error; } if (!ep) { ret = -ENODEV; goto error; } } Loading Loading @@ -843,16 +873,26 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) spin_unlock_irq(&epfile->ffs->eps_lock); } else { DECLARE_COMPLETION_ONSTACK(done); struct completion *done; req = ep->req; req->buf = data; req->length = data_len; req->context = &done; req->complete = ffs_epfile_io_complete; ret = 0; if (io_data->read) { reinit_completion( &epfile->ffs->epout_completion); done = &epfile->ffs->epout_completion; req->context = done; } else { reinit_completion( &epfile->ffs->epin_completion); done = &epfile->ffs->epin_completion; req->context = done; } /* Don't queue another read if previous is still busy */ if (!(io_data->read && ep->is_busy)) { ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); Loading @@ -862,11 +902,19 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) spin_unlock_irq(&epfile->ffs->eps_lock); if (unlikely(ret < 0)) { /* nop */ ret = -EIO; } else if (unlikely( wait_for_completion_interruptible(&done))) { ret = -EINTR; wait_for_completion_interruptible(done))) { spin_lock_irq(&epfile->ffs->eps_lock); /* * While we were acquiring lock endpoint got * disabled (disconnect) or changed * (composition switch) */ if (epfile->ep == ep) usb_ep_dequeue(ep->ep, req); spin_unlock_irq(&epfile->ffs->eps_lock); ret = -EINTR; } else { /* * XXX We may end up silently droping data Loading @@ -875,7 +923,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * to maxpacketsize), we may end up with more * data then user space has space for. */ spin_lock_irq(&epfile->ffs->eps_lock); /* * While we were acquiring lock endpoint got * disabled (disconnect) or changed * (composition switch) */ if (epfile->ep == ep) ret = ep->status; else ret = -ENODEV; spin_unlock_irq(&epfile->ffs->eps_lock); if (io_data->read && ret > 0) { if (io_data->len != MAX_BUF_LEN && ret < io_data->len) Loading Loading @@ -955,6 +1014,7 @@ ffs_epfile_open(struct inode *inode, struct file *file) file->private_data = epfile; ffs_data_opened(epfile->ffs); atomic_set(&epfile->error, 0); return 0; } Loading Loading @@ -1049,7 +1109,9 @@ ffs_epfile_release(struct inode *inode, struct file *file) ENTER(); atomic_set(&epfile->error, 1); ffs_data_closed(epfile->ffs); file->private_data = NULL; return 0; } Loading Loading @@ -1487,6 +1549,8 @@ static struct ffs_data *ffs_data_new(void) spin_lock_init(&ffs->eps_lock); init_waitqueue_head(&ffs->ev.waitq); init_completion(&ffs->ep0req_completion); init_completion(&ffs->epout_completion); init_completion(&ffs->epin_completion); /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; Loading @@ -1498,9 +1562,16 @@ static void ffs_data_clear(struct ffs_data *ffs) { ENTER(); pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__, ffs->gadget, ffs->flags); if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags)) ffs_closed(ffs); /* Dump ffs->gadget and ffs->flags */ if (ffs->gadget) pr_err("%s: ffs:%p ffs->gadget= %p, ffs->flags= %lu\n", __func__, ffs, ffs->gadget, ffs->flags); BUG_ON(ffs->gadget); if (ffs->epfiles) Loading Loading @@ -1543,7 +1614,6 @@ static void ffs_data_reset(struct ffs_data *ffs) static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) { struct usb_gadget_strings **lang; int first_id; ENTER(); Loading @@ -1551,9 +1621,14 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) return -EBADFD; first_id = usb_string_ids_n(cdev, ffs->strings_count); if (!ffs->first_id || ffs->old_strings_count < ffs->strings_count) { int first_id = usb_string_ids_n(cdev, ffs->strings_count); if (unlikely(first_id < 0)) return first_id; ffs->first_id = first_id; ffs->old_strings_count = ffs->strings_count; } ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); if (unlikely(!ffs->ep0req)) Loading @@ -1565,7 +1640,7 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) if (lang) { for (; *lang; ++lang) { struct usb_string *str = (*lang)->strings; int id = first_id; int id = ffs->first_id; for (; str->s; ++id, ++str) str->id = id; } Loading Loading @@ -1652,9 +1727,12 @@ static void ffs_func_eps_disable(struct ffs_function *func) spin_lock_irqsave(&func->ffs->eps_lock, flags); do { atomic_set(&epfile->error, 1); /* pending requests get nuked */ if (likely(ep->ep)) if (likely(ep->ep)) { usb_ep_disable(ep->ep); ep->ep->driver_data = NULL; } epfile->ep = NULL; ++ep; Loading Loading @@ -2935,8 +3013,10 @@ static int ffs_func_set_alt(struct usb_function *f, return intf; } if (ffs->func) if (ffs->func) { ffs_func_eps_disable(ffs->func); ffs->func = NULL; } if (ffs->state != FFS_ACTIVE) return -ENODEV; Loading Loading @@ -3231,6 +3311,7 @@ static void ffs_func_unbind(struct usb_configuration *c, if (ep->ep && ep->req) usb_ep_free_request(ep->ep, ep->req); ep->req = NULL; ep->ep = NULL; ++ep; } while (--count); spin_unlock_irqrestore(&func->ffs->eps_lock, flags); Loading drivers/usb/gadget/function/u_fs.h +5 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,8 @@ struct ffs_data { */ struct usb_request *ep0req; /* P: mutex */ struct completion ep0req_completion; /* P: mutex */ struct completion epin_completion; struct completion epout_completion; /* reference counter */ atomic_t ref; Loading Loading @@ -233,6 +235,9 @@ struct ffs_data { unsigned short eps_count; unsigned short _pad1; int first_id; int old_strings_count; /* filled by __ffs_data_got_strings() */ /* ids in stringtabs are set in functionfs_bind() */ const void *raw_strings; Loading Loading
drivers/usb/gadget/function/f_fs.c +99 −18 Original line number Diff line number Diff line Loading @@ -123,6 +123,7 @@ struct ffs_epfile { /* Protects ep->ep and ep->req. */ struct mutex mutex; wait_queue_head_t wait; atomic_t error; struct ffs_data *ffs; struct ffs_ep *ep; /* P: ffs->eps_lock */ Loading Loading @@ -538,6 +539,10 @@ static int ffs_ep0_open(struct inode *inode, struct file *file) if (unlikely(ffs->state == FFS_CLOSING)) return -EBUSY; smp_mb__before_atomic(); if (atomic_read(&ffs->opened)) return -EBUSY; file->private_data = ffs; ffs_data_opened(ffs); Loading Loading @@ -630,8 +635,12 @@ static const struct file_operations ffs_ep0_operations = { static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) { struct ffs_ep *ep = _ep->driver_data; ENTER(); if (likely(req->context)) { /* req may be freed during unbind */ if (ep && ep->req && likely(req->context)) { struct ffs_ep *ep = _ep->driver_data; ep->status = req->status ? req->status : req->actual; /* Set is_busy false to indicate completion of last request */ Loading Loading @@ -705,6 +714,12 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ssize_t ret, data_len = -EINVAL; int halt; pr_debug("%s: len %zu, read %d\n", __func__, io_data->len, io_data->read); if (atomic_read(&epfile->error)) return -ENODEV; /* Are we still active? */ if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { ret = -ENODEV; Loading @@ -719,9 +734,24 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) goto error; } ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); if (ret) { ret = -EINTR; /* Don't wait on write if device is offline */ if (!io_data->read) { ret = -ENODEV; goto error; } /* * if ep is disabled, this fails all current IOs * and wait for next epfile open to happen */ if (!atomic_read(&epfile->error)) { ret = wait_event_interruptible(epfile->wait, (ep = epfile->ep)); if (ret < 0) goto error; } if (!ep) { ret = -ENODEV; goto error; } } Loading Loading @@ -843,16 +873,26 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) spin_unlock_irq(&epfile->ffs->eps_lock); } else { DECLARE_COMPLETION_ONSTACK(done); struct completion *done; req = ep->req; req->buf = data; req->length = data_len; req->context = &done; req->complete = ffs_epfile_io_complete; ret = 0; if (io_data->read) { reinit_completion( &epfile->ffs->epout_completion); done = &epfile->ffs->epout_completion; req->context = done; } else { reinit_completion( &epfile->ffs->epin_completion); done = &epfile->ffs->epin_completion; req->context = done; } /* Don't queue another read if previous is still busy */ if (!(io_data->read && ep->is_busy)) { ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); Loading @@ -862,11 +902,19 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) spin_unlock_irq(&epfile->ffs->eps_lock); if (unlikely(ret < 0)) { /* nop */ ret = -EIO; } else if (unlikely( wait_for_completion_interruptible(&done))) { ret = -EINTR; wait_for_completion_interruptible(done))) { spin_lock_irq(&epfile->ffs->eps_lock); /* * While we were acquiring lock endpoint got * disabled (disconnect) or changed * (composition switch) */ if (epfile->ep == ep) usb_ep_dequeue(ep->ep, req); spin_unlock_irq(&epfile->ffs->eps_lock); ret = -EINTR; } else { /* * XXX We may end up silently droping data Loading @@ -875,7 +923,18 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * to maxpacketsize), we may end up with more * data then user space has space for. */ spin_lock_irq(&epfile->ffs->eps_lock); /* * While we were acquiring lock endpoint got * disabled (disconnect) or changed * (composition switch) */ if (epfile->ep == ep) ret = ep->status; else ret = -ENODEV; spin_unlock_irq(&epfile->ffs->eps_lock); if (io_data->read && ret > 0) { if (io_data->len != MAX_BUF_LEN && ret < io_data->len) Loading Loading @@ -955,6 +1014,7 @@ ffs_epfile_open(struct inode *inode, struct file *file) file->private_data = epfile; ffs_data_opened(epfile->ffs); atomic_set(&epfile->error, 0); return 0; } Loading Loading @@ -1049,7 +1109,9 @@ ffs_epfile_release(struct inode *inode, struct file *file) ENTER(); atomic_set(&epfile->error, 1); ffs_data_closed(epfile->ffs); file->private_data = NULL; return 0; } Loading Loading @@ -1487,6 +1549,8 @@ static struct ffs_data *ffs_data_new(void) spin_lock_init(&ffs->eps_lock); init_waitqueue_head(&ffs->ev.waitq); init_completion(&ffs->ep0req_completion); init_completion(&ffs->epout_completion); init_completion(&ffs->epin_completion); /* XXX REVISIT need to update it in some places, or do we? */ ffs->ev.can_stall = 1; Loading @@ -1498,9 +1562,16 @@ static void ffs_data_clear(struct ffs_data *ffs) { ENTER(); pr_debug("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__, ffs->gadget, ffs->flags); if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags)) ffs_closed(ffs); /* Dump ffs->gadget and ffs->flags */ if (ffs->gadget) pr_err("%s: ffs:%p ffs->gadget= %p, ffs->flags= %lu\n", __func__, ffs, ffs->gadget, ffs->flags); BUG_ON(ffs->gadget); if (ffs->epfiles) Loading Loading @@ -1543,7 +1614,6 @@ static void ffs_data_reset(struct ffs_data *ffs) static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) { struct usb_gadget_strings **lang; int first_id; ENTER(); Loading @@ -1551,9 +1621,14 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) return -EBADFD; first_id = usb_string_ids_n(cdev, ffs->strings_count); if (!ffs->first_id || ffs->old_strings_count < ffs->strings_count) { int first_id = usb_string_ids_n(cdev, ffs->strings_count); if (unlikely(first_id < 0)) return first_id; ffs->first_id = first_id; ffs->old_strings_count = ffs->strings_count; } ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); if (unlikely(!ffs->ep0req)) Loading @@ -1565,7 +1640,7 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) if (lang) { for (; *lang; ++lang) { struct usb_string *str = (*lang)->strings; int id = first_id; int id = ffs->first_id; for (; str->s; ++id, ++str) str->id = id; } Loading Loading @@ -1652,9 +1727,12 @@ static void ffs_func_eps_disable(struct ffs_function *func) spin_lock_irqsave(&func->ffs->eps_lock, flags); do { atomic_set(&epfile->error, 1); /* pending requests get nuked */ if (likely(ep->ep)) if (likely(ep->ep)) { usb_ep_disable(ep->ep); ep->ep->driver_data = NULL; } epfile->ep = NULL; ++ep; Loading Loading @@ -2935,8 +3013,10 @@ static int ffs_func_set_alt(struct usb_function *f, return intf; } if (ffs->func) if (ffs->func) { ffs_func_eps_disable(ffs->func); ffs->func = NULL; } if (ffs->state != FFS_ACTIVE) return -ENODEV; Loading Loading @@ -3231,6 +3311,7 @@ static void ffs_func_unbind(struct usb_configuration *c, if (ep->ep && ep->req) usb_ep_free_request(ep->ep, ep->req); ep->req = NULL; ep->ep = NULL; ++ep; } while (--count); spin_unlock_irqrestore(&func->ffs->eps_lock, flags); Loading
drivers/usb/gadget/function/u_fs.h +5 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,8 @@ struct ffs_data { */ struct usb_request *ep0req; /* P: mutex */ struct completion ep0req_completion; /* P: mutex */ struct completion epin_completion; struct completion epout_completion; /* reference counter */ atomic_t ref; Loading Loading @@ -233,6 +235,9 @@ struct ffs_data { unsigned short eps_count; unsigned short _pad1; int first_id; int old_strings_count; /* filled by __ffs_data_got_strings() */ /* ids in stringtabs are set in functionfs_bind() */ const void *raw_strings; Loading