[PATCH v3] soc: qcom: pmic_glink: Fix device access from worker during suspend

From: Abel Vesa

Date: Wed Aug 19 2026 - 03:24:10 EST


From: Abel Vesa <abel.vesa@xxxxxxxxxx>

For historical reasons, the GLINK smem interrupt is registered with
IRRQF_NO_SUSPEND flag set, which is the underlying problem here, since the
incoming messages can be delivered during late suspend and early
resume.

In this specific case, the pmic_glink_altmode_worker() currently gets
scheduled on the system_wq which can be scheduled to run while devices
are still suspended. This proves to be a problem when a Type-C retimer,
switch or mux that is controlled over a bus like I2C, because the I2C
controller is suspended.

This has been proven to be the case on the X Elite boards where such
retimers (ParadeTech PS8830) are used in order to handle Type-C
orientation and altmode configuration. The following warning is thrown:

[ 35.134876] i2c i2c-4: Transfer while suspended
[ 35.143865] WARNING: CPU: 0 PID: 99 at drivers/i2c/i2c-core.h:56 __i2c_transfer+0xb4/0x57c [i2c_core]
[ 35.352879] Workqueue: events pmic_glink_altmode_worker [pmic_glink_altmode]
[ 35.360179] pstate: 61400005 (nZCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[ 35.455242] Call trace:
[ 35.457826] __i2c_transfer+0xb4/0x57c [i2c_core] (P)
[ 35.463086] i2c_transfer+0x98/0xf0 [i2c_core]
[ 35.467713] i2c_transfer_buffer_flags+0x54/0x88 [i2c_core]
[ 35.473502] regmap_i2c_write+0x20/0x48 [regmap_i2c]
[ 35.478659] _regmap_raw_write_impl+0x780/0x944
[ 35.483401] _regmap_bus_raw_write+0x60/0x7c
[ 35.487848] _regmap_write+0x134/0x184
[ 35.491773] regmap_write+0x54/0x78
[ 35.495418] ps883x_set+0x58/0xec [ps883x]
[ 35.499688] ps883x_sw_set+0x60/0x84 [ps883x]
[ 35.504223] typec_switch_set+0x48/0x74 [typec]
[ 35.508952] pmic_glink_altmode_worker+0x44/0x1fc [pmic_glink_altmode]
[ 35.515712] process_scheduled_works+0x1a0/0x2d0
[ 35.520525] worker_thread+0x2a8/0x3c8
[ 35.524449] kthread+0xfc/0x184
[ 35.527749] ret_from_fork+0x10/0x20

The proper solution here should be to not deliver these kind of messages
during system suspend at all, or at least make it configurable per glink
client. But simply dropping the IRQF_NO_SUSPEND flag entirely will break
other clients. The final shape of the rework of the pmic glink driver in
order to fulfill both the filtering of the messages that need to be able
to wake-up the system and the queueing of these messages until the system
has properly resumed is still being discussed and it is planned as a
future effort.

Meanwhile, the stop-gap fix here is to schedule the pmic glink altmode
worker on the system_freezable_wq instead of the system_wq. This will
result in the altmode worker not being scheduled to run until the
devices are resumed first, which will give the controllers like I2C a
chance to resume before the transfer is requested.

Reported-by: Johan Hovold <johan+linaro@xxxxxxxxxx>
Closes: https://lore.kernel.org/lkml/Z1CCVjEZMQ6hJ-wK@xxxxxxxxxxxxxxxxxxxx/
Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support")
Cc: stable@xxxxxxxxxxxxxxx # 6.3
Reviewed-by: Caleb Connolly <caleb.connolly@xxxxxxxxxx>
Reviewed-by: Bjorn Andersson <andersson@xxxxxxxxxx>
Signed-off-by: Abel Vesa <abel.vesa@xxxxxxxxxx>
Signed-off-by: Abel Vesa <abel.vesa@xxxxxxxxxxxxxxxx>
---
Reviving this old patch since it is still an unsolved problem and the
conversation about it stopped. The hope was that this would be fixed
in some other way, but none of the solutions discussed off-list seemed
to surface. So maybe this can be merged as a stop-gap for now.

I've been running with this patch (and the ucsi generic one) on my Hamoa
laptop ever since and the USB plug/unplug during suspend issue has went
away for good.

I intend respin the UCSI generic patch as well.

Changes in v3:
- Rebased on next-20260818.
- Picked up Bjorn's R-b tag.
- Dropped the RFC prefix, sent as proper patch.
- Link to v2: https://lore.kernel.org/all/20250129-soc-qcom-pmic-glink-fix-device-access-on-worker-while-suspended-v2-1-de2a3eca514e@xxxxxxxxxx/
---
drivers/soc/qcom/pmic_glink_altmode.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index 13c434f8d03a..465e5d2316a0 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -451,7 +451,7 @@ static void pmic_glink_altmode_sc8180xp_notify(struct pmic_glink_altmode *altmod
alt_port->mode = mode;
alt_port->hpd_state = hpd_state;
alt_port->hpd_irq = hpd_irq;
- schedule_work(&alt_port->work);
+ queue_work(system_freezable_wq, &alt_port->work);
}

#define SC8280XP_DPAM_MASK 0x3f
@@ -502,7 +502,7 @@ static void pmic_glink_altmode_sc8280xp_notify(struct pmic_glink_altmode *altmod
alt_port->tbt_data = *tbt;
}

- schedule_work(&alt_port->work);
+ queue_work(system_freezable_wq, &alt_port->work);
}

static void pmic_glink_altmode_callback(const void *data, size_t len, void *priv)

---
base-commit: 5453bc3279e9f8578ac3e534d476240e40c879e1
change-id: 20260819-b4-soc-qcom-pmic-glink-fix-device-access-on-worker-while-suspended-95a4f21e6632

Best regards,
--
Abel Vesa <abel.vesa@xxxxxxxxxxxxxxxx>