Peter Chen <peter.c...@freescale.com> writes:

> On Thu, Jan 24, 2013 at 04:35:30PM +0200, Alexander Shishkin wrote:
>> Peter Chen <peter.c...@freescale.com> writes:
>> 
>> > - Create init/destroy API for probe and remove
>> > - start/stop API are only used otg id switch process
>> > - Create the gadget at ci_hdrc_probe if the gadget is supported
>> > at that port, the main purpose for this is to avoid gadget module
>> > load fail at init.rc
>> 
>> I don't think it's necessary to mention android-specific init scripts
>> here in our patches.
>
> Ok, will just mention init script.
>> 
>> >  
>> > +static inline void ci_role_destroy(struct ci13xxx *ci)
>> > +{
>> > +  enum ci_role role = ci->role;
>> > +
>> > +  if (role == CI_ROLE_END)
>> > +          return;
>> > +
>> > +  ci->role = CI_ROLE_END;
>> > +
>> > +  ci->roles[role]->destroy(ci);
>> > +}
>> 
>> What does this do? It should take role an a parameter, at least. Or it
>> can be called ci_roles_destroy() and, well, destroy all the roles. Now
>> we're in a situation where we destroy one.
> Yes, this function has some problems, I suggest just call two lines at
> ci_role_destory, do you think so?
>
>       ci->roles[role]->destroy(ci);
>       ci->role = CI_ROLE_END;

I just don't see why it's needed at all. See below.

>> 
>> The idea is that, with this api, we can (and should) have both roles
>> allocated all the time, but only one role start()'ed.
>> 
>> What we can do here is move the udc's .init() code to
>> ci_hdrc_gadget_init() and add a complementary ci_hdrc_gadget_destroy(),
>> which we call in ci_hdrc_remove() and probe's error path. And we can
>> probably do something similar for the host, or just leave it as it is
>> now. Seems simpler to me.
> Yes, current code has bug that it should call ci_role_destroy at probe's
> error path.
> For your comments, it still needs to add destory function for udc which will
> be called at core.c. I still prefer current way due to below reasons:
>
> - It can keep ci_hdrc_gadget_init() clean
> - .init and .remove are different logical function with .start and .stop.
> The .init and .remove are used for create and destroy, .start and .stop
> are used at id role switch.

True, and we can keep it that way: (again, untested)

---cut---
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 342b430..36f495a 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -67,18 +67,14 @@ enum ci_role {
 
 /**
  * struct ci_role_driver - host/gadget role driver
- * init: init this role (used at module probe)
  * start: start this role (used at id switch)
  * stop: stop this role (used at id switch)
- * destroy: destroy this role (used at module remove)
  * irq: irq handler for this role
  * name: role name string (host/gadget)
  */
 struct ci_role_driver {
-       int             (*init)(struct ci13xxx *);
        int             (*start)(struct ci13xxx *);
        void            (*stop)(struct ci13xxx *);
-       void            (*destroy)(struct ci13xxx *);
        irqreturn_t     (*irq)(struct ci13xxx *);
        const char      *name;
 };
@@ -212,17 +208,6 @@ static inline void ci_role_stop(struct ci13xxx *ci)
        ci->roles[role]->stop(ci);
 }
 
-static inline void ci_role_destroy(struct ci13xxx *ci)
-{
-       enum ci_role role = ci->role;
-
-       if (role == CI_ROLE_END)
-               return;
-
-       ci->role = CI_ROLE_END;
-
-       ci->roles[role]->destroy(ci);
-}
 /******************************************************************************
  * REGISTERS
  *****************************************************************************/
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index a61e759..83f35fa 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -402,6 +402,12 @@ static ssize_t store_role(struct device *dev, struct 
device_attribute *attr,
        if (ret)
                return ret;
 
+       /*
+        * there won't be an interrupt in case of manual switching,
+        * so we need to check vbus session manually
+        */
+       ci_handle_vbus_change(ci);
+
        return count;
 }
 
@@ -592,30 +598,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 
        otgsc = hw_read(ci, OP_OTGSC, ~0);
 
-       /*
-        * If the gadget is supported, call its init unconditionally,
-        * We need to support load gadget module at init.rc.
-        */
-       if (ci->roles[CI_ROLE_GADGET]) {
-               ret = ci->roles[CI_ROLE_GADGET]->init(ci);
-               if (ret) {
-                       dev_err(dev, "can't init %s role, ret=%d\n",
-                                       ci_role(ci)->name, ret);
-                       ret = -ENODEV;
-                       goto rm_wq;
-               }
-       }
-
-       if (ci->role == CI_ROLE_HOST) {
-               ret = ci->roles[CI_ROLE_HOST]->init(ci);
-               if (ret) {
-                       dev_err(dev, "can't init %s role, ret=%d\n",
-                                       ci_role(ci)->name, ret);
-                       ret = -ENODEV;
-                       goto rm_wq;
-               }
-       }
-
        platform_set_drvdata(pdev, ci);
        ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name,
                          ci);
@@ -626,6 +608,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        if (ret)
                goto rm_attr;
 
+       ci_role_start(ci, ci->role);
+
        /* Handle the situation that usb device at the MicroB to A cable */
        if (ci->is_otg && !(otgsc & OTGSC_ID))
                queue_delayed_work(ci->wq, &ci->dwork, msecs_to_jiffies(500));
@@ -651,7 +635,8 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        destroy_workqueue(ci->wq);
        device_remove_file(ci->dev, &dev_attr_role);
        free_irq(ci->irq, ci);
-       ci_role_destroy(ci);
+       ci_hdrc_gadget_destroy(ci);
+       ci_hdrc_host_destroy(ci);
 
        return 0;
 }
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 7f4538c..ead3158 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -95,10 +95,8 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
        if (!rdrv)
                return -ENOMEM;
 
-       rdrv->init      = host_start;
        rdrv->start     = host_start;
        rdrv->stop      = host_stop;
-       rdrv->destroy   = host_stop;
        rdrv->irq       = host_irq;
        rdrv->name      = "host";
        ci->roles[CI_ROLE_HOST] = rdrv;
@@ -107,3 +105,9 @@ int ci_hdrc_host_init(struct ci13xxx *ci)
 
        return 0;
 }
+
+void ci_hdrc_host_destroy(struct ci13xxx *ci)
+{
+       if (ci->role == CI_ROLE_HOST)
+               host_stop(ci);
+}
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
index 761fb1f..2e529be 100644
--- a/drivers/usb/chipidea/host.h
+++ b/drivers/usb/chipidea/host.h
@@ -4,6 +4,7 @@
 #ifdef CONFIG_USB_CHIPIDEA_HOST
 
 int ci_hdrc_host_init(struct ci13xxx *ci);
+void ci_hdrc_host_destroy(struct ci13xxx *ci);
 
 #else
 
@@ -12,6 +13,10 @@ static inline int ci_hdrc_host_init(struct ci13xxx *ci)
        return -ENXIO;
 }
 
+static void ci_hdrc_host_destroy(struct ci13xxx *ci)
+{
+}
+
 #endif
 
 #endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 38446de..38b06ac 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1750,10 +1750,10 @@ static int udc_start(struct ci13xxx *ci)
         * - Enable vbus detect
         * - If it has already connected to host, notify udc
         */
-       if (ci->role == CI_ROLE_GADGET) {
+       //if (ci->role == CI_ROLE_GADGET) {
                ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
                ci_handle_vbus_change(ci);
-       }
+               //}
 
        return retval;
 
@@ -1798,11 +1798,10 @@ static void udc_id_switch_for_host(struct ci13xxx *ci)
 }
 
 /**
- * udc_remove: parent remove must call this to remove UDC
- *
- * No interrupts active, the IRQ has been released
+ * ci_hdrc_gadget_init - initialize device related bits
+ * ci: the controller
  */
-static void udc_stop(struct ci13xxx *ci)
+void ci_hdrc_gadget_destroy(struct ci13xxx *ci)
 {
        if (ci == NULL)
                return;
@@ -1821,8 +1820,6 @@ static void udc_stop(struct ci13xxx *ci)
        }
        dbg_remove_files(&ci->gadget.dev);
        device_unregister(&ci->gadget.dev);
-       /* my kobject is dynamic, I swear! */
-       memset(&ci->gadget, 0, sizeof(ci->gadget));
 }
 
 /**
@@ -1842,13 +1839,11 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
        if (!rdrv)
                return -ENOMEM;
 
-       rdrv->init      = udc_start;
        rdrv->start     = udc_id_switch_for_device;
        rdrv->stop      = udc_id_switch_for_host;
-       rdrv->destroy   = udc_stop;
        rdrv->irq       = udc_irq;
        rdrv->name      = "gadget";
        ci->roles[CI_ROLE_GADGET] = rdrv;
 
-       return 0;
+       return udc_start(ci);
 }
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index 4ff2384d..12fd7cf 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -80,6 +80,7 @@ struct ci13xxx_req {
 #ifdef CONFIG_USB_CHIPIDEA_UDC
 
 int ci_hdrc_gadget_init(struct ci13xxx *ci);
+void ci_hdrc_gadget_destroy(struct ci13xxx *ci);
 
 #else
 
@@ -88,6 +89,10 @@ static inline int ci_hdrc_gadget_init(struct ci13xxx *ci)
        return -ENXIO;
 }
 
+static void ci_hdrc_gadget_destroy(struct ci13xxx *ci)
+{
+}
+
 #endif
 
 #endif /* __DRIVERS_USB_CHIPIDEA_UDC_H */
---cut---

Which is shorter (32 insertions(+), 53 deletions(-)) and makes the main
probe easier on the eyes. What do you think?

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

Reply via email to