Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Imran Shaik" <imran.shaik@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v2 04/10] ptp: qcom: Add PTP driver for the Qualcomm TSC hardware
Date: Mon, 09 Nov 2026 13:19:54 +0000	[thread overview]
Message-ID: <sashiko-outbox-205001@kernel.org> (raw)
In-Reply-To: <20261108-tscss-v2-4-d5f575010427@oss.qualcomm.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] ptp: qcom: torn 64-bit counter read in qcom_tsc_read_time() on
  rollover
- [High] ptp: qcom: period truncated to 0 for small negative ppb in
  adjfine()
- [Medium] ptp: qcom: ahb_clk and devres leak in
  qcom_tsc_enable_clocks() on error
- [Medium] ptp: qcom: uninitialized clock at probe and skipped config in
  qcom_tsc_settime()
--

commit 9c266c0baa9449c0c5ca7b1a7e003c4cbd0cb88b
Author: Imran Shaik <imran.shaik@oss.qualcomm.com>

ptp: qcom: Add PTP driver for the Qualcomm TSC hardware

This commit adds a PTP Hardware Clock driver for the Qualcomm Timestamp
Counter (TSC) hardware on SA8775P, QDU1000, and Nord SoCs.

> diff --git a/drivers/ptp/ptp_qcom_tsc.c b/drivers/ptp/ptp_qcom_tsc.c
> new file mode 100644
> index 0000000000000..82ddbdd63389d
> --- /dev/null
> +++ b/drivers/ptp/ptp_qcom_tsc.c
> @@ -0,0 +1,598 @@

[ ... ]

> +static int qcom_tsc_read_time(struct qcom_tsc *tsc, struct timespec64 *ts)
> +{
> +	const struct qcom_tsc_regs *regs = tsc->soc->reg_layout;
> +	u32 hi, lo;
> +
> +	if (!qcom_tsc_is_enabled(tsc))
> +		return -EINVAL;
> +
> +	hi = readl_relaxed(tsc->base + regs->read_cntcv_hi);
> +	lo = readl_relaxed(tsc->base + regs->read_cntcv_lo);

[Severity: High]
Can read_cntcv_lo roll over between reading read_cntcv_hi and
read_cntcv_lo?  If the lower word wraps between the two 32-bit reads, the
old upper word is paired with the post-rollover lower word, returning a
timestamp that jumps backward by 1 second (when rollover is true) or ~4.295
seconds (when rollover is false).  Because qcom_tsc_settime() and
qcom_tsc_update_offset() call qcom_tsc_read_time() to compute the delta or
new counter value written back to the hardware, a torn read during
settime64() or adjtime() also permanently shifts the hardware clock.
Re-reading read_cntcv_hi in a loop until two consecutive upper-word reads
match would avoid this.

[ ... ]

> +static int qcom_tsc_enable_clocks(struct qcom_tsc *tsc)
> +{
> +	int ret;
> +
> +	if (tsc->clocks_enabled)
> +		return 0;
> +
> +	ret = clk_prepare_enable(tsc->ahb_clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = devm_add_action_or_reset(tsc->dev, qcom_tsc_clk_disable, tsc->ahb_clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(tsc->cntr_clk);
> +	if (ret)
> +		return ret;
> +
> +	ret = devm_add_action_or_reset(tsc->dev, qcom_tsc_clk_disable, tsc->cntr_clk);
> +	if (ret)
> +		return ret;
> +
> +	tsc->clocks_enabled = true;
> +
> +	return 0;
> +}

[Severity: Medium]
If enabling tsc->cntr_clk or registering its devm action fails here, does
tsc->ahb_clk remain enabled with tsc->clocks_enabled still false?  Because
qcom_tsc_enable_clocks() runs from the runtime .settime64 callback rather
than probe, returning an error does not unwind devres actions on tsc->dev,
and each subsequent qcom_tsc_settime() call will prepare_enable
tsc->ahb_clk and queue another devres action again.

[ ... ]

> +static int qcom_tsc_drift_correction(struct qcom_tsc *tsc, long scaled_ppm)
> +{
> +	const struct qcom_tsc_soc_data *soc = tsc->soc;
> +	const struct qcom_tsc_regs *regs = soc->reg_layout;
> +	long ppb = scaled_ppm_to_ppb(scaled_ppm);
> +	u64 period, incval = 0;
> +	u32 regval = 0, subperiod;
> +
> +	if (ppb == 0)
> +		return 0;
> +
> +	if (ppb < 0) {
> +		ppb = -ppb;
> +		regval &= ~DRIFT_JUMP_SWALLOW;
> +
> +		period = div_u64(ppb, soc->cntr_res);
> +		if (period >= DRIFT_MAX_RES)
> +			period = DRIFT_MAX_RES;
> +	} else {
> +		regval |= DRIFT_JUMP_SWALLOW;
> +
> +		period = div_u64(ppb, soc->cntr_res);
> +		if (period >= DRIFT_MAX_RES) {
> +			period = DRIFT_MAX_RES;
> +			incval = soc->cntr_res * 2;
> +		} else if (ppb < soc->cntr_res) {
> +			incval = soc->cntr_res + ppb;
> +			period = 1;
> +		} else {
> +			incval = soc->cntr_res * 2;
> +		}
> +	}

[Severity: High]
Does the negative ppb branch truncate period to 0 when 0 < -ppb <
soc->cntr_res (for example, -63 <= ppb <= -1 on SA8775P where cntr_res is
64)?  Unlike the positive branch, which clamps period to 1 and adjusts
incval when ppb < soc->cntr_res, the negative branch leaves period = 0 and
incval = 0 and triggers drift_correct_cmd with a zero period, dropping fine
negative frequency adjustments during PTP synchronization.

[ ... ]

> +static int qcom_ptp_tsc_probe(struct platform_device *pdev)
> +{

[ ... ]

> +	/* Both clocks are enabled on first use, when the counter is set */
> +	tsc->ahb_clk = devm_clk_get(&pdev->dev, "ahb");
> +	if (IS_ERR(tsc->ahb_clk))
> +		return PTR_ERR(tsc->ahb_clk);
> +
> +	tsc->cntr_clk = devm_clk_get(&pdev->dev, "cntr");
> +	if (IS_ERR(tsc->cntr_clk))
> +		return PTR_ERR(tsc->cntr_clk);
> +
> +	tsc->ptp_info = qcom_ptp_info;
> +
> +	tsc->ptp = ptp_clock_register(&tsc->ptp_info, &pdev->dev);

[Severity: Medium]
Should the clocks and hardware counter be initialized before
ptp_clock_register() exposes the PHC?  Because tsc->clocks_enabled starts
as false and the counter is only enabled in qcom_tsc_settime(), any
gettime64(), adjtime(), adjfine(), or virtual clock creation
(n_vclocks_store() -> ptp_vclock_register()) fails with -EINVAL until
userspace calls clock_settime().  In addition, if BIT(0) in control_cntcr
is already set at probe (from firmware or a prior driver bind/unbind, since
qcom_ptp_tsc_remove() does not disable the counter), the first
qcom_tsc_settime() call sees qcom_tsc_is_enabled(tsc) == true and takes the
qcom_tsc_update_offset() path without programming PULSE_WIDTH_MASK or
ROLLOVER_VAL:

drivers/ptp/ptp_qcom_tsc.c:qcom_tsc_settime() {
    ...
	if (qcom_tsc_is_enabled(tsc)) {
		qcom_tsc_read_time(tsc, &tod);
		ret = qcom_tsc_update_offset(tsc, timespec64_sub(*ts, tod));
		mutex_unlock(&tsc->lock);
		return ret;
	}

	/* Configure and enable the TSC counter */
	regval = readl_relaxed(tsc->base + regs->control_cntcr);
	regval &= ~PULSE_WIDTH_MASK;
	regval |= FIELD_PREP(PULSE_WIDTH_MASK, tsc->soc->pulse_width);
	writel_relaxed(regval, tsc->base + regs->control_cntcr);

	if (tsc->soc->rollover)
		writel_relaxed(ROLLOVER_VAL, tsc->base + regs->rollover_val);
    ...
}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-tscss-v2-0-d5f575010427@oss.qualcomm.com?part=4

  reply	other threads:[~2026-11-09 13:19 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 13:18 [PATCH v2 00/10] Add support for Qualcomm TSCSS hardware Imran Shaik
2026-11-08 13:18 ` [PATCH v2 01/10] dt-bindings: ptp: Document the TSCSS on Qualcomm SA8775P and QCS8300 SoCs Imran Shaik
2026-11-09 12:48   ` Krzysztof Kozlowski
2026-11-09 13:19   ` sashiko-bot
2026-11-08 13:18 ` [PATCH v2 02/10] dt-bindings: ptp: Document TSCSS hardware on Qualcomm QDU1000 SoC Imran Shaik
2026-11-09 12:49   ` Krzysztof Kozlowski
2026-11-08 13:18 ` [PATCH v2 03/10] dt-bindings: ptp: Document TSCSS hardware on Qualcomm Nord and Shikra SoCs Imran Shaik
2026-11-09 12:51   ` Krzysztof Kozlowski
2026-11-09 13:19   ` sashiko-bot
2026-11-08 13:18 ` [PATCH v2 04/10] ptp: qcom: Add PTP driver for the Qualcomm TSC hardware Imran Shaik
2026-11-09 13:19   ` sashiko-bot [this message]
2026-11-08 13:18 ` [PATCH v2 05/10] arm64: defconfig: Enable Qualcomm TSC driver Imran Shaik
2026-11-08 13:18 ` [PATCH v2 06/10] arm64: dts: qcom: lemans: Add support for TSCSS node Imran Shaik
2026-11-09 12:52   ` Krzysztof Kozlowski
2026-11-09 13:19   ` sashiko-bot
2026-11-08 13:18 ` [PATCH v2 07/10] arm64: dts: qcom: monaco: " Imran Shaik
2026-11-08 13:18 ` [PATCH v2 08/10] arm64: dts: qcom: qdu1000: " Imran Shaik
2026-11-09 12:52   ` Krzysztof Kozlowski
2026-11-08 13:18 ` [PATCH v2 09/10] arm64: dts: qcom: shikra: " Imran Shaik
2026-11-08 13:18 ` [PATCH v2 10/10] arm64: dts: qcom: nord: " Imran Shaik
2026-11-09  8:43   ` Shawn Guo
2026-11-09 12:52   ` Krzysztof Kozlowski

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=sashiko-outbox-205001@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=imran.shaik@oss.qualcomm.com \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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