USB: ci13xxx_udc: make suspend and resume in gadget driver optional
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / gadget / ci13xxx_udc.c
index 83428f56253bd5283a8962448fa8cd7b899aee96..9db7e7667c2b05e2be281d398716e0d6584983de 100644 (file)
@@ -71,6 +71,9 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+
+#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
+
 /* ctrl register bank access */
 static DEFINE_SPINLOCK(udc_lock);
 
@@ -1434,7 +1437,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                return -EALREADY;
 
        mReq->req.status = -EALREADY;
-       if (length && !mReq->req.dma) {
+       if (length && mReq->req.dma == DMA_ADDR_INVALID) {
                mReq->req.dma = \
                        dma_map_single(mEp->device, mReq->req.buf,
                                       length, mEp->dir ? DMA_TO_DEVICE :
@@ -1453,7 +1456,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                                dma_unmap_single(mEp->device, mReq->req.dma,
                                        length, mEp->dir ? DMA_TO_DEVICE :
                                        DMA_FROM_DEVICE);
-                               mReq->req.dma = 0;
+                               mReq->req.dma = DMA_ADDR_INVALID;
                                mReq->map     = 0;
                        }
                        return -ENOMEM;
@@ -1549,7 +1552,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
 
@@ -1610,7 +1613,6 @@ __acquires(mEp->lock)
  * @gadget: gadget
  *
  * This function returns an error code
- * Caller must hold lock
  */
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
@@ -2189,6 +2191,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
        mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
        if (mReq != NULL) {
                INIT_LIST_HEAD(&mReq->queue);
+               mReq->req.dma = DMA_ADDR_INVALID;
 
                mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
                                           &mReq->dma);
@@ -2328,7 +2331,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
        req->status = -ECONNRESET;
@@ -2500,12 +2503,12 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
        spin_lock_irqsave(udc->lock, flags);
        if (!udc->remote_wakeup) {
                ret = -EOPNOTSUPP;
-               dbg_trace("remote wakeup feature is not enabled\n");
+               trace("remote wakeup feature is not enabled\n");
                goto out;
        }
        if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
                ret = -EINVAL;
-               dbg_trace("port is not suspended\n");
+               trace("port is not suspended\n");
                goto out;
        }
        hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
@@ -2560,9 +2563,7 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
        if (driver             == NULL ||
            bind               == NULL ||
            driver->setup      == NULL ||
-           driver->disconnect == NULL ||
-           driver->suspend    == NULL ||
-           driver->resume     == NULL)
+           driver->disconnect == NULL)
                return -EINVAL;
        else if (udc         == NULL)
                return -ENODEV;
@@ -2690,8 +2691,6 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
            driver->unbind     == NULL ||
            driver->setup      == NULL ||
            driver->disconnect == NULL ||
-           driver->suspend    == NULL ||
-           driver->resume     == NULL ||
            driver             != udc->driver)
                return -EINVAL;
 
@@ -2703,7 +2702,9 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
                if (udc->udc_driver->notify_event)
                        udc->udc_driver->notify_event(udc,
                        CI13XXX_CONTROLLER_STOPPED_EVENT);
+               spin_unlock_irqrestore(udc->lock, flags);
                _gadget_stop_activity(&udc->gadget);
+               spin_lock_irqsave(udc->lock, flags);
                pm_runtime_put(&udc->gadget.dev);
        }
 
@@ -2788,7 +2789,7 @@ static irqreturn_t udc_irq(void)
                        isr_statistics.pci++;
                        udc->gadget.speed = hw_port_is_high_speed() ?
                                USB_SPEED_HIGH : USB_SPEED_FULL;
-                       if (udc->suspended) {
+                       if (udc->suspended && udc->driver->resume) {
                                spin_unlock(udc->lock);
                                udc->driver->resume(&udc->gadget);
                                spin_lock(udc->lock);
@@ -2802,7 +2803,8 @@ static irqreturn_t udc_irq(void)
                        isr_tr_complete_handler(udc);
                }
                if (USBi_SLI & intr) {
-                       if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+                       if (udc->gadget.speed != USB_SPEED_UNKNOWN &&
+                           udc->driver->suspend) {
                                udc->suspended = 1;
                                spin_unlock(udc->lock);
                                udc->driver->suspend(&udc->gadget);
@@ -2850,7 +2852,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
        struct ci13xxx *udc;
        int retval = 0;
 
-       trace("%p, %p, %p", dev, regs, name);
+       trace("%p, %p, %p", dev, regs, driver->name);
 
        if (dev == NULL || regs == NULL || driver == NULL ||
                        driver->name == NULL)