Re: [PATCH] i3c: master: adi: initialize the lock before enabling interrupts

Frank Li <[email protected]>
Newsgroups org.infradead.lists.linux-i3c,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <ajMG_yuwzqGhjaBD@lizhi-Precision-Tower-5810>
On Wed, Jun 17, 2026 at 11:01:38PM +0800, Runyu Xiao wrote:
> adi_i3c_master_probe() requests the IRQ and unmasks REG_IRQ_PENDING_CMDR
> before the controller's IBI state, transfer queue list and transfer
> queue lock are initialized.  A pending CMDR interrupt can therefore run
> adi_i3c_master_irq() and take master->xferqueue.lock before the dynamic
> lock has been initialized.
>
> This issue was found by our static analysis tool and then manually
> reviewed against the current tree.
>
> The grounded PoC kept the probe ordering and the IRQ path
> adi_i3c_master_probe() -> adi_i3c_master_irq() -> xferqueue.lock, with a
> pending CMDR interrupt arriving after REG_IRQ_PENDING_CMDR is unmasked.
> Lockdep reported:
>
>   INFO: trying to register non-static key.
>   you didn't initialize this object before use?
>   lock_acquire+0xbb/0x290
>   _raw_spin_lock_irqsave+0x36/0x60
>   adi_i3c_master_irq+0x32/0x56 [vuln_msv]
>   adi_i3c_master_probe+0x5a/0xf47 [vuln_msv]
>
> Initialize the transfer queue and IBI state before requesting and
> unmasking the IRQ.
>
> Fixes: a79ac2cdc91d ("i3c: master: Add driver for Analog Devices I3C Controller IP")
> Cc: [email protected]
> Signed-off-by: Runyu Xiao <[email protected]>
> ---

Reviewed-by: Frank Li <[email protected]>

>  drivers/i3c/master/adi-i3c-master.c | 15 +++++++--------
>  1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/i3c/master/adi-i3c-master.c b/drivers/i3c/master/adi-i3c-master.c
> index 82ac0b3d057a..cf873d46e10f 100644
> --- a/drivers/i3c/master/adi-i3c-master.c
> +++ b/drivers/i3c/master/adi-i3c-master.c
> @@ -967,17 +967,9 @@ static int adi_i3c_master_probe(struct platform_device *pdev)
>  	writel(0x00, master->regs + REG_ENABLE);
>  	writel(0x00, master->regs + REG_IRQ_MASK);
>
> -	ret = devm_request_irq(&pdev->dev, irq, adi_i3c_master_irq, 0,
> -			       dev_name(&pdev->dev), master);
> -	if (ret)
> -		return ret;
> -
>  	platform_set_drvdata(pdev, master);
>
>  	master->free_rr_slots = GENMASK(ADI_MAX_DEVS, 1);
> -
> -	writel(REG_IRQ_PENDING_CMDR, master->regs + REG_IRQ_MASK);
> -
>  	spin_lock_init(&master->ibi.lock);
>  	master->ibi.num_slots = 15;
>  	master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots,
> @@ -989,6 +981,13 @@ static int adi_i3c_master_probe(struct platform_device *pdev)
>  	spin_lock_init(&master->xferqueue.lock);
>  	INIT_LIST_HEAD(&master->xferqueue.list);
>
> +	ret = devm_request_irq(&pdev->dev, irq, adi_i3c_master_irq, 0,
> +			       dev_name(&pdev->dev), master);
> +	if (ret)
> +		return ret;
> +
> +	writel(REG_IRQ_PENDING_CMDR, master->regs + REG_IRQ_MASK);
> +
>  	return i3c_master_register(&master->base, &pdev->dev,
>  				   &adi_i3c_master_ops, false);
>  }
> --
> 2.34.1
>

-- 
linux-i3c mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-i3c
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.