This patches converts the driver into the new style start/stop interface. As a result the driver no longer uses the static global udc variable. Since the driver is accessing global variables, there can be only one device served at a time. Compile tested only. Cc: Thomas Dahlmann <dahlmann.thomas@xxxxxxxx> Signed-off-by: Sebastian Andrzej Siewior <sebastian@xxxxxxxxxxxxx> --- drivers/usb/gadget/amd5536udc.c | 113 +++++++++++++++------------------------ 1 files changed, 43 insertions(+), 70 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index f0a05e3..5e63716 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -64,6 +64,7 @@ /* udc specific */ #include "amd5536udc.h" +static atomic_t count_devices = ATOMIC_INIT(0); static void udc_tasklet_disconnect(struct udc *dev); static void empty_req_queue(struct udc_ep *); static int udc_probe(struct udc *dev); @@ -89,9 +90,6 @@ static const struct usb_ep_ops udc_ep_ops; /* received setup data */ static union udc_setup_data setup_data; -/* pointer to device object */ -static struct udc *udc; - /* irq spin lock for soft reset */ static DEFINE_SPINLOCK(udc_irq_spinlock); /* stall spin lock */ @@ -1297,9 +1295,9 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) u32 tmp; u32 dma_sts; /* stop potential receive DMA */ - tmp = readl(&udc->regs->ctl); + tmp = readl(&ep->dev->regs->ctl); writel(tmp & AMD_UNMASK_BIT(UDC_DEVCTL_RDE), - &udc->regs->ctl); + &ep->dev->regs->ctl); /* * Cancel transfer later in ISR * if descriptor was touched. @@ -1313,7 +1311,7 @@ static int udc_dequeue(struct usb_ep *usbep, struct usb_request *usbreq) writel(ep->bna_dummy_req->td_phys, &ep->regs->desptr); } - writel(tmp, &udc->regs->ctl); + writel(tmp, &ep->dev->regs->ctl); } } } @@ -1423,15 +1421,16 @@ static int udc_wakeup(struct usb_gadget *gadget) return 0; } -static int amd5536_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int amd5536_stop(struct usb_gadget_driver *driver); +static int amd5536_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); +static int amd5536_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); /* gadget operations */ static const struct usb_gadget_ops udc_ops = { .wakeup = udc_wakeup, .get_frame = udc_get_frame, - .start = amd5536_start, - .stop = amd5536_stop, + .udc_start = amd5536_start, + .udc_stop = amd5536_stop, }; /* Setups endpoint parameters, adds endpoints to linked list */ @@ -1708,6 +1707,7 @@ static void udc_soft_reset(struct udc *dev) /* RDE timer callback to set RDE bit */ static void udc_timer_function(unsigned long v) { + struct udc *dev = (struct udc *)v; u32 tmp; spin_lock_irq(&udc_irq_spinlock); @@ -1719,11 +1719,11 @@ static void udc_timer_function(unsigned long v) */ if (set_rde > 1) { /* set RDE to receive setup data */ - tmp = readl(&udc->regs->ctl); + tmp = readl(&dev->regs->ctl); tmp |= AMD_BIT(UDC_DEVCTL_RDE); - writel(tmp, &udc->regs->ctl); + writel(tmp, &dev->regs->ctl); set_rde = -1; - } else if (readl(&udc->regs->sts) + } else if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { /* * if fifo empty setup polling, do not just @@ -1754,7 +1754,6 @@ static void udc_timer_function(unsigned long v) spin_unlock_irq(&udc_irq_spinlock); if (stop_timer) complete(&on_exit); - } /* Handle halt state, used in stall poll timer */ @@ -1790,6 +1789,7 @@ static void udc_handle_halt_state(struct udc_ep *ep) /* Stall timer callback to poll S bit and set it again after */ static void udc_pollstall_timer_function(unsigned long v) { + struct udc *dev = (struct udc *)v; struct udc_ep *ep; int halted = 0; @@ -1798,12 +1798,12 @@ static void udc_pollstall_timer_function(unsigned long v) * only one IN and OUT endpoints are handled * IN poll stall */ - ep = &udc->ep[UDC_EPIN_IX]; + ep = &dev->ep[UDC_EPIN_IX]; udc_handle_halt_state(ep); if (ep->halted) halted = 1; /* OUT poll stall */ - ep = &udc->ep[UDC_EPOUT_IX]; + ep = &dev->ep[UDC_EPOUT_IX]; udc_handle_halt_state(ep); if (ep->halted) halted = 1; @@ -1935,41 +1935,26 @@ static int setup_ep0(struct udc *dev) } /* Called by gadget driver to register itself */ -static int amd5536_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int amd5536_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct udc *dev = udc; - int retval; + struct udc *dev; u32 tmp; - if (!driver || !bind || !driver->setup - || driver->max_speed < USB_SPEED_HIGH) + if (driver->max_speed < USB_SPEED_HIGH) return -EINVAL; - if (!dev) - return -ENODEV; - if (dev->driver) - return -EBUSY; + dev = container_of(gadget, struct udc, gadget); driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = bind(&dev->gadget); - /* Some gadget drivers use both ep0 directions. * NOTE: to gadget driver, ep0 is just one endpoint... */ dev->ep[UDC_EP0OUT_IX].ep.driver_data = dev->ep[UDC_EP0IN_IX].ep.driver_data; - if (retval) { - DBG(dev, "binding to %s returning %d\n", - driver->driver.name, retval); - dev->driver = NULL; - dev->gadget.dev.driver = NULL; - return retval; - } - /* get ready for ep0 traffic */ setup_ep0(dev); @@ -1984,19 +1969,10 @@ static int amd5536_start(struct usb_gadget_driver *driver, } /* shutdown requests and disconnect from gadget */ -static void -shutdown(struct udc *dev, struct usb_gadget_driver *driver) -__releases(dev->lock) -__acquires(dev->lock) +static void shutdown(struct udc *dev, struct usb_gadget_driver *driver) { int tmp; - if (dev->gadget.speed != USB_SPEED_UNKNOWN) { - spin_unlock(&dev->lock); - driver->disconnect(&dev->gadget); - spin_lock(&dev->lock); - } - /* empty queues and init hardware */ udc_basic_init(dev); for (tmp = 0; tmp < UDC_EP_NUM; tmp++) @@ -2006,23 +1982,20 @@ __acquires(dev->lock) } /* Called by gadget driver to unregister itself */ -static int amd5536_stop(struct usb_gadget_driver *driver) +static int amd5536_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct udc *dev = udc; + struct udc *dev = container_of(gadget, struct udc, gadget); unsigned long flags; u32 tmp; - if (!dev) - return -ENODEV; - if (!driver || driver != dev->driver || !driver->unbind) - return -EINVAL; + dev = container_of (gadget, struct udc, gadget); spin_lock_irqsave(&dev->lock, flags); udc_mask_unused_interrupts(dev); shutdown(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); - driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; dev->driver = NULL; @@ -2031,7 +2004,6 @@ static int amd5536_stop(struct usb_gadget_driver *driver) tmp |= AMD_BIT(UDC_DEVCTL_SD); writel(tmp, &dev->regs->ctl); - DBG(dev, "%s: unregistered\n", driver->driver.name); return 0; @@ -2584,9 +2556,9 @@ __acquires(dev->lock) * clear stall bits * only one IN and OUT endpoints are handled */ - ep_tmp = &udc->ep[UDC_EPIN_IX]; + ep_tmp = &dev->ep[UDC_EPIN_IX]; udc_set_halt(&ep_tmp->ep, 0); - ep_tmp = &udc->ep[UDC_EPOUT_IX]; + ep_tmp = &dev->ep[UDC_EPOUT_IX]; udc_set_halt(&ep_tmp->ep, 0); } @@ -3012,7 +2984,7 @@ __acquires(dev->lock) writel(tmp, &dev->regs->irqmsk); DBG(dev, "USB Disconnect (session valid low)\n"); /* cleanup on disconnect */ - usb_disconnect(udc); + usb_disconnect(dev); } } @@ -3096,7 +3068,6 @@ static void udc_remove(struct udc *dev) wait_for_completion(&on_pollstall_exit); if (udc_pollstall_timer.data) del_timer_sync(&udc_pollstall_timer); - udc = NULL; } /* Reset all pci context */ @@ -3106,7 +3077,7 @@ static void udc_pci_remove(struct pci_dev *pdev) dev = pci_get_drvdata(pdev); - usb_del_gadget_udc(&udc->gadget); + usb_del_gadget_udc(&dev->gadget); /* gadget driver must not be registered */ BUG_ON(dev->driver != NULL); @@ -3142,6 +3113,7 @@ static void udc_pci_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); udc_remove(dev); + atomic_dec(&count_devices); } /* create dma pools on init */ @@ -3211,11 +3183,13 @@ static int udc_pci_probe( struct udc *dev; unsigned long resource; unsigned long len; - int retval = 0; + int retval; + retval = atomic_inc_return(&count_devices); /* one udc only */ - if (udc) { - dev_dbg(&pdev->dev, "already probed\n"); + if (retval > 1) { + dev_err(&pdev->dev, "Only one device is supported.\n"); + atomic_dec(&count_devices); return -EBUSY; } @@ -3307,9 +3281,9 @@ static int udc_pci_probe( dev->gadget.dev.dma_mask = pdev->dev.dma_mask; /* general probing */ - if (udc_probe(dev) == 0) - return 0; - + retval = udc_probe(dev); + if (!retval) + return retval; finished: if (dev) udc_pci_remove(pdev); @@ -3353,9 +3327,8 @@ static int udc_probe(struct udc *dev) } dev_info(&dev->pdev->dev, "driver version: %s(for Geode5536 B1)\n", tmp); - udc = dev; - retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget); + retval = usb_add_gadget_udc(&dev->pdev->dev, &dev->gadget); if (retval) goto finished; @@ -3369,11 +3342,11 @@ static int udc_probe(struct udc *dev) /* timer init */ init_timer(&udc_timer); udc_timer.function = udc_timer_function; - udc_timer.data = 1; + udc_timer.data = (unsigned long)dev; /* timer pollstall init */ init_timer(&udc_pollstall_timer); udc_pollstall_timer.function = udc_pollstall_timer_function; - udc_pollstall_timer.data = 1; + udc_pollstall_timer.data = (unsigned long)dev; /* set SD */ reg = readl(&dev->regs->ctl); -- 1.7.8.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html