* [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance
@ 2026-05-21 1:09 Michael Scott
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Michael Scott @ 2026-05-21 1:09 UTC (permalink / raw)
To: linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, Michael Scott
Four patches:
* Two pre-existing bug fixes in phy-qcom-qmp-combo that are reachable
today on any board which registers a usb_role_switch on this PHY,
and will become reachable on more X1E boards as their Type-C
support matures (patches 1-2).
* Two dell-thena DT maintenance items: one mirrors a regulator
always-on change Hovold applied to the rest of the X1E80100
family but that dell-thena missed, and one bumps the linux,cma
reserved-memory pool so the camera pipeline can actually
allocate buffers alongside a normal desktop (patches 3-4).
== Changes since v1 ==
* Rebased from v7.1-rc4 onto linux-next (next-20260520). v1 did not
apply on top of commit f546912bcac6 ("phy: qcom: qmp-combo: Move
pipe_clk on/off to common"), which landed in phy/next after
v7.1-rc4; patch 1's hunk context is adjusted for that refactor.
No functional change to any patch.
v1: https://lore.kernel.org/linux-arm-msm/20260521003615.1260844-1-mike.scott@oss.qualcomm.com/
== phy-qcom-qmp-combo fixes (patches 1-2) ==
Both bugs were found by exercising the typec_mux + role-switch code
paths on Dell Latitude 7455 (X1E80100, dell-thena). In mainline
today the bugs are reachable on x1e001de-devkit, which registers a
usb_role_switch on one USB-C port; they would also fire on any
future board that opts into the same DT pattern.
Patch 1: qmp_combo_usb_power_off() / qmp_combo_usb_exit() can be
re-entered as ->exit from an external consumer (dwc3 phy_exit during
driver unbind) after this device's backing devm resources have
already been released along a separate teardown chain. The
dereference of qmp->pcs (whose ioremap has been freed) then oopses
with a level-3 translation fault. The patch adds a usb_init_count
guard so the re-entry is a no-op. The proper long-term fix is a
teardown-ordering rework so the QMP PHY outlives any consumer that
may still call its phy_ops; until then, this guard prevents the
oops.
Patch 2: qmp_combo_typec_mux_set() updates the cached qmpphy_mode
unconditionally, but only reprograms hardware when init_count is
non-zero. So a typec_mux_set arriving before phy_init updates the
cache without programming hardware; subsequent calls then see a
"match" against the cached mode and bail out early, leaving the
lane mux in whatever state it powered up in. The patch tracks
separately whether the cache has been committed to hardware, so
the fast-path bail only happens when the cache truly reflects the
hardware.
== DT maintenance (patches 3-4) ==
Patch 3 marks vreg_l12b_1p2 and vreg_l15b_1p8 always-on. Hovold did
this for every other X1E80100 board in March 2025; dell-thena landed
four months later (commit e7733b42111c) and missed the change, which
leaves the kernel free to disable those LDOs even though several
board-level fixed regulators have no described vin-supply link back
to them.
Patch 4 raises linux,cma from 128 MiB to 256 MiB. The 128 MiB pool
is too small to support libcamera's buffer set in parallel with the
normal desktop: msm DRM framebuffers, qcom_iris codec buffers, and
qcom_camss VFE pre-allocations occupy ~100 MiB at GNOME idle,
leaving ~25 MiB free. libcamera's "simple" pipeline asks for four
8.35 MiB ABGR8888 frames (32 MiB total) and the fourth allocation
fails with "dma-heap allocation failure". At 256 MiB, ~150 MiB is
free at idle -- comfortable headroom.
Note for other X1E maintainers: every other X1E80100 / X1E78100 /
X1P42100 board in mainline is still on the 128 MiB default, and
several of them carry camera nodes (Dell XPS 13 9345, Medion
Sprchrgd-14, ASUS Zenbook A14, Microsoft Romulus, Microsoft Denali,
Lenovo ThinkBook 16). Those boards are likely to hit the same
allocation failure once libcamera enablement lands on them, and
should probably take a similar bump. I limited this patch to
dell-thena because I do not have the other boards on hand to
verify the resulting CmaFree numbers under a real workload --
applying the same change blindly across boards I cannot test would
just shift the guesswork.
== Patch summary ==
1/4 phy: qcom: qmp-combo: skip USB power_off/exit after device
teardown
2/4 phy: qcom: qmp-combo: track whether the cached typec_mux mode
was committed to hardware
3/4 arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on
4/4 arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB
== Testing ==
Hardware: Dell Latitude 7455 (X1E80100), running Ubuntu 26.04.
Test kernel: a local build of Ubuntu's 7.0.0-15-generic source with
this series applied on top. The series in this submission is rebased
onto linux-next (next-20260520) so that it applies cleanly on top of
Val Packett's recent qmp-combo refactor (commit f546912bcac6, "phy:
qcom: qmp-combo: Move pipe_clk on/off to common"), which is queued in
phy/next and reaches mainline at the next merge window.
- Without this series:
* Writing "none" to a manually-bound usb_role_switch reliably
oopses the kernel. vmcore captured via kdump-tools; crash(1)
analysis confirms qmp->pcs UAF in qmp_combo_usb_power_off,
reached via dwc3_remove -> dwc3_phy_exit -> phy_exit ->
qmp_combo_usb_exit.
* Without patch 2, the first typec_mux_set arriving before
phy_init updates the cache but not the hardware; the next
call hits "same qmpphy mode, bail out" and the lane mux
stays in its default configuration.
* libcamera-mediated camera apps (gnome-snapshot, etc.) fail
to start with "dma-heap allocation failure for frame-3".
- With this series:
* Role-switch teardown no longer oopses (patch 1's guard).
* QMP PHY is reprogrammed on first altmode notification after
phy_init (patch 2's committed-state tracking).
* CmaFree at GNOME idle is ~150 MiB (was ~25 MiB).
* gnome-snapshot opens with a live preview from the OV02E10
sensor.
Patches 1-2 were exercised by manually wiring up a usb_role_switch
on dell-thena and driving the role-switch path; the DT change that
makes that wiring permanent is not part of this series.
A personal note: it has been a while since I last sent patches
upstream -- as you may have gathered from v1 being based on v7.1-rc4
rather than linux-next. Apologies for the extra round-trip; if I have
missed any other recent process changes, corrections are welcome.
Michael Scott (4):
phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
phy: qcom: qmp-combo: track whether the cached typec_mux mode was
committed to hardware
arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on
arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB
arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 4 ++-
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 47 +++++++++++++++++++++++++++--
2 files changed, 48 insertions(+), 3 deletions(-)
base-commit: 687da68900cd1a46549f7d9430c7d40346cb86a0
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
@ 2026-05-21 1:09 ` Michael Scott
2026-05-21 1:52 ` sashiko-bot
2026-05-21 11:58 ` Bryan O'Donoghue
2026-05-21 1:09 ` [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
` (3 subsequent siblings)
4 siblings, 2 replies; 13+ messages in thread
From: Michael Scott @ 2026-05-21 1:09 UTC (permalink / raw)
To: linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, Michael Scott
qmp_combo_usb_power_off() is reachable from an external consumer
(notably dwc3 via phy_exit() during driver unbind) after this device's
backing resources have already been released along a separate teardown
chain. The dereference of qmp->pcs (whose ioremap mapping has been
freed by devm cleanup) then takes a level-3 translation fault and
oopses.
Easily reproducible during testing of USB-C role-switch enablement on
Dell Latitude 7455 (X1E80100), by writing "none" to a USB-C DWC3's
usb_role_switch role attribute, e.g.
echo none > /sys/class/usb_role/a800000.usb-role-switch/role
which triggers the chain:
Unable to handle kernel paging request at virtual address ffff8000876c5400
pc : qmp_combo_usb_power_off.isra.0+0x58/0x470 [phy_qcom_qmp_combo]
Call trace:
qmp_combo_usb_power_off+0x58/0x470 [phy_qcom_qmp_combo]
qmp_combo_usb_exit+0x38/0x90 [phy_qcom_qmp_combo]
phy_exit
dwc3_phy_exit [dwc3]
dwc3_core_remove [dwc3]
dwc3_remove [dwc3]
platform_remove
device_release_driver_internal
device_driver_detach
unbind_store
sysfs_kf_write
vfs_write
ksys_write
__arm64_sys_write
el0_svc
Two WARNs precede the oops from the same teardown chain, confirming
the resource ordering:
WARNING: drivers/clk/clk.c:4494 at clk_nodrv_disable_unprepare+0x8/0x18
WARNING: drivers/regulator/core.c:2657 at _regulator_put+0x84/0x98
i.e. the pipe clock provider has been unregistered and the regulators
released before qmp_combo_usb_power_off() runs.
The proper long-term fix is a teardown-ordering rework so the QMP
PHY's backing resources outlive any consumer that may still call its
phy_ops. Pending that, guard the power_off/exit paths with the
existing usb_init_count balance so re-entry after teardown does not
oops. usb_init_count tracks the balance of usb_power_on/off; if it
is zero we have either never powered on or have already powered off,
and there is nothing to do.
The same guard is added to qmp_combo_usb_exit() since it is the entry
point used by external consumers via phy_exit().
Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index cdcfad2e86b1..0db200292642 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -3926,6 +3926,17 @@ static int qmp_combo_usb_power_off(struct phy *phy)
struct qmp_combo *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
+ /*
+ * Reachable as ->exit from external consumers (notably dwc3) after
+ * this device's backing resources have already been released along
+ * a teardown chain. Refuse to touch registers in that case.
+ */
+ if (!qmp->usb_init_count) {
+ dev_dbg(qmp->dev, "%s: PHY not powered on, skipping\n",
+ __func__);
+ return 0;
+ }
+
/* PHY reset */
qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
@@ -3968,6 +3979,17 @@ static int qmp_combo_usb_exit(struct phy *phy)
struct qmp_combo *qmp = phy_get_drvdata(phy);
int ret;
+ /*
+ * See qmp_combo_usb_power_off(): an external consumer may call
+ * phy_exit() after the QMP device's resources have been torn
+ * down. usb_init_count tracks usb_init/usb_exit balance.
+ */
+ if (!qmp->usb_init_count) {
+ dev_dbg(qmp->dev, "%s: PHY not initialised, skipping\n",
+ __func__);
+ return 0;
+ }
+
mutex_lock(&qmp->phy_mutex);
ret = qmp_combo_usb_power_off(phy);
if (ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
@ 2026-05-21 1:09 ` Michael Scott
2026-05-21 2:37 ` sashiko-bot
2026-05-21 12:00 ` Bryan O'Donoghue
2026-05-21 1:09 ` [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on Michael Scott
` (2 subsequent siblings)
4 siblings, 2 replies; 13+ messages in thread
From: Michael Scott @ 2026-05-21 1:09 UTC (permalink / raw)
To: linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, Michael Scott
qmp_combo_typec_mux_set() updates qmp->qmpphy_mode (the cached state)
unconditionally, but only reprograms hardware when qmp->init_count is
non-zero. If pmic_glink_altmode (or any other typec_mux consumer)
calls into the PHY before DWC3 has performed phy_init() -- a real
ordering observed during testing of USB-C role-switch enablement on
Snapdragon X (X1E80100) -- the cache transitions away from the
probe default QMPPHY_MODE_USB3DP but the hardware is never touched.
Subsequent calls (for example on partner detach, where TYPEC_STATE_SAFE
also resolves to QMPPHY_MODE_USB3_ONLY in the !DP-SVID branch) then
match the cached mode and the function bails out early with:
qcom-qmp-combo-phy faXX000.phy: typec_mux_set: same qmpphy mode, bail out
leaving the lane mux in whatever configuration it powered up in. On
the Dell Latitude 7455 this manifests as the SS lanes being left in
the default state when the first altmode notification arrives during
DWC3 probe, with the function bailing out on every subsequent attach.
Track separately whether the cached mode has actually been committed
to hardware. The bail-out optimization is only safe when the cache
truly reflects the hardware:
- qmp_combo_typec_mux_set(): bail only when the cached mode matches
and was committed; clear the committed flag whenever the cache is
updated, set it again after a successful reprogram inside the
init_count-guarded block.
- qmp_combo_com_init(): set the committed flag at the end of a
successful init, since com_init() programs registers from the
cached qmpphy_mode.
No behavioural change on platforms where typec_mux_set never fires
before phy_init -- committed remains true through normal operation.
Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 25 +++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
index 0db200292642..e28bc1cc7a78 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
@@ -2295,6 +2295,7 @@ struct qmp_combo {
struct mutex phy_mutex;
int init_count;
enum qmpphy_mode qmpphy_mode;
+ bool qmpphy_mode_committed;
struct phy *usb_phy;
enum phy_mode phy_mode;
@@ -3754,6 +3755,9 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
SW_PWRDN);
+ /* com_init() just programmed registers from qmp->qmpphy_mode. */
+ qmp->qmpphy_mode_committed = true;
+
return 0;
err_disable_clocks:
@@ -4509,9 +4513,22 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
new_mode = QMPPHY_MODE_USB3_ONLY;
}
+ /*
+ * Fast-path bail only when the cached mode is also known to be
+ * committed to hardware. The cache may be ahead of the hardware
+ * if a typec_mux_set arrived while the PHY had not yet been
+ * initialised (init_count == 0); in that case the cache update
+ * below was the only thing that ran, and we still need to drive
+ * the registers when the PHY does come up.
+ */
if (new_mode == qmp->qmpphy_mode) {
- dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n");
- return 0;
+ if (qmp->qmpphy_mode_committed) {
+ dev_dbg(qmp->dev,
+ "typec_mux_set: same qmpphy mode (committed), bail out\n");
+ return 0;
+ }
+ dev_dbg(qmp->dev,
+ "typec_mux_set: same qmpphy mode but uncommitted; reprogramming\n");
}
if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) {
@@ -4523,6 +4540,7 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
qmp->qmpphy_mode, new_mode);
qmp->qmpphy_mode = new_mode;
+ qmp->qmpphy_mode_committed = false;
if (qmp->init_count) {
if (qmp->usb_init_count)
@@ -4551,6 +4569,9 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
if (qmp->dp_init_count)
cfg->dp_aux_init(qmp);
}
+
+ /* Reprogram complete; cache now reflects hardware. */
+ qmp->qmpphy_mode_committed = true;
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
2026-05-21 1:09 ` [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
@ 2026-05-21 1:09 ` Michael Scott
2026-05-21 4:28 ` Val Packett
2026-05-21 1:09 ` [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
2026-05-21 4:39 ` [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Val Packett
4 siblings, 1 reply; 13+ messages in thread
From: Michael Scott @ 2026-05-21 1:09 UTC (permalink / raw)
To: linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, Michael Scott, stable
The l12b and l15b supplies are used by components that are not (fully)
described (and some never will be) and must never be disabled.
Mark the regulators as always-on to prevent them from being disabled,
for example, when consumers probe defer or suspend.
Note that these supplies currently have no consumers described in
mainline for dell-thena beyond the audio codec (vdd-buck/vdd-rxtx/
vdd-io on wcd938x), which can release them when the codec goes idle.
The board-level gpio-fixed regulators that feed the Type-C retimer's
VDDIO and other rails are not described with a vin-supply link, so
the kernel cannot keep their parent LDOs alive on its own.
This mirrors the same change Johan Hovold applied to every other
X1E80100 board in a March 2025 series; commit 63169c07d740
("arm64: dts: qcom: x1e80100-dell-xps13-9345: mark l12b and l15b always-on")
is representative. The dell-thena board file was introduced four months
later and did not inherit that change; this patch closes the gap.
Fixes: e7733b42111c ("arm64: dts: qcom: Add support for Dell Inspiron 7441 / Latitude 7455")
Cc: stable@vger.kernel.org
Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
index db291730130c..d6de4da02dcd 100644
--- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
@@ -589,6 +589,7 @@ vreg_l12b_1p2: ldo12 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
};
vreg_l13b_3p0: ldo13 {
@@ -610,6 +611,7 @@ vreg_l15b_1p8: ldo15 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
};
};
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
` (2 preceding siblings ...)
2026-05-21 1:09 ` [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on Michael Scott
@ 2026-05-21 1:09 ` Michael Scott
2026-05-21 3:52 ` Val Packett
2026-05-21 12:04 ` Bryan O'Donoghue
2026-05-21 4:39 ` [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Val Packett
4 siblings, 2 replies; 13+ messages in thread
From: Michael Scott @ 2026-05-21 1:09 UTC (permalink / raw)
To: linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, Michael Scott
The 128 MiB linux,cma reserved-memory pool on dell-thena is too small
to support the camera pipeline in parallel with the normal Linux
desktop. On a freshly-booted system with GNOME running, the typical
runtime consumers — msm DRM framebuffers (Wayland triple buffering on
the eDP panel), qcom_iris video codec buffers, qcom_camss VFE
pre-allocated buffers — already occupy ~100 MiB of the pool, leaving
only ~25 MiB free.
The libcamera "simple" pipeline handler used by /dev/media0 on
dell-thena allocates four ABGR8888 frames at 1920×1088 = 32 MiB total.
That request fails on the fourth frame:
ERROR DmaBufAllocator: dma-heap allocation failure for frame-3
ERROR Allocator: Stream is not part of /base/.../camera@10 active configuration
Can't allocate buffers
Failed to start camera session
resulting in gnome-snapshot's "Could not play camera stream" and any
other libcamera-mediated app being unable to actually stream.
Bumping linux,cma to 256 MiB (a 0.9% reservation on these laptops'
typical 27 GiB RAM) leaves ~150 MiB free at runtime — sufficient for
the libcamera buffer set plus headroom for video playback or other
CMA-hungry workloads in parallel.
Tested on Dell Latitude 7455: with the 256 MiB pool, CmaFree at
GNOME-desktop idle is ~150 MiB, gnome-snapshot streams the OV02E10
camera cleanly, and `cam -c 1 --capture=2` succeeds.
The companion board files dell-inspiron-14-plus-7441 and the upstream
.dts variants inherit from x1-dell-thena.dtsi, so this changes the
pool size for every dell-thena-based laptop in one place.
Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
---
arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
index d6de4da02dcd..714988a81384 100644
--- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
@@ -167,7 +167,7 @@ led-camera-indicator {
reserved-memory {
linux,cma {
compatible = "shared-dma-pool";
- size = <0x0 0x8000000>;
+ size = <0x0 0x10000000>;
reusable;
linux,cma-default;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
@ 2026-05-21 1:52 ` sashiko-bot
2026-05-21 11:58 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-05-21 1:52 UTC (permalink / raw)
To: Michael Scott
Cc: vkoul, linux-phy, robh, conor+dt, neil.armstrong, devicetree,
olteanv
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] The lockless check of `qmp->usb_init_count` in `qmp_combo_usb_exit()` introduces a Time-of-Check to Time-of-Use (TOCTOU) race condition that can lead to an integer underflow and unbalanced resource management.
Pre-existing issues:
- [Critical] The patch attempts to prevent a crash by checking `qmp->usb_init_count` after the device's backing resources are released, but the `qmp` structure itself has already been freed via `devm` cleanup, resulting in a Use-After-Free.
--
commit 639386ffdb78db9a5c3e78a1f3ada8713f38acd7
Author: Michael Scott <mike.scott@oss.qualcomm.com>
phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
The commit attempts to prevent crashes when external consumers like dwc3
call phy_exit() after the QMP PHY's backing resources have been released,
by guarding the power_off and exit paths with a check on the
usb_init_count balance.
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index cdcfad2e86b1d..0db200292642e 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3926,6 +3926,17 @@ static int qmp_combo_usb_power_off(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
>
> + /*
> + * Reachable as ->exit from external consumers (notably dwc3) after
> + * this device's backing resources have already been released along
> + * a teardown chain. Refuse to touch registers in that case.
> + */
> + if (!qmp->usb_init_count) {
[Severity: Critical]
This is a pre-existing issue, but the qmp structure itself is allocated
using devm_kzalloc(), so it is freed during the device's devres cleanup.
If dwc3 calls phy_exit() after qmp_combo has been unbound, won't accessing
qmp->usb_init_count result in a Use-After-Free (UAF) read?
If the freed memory happens to be zeroed, the read evaluates to 0 and
successfully masks the bug by skipping the remainder of the function. If
SLUB poisoning or KASAN is enabled, this will trigger a UAF splat or read a
non-zero value, proceeding to call mutex_lock(&qmp->phy_mutex) on freed
memory.
Does this patch replace a vmap UAF on qmp->pcs with a slab UAF on the freed
qmp structure instead of fixing the underlying lifecycle bug?
[ ... ]
> @@ -3968,6 +3979,17 @@ static int qmp_combo_usb_exit(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> int ret;
>
> + /*
> + * See qmp_combo_usb_power_off(): an external consumer may call
> + * phy_exit() after the QMP device's resources have been torn
> + * down. usb_init_count tracks usb_init/usb_exit balance.
> + */
> + if (!qmp->usb_init_count) {
[Severity: High]
Does checking qmp->usb_init_count outside of qmp->phy_mutex introduce a
Time-of-Check to Time-of-Use (TOCTOU) race?
If a concurrent thread (such as qmp_combo_typec_mux_set() reacting to a
Type-C event) acquires the mutex and decrements usb_init_count to zero
immediately after this lockless check succeeds, qmp_combo_usb_exit() will
proceed to acquire the lock.
It will then call qmp_combo_usb_power_off(), which will safely check the
count under the lock and return 0 for success.
Because qmp_combo_usb_power_off() returns success, qmp_combo_usb_exit()
mistakenly proceeds to call qmp_combo_com_exit() and unconditionally
executes qmp->usb_init_count--.
Since the counter is an unsigned int and is already 0, could this wrap
around to UINT_MAX and cause unbalanced regulator and clock disables
which can crash the system?
> + dev_dbg(qmp->dev, "%s: PHY not initialised, skipping\n",
> + __func__);
> + return 0;
> + }
> +
> mutex_lock(&qmp->phy_mutex);
> ret = qmp_combo_usb_power_off(phy);
> if (ret)
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260521010935.1333494-1-mike.scott@oss.qualcomm.com?part=1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware
2026-05-21 1:09 ` [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
@ 2026-05-21 2:37 ` sashiko-bot
2026-05-21 12:00 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-05-21 2:37 UTC (permalink / raw)
To: Michael Scott
Cc: devicetree, robh, conor+dt, vkoul, neil.armstrong, olteanv,
linux-phy
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The patch fails to resolve the unprogrammed hardware state because the reprogramming sequence is still completely bypassed when `init_count == 0`.
Pre-existing issues:
- [High] The error handling path in `qmp_combo_com_init()` incorrectly decrements `init_count` when called with `force == true`.
- [High] Type-C MUX set operations modify `usb_init_count` independently of `init_count`, leading to resource leaks.
- [High] Lockless access to `qmp->usb_init_count` in `qmp_combo_usb_exit()` causes a Time-Of-Check to Time-Of-Use race condition.
--
commit c4bd0ad144568b18cf6ccfdc50c09f8d088db9c4
Author: Michael Scott <mike.scott@oss.qualcomm.com>
phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware
This commit introduces a qmpphy_mode_committed flag to track whether the
cached typec_mux mode has been applied to hardware. It aims to prevent an
early bail-out in qmp_combo_typec_mux_set() when the PHY has not yet been
initialized and the hardware state is out of sync with the cache.
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 0db200292642e..e28bc1cc7a78b 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
[ ... ]
> @@ -3754,6 +3755,9 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
> qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
> SW_PWRDN);
>
> + /* com_init() just programmed registers from qmp->qmpphy_mode. */
> + qmp->qmpphy_mode_committed = true;
> +
> return 0;
>
> err_disable_clocks:
> clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
> err_assert_reset:
> reset_control_bulk_assert(cfg->num_resets, qmp->resets);
> err_disable_regulators:
> regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> err_decrement_count:
> qmp->init_count--;
[Severity: High]
This is a pre-existing issue, but does this error path permanently break the
PHY's power management lifecycle?
When qmp_combo_com_init() is called with force == true, the init_count is not
incremented at the start of the function. However, if a hardware
initialization step fails and execution jumps to err_decrement_count, it will
decrement qmp->init_count, leading to an integer underflow.
> return ret;
> }
[ ... ]
> @@ -4509,9 +4513,22 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> new_mode = QMPPHY_MODE_USB3_ONLY;
> }
>
> + /*
> + * Fast-path bail only when the cached mode is also known to be
> + * committed to hardware. The cache may be ahead of the hardware
> + * if a typec_mux_set arrived while the PHY had not yet been
> + * initialised (init_count == 0); in that case the cache update
> + * below was the only thing that ran, and we still need to drive
> + * the registers when the PHY does come up.
> + */
> if (new_mode == qmp->qmpphy_mode) {
> - dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n");
> - return 0;
> + if (qmp->qmpphy_mode_committed) {
> + dev_dbg(qmp->dev,
> + "typec_mux_set: same qmpphy mode (committed), bail out\n");
> + return 0;
> + }
> + dev_dbg(qmp->dev,
> + "typec_mux_set: same qmpphy mode but uncommitted; reprogramming\n");
> }
>
> if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) {
> @@ -4523,6 +4540,7 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> qmp->qmpphy_mode, new_mode);
>
> qmp->qmpphy_mode = new_mode;
> + qmp->qmpphy_mode_committed = false;
>
> if (qmp->init_count) {
[Severity: High]
Does this actually fix the unprogrammed hardware state?
When init_count == 0, the early bailout is bypassed, but the hardware
programming block inside this if (qmp->init_count) condition is also skipped.
Once phy_init() is called, it executes qmp_combo_com_init(), which sets
qmpphy_mode_committed = true. Would subsequent calls to typec_mux_set() then
see committed == true and hit the early bailout just as they did before this
patch?
> if (qmp->usb_init_count)
[Severity: High]
This isn't a bug introduced by this patch, but can the interaction between
usb_init_count and init_count lead to a resource leak?
When transitioning to DP-only mode in qmp_combo_typec_mux_set(),
qmp->usb_init_count is decremented while using qmp_combo_com_exit(qmp, true),
which bypasses decrementing the master qmp->init_count.
If usb_init_count drops to 0, would a subsequent phy_exit() by the USB consumer
return early in qmp_combo_usb_exit() and skip calling
qmp_combo_com_exit(qmp, false)? This would leave the USB consumer's original
contribution to init_count unaccounted for, keeping regulators and clocks
enabled forever.
[Severity: High]
This is a pre-existing issue, but does lockless access to qmp->usb_init_count
in qmp_combo_usb_exit() cause a Time-Of-Check to Time-Of-Use race condition?
If qmp_combo_usb_exit() checks usb_init_count without holding qmp->phy_mutex,
could it drop to 0 concurrently via a MUX switch to DP-only in
qmp_combo_typec_mux_set()? When qmp_combo_usb_exit() subsequently acquires the
lock and continues, it would decrement usb_init_count causing an underflow to
UINT_MAX, allowing future exits to bypass the zero check and trigger unbalanced
teardowns.
> @@ -4551,6 +4569,9 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> if (qmp->dp_init_count)
> cfg->dp_aux_init(qmp);
> }
> +
> + /* Reprogram complete; cache now reflects hardware. */
> + qmp->qmpphy_mode_committed = true;
> }
>
> return 0;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260521010935.1333494-1-mike.scott@oss.qualcomm.com?part=2
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB
2026-05-21 1:09 ` [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
@ 2026-05-21 3:52 ` Val Packett
2026-05-21 12:04 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: Val Packett @ 2026-05-21 3:52 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel
On 5/20/26 10:09 PM, Michael Scott wrote:
> The 128 MiB linux,cma reserved-memory pool on dell-thena is too small
> to support the camera pipeline in parallel with the normal Linux
> desktop. On a freshly-booted system with GNOME running, the typical
> runtime consumers — msm DRM framebuffers (Wayland triple buffering on
> the eDP panel), qcom_iris video codec buffers, qcom_camss VFE
> pre-allocated buffers — already occupy ~100 MiB of the pool, leaving
> only ~25 MiB free.
Huh, I'm surprised that drm framebuffers use CMA… IIRC, msm drm can work
fine without a cma node present at all.
Indeed, with a desktop on a 4K monitor I'm seeing..
CmaTotal: 131072 kB
CmaFree: 1704 kB
> The libcamera "simple" pipeline handler used by /dev/media0 on
> dell-thena allocates four ABGR8888 frames at 1920×1088 = 32 MiB total.
> That request fails on the fourth frame:
>
> ERROR DmaBufAllocator: dma-heap allocation failure for frame-3
> ERROR Allocator: Stream is not part of /base/.../camera@10 active configuration
> Can't allocate buffers
> Failed to start camera session
>
> resulting in gnome-snapshot's "Could not play camera stream" and any
> other libcamera-mediated app being unable to actually stream.
..however I couldn't reproduce any failures, Snapshot started up just
fine, lowering CmaFree to 300 kB.
I have even launched both Snapshot and ffplay with a 4K AV1 video
through av1_v4l2m2m, CmaFree went all the way down to zero but there
were no errors whatsoever, both worked simultaneously just fine. o_0
I think drm buffers might just get evicted from that area or something?
> Bumping linux,cma to 256 MiB (a 0.9% reservation on these laptops'
> typical 27 GiB RAM) leaves ~150 MiB free at runtime — sufficient for
> the libcamera buffer set plus headroom for video playback or other
> CMA-hungry workloads in parallel.
>
> Tested on Dell Latitude 7455: with the 256 MiB pool, CmaFree at
> GNOME-desktop idle is ~150 MiB, gnome-snapshot streams the OV02E10
> camera cleanly, and `cam -c 1 --capture=2` succeeds.
>
> The companion board files dell-inspiron-14-plus-7441 and the upstream
> .dts variants inherit from x1-dell-thena.dtsi, so this changes the
> pool size for every dell-thena-based laptop in one place.
In any case, that's not an objection of course, just wondering why it's
working fine for me and not for you..
Acked-by: Val Packett <val@packett.cool>
~val
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on
2026-05-21 1:09 ` [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on Michael Scott
@ 2026-05-21 4:28 ` Val Packett
0 siblings, 0 replies; 13+ messages in thread
From: Val Packett @ 2026-05-21 4:28 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel, stable
On 5/20/26 10:09 PM, Michael Scott wrote:
> The l12b and l15b supplies are used by components that are not (fully)
> described (and some never will be) and must never be disabled.
>
> Mark the regulators as always-on to prevent them from being disabled,
> for example, when consumers probe defer or suspend.
>
> Note that these supplies currently have no consumers described in
> mainline for dell-thena beyond the audio codec (vdd-buck/vdd-rxtx/
> vdd-io on wcd938x), which can release them when the codec goes idle.
> The board-level gpio-fixed regulators that feed the Type-C retimer's
> VDDIO and other rails are not described with a vin-supply link, so
> the kernel cannot keep their parent LDOs alive on its own.
>
> This mirrors the same change Johan Hovold applied to every other
> X1E80100 board in a March 2025 series; commit 63169c07d740
> ("arm64: dts: qcom: x1e80100-dell-xps13-9345: mark l12b and l15b always-on")
> is representative. The dell-thena board file was introduced four months
> later and did not inherit that change; this patch closes the gap.
Acked-by: Val Packett <val@packett.cool>
Asked a friend who has totally legitimate access to the XPS schematics
about what those components are:
L12B: IO_1P2/275mA
- MOSFETs and pullups on a bunch of I2C, PCIe CLKREQ/WAKE, etc.
- VDDIO for WSA speakers
- NVME_PLN_N_1P2 (Power Loss Notification?)
- bunch of VDD_PX pins on the SoC
L15B: IO_1P8/1.09A
- MOSFETs and pullups on eDP HPD, bunch of I2C, PCIe CLKREQ/WAKE, some
INTR#/RESET#, SSD Load Switch, etc.
- VIN for Load Switch outputting retimer's VDDIO
- VDD_1P8 for WSA speakers
- VDDIO for power monitor ICs on IR_I2C
Yeahhh.. I think the load switches could potentially be modeled but the
huge bunch of random pullups not so much. I wonder how Windows handles
this. Maybe it could be in low-power mode when speakers are idle?
~val
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
` (3 preceding siblings ...)
2026-05-21 1:09 ` [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
@ 2026-05-21 4:39 ` Val Packett
4 siblings, 0 replies; 13+ messages in thread
From: Val Packett @ 2026-05-21 4:39 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, bryan.odonoghue, laurentiu.tudor1,
alex.vinarskis, linux-kernel
On 5/20/26 10:09 PM, Michael Scott wrote:
> Four patches:
>
> * Two pre-existing bug fixes in phy-qcom-qmp-combo that are reachable
> today on any board which registers a usb_role_switch on this PHY,
> and will become reachable on more X1E boards as their Type-C
> support matures (patches 1-2).
> [..]
Thanks for digging into this!
I have successfully used automatic role-switching (even switching
between USB2 gadget and USB3+DP mostly worked fine) but I do remember
manual sysfs switching causing more issues..
Would be great to see no more dr_mode = "host" upstream. Though I
vaguely remember some objections related to booting from USB (?)
~val
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
2026-05-21 1:52 ` sashiko-bot
@ 2026-05-21 11:58 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: Bryan O'Donoghue @ 2026-05-21 11:58 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, laurentiu.tudor1, alex.vinarskis,
linux-kernel
On 21/05/2026 02:09, Michael Scott wrote:
> qmp_combo_usb_power_off() is reachable from an external consumer
> (notably dwc3 via phy_exit() during driver unbind) after this device's
> backing resources have already been released along a separate teardown
> chain. The dereference of qmp->pcs (whose ioremap mapping has been
> freed by devm cleanup) then takes a level-3 translation fault and
> oopses.
>
> Easily reproducible during testing of USB-C role-switch enablement on
> Dell Latitude 7455 (X1E80100), by writing "none" to a USB-C DWC3's
> usb_role_switch role attribute, e.g.
>
> echo none > /sys/class/usb_role/a800000.usb-role-switch/role
>
> which triggers the chain:
>
> Unable to handle kernel paging request at virtual address ffff8000876c5400
> pc : qmp_combo_usb_power_off.isra.0+0x58/0x470 [phy_qcom_qmp_combo]
> Call trace:
> qmp_combo_usb_power_off+0x58/0x470 [phy_qcom_qmp_combo]
> qmp_combo_usb_exit+0x38/0x90 [phy_qcom_qmp_combo]
> phy_exit
> dwc3_phy_exit [dwc3]
> dwc3_core_remove [dwc3]
> dwc3_remove [dwc3]
> platform_remove
> device_release_driver_internal
> device_driver_detach
> unbind_store
> sysfs_kf_write
> vfs_write
> ksys_write
> __arm64_sys_write
> el0_svc
>
> Two WARNs precede the oops from the same teardown chain, confirming
> the resource ordering:
>
> WARNING: drivers/clk/clk.c:4494 at clk_nodrv_disable_unprepare+0x8/0x18
> WARNING: drivers/regulator/core.c:2657 at _regulator_put+0x84/0x98
>
> i.e. the pipe clock provider has been unregistered and the regulators
> released before qmp_combo_usb_power_off() runs.
>
> The proper long-term fix is a teardown-ordering rework so the QMP
> PHY's backing resources outlive any consumer that may still call its
> phy_ops. Pending that, guard the power_off/exit paths with the
> existing usb_init_count balance so re-entry after teardown does not
> oops. usb_init_count tracks the balance of usb_power_on/off; if it
> is zero we have either never powered on or have already powered off,
> and there is nothing to do.
>
> The same guard is added to qmp_combo_usb_exit() since it is the entry
> point used by external consumers via phy_exit().
>
> Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
Something like this requires a Fixes: tag
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index cdcfad2e86b1..0db200292642 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -3926,6 +3926,17 @@ static int qmp_combo_usb_power_off(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
>
> + /*
> + * Reachable as ->exit from external consumers (notably dwc3) after
> + * this device's backing resources have already been released along
> + * a teardown chain. Refuse to touch registers in that case.
> + */
> + if (!qmp->usb_init_count) {
> + dev_dbg(qmp->dev, "%s: PHY not powered on, skipping\n",
> + __func__);
> + return 0;
> + }
> +
> /* PHY reset */
> qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
>
> @@ -3968,6 +3979,17 @@ static int qmp_combo_usb_exit(struct phy *phy)
> struct qmp_combo *qmp = phy_get_drvdata(phy);
> int ret;
>
> + /*
> + * See qmp_combo_usb_power_off(): an external consumer may call
> + * phy_exit() after the QMP device's resources have been torn
> + * down. usb_init_count tracks usb_init/usb_exit balance.
> + */
> + if (!qmp->usb_init_count) {
> + dev_dbg(qmp->dev, "%s: PHY not initialised, skipping\n",
> + __func__);
> + return 0;
> + }
> +
> mutex_lock(&qmp->phy_mutex);
> ret = qmp_combo_usb_power_off(phy);
This can't be right - you check usb_init_count before the mutex and then
again inside the mutex @ qmp_combo_usb_power_off();
It seems like an error to even get to this function with !usb_init_count
also check if that is a signed or an unsigned value as usb_init_count =
-1 will evaluate true.
> if (ret)
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware
2026-05-21 1:09 ` [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
2026-05-21 2:37 ` sashiko-bot
@ 2026-05-21 12:00 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: Bryan O'Donoghue @ 2026-05-21 12:00 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, laurentiu.tudor1, alex.vinarskis,
linux-kernel
On 21/05/2026 02:09, Michael Scott wrote:
> qmp_combo_typec_mux_set() updates qmp->qmpphy_mode (the cached state)
> unconditionally, but only reprograms hardware when qmp->init_count is
> non-zero. If pmic_glink_altmode (or any other typec_mux consumer)
> calls into the PHY before DWC3 has performed phy_init() -- a real
> ordering observed during testing of USB-C role-switch enablement on
> Snapdragon X (X1E80100) -- the cache transitions away from the
> probe default QMPPHY_MODE_USB3DP but the hardware is never touched.
>
> Subsequent calls (for example on partner detach, where TYPEC_STATE_SAFE
> also resolves to QMPPHY_MODE_USB3_ONLY in the !DP-SVID branch) then
> match the cached mode and the function bails out early with:
>
> qcom-qmp-combo-phy faXX000.phy: typec_mux_set: same qmpphy mode, bail out
>
> leaving the lane mux in whatever configuration it powered up in. On
> the Dell Latitude 7455 this manifests as the SS lanes being left in
> the default state when the first altmode notification arrives during
> DWC3 probe, with the function bailing out on every subsequent attach.
>
> Track separately whether the cached mode has actually been committed
> to hardware. The bail-out optimization is only safe when the cache
> truly reflects the hardware:
>
> - qmp_combo_typec_mux_set(): bail only when the cached mode matches
> and was committed; clear the committed flag whenever the cache is
> updated, set it again after a successful reprogram inside the
> init_count-guarded block.
>
> - qmp_combo_com_init(): set the committed flag at the end of a
> successful init, since com_init() programs registers from the
> cached qmpphy_mode.
>
> No behavioural change on platforms where typec_mux_set never fires
> before phy_init -- committed remains true through normal operation.
>
> Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 25 +++++++++++++++++++++--
> 1 file changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> index 0db200292642..e28bc1cc7a78 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
> @@ -2295,6 +2295,7 @@ struct qmp_combo {
> struct mutex phy_mutex;
> int init_count;
> enum qmpphy_mode qmpphy_mode;
> + bool qmpphy_mode_committed;
>
> struct phy *usb_phy;
> enum phy_mode phy_mode;
> @@ -3754,6 +3755,9 @@ static int qmp_combo_com_init(struct qmp_combo *qmp, bool force)
> qphy_setbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
> SW_PWRDN);
>
> + /* com_init() just programmed registers from qmp->qmpphy_mode. */
> + qmp->qmpphy_mode_committed = true;
> +
> return 0;
>
> err_disable_clocks:
> @@ -4509,9 +4513,22 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> new_mode = QMPPHY_MODE_USB3_ONLY;
> }
>
> + /*
> + * Fast-path bail only when the cached mode is also known to be
> + * committed to hardware. The cache may be ahead of the hardware
> + * if a typec_mux_set arrived while the PHY had not yet been
> + * initialised (init_count == 0); in that case the cache update
> + * below was the only thing that ran, and we still need to drive
> + * the registers when the PHY does come up.
> + */
> if (new_mode == qmp->qmpphy_mode) {
> - dev_dbg(qmp->dev, "typec_mux_set: same qmpphy mode, bail out\n");
> - return 0;
> + if (qmp->qmpphy_mode_committed) {
> + dev_dbg(qmp->dev,
> + "typec_mux_set: same qmpphy mode (committed), bail out\n");
> + return 0;
> + }
> + dev_dbg(qmp->dev,
> + "typec_mux_set: same qmpphy mode but uncommitted; reprogramming\n");
> }
>
> if (qmp->qmpphy_mode != QMPPHY_MODE_USB3_ONLY && qmp->dp_powered_on) {
> @@ -4523,6 +4540,7 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> qmp->qmpphy_mode, new_mode);
>
> qmp->qmpphy_mode = new_mode;
> + qmp->qmpphy_mode_committed = false;
>
> if (qmp->init_count) {
> if (qmp->usb_init_count)
> @@ -4551,6 +4569,9 @@ static int qmp_combo_typec_mux_set(struct typec_mux_dev *mux, struct typec_mux_s
> if (qmp->dp_init_count)
> cfg->dp_aux_init(qmp);
> }
> +
> + /* Reprogram complete; cache now reflects hardware. */
> + qmp->qmpphy_mode_committed = true;
> }
>
> return 0;
Can we not make the commit to hardware atomic from the perspective of
the caller ?
i.e. use a workqueue and a completion timeout when setting ?
---
bod
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB
2026-05-21 1:09 ` [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
2026-05-21 3:52 ` Val Packett
@ 2026-05-21 12:04 ` Bryan O'Donoghue
1 sibling, 0 replies; 13+ messages in thread
From: Bryan O'Donoghue @ 2026-05-21 12:04 UTC (permalink / raw)
To: Michael Scott, linux-arm-msm
Cc: vkoul, neil.armstrong, dmitry.baryshkov, wesley.cheng, abelvesa,
faisal.hassan, linux-phy, andersson, konradybcio, robh, krzk+dt,
conor+dt, devicetree, val, laurentiu.tudor1, alex.vinarskis,
linux-kernel
On 21/05/2026 02:09, Michael Scott wrote:
> The 128 MiB linux,cma reserved-memory pool on dell-thena is too small
> to support the camera pipeline in parallel with the normal Linux
> desktop. On a freshly-booted system with GNOME running, the typical
> runtime consumers — msm DRM framebuffers (Wayland triple buffering on
> the eDP panel), qcom_iris video codec buffers, qcom_camss VFE
> pre-allocated buffers — already occupy ~100 MiB of the pool, leaving
> only ~25 MiB free.
>
> The libcamera "simple" pipeline handler used by /dev/media0 on
> dell-thena allocates four ABGR8888 frames at 1920×1088 = 32 MiB total.
> That request fails on the fourth frame:
>
> ERROR DmaBufAllocator: dma-heap allocation failure for frame-3
> ERROR Allocator: Stream is not part of /base/.../camera@10 active configuration
> Can't allocate buffers
> Failed to start camera session
>
> resulting in gnome-snapshot's "Could not play camera stream" and any
> other libcamera-mediated app being unable to actually stream.
>
> Bumping linux,cma to 256 MiB (a 0.9% reservation on these laptops'
> typical 27 GiB RAM) leaves ~150 MiB free at runtime — sufficient for
> the libcamera buffer set plus headroom for video playback or other
> CMA-hungry workloads in parallel.
>
> Tested on Dell Latitude 7455: with the 256 MiB pool, CmaFree at
> GNOME-desktop idle is ~150 MiB, gnome-snapshot streams the OV02E10
> camera cleanly, and `cam -c 1 --capture=2` succeeds.
>
> The companion board files dell-inspiron-14-plus-7441 and the upstream
> .dts variants inherit from x1-dell-thena.dtsi, so this changes the
> pool size for every dell-thena-based laptop in one place.
>
> Signed-off-by: Michael Scott <mike.scott@oss.qualcomm.com>
> ---
> arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
> index d6de4da02dcd..714988a81384 100644
> --- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
> +++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi
> @@ -167,7 +167,7 @@ led-camera-indicator {
> reserved-memory {
> linux,cma {
> compatible = "shared-dma-pool";
> - size = <0x0 0x8000000>;
> + size = <0x0 0x10000000>;
> reusable;
> linux,cma-default;
> };
How old is your version of libcamera ?
With CONFIG_UDMA=y you don't need a contiguous memory area at all and
you will get juicy and delicious GPUISP.
Instead of allocating in the kernel just use a better version of libcamera
┌─[deckard@inspiron14p-linux] - [~/Development/libcamera] - [Thu May 21,
13:03]
└─[$] <git:(0.7.0-multipass-v0*)> zcat /proc/config.gz | grep UDMA
CONFIG_UDMABUF=y
┌─[deckard@inspiron14p-linux] - [~/Development/libcamera] - [Thu May 21,
13:03]
└─[$] <git:(0.7.0-multipass-v0*)> cam -v
libcamera version v0.7.1
┌─[deckard@inspiron14p-linux] - [~/Development/libcamera] - [Thu May 21,
13:03]
└─[$] <git:(0.7.0-multipass-v0*)> qcam
[68:50:10.493478857] [438859] INFO Camera camera_manager.cpp:340
libcamera v0.7.1
[68:50:10.511134091] [438863] ERROR V4L2 v4l2_subdevice.cpp:1192
'ov02e10 10-0010': Unable to get rectangle 2 on pad 0/0: Inappropriate
ioctl for device
[68:50:10.511201590] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:402 'ov02e10 10-0010': The PixelArraySize
property has been defaulted to 1928x1088
[68:50:10.511206069] [438863] ERROR V4L2 v4l2_subdevice.cpp:1192
'ov02e10 10-0010': Unable to get rectangle 1 on pad 0/0: Inappropriate
ioctl for device
[68:50:10.511209559] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:413 'ov02e10 10-0010': The
PixelArrayActiveAreas property has been defaulted to (0, 0)/1928x1088
[68:50:10.511213778] [438863] ERROR V4L2 v4l2_subdevice.cpp:1192
'ov02e10 10-0010': Unable to get rectangle 0 on pad 0/0: Inappropriate
ioctl for device
[68:50:10.511216590] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:421 'ov02e10 10-0010': Failed to retrieve the
sensor crop rectangle
[68:50:10.511219559] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:427 'ov02e10 10-0010': The sensor kernel driver
needs to be fixed
[68:50:10.511221746] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:429 'ov02e10 10-0010': See
Documentation/sensor_driver_requirements.rst in the libcamera sources
for more information
[68:50:10.511327474] [438863] WARN CameraSensorProperties
camera_sensor_properties.cpp:538 No static properties available for
'ov02e10'
[68:50:10.511330599] [438863] WARN CameraSensorProperties
camera_sensor_properties.cpp:540 Please consider updating the camera
sensor properties database
[68:50:10.511334089] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:617 'ov02e10 10-0010': Rotation control not
available, default to 0 degrees
[68:50:10.511340912] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:502 'ov02e10 10-0010': No sensor delays found
in static properties. Assuming unverified defaults.
[68:50:10.512362985] [438863] WARN IPAProxy ipa_proxy.cpp:196
Configuration file 'ov02e10.yaml' not found for IPA module 'simple',
falling back to '/usr/share/libcamera/ipa/simple/uncalibrated.yaml'
[68:50:10.512372828] [438863] ERROR V4L2 v4l2_subdevice.cpp:1192
'ov02e10 10-0010': Unable to get rectangle 0 on pad 0/0: Inappropriate
ioctl for device
[68:50:10.512377464] [438863] WARN CameraSensor
camera_sensor_legacy.cpp:881 'ov02e10 10-0010': The analogue crop
rectangle has been defaulted to the active area size
[68:50:10.512386578] [438863] WARN IPASoft soft_simple.cpp:104 IPASoft:
Failed to create camera sensor helper for ov02e10
[68:50:10.512505275] [438863] INFO Camera camera_manager.cpp:223 Adding
camera '/base/soc@0/cci@ac16000/i2c-bus@1/camera@10' for pipeline
handler simple
[68:50:10.548026157] [438859] INFO Camera camera.cpp:1216 configuring
streams: (0) 1920x1088-ABGR8888/sRGB
[68:50:10.548323081] [438863] INFO IPASoft soft_simple.cpp:258 IPASoft:
Exposure 1-2242, gain 16-248 (1)
[68:50:10.548402247] [438863] INFO SoftwareIsp software_isp.cpp:278
Input 1928x1088-GRBG-10-CSI2P stride 2416
Zero-copy enabled
[68:50:10.636862424] [438866] INFO eGL egl.cpp:288 EGL: EGL_VERSION: 1.5
[68:50:10.636899299] [438866] INFO eGL egl.cpp:289 EGL: EGL_VENDOR:
Mesa Project
[68:50:10.636902112] [438866] INFO eGL egl.cpp:290 EGL:
EGL_CLIENT_APIS: OpenGL OpenGL_ES
[68:50:10.636904768] [438866] INFO eGL egl.cpp:291 EGL: EGL_EXTENSIONS:
EGL_ANDROID_blob_cache EGL_ANDROID_native_fence_sync
EGL_EXT_config_select_group EGL_EXT_create_context_robustness
EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers
EGL_EXT_query_reset_notification_strategy EGL_EXT_surface_compression
EGL_IMG_context_priority EGL_KHR_cl_event2 EGL_KHR_config_attribs
EGL_KHR_context_flush_control EGL_KHR_create_context
EGL_KHR_create_context_no_error EGL_KHR_fence_sync
EGL_KHR_get_all_proc_addresses EGL_KHR_gl_colorspace
EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image
EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image
EGL_KHR_image_base EGL_KHR_no_config_context EGL_KHR_reusable_sync
EGL_KHR_surfaceless_context EGL_EXT_pixel_format_float EGL_KHR_wait_sync
EGL_MESA_configless_context EGL_MESA_gl_interop
EGL_MESA_image_dma_buf_export EGL_MESA_query_driver
EGL_MESA_x11_native_visual_id EGL_NV_context_priority_realtime
[68:50:10.643064652] [438866] INFO eGL egl.cpp:332 EGL: GL_VERSION:
OpenGL ES 3.2 Mesa 26.0.6-arch1.1
[68:50:12.667202273] [438866] INFO Benchmark benchmark.cpp:89 Debayer
processed 30 frames in 228802us, 7626 us/frame
┌─[deckard@inspiron14p-linux] - [~/Development/libcamera] - [Thu May 21,
13:03]
└─[$] <git:(0.7.0-multipass-v0*)>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-21 12:04 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-21 1:09 [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Michael Scott
2026-05-21 1:09 ` [PATCH v2 1/4] phy: qcom: qmp-combo: skip USB power_off/exit after device teardown Michael Scott
2026-05-21 1:52 ` sashiko-bot
2026-05-21 11:58 ` Bryan O'Donoghue
2026-05-21 1:09 ` [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware Michael Scott
2026-05-21 2:37 ` sashiko-bot
2026-05-21 12:00 ` Bryan O'Donoghue
2026-05-21 1:09 ` [PATCH v2 3/4] arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on Michael Scott
2026-05-21 4:28 ` Val Packett
2026-05-21 1:09 ` [PATCH v2 4/4] arm64: dts: qcom: x1-dell-thena: bump linux,cma to 256 MiB Michael Scott
2026-05-21 3:52 ` Val Packett
2026-05-21 12:04 ` Bryan O'Donoghue
2026-05-21 4:39 ` [PATCH v2 0/4] phy: qcom: qmp-combo fixes + x1-dell-thena DT maintenance Val Packett
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox