]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
phy: qcom-usb-hs: Fix extcon double register after power cycle
authorStephan Gerhold <stephan@gerhold.net>
Tue, 8 Oct 2019 11:52:08 +0000 (13:52 +0200)
committerKhalid Elmously <khalid.elmously@canonical.com>
Wed, 29 Jan 2020 04:45:21 +0000 (23:45 -0500)
BugLink: https://bugs.launchpad.net/bugs/1859712
[ Upstream commit 64f86b9978449ff05bfa6c64b4c5439e21e9c80b ]

Commit f0b5c2c96370 ("phy: qcom-usb-hs: Replace the extcon API")
switched from extcon_register_notifier() to the resource-managed
API, i.e. devm_extcon_register_notifier().

This is problematic in this case, because the extcon notifier
is dynamically registered/unregistered whenever the PHY is powered
on/off. The resource-managed API does not unregister the notifier
until the driver is removed, so as soon as the PHY is power cycled,
attempting to register the notifier again results in:

double register detected
WARNING: CPU: 1 PID: 182 at kernel/notifier.c:26 notifier_chain_register+0x74/0xa0
Call trace:
 ...
 extcon_register_notifier+0x74/0xb8
 devm_extcon_register_notifier+0x54/0xb8
 qcom_usb_hs_phy_power_on+0x1fc/0x208
 ...

... and USB stops working after plugging the cable out and in
another time.

The easiest way to fix this is to make a partial revert of
commit f0b5c2c96370 ("phy: qcom-usb-hs: Replace the extcon API")
and avoid using the resource-managed API in this case.

Fixes: f0b5c2c96370 ("phy: qcom-usb-hs: Replace the extcon API")
Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/phy/qualcomm/phy-qcom-usb-hs.c

index 2d0c70b5589f4fe4f325cde23c8b060340d2a69d..643934a2a70c35e588051258dd1e1d25962adbba 100644 (file)
@@ -159,8 +159,8 @@ static int qcom_usb_hs_phy_power_on(struct phy *phy)
                /* setup initial state */
                qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
                                              uphy->vbus_edev);
-               ret = devm_extcon_register_notifier(&ulpi->dev, uphy->vbus_edev,
-                               EXTCON_USB, &uphy->vbus_notify);
+               ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
+                                              &uphy->vbus_notify);
                if (ret)
                        goto err_ulpi;
        }
@@ -181,6 +181,9 @@ static int qcom_usb_hs_phy_power_off(struct phy *phy)
 {
        struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
 
+       if (uphy->vbus_edev)
+               extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
+                                          &uphy->vbus_notify);
        regulator_disable(uphy->v3p3);
        regulator_disable(uphy->v1p8);
        clk_disable_unprepare(uphy->sleep_clk);