On Wed, Aug 9, 2023 at 10:40 AM Xu Yang <xu.yang_2@xxxxxxx> wrote: > > Some NXP processor using chipidea IP has a bug when frame babble is > detected. > > As per 4.15.1.1.1 Serial Bus Babble: > A babble condition also exists if IN transaction is in progress at > High-speed SOF2 point. This is called frame babble. The host controller > must disable the port to which the frame babble is detected. > > The USB controller has disabled the port (PE cleared) and has asserted > USBERRINT when frame babble is detected, but PEC is not asserted. > Therefore, the SW isn't aware that port has been disabled. Then the > SW keeps sending packets to this port, but all of the transfers will > fail. > > This workaround will firstly assert PCD by SW when USBERRINT is detected > and then judge whether port change has really occurred or not by polling > roothub status. Because the PEC doesn't get asserted in our case, this > patch will also assert it by SW when specific conditions are satisfied. > > Signed-off-by: Xu Yang <xu.yang_2@xxxxxxx> > Acked-by: Peter Chen <peter.chen@xxxxxxxxxx> Peter > --- > Changes in v2: > - fix typo in commit message > - Adjust the judgement logic in echi_irq() as suggested from Alan > --- > drivers/usb/host/ehci-hcd.c | 8 ++++++-- > drivers/usb/host/ehci-hub.c | 10 +++++++++- > drivers/usb/host/ehci.h | 10 ++++++++++ > 3 files changed, 25 insertions(+), 3 deletions(-) > > diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c > index a1930db0da1c..802bfafb1012 100644 > --- a/drivers/usb/host/ehci-hcd.c > +++ b/drivers/usb/host/ehci-hcd.c > @@ -755,10 +755,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) > > /* normal [4.15.1.2] or error [4.15.1.1] completion */ > if (likely ((status & (STS_INT|STS_ERR)) != 0)) { > - if (likely ((status & STS_ERR) == 0)) > + if (likely ((status & STS_ERR) == 0)) { > INCR(ehci->stats.normal); > - else > + } else { > + /* Force to check port status */ > + if (ehci->has_ci_pec_bug) > + status |= STS_PCD; > INCR(ehci->stats.error); > + } > bh = 1; > } > > diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c > index efe30e3be22f..1aee392e8492 100644 > --- a/drivers/usb/host/ehci-hub.c > +++ b/drivers/usb/host/ehci-hub.c > @@ -674,7 +674,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) > > if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) > || (ehci->reset_done[i] && time_after_eq( > - jiffies, ehci->reset_done[i]))) { > + jiffies, ehci->reset_done[i])) > + || ehci_has_ci_pec_bug(ehci, temp)) { > if (i < 7) > buf [0] |= 1 << (i + 1); > else > @@ -875,6 +876,13 @@ int ehci_hub_control( > if (temp & PORT_PEC) > status |= USB_PORT_STAT_C_ENABLE << 16; > > + if (ehci_has_ci_pec_bug(ehci, temp)) { > + status |= USB_PORT_STAT_C_ENABLE << 16; > + ehci_info(ehci, > + "PE is cleared by HW port:%d PORTSC:%08x\n", > + wIndex + 1, temp); > + } > + > if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){ > status |= USB_PORT_STAT_C_OVERCURRENT << 16; > > diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h > index c5c7f8782549..1441e3400796 100644 > --- a/drivers/usb/host/ehci.h > +++ b/drivers/usb/host/ehci.h > @@ -207,6 +207,7 @@ struct ehci_hcd { /* one per controller */ > unsigned has_fsl_port_bug:1; /* FreeScale */ > unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */ > unsigned has_fsl_susp_errata:1; /* NXP SUSP quirk */ > + unsigned has_ci_pec_bug:1; /* ChipIdea PEC bug */ > unsigned big_endian_mmio:1; > unsigned big_endian_desc:1; > unsigned big_endian_capbase:1; > @@ -707,6 +708,15 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) > */ > #define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata) > > +/* > + * Some Freescale/NXP processors using ChipIdea IP have a bug in which > + * disabling the port (PE is cleared) does not cause PEC to be asserted > + * when frame babble is detected. > + */ > +#define ehci_has_ci_pec_bug(e, portsc) \ > + ((e)->has_ci_pec_bug && ((e)->command & CMD_PSE) \ > + && !(portsc & PORT_PEC) && !(portsc & PORT_PE)) > + > /* > * While most USB host controllers implement their registers in > * little-endian format, a minority (celleb companion chip) implement > -- > 2.34.1 >