|
@@ -2571,58 +2571,11 @@ static const struct usb_gadget_ops usb_gadget_ops = {
|
|
|
.stop = ci13xxx_stop,
|
|
|
};
|
|
|
|
|
|
-/**
|
|
|
- * ci13xxx_start: register a gadget driver
|
|
|
- * @driver: the driver being registered
|
|
|
- * @bind: the driver's bind callback
|
|
|
- *
|
|
|
- * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
|
|
|
- * Interrupts are enabled here.
|
|
|
- */
|
|
|
-static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|
|
- int (*bind)(struct usb_gadget *))
|
|
|
+static int init_eps(struct ci13xxx *udc)
|
|
|
{
|
|
|
- struct ci13xxx *udc = _udc;
|
|
|
- unsigned long flags;
|
|
|
- int i, j;
|
|
|
- int retval = -ENOMEM;
|
|
|
-
|
|
|
- trace(udc->dev, "%p", driver);
|
|
|
-
|
|
|
- if (driver == NULL ||
|
|
|
- bind == NULL ||
|
|
|
- driver->setup == NULL ||
|
|
|
- driver->disconnect == NULL)
|
|
|
- return -EINVAL;
|
|
|
- else if (udc == NULL)
|
|
|
- return -ENODEV;
|
|
|
- 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;
|
|
|
+ int retval = 0, i, j;
|
|
|
|
|
|
- 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 (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];
|
|
@@ -2640,10 +2593,8 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|
|
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);
|
|
|
+ &mEp->qh.dma);
|
|
|
if (mEp->qh.ptr == NULL)
|
|
|
retval = -ENOMEM;
|
|
|
else
|
|
@@ -2664,9 +2615,43 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|
|
|
|
|
list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
|
|
|
}
|
|
|
- }
|
|
|
- if (retval)
|
|
|
- goto done;
|
|
|
+
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ci13xxx_start: register a gadget driver
|
|
|
+ * @driver: the driver being registered
|
|
|
+ * @bind: the driver's bind callback
|
|
|
+ *
|
|
|
+ * Check ci13xxx_start() at <linux/usb/gadget.h> for details.
|
|
|
+ * Interrupts are enabled here.
|
|
|
+ */
|
|
|
+static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|
|
+ int (*bind)(struct usb_gadget *))
|
|
|
+{
|
|
|
+ struct ci13xxx *udc = _udc;
|
|
|
+ unsigned long flags;
|
|
|
+ int i, j;
|
|
|
+ int retval = -ENOMEM;
|
|
|
+
|
|
|
+ trace(udc->dev, "%p", driver);
|
|
|
+
|
|
|
+ if (driver == NULL ||
|
|
|
+ bind == NULL ||
|
|
|
+ driver->setup == NULL ||
|
|
|
+ driver->disconnect == NULL)
|
|
|
+ return -EINVAL;
|
|
|
+ else if (udc == NULL)
|
|
|
+ return -ENODEV;
|
|
|
+ else if (udc->driver != NULL)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&udc->lock, flags);
|
|
|
+
|
|
|
+ dev_info(udc->dev, "hw_ep_max = %d\n", udc->hw_ep_max);
|
|
|
+
|
|
|
+ udc->gadget.dev.driver = NULL;
|
|
|
|
|
|
spin_unlock_irqrestore(&udc->lock, flags);
|
|
|
udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
|
|
@@ -2680,7 +2665,6 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
|
|
|
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 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
|
|
|
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 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
|
|
|
|
|
|
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 @@ unreg_device:
|
|
|
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 @@ free_udc:
|
|
|
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);
|