Linux-PHY Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Michael Scott" <mike.scott@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
	vkoul@kernel.org, neil.armstrong@linaro.org, olteanv@gmail.com,
	linux-phy@lists.infradead.org
Subject: Re: [PATCH v2 2/4] phy: qcom: qmp-combo: track whether the cached typec_mux mode was committed to hardware
Date: Thu, 21 May 2026 02:37:51 +0000	[thread overview]
Message-ID: <20260521023751.B46421F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260521010935.1333494-3-mike.scott@oss.qualcomm.com>

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

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

  reply	other threads:[~2026-05-21  2:37 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260521023751.B46421F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=mike.scott@oss.qualcomm.com \
    --cc=neil.armstrong@linaro.org \
    --cc=olteanv@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox