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>
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index ce50af9..c18068d 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2571,6 +2571,54 @@
.stop = ci13xxx_stop,
};
+static int init_eps(struct ci13xxx *udc)
+{
+ int retval = 0, i, j;
+
+ for (i = 0; i < udc->hw_ep_max/2; i++)
+ for (j = RX; j <= TX; j++) {
+ int k = i + j * udc->hw_ep_max/2;
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
+
+ scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
+ (j == TX) ? "in" : "out");
+
+ mEp->udc = udc;
+ mEp->lock = &udc->lock;
+ mEp->device = &udc->gadget.dev;
+ mEp->td_pool = udc->td_pool;
+
+ mEp->ep.name = mEp->name;
+ mEp->ep.ops = &usb_ep_ops;
+ mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+
+ INIT_LIST_HEAD(&mEp->qh.queue);
+ mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
+ &mEp->qh.dma);
+ if (mEp->qh.ptr == NULL)
+ retval = -ENOMEM;
+ else
+ memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
+
+ /*
+ * set up shorthands for ep0 out and in endpoints,
+ * don't add to gadget's ep_list
+ */
+ if (i == 0) {
+ if (j == RX)
+ udc->ep0out = mEp;
+ else
+ udc->ep0in = mEp;
+
+ continue;
+ }
+
+ list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
+ }
+
+ return retval;
+}
+
/**
* ci13xxx_start: register a gadget driver
* @driver: the driver being registered
@@ -2599,75 +2647,12 @@
else if (udc->driver != NULL)
return -EBUSY;
- /* alloc resources */
- udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev,
- sizeof(struct ci13xxx_qh),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->qh_pool == NULL)
- return -ENOMEM;
-
- udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev,
- sizeof(struct ci13xxx_td),
- 64, CI13XXX_PAGE_SIZE);
- if (udc->td_pool == NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- return -ENOMEM;
- }
-
spin_lock_irqsave(&udc->lock, flags);
dev_info(udc->dev, "hw_ep_max = %d\n", udc->hw_ep_max);
udc->gadget.dev.driver = NULL;
- retval = 0;
- for (i = 0; i < udc->hw_ep_max/2; i++) {
- for (j = RX; j <= TX; j++) {
- int k = i + j * udc->hw_ep_max/2;
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k];
-
- scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i,
- (j == TX) ? "in" : "out");
-
- mEp->udc = udc;
- mEp->lock = &udc->lock;
- mEp->device = &udc->gadget.dev;
- mEp->td_pool = udc->td_pool;
-
- mEp->ep.name = mEp->name;
- mEp->ep.ops = &usb_ep_ops;
- mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
-
- INIT_LIST_HEAD(&mEp->qh.queue);
- spin_unlock_irqrestore(&udc->lock, flags);
- mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL,
- &mEp->qh.dma);
- spin_lock_irqsave(&udc->lock, flags);
- if (mEp->qh.ptr == NULL)
- retval = -ENOMEM;
- else
- memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr));
-
- /*
- * set up shorthands for ep0 out and in endpoints,
- * don't add to gadget's ep_list
- */
- if (i == 0) {
- if (j == RX)
- udc->ep0out = mEp;
- else
- udc->ep0in = mEp;
-
- continue;
- }
-
- list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
- }
- }
- if (retval)
- goto done;
-
spin_unlock_irqrestore(&udc->lock, flags);
udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
retval = usb_ep_enable(&udc->ep0out->ep);
@@ -2680,7 +2665,6 @@
return retval;
spin_lock_irqsave(&udc->lock, flags);
- udc->gadget.ep0 = &udc->ep0in->ep;
/* bind gadget */
driver->driver.bus = NULL;
udc->gadget.dev.driver = &driver->driver;
@@ -2754,32 +2738,10 @@
spin_lock_irqsave(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
-
- /* free resources */
- for (i = 0; i < udc->hw_ep_max; i++) {
- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
-
- if (mEp->num)
- list_del_init(&mEp->ep.ep_list);
-
- if (mEp->qh.ptr != NULL)
- dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
- }
-
- udc->gadget.ep0 = NULL;
udc->driver = NULL;
spin_unlock_irqrestore(&udc->lock, flags);
- if (udc->td_pool != NULL) {
- dma_pool_destroy(udc->td_pool);
- udc->td_pool = NULL;
- }
- if (udc->qh_pool != NULL) {
- dma_pool_destroy(udc->qh_pool);
- udc->qh_pool = NULL;
- }
-
return 0;
}
@@ -2920,16 +2882,39 @@
udc->dev = dev;
+ /* alloc resources */
+ udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
+ sizeof(struct ci13xxx_qh),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->qh_pool == NULL) {
+ retval = -ENOMEM;
+ goto free_udc;
+ }
+
+ udc->td_pool = dma_pool_create("ci13xxx_td", dev,
+ sizeof(struct ci13xxx_td),
+ 64, CI13XXX_PAGE_SIZE);
+ if (udc->td_pool == NULL) {
+ retval = -ENOMEM;
+ goto free_qh_pool;
+ }
+
retval = hw_device_init(udc, regs, driver->capoffset);
if (retval < 0)
- goto free_udc;
+ goto free_pools;
+
+ retval = init_eps(udc);
+ if (retval)
+ goto free_pools;
+
+ udc->gadget.ep0 = &udc->ep0in->ep;
udc->transceiver = usb_get_transceiver();
if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
if (udc->transceiver == NULL) {
retval = -ENODEV;
- goto free_udc;
+ goto free_pools;
}
}
@@ -2984,6 +2969,10 @@
put_transceiver:
if (udc->transceiver)
usb_put_transceiver(udc->transceiver);
+free_pools:
+ dma_pool_destroy(udc->td_pool);
+free_qh_pool:
+ dma_pool_destroy(udc->qh_pool);
free_udc:
kfree(udc);
_udc = NULL;
@@ -2998,12 +2987,22 @@
static void udc_remove(void)
{
struct ci13xxx *udc = _udc;
+ int i;
if (udc == NULL)
return;
usb_del_gadget_udc(&udc->gadget);
+ for (i = 0; i < udc->hw_ep_max; i++) {
+ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
+
+ dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+ }
+
+ dma_pool_destroy(udc->td_pool);
+ dma_pool_destroy(udc->qh_pool);
+
if (udc->transceiver) {
otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
usb_put_transceiver(udc->transceiver);