2022-11-18 11:33:27

by Chunfeng Yun

[permalink] [raw]
Subject: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports

There is error log when add a usb3 root hub without ports:
"hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"

so omit the shared hcd if either of the root hubs has no ports, but
usually there is no usb3 port.

Signed-off-by: Chunfeng Yun <[email protected]>
---
drivers/usb/host/xhci-mtk.c | 72 +++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 01705e559c42..cff3c4aea036 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -485,6 +485,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
const struct hc_driver *driver;
struct xhci_hcd *xhci;
struct resource *res;
+ struct usb_hcd *usb3_hcd;
struct usb_hcd *hcd;
int ret = -ENODEV;
int wakeup_irq;
@@ -593,6 +594,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)

xhci = hcd_to_xhci(hcd);
xhci->main_hcd = hcd;
+ xhci->allow_single_roothub = 1;

/*
* imod_interval is the interrupt moderation value in nanoseconds.
@@ -602,24 +604,29 @@ static int xhci_mtk_probe(struct platform_device *pdev)
xhci->imod_interval = 5000;
device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval);

- xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
- dev_name(dev), hcd);
- if (!xhci->shared_hcd) {
- ret = -ENOMEM;
- goto disable_device_wakeup;
- }
-
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret)
- goto put_usb3_hcd;
+ goto disable_device_wakeup;

- if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
+ if (!xhci_has_one_roothub(xhci)) {
+ xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
+ dev_name(dev), hcd);
+ if (!xhci->shared_hcd) {
+ ret = -ENOMEM;
+ goto dealloc_usb2_hcd;
+ }
+ }
+
+ usb3_hcd = xhci_get_usb3_hcd(xhci);
+ if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
!(xhci->quirks & XHCI_BROKEN_STREAMS))
- xhci->shared_hcd->can_do_streams = 1;
+ usb3_hcd->can_do_streams = 1;

- ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
- if (ret)
- goto dealloc_usb2_hcd;
+ if (xhci->shared_hcd) {
+ ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+ if (ret)
+ goto put_usb3_hcd;
+ }

if (wakeup_irq > 0) {
ret = dev_pm_set_dedicated_wake_irq_reverse(dev, wakeup_irq);
@@ -641,13 +648,13 @@ static int xhci_mtk_probe(struct platform_device *pdev)
usb_remove_hcd(xhci->shared_hcd);
xhci->shared_hcd = NULL;

-dealloc_usb2_hcd:
- usb_remove_hcd(hcd);
-
put_usb3_hcd:
- xhci_mtk_sch_exit(mtk);
usb_put_hcd(xhci->shared_hcd);

+dealloc_usb2_hcd:
+ xhci_mtk_sch_exit(mtk);
+ usb_remove_hcd(hcd);
+
disable_device_wakeup:
device_init_wakeup(dev, false);

@@ -679,10 +686,15 @@ static int xhci_mtk_remove(struct platform_device *pdev)
dev_pm_clear_wake_irq(dev);
device_init_wakeup(dev, false);

- usb_remove_hcd(shared_hcd);
- xhci->shared_hcd = NULL;
+ if (shared_hcd) {
+ usb_remove_hcd(shared_hcd);
+ xhci->shared_hcd = NULL;
+ }
usb_remove_hcd(hcd);
- usb_put_hcd(shared_hcd);
+
+ if (shared_hcd)
+ usb_put_hcd(shared_hcd);
+
usb_put_hcd(hcd);
xhci_mtk_sch_exit(mtk);
clk_bulk_disable_unprepare(BULK_CLKS_NUM, mtk->clks);
@@ -700,13 +712,16 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev)
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct usb_hcd *shared_hcd = xhci->shared_hcd;
int ret;

xhci_dbg(xhci, "%s: stop port polling\n", __func__);
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
del_timer_sync(&hcd->rh_timer);
- clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
- del_timer_sync(&xhci->shared_hcd->rh_timer);
+ if (shared_hcd) {
+ clear_bit(HCD_FLAG_POLL_RH, &shared_hcd->flags);
+ del_timer_sync(&shared_hcd->rh_timer);
+ }

ret = xhci_mtk_host_disable(mtk);
if (ret)
@@ -718,8 +733,10 @@ static int __maybe_unused xhci_mtk_suspend(struct device *dev)

restart_poll_rh:
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
- set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
- usb_hcd_poll_rh_status(xhci->shared_hcd);
+ if (shared_hcd) {
+ set_bit(HCD_FLAG_POLL_RH, &shared_hcd->flags);
+ usb_hcd_poll_rh_status(shared_hcd);
+ }
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
usb_hcd_poll_rh_status(hcd);
return ret;
@@ -730,6 +747,7 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev)
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
struct usb_hcd *hcd = mtk->hcd;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct usb_hcd *shared_hcd = xhci->shared_hcd;
int ret;

usb_wakeup_set(mtk, false);
@@ -742,8 +760,10 @@ static int __maybe_unused xhci_mtk_resume(struct device *dev)
goto disable_clks;

xhci_dbg(xhci, "%s: restart port polling\n", __func__);
- set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
- usb_hcd_poll_rh_status(xhci->shared_hcd);
+ if (shared_hcd) {
+ set_bit(HCD_FLAG_POLL_RH, &shared_hcd->flags);
+ usb_hcd_poll_rh_status(shared_hcd);
+ }
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
usb_hcd_poll_rh_status(hcd);
return 0;
--
2.18.0



Subject: Re: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports

Il 18/11/22 12:01, Chunfeng Yun ha scritto:
> There is error log when add a usb3 root hub without ports:
> "hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"
>
> so omit the shared hcd if either of the root hubs has no ports, but
> usually there is no usb3 port.
>
> Signed-off-by: Chunfeng Yun <[email protected]>

Reviewed-by: AngeloGioacchino Del Regno <[email protected]>



2022-11-23 12:14:10

by Mathias Nyman

[permalink] [raw]
Subject: Re: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports

On 18.11.2022 13.01, Chunfeng Yun wrote:
> There is error log when add a usb3 root hub without ports:
> "hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"
>
> so omit the shared hcd if either of the root hubs has no ports, but
> usually there is no usb3 port.
>
> Signed-off-by: Chunfeng Yun <[email protected]>
> ---
> drivers/usb/host/xhci-mtk.c | 72 +++++++++++++++++++++++--------------
> 1 file changed, 46 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
> index 01705e559c42..cff3c4aea036 100644
> --- a/drivers/usb/host/xhci-mtk.c
> +++ b/drivers/usb/host/xhci-mtk.c
> @@ -485,6 +485,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
> const struct hc_driver *driver;
> struct xhci_hcd *xhci;
> struct resource *res;
> + struct usb_hcd *usb3_hcd;
> struct usb_hcd *hcd;
> int ret = -ENODEV;
> int wakeup_irq;
> @@ -593,6 +594,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
>
> xhci = hcd_to_xhci(hcd);
> xhci->main_hcd = hcd;
> + xhci->allow_single_roothub = 1;
>
> /*
> * imod_interval is the interrupt moderation value in nanoseconds.
> @@ -602,24 +604,29 @@ static int xhci_mtk_probe(struct platform_device *pdev)
> xhci->imod_interval = 5000;
> device_property_read_u32(dev, "imod-interval-ns", &xhci->imod_interval);
>
> - xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> - dev_name(dev), hcd);
> - if (!xhci->shared_hcd) {
> - ret = -ENOMEM;
> - goto disable_device_wakeup;
> - }
> -
> ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> if (ret)
> - goto put_usb3_hcd;
> + goto disable_device_wakeup;
>
> - if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> + if (!xhci_has_one_roothub(xhci)) {
> + xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> + dev_name(dev), hcd);
> + if (!xhci->shared_hcd) {
> + ret = -ENOMEM;
> + goto dealloc_usb2_hcd;
> + }
> + }
> +
> + usb3_hcd = xhci_get_usb3_hcd(xhci);
> + if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> !(xhci->quirks & XHCI_BROKEN_STREAMS))
> - xhci->shared_hcd->can_do_streams = 1;
> + usb3_hcd->can_do_streams = 1;
>
> - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> - if (ret)
> - goto dealloc_usb2_hcd;
> + if (xhci->shared_hcd) {
> + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> + if (ret)
> + goto put_usb3_hcd;
> + }
>
> if (wakeup_irq > 0) {
> ret = dev_pm_set_dedicated_wake_irq_reverse(dev, wakeup_irq);

dev_pm_set_dedicated_wake_irq_reverse() can be called with just one hcd, if it fails
it will goto dealloc_usb3_hcd:

dealloc_usb3_hcd:
usb_remove_hcd(xhci->shared_hcd); // xhci->shared_hcd may be null
xhci->shared_hcd = NULL; // causes usb_put_hcd() issues if shared_hcd exists

put_usb3_hcd:
usb_put_hcd(xhci->shared_hcd); // shared_hcd may be set NULL above

-Mathias

2022-11-24 06:04:07

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports

On Wed, 2022-11-23 at 13:10 +0200, Mathias Nyman wrote:
> On 18.11.2022 13.01, Chunfeng Yun wrote:
> > There is error log when add a usb3 root hub without ports:
> > "hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"
> >
> > so omit the shared hcd if either of the root hubs has no ports, but
> > usually there is no usb3 port.
> >
> > Signed-off-by: Chunfeng Yun <[email protected]>
> > ---
> > drivers/usb/host/xhci-mtk.c | 72 +++++++++++++++++++++++---------
> > -----
> > 1 file changed, 46 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-
> > mtk.c
> > index 01705e559c42..cff3c4aea036 100644
> > --- a/drivers/usb/host/xhci-mtk.c
> > +++ b/drivers/usb/host/xhci-mtk.c
> > @@ -485,6 +485,7 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> > const struct hc_driver *driver;
> > struct xhci_hcd *xhci;
> > struct resource *res;
> > + struct usb_hcd *usb3_hcd;
> > struct usb_hcd *hcd;
> > int ret = -ENODEV;
> > int wakeup_irq;
> > @@ -593,6 +594,7 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> >
> > xhci = hcd_to_xhci(hcd);
> > xhci->main_hcd = hcd;
> > + xhci->allow_single_roothub = 1;
> >
> > /*
> > * imod_interval is the interrupt moderation value in
> > nanoseconds.
> > @@ -602,24 +604,29 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> > xhci->imod_interval = 5000;
> > device_property_read_u32(dev, "imod-interval-ns", &xhci-
> > >imod_interval);
> >
> > - xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> > - dev_name(dev), hcd);
> > - if (!xhci->shared_hcd) {
> > - ret = -ENOMEM;
> > - goto disable_device_wakeup;
> > - }
> > -
> > ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> > if (ret)
> > - goto put_usb3_hcd;
> > + goto disable_device_wakeup;
> >
> > - if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> > + if (!xhci_has_one_roothub(xhci)) {
> > + xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> > + dev_name(dev),
> > hcd);
> > + if (!xhci->shared_hcd) {
> > + ret = -ENOMEM;
> > + goto dealloc_usb2_hcd;
> > + }
> > + }
> > +
> > + usb3_hcd = xhci_get_usb3_hcd(xhci);
> > + if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> > !(xhci->quirks & XHCI_BROKEN_STREAMS))
> > - xhci->shared_hcd->can_do_streams = 1;
> > + usb3_hcd->can_do_streams = 1;
> >
> > - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> > - if (ret)
> > - goto dealloc_usb2_hcd;
> > + if (xhci->shared_hcd) {
> > + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> > + if (ret)
> > + goto put_usb3_hcd;
> > + }
> >
> > if (wakeup_irq > 0) {
> > ret = dev_pm_set_dedicated_wake_irq_reverse(dev,
> > wakeup_irq);
>
>
> dev_pm_set_dedicated_wake_irq_reverse() can be called with just one
> hcd, if it fails
> it will goto dealloc_usb3_hcd:
>
> dealloc_usb3_hcd:
> usb_remove_hcd(xhci->shared_hcd); // xhci->shared_hcd may be
> null
> xhci->shared_hcd = NULL; // causes usb_put_hcd() issues if
> shared_hcd exists
>
> put_usb3_hcd:
> usb_put_hcd(xhci->shared_hcd); // shared_hcd may be set NULL
> above

I'll check it again, thanks

>
> -Mathias
>

2022-11-24 11:02:11

by Chunfeng Yun

[permalink] [raw]
Subject: Re: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports

On Wed, 2022-11-23 at 13:10 +0200, Mathias Nyman wrote:
> On 18.11.2022 13.01, Chunfeng Yun wrote:
> > There is error log when add a usb3 root hub without ports:
> > "hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"
> >
> > so omit the shared hcd if either of the root hubs has no ports, but
> > usually there is no usb3 port.
> >
> > Signed-off-by: Chunfeng Yun <[email protected]>
> > ---
> > drivers/usb/host/xhci-mtk.c | 72 +++++++++++++++++++++++---------
> > -----
> > 1 file changed, 46 insertions(+), 26 deletions(-)
> >
> > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-
> > mtk.c
> > index 01705e559c42..cff3c4aea036 100644
> > --- a/drivers/usb/host/xhci-mtk.c
> > +++ b/drivers/usb/host/xhci-mtk.c
> > @@ -485,6 +485,7 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> > const struct hc_driver *driver;
> > struct xhci_hcd *xhci;
> > struct resource *res;
> > + struct usb_hcd *usb3_hcd;
> > struct usb_hcd *hcd;
> > int ret = -ENODEV;
> > int wakeup_irq;
> > @@ -593,6 +594,7 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> >
> > xhci = hcd_to_xhci(hcd);
> > xhci->main_hcd = hcd;
> > + xhci->allow_single_roothub = 1;
> >
> > /*
> > * imod_interval is the interrupt moderation value in
> > nanoseconds.
> > @@ -602,24 +604,29 @@ static int xhci_mtk_probe(struct
> > platform_device *pdev)
> > xhci->imod_interval = 5000;
> > device_property_read_u32(dev, "imod-interval-ns", &xhci-
> > >imod_interval);
> >
> > - xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> > - dev_name(dev), hcd);
> > - if (!xhci->shared_hcd) {
> > - ret = -ENOMEM;
> > - goto disable_device_wakeup;
> > - }
> > -
> > ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> > if (ret)
> > - goto put_usb3_hcd;
> > + goto disable_device_wakeup;
> >
> > - if (HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> > + if (!xhci_has_one_roothub(xhci)) {
> > + xhci->shared_hcd = usb_create_shared_hcd(driver, dev,
> > + dev_name(dev),
> > hcd);
> > + if (!xhci->shared_hcd) {
> > + ret = -ENOMEM;
> > + goto dealloc_usb2_hcd;
> > + }
> > + }
> > +
> > + usb3_hcd = xhci_get_usb3_hcd(xhci);
> > + if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 &&
> > !(xhci->quirks & XHCI_BROKEN_STREAMS))
> > - xhci->shared_hcd->can_do_streams = 1;
> > + usb3_hcd->can_do_streams = 1;
> >
> > - ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> > - if (ret)
> > - goto dealloc_usb2_hcd;
> > + if (xhci->shared_hcd) {
> > + ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> > + if (ret)
> > + goto put_usb3_hcd;
> > + }
> >
> > if (wakeup_irq > 0) {
> > ret = dev_pm_set_dedicated_wake_irq_reverse(dev,
> > wakeup_irq);
>
>
> dev_pm_set_dedicated_wake_irq_reverse() can be called with just one
> hcd, if it fails
> it will goto dealloc_usb3_hcd:
>
> dealloc_usb3_hcd:
> usb_remove_hcd(xhci->shared_hcd); // xhci->shared_hcd may be
> null
usb_remove_hcd() has handled NULL argument, no need check it here

> xhci->shared_hcd = NULL; // causes usb_put_hcd() issues if
> shared_hcd exists
This line shall be removed, I'll prepare a patch.

>
> put_usb3_hcd:
> usb_put_hcd(xhci->shared_hcd); // shared_hcd may be set NULL
> above
usb_put_hcd() has handled NULL argument, no need check it here

Thanks a lot

>
> -Mathias
>

2022-11-25 07:31:47

by Macpaul Lin

[permalink] [raw]
Subject: Re: [PATCH] usb: host: xhci-mtk: omit shared hcd if either root hub has no ports



On 11/24/22 18:38, Chunfeng Yun (云春峰) wrote:
> On Wed, 2022-11-23 at 13:10 +0200, Mathias Nyman wrote:
>> On 18.11.2022 13.01, Chunfeng Yun wrote:
>>> There is error log when add a usb3 root hub without ports:
>>> "hub 4-0:1.0: config failed, hub doesn't have any ports! (err -19)"
>>>
>>> so omit the shared hcd if either of the root hubs has no ports, but
>>> usually there is no usb3 port.
>>>
>>> Signed-off-by: Chunfeng Yun <[email protected]>
>>> ---
>>> drivers/usb/host/xhci-mtk.c | 72 +++++++++++++++++++++++---------

[deleted...]

Dear Chunfeng,

Since this issue has been reported by Canonical as a ticket
on launchpad (sorry, it has been reported as a private ticket...),
could you please to check if add "Cc: [email protected]" and
"Fixes:" tags are valid?

If it is possible, please help to list dependent patches to backport
to stable tree also. Is it possible to include this patch in recent LTS
tree?

Thanks
Macpaul Lin