Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: gadget: udc: Process disconnect synchronously

As the comment in usb_disconnect() hints, do not defer the
disconnect processing, and instead just do it directly in
the irq handler. This allows the driver to avoid using a
nowadays deprecated tasklet.

Acked-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Link: https://lore.kernel.org/r/20210119001653.127975-1-dave@stgolabs.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Davidlohr Bueso and committed by
Greg Kroah-Hartman
908f6e2b 79f06f04

+3 -27
+3 -27
drivers/usb/gadget/udc/snps_udc_core.c
··· 36 36 #include <asm/unaligned.h> 37 37 #include "amd5536udc.h" 38 38 39 - static void udc_tasklet_disconnect(unsigned long); 40 39 static void udc_setup_endpoints(struct udc *dev); 41 40 static void udc_soft_reset(struct udc *dev); 42 41 static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep); ··· 93 94 static struct timer_list udc_pollstall_timer; 94 95 static int stop_pollstall_timer; 95 96 static DECLARE_COMPLETION(on_pollstall_exit); 96 - 97 - /* tasklet for usb disconnect */ 98 - static DECLARE_TASKLET_OLD(disconnect_tasklet, udc_tasklet_disconnect); 99 97 100 98 /* endpoint names used for print */ 101 99 static const char ep0_string[] = "ep0in"; ··· 1633 1637 */ 1634 1638 static void usb_disconnect(struct udc *dev) 1635 1639 { 1640 + u32 tmp; 1641 + 1636 1642 /* Return if already disconnected */ 1637 1643 if (!dev->connected) 1638 1644 return; ··· 1646 1648 /* mask interrupts */ 1647 1649 udc_mask_unused_interrupts(dev); 1648 1650 1649 - /* REVISIT there doesn't seem to be a point to having this 1650 - * talk to a tasklet ... do it directly, we already hold 1651 - * the spinlock needed to process the disconnect. 1652 - */ 1653 - 1654 - tasklet_schedule(&disconnect_tasklet); 1655 - } 1656 - 1657 - /* Tasklet for disconnect to be outside of interrupt context */ 1658 - static void udc_tasklet_disconnect(unsigned long par) 1659 - { 1660 - struct udc *dev = udc; 1661 - u32 tmp; 1662 - 1663 - DBG(dev, "Tasklet disconnect\n"); 1664 - spin_lock_irq(&dev->lock); 1665 - 1666 1651 if (dev->driver) { 1667 1652 spin_unlock(&dev->lock); 1668 1653 dev->driver->disconnect(&dev->gadget); ··· 1654 1673 /* empty queues */ 1655 1674 for (tmp = 0; tmp < UDC_EP_NUM; tmp++) 1656 1675 empty_req_queue(&dev->ep[tmp]); 1657 - 1658 1676 } 1659 1677 1660 1678 /* disable ep0 */ 1661 - ep_init(dev->regs, 1662 - &dev->ep[UDC_EP0IN_IX]); 1663 - 1679 + ep_init(dev->regs, &dev->ep[UDC_EP0IN_IX]); 1664 1680 1665 1681 if (!soft_reset_occured) { 1666 1682 /* init controller by soft reset */ ··· 1673 1695 tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); 1674 1696 writel(tmp, &dev->regs->cfg); 1675 1697 } 1676 - 1677 - spin_unlock_irq(&dev->lock); 1678 1698 } 1679 1699 1680 1700 /* Reset the UDC core */