On Tue, Nov 20, 2012 at 10:12:30PM +0800, Peter Chen wrote:
> On Tue, Nov 20, 2012 at 02:08:18PM +0200, Alexander Shishkin wrote:
> > Peter Chen <[email protected]> writes:
> >
> > > Since we can't load/unload gadget module on the fly, we can't
> > > de-init gadget structure during the otg switch.
> > > We have to create gadget at the probe function no matter current
> > > role is the host or device, of cource, the gadget will not
> > > be created for host-only port.
> >
> > No, this is much worse than the previous version.
> >
> > >
> > > Signed-off-by: Peter Chen <[email protected]>
> > > ---
> > > drivers/usb/chipidea/ci.h | 10 +++++++---
> > > drivers/usb/chipidea/core.c | 7 ++++++-
> > > 2 files changed, 13 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
> > > index d32f932..c704aa7 100644
> > > --- a/drivers/usb/chipidea/ci.h
> > > +++ b/drivers/usb/chipidea/ci.h
> > > @@ -188,9 +188,13 @@ static inline int ci_role_start(struct ci13xxx *ci,
> > > enum ci_role role)
> > > if (!ci->roles[role])
> > > return -ENXIO;
> > >
> > > - ret = ci->roles[role]->start(ci);
> > > - if (!ret)
> > > - ci->role = role;
> > > + /* Only host role is supported at this function*/
> > > + if (role == CI_ROLE_HOST) {
> > > + ret = ci->roles[role]->start(ci);
> > > + if (!ret)
> > > + ci->role = role;
> > > + }
> > > +
> > > return ret;
> > > }
> >
> > This is bad in a number of ways. What we need is add a "destroy" method
> > to the role and not add
> >
> > if (ci->role == CI_ROLE_HOST)
> > hackity_hackity();
> >
> > to ten different places in the driver. This is really bad, even worse
> > than the fact that with this patch you're returning an uninitialized
> > 'ret' in case of non-host, which (correct me if I'm wrong) should
> > explode straight away, which in turn makes me wonder how is this
> > patchset fully tested as it claims to be.
>
> Oh, my fault, maybe this uninitialized value is just 0 at my test.
> I will consider this problem more.
How about this:
/* prepare for switch to device */
static int udc_id_switch_for_device(struct ci13xxx *ci)
{
usb_gadget_vbus_disconnect(&ci->gadget);
/* host doesn't care B_SESSION_VALID event */
hw_write(ci, OP_OTGSC, OTGSC_BSVIE, ~OTGSC_BSVIE);
hw_write(ci, OP_OTGSC, OTGSC_BSVIS, OTGSC_BSVIS);
ci->role = CI_ROLE_END;
}
/* prepare for switch to host */
static int udc_id_switch_for_host(struct ci13xxx *ci)
{
ci->role = role;
hw_write(ci, OP_OTGSC, OTGSC_BSVIS, OTGSC_BSVIS);
hw_write(ci, OP_OTGSC, OTGSC_BSVIE, OTGSC_BSVIE);
}
struct ci_role_driver device {
.init = udc_start;
.start = udc_id_switch_for_device;
.stop = udc_id_switch_for_host;
.destroy = udc_stop;
};
struct ci_role_driver host {
.init = host_start;
.start = host_start;
.stop = host_stop;
.destroy = stop_stop;
};
At probe call role .init. At remove, call role .destroy
During id_switch, just call ci_role_stop/ci_role_start.
For host mode at otg port during init case, I still think we
should call device .init, as the modprobe gadget will
fail if device .init isn't called, like the "modprobe g_ether"
will fail at user's init.rc.
--
Best Regards,
Peter Chen
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html