diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-28 17:28:59 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-28 17:28:59 +0100 |
commit | 4ae8beac0abb9c3bbbb8340bab46eb287aea3001 (patch) | |
tree | 03dfef1709539290a186b6737e449044e186c245 /drivers/usb/gadget/configfs.c | |
parent | Linux 5.4-rc5 (diff) | |
parent | usb: cdns3: gadget: Don't manage pullups (diff) | |
download | linux-4ae8beac0abb9c3bbbb8340bab46eb287aea3001.tar.xz linux-4ae8beac0abb9c3bbbb8340bab46eb287aea3001.zip |
Merge tag 'fixes-for-v5.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus
Felipe writes:
USB: fixes for v5.4-rc5
Not much here, only 14 commits in different drivers.
As for the specifics, Roger Quadros fixed an important bug in cdns3
where the driver was making decisions about data pull-up management
behind the UDC framework's back.
The Atmel UDC got a fix for interrupt storm in FIFO mode, this was done
by Cristian Brisan.
Apart from these, we have the usual set of non-critical fixes.
Signed-off-by: Felipe Balbi <balbi@kernel.org>
* tag 'fixes-for-v5.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb:
usb: cdns3: gadget: Don't manage pullups
usb: dwc3: remove the call trace of USBx_GFLADJ
usb: gadget: configfs: fix concurrent issue between composite APIs
usb: dwc3: pci: prevent memory leak in dwc3_pci_probe
usb: gadget: composite: Fix possible double free memory bug
usb: gadget: udc: atmel: Fix interrupt storm in FIFO mode.
usb: renesas_usbhs: fix type of buf
usb: renesas_usbhs: Fix warnings in usbhsg_recip_handler_std_set_device()
usb: gadget: udc: renesas_usb3: Fix __le16 warnings
usb: renesas_usbhs: fix __le16 warnings
usb: cdns3: include host-export,h for cdns3_host_init
usb: mtu3: fix missing include of mtu3_dr.h
usb: fsl: Check memory resource before releasing it
usb: dwc3: select CONFIG_REGMAP_MMIO
Diffstat (limited to 'drivers/usb/gadget/configfs.c')
-rw-r--r-- | drivers/usb/gadget/configfs.c | 110 |
1 files changed, 105 insertions, 5 deletions
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 025129942894..33852c2b29d1 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -61,6 +61,8 @@ struct gadget_info { bool use_os_desc; char b_vendor_code; char qw_sign[OS_STRING_QW_SIGN_LEN]; + spinlock_t spinlock; + bool unbind; }; static inline struct gadget_info *to_gadget_info(struct config_item *item) @@ -1244,6 +1246,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget, int ret; /* the gi->lock is hold by the caller */ + gi->unbind = 0; cdev->gadget = gadget; set_gadget_data(gadget, cdev); ret = composite_dev_prepare(composite, cdev); @@ -1376,31 +1379,128 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) { struct usb_composite_dev *cdev; struct gadget_info *gi; + unsigned long flags; /* the gi->lock is hold by the caller */ cdev = get_gadget_data(gadget); gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + gi->unbind = 1; + spin_unlock_irqrestore(&gi->spinlock, flags); kfree(otg_desc[0]); otg_desc[0] = NULL; purge_configs_funcs(gi); composite_dev_cleanup(cdev); usb_ep_autoconfig_reset(cdev->gadget); + spin_lock_irqsave(&gi->spinlock, flags); cdev->gadget = NULL; set_gadget_data(gadget, NULL); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + +static int configfs_composite_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + int ret; + + cdev = get_gadget_data(gadget); + if (!cdev) + return 0; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return 0; + } + + ret = composite_setup(gadget, ctrl); + spin_unlock_irqrestore(&gi->spinlock, flags); + return ret; +} + +static void configfs_composite_disconnect(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_disconnect(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + +static void configfs_composite_suspend(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_suspend(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); +} + +static void configfs_composite_resume(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + unsigned long flags; + + cdev = get_gadget_data(gadget); + if (!cdev) + return; + + gi = container_of(cdev, struct gadget_info, cdev); + spin_lock_irqsave(&gi->spinlock, flags); + cdev = get_gadget_data(gadget); + if (!cdev || gi->unbind) { + spin_unlock_irqrestore(&gi->spinlock, flags); + return; + } + + composite_resume(gadget); + spin_unlock_irqrestore(&gi->spinlock, flags); } static const struct usb_gadget_driver configfs_driver_template = { .bind = configfs_composite_bind, .unbind = configfs_composite_unbind, - .setup = composite_setup, - .reset = composite_disconnect, - .disconnect = composite_disconnect, + .setup = configfs_composite_setup, + .reset = configfs_composite_disconnect, + .disconnect = configfs_composite_disconnect, - .suspend = composite_suspend, - .resume = composite_resume, + .suspend = configfs_composite_suspend, + .resume = configfs_composite_resume, .max_speed = USB_SPEED_SUPER, .driver = { |