Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ali Rouhi" <arouhi@sitime.com>
Cc: conor+dt@kernel.org, devicetree@vger.kernel.org, robh@kernel.org
Subject: Re: [PATCH net-next v6 3/3] dpll: add SiTime SiT9531x DPLL clock driver
Date: Thu, 13 Aug 2026 17:56:01 +0000	[thread overview]
Message-ID: <20260813175601.D57C31F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260812175337.18155-4-arouhi@sitime.com>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] Use-After-Free of Pin Properties and Frequency Arrays
- [High] State Mismatch / Logic Flaw in Pin Getters
- [High] Destructive Priority Overwrite in Hardware Table
- [High] Use-After-Free on Probe Error Path Due to Missing DPLL Unregistration
- [Medium] Silent Failure on Manual Pin Connection Request
- [Medium] Missing SYSREF/SYNCB/Pulser Features
- [Medium] Hardware Routing Loop via INTSYNC
--

--- Patch [3]: [PATCH net-next v6 3/3] dpll: add SiTime SiT9531x DPLL clock driver ---
commit 841a91aff3f30b8a2e2bee8952633134d7bbdee2
Author: Ali Rouhi <arouhi@sitime.com>
Subject: dpll: add SiTime SiT9531x DPLL clock driver
Summary: This commit adds a DPLL subsystem driver for the SiTime SiT95316
and SiT95317 clock generators. It supports hardware state monitoring, priority
management, and frequency/phase configuration.

>  - SYSREF/SYNCB/Pulser output mode control

[Severity: Medium]
Is this functionality fully exposed to userspace? The commit message mentions
support for SYSREF/SYNCB/Pulser modes, but looking at the driver,
sit9531x_output_pulse_ctrl_set() only appears to be called with a hardcoded
default during embedded sync setup. It looks like the other modes might not
be reachable.

> diff --git a/drivers/dpll/sit9531x/core.c b/drivers/dpll/sit9531x/core.c
> index 0000000000000..711ab16b0897a
> --- /dev/null
> +++ b/drivers/dpll/sit9531x/core.c

[ ... ]

> @@ -596,32 +596,25 @@ int sit9531x_input_prio_set(struct sit9531x_dev *sitdev, u8 pll_idx,
>  
>  	usleep_range(10000, 12000);
>  
>  	/*
>  	 * Write the requested slot on Page 1, then fill the remaining
>  	 * slots with the same source, matching the procedure script's
>  	 * backfill behaviour.
>  	 */
>  	for (slot = prio; slot < SIT9531X_PRIO_MAX_SLOTS; slot++) {
>  		reg = sit9531x_prio_reg(pll_idx, slot);
>  
>  		rc = sit9531x_read_u8(sitdev, reg, &val);
>  		if (rc)
>  			goto commit;
>  
>  		val = sit9531x_prio_slot_set(val, slot, input_idx);

[Severity: High]
Does this loop unintentionally wipe out fallback configurations? When userspace
sets a priority, this loop fills not only the requested slot but also all
lower-priority slots with the exact same input source. This appears to destroy
any other fallback inputs the user might have configured in the hardware table.

[ ... ]

> @@ -2496,25 +2496,15 @@ int sit9531x_dev_start(struct sit9531x_dev *sitdev)
>  	if (rc)
>  		return rc;
>  
>  	list_for_each_entry(sitdpll, &sitdev->dplls, list) {
>  		rc = sit9531x_dpll_register(sitdpll);
>  		if (rc) {
>  			dev_err_probe(sitdev->dev, rc,
>  				      "Failed to register DPLL%u\n",
>  				      sitdpll->id);
>  			return rc;
>  		}
>  	}

[ ... ]

> @@ -2825,18 +2815,10 @@ static void sit9531x_dpll_list_free(struct sit9531x_dev *sitdev)
>  {
>  	struct sit9531x_dpll *sitdpll, *next;
>  
>  	list_for_each_entry_safe(sitdpll, next, &sitdev->dplls, list) {
>  		list_del(&sitdpll->list);
>  		sit9531x_dpll_free(sitdpll);
>  	}
>  }

[Severity: High]
Could this error path leave the DPLL subsystem with dangling pointers? If
sit9531x_dpll_register() succeeds for the first DPLL but fails for the next,
sit9531x_dev_start() returns an error without unwinding the already
registered DPLLs. The error handler in sit9531x_devm_dpll_init() then calls
sit9531x_dpll_list_free() to free the backing memory directly, bypassing
dpll_device_unregister() and dpll_pin_unregister().

> diff --git a/drivers/dpll/sit9531x/dpll.c b/drivers/dpll/sit9531x/dpll.c
> index 0000000000000..364f870ac3041
> --- /dev/null
> +++ b/drivers/dpll/sit9531x/dpll.c

[ ... ]

> @@ -259,32 +259,25 @@ static int
>  sit9531x_dpll_input_pin_state_on_dpll_get(const struct dpll_pin *pin,
>  					  void *pin_priv,
>  					  const struct dpll_device *dpll,
>  					  void *dpll_priv,
>  					  enum dpll_pin_state *state,
>  					  struct netlink_ext_ack *extack)
>  {

[ ... ]

>  	if (chan->locked && !chan->inner_lol &&
>  	    chan->selected_ref == dpin->id)
>  		*state = DPLL_PIN_STATE_CONNECTED;
>  	/* In auto mode, enabled inputs with good signal are selectable */
>  	else if (!chan->mode && ref->enabled && !ref->los && !ref->oof)
>  		*state = DPLL_PIN_STATE_SELECTABLE;
>  	else
>  		*state = DPLL_PIN_STATE_DISCONNECTED;

[Severity: High]
Might this logic report an incorrect routing state? The ref->enabled flag
represents a global physical state for the pin. If DPLL A requests an input
and enables the receiver, DPLL B will also see ref->enabled as true and
report the pin as DPLL_PIN_STATE_SELECTABLE, even if that pin isn't in DPLL
B's priority table.

Additionally, if a signal is lost (ref->los becomes true), this drops the
state to DPLL_PIN_STATE_DISCONNECTED. Does the DPLL API expect degraded pins
to still show as logically connected or selectable rather than entirely
disconnected?

[ ... ]

> @@ -326,32 +319,25 @@ static int
>  sit9531x_dpll_input_pin_state_on_dpll_set(const struct dpll_pin *pin,
>  					  void *pin_priv,
>  					  const struct dpll_device *dpll,
>  					  void *dpll_priv,
>  					  enum dpll_pin_state state,
>  					  struct netlink_ext_ack *extack)
>  {

[ ... ]

>  	switch (state) {
>  	case DPLL_PIN_STATE_DISCONNECTED:
>  		rc = sit9531x_input_prio_remove(sitdev, sitdpll->id, hw_src);
>  		if (rc)
>  			break;
>  		ref->pll_mask &= ~pll_bit;
>  		if (ref->pll_mask)
>  			rc = 0;	/* another DPLL still uses this input */
>  		else
>  			rc = sit9531x_input_disable(sitdev, dpin->id);
>  		break;
>  	case DPLL_PIN_STATE_SELECTABLE:
>  	case DPLL_PIN_STATE_CONNECTED:
>  		rc = sit9531x_input_enable(sitdev, dpin->id);
>  		if (rc)
>  			break;
>  		rc = sit9531x_input_prio_add(sitdev, sitdpll->id, hw_src);

[Severity: Medium]
Should DPLL_PIN_STATE_CONNECTED enforce a manual lock here? It appears to
fall through to the exact same logic as DPLL_PIN_STATE_SELECTABLE, adding
the input to the priority table but leaving the hardware in automatic
selection mode instead of forcing a connection.

[ ... ]

> @@ -651,32 +637,25 @@ static int
>  sit9531x_dpll_intsync_src_state_on_dpll_set(const struct dpll_pin *pin,
>  					    void *pin_priv,
>  					    const struct dpll_device *dpll,
>  					    void *dpll_priv,
>  					    enum dpll_pin_state state,
>  					    struct netlink_ext_ack *extack)
>  {

[ ... ]

>  	switch (state) {
>  	case DPLL_PIN_STATE_CONNECTED:
>  		if (sitdev->intsync_src == sitdpll->id)
>  			break;
>  		if (sitdev->intsync_src >= 0) {
>  			NL_SET_ERR_MSG(extack,
>  				       "INTSYNC is already sourced by another PLL");
>  			rc = -EBUSY;
>  			break;
>  		}
>  		rc = sit9531x_intsync_enable(sitdev, sitdpll->id);

[Severity: Medium]
Is there a protection missing here against hardware routing loops? While the
destination getter correctly prevents adding INTSYNC to a PLL's priority
table if that PLL is already the source, this function doesn't seem to check
if the PLL already has INTSYNC as a destination before making it the source.
Could userspace configure a PLL to source from INTSYNC and then drive INTSYNC
with the same PLL?

> diff --git a/drivers/dpll/sit9531x/prop.c b/drivers/dpll/sit9531x/prop.c
> index 0000000000000..8a0105c8c6472
> --- /dev/null
> +++ b/drivers/dpll/sit9531x/prop.c

[ ... ]

> @@ -357,10 +357,8 @@ void sit9531x_pin_props_put(struct sit9531x_pin_props *props)
>  {
>  	kfree(props->dpll_props.freq_supported);
>  
>  	if (props->fwnode)
>  		fwnode_handle_put(props->fwnode);
>  
>  	kfree(props);
>  }

[Severity: Critical]
Will this lead to a use-after-free when userspace queries the pin properties?
The sit9531x_pin_props_get() function dynamically allocates both the props
structure and the freq_supported array. When passed into dpll_pin_get()
in sit9531x_dpll_pin_register(), the DPLL core retains those pointers.
Since sit9531x_pin_props_put() immediately frees these allocations on the
success path, it looks like the DPLL core might be left holding dangling
pointers.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260812175337.18155-1-arouhi@sitime.com?part=3

      reply	other threads:[~2026-08-13 17:56 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12 17:55 [PATCH net-next v6 0/3] dpll: add SiTime SiT9531x DPLL clock driver Ali Rouhi
2026-08-12 17:55 ` [PATCH net-next v6 1/3] dt-bindings: vendor-prefixes: add SiTime Corporation Ali Rouhi
2026-08-12 17:55 ` [PATCH net-next v6 2/3] dt-bindings: dpll: add SiTime SiT95316 clock generator Ali Rouhi
2026-08-13  7:35   ` Krzysztof Kozlowski
2026-08-12 17:55 ` [PATCH net-next v6 3/3] dpll: add SiTime SiT9531x DPLL clock driver Ali Rouhi
2026-08-13 17:56   ` sashiko-bot [this message]

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=20260813175601.D57C31F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=arouhi@sitime.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --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