Linux clock framework development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Christian Marangi" <ansuelsmth@gmail.com>,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org
Cc: robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v10 5/5] clk: en7523: add support for Airoha AN7583 clock
Date: Thu, 05 Nov 2026 12:25:20 +0000	[thread overview]
Message-ID: <sashiko-outbox-199026@kernel.org> (raw)
In-Reply-To: <20261105121059.11201-6-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] clk: en7523: sleeping in atomic context in en7581_pci_disable()
- [High] clk: en7523: separate spinlocks fail to serialize shared SCU registers
- [High] clk: en7523: AN7583 MDIO clocks registered as fixed-rate clocks
--

commit 0c38944a68dcbbf6c296bc45b4d9669bdee653fb
Author: Christian Marangi <ansuelsmth@gmail.com>

clk: en7523: add support for Airoha AN7583 clock

This commit adds clock and reset controller support for the Airoha AN7583
SoC, including its base clock descriptors, MDIO clocks, and reset line
mappings.

> diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
> index 979dd9c20a4f2..c1cc6fbc3c019 100644
> --- a/drivers/clk/clk-en7523.c
> +++ b/drivers/clk/clk-en7523.c
[ ... ]
> @@ -372,6 +381,138 @@ static const struct en_clk_desc en7581_base_clks[] = {
>  	}
>  };
>  
> +static const struct en_clk_desc an7583_base_clks[] = {
[ ... ]
> +	}, {
> +		.id = AN7583_CLK_MDIO0,
> +		.name = "mdio0",
> +
> +		.base_reg = REG_CRYPTO_CLKSRC2,
> +
> +		.base_value = 25000000,
> +
> +		.div_bits = 4,
> +		.div_shift = 15,
> +		.div_step = 1,
> +		.div_offset = 1,
> +	}, {
> +		.id = AN7583_CLK_MDIO1,
> +		.name = "mdio1",
> +
> +		.base_reg = REG_CRYPTO_CLKSRC2,
> +
> +		.base_value = 25000000,
> +
> +		.div_bits = 4,
> +		.div_shift = 19,
> +		.div_step = 1,
> +		.div_offset = 1,
> +	}
> +};

[Severity: High]
Can AN7583_CLK_MDIO0 and AN7583_CLK_MDIO1 work as intended when registered
via en7581_register_clocks()?

In drivers/clk/clk-en7523.c, an7583_clk_hw_init() calls
en7581_register_clocks(), which reads the initial hardware register value
at probe time and registers every clock in soc_data->base_clks with
devm_clk_hw_register_fixed_rate():

    hw = devm_clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);

However, in drivers/net/mdio/mdio-airoha.c, airoha_mdio_probe() calls
clk_set_rate(priv->clk, freq) to divide the 25 MHz default MDIO clock down
to 2.5 MHz. Since clk_fixed_rate_ops does not implement .set_rate,
.round_rate, or .determine_rate, clk_set_rate() will return 0 without
programming the 4-bit divider in REG_CRYPTO_CLKSRC2, leaving the MDIO bus
clock running at its 25 MHz boot default. Should the MDIO clocks implement
clockops that support setting the divider rate?

>  static const u16 en7581_rst_ofs[] = {
[ ... ]
> @@ -1152,6 +1351,43 @@ static int en7581_clk_hw_init(struct platform_device *pdev,
>  	return en7581_serdes_phy_register(&pdev->dev);
>  }
>  
> +static int an7583_clk_hw_init(struct platform_device *pdev,
> +			      struct clk_hw_onecell_data *clk_data)
> +{
[ ... ]
> +	en7581_register_clocks(dev, clk_data, map, base);
> +
> +	val = readl(base + REG_RST_CTRL1);
> +	val |= REG_PCIE_HB_RST;
> +	writel(val, base + REG_RST_CTRL1);
> +	val &= ~REG_PCIE_HB_RST;
> +	writel(val, base + REG_RST_CTRL1);
> +
> +	ret = en7581_reset_register(dev, base, an7583_rst_map,
> +				    ARRAY_SIZE(an7583_rst_map),
> +				    en7581_rst_ofs);
> +	if (ret)
> +		return ret;

[Severity: High]
As reported by Sashiko on v6 [1], do cg->lock and rst_data->lock fail to
serialize concurrent read-modify-write accesses to the shared SCU registers?

In drivers/clk/clk-en7523.c, an7583_clk_hw_init() registers the PCIe clock
via en7581_register_clocks() -> en7523_register_pcie_clk() (which allocates
struct en_clk_gate with its own cg->lock) and registers the reset controller
via en7581_reset_register() (which allocates struct en_rst_data with a
separate rst_data->lock) over the same MMIO base.

In an7583_rst_map, AN7583_PCIC_PERSTOUT0_RST and AN7583_PCIC_PERSTOUT1_RST
map to bank 2 of en7581_rst_ofs, which is REG_NP_SCU_PCIC (offset 0x88).
Asserting or deasserting these resets in en7523_reset_update() performs a
readl()/writel() read-modify-write on base + 0x88 under rst_data->lock:

    spin_lock_irqsave(&rst_data->lock, flags);
    val = readl(addr);
    if (assert ^ inverted)
            val |= BIT(id % RST_NR_PER_BANK);
    else
            val &= ~BIT(id % RST_NR_PER_BANK);
    writel(val, addr);
    spin_unlock_irqrestore(&rst_data->lock, flags);

At the same time, en7581_pci_enable() and en7581_pci_disable() perform a
readl()/writel() read-modify-write on the same physical register
REG_PCI_CONTROL (offset 0x88) under cg->lock:

    spin_lock_irqsave(&cg->lock, flags);
    val = readl(np_base + REG_PCI_CONTROL);
    writel(val | mask, np_base + REG_PCI_CONTROL);
    spin_unlock_irqrestore(&cg->lock, flags);

Similarly, on EN7523 and EN751221, en7523_pci_prepare() modifies
REG_RESET_CONTROL1 (offset 0x834) and REG_PCI_CONTROL (offset 0x88) under
cg->lock, while en7523_reset_update() modifies REG_RST_CTRL1 (offset 0x834)
under rst_data->lock. In addition, in en7523_pci_prepare(), after releasing
cg->lock and sleeping in usleep_range(1000, 2000), the code re-acquires
cg->lock and writes back the cached val without re-reading REG_PCI_CONTROL:

    spin_lock_irqsave(&cg->lock, flags);
    val |= REG_PCI_CONTROL_REFCLK_EN1;
    writel(val, np_base + REG_PCI_CONTROL);
    spin_unlock_irqrestore(&cg->lock, flags);

Because cg->lock and rst_data->lock are separate spinlock_t instances, can
concurrent clock and reset operations race and overwrite each other's bit
updates in 0x88 and 0x834?

[ ... ]
> @@ -1305,6 +1541,18 @@ static const struct en_clk_soc_data en7581_data = {
>  	.hw_init = en7581_clk_hw_init,
>  };
>  
> +static const struct en_clk_soc_data an7583_data = {
> +	.base_clks = an7583_base_clks,
> +	/* We increment num_clocks by 1 to account for additional PCIe clock */
> +	.num_clocks = ARRAY_SIZE(an7583_base_clks) + 1,
> +	.pcie_ops = {
> +		.is_enabled = en7581_pci_is_enabled,
> +		.enable = en7581_pci_enable,
> +		.disable = en7581_pci_disable,
> +	},
> +	.hw_init = an7583_clk_hw_init,
> +};

[Severity: High]
As reported by Sashiko on v6 [1], does wiring en7581_pci_disable() to
.disable in an7583_data cause sleeping in atomic context when the PCIe
clock is disabled?

When a consumer calls clk_disable() or clk_disable_unprepare() on
EN7523_CLK_PCIE, the Common Clock Framework holds enable_lock via
spin_lock_irqsave() in clk_core_disable_lock() and calls
core->ops->disable(core->hw).

In drivers/clk/clk-en7523.c, en7581_pci_disable() calls usleep_range()
while enable_lock is held with interrupts disabled:

    spin_lock_irqsave(&cg->lock, flags);
    val = readl(np_base + REG_PCI_CONTROL);
    writel(val & ~mask, np_base + REG_PCI_CONTROL);
    spin_unlock_irqrestore(&cg->lock, flags);

    usleep_range(1000, 2000);

Should this sleep be moved to an .unprepare callback (which runs under the
sleepable prepare_lock mutex, as in en7523_data and en751221_data), or use
a non-sleeping delay such as udelay()?

[1] https://lore.kernel.org/r/20260819222743.5044F1F000E9@smtp.kernel.org

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261105121059.11201-1-ansuelsmth@gmail.com?part=5

      reply	other threads:[~2026-11-05 12:25 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05 12:10 [PATCH v10 0/5] clk: add support for Airoha AN7583 clock Christian Marangi
2026-11-05 12:10 ` [PATCH v10 1/5] dt-bindings: clock: airoha: Document support for " Christian Marangi
2026-11-05 12:10 ` [PATCH v10 2/5] clk: en7523: use devm variant for clk_hw_register and fixed clock Christian Marangi
2026-11-05 12:10 ` [PATCH v10 3/5] clk: en7523: protect concurrent access to reset and PCI register Christian Marangi
2026-11-05 12:22   ` sashiko-bot
2026-11-05 12:10 ` [PATCH v10 4/5] clk: en7523: generalize register clocks function Christian Marangi
2026-11-05 12:10 ` [PATCH v10 5/5] clk: en7523: add support for Airoha AN7583 clock Christian Marangi
2026-11-05 12:25   ` 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=sashiko-outbox-199026@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=ansuelsmth@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-clk@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