Hi Mathias, Please provide your suggestions to resolve this.
Thank you. Regards, Srinath. On Thu, Aug 3, 2017 at 11:42 PM, Srinath Mannam <srinath.man...@broadcom.com> wrote: > Hi Mathias, > > In our SOC, xHCI controller has three ports. In that one is SS and two > HS ports, all ports are connected with separate phy controller. > > We have a bug in HS phy controllers. > Because of this bug, HS phy controller needs to reset after > disconnected the device in the corresponding HS port. > > I could not find any available mechanism or quirks in kernel to handle > these cases. > So, I did modifications in xhci-plat.c, xhci.c and xhci-hub.c files to > fix this issue. > > But the modifications are not cleaner to upstream. > > Please help me in the implementation of proper fix. > > Below are the code changes. > > --- > drivers/usb/host/xhci-hub.c | 9 +++++++++ > drivers/usb/host/xhci-plat.c | 11 +++++++++++ > drivers/usb/host/xhci.c | 2 ++ > drivers/usb/host/xhci.h | 1 + > 4 files changed, 23 insertions(+) > > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c > index 0ef1690..3fdb07d 100644 > --- a/drivers/usb/host/xhci-hub.c > +++ b/drivers/usb/host/xhci-hub.c > @@ -1193,6 +1193,15 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 > typeReq, u16 wValue, > case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: > xhci_clear_port_change_bit(xhci, wValue, wIndex, > port_array[wIndex], temp); > + if ((wValue == USB_PORT_FEAT_C_CONNECTION) && > + !(temp & PORT_CONNECT) && > + (hcd->speed < HCD_USB3)) { > + > + hcd->driver->port_power(hcd, > + wIndex + > + xhci->num_usb3_ports, > + false); > + } > break; > case USB_PORT_FEAT_ENABLE: > xhci_disable_port(hcd, xhci, wIndex, > diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c > index 1a1d6b8..2e1facd 100644 > --- a/drivers/usb/host/xhci-plat.c > +++ b/drivers/usb/host/xhci-plat.c > @@ -30,11 +30,13 @@ static struct hc_driver __read_mostly xhci_plat_hc_driver; > > static int xhci_plat_setup(struct usb_hcd *hcd); > static int xhci_plat_start(struct usb_hcd *hcd); > +static int xhci_plat_portpower(struct usb_hcd *hcd, int portnum, bool > enable); > > static const struct xhci_driver_overrides xhci_plat_overrides __initconst = { > .extra_priv_size = sizeof(struct xhci_plat_priv), > .reset = xhci_plat_setup, > .start = xhci_plat_start, > + .port_power = xhci_plat_portpower, > }; > > static void xhci_priv_plat_start(struct usb_hcd *hcd) > @@ -64,6 +66,15 @@ static void xhci_plat_quirks(struct device *dev, > struct xhci_hcd *xhci) > */ > xhci->quirks |= XHCI_PLAT; > } > +static int xhci_plat_portpower(struct usb_hcd *hcd, int portnum, bool enable) > +{ > + struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd); > + > + if (enable == false) > + phy_reset(priv->phys[portnum]); > + > + return 0; > +} > > /* called during probe() after chip reset completes */ > static int xhci_plat_setup(struct usb_hcd *hcd) > diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c > index 1a4ca02..a41c009 100644 > --- a/drivers/usb/host/xhci.c > +++ b/drivers/usb/host/xhci.c > @@ -5028,6 +5028,8 @@ void xhci_init_driver(struct hc_driver *drv, > drv->reset = over->reset; > if (over->start) > drv->start = over->start; > + if (over->port_power) > + drv->port_power = over->port_power; > } > } > EXPORT_SYMBOL_GPL(xhci_init_driver); > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h > index f945380..08c573c 100644 > --- a/drivers/usb/host/xhci.h > +++ b/drivers/usb/host/xhci.h > @@ -1692,6 +1692,7 @@ struct xhci_driver_overrides { > size_t extra_priv_size; > int (*reset)(struct usb_hcd *hcd); > int (*start)(struct usb_hcd *hcd); > + int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable); > }; > > #define XHCI_CFC_DELAY 10 > -- > 2.7.4 > > > Regards, > Srinath. -- 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