diff options
Diffstat (limited to 'drivers/usb/gadget')
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 148 | ||||
| -rw-r--r-- | drivers/usb/gadget/function/f_hid.c | 3 | ||||
| -rw-r--r-- | drivers/usb/gadget/legacy/inode.c | 49 | ||||
| -rw-r--r-- | drivers/usb/gadget/legacy/raw_gadget.c | 3 | ||||
| -rw-r--r-- | drivers/usb/gadget/legacy/zero.c | 27 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/cdns2/cdns2-gadget.c | 1 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/lpc32xx_udc.c | 42 | ||||
| -rw-r--r-- | drivers/usb/gadget/udc/tegra-xudc.c | 6 |
8 files changed, 157 insertions, 122 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 47cfbe41fdff..05c6750702b6 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -160,8 +160,6 @@ struct ffs_epfile { struct ffs_data *ffs; struct ffs_ep *ep; /* P: ffs->eps_lock */ - struct dentry *dentry; - /* * Buffer for holding data from partial reads which may happen since * we’re rounding user read requests to a multiple of a max packet size. @@ -271,11 +269,11 @@ struct ffs_desc_helper { }; static int __must_check ffs_epfiles_create(struct ffs_data *ffs); -static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count); +static void ffs_epfiles_destroy(struct super_block *sb, + struct ffs_epfile *epfiles, unsigned count); -static struct dentry * -ffs_sb_create_file(struct super_block *sb, const char *name, void *data, - const struct file_operations *fops); +static int ffs_sb_create_file(struct super_block *sb, const char *name, + void *data, const struct file_operations *fops); /* Devices management *******************************************************/ @@ -640,13 +638,22 @@ done_mutex: static int ffs_ep0_open(struct inode *inode, struct file *file) { - struct ffs_data *ffs = inode->i_private; + struct ffs_data *ffs = inode->i_sb->s_fs_info; + int ret; - if (ffs->state == FFS_CLOSING) - return -EBUSY; + /* Acquire mutex */ + ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); + if (ret < 0) + return ret; - file->private_data = ffs; ffs_data_opened(ffs); + if (ffs->state == FFS_CLOSING) { + ffs_data_closed(ffs); + mutex_unlock(&ffs->mutex); + return -EBUSY; + } + mutex_unlock(&ffs->mutex); + file->private_data = ffs; return stream_open(inode, file); } @@ -1193,14 +1200,33 @@ error: static int ffs_epfile_open(struct inode *inode, struct file *file) { - struct ffs_epfile *epfile = inode->i_private; + struct ffs_data *ffs = inode->i_sb->s_fs_info; + struct ffs_epfile *epfile; + int ret; - if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) + /* Acquire mutex */ + ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); + if (ret < 0) + return ret; + + if (!atomic_inc_not_zero(&ffs->opened)) { + mutex_unlock(&ffs->mutex); + return -ENODEV; + } + /* + * we want the state to be FFS_ACTIVE; FFS_ACTIVE alone is + * not enough, though - we might have been through FFS_CLOSING + * and back to FFS_ACTIVE, with our file already removed. + */ + epfile = smp_load_acquire(&inode->i_private); + if (unlikely(ffs->state != FFS_ACTIVE || !epfile)) { + mutex_unlock(&ffs->mutex); + ffs_data_closed(ffs); return -ENODEV; + } + mutex_unlock(&ffs->mutex); file->private_data = epfile; - ffs_data_opened(epfile->ffs); - return stream_open(inode, file); } @@ -1306,9 +1332,7 @@ static void ffs_dmabuf_release(struct kref *ref) struct dma_buf *dmabuf = attach->dmabuf; pr_vdebug("FFS DMABUF release\n"); - dma_resv_lock(dmabuf->resv, NULL); - dma_buf_unmap_attachment(attach, priv->sgt, priv->dir); - dma_resv_unlock(dmabuf->resv); + dma_buf_unmap_attachment_unlocked(attach, priv->sgt, priv->dir); dma_buf_detach(attach->dmabuf, attach); dma_buf_put(dmabuf); @@ -1332,7 +1356,7 @@ static void ffs_dmabuf_put(struct dma_buf_attachment *attach) static int ffs_epfile_release(struct inode *inode, struct file *file) { - struct ffs_epfile *epfile = inode->i_private; + struct ffs_epfile *epfile = file->private_data; struct ffs_dmabuf_priv *priv, *tmp; struct ffs_data *ffs = epfile->ffs; @@ -1866,26 +1890,26 @@ ffs_sb_make_inode(struct super_block *sb, void *data, } /* Create "regular" file */ -static struct dentry *ffs_sb_create_file(struct super_block *sb, - const char *name, void *data, - const struct file_operations *fops) +static int ffs_sb_create_file(struct super_block *sb, const char *name, + void *data, const struct file_operations *fops) { struct ffs_data *ffs = sb->s_fs_info; struct dentry *dentry; struct inode *inode; - dentry = d_alloc_name(sb->s_root, name); - if (!dentry) - return NULL; - inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms); - if (!inode) { - dput(dentry); - return NULL; + if (!inode) + return -ENOMEM; + dentry = simple_start_creating(sb->s_root, name); + if (IS_ERR(dentry)) { + iput(inode); + return PTR_ERR(dentry); } - d_add(dentry, inode); - return dentry; + d_make_persistent(dentry, inode); + + simple_done_creating(dentry); + return 0; } /* Super block */ @@ -1928,10 +1952,7 @@ static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc) return -ENOMEM; /* EP0 file */ - if (!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations)) - return -ENOMEM; - - return 0; + return ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations); } enum { @@ -2071,12 +2092,21 @@ static int ffs_fs_init_fs_context(struct fs_context *fc) return 0; } +static void ffs_data_reset(struct ffs_data *ffs); + static void ffs_fs_kill_sb(struct super_block *sb) { - kill_litter_super(sb); - if (sb->s_fs_info) - ffs_data_closed(sb->s_fs_info); + kill_anon_super(sb); + if (sb->s_fs_info) { + struct ffs_data *ffs = sb->s_fs_info; + ffs->state = FFS_CLOSING; + ffs_data_reset(ffs); + // no configfs accesses from that point on, + // so no further schedule_work() is possible + cancel_work_sync(&ffs->reset_work); + ffs_data_put(ffs); + } } static struct file_system_type ffs_fs_type = { @@ -2114,7 +2144,6 @@ static void functionfs_cleanup(void) /* ffs_data and ffs_function construction and destruction code **************/ static void ffs_data_clear(struct ffs_data *ffs); -static void ffs_data_reset(struct ffs_data *ffs); static void ffs_data_get(struct ffs_data *ffs) { @@ -2123,7 +2152,6 @@ static void ffs_data_get(struct ffs_data *ffs) static void ffs_data_opened(struct ffs_data *ffs) { - refcount_inc(&ffs->ref); if (atomic_add_return(1, &ffs->opened) == 1 && ffs->state == FFS_DEACTIVATED) { ffs->state = FFS_CLOSING; @@ -2148,11 +2176,11 @@ static void ffs_data_put(struct ffs_data *ffs) static void ffs_data_closed(struct ffs_data *ffs) { - struct ffs_epfile *epfiles; - unsigned long flags; - if (atomic_dec_and_test(&ffs->opened)) { if (ffs->no_disconnect) { + struct ffs_epfile *epfiles; + unsigned long flags; + ffs->state = FFS_DEACTIVATED; spin_lock_irqsave(&ffs->eps_lock, flags); epfiles = ffs->epfiles; @@ -2161,7 +2189,7 @@ static void ffs_data_closed(struct ffs_data *ffs) flags); if (epfiles) - ffs_epfiles_destroy(epfiles, + ffs_epfiles_destroy(ffs->sb, epfiles, ffs->eps_count); if (ffs->setup_state == FFS_SETUP_PENDING) @@ -2171,12 +2199,6 @@ static void ffs_data_closed(struct ffs_data *ffs) ffs_data_reset(ffs); } } - if (atomic_read(&ffs->opened) < 0) { - ffs->state = FFS_CLOSING; - ffs_data_reset(ffs); - } - - ffs_data_put(ffs); } static struct ffs_data *ffs_data_new(const char *dev_name) @@ -2226,7 +2248,7 @@ static void ffs_data_clear(struct ffs_data *ffs) * copy of epfile will save us from use-after-free. */ if (epfiles) { - ffs_epfiles_destroy(epfiles, ffs->eps_count); + ffs_epfiles_destroy(ffs->sb, epfiles, ffs->eps_count); ffs->epfiles = NULL; } @@ -2323,6 +2345,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs) { struct ffs_epfile *epfile, *epfiles; unsigned i, count; + int err; count = ffs->eps_count; epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL); @@ -2339,12 +2362,11 @@ static int ffs_epfiles_create(struct ffs_data *ffs) sprintf(epfile->name, "ep%02x", ffs->eps_addrmap[i]); else sprintf(epfile->name, "ep%u", i); - epfile->dentry = ffs_sb_create_file(ffs->sb, epfile->name, - epfile, - &ffs_epfile_operations); - if (!epfile->dentry) { - ffs_epfiles_destroy(epfiles, i - 1); - return -ENOMEM; + err = ffs_sb_create_file(ffs->sb, epfile->name, + epfile, &ffs_epfile_operations); + if (err) { + ffs_epfiles_destroy(ffs->sb, epfiles, i - 1); + return err; } } @@ -2352,16 +2374,20 @@ static int ffs_epfiles_create(struct ffs_data *ffs) return 0; } -static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) +static void clear_one(struct dentry *dentry) +{ + smp_store_release(&dentry->d_inode->i_private, NULL); +} + +static void ffs_epfiles_destroy(struct super_block *sb, + struct ffs_epfile *epfiles, unsigned count) { struct ffs_epfile *epfile = epfiles; + struct dentry *root = sb->s_root; for (; count; --count, ++epfile) { BUG_ON(mutex_is_locked(&epfile->mutex)); - if (epfile->dentry) { - simple_recursive_removal(epfile->dentry, NULL); - epfile->dentry = NULL; - } + simple_remove_by_name(root, epfile->name, clear_one); } kfree(epfiles); diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index 307ea563af95..3ddfd4f66f0b 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -1272,8 +1272,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) INIT_WORK(&hidg->work, get_report_workqueue_handler); hidg->workqueue = alloc_workqueue("report_work", - WQ_FREEZABLE | - WQ_MEM_RECLAIM, + WQ_FREEZABLE | WQ_MEM_RECLAIM | WQ_PERCPU, 1); if (!hidg->workqueue) { diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 13c3da49348c..62566a8e7451 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -150,7 +150,6 @@ struct dev_data { void *buf; wait_queue_head_t wait; struct super_block *sb; - struct dentry *dentry; /* except this scratch i/o buffer for ep0 */ u8 rbuf[RBUF_SIZE]; @@ -208,7 +207,6 @@ struct ep_data { struct usb_endpoint_descriptor desc, hs_desc; struct list_head epfiles; wait_queue_head_t wait; - struct dentry *dentry; }; static inline void get_ep (struct ep_data *data) @@ -1561,16 +1559,12 @@ static void destroy_ep_files (struct dev_data *dev) spin_lock_irq (&dev->lock); while (!list_empty(&dev->epfiles)) { struct ep_data *ep; - struct dentry *dentry; /* break link to FS */ ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles); list_del_init (&ep->epfiles); spin_unlock_irq (&dev->lock); - dentry = ep->dentry; - ep->dentry = NULL; - /* break link to controller */ mutex_lock(&ep->lock); if (ep->state == STATE_EP_ENABLED) @@ -1581,10 +1575,11 @@ static void destroy_ep_files (struct dev_data *dev) mutex_unlock(&ep->lock); wake_up (&ep->wait); - put_ep (ep); /* break link to dcache */ - simple_recursive_removal(dentry, NULL); + simple_remove_by_name(dev->sb->s_root, ep->name, NULL); + + put_ep (ep); spin_lock_irq (&dev->lock); } @@ -1592,14 +1587,14 @@ static void destroy_ep_files (struct dev_data *dev) } -static struct dentry * -gadgetfs_create_file (struct super_block *sb, char const *name, +static int gadgetfs_create_file (struct super_block *sb, char const *name, void *data, const struct file_operations *fops); static int activate_ep_files (struct dev_data *dev) { struct usb_ep *ep; struct ep_data *data; + int err; gadget_for_each_ep (ep, dev->gadget) { @@ -1622,9 +1617,9 @@ static int activate_ep_files (struct dev_data *dev) if (!data->req) goto enomem1; - data->dentry = gadgetfs_create_file (dev->sb, data->name, + err = gadgetfs_create_file (dev->sb, data->name, data, &ep_io_operations); - if (!data->dentry) + if (err) goto enomem2; list_add_tail (&data->epfiles, &dev->epfiles); } @@ -1988,25 +1983,27 @@ gadgetfs_make_inode (struct super_block *sb, /* creates in fs root directory, so non-renamable and non-linkable. * so inode and dentry are paired, until device reconfig. */ -static struct dentry * -gadgetfs_create_file (struct super_block *sb, char const *name, +static int gadgetfs_create_file (struct super_block *sb, char const *name, void *data, const struct file_operations *fops) { struct dentry *dentry; struct inode *inode; - dentry = d_alloc_name(sb->s_root, name); - if (!dentry) - return NULL; - inode = gadgetfs_make_inode (sb, data, fops, S_IFREG | (default_perm & S_IRWXUGO)); - if (!inode) { - dput(dentry); - return NULL; + if (!inode) + return -ENOMEM; + + dentry = simple_start_creating(sb->s_root, name); + if (IS_ERR(dentry)) { + iput(inode); + return PTR_ERR(dentry); } - d_add (dentry, inode); - return dentry; + + d_make_persistent(dentry, inode); + + simple_done_creating(dentry); + return 0; } static const struct super_operations gadget_fs_operations = { @@ -2059,8 +2056,8 @@ gadgetfs_fill_super (struct super_block *sb, struct fs_context *fc) goto Enomem; dev->sb = sb; - dev->dentry = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations); - if (!dev->dentry) { + rc = gadgetfs_create_file(sb, CHIP, dev, &ep0_operations); + if (rc) { put_dev(dev); goto Enomem; } @@ -2102,7 +2099,7 @@ static void gadgetfs_kill_sb (struct super_block *sb) { mutex_lock(&sb_mutex); - kill_litter_super (sb); + kill_anon_super (sb); if (the_device) { put_dev (the_device); the_device = NULL; diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c index b71680c58de6..46f343ba48b3 100644 --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -40,6 +40,7 @@ MODULE_LICENSE("GPL"); static DEFINE_IDA(driver_id_numbers); #define DRIVER_DRIVER_NAME_LENGTH_MAX 32 +#define USB_RAW_IO_LENGTH_MAX KMALLOC_MAX_SIZE #define RAW_EVENT_QUEUE_SIZE 16 @@ -667,6 +668,8 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, return ERR_PTR(-EINVAL); if (!usb_raw_io_flags_valid(io->flags)) return ERR_PTR(-EINVAL); + if (io->length > USB_RAW_IO_LENGTH_MAX) + return ERR_PTR(-EINVAL); if (get_from_user) data = memdup_user(ptr + sizeof(*io), io->length); else { diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c index a05785bdeb30..08a21bd0c2ba 100644 --- a/drivers/usb/gadget/legacy/zero.c +++ b/drivers/usb/gadget/legacy/zero.c @@ -147,6 +147,12 @@ static struct usb_gadget_strings *dev_strings[] = { NULL, }; +static struct usb_function *func_lb; +static struct usb_function_instance *func_inst_lb; + +static struct usb_function *func_ss; +static struct usb_function_instance *func_inst_ss; + /*-------------------------------------------------------------------------*/ static struct timer_list autoresume_timer; @@ -156,6 +162,7 @@ static void zero_autoresume(struct timer_list *unused) { struct usb_composite_dev *cdev = autoresume_cdev; struct usb_gadget *g = cdev->gadget; + int status; /* unconfigured devices can't issue wakeups */ if (!cdev->config) @@ -165,10 +172,18 @@ static void zero_autoresume(struct timer_list *unused) * more significant than just a timer firing; likely * because of some direct user request. */ - if (g->speed != USB_SPEED_UNKNOWN) { - int status = usb_gadget_wakeup(g); - INFO(cdev, "%s --> %d\n", __func__, status); + if (g->speed == USB_SPEED_UNKNOWN) + return; + + if (g->speed >= USB_SPEED_SUPER) { + if (loopdefault) + status = usb_func_wakeup(func_lb); + else + status = usb_func_wakeup(func_ss); + } else { + status = usb_gadget_wakeup(g); } + INFO(cdev, "%s --> %d\n", __func__, status); } static void zero_suspend(struct usb_composite_dev *cdev) @@ -206,9 +221,6 @@ static struct usb_configuration loopback_driver = { /* .iConfiguration = DYNAMIC */ }; -static struct usb_function *func_ss; -static struct usb_function_instance *func_inst_ss; - static int ss_config_setup(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl) { @@ -248,9 +260,6 @@ module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); -static struct usb_function *func_lb; -static struct usb_function_instance *func_inst_lb; - module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(qlen, "depth of loopback queue"); diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c index 7e69944ef18a..9b53daf76583 100644 --- a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c +++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c @@ -2415,7 +2415,6 @@ int cdns2_gadget_resume(struct cdns2_device *pdev, bool hibernated) void cdns2_gadget_remove(struct cdns2_device *pdev) { - pm_runtime_mark_last_busy(pdev->dev); pm_runtime_put_autosuspend(pdev->dev); usb_del_gadget(&pdev->gadget); diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 1a7d3c4f652f..83c7e243dcf9 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -3020,7 +3020,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) pdev->dev.dma_mask = &lpc32xx_usbd_dmamask; retval = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (retval) - return retval; + goto err_put_client; udc->board = &lpc32xx_usbddata; @@ -3038,28 +3038,32 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) /* Get IRQs */ for (i = 0; i < 4; i++) { udc->udp_irq[i] = platform_get_irq(pdev, i); - if (udc->udp_irq[i] < 0) - return udc->udp_irq[i]; + if (udc->udp_irq[i] < 0) { + retval = udc->udp_irq[i]; + goto err_put_client; + } } udc->udp_baseaddr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(udc->udp_baseaddr)) { dev_err(udc->dev, "IO map failure\n"); - return PTR_ERR(udc->udp_baseaddr); + retval = PTR_ERR(udc->udp_baseaddr); + goto err_put_client; } /* Get USB device clock */ udc->usb_slv_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(udc->usb_slv_clk)) { dev_err(udc->dev, "failed to acquire USB device clock\n"); - return PTR_ERR(udc->usb_slv_clk); + retval = PTR_ERR(udc->usb_slv_clk); + goto err_put_client; } /* Enable USB device clock */ retval = clk_prepare_enable(udc->usb_slv_clk); if (retval < 0) { dev_err(udc->dev, "failed to start USB device clock\n"); - return retval; + goto err_put_client; } /* Setup deferred workqueue data */ @@ -3080,7 +3084,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (!udc->udca_v_base) { dev_err(udc->dev, "error getting UDCA region\n"); retval = -ENOMEM; - goto i2c_fail; + goto err_disable_clk; } udc->udca_p_base = dma_handle; dev_dbg(udc->dev, "DMA buffer(0x%x bytes), P:0x%08x, V:0x%p\n", @@ -3093,7 +3097,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (!udc->dd_cache) { dev_err(udc->dev, "error getting DD DMA region\n"); retval = -ENOMEM; - goto dma_alloc_fail; + goto err_free_dma; } /* Clear USB peripheral and initialize gadget endpoints */ @@ -3107,14 +3111,14 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (retval < 0) { dev_err(udc->dev, "LP request irq %d failed\n", udc->udp_irq[IRQ_USB_LP]); - goto irq_req_fail; + goto err_destroy_pool; } retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_HP], lpc32xx_usb_hp_irq, 0, "udc_hp", udc); if (retval < 0) { dev_err(udc->dev, "HP request irq %d failed\n", udc->udp_irq[IRQ_USB_HP]); - goto irq_req_fail; + goto err_destroy_pool; } retval = devm_request_irq(dev, udc->udp_irq[IRQ_USB_DEVDMA], @@ -3122,7 +3126,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (retval < 0) { dev_err(udc->dev, "DEV request irq %d failed\n", udc->udp_irq[IRQ_USB_DEVDMA]); - goto irq_req_fail; + goto err_destroy_pool; } /* The transceiver interrupt is used for VBUS detection and will @@ -3133,7 +3137,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) if (retval < 0) { dev_err(udc->dev, "VBUS request irq %d failed\n", udc->udp_irq[IRQ_USB_ATX]); - goto irq_req_fail; + goto err_destroy_pool; } /* Initialize wait queue */ @@ -3142,7 +3146,7 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) retval = usb_add_gadget_udc(dev, &udc->gadget); if (retval < 0) - goto add_gadget_fail; + goto err_destroy_pool; dev_set_drvdata(dev, udc); device_init_wakeup(dev, 1); @@ -3154,14 +3158,16 @@ static int lpc32xx_udc_probe(struct platform_device *pdev) dev_info(udc->dev, "%s version %s\n", driver_name, DRIVER_VERSION); return 0; -add_gadget_fail: -irq_req_fail: +err_destroy_pool: dma_pool_destroy(udc->dd_cache); -dma_alloc_fail: +err_free_dma: dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, udc->udca_v_base, udc->udca_p_base); -i2c_fail: +err_disable_clk: clk_disable_unprepare(udc->usb_slv_clk); +err_put_client: + put_device(&udc->isp1301_i2c_client->dev); + dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval); return retval; @@ -3190,6 +3196,8 @@ static void lpc32xx_udc_remove(struct platform_device *pdev) udc->udca_v_base, udc->udca_p_base); clk_disable_unprepare(udc->usb_slv_clk); + + put_device(&udc->isp1301_i2c_client->dev); } #ifdef CONFIG_PM diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 0c38fc37b6e6..9d2007f448c0 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -1558,12 +1558,6 @@ static int __tegra_xudc_ep_set_halt(struct tegra_xudc_ep *ep, bool halt) return -ENOTSUPP; } - if (!!(xudc_readl(xudc, EP_HALT) & BIT(ep->index)) == halt) { - dev_dbg(xudc->dev, "EP %u already %s\n", ep->index, - halt ? "halted" : "not halted"); - return 0; - } - if (halt) { ep_halt(xudc, ep->index); } else { |
