Re: [PATCH] Revert "ARM: dts: bcm283x: Fix DTC warnings about missing phy-cells"
From: Arnd Bergmann
Date: Mon Jan 08 2018 - 06:23:17 EST
On Mon, Jan 8, 2018 at 10:36 AM, Stefan Wahren <stefan.wahren@xxxxxxxx> wrote:
> Am 08.01.2018 um 10:27 schrieb Arnd Bergmann:
>>
>> On Mon, Jan 8, 2018 at 10:15 AM, Stefan Wahren <stefan.wahren@xxxxxxxx>
>> wrote:
>>>
>>> Hi Eric,
>>> Am 07.01.2018 um 23:08 schrieb Eric Anholt:
>>>>
>>>> Stefan Wahren <stefan.wahren@xxxxxxxx> writes:
>>>>
>>>>> This reverts commit 014d6da6cb2525d7f48fb08c705cb130cc7b5f4a.
>>>>>
>>>>> The DT clean up could trigger an endless deferred probe of DWC2 USB
>>>>> driver
>>>>> on the Raspberry Pi 2/3. So revert the change until we fixed the
>>>>> probing
>>>>> issue.
>>>>
>>>> Why's that? I found that I needed to enable the generic no-op phy
>>>> driver, but other than that it was fine.
>>>
>>>
>>> in order to avoid this regression. Changing the configuration is not a
>>> solution for the kernelci guys.
>>>
>>> Btw
>>>
>>> CONFIG_NOP_USB_XCEIV=y
>>>
>>> is already enabled in arm64/defconfig and the issue still occured. Do you
>>> mean a different option?
>>
>> Obviously we need to fix this, but I really want to understand what
>> exactly
>> happened so we can fix the code if possible rather than making the
>> dts file incompatible with the binding again.
>
>
> i fully agree, but dwc2 "hacking" usually requires more time than reverting
> this change.
>
>>
>> Do you have any more insight into how we get into the deferred probe
>> situation?
>
>
> I send this bug report [1] on Friday to linux-usb.
>
> Stefan
>
> [1] - https://marc.info/?l=linux-usb&m=151518314314753&w=2
Ok, I looked at the code now and it seems that the generic phy layer
returns -EINVAL for a phy reference to an invalid node, but not a
reference to a valid node without a driver, here it returns
-EPROBE_DEFER, which by itself is reasonable behavior.
In this case, the NOP_USB_XCEIV driver is using the old usb-phy
framework, and the dwc2 driver tries both but bails out when the
generic phy returns -EPROBE_DEFER.
It sounds like the problem is not limited to raspberry pi then, but
the same thing would happen on any other machine using the
same algorithm. I looked at the other USB drivers that support
both generic-phy and usb-phy drivers:
- the generic usb-hcd code (usb_add_hcd) tries usb-phy first
and then tries generic-phy, but appears to also return
with -EPROBE_DEFER if either of the two asks for deferral.
other return codes are ignored.
- dwc2 (as show above) tries generic-phy first, propagates
-EPROBE_DEFER before trying usb-phy.
- dwc3 tries usb-phy first, and propagates -EPROBE_DEFER
from generic-phy even if usb-phy had succeeded.
- chipidea tries both and uses whichever one works, returning
-EPROBE_DEFER as long as both fail.
- musb/da8xx_probe propagates any error from generic-phy including
-EPROBE_DEFER, it then registers a generic phy and uses
that internally.
- musb/musb_dsps tries both, it fails if usb-phy is not working, but
ignores errors from generic-phy
- musb/omap2430 needs both usb-phy and generic-phy
- musb/sunxi needs a generic-phy and then registers a usb-phy
- renesas_usbhs tries both if they are enabled and fails
if one of them returns any error.
It's hard to tell what exactly is affected by the usb-hcd change,
most importantly since this is configuration dependent: if
the generic-phy layer is disabled, nothing changes, but otherwise
it would be broken the same way as dwc2 and dwc3.
The best idea I have so far is to had a hack into the generic
phy code with a full list of compatible strings that the must
never return -EPROBE_DEFER because that would break
the usb-phy handling:
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index b4964b067aec..6b9c3a1e7ce5 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -387,6 +387,24 @@ int phy_calibrate(struct phy *phy)
}
EXPORT_SYMBOL_GPL(phy_calibrate);
+static struct of_device_id legacy_usbphy[] = {
+ { .compatible = "fsl,imx23-usbphy" },
+ { .compatible = "fsl,imx6q-usbphy" },
+ { .compatible = "fsl,imx6sl-usbphy" },
+ { .compatible = "fsl,imx6sx-usbphy" },
+ { .compatible = "fsl,imx6ul-usbphy" },
+ { .compatible = "fsl,vf610-usbphy" },
+ { .compatible = "nvidia,tegra20-usb-phy" },
+ { .compatible = "nvidia,tegra30-usb-phy" },
+ { .compatible = "nxp,isp1301" },
+ { .compatible = "ti,am335x-usb-ctrl-module" },
+ { .compatible = "ti,am335x-usb-phy" },
+ { .compatible = "ti,keystone-usbphy" },
+ { .compatible = "ti,twl6030-usb" },
+ { .compatible = "usb-nop-xceiv" },
+ {},
+};
+
/**
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
* @np: device_node for which to get the phy
@@ -410,6 +428,15 @@ static struct phy *_of_phy_get(struct device_node
*np, int index)
if (ret)
return ERR_PTR(-ENODEV);
+ /*
+ * Some USB host controllers use a "phys" property to refer to
+ * a device that does not have a generic phy driver but that
+ * has a driver for the older usb-phy framework.
+ * We must not return -EPROBE_DEFER for those, so bail out early.
+ */
+ if (of_match_node(legacy_usbphy, args.np))
+ return ERR_PTR(-ENODEV);
+
mutex_lock(&phy_provider_mutex);
phy_provider = of_phy_provider_lookup(args.np);
if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
Arnd