[PATCH v1] phy: qcom-qusb2: Set drvdata before pm_runtime_set_active in probe

From: Varadarajan Narayanan
Date: Thu Jan 09 2025 - 05:08:38 EST


From: Vignesh Viswanathan <quic_viswanat@xxxxxxxxxxx>

The commit 891a96f65ac3 ("phy: qcom-qusb2: Add support for
runtime PM") added support for runtime PM to the qcom-qusb2
driver. However, pm_runtime_set_active is invoked before driver
data is saved into the 'device' structure. Randomly the runtime
PM ops seem to get invoked between pm_runtime_set_active and
dev_set_drvdata resulting in the following crash.

Hence do dev_set_drvdata early in the probe.

Unable to handle kernel NULL pointer dereference at virtual address 00000065 when read

[ . . . ]

PC is at qusb2_phy_runtime_suspend+0x8/0x164 [phy_qcom_qusb2]
LR is at __rpm_callback+0x3c/0x110
pc : [<82780018>] lr : [<40523ff0>] psr: a0000013
sp : 410dfe88 ip : 00000000 fp : 4015eb68
r10: 00000003 r9 : 00000000 r8 : 410c8894
r7 : 405222f0 r6 : 405222f0 r5 : 00000000 r4 : 00000000
r3 : 82780010 r2 : 411088c0 r1 : 410c8810 r0 : 410c8810
Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c0383d Table: 422a806a DAC: 00000055

[ . . . ]

Call Trace:
qusb2_phy_runtime_suspend+0x8/0x164 [phy_qcom_qusb2]
__rpm_callback+0x3c/0x110
rpm_callback+0x50/0x54
rpm_suspend+0x23c/0x428
pm_runtime_work+0x74/0x8c
process_scheduled_works+0x1bc/0x2b8
worker_thread+0x260/0x2e4
kthread+0x118/0x12c
ret_from_fork+0x14/0x38
Exception stack(0x410dffb0 to 0x410dfff8)

Fixes: 891a96f65ac3b ("phy: qcom-qusb2: Add support for runtime PM")
Signed-off-by: Vignesh Viswanathan <quic_viswanat@xxxxxxxxxxx>
Signed-off-by: Varadarajan Narayanan <quic_varada@xxxxxxxxxxx>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 1f5f7df14d5a..e08d9c5b409b 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -1025,6 +1025,8 @@ static int qusb2_phy_probe(struct platform_device *pdev)
return -ENOMEM;
or = &qphy->overrides;

+ dev_set_drvdata(dev, qphy);
+
qphy->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(qphy->base))
return PTR_ERR(qphy->base);
@@ -1135,7 +1137,6 @@ static int qusb2_phy_probe(struct platform_device *pdev)
}
qphy->phy = generic_phy;

- dev_set_drvdata(dev, qphy);
phy_set_drvdata(generic_phy, qphy);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

base-commit: 6ecd20965bdc21b265a0671ccf36d9ad8043f5ab
--
2.34.1