diff options
Diffstat (limited to 'drivers/usb/gadget/function')
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 17 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_mass_storage.c | 27 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_mass_storage.h | 14 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_printer.c | 7 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/u_fs.h | 1 |
5 files changed, 27 insertions, 39 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9990944a7245..8b342587f8ad 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
| @@ -46,7 +46,8 @@ | |||
| 46 | static void ffs_data_get(struct ffs_data *ffs); | 46 | static void ffs_data_get(struct ffs_data *ffs); |
| 47 | static void ffs_data_put(struct ffs_data *ffs); | 47 | static void ffs_data_put(struct ffs_data *ffs); |
| 48 | /* Creates new ffs_data object. */ | 48 | /* Creates new ffs_data object. */ |
| 49 | static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc)); | 49 | static struct ffs_data *__must_check ffs_data_new(const char *dev_name) |
| 50 | __attribute__((malloc)); | ||
| 50 | 51 | ||
| 51 | /* Opened counter handling. */ | 52 | /* Opened counter handling. */ |
| 52 | static void ffs_data_opened(struct ffs_data *ffs); | 53 | static void ffs_data_opened(struct ffs_data *ffs); |
| @@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, | |||
| 780 | struct usb_request *req) | 781 | struct usb_request *req) |
| 781 | { | 782 | { |
| 782 | struct ffs_io_data *io_data = req->context; | 783 | struct ffs_io_data *io_data = req->context; |
| 784 | struct ffs_data *ffs = io_data->ffs; | ||
| 783 | 785 | ||
| 784 | ENTER(); | 786 | ENTER(); |
| 785 | 787 | ||
| 786 | INIT_WORK(&io_data->work, ffs_user_copy_worker); | 788 | INIT_WORK(&io_data->work, ffs_user_copy_worker); |
| 787 | schedule_work(&io_data->work); | 789 | queue_work(ffs->io_completion_wq, &io_data->work); |
| 788 | } | 790 | } |
| 789 | 791 | ||
| 790 | static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) | 792 | static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) |
| @@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, | |||
| 1500 | if (unlikely(ret < 0)) | 1502 | if (unlikely(ret < 0)) |
| 1501 | return ERR_PTR(ret); | 1503 | return ERR_PTR(ret); |
| 1502 | 1504 | ||
| 1503 | ffs = ffs_data_new(); | 1505 | ffs = ffs_data_new(dev_name); |
| 1504 | if (unlikely(!ffs)) | 1506 | if (unlikely(!ffs)) |
| 1505 | return ERR_PTR(-ENOMEM); | 1507 | return ERR_PTR(-ENOMEM); |
| 1506 | ffs->file_perms = data.perms; | 1508 | ffs->file_perms = data.perms; |
| @@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs) | |||
| 1610 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || | 1612 | BUG_ON(waitqueue_active(&ffs->ev.waitq) || |
| 1611 | waitqueue_active(&ffs->ep0req_completion.wait) || | 1613 | waitqueue_active(&ffs->ep0req_completion.wait) || |
| 1612 | waitqueue_active(&ffs->wait)); | 1614 | waitqueue_active(&ffs->wait)); |
| 1615 | destroy_workqueue(ffs->io_completion_wq); | ||
| 1613 | kfree(ffs->dev_name); | 1616 | kfree(ffs->dev_name); |
| 1614 | kfree(ffs); | 1617 | kfree(ffs); |
| 1615 | } | 1618 | } |
| @@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs) | |||
| 1642 | ffs_data_put(ffs); | 1645 | ffs_data_put(ffs); |
| 1643 | } | 1646 | } |
| 1644 | 1647 | ||
| 1645 | static struct ffs_data *ffs_data_new(void) | 1648 | static struct ffs_data *ffs_data_new(const char *dev_name) |
| 1646 | { | 1649 | { |
| 1647 | struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); | 1650 | struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); |
| 1648 | if (unlikely(!ffs)) | 1651 | if (unlikely(!ffs)) |
| @@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void) | |||
| 1650 | 1653 | ||
| 1651 | ENTER(); | 1654 | ENTER(); |
| 1652 | 1655 | ||
| 1656 | ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name); | ||
| 1657 | if (!ffs->io_completion_wq) { | ||
| 1658 | kfree(ffs); | ||
| 1659 | return NULL; | ||
| 1660 | } | ||
| 1661 | |||
| 1653 | refcount_set(&ffs->ref, 1); | 1662 | refcount_set(&ffs->ref, 1); |
| 1654 | atomic_set(&ffs->opened, 0); | 1663 | atomic_set(&ffs->opened, 0); |
| 1655 | ffs->state = FFS_READ_DESCRIPTORS; | 1664 | ffs->state = FFS_READ_DESCRIPTORS; |
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index d6bd0244b008..5153e29870c3 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c | |||
| @@ -307,8 +307,6 @@ struct fsg_common { | |||
| 307 | struct completion thread_notifier; | 307 | struct completion thread_notifier; |
| 308 | struct task_struct *thread_task; | 308 | struct task_struct *thread_task; |
| 309 | 309 | ||
| 310 | /* Callback functions. */ | ||
| 311 | const struct fsg_operations *ops; | ||
| 312 | /* Gadget's private data. */ | 310 | /* Gadget's private data. */ |
| 313 | void *private_data; | 311 | void *private_data; |
| 314 | 312 | ||
| @@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common) | |||
| 2438 | static int fsg_main_thread(void *common_) | 2436 | static int fsg_main_thread(void *common_) |
| 2439 | { | 2437 | { |
| 2440 | struct fsg_common *common = common_; | 2438 | struct fsg_common *common = common_; |
| 2439 | int i; | ||
| 2441 | 2440 | ||
| 2442 | /* | 2441 | /* |
| 2443 | * Allow the thread to be killed by a signal, but set the signal mask | 2442 | * Allow the thread to be killed by a signal, but set the signal mask |
| @@ -2476,21 +2475,16 @@ static int fsg_main_thread(void *common_) | |||
| 2476 | common->thread_task = NULL; | 2475 | common->thread_task = NULL; |
| 2477 | spin_unlock_irq(&common->lock); | 2476 | spin_unlock_irq(&common->lock); |
| 2478 | 2477 | ||
| 2479 | if (!common->ops || !common->ops->thread_exits | 2478 | /* Eject media from all LUNs */ |
| 2480 | || common->ops->thread_exits(common) < 0) { | ||
| 2481 | int i; | ||
| 2482 | 2479 | ||
| 2483 | down_write(&common->filesem); | 2480 | down_write(&common->filesem); |
| 2484 | for (i = 0; i < ARRAY_SIZE(common->luns); i++) { | 2481 | for (i = 0; i < ARRAY_SIZE(common->luns); i++) { |
| 2485 | struct fsg_lun *curlun = common->luns[i]; | 2482 | struct fsg_lun *curlun = common->luns[i]; |
| 2486 | if (!curlun || !fsg_lun_is_open(curlun)) | ||
| 2487 | continue; | ||
| 2488 | 2483 | ||
| 2484 | if (curlun && fsg_lun_is_open(curlun)) | ||
| 2489 | fsg_lun_close(curlun); | 2485 | fsg_lun_close(curlun); |
| 2490 | curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; | ||
| 2491 | } | ||
| 2492 | up_write(&common->filesem); | ||
| 2493 | } | 2486 | } |
| 2487 | up_write(&common->filesem); | ||
| 2494 | 2488 | ||
| 2495 | /* Let fsg_unbind() know the thread has exited */ | 2489 | /* Let fsg_unbind() know the thread has exited */ |
| 2496 | complete_and_exit(&common->thread_notifier, 0); | 2490 | complete_and_exit(&common->thread_notifier, 0); |
| @@ -2681,13 +2675,6 @@ void fsg_common_remove_luns(struct fsg_common *common) | |||
| 2681 | } | 2675 | } |
| 2682 | EXPORT_SYMBOL_GPL(fsg_common_remove_luns); | 2676 | EXPORT_SYMBOL_GPL(fsg_common_remove_luns); |
| 2683 | 2677 | ||
| 2684 | void fsg_common_set_ops(struct fsg_common *common, | ||
| 2685 | const struct fsg_operations *ops) | ||
| 2686 | { | ||
| 2687 | common->ops = ops; | ||
| 2688 | } | ||
| 2689 | EXPORT_SYMBOL_GPL(fsg_common_set_ops); | ||
| 2690 | |||
| 2691 | void fsg_common_free_buffers(struct fsg_common *common) | 2678 | void fsg_common_free_buffers(struct fsg_common *common) |
| 2692 | { | 2679 | { |
| 2693 | _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); | 2680 | _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); |
diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index d3902313b8ac..dc05ca0c4359 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h | |||
| @@ -60,17 +60,6 @@ struct fsg_module_parameters { | |||
| 60 | struct fsg_common; | 60 | struct fsg_common; |
| 61 | 61 | ||
| 62 | /* FSF callback functions */ | 62 | /* FSF callback functions */ |
| 63 | struct fsg_operations { | ||
| 64 | /* | ||
| 65 | * Callback function to call when thread exits. If no | ||
| 66 | * callback is set or it returns value lower then zero MSF | ||
| 67 | * will force eject all LUNs it operates on (including those | ||
| 68 | * marked as non-removable or with prevent_medium_removal flag | ||
| 69 | * set). | ||
| 70 | */ | ||
| 71 | int (*thread_exits)(struct fsg_common *common); | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct fsg_lun_opts { | 63 | struct fsg_lun_opts { |
| 75 | struct config_group group; | 64 | struct config_group group; |
| 76 | struct fsg_lun *lun; | 65 | struct fsg_lun *lun; |
| @@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun); | |||
| 142 | 131 | ||
| 143 | void fsg_common_remove_luns(struct fsg_common *common); | 132 | void fsg_common_remove_luns(struct fsg_common *common); |
| 144 | 133 | ||
| 145 | void fsg_common_set_ops(struct fsg_common *common, | ||
| 146 | const struct fsg_operations *ops); | ||
| 147 | |||
| 148 | int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, | 134 | int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, |
| 149 | unsigned int id, const char *name, | 135 | unsigned int id, const char *name, |
| 150 | const char **name_pfx); | 136 | const char **name_pfx); |
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 8df244fc9d80..ea0da35a44e2 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c | |||
| @@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
| 555 | size_t size; /* Amount of data in a TX request. */ | 555 | size_t size; /* Amount of data in a TX request. */ |
| 556 | size_t bytes_copied = 0; | 556 | size_t bytes_copied = 0; |
| 557 | struct usb_request *req; | 557 | struct usb_request *req; |
| 558 | int value; | ||
| 558 | 559 | ||
| 559 | DBG(dev, "printer_write trying to send %d bytes\n", (int)len); | 560 | DBG(dev, "printer_write trying to send %d bytes\n", (int)len); |
| 560 | 561 | ||
| @@ -634,7 +635,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
| 634 | return -EAGAIN; | 635 | return -EAGAIN; |
| 635 | } | 636 | } |
| 636 | 637 | ||
| 637 | if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { | 638 | /* here, we unlock, and only unlock, to avoid deadlock. */ |
| 639 | spin_unlock(&dev->lock); | ||
| 640 | value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); | ||
| 641 | spin_lock(&dev->lock); | ||
| 642 | if (value) { | ||
| 638 | list_add(&req->list, &dev->tx_reqs); | 643 | list_add(&req->list, &dev->tx_reqs); |
| 639 | spin_unlock_irqrestore(&dev->lock, flags); | 644 | spin_unlock_irqrestore(&dev->lock, flags); |
| 640 | mutex_unlock(&dev->lock_printer_io); | 645 | mutex_unlock(&dev->lock_printer_io); |
diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 540f1c48c1a8..79f70ebf85dc 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h | |||
| @@ -279,6 +279,7 @@ struct ffs_data { | |||
| 279 | } file_perms; | 279 | } file_perms; |
| 280 | 280 | ||
| 281 | struct eventfd_ctx *ffs_eventfd; | 281 | struct eventfd_ctx *ffs_eventfd; |
| 282 | struct workqueue_struct *io_completion_wq; | ||
| 282 | bool no_disconnect; | 283 | bool no_disconnect; |
| 283 | struct work_struct reset_work; | 284 | struct work_struct reset_work; |
| 284 | 285 | ||
