[RFC v3 11/11] usb: gadget: ci13xxx: convert to new style

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


In order to function as a "newstyle" udc, move endpoint (de-)initialization
from gadget's start/stop to platform driver's probe/remove. Since there is
no need in the global _udc pointer, remove it.

Signed-off-by: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx>
---
 drivers/usb/gadget/ci13xxx_udc.c |  248 ++++++++++++++++----------------------
 1 file changed, 104 insertions(+), 144 deletions(-)

diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index bca2afe..f9ff9e0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -96,9 +96,6 @@ ctrl_endpt_in_desc = {
 	.wMaxPacketSize  = cpu_to_le16(CTRL_PAYLOAD_MAX),
 };
 
-/* UDC descriptor */
-static struct ci13xxx *_udc;
-
 /* Interrupt statistics */
 #define ISR_MASK   0x1F
 static struct {
@@ -1679,7 +1676,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
 	usb_ep_fifo_flush(&udc->ep0out->ep);
 	usb_ep_fifo_flush(&udc->ep0in->ep);
 
-	udc->driver->disconnect(gadget);
+	if (udc->driver)
+		udc->driver->disconnect(gadget);
 
 	/* make sure to disable all endpoints */
 	gadget_for_each_ep(ep, gadget) {
@@ -1789,7 +1787,7 @@ __acquires(mEp->lock)
 
 	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 		/* Assume that device is bus powered for now. */
-		*(u16 *)req->buf = _udc->remote_wakeup << 1;
+		*(u16 *)req->buf = udc->remote_wakeup << 1;
 		retval = 0;
 	} else if ((setup->bRequestType & USB_RECIP_MASK) \
 		   == USB_RECIP_ENDPOINT) {
@@ -1896,7 +1894,7 @@ __acquires(mEp->lock)
 			spin_unlock(mEp->lock);
 			if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
 					mReq->req.length)
-				mEpTemp = _udc->ep0in;
+				mEpTemp = mEp->udc->ep0in;
 			mReq->req.complete(&mEpTemp->ep, &mReq->req);
 			spin_lock(mEp->lock);
 		}
@@ -2277,6 +2275,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 {
 	struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
 	struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+	struct ci13xxx *udc = mEp->udc;
 	int retval = 0;
 	unsigned long flags;
 
@@ -2289,8 +2288,8 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 
 	if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
 		if (req->length)
-			mEp = (_udc->ep0_dir == RX) ?
-				_udc->ep0out : _udc->ep0in;
+			mEp = (udc->ep0_dir == RX) ?
+			       udc->ep0out : udc->ep0in;
 		if (!list_empty(&mEp->qh.queue)) {
 			_ep_nuke(mEp);
 			retval = -EOVERFLOW;
@@ -2556,9 +2555,10 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
 	return -ENOTSUPP;
 }
 
-static int ci13xxx_start(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *));
-static int ci13xxx_stop(struct usb_gadget_driver *driver);
+static int ci13xxx_start(struct usb_gadget *gadget,
+			 struct usb_gadget_driver *driver);
+static int ci13xxx_stop(struct usb_gadget *gadget,
+			struct usb_gadget_driver *driver);
 /**
  * Device operations part of the API to the USB controller hardware,
  * which don't involve endpoints (or i/o)
@@ -2568,62 +2568,15 @@ static const struct usb_gadget_ops usb_gadget_ops = {
 	.vbus_session	= ci13xxx_vbus_session,
 	.wakeup		= ci13xxx_wakeup,
 	.vbus_draw	= ci13xxx_vbus_draw,
-	.start		= ci13xxx_start,
-	.stop		= ci13xxx_stop,
+	.udc_start	= ci13xxx_start,
+	.udc_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;
-
-	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;
-	}
+	int retval = 0, i, j;
 
-	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];
@@ -2641,10 +2594,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
@@ -2665,11 +2616,30 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
 
 			list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list);
 		}
-	}
-	if (retval)
-		goto done;
 
-	spin_unlock_irqrestore(&udc->lock, flags);
+	return retval;
+}
+
+/**
+ * ci13xxx_start: register a gadget driver
+ * @gadget: our gadget
+ * @driver: the driver being registered
+ *
+ * Interrupts are enabled here.
+ */
+static int ci13xxx_start(struct usb_gadget *gadget,
+			 struct usb_gadget_driver *driver)
+{
+	struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+	unsigned long flags;
+	int retval = -ENOMEM;
+
+	trace("%p", driver);
+
+	if (driver->disconnect == NULL)
+		return -EINVAL;
+
+
 	udc->ep0out->ep.desc = &ctrl_endpt_out_desc;
 	retval = usb_ep_enable(&udc->ep0out->ep);
 	if (retval)
@@ -2681,20 +2651,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;
-
-	spin_unlock_irqrestore(&udc->lock, flags);
-	retval = bind(&udc->gadget);                /* MAY SLEEP */
-	spin_lock_irqsave(&udc->lock, flags);
-
-	if (retval) {
-		udc->gadget.dev.driver = NULL;
-		goto done;
-	}
-
 	udc->driver = driver;
 	pm_runtime_get_sync(&udc->gadget.dev);
 	if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
@@ -2718,23 +2674,15 @@ static int ci13xxx_start(struct usb_gadget_driver *driver,
 
 /**
  * ci13xxx_stop: unregister a gadget driver
- *
- * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details
  */
-static int ci13xxx_stop(struct usb_gadget_driver *driver)
+static int ci13xxx_stop(struct usb_gadget *gadget,
+			struct usb_gadget_driver *driver)
 {
-	struct ci13xxx *udc = _udc;
-	unsigned long i, flags;
+	struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget);
+	unsigned long flags;
 
 	trace(udc->dev, "%p", driver);
 
-	if (driver             == NULL ||
-	    driver->unbind     == NULL ||
-	    driver->setup      == NULL ||
-	    driver->disconnect == NULL ||
-	    driver             != udc->driver)
-		return -EINVAL;
-
 	spin_lock_irqsave(&udc->lock, flags);
 
 	if (!(udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) ||
@@ -2743,43 +2691,14 @@ 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);
+		udc->driver = NULL;
 		spin_unlock_irqrestore(&udc->lock, flags);
 		_gadget_stop_activity(&udc->gadget);
 		spin_lock_irqsave(&udc->lock, flags);
 		pm_runtime_put(&udc->gadget.dev);
 	}
 
-	/* unbind gadget */
 	spin_unlock_irqrestore(&udc->lock, flags);
-	driver->unbind(&udc->gadget);               /* MAY SLEEP */
-	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;
 }
@@ -2795,7 +2714,7 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
  */
 static irqreturn_t udc_irq(int irq, void *data)
 {
-	struct ci13xxx *udc = _udc;
+	struct ci13xxx *udc = data;
 	irqreturn_t retval;
 	u32 intr;
 
@@ -2885,7 +2804,7 @@ static void udc_release(struct device *dev)
  * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask
  */
 static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
-		     void __iomem *regs)
+		     void __iomem *regs, struct ci13xxx **_udc)
 {
 	struct ci13xxx *udc;
 	int retval = 0;
@@ -2911,7 +2830,6 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
 	udc->gadget.name         = driver->name;
 
 	INIT_LIST_HEAD(&udc->gadget.ep_list);
-	udc->gadget.ep0 = NULL;
 
 	dev_set_name(&udc->gadget.dev, "gadget");
 	udc->gadget.dev.dma_mask = dev->dma_mask;
@@ -2921,16 +2839,42 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
 
 	udc->dev = dev;
 
-	retval = hw_device_init(udc, regs, driver->capoffset);
-	if (retval < 0)
+	/* 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) {
+		trace(dev, "hw_device_init failed\n");
+		goto free_pools;
+	}
+	trace(dev, "hw_device_init succeeded\n");
+
+	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;
 		}
 	}
 
@@ -2966,7 +2910,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
 	pm_runtime_no_callbacks(&udc->gadget.dev);
 	pm_runtime_enable(&udc->gadget.dev);
 
-	_udc = udc;
+	*_udc = udc;
 	return retval;
 
 remove_trans:
@@ -2985,9 +2929,13 @@ 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;
+	*_udc = NULL;
 	return retval;
 }
 
@@ -2996,15 +2944,24 @@ free_udc:
  *
  * No interrupts active, the IRQ has been released
  */
-static void udc_remove(void)
+static void udc_remove(struct ci13xxx *udc)
 {
-	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);
@@ -3016,13 +2973,13 @@ static void udc_remove(void)
 
 	kfree(udc->hw_bank.regmap);
 	kfree(udc);
-	_udc = NULL;
 }
 
 static int __devinit ci_udc_probe(struct platform_device *pdev)
 {
 	struct device	*dev = &pdev->dev;
 	struct ci13xxx_udc_driver *driver = dev->platform_data;
+	struct ci13xxx	*udc;
 	struct resource	*res;
 	void __iomem	*base;
 	int		ret;
@@ -3044,30 +3001,33 @@ static int __devinit ci_udc_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
-	ret = udc_probe(driver, dev, base);
+	ret = udc_probe(driver, dev, base, &udc);
 	if (ret)
 		return ret;
 
-	_udc->irq = platform_get_irq(pdev, 0);
-	if (_udc->irq < 0) {
+	udc->irq = platform_get_irq(pdev, 0);
+	if (udc->irq < 0) {
 		dev_err(dev, "missing IRQ\n");
 		ret = -ENODEV;
 		goto out;
 	}
 
-	ret = request_irq(_udc->irq, udc_irq, IRQF_SHARED, driver->name, _udc);
+	platform_set_drvdata(pdev, udc);
+	ret = request_irq(udc->irq, udc_irq, IRQF_SHARED, driver->name, udc);
 
 out:
 	if (ret)
-		udc_remove();
+		udc_remove(udc);
 
 	return ret;
 }
 
 static int __devexit ci_udc_remove(struct platform_device *pdev)
 {
-	free_irq(_udc->irq, _udc);
-	udc_remove();
+	struct ci13xxx *udc = platform_get_drvdata(pdev);
+
+	free_irq(udc->irq, udc);
+	udc_remove(udc);
 
 	return 0;
 }
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


B and H Foto and Electronics Corp.

[Linux Media]     [Video for Linux]     [Linux Input]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]     [More Archives]

Add to Google Powered by Linux