Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: qcom-qusb2: Fix NULL pointer dereference on early suspend

Enabling runtime PM before attaching the QPHY instance as driver data
can lead to a NULL pointer dereference in runtime PM callbacks that
expect valid driver data. There is a small window where the suspend
callback may run after PM runtime enabling and before runtime forbid.
This causes a sporadic crash during boot:

```
Unable to handle kernel NULL pointer dereference at virtual address 00000000000000a1
[...]
CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 6.16.7+ #116 PREEMPT
Workqueue: pm pm_runtime_work
pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : qusb2_phy_runtime_suspend+0x14/0x1e0 [phy_qcom_qusb2]
lr : pm_generic_runtime_suspend+0x2c/0x44
[...]
```

Attach the QPHY instance as driver data before enabling runtime PM to
prevent NULL pointer dereference in runtime PM callbacks.

Reorder pm_runtime_enable() and pm_runtime_forbid() to prevent a
short window where an unnecessary runtime suspend can occur.

Use the devres-managed version to ensure PM runtime is symmetrically
disabled during driver removal for proper cleanup.

Fixes: 891a96f65ac3 ("phy: qcom-qusb2: Add support for runtime PM")
Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
Link: https://patch.msgid.link/20251219085640.114473-1-loic.poulain@oss.qualcomm.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Loic Poulain and committed by
Vinod Koul
1ca52c09 8becf917

+8 -8
+8 -8
drivers/phy/qualcomm/phy-qcom-qusb2.c
··· 1093 1093 or->hsdisc_trim.override = true; 1094 1094 } 1095 1095 1096 - pm_runtime_set_active(dev); 1097 - pm_runtime_enable(dev); 1096 + dev_set_drvdata(dev, qphy); 1097 + 1098 1098 /* 1099 - * Prevent runtime pm from being ON by default. Users can enable 1100 - * it using power/control in sysfs. 1099 + * Enable runtime PM support, but forbid it by default. 1100 + * Users can allow it again via the power/control attribute in sysfs. 1101 1101 */ 1102 + pm_runtime_set_active(dev); 1102 1103 pm_runtime_forbid(dev); 1104 + ret = devm_pm_runtime_enable(dev); 1105 + if (ret) 1106 + return ret; 1103 1107 1104 1108 generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops); 1105 1109 if (IS_ERR(generic_phy)) { 1106 1110 ret = PTR_ERR(generic_phy); 1107 1111 dev_err(dev, "failed to create phy, %d\n", ret); 1108 - pm_runtime_disable(dev); 1109 1112 return ret; 1110 1113 } 1111 1114 qphy->phy = generic_phy; 1112 1115 1113 - dev_set_drvdata(dev, qphy); 1114 1116 phy_set_drvdata(generic_phy, qphy); 1115 1117 1116 1118 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); 1117 - if (IS_ERR(phy_provider)) 1118 - pm_runtime_disable(dev); 1119 1119 1120 1120 return PTR_ERR_OR_ZERO(phy_provider); 1121 1121 }