summaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2012-05-08 16:29:03 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-09 18:00:26 -0400
commit790c2d52b24e2ecd00ca014821c1adc41be2ac94 (patch)
treeaec4892d6b5d57c6a2a0e35d4411feee0a18a118 /drivers/usb/gadget
parent0f089094cde53a2639c965cd3bd3fdef27006446 (diff)
usb: gadget: ci13xxx: move endpoint (de-)initialization to probe/remove
Currently, endpoints are initialized in gadget start/stop methods, however for the new style gadgets it is expected that bind() can be called before controller's start(), and we need endpoints already initialized at that point. So, move endpoint initialization to controller's probe before we switch to the "new style" gadget framework. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/ci13xxx_udc.c161
1 files changed, 80 insertions, 81 deletions
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index ce50af97ab3f..c18068df73a1 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2571,58 +2571,11 @@ static const struct usb_gadget_ops usb_gadget_ops = {
2571 .stop = ci13xxx_stop, 2571 .stop = ci13xxx_stop,
2572}; 2572};
2573 2573
2574/** 2574static int init_eps(struct ci13xxx *udc)
2575 * ci13xxx_start: register a gadget driver
2576 * @driver: the driver being registered
2577 * @bind: the driver's bind callback
2578 *
2579 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
2580 * Interrupts are enabled here.
2581 */
2582static int ci13xxx_start(struct usb_gadget_driver *driver,
2583 int (*bind)(struct usb_gadget *))
2584{ 2575{
2585 struct ci13xxx *udc = _udc; 2576 int retval = 0, i, j;
2586 unsigned long flags;
2587 int i, j;
2588 int retval = -ENOMEM;
2589
2590 trace(udc->dev, "%p", driver);
2591
2592 if (driver == NULL ||
2593 bind == NULL ||
2594 driver->setup == NULL ||
2595 driver->disconnect == NULL)
2596 return -EINVAL;
2597 else if (udc == NULL)
2598 return -ENODEV;
2599 else if (udc->driver != NULL)
2600 return -EBUSY;
2601
2602 /* alloc resources */
2603 udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
2604 sizeof(struct ci13xxx_qh),
2605 64, CI13XXX_PAGE_SIZE);
2606 if (udc->qh_pool == NULL)
2607 return -ENOMEM;
2608 2577
2609 udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev, 2578 for (i = 0; i < udc->hw_ep_max/2; i++)
2610 sizeof(struct ci13xxx_td),
2611 64, CI13XXX_PAGE_SIZE);
2612 if (udc->td_pool == NULL) {
2613 dma_pool_destroy(udc->qh_pool);
2614 udc->qh_pool = NULL;
2615 return -ENOMEM;
2616 }
2617
2618 spin_lock_irqsave(&udc->lock, flags);
2619
2620 dev_info(udc->dev, "hw_ep_max = %d\n", udc->hw_ep_max);
2621
2622 udc->gadget.dev.driver = NULL;
2623
2624 retval = 0;
2625 for (i = 0; i < udc->hw_ep_max/2; i++) {
2626 for (j = RX; j <= TX; j++) { 2579 for (j = RX; j <= TX; j++) {
2627 int k = i + j * udc->hw_ep_max/2; 2580 int k = i + j * udc->hw_ep_max/2;
2628 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; 2581 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
@@ -2640,10 +2593,8 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
2640 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; 2593 mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
2641 2594
2642 INIT_LIST_HEAD(&mEp->qh.queue); 2595 INIT_LIST_HEAD(&mEp->qh.queue);
2643 spin_unlock_irqrestore(&udc->lock, flags);
2644 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, 2596 mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
2645 &mEp->qh.dma); 2597 &mEp->qh.dma);
2646 spin_lock_irqsave(&udc->lock, flags);
2647 if (mEp->qh.ptr == NULL) 2598 if (mEp->qh.ptr == NULL)
2648 retval = -ENOMEM; 2599 retval = -ENOMEM;
2649 else 2600 else
@@ -2664,9 +2615,43 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
2664 2615
2665 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); 2616 list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
2666 } 2617 }
2667 } 2618
2668 if (retval) 2619 return retval;
2669 goto done; 2620}
2621
2622/**
2623 * ci13xxx_start: register a gadget driver
2624 * @driver: the driver being registered
2625 * @bind: the driver's bind callback
2626 *
2627 * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
2628 * Interrupts are enabled here.
2629 */
2630static int ci13xxx_start(struct usb_gadget_driver *driver,
2631 int (*bind)(struct usb_gadget *))
2632{
2633 struct ci13xxx *udc = _udc;
2634 unsigned long flags;
2635 int i, j;
2636 int retval = -ENOMEM;
2637
2638 trace(udc->dev, "%p", driver);
2639
2640 if (driver == NULL ||
2641 bind == NULL ||
2642 driver->setup == NULL ||
2643 driver->disconnect == NULL)
2644 return -EINVAL;
2645 else if (udc == NULL)
2646 return -ENODEV;
2647 else if (udc->driver != NULL)
2648 return -EBUSY;
2649
2650 spin_lock_irqsave(&udc->lock, flags);
2651
2652 dev_info(udc->dev, "hw_ep_max = %d\n", udc->hw_ep_max);
2653
2654 udc->gadget.dev.driver = NULL;
2670 2655
2671 spin_unlock_irqrestore(&udc->lock, flags); 2656 spin_unlock_irqrestore(&udc->lock, flags);
2672 udc->ep0out->ep.desc = &ctrl_endpt_out_desc; 2657 udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
@@ -2680,7 +2665,6 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
2680 return retval; 2665 return retval;
2681 spin_lock_irqsave(&udc->lock, flags); 2666 spin_lock_irqsave(&udc->lock, flags);
2682 2667
2683 udc->gadget.ep0 = &udc->ep0in->ep;
2684 /* bind gadget */ 2668 /* bind gadget */
2685 driver->driver.bus = NULL; 2669 driver->driver.bus = NULL;
2686 udc->gadget.dev.driver = &driver->driver; 2670 udc->gadget.dev.driver = &driver->driver;
@@ -2754,32 +2738,10 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
2754 spin_lock_irqsave(&udc->lock, flags); 2738 spin_lock_irqsave(&udc->lock, flags);
2755 2739
2756 udc->gadget.dev.driver = NULL; 2740 udc->gadget.dev.driver = NULL;
2757
2758 /* free resources */
2759 for (i = 0; i < udc->hw_ep_max; i++) {
2760 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2761
2762 if (mEp->num)
2763 list_del_init(&mEp->ep.ep_list);
2764
2765 if (mEp->qh.ptr != NULL)
2766 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
2767 }
2768
2769 udc->gadget.ep0 = NULL;
2770 udc->driver = NULL; 2741 udc->driver = NULL;
2771 2742
2772 spin_unlock_irqrestore(&udc->lock, flags); 2743 spin_unlock_irqrestore(&udc->lock, flags);
2773 2744
2774 if (udc->td_pool != NULL) {
2775 dma_pool_destroy(udc->td_pool);
2776 udc->td_pool = NULL;
2777 }
2778 if (udc->qh_pool != NULL) {
2779 dma_pool_destroy(udc->qh_pool);
2780 udc->qh_pool = NULL;
2781 }
2782
2783 return 0; 2745 return 0;
2784} 2746}
2785 2747
@@ -2920,16 +2882,39 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
2920 2882
2921 udc->dev = dev; 2883 udc->dev = dev;
2922 2884
2885 /* alloc resources */
2886 udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
2887 sizeof(struct ci13xxx_qh),
2888 64, CI13XXX_PAGE_SIZE);
2889 if (udc->qh_pool == NULL) {
2890 retval = -ENOMEM;
2891 goto free_udc;
2892 }
2893
2894 udc->td_pool = dma_pool_create("ci13xxx_td", dev,
2895 sizeof(struct ci13xxx_td),
2896 64, CI13XXX_PAGE_SIZE);
2897 if (udc->td_pool == NULL) {
2898 retval = -ENOMEM;
2899 goto free_qh_pool;
2900 }
2901
2923 retval = hw_device_init(udc, regs, driver->capoffset); 2902 retval = hw_device_init(udc, regs, driver->capoffset);
2924 if (retval < 0) 2903 if (retval < 0)
2925 goto free_udc; 2904 goto free_pools;
2905
2906 retval = init_eps(udc);
2907 if (retval)
2908 goto free_pools;
2909
2910 udc->gadget.ep0 = &udc->ep0in->ep;
2926 2911
2927 udc->transceiver = usb_get_transceiver(); 2912 udc->transceiver = usb_get_transceiver();
2928 2913
2929 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { 2914 if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
2930 if (udc->transceiver == NULL) { 2915 if (udc->transceiver == NULL) {
2931 retval = -ENODEV; 2916 retval = -ENODEV;
2932 goto free_udc; 2917 goto free_pools;
2933 } 2918 }
2934 } 2919 }
2935 2920
@@ -2984,6 +2969,10 @@ unreg_device:
2984put_transceiver: 2969put_transceiver:
2985 if (udc->transceiver) 2970 if (udc->transceiver)
2986 usb_put_transceiver(udc->transceiver); 2971 usb_put_transceiver(udc->transceiver);
2972free_pools:
2973 dma_pool_destroy(udc->td_pool);
2974free_qh_pool:
2975 dma_pool_destroy(udc->qh_pool);
2987free_udc: 2976free_udc:
2988 kfree(udc); 2977 kfree(udc);
2989 _udc = NULL; 2978 _udc = NULL;
@@ -2998,12 +2987,22 @@ free_udc:
2998static void udc_remove(void) 2987static void udc_remove(void)
2999{ 2988{
3000 struct ci13xxx *udc = _udc; 2989 struct ci13xxx *udc = _udc;
2990 int i;
3001 2991
3002 if (udc == NULL) 2992 if (udc == NULL)
3003 return; 2993 return;
3004 2994
3005 usb_del_gadget_udc(&udc->gadget); 2995 usb_del_gadget_udc(&udc->gadget);
3006 2996
2997 for (i = 0; i < udc->hw_ep_max; i++) {
2998 struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
2999
3000 dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
3001 }
3002
3003 dma_pool_destroy(udc->td_pool);
3004 dma_pool_destroy(udc->qh_pool);
3005
3007 if (udc->transceiver) { 3006 if (udc->transceiver) {
3008 otg_set_peripheral(udc->transceiver->otg, &udc->gadget); 3007 otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
3009 usb_put_transceiver(udc->transceiver); 3008 usb_put_transceiver(udc->transceiver);