These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / gadget / udc / amd5536udc.c
index de7e5e2..cd87641 100644 (file)
 
 static void udc_tasklet_disconnect(unsigned long);
 static void empty_req_queue(struct udc_ep *);
-static int udc_probe(struct udc *dev);
-static void udc_basic_init(struct udc *dev);
 static void udc_setup_endpoints(struct udc *dev);
 static void udc_soft_reset(struct udc *dev);
 static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
 static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req);
-static int udc_create_dma_chain(struct udc_ep *ep, struct udc_request *req,
-                               unsigned long buf_len, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
 
 /* description */
 static const char mod_desc[] = UDC_MOD_DESCRIPTION;
@@ -138,15 +130,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
 
 /* endpoint names used for print */
 static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
-       ep0_string,
-       "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
-       "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
-       "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
-       "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
-       "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
-       "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
-       "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+static const struct {
+       const char *name;
+       const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+       { \
+               .name = _name, \
+               .caps = _caps, \
+       }
+
+       EP_INFO(ep0_string,
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep1in-int",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep2in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep3in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep4in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep5in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep6in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep7in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep8in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep9in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep10in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep11in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep12in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep13in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep14in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep15in-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+       EP_INFO("ep0out",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep1out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep2out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep3out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep4out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep5out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep6out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep7out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep8out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep9out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep10out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep11out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep12out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep13out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep14out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+       EP_INFO("ep15out-bulk",
+               USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
 };
 
 /* DMA usage flag */
@@ -548,6 +607,30 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
        return &req->req;
 }
 
+/* frees pci pool descriptors of a DMA chain */
+static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
+{
+       int ret_val = 0;
+       struct udc_data_dma     *td;
+       struct udc_data_dma     *td_last = NULL;
+       unsigned int i;
+
+       DBG(dev, "free chain req = %p\n", req);
+
+       /* do not free first desc., will be done by free for request */
+       td_last = req->td_data;
+       td = phys_to_virt(td_last->next);
+
+       for (i = 1; i < req->chain_len; i++) {
+               pci_pool_free(dev->data_requests, td,
+                             (dma_addr_t)td_last->next);
+               td_last = td;
+               td = phys_to_virt(td_last->next);
+       }
+
+       return ret_val;
+}
+
 /* Frees request packet, called by gadget driver */
 static void
 udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -722,6 +805,123 @@ udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
        return finished;
 }
 
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+       struct udc_ep *ep,
+       struct udc_request *req,
+       unsigned long buf_len, gfp_t gfp_flags
+)
+{
+       unsigned long bytes = req->req.length;
+       unsigned int i;
+       dma_addr_t dma_addr;
+       struct udc_data_dma     *td = NULL;
+       struct udc_data_dma     *last = NULL;
+       unsigned long txbytes;
+       unsigned create_new_chain = 0;
+       unsigned len;
+
+       VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
+            bytes, buf_len);
+       dma_addr = DMA_DONT_USE;
+
+       /* unset L bit in first desc for OUT */
+       if (!ep->in)
+               req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+
+       /* alloc only new desc's if not already available */
+       len = req->req.length / ep->ep.maxpacket;
+       if (req->req.length % ep->ep.maxpacket)
+               len++;
+
+       if (len > req->chain_len) {
+               /* shorter chain already allocated before */
+               if (req->chain_len > 1)
+                       udc_free_dma_chain(ep->dev, req);
+               req->chain_len = len;
+               create_new_chain = 1;
+       }
+
+       td = req->td_data;
+       /* gen. required number of descriptors and buffers */
+       for (i = buf_len; i < bytes; i += buf_len) {
+               /* create or determine next desc. */
+               if (create_new_chain) {
+                       td = pci_pool_alloc(ep->dev->data_requests,
+                                           gfp_flags, &dma_addr);
+                       if (!td)
+                               return -ENOMEM;
+
+                       td->status = 0;
+               } else if (i == buf_len) {
+                       /* first td */
+                       td = (struct udc_data_dma *)phys_to_virt(
+                                               req->td_data->next);
+                       td->status = 0;
+               } else {
+                       td = (struct udc_data_dma *)phys_to_virt(last->next);
+                       td->status = 0;
+               }
+
+               if (td)
+                       td->bufptr = req->req.dma + i; /* assign buffer */
+               else
+                       break;
+
+               /* short packet ? */
+               if ((bytes - i) >= buf_len) {
+                       txbytes = buf_len;
+               } else {
+                       /* short packet */
+                       txbytes = bytes - i;
+               }
+
+               /* link td and assign tx bytes */
+               if (i == buf_len) {
+                       if (create_new_chain)
+                               req->td_data->next = dma_addr;
+                       /*
+                        * else
+                        *      req->td_data->next = virt_to_phys(td);
+                        */
+                       /* write tx bytes */
+                       if (ep->in) {
+                               /* first desc */
+                               req->td_data->status =
+                                       AMD_ADDBITS(req->td_data->status,
+                                                   ep->ep.maxpacket,
+                                                   UDC_DMA_IN_STS_TXBYTES);
+                               /* second desc */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               } else {
+                       if (create_new_chain)
+                               last->next = dma_addr;
+                       /*
+                        * else
+                        *      last->next = virt_to_phys(td);
+                        */
+                       if (ep->in) {
+                               /* write tx bytes */
+                               td->status = AMD_ADDBITS(td->status,
+                                                       txbytes,
+                                                       UDC_DMA_IN_STS_TXBYTES);
+                       }
+               }
+               last = td;
+       }
+       /* set last bit */
+       if (td) {
+               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* last desc. points to itself */
+               req->td_data_last = td;
+       }
+
+       return 0;
+}
+
 /* create/re-init a DMA descriptor or a DMA descriptor chain */
 static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
 {
@@ -846,32 +1046,6 @@ __acquires(ep->dev->lock)
        ep->halted = halted;
 }
 
-/* frees pci pool descriptors of a DMA chain */
-static int udc_free_dma_chain(struct udc *dev, struct udc_request *req)
-{
-
-       int ret_val = 0;
-       struct udc_data_dma     *td;
-       struct udc_data_dma     *td_last = NULL;
-       unsigned int i;
-
-       DBG(dev, "free chain req = %p\n", req);
-
-       /* do not free first desc., will be done by free for request */
-       td_last = req->td_data;
-       td = phys_to_virt(td_last->next);
-
-       for (i = 1; i < req->chain_len; i++) {
-
-               pci_pool_free(dev->data_requests, td,
-                               (dma_addr_t) td_last->next);
-               td_last = td;
-               td = phys_to_virt(td_last->next);
-       }
-
-       return ret_val;
-}
-
 /* Iterates to the end of a DMA chain and returns last descriptor */
 static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
 {
@@ -908,125 +1082,6 @@ static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
 
 }
 
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
-       struct udc_ep *ep,
-       struct udc_request *req,
-       unsigned long buf_len, gfp_t gfp_flags
-)
-{
-       unsigned long bytes = req->req.length;
-       unsigned int i;
-       dma_addr_t dma_addr;
-       struct udc_data_dma     *td = NULL;
-       struct udc_data_dma     *last = NULL;
-       unsigned long txbytes;
-       unsigned create_new_chain = 0;
-       unsigned len;
-
-       VDBG(ep->dev, "udc_create_dma_chain: bytes=%ld buf_len=%ld\n",
-                       bytes, buf_len);
-       dma_addr = DMA_DONT_USE;
-
-       /* unset L bit in first desc for OUT */
-       if (!ep->in)
-               req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
-
-       /* alloc only new desc's if not already available */
-       len = req->req.length / ep->ep.maxpacket;
-       if (req->req.length % ep->ep.maxpacket)
-               len++;
-
-       if (len > req->chain_len) {
-               /* shorter chain already allocated before */
-               if (req->chain_len > 1)
-                       udc_free_dma_chain(ep->dev, req);
-               req->chain_len = len;
-               create_new_chain = 1;
-       }
-
-       td = req->td_data;
-       /* gen. required number of descriptors and buffers */
-       for (i = buf_len; i < bytes; i += buf_len) {
-               /* create or determine next desc. */
-               if (create_new_chain) {
-
-                       td = pci_pool_alloc(ep->dev->data_requests,
-                                       gfp_flags, &dma_addr);
-                       if (!td)
-                               return -ENOMEM;
-
-                       td->status = 0;
-               } else if (i == buf_len) {
-                       /* first td */
-                       td = (struct udc_data_dma *) phys_to_virt(
-                                               req->td_data->next);
-                       td->status = 0;
-               } else {
-                       td = (struct udc_data_dma *) phys_to_virt(last->next);
-                       td->status = 0;
-               }
-
-
-               if (td)
-                       td->bufptr = req->req.dma + i; /* assign buffer */
-               else
-                       break;
-
-               /* short packet ? */
-               if ((bytes - i) >= buf_len) {
-                       txbytes = buf_len;
-               } else {
-                       /* short packet */
-                       txbytes = bytes - i;
-               }
-
-               /* link td and assign tx bytes */
-               if (i == buf_len) {
-                       if (create_new_chain)
-                               req->td_data->next = dma_addr;
-                       /*
-                       else
-                               req->td_data->next = virt_to_phys(td);
-                       */
-                       /* write tx bytes */
-                       if (ep->in) {
-                               /* first desc */
-                               req->td_data->status =
-                                       AMD_ADDBITS(req->td_data->status,
-                                                       ep->ep.maxpacket,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                               /* second desc */
-                               td->status = AMD_ADDBITS(td->status,
-                                                       txbytes,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                       }
-               } else {
-                       if (create_new_chain)
-                               last->next = dma_addr;
-                       /*
-                       else
-                               last->next = virt_to_phys(td);
-                       */
-                       if (ep->in) {
-                               /* write tx bytes */
-                               td->status = AMD_ADDBITS(td->status,
-                                                       txbytes,
-                                                       UDC_DMA_IN_STS_TXBYTES);
-                       }
-               }
-               last = td;
-       }
-       /* set last bit */
-       if (td) {
-               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
-               /* last desc. points to itself */
-               req->td_data_last = td;
-       }
-
-       return 0;
-}
-
 /* Enabling RX DMA */
 static void udc_set_rde(struct udc *dev)
 {
@@ -1386,6 +1441,26 @@ static int udc_get_frame(struct usb_gadget *gadget)
        return -EOPNOTSUPP;
 }
 
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+       unsigned long flags;
+       u32 tmp;
+
+       DBG(dev, "UDC initiates remote wakeup\n");
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
 /* Remote wakeup gadget interface */
 static int udc_wakeup(struct usb_gadget *gadget)
 {
@@ -1431,33 +1506,6 @@ static void make_ep_lists(struct udc *dev)
        dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
 }
 
-/* init registers at driver load time */
-static int startup_registers(struct udc *dev)
-{
-       u32 tmp;
-
-       /* init controller by soft reset */
-       udc_soft_reset(dev);
-
-       /* mask not needed interrupts */
-       udc_mask_unused_interrupts(dev);
-
-       /* put into initial config */
-       udc_basic_init(dev);
-       /* link up all endpoints */
-       udc_setup_endpoints(dev);
-
-       /* program speed */
-       tmp = readl(&dev->regs->cfg);
-       if (use_fullspeed)
-               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
-       else
-               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
-       writel(tmp, &dev->regs->cfg);
-
-       return 0;
-}
-
 /* Inits UDC context */
 static void udc_basic_init(struct udc *dev)
 {
@@ -1496,6 +1544,33 @@ static void udc_basic_init(struct udc *dev)
        dev->data_ep_queued = 0;
 }
 
+/* init registers at driver load time */
+static int startup_registers(struct udc *dev)
+{
+       u32 tmp;
+
+       /* init controller by soft reset */
+       udc_soft_reset(dev);
+
+       /* mask not needed interrupts */
+       udc_mask_unused_interrupts(dev);
+
+       /* put into initial config */
+       udc_basic_init(dev);
+       /* link up all endpoints */
+       udc_setup_endpoints(dev);
+
+       /* program speed */
+       tmp = readl(&dev->regs->cfg);
+       if (use_fullspeed)
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);
+       else
+               tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);
+       writel(tmp, &dev->regs->cfg);
+
+       return 0;
+}
+
 /* Sets initial endpoint parameters */
 static void udc_setup_endpoints(struct udc *dev)
 {
@@ -1517,7 +1592,8 @@ static void udc_setup_endpoints(struct udc *dev)
        for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
                ep = &dev->ep[tmp];
                ep->dev = dev;
-               ep->ep.name = ep_string[tmp];
+               ep->ep.name = ep_info[tmp].name;
+               ep->ep.caps = ep_info[tmp].caps;
                ep->num = tmp;
                /* txfifo size is calculated at enable time */
                ep->txfifo = dev->txfifo;
@@ -2109,7 +2185,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
                }
 
        /* DMA */
-       } else if (!ep->cancel_transfer && req != NULL) {
+       } else if (!ep->cancel_transfer && req) {
                ret_val = IRQ_HANDLED;
 
                /* check for DMA done */
@@ -3039,6 +3115,17 @@ static void udc_remove(struct udc *dev)
        udc = NULL;
 }
 
+/* free all the dma pools */
+static void free_dma_pools(struct udc *dev)
+{
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td,
+                     dev->ep[UDC_EP0OUT_IX].td_phys);
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+                     dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+       dma_pool_destroy(dev->stp_requests);
+       dma_pool_destroy(dev->data_requests);
+}
+
 /* Reset all pci context */
 static void udc_pci_remove(struct pci_dev *pdev)
 {
@@ -3048,35 +3135,19 @@ static void udc_pci_remove(struct pci_dev *pdev)
 
        usb_del_gadget_udc(&udc->gadget);
        /* gadget driver must not be registered */
-       BUG_ON(dev->driver != NULL);
+       if (WARN_ON(dev->driver))
+               return;
 
        /* dma pool cleanup */
-       if (dev->data_requests)
-               pci_pool_destroy(dev->data_requests);
-
-       if (dev->stp_requests) {
-               /* cleanup DMA desc's for ep0in */
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td_stp,
-                       dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td,
-                       dev->ep[UDC_EP0OUT_IX].td_phys);
-
-               pci_pool_destroy(dev->stp_requests);
-       }
+       free_dma_pools(dev);
 
        /* reset controller */
        writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
-       if (dev->irq_registered)
-               free_irq(pdev->irq, dev);
-       if (dev->regs)
-               iounmap(dev->regs);
-       if (dev->mem_region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-       if (dev->active)
-               pci_disable_device(pdev);
+       free_irq(pdev->irq, dev);
+       iounmap(dev->virt_addr);
+       release_mem_region(pci_resource_start(pdev, 0),
+                          pci_resource_len(pdev, 0));
+       pci_disable_device(pdev);
 
        udc_remove(dev);
 }
@@ -3101,8 +3172,7 @@ static int init_dma_pools(struct udc *dev)
                sizeof(struct udc_data_dma), 0, 0);
        if (!dev->data_requests) {
                DBG(dev, "can't get request data pool\n");
-               retval = -ENOMEM;
-               goto finished;
+               return -ENOMEM;
        }
 
        /* EP0 in dma regs = dev control regs */
@@ -3114,27 +3184,101 @@ static int init_dma_pools(struct udc *dev)
        if (!dev->stp_requests) {
                DBG(dev, "can't get stp request pool\n");
                retval = -ENOMEM;
-               goto finished;
+               goto err_create_dma_pool;
        }
        /* setup */
        td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
                                &dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-       if (td_stp == NULL) {
+       if (!td_stp) {
                retval = -ENOMEM;
-               goto finished;
+               goto err_alloc_dma;
        }
        dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
 
        /* data: 0 packets !? */
        td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
                                &dev->ep[UDC_EP0OUT_IX].td_phys);
-       if (td_data == NULL) {
+       if (!td_data) {
                retval = -ENOMEM;
-               goto finished;
+               goto err_alloc_phys;
        }
        dev->ep[UDC_EP0OUT_IX].td = td_data;
        return 0;
 
+err_alloc_phys:
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+                     dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+err_alloc_dma:
+       dma_pool_destroy(dev->stp_requests);
+       dev->stp_requests = NULL;
+err_create_dma_pool:
+       dma_pool_destroy(dev->data_requests);
+       dev->data_requests = NULL;
+       return retval;
+}
+
+/* general probe */
+static int udc_probe(struct udc *dev)
+{
+       char            tmp[128];
+       u32             reg;
+       int             retval;
+
+       /* mark timer as not initialized */
+       udc_timer.data = 0;
+       udc_pollstall_timer.data = 0;
+
+       /* device struct setup */
+       dev->gadget.ops = &udc_ops;
+
+       dev_set_name(&dev->gadget.dev, "gadget");
+       dev->gadget.name = name;
+       dev->gadget.max_speed = USB_SPEED_HIGH;
+
+       /* init registers, interrupts, ... */
+       startup_registers(dev);
+
+       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+       snprintf(tmp, sizeof(tmp), "%d", dev->irq);
+       dev_info(&dev->pdev->dev,
+                "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
+                tmp, dev->phys_addr, dev->chiprev,
+                (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
+       strcpy(tmp, UDC_DRIVER_VERSION_STRING);
+       if (dev->chiprev == UDC_HSA0_REV) {
+               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev_info(&dev->pdev->dev,
+                "driver version: %s(for Geode5536 B1)\n", tmp);
+       udc = dev;
+
+       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+                                           gadget_release);
+       if (retval)
+               goto finished;
+
+       /* timer init */
+       init_timer(&udc_timer);
+       udc_timer.function = udc_timer_function;
+       udc_timer.data = 1;
+       /* timer pollstall init */
+       init_timer(&udc_pollstall_timer);
+       udc_pollstall_timer.function = udc_pollstall_timer_function;
+       udc_pollstall_timer.data = 1;
+
+       /* set SD */
+       reg = readl(&dev->regs->ctl);
+       reg |= AMD_BIT(UDC_DEVCTL_SD);
+       writel(reg, &dev->regs->ctl);
+
+       /* print dev register info */
+       print_regs(dev);
+
+       return 0;
+
 finished:
        return retval;
 }
@@ -3158,19 +3302,14 @@ static int udc_pci_probe(
 
        /* init */
        dev = kzalloc(sizeof(struct udc), GFP_KERNEL);
-       if (!dev) {
-               retval = -ENOMEM;
-               goto finished;
-       }
+       if (!dev)
+               return -ENOMEM;
 
        /* pci setup */
        if (pci_enable_device(pdev) < 0) {
-               kfree(dev);
-               dev = NULL;
                retval = -ENODEV;
-               goto finished;
+               goto err_pcidev;
        }
-       dev->active = 1;
 
        /* PCI resource allocation */
        resource = pci_resource_start(pdev, 0);
@@ -3178,28 +3317,21 @@ static int udc_pci_probe(
 
        if (!request_mem_region(resource, len, name)) {
                dev_dbg(&pdev->dev, "pci device used already\n");
-               kfree(dev);
-               dev = NULL;
                retval = -EBUSY;
-               goto finished;
+               goto err_memreg;
        }
-       dev->mem_region = 1;
 
        dev->virt_addr = ioremap_nocache(resource, len);
-       if (dev->virt_addr == NULL) {
+       if (!dev->virt_addr) {
                dev_dbg(&pdev->dev, "start address cannot be mapped\n");
-               kfree(dev);
-               dev = NULL;
                retval = -EFAULT;
-               goto finished;
+               goto err_ioremap;
        }
 
        if (!pdev->irq) {
                dev_err(&pdev->dev, "irq not set\n");
-               kfree(dev);
-               dev = NULL;
                retval = -ENODEV;
-               goto finished;
+               goto err_irq;
        }
 
        spin_lock_init(&dev->lock);
@@ -3215,12 +3347,9 @@ static int udc_pci_probe(
 
        if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
                dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
-               kfree(dev);
-               dev = NULL;
                retval = -EBUSY;
-               goto finished;
+               goto err_irq;
        }
-       dev->irq_registered = 1;
 
        pci_set_drvdata(pdev, dev);
 
@@ -3234,7 +3363,7 @@ static int udc_pci_probe(
        if (use_dma) {
                retval = init_dma_pools(dev);
                if (retval != 0)
-                       goto finished;
+                       goto err_dma;
        }
 
        dev->phys_addr = resource;
@@ -3242,101 +3371,28 @@ static int udc_pci_probe(
        dev->pdev = pdev;
 
        /* general probing */
-       if (udc_probe(dev) == 0)
-               return 0;
-
-finished:
-       if (dev)
-               udc_pci_remove(pdev);
-       return retval;
-}
-
-/* general probe */
-static int udc_probe(struct udc *dev)
-{
-       char            tmp[128];
-       u32             reg;
-       int             retval;
-
-       /* mark timer as not initialized */
-       udc_timer.data = 0;
-       udc_pollstall_timer.data = 0;
-
-       /* device struct setup */
-       dev->gadget.ops = &udc_ops;
-
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.name = name;
-       dev->gadget.max_speed = USB_SPEED_HIGH;
-
-       /* init registers, interrupts, ... */
-       startup_registers(dev);
-
-       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
-       snprintf(tmp, sizeof tmp, "%d", dev->irq);
-       dev_info(&dev->pdev->dev,
-               "irq %s, pci mem %08lx, chip rev %02x(Geode5536 %s)\n",
-               tmp, dev->phys_addr, dev->chiprev,
-               (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1");
-       strcpy(tmp, UDC_DRIVER_VERSION_STRING);
-       if (dev->chiprev == UDC_HSA0_REV) {
-               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+       if (udc_probe(dev)) {
                retval = -ENODEV;
-               goto finished;
+               goto err_probe;
        }
-       dev_info(&dev->pdev->dev,
-               "driver version: %s(for Geode5536 B1)\n", tmp);
-       udc = dev;
-
-       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto finished;
-
-       /* timer init */
-       init_timer(&udc_timer);
-       udc_timer.function = udc_timer_function;
-       udc_timer.data = 1;
-       /* timer pollstall init */
-       init_timer(&udc_pollstall_timer);
-       udc_pollstall_timer.function = udc_pollstall_timer_function;
-       udc_pollstall_timer.data = 1;
-
-       /* set SD */
-       reg = readl(&dev->regs->ctl);
-       reg |= AMD_BIT(UDC_DEVCTL_SD);
-       writel(reg, &dev->regs->ctl);
-
-       /* print dev register info */
-       print_regs(dev);
-
        return 0;
 
-finished:
+err_probe:
+       if (use_dma)
+               free_dma_pools(dev);
+err_dma:
+       free_irq(pdev->irq, dev);
+err_irq:
+       iounmap(dev->virt_addr);
+err_ioremap:
+       release_mem_region(resource, len);
+err_memreg:
+       pci_disable_device(pdev);
+err_pcidev:
+       kfree(dev);
        return retval;
 }
 
-/* Initiates a remote wakeup */
-static int udc_remote_wakeup(struct udc *dev)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       DBG(dev, "UDC initiates remote wakeup\n");
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       tmp = readl(&dev->regs->ctl);
-       tmp |= AMD_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
 /* PCI device parameters */
 static const struct pci_device_id pci_id[] = {
        {