From jarkko.nikula at linux.intel.com  Mon Mar  3 00:09:58 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Mon, 3 Mar 2025 10:09:58 +0200
Subject: [PATCH 2/4] i3c: mipi-i3c-hci: Fix handling status of
 i3c_hci_irq_handler()
In-Reply-To: <Z8Hg+o/oOPUd3oL7@lizhi-Precision-Tower-5810>
References: <20250228141802.1344453-1-jarkko.nikula@linux.intel.com>
 <20250228141802.1344453-2-jarkko.nikula@linux.intel.com>
 <Z8Hg+o/oOPUd3oL7@lizhi-Precision-Tower-5810>
Message-ID: <0efe8cc1-dd25-4052-a930-73e76c181307@linux.intel.com>

Hi

On 2/28/25 6:14 PM, Frank Li wrote:
> On Fri, Feb 28, 2025 at 04:18:00PM +0200, Jarkko Nikula wrote:
>> Return IRQ_HANDLED from the i3c_hci_irq_handler() only if some
>> INTR_STATUS bit was set or if DMA/PIO handler handled it.
>>
>> Currently it returns IRQ_HANDLED in case INTR_STATUS is zero and IO
>> handler returns false. Which could be the case if interrupt comes from
>> other device or is spurious.
>>
>> Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
>> ---
>>   drivers/i3c/master/mipi-i3c-hci/core.c | 6 +++---
>>   1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
>> index e139d7e4d252..e5593b6e897e 100644
>> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
>> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
>> @@ -594,6 +594,7 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
>>
>>   	if (val) {
>>   		reg_write(INTR_STATUS, val);
>> +		result = IRQ_HANDLED;
> 
> Not related this patch.
> reg_write(INTR_STATUS, val); should be unconditional since INTR_STATUS is
> w1c.
> 
> I am strange why need return IRQ_NONE case. I suppose it should always
> return IRQ_HANDLED.
> 
This makes driver more ready for shared interrupts and let kernel 
interrupt code be able to disable bad behaving interrupt (misrouted, 
wrong polarity, etc) by returning IRQ_NONE when we know interrupt wasn't 
generated by this device.

Currently driver doesn't support shared interrupts since IRQF_SHARED 
flag is not passed to the devm_request_irq() call in i3c_hci_probe(). I 
didn't change that since I don't have a setup to test.


From Frank.li at nxp.com  Mon Mar  3 11:48:28 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 3 Mar 2025 14:48:28 -0500
Subject: [PATCH v5 3/5] i3c: master: svc: Fix npcm845 FIFO empty issue
In-Reply-To: <Z8CfhvcoQSKsk3Ev@lizhi-Precision-Tower-5810>
References: <20250227060131.2206860-1-yschu@nuvoton.com>
 <20250227060131.2206860-4-yschu@nuvoton.com>
 <Z8CfhvcoQSKsk3Ev@lizhi-Precision-Tower-5810>
Message-ID: <Z8YHjNx+VBy/Ic07@lizhi-Precision-Tower-5810>

On Thu, Feb 27, 2025 at 12:23:18PM -0500, Frank Li wrote:
> On Thu, Feb 27, 2025 at 02:01:29PM +0800, Stanley Chu wrote:
> > From: Stanley Chu <yschu at nuvoton.com>
> >
> > I3C HW stalls the write transfer if the transmit FIFO becomes empty,
> > when new data is written to FIFO, I3C HW resumes the transfer but the
> > first transmitted data bit may have the wrong value.
> > Fill the FIFO in advance to prevent FIFO from becoming empty.
> >
> > Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> > ---
> >  drivers/i3c/master/svc-i3c-master.c | 52 ++++++++++++++++++++++++-----
> >  1 file changed, 43 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > index 9143a079de53..a0c6d8053a25 100644
> > --- a/drivers/i3c/master/svc-i3c-master.c
> > +++ b/drivers/i3c/master/svc-i3c-master.c
> > @@ -114,6 +114,7 @@
> >  #define SVC_I3C_MWDATAHE     0x0BC
> >  #define SVC_I3C_MRDATAB      0x0C0
> >  #define SVC_I3C_MRDATAH      0x0C8
> > +#define SVC_I3C_MWDATAB1     0x0CC
> >  #define SVC_I3C_MWMSG_SDR    0x0D0
> >  #define SVC_I3C_MRMSG_SDR    0x0D4
> >  #define SVC_I3C_MWMSG_DDR    0x0D8
> > @@ -940,7 +941,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> >  					u8 *addrs, unsigned int *count)
> >  {
> >  	u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
> > -	unsigned int dev_nb = 0, last_addr = 0;
> > +	unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
> >  	u32 reg;
> >  	int ret, i;
> >
> > @@ -983,6 +984,25 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> >  		if (SVC_I3C_MSTATUS_RXPEND(reg)) {
> >  			u8 data[6];
> >
> > +			/*
> > +			 * One slave sends its ID to request for address assignment,
> > +			 * prefilling the dynamic address can reduce SCL clock stalls
> > +			 * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk.
> > +			 *
> > +			 * Ideally, prefilling before the processDAA command is better.
> > +			 * However, it requires an additional check to write the dyn_addr
> > +			 * at the right time because the driver needs to write the processDAA
> > +			 * command twice for one assignment.
> > +			 * Prefilling here is safe and efficient because the FIFO starts
> > +			 * filling within a few hundred nanoseconds, which is significantly
> > +			 * faster compared to the 64 SCL clock cycles.
> > +			 */
> > +			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > +			if (dyn_addr < 0)
> > +				return -ENOSPC;
> > +
> > +			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
> > +
> >  			/*
> >  			 * We only care about the 48-bit provisioned ID yet to
> >  			 * be sure a device does not nack an address twice.
> > @@ -1061,21 +1081,16 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> >  		if (ret)
> >  			break;
> >
> > -		/* Give the slave device a suitable dynamic address */
> > -		ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > -		if (ret < 0)
> > -			break;
> > -
> > -		addrs[dev_nb] = ret;
> > +		addrs[dev_nb] = dyn_addr;
> >  		dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
> >  			dev_nb, addrs[dev_nb]);
> > -
> > -		writel(addrs[dev_nb], master->regs + SVC_I3C_MWDATAB);
> >  		last_addr = addrs[dev_nb++];
> >  	}
> >
> >  	/* Need manual issue STOP except for Complete condition */
> >  	svc_i3c_master_emit_stop(master);
> > +	svc_i3c_master_flush_fifo(master);
> > +
> >  	return ret;
> >  }
> >
> > @@ -1272,6 +1287,24 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
> >  		       SVC_I3C_MCTRL_RDTERM(*actual_len),
> >  		       master->regs + SVC_I3C_MCTRL);
> >
> > +		/*
> > +		 * The entire transaction can consist of multiple write transfers.
> > +		 * Prefilling before EmitStartAddr causes the data to be emitted
> > +		 * immediately, becoming part of the previous transfer.
> > +		 * The only way to work around this hardware issue is to let the
> > +		 * FIFO start filling as soon as possible after EmitStartAddr.
> > +		 */
> > +		if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) {
> > +			u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : BIT(8);
>
> Define BIT(8) as macro
>
> Let me find a time at next week to do simple test for this.


I run basic test, it is fine!

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>
> > +			u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE);
> > +
> > +			writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1);
> > +			/* Mark END bit if this is the last byte */
> > +			writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB);
> > +			xfer_len -= len;
> > +			out += len;
> > +		}
> > +
> >  		ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
> >  				 SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000);
> >  		if (ret)
> > @@ -1360,6 +1393,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
> >  emit_stop:
> >  	svc_i3c_master_emit_stop(master);
> >  	svc_i3c_master_clear_merrwarn(master);
> > +	svc_i3c_master_flush_fifo(master);
> >
> >  	return ret;
> >  }
> > --
> > 2.34.1
> >


From conor at kernel.org  Mon Mar  3 09:11:27 2025
From: conor at kernel.org (Conor Dooley)
Date: Mon, 3 Mar 2025 17:11:27 +0000
Subject: [PATCH v2 1/4] dt-bindings: i3c: silvaco: Add npcm845 compatible
 string
In-Reply-To: <20250220054330.1711979-2-yschu@nuvoton.com>
References: <20250220054330.1711979-1-yschu@nuvoton.com>
 <20250220054330.1711979-2-yschu@nuvoton.com>
Message-ID: <20250303-chest-presoak-5d3f3b821d1f@spud>

On Thu, Feb 20, 2025 at 01:43:27PM +0800, Stanley Chu wrote:
> Add a compatible string for Nuvoton BMC NPCM845 i3c controller.

Why is a fallback not an option here? Your commit message should call
out why not.

> 
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> ---
>  Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> index c56ff77677f1..9be4bc4cc482 100644
> --- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> +++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
> @@ -14,7 +14,9 @@ allOf:
>  
>  properties:
>    compatible:
> -    const: silvaco,i3c-master-v1
> +    enum:
> +      - silvaco,i3c-master-v1
> +      - nuvoton,npcm845-i3c
>  
>    reg:
>      maxItems: 1
> -- 
> 2.34.1
> 
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-i3c/attachments/20250303/39d4d1ce/attachment.sig>

From stanley.chuys at gmail.com  Tue Mar  4 19:44:09 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:09 +0800
Subject: [PATCH v6 0/5] Add support for Nuvoton npcm845 i3c controller
Message-ID: <20250305034414.2246870-1-yschu@nuvoton.com>

This patchset adds support for the Nuvoton npcm845
Board Management controller (BMC) SoC family.

The Nuvoton npcm845 uses the same Silvico IP but an older version.
This patchset adds fixes for the npcm845 specific hardware issues.

--
v6:
 - Define QUIRK when it is really used in the separate patches.

v5:
 - Add default driver data
 - Add helper function svc_has_daa_corrupt()
 - Revise SVC_I3C_QUIRK_FIFO_EMPTY fix and add comments

v4:
 - Fix kernel test robot build warning.
 - Add SVC_I3C_QUIRK_DAA_CORRUPT fix

v3:
 - Add more description in dt-binging commit message
 - Add the svc_i3c_drvdata structure in struct svc_i3c_master
 - Improve the do_daa

v2:
 - Add a new compatible string in dt-binding doc.
 - Add driver data for npcm845 to address the quirks.
 - Modify svc_i3c_master_write to be reused by SVC_I3C_QUIRK_FIFO_EMPTY fix
 - Fix typo of SVC_I3C_QUIRK_FALSE_SLVSTART fix.
 - Remove the code changes in svc_i3c_master_do_daa_locked, will add it in
   another patch series for common improvement.
---

Stanley Chu (5):
  dt-bindings: i3c: silvaco: Add npcm845 compatible string
  i3c: master: svc: Add support for Nuvoton npcm845 i3c
  i3c: master: svc: Fix npcm845 FIFO empty issue
  i3c: master: svc: Fix npcm845 invalid slvstart event
  i3c: master: svc: Fix npcm845 DAA process corruption

 .../bindings/i3c/silvaco,i3c-master.yaml      |   4 +-
 drivers/i3c/master/svc-i3c-master.c           | 127 ++++++++++++++++--
 2 files changed, 120 insertions(+), 11 deletions(-)

-- 
2.34.1



From stanley.chuys at gmail.com  Tue Mar  4 19:44:10 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:10 +0800
Subject: [PATCH v6 1/5] dt-bindings: i3c: silvaco: Add npcm845 compatible string
In-Reply-To: <20250305034414.2246870-1-yschu@nuvoton.com>
References: <20250305034414.2246870-1-yschu@nuvoton.com>
Message-ID: <20250305034414.2246870-2-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

Nuvoton npcm845 SoC uses the same Silvico IP but an older version.
Need to add a new compatible string to distinguish between different
hardware versions.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
index c56ff77677f1..4fbdcdac0aee 100644
--- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
+++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
@@ -14,7 +14,9 @@ allOf:
 
 properties:
   compatible:
-    const: silvaco,i3c-master-v1
+    enum:
+      - nuvoton,npcm845-i3c
+      - silvaco,i3c-master-v1
 
   reg:
     maxItems: 1
-- 
2.34.1



From stanley.chuys at gmail.com  Tue Mar  4 19:44:11 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:11 +0800
Subject: [PATCH v6 2/5] i3c: master: svc: Add support for Nuvoton npcm845 i3c
In-Reply-To: <20250305034414.2246870-1-yschu@nuvoton.com>
References: <20250305034414.2246870-1-yschu@nuvoton.com>
Message-ID: <20250305034414.2246870-3-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

Nuvoton npcm845 SoC uses an older IP version, which has specific
hardware issues that need to be addressed with a different compatible
string.

Add driver data for different compatible strings to define platform
specific quirks.
Add compatible string for npcm845 to define its own driver data.

Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..7cafdc8fd1ad 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -158,6 +158,10 @@ struct svc_i3c_regs_save {
 	u32 mdynaddr;
 };
 
+struct svc_i3c_drvdata {
+	u32 quirks;
+};
+
 /**
  * struct svc_i3c_master - Silvaco I3C Master structure
  * @base: I3C master controller
@@ -183,6 +187,7 @@ struct svc_i3c_regs_save {
  * @ibi.tbq_slot: To be queued IBI slot
  * @ibi.lock: IBI lock
  * @lock: Transfer lock, protect between IBI work thread and callbacks from master
+ * @drvdata: Driver data
  * @enabled_events: Bit masks for enable events (IBI, HotJoin).
  * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
  */
@@ -214,6 +219,7 @@ struct svc_i3c_master {
 		spinlock_t lock;
 	} ibi;
 	struct mutex lock;
+	const struct svc_i3c_drvdata *drvdata;
 	u32 enabled_events;
 	u32 mctrl_config;
 };
@@ -1817,6 +1823,10 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
 	if (!master)
 		return -ENOMEM;
 
+	master->drvdata = of_device_get_match_data(dev);
+	if (!master->drvdata)
+		return -EINVAL;
+
 	master->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(master->regs))
 		return PTR_ERR(master->regs);
@@ -1958,8 +1968,13 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 			   svc_i3c_runtime_resume, NULL)
 };
 
+const struct svc_i3c_drvdata npcm845_drvdata = {};
+
+const struct svc_i3c_drvdata svc_default_drvdata = {};
+
 static const struct of_device_id svc_i3c_master_of_match_tbl[] = {
-	{ .compatible = "silvaco,i3c-master-v1"},
+	{ .compatible = "nuvoton,npcm845-i3c", .data = &npcm845_drvdata },
+	{ .compatible = "silvaco,i3c-master-v1", .data = &svc_default_drvdata },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, svc_i3c_master_of_match_tbl);
-- 
2.34.1



From stanley.chuys at gmail.com  Tue Mar  4 19:44:14 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:14 +0800
Subject: [PATCH v6 5/5] i3c: master: svc: Fix npcm845 DAA process corruption
In-Reply-To: <20250305034414.2246870-1-yschu@nuvoton.com>
References: <20250305034414.2246870-1-yschu@nuvoton.com>
Message-ID: <20250305034414.2246870-6-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets
corrupted and results in a no repeated-start condition at the end of
address assignment.

Workaround: Set MCONFIG.SKEW to 1 before initiating the DAA process.
After the DAA process is completed, return MCONFIG.SKEW to its previous
value.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 30 ++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 5c29912e0a69..df7eb038c6c9 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -32,6 +32,7 @@
 #define   SVC_I3C_MCONFIG_ODBAUD(x) FIELD_PREP(GENMASK(23, 16), (x))
 #define   SVC_I3C_MCONFIG_ODHPP(x) FIELD_PREP(BIT(24), (x))
 #define   SVC_I3C_MCONFIG_SKEW(x) FIELD_PREP(GENMASK(27, 25), (x))
+#define   SVC_I3C_MCONFIG_SKEW_MASK GENMASK(27, 25)
 #define   SVC_I3C_MCONFIG_I2CBAUD(x) FIELD_PREP(GENMASK(31, 28), (x))
 
 #define SVC_I3C_MCTRL        0x084
@@ -150,6 +151,16 @@
  * If it is a true SlvStart, the MSTATUS state is SLVREQ.
  */
 #define SVC_I3C_QUIRK_FALSE_SLVSTART	BIT(1)
+/*
+ * SVC_I3C_QUIRK_DAA_CORRUPT:
+ * When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets
+ * corrupted and results in a no repeated-start condition at the end of
+ * address assignment.
+ * Workaround:
+ * Set MCONFIG.SKEW to 1 before initiating the DAA process. After the DAA
+ * process is completed, return MCONFIG.SKEW to its previous value.
+ */
+#define SVC_I3C_QUIRK_DAA_CORRUPT	BIT(2)
 
 struct svc_i3c_cmd {
 	u8 addr;
@@ -259,6 +270,13 @@ static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk)
 	return (master->drvdata->quirks & quirk);
 }
 
+static inline bool svc_has_daa_corrupt(struct svc_i3c_master *master)
+{
+	return ((master->drvdata->quirks & SVC_I3C_QUIRK_DAA_CORRUPT) &&
+		!(master->mctrl_config &
+		(SVC_I3C_MCONFIG_SKEW_MASK | SVC_I3C_MCONFIG_ODHPP(1))));
+}
+
 static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
 {
 	return !!(master->enabled_events & mask);
@@ -1144,7 +1162,16 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
 	}
 
 	spin_lock_irqsave(&master->xferqueue.lock, flags);
+
+	if (svc_has_daa_corrupt(master))
+		writel(master->mctrl_config | SVC_I3C_MCONFIG_SKEW(1),
+		       master->regs + SVC_I3C_MCONFIG);
+
 	ret = svc_i3c_master_do_daa_locked(master, addrs, &dev_nb);
+
+	if (svc_has_daa_corrupt(master))
+		writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
+
 	spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 
 	svc_i3c_master_clear_merrwarn(master);
@@ -2031,7 +2058,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 
 const struct svc_i3c_drvdata npcm845_drvdata = {
 	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY |
-		SVC_I3C_QUIRK_FALSE_SLVSTART,
+		SVC_I3C_QUIRK_FALSE_SLVSTART |
+		SVC_I3C_QUIRK_DAA_CORRUPT,
 };
 
 const struct svc_i3c_drvdata svc_default_drvdata = {};
-- 
2.34.1



From stanley.chuys at gmail.com  Tue Mar  4 19:44:12 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:12 +0800
Subject: [PATCH v6 3/5] i3c: master: svc: Fix npcm845 FIFO empty issue
In-Reply-To: <20250305034414.2246870-1-yschu@nuvoton.com>
References: <20250305034414.2246870-1-yschu@nuvoton.com>
Message-ID: <20250305034414.2246870-4-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

I3C HW stalls the write transfer if the transmit FIFO becomes empty,
when new data is written to FIFO, I3C HW resumes the transfer but the
first transmitted data bit may have the wrong value.
Fill the FIFO in advance to prevent FIFO from becoming empty.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 71 +++++++++++++++++++++++++----
 1 file changed, 61 insertions(+), 10 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 7cafdc8fd1ad..46b032b61f3c 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -113,6 +113,7 @@
 #define SVC_I3C_MWDATAHE     0x0BC
 #define SVC_I3C_MRDATAB      0x0C0
 #define SVC_I3C_MRDATAH      0x0C8
+#define SVC_I3C_MWDATAB1     0x0CC
 #define SVC_I3C_MWMSG_SDR    0x0D0
 #define SVC_I3C_MRMSG_SDR    0x0D4
 #define SVC_I3C_MWMSG_DDR    0x0D8
@@ -133,6 +134,16 @@
 #define SVC_I3C_EVENT_IBI	GENMASK(7, 0)
 #define SVC_I3C_EVENT_HOTJOIN	BIT(31)
 
+/*
+ * SVC_I3C_QUIRK_FIFO_EMPTY:
+ * I3C HW stalls the write transfer if the transmit FIFO becomes empty,
+ * when new data is written to FIFO, I3C HW resumes the transfer but
+ * the first transmitted data bit may have the wrong value.
+ * Workaround:
+ * Fill the FIFO in advance to prevent FIFO from becoming empty.
+ */
+#define SVC_I3C_QUIRK_FIFO_EMPTY	BIT(0)
+
 struct svc_i3c_cmd {
 	u8 addr;
 	bool rnw;
@@ -236,6 +247,11 @@ struct svc_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
+static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk)
+{
+	return (master->drvdata->quirks & quirk);
+}
+
 static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
 {
 	return !!(master->enabled_events & mask);
@@ -894,7 +910,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 					u8 *addrs, unsigned int *count)
 {
 	u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
-	unsigned int dev_nb = 0, last_addr = 0;
+	unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
 	u32 reg;
 	int ret, i;
 
@@ -937,6 +953,25 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 		if (SVC_I3C_MSTATUS_RXPEND(reg)) {
 			u8 data[6];
 
+			/*
+			 * One slave sends its ID to request for address assignment,
+			 * prefilling the dynamic address can reduce SCL clock stalls
+			 * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk.
+			 *
+			 * Ideally, prefilling before the processDAA command is better.
+			 * However, it requires an additional check to write the dyn_addr
+			 * at the right time because the driver needs to write the processDAA
+			 * command twice for one assignment.
+			 * Prefilling here is safe and efficient because the FIFO starts
+			 * filling within a few hundred nanoseconds, which is significantly
+			 * faster compared to the 64 SCL clock cycles.
+			 */
+			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
+			if (dyn_addr < 0)
+				return -ENOSPC;
+
+			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
+
 			/*
 			 * We only care about the 48-bit provisioned ID yet to
 			 * be sure a device does not nack an address twice.
@@ -1015,21 +1050,16 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 		if (ret)
 			break;
 
-		/* Give the slave device a suitable dynamic address */
-		ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
-		if (ret < 0)
-			break;
-
-		addrs[dev_nb] = ret;
+		addrs[dev_nb] = dyn_addr;
 		dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
 			dev_nb, addrs[dev_nb]);
-
-		writel(addrs[dev_nb], master->regs + SVC_I3C_MWDATAB);
 		last_addr = addrs[dev_nb++];
 	}
 
 	/* Need manual issue STOP except for Complete condition */
 	svc_i3c_master_emit_stop(master);
+	svc_i3c_master_flush_fifo(master);
+
 	return ret;
 }
 
@@ -1226,6 +1256,24 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		       SVC_I3C_MCTRL_RDTERM(*actual_len),
 		       master->regs + SVC_I3C_MCTRL);
 
+		/*
+		 * The entire transaction can consist of multiple write transfers.
+		 * Prefilling before EmitStartAddr causes the data to be emitted
+		 * immediately, becoming part of the previous transfer.
+		 * The only way to work around this hardware issue is to let the
+		 * FIFO start filling as soon as possible after EmitStartAddr.
+		 */
+		if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) {
+			u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END;
+			u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE);
+
+			writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1);
+			/* Mark END bit if this is the last byte */
+			writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB);
+			xfer_len -= len;
+			out += len;
+		}
+
 		ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
 				 SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000);
 		if (ret)
@@ -1314,6 +1362,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 emit_stop:
 	svc_i3c_master_emit_stop(master);
 	svc_i3c_master_clear_merrwarn(master);
+	svc_i3c_master_flush_fifo(master);
 
 	return ret;
 }
@@ -1968,7 +2017,9 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 			   svc_i3c_runtime_resume, NULL)
 };
 
-const struct svc_i3c_drvdata npcm845_drvdata = {};
+const struct svc_i3c_drvdata npcm845_drvdata = {
+	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY,
+};
 
 const struct svc_i3c_drvdata svc_default_drvdata = {};
 
-- 
2.34.1



From stanley.chuys at gmail.com  Tue Mar  4 19:44:13 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Wed,  5 Mar 2025 11:44:13 +0800
Subject: [PATCH v6 4/5] i3c: master: svc: Fix npcm845 invalid slvstart event
In-Reply-To: <20250305034414.2246870-1-yschu@nuvoton.com>
References: <20250305034414.2246870-1-yschu@nuvoton.com>
Message-ID: <20250305034414.2246870-5-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

I3C HW may generate an invalid SlvStart event when emitting a STOP.
If it is a true SlvStart, the MSTATUS state is SLVREQ. Check the
MSTATUS state to ignore the false event.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 46b032b61f3c..5c29912e0a69 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -58,6 +58,7 @@
 #define SVC_I3C_MSTATUS      0x088
 #define   SVC_I3C_MSTATUS_STATE(x) FIELD_GET(GENMASK(2, 0), (x))
 #define   SVC_I3C_MSTATUS_STATE_DAA(x) (SVC_I3C_MSTATUS_STATE(x) == 5)
+#define   SVC_I3C_MSTATUS_STATE_SLVREQ(x) (SVC_I3C_MSTATUS_STATE(x) == 1)
 #define   SVC_I3C_MSTATUS_STATE_IDLE(x) (SVC_I3C_MSTATUS_STATE(x) == 0)
 #define   SVC_I3C_MSTATUS_BETWEEN(x) FIELD_GET(BIT(4), (x))
 #define   SVC_I3C_MSTATUS_NACKED(x) FIELD_GET(BIT(5), (x))
@@ -143,6 +144,12 @@
  * Fill the FIFO in advance to prevent FIFO from becoming empty.
  */
 #define SVC_I3C_QUIRK_FIFO_EMPTY	BIT(0)
+/*
+ * SVC_I3C_QUIRK_FLASE_SLVSTART:
+ * I3C HW may generate an invalid SlvStart event when emitting a STOP.
+ * If it is a true SlvStart, the MSTATUS state is SLVREQ.
+ */
+#define SVC_I3C_QUIRK_FALSE_SLVSTART	BIT(1)
 
 struct svc_i3c_cmd {
 	u8 addr;
@@ -586,6 +593,11 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
 	/* Clear the interrupt status */
 	writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS);
 
+	/* Ignore the false event */
+	if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) &&
+	    !SVC_I3C_MSTATUS_STATE_SLVREQ(active))
+		return IRQ_HANDLED;
+
 	svc_i3c_master_disable_interrupts(master);
 
 	/* Handle the interrupt in a non atomic context */
@@ -2018,7 +2030,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 };
 
 const struct svc_i3c_drvdata npcm845_drvdata = {
-	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY,
+	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY |
+		SVC_I3C_QUIRK_FALSE_SLVSTART,
 };
 
 const struct svc_i3c_drvdata svc_default_drvdata = {};
-- 
2.34.1



From lkp at intel.com  Wed Mar  5 22:56:57 2025
From: lkp at intel.com (kernel test robot)
Date: Thu, 6 Mar 2025 14:56:57 +0800
Subject: [PATCH v6 2/5] i3c: master: svc: Add support for Nuvoton npcm845
 i3c
In-Reply-To: <20250305034414.2246870-3-yschu@nuvoton.com>
References: <20250305034414.2246870-3-yschu@nuvoton.com>
Message-ID: <202503061400.GGr64rkR-lkp@intel.com>

Hi Stanley,

kernel test robot noticed the following build warnings:

[auto build test WARNING on robh/for-next]
[also build test WARNING on linus/master v6.14-rc5 next-20250305]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Stanley-Chu/dt-bindings-i3c-silvaco-Add-npcm845-compatible-string/20250305-114705
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link:    https://lore.kernel.org/r/20250305034414.2246870-3-yschu%40nuvoton.com
patch subject: [PATCH v6 2/5] i3c: master: svc: Add support for Nuvoton npcm845 i3c
config: sparc-randconfig-r121-20250306 (https://download.01.org/0day-ci/archive/20250306/202503061400.GGr64rkR-lkp at intel.com/config)
compiler: sparc-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250306/202503061400.GGr64rkR-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503061400.GGr64rkR-lkp at intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/i3c/master/svc-i3c-master.c:1971:30: sparse: sparse: symbol 'npcm845_drvdata' was not declared. Should it be static?
>> drivers/i3c/master/svc-i3c-master.c:1973:30: sparse: sparse: symbol 'svc_default_drvdata' was not declared. Should it be static?
   drivers/i3c/master/svc-i3c-master.c:559:9: sparse: sparse: context imbalance in 'svc_i3c_master_ibi_work' - wrong count at exit
   drivers/i3c/master/svc-i3c-master.c: note: in included file (through include/linux/mutex.h, include/linux/notifier.h, include/linux/clk.h):
   include/linux/list.h:83:21: sparse: sparse: self-comparison always evaluates to true

vim +/svc_default_drvdata +1973 drivers/i3c/master/svc-i3c-master.c

  1972	
> 1973	const struct svc_i3c_drvdata svc_default_drvdata = {};
  1974	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From stanley.chuys at gmail.com  Wed Mar  5 23:54:24 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:24 +0800
Subject: [PATCH v7 0/5] Add support for Nuvoton npcm845 i3c controller
Message-ID: <20250306075429.2265183-1-yschu@nuvoton.com>

This patchset adds support for the Nuvoton npcm845
Board Management controller (BMC) SoC family.

The Nuvoton npcm845 uses the same Silvico IP but an older version.
This patchset adds fixes for the npcm845 specific hardware issues.

--
v7:
 - Fix kernel test robot build warning.

v6:
 - Define QUIRK when it is really used in the separate patches.

v5:
 - Add default driver data
 - Add helper function svc_has_daa_corrupt()
 - Revise SVC_I3C_QUIRK_FIFO_EMPTY fix and add comments

v4:
 - Fix kernel test robot build warning.
 - Add SVC_I3C_QUIRK_DAA_CORRUPT fix

v3:
 - Add more description in dt-binging commit message
 - Add the svc_i3c_drvdata structure in struct svc_i3c_master
 - Improve the do_daa

v2:
 - Add a new compatible string in dt-binding doc.
 - Add driver data for npcm845 to address the quirks.
 - Modify svc_i3c_master_write to be reused by SVC_I3C_QUIRK_FIFO_EMPTY fix
 - Fix typo of SVC_I3C_QUIRK_FALSE_SLVSTART fix.
 - Remove the code changes in svc_i3c_master_do_daa_locked, will add it in
   another patch series for common improvement.
---

Stanley Chu (5):
  dt-bindings: i3c: silvaco: Add npcm845 compatible string
  i3c: master: svc: Add support for Nuvoton npcm845 i3c
  i3c: master: svc: Fix npcm845 FIFO empty issue
  i3c: master: svc: Fix npcm845 invalid slvstart event
  i3c: master: svc: Fix npcm845 DAA process corruption

 .../bindings/i3c/silvaco,i3c-master.yaml      |   4 +-
 drivers/i3c/master/svc-i3c-master.c           | 127 ++++++++++++++++--
 2 files changed, 120 insertions(+), 11 deletions(-)

-- 
2.34.1



From stanley.chuys at gmail.com  Wed Mar  5 23:54:25 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:25 +0800
Subject: [PATCH v7 1/5] dt-bindings: i3c: silvaco: Add npcm845 compatible string
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <20250306075429.2265183-2-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

Nuvoton npcm845 SoC uses the same Silvico IP but an older version.
Need to add a new compatible string to distinguish between different
hardware versions.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski at linaro.org>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
index c56ff77677f1..4fbdcdac0aee 100644
--- a/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
+++ b/Documentation/devicetree/bindings/i3c/silvaco,i3c-master.yaml
@@ -14,7 +14,9 @@ allOf:
 
 properties:
   compatible:
-    const: silvaco,i3c-master-v1
+    enum:
+      - nuvoton,npcm845-i3c
+      - silvaco,i3c-master-v1
 
   reg:
     maxItems: 1
-- 
2.34.1



From stanley.chuys at gmail.com  Wed Mar  5 23:54:26 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:26 +0800
Subject: [PATCH v7 2/5] i3c: master: svc: Add support for Nuvoton npcm845 i3c
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <20250306075429.2265183-3-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

Nuvoton npcm845 SoC uses an older IP version, which has specific
hardware issues that need to be addressed with a different compatible
string.

Add driver data for different compatible strings to define platform
specific quirks.
Add compatible string for npcm845 to define its own driver data.

Reported-by: kernel test robot <lkp at intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202503061400.GGr64rkR-lkp at intel.com/
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..40269b692aa8 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -158,6 +158,10 @@ struct svc_i3c_regs_save {
 	u32 mdynaddr;
 };
 
+struct svc_i3c_drvdata {
+	u32 quirks;
+};
+
 /**
  * struct svc_i3c_master - Silvaco I3C Master structure
  * @base: I3C master controller
@@ -183,6 +187,7 @@ struct svc_i3c_regs_save {
  * @ibi.tbq_slot: To be queued IBI slot
  * @ibi.lock: IBI lock
  * @lock: Transfer lock, protect between IBI work thread and callbacks from master
+ * @drvdata: Driver data
  * @enabled_events: Bit masks for enable events (IBI, HotJoin).
  * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
  */
@@ -214,6 +219,7 @@ struct svc_i3c_master {
 		spinlock_t lock;
 	} ibi;
 	struct mutex lock;
+	const struct svc_i3c_drvdata *drvdata;
 	u32 enabled_events;
 	u32 mctrl_config;
 };
@@ -1817,6 +1823,10 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
 	if (!master)
 		return -ENOMEM;
 
+	master->drvdata = of_device_get_match_data(dev);
+	if (!master->drvdata)
+		return -EINVAL;
+
 	master->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(master->regs))
 		return PTR_ERR(master->regs);
@@ -1958,8 +1968,13 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 			   svc_i3c_runtime_resume, NULL)
 };
 
+static const struct svc_i3c_drvdata npcm845_drvdata = {};
+
+static const struct svc_i3c_drvdata svc_default_drvdata = {};
+
 static const struct of_device_id svc_i3c_master_of_match_tbl[] = {
-	{ .compatible = "silvaco,i3c-master-v1"},
+	{ .compatible = "nuvoton,npcm845-i3c", .data = &npcm845_drvdata },
+	{ .compatible = "silvaco,i3c-master-v1", .data = &svc_default_drvdata },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, svc_i3c_master_of_match_tbl);
-- 
2.34.1



From stanley.chuys at gmail.com  Wed Mar  5 23:54:27 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:27 +0800
Subject: [PATCH v7 3/5] i3c: master: svc: Fix npcm845 FIFO empty issue
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <20250306075429.2265183-4-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

I3C HW stalls the write transfer if the transmit FIFO becomes empty,
when new data is written to FIFO, I3C HW resumes the transfer but the
first transmitted data bit may have the wrong value.
Fill the FIFO in advance to prevent FIFO from becoming empty.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 71 +++++++++++++++++++++++++----
 1 file changed, 61 insertions(+), 10 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 40269b692aa8..cba89a685e13 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -113,6 +113,7 @@
 #define SVC_I3C_MWDATAHE     0x0BC
 #define SVC_I3C_MRDATAB      0x0C0
 #define SVC_I3C_MRDATAH      0x0C8
+#define SVC_I3C_MWDATAB1     0x0CC
 #define SVC_I3C_MWMSG_SDR    0x0D0
 #define SVC_I3C_MRMSG_SDR    0x0D4
 #define SVC_I3C_MWMSG_DDR    0x0D8
@@ -133,6 +134,16 @@
 #define SVC_I3C_EVENT_IBI	GENMASK(7, 0)
 #define SVC_I3C_EVENT_HOTJOIN	BIT(31)
 
+/*
+ * SVC_I3C_QUIRK_FIFO_EMPTY:
+ * I3C HW stalls the write transfer if the transmit FIFO becomes empty,
+ * when new data is written to FIFO, I3C HW resumes the transfer but
+ * the first transmitted data bit may have the wrong value.
+ * Workaround:
+ * Fill the FIFO in advance to prevent FIFO from becoming empty.
+ */
+#define SVC_I3C_QUIRK_FIFO_EMPTY	BIT(0)
+
 struct svc_i3c_cmd {
 	u8 addr;
 	bool rnw;
@@ -236,6 +247,11 @@ struct svc_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
+static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk)
+{
+	return (master->drvdata->quirks & quirk);
+}
+
 static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
 {
 	return !!(master->enabled_events & mask);
@@ -894,7 +910,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 					u8 *addrs, unsigned int *count)
 {
 	u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
-	unsigned int dev_nb = 0, last_addr = 0;
+	unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
 	u32 reg;
 	int ret, i;
 
@@ -937,6 +953,25 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 		if (SVC_I3C_MSTATUS_RXPEND(reg)) {
 			u8 data[6];
 
+			/*
+			 * One slave sends its ID to request for address assignment,
+			 * prefilling the dynamic address can reduce SCL clock stalls
+			 * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk.
+			 *
+			 * Ideally, prefilling before the processDAA command is better.
+			 * However, it requires an additional check to write the dyn_addr
+			 * at the right time because the driver needs to write the processDAA
+			 * command twice for one assignment.
+			 * Prefilling here is safe and efficient because the FIFO starts
+			 * filling within a few hundred nanoseconds, which is significantly
+			 * faster compared to the 64 SCL clock cycles.
+			 */
+			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
+			if (dyn_addr < 0)
+				return -ENOSPC;
+
+			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
+
 			/*
 			 * We only care about the 48-bit provisioned ID yet to
 			 * be sure a device does not nack an address twice.
@@ -1015,21 +1050,16 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 		if (ret)
 			break;
 
-		/* Give the slave device a suitable dynamic address */
-		ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
-		if (ret < 0)
-			break;
-
-		addrs[dev_nb] = ret;
+		addrs[dev_nb] = dyn_addr;
 		dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
 			dev_nb, addrs[dev_nb]);
-
-		writel(addrs[dev_nb], master->regs + SVC_I3C_MWDATAB);
 		last_addr = addrs[dev_nb++];
 	}
 
 	/* Need manual issue STOP except for Complete condition */
 	svc_i3c_master_emit_stop(master);
+	svc_i3c_master_flush_fifo(master);
+
 	return ret;
 }
 
@@ -1226,6 +1256,24 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		       SVC_I3C_MCTRL_RDTERM(*actual_len),
 		       master->regs + SVC_I3C_MCTRL);
 
+		/*
+		 * The entire transaction can consist of multiple write transfers.
+		 * Prefilling before EmitStartAddr causes the data to be emitted
+		 * immediately, becoming part of the previous transfer.
+		 * The only way to work around this hardware issue is to let the
+		 * FIFO start filling as soon as possible after EmitStartAddr.
+		 */
+		if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) {
+			u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END;
+			u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE);
+
+			writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1);
+			/* Mark END bit if this is the last byte */
+			writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB);
+			xfer_len -= len;
+			out += len;
+		}
+
 		ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
 				 SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000);
 		if (ret)
@@ -1314,6 +1362,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 emit_stop:
 	svc_i3c_master_emit_stop(master);
 	svc_i3c_master_clear_merrwarn(master);
+	svc_i3c_master_flush_fifo(master);
 
 	return ret;
 }
@@ -1968,7 +2017,9 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 			   svc_i3c_runtime_resume, NULL)
 };
 
-static const struct svc_i3c_drvdata npcm845_drvdata = {};
+static const struct svc_i3c_drvdata npcm845_drvdata = {
+	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY,
+};
 
 static const struct svc_i3c_drvdata svc_default_drvdata = {};
 
-- 
2.34.1



From stanley.chuys at gmail.com  Wed Mar  5 23:54:28 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:28 +0800
Subject: [PATCH v7 4/5] i3c: master: svc: Fix npcm845 invalid slvstart event
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <20250306075429.2265183-5-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

I3C HW may generate an invalid SlvStart event when emitting a STOP.
If it is a true SlvStart, the MSTATUS state is SLVREQ. Check the
MSTATUS state to ignore the false event.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index cba89a685e13..1cab5b8594de 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -58,6 +58,7 @@
 #define SVC_I3C_MSTATUS      0x088
 #define   SVC_I3C_MSTATUS_STATE(x) FIELD_GET(GENMASK(2, 0), (x))
 #define   SVC_I3C_MSTATUS_STATE_DAA(x) (SVC_I3C_MSTATUS_STATE(x) == 5)
+#define   SVC_I3C_MSTATUS_STATE_SLVREQ(x) (SVC_I3C_MSTATUS_STATE(x) == 1)
 #define   SVC_I3C_MSTATUS_STATE_IDLE(x) (SVC_I3C_MSTATUS_STATE(x) == 0)
 #define   SVC_I3C_MSTATUS_BETWEEN(x) FIELD_GET(BIT(4), (x))
 #define   SVC_I3C_MSTATUS_NACKED(x) FIELD_GET(BIT(5), (x))
@@ -143,6 +144,12 @@
  * Fill the FIFO in advance to prevent FIFO from becoming empty.
  */
 #define SVC_I3C_QUIRK_FIFO_EMPTY	BIT(0)
+/*
+ * SVC_I3C_QUIRK_FLASE_SLVSTART:
+ * I3C HW may generate an invalid SlvStart event when emitting a STOP.
+ * If it is a true SlvStart, the MSTATUS state is SLVREQ.
+ */
+#define SVC_I3C_QUIRK_FALSE_SLVSTART	BIT(1)
 
 struct svc_i3c_cmd {
 	u8 addr;
@@ -586,6 +593,11 @@ static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)
 	/* Clear the interrupt status */
 	writel(SVC_I3C_MINT_SLVSTART, master->regs + SVC_I3C_MSTATUS);
 
+	/* Ignore the false event */
+	if (svc_has_quirk(master, SVC_I3C_QUIRK_FALSE_SLVSTART) &&
+	    !SVC_I3C_MSTATUS_STATE_SLVREQ(active))
+		return IRQ_HANDLED;
+
 	svc_i3c_master_disable_interrupts(master);
 
 	/* Handle the interrupt in a non atomic context */
@@ -2018,7 +2030,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 };
 
 static const struct svc_i3c_drvdata npcm845_drvdata = {
-	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY,
+	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY |
+		SVC_I3C_QUIRK_FALSE_SLVSTART,
 };
 
 static const struct svc_i3c_drvdata svc_default_drvdata = {};
-- 
2.34.1



From stanley.chuys at gmail.com  Wed Mar  5 23:54:29 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Thu,  6 Mar 2025 15:54:29 +0800
Subject: [PATCH v7 5/5] i3c: master: svc: Fix npcm845 DAA process corruption
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <20250306075429.2265183-6-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets
corrupted and results in a no repeated-start condition at the end of
address assignment.

Workaround: Set MCONFIG.SKEW to 1 before initiating the DAA process.
After the DAA process is completed, return MCONFIG.SKEW to its previous
value.

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 30 ++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 1cab5b8594de..c086e0e38279 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -32,6 +32,7 @@
 #define   SVC_I3C_MCONFIG_ODBAUD(x) FIELD_PREP(GENMASK(23, 16), (x))
 #define   SVC_I3C_MCONFIG_ODHPP(x) FIELD_PREP(BIT(24), (x))
 #define   SVC_I3C_MCONFIG_SKEW(x) FIELD_PREP(GENMASK(27, 25), (x))
+#define   SVC_I3C_MCONFIG_SKEW_MASK GENMASK(27, 25)
 #define   SVC_I3C_MCONFIG_I2CBAUD(x) FIELD_PREP(GENMASK(31, 28), (x))
 
 #define SVC_I3C_MCTRL        0x084
@@ -150,6 +151,16 @@
  * If it is a true SlvStart, the MSTATUS state is SLVREQ.
  */
 #define SVC_I3C_QUIRK_FALSE_SLVSTART	BIT(1)
+/*
+ * SVC_I3C_QUIRK_DAA_CORRUPT:
+ * When MCONFIG.SKEW=0 and MCONFIG.ODHPP=0, the ENTDAA transaction gets
+ * corrupted and results in a no repeated-start condition at the end of
+ * address assignment.
+ * Workaround:
+ * Set MCONFIG.SKEW to 1 before initiating the DAA process. After the DAA
+ * process is completed, return MCONFIG.SKEW to its previous value.
+ */
+#define SVC_I3C_QUIRK_DAA_CORRUPT	BIT(2)
 
 struct svc_i3c_cmd {
 	u8 addr;
@@ -259,6 +270,13 @@ static inline bool svc_has_quirk(struct svc_i3c_master *master, u32 quirk)
 	return (master->drvdata->quirks & quirk);
 }
 
+static inline bool svc_has_daa_corrupt(struct svc_i3c_master *master)
+{
+	return ((master->drvdata->quirks & SVC_I3C_QUIRK_DAA_CORRUPT) &&
+		!(master->mctrl_config &
+		(SVC_I3C_MCONFIG_SKEW_MASK | SVC_I3C_MCONFIG_ODHPP(1))));
+}
+
 static inline bool is_events_enabled(struct svc_i3c_master *master, u32 mask)
 {
 	return !!(master->enabled_events & mask);
@@ -1144,7 +1162,16 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
 	}
 
 	spin_lock_irqsave(&master->xferqueue.lock, flags);
+
+	if (svc_has_daa_corrupt(master))
+		writel(master->mctrl_config | SVC_I3C_MCONFIG_SKEW(1),
+		       master->regs + SVC_I3C_MCONFIG);
+
 	ret = svc_i3c_master_do_daa_locked(master, addrs, &dev_nb);
+
+	if (svc_has_daa_corrupt(master))
+		writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG);
+
 	spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 
 	svc_i3c_master_clear_merrwarn(master);
@@ -2031,7 +2058,8 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
 
 static const struct svc_i3c_drvdata npcm845_drvdata = {
 	.quirks = SVC_I3C_QUIRK_FIFO_EMPTY |
-		SVC_I3C_QUIRK_FALSE_SLVSTART,
+		SVC_I3C_QUIRK_FALSE_SLVSTART |
+		SVC_I3C_QUIRK_DAA_CORRUPT,
 };
 
 static const struct svc_i3c_drvdata svc_default_drvdata = {};
-- 
2.34.1



From Frank.li at nxp.com  Thu Mar  6 07:08:19 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 10:08:19 -0500
Subject: [PATCH v7 2/5] i3c: master: svc: Add support for Nuvoton npcm845
 i3c
In-Reply-To: <20250306075429.2265183-3-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
 <20250306075429.2265183-3-yschu@nuvoton.com>
Message-ID: <Z8m6Y8WTevsCUMZX@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 03:54:26PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> Nuvoton npcm845 SoC uses an older IP version, which has specific
> hardware issues that need to be addressed with a different compatible
> string.
>
> Add driver data for different compatible strings to define platform
> specific quirks.
> Add compatible string for npcm845 to define its own driver data.
>
> Reported-by: kernel test robot <lkp at intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202503061400.GGr64rkR-lkp at intel.com/

Needn't these for new version. Need such tags only when seperated patch
that fix this issue.

I think alex can drop these when apply. If need respin patches, remove it.

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> ---
>  drivers/i3c/master/svc-i3c-master.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index d6057d8c7dec..40269b692aa8 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -158,6 +158,10 @@ struct svc_i3c_regs_save {
>  	u32 mdynaddr;
>  };
>
> +struct svc_i3c_drvdata {
> +	u32 quirks;
> +};
> +
>  /**
>   * struct svc_i3c_master - Silvaco I3C Master structure
>   * @base: I3C master controller
> @@ -183,6 +187,7 @@ struct svc_i3c_regs_save {
>   * @ibi.tbq_slot: To be queued IBI slot
>   * @ibi.lock: IBI lock
>   * @lock: Transfer lock, protect between IBI work thread and callbacks from master
> + * @drvdata: Driver data
>   * @enabled_events: Bit masks for enable events (IBI, HotJoin).
>   * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back.
>   */
> @@ -214,6 +219,7 @@ struct svc_i3c_master {
>  		spinlock_t lock;
>  	} ibi;
>  	struct mutex lock;
> +	const struct svc_i3c_drvdata *drvdata;
>  	u32 enabled_events;
>  	u32 mctrl_config;
>  };
> @@ -1817,6 +1823,10 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
>  	if (!master)
>  		return -ENOMEM;
>
> +	master->drvdata = of_device_get_match_data(dev);
> +	if (!master->drvdata)
> +		return -EINVAL;
> +
>  	master->regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(master->regs))
>  		return PTR_ERR(master->regs);
> @@ -1958,8 +1968,13 @@ static const struct dev_pm_ops svc_i3c_pm_ops = {
>  			   svc_i3c_runtime_resume, NULL)
>  };
>
> +static const struct svc_i3c_drvdata npcm845_drvdata = {};
> +
> +static const struct svc_i3c_drvdata svc_default_drvdata = {};
> +
>  static const struct of_device_id svc_i3c_master_of_match_tbl[] = {
> -	{ .compatible = "silvaco,i3c-master-v1"},
> +	{ .compatible = "nuvoton,npcm845-i3c", .data = &npcm845_drvdata },
> +	{ .compatible = "silvaco,i3c-master-v1", .data = &svc_default_drvdata },
>  	{ /* sentinel */ },
>  };
>  MODULE_DEVICE_TABLE(of, svc_i3c_master_of_match_tbl);
> --
> 2.34.1
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Thu Mar  6 07:31:24 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 10:31:24 -0500
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh wrote:
> Hi Frank,
>
> Please find my inline comments.
>
> Regards,
> Manju

Avoid top post for linux kernel mail list.

>
> > -----Original Message-----
> > From: Frank Li <frank.li at nxp.com>
> > Sent: Friday, February 28, 2025 9:19 PM
> > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> >
> > Subject should be "Fix read from unreadable memory at
> > svc_i3c_master_ibi_work()"
> > Or like below pattern:
> > 	Do ... to fix ...
> >
> [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh wrote:
> > > I3C Master driver svc-i3c-master
> >
> > Needn't this line.
> >
> [Manjunatha Venkatesh] Removed this line and submitted the new patch
> > >
> > > As part of I3C driver probing sequence for particular device instance,
> > > While adding to queue it is trying to access ibi variable of dev which
> > > is not yet initialized causing "Unable to handle kernel read from
> > > unreadable memory" resulting in kernel panic.
> >
> > Can you provide more detail information why/how this happen? which
> > varible read cause this problem?
> >
> [Manjunatha Venkatesh] : Below is the sequence where this issue happened.
> 1. During boot up sequence IBI is received at host  from the slave device before requesting for IBI, Usually will request IBI by calling i3c_device_request_ibi() during probe of slave driver.
> 2. Since master code trying to access IBI Variable for the particular device instance before actually it initialized by slave driver, due to this randomly accessing the address and causing kernel panic.
> 3. i3c_device_request_ibi() function invoked by the slave driver where dev->ibi = ibi; assigned as part of function call i3c_dev_request_ibi_locked().
> 4. But when IBI request sent by slave device, master code  trying to access this variable before its initialized due to this race condition situation kernel panic happened.

Write above reproduce steps to commit message.

I think it is common problem for i3c framework.

You'd better change i3c_master_queue_ibi()

void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
{
	if (!slot)
		return;

        atomic_inc(&dev->ibi->pending_ibis);
        queue_work(dev->ibi->wq, &slot->work);
}

Frank
>
>
> > Need fix tags and cc stable.
> >
> [Manjunatha Venkatesh] : fix tags and cc stable updated in the commit message.
>
> > Frank
> > >
> > > Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > ---
> > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > b/drivers/i3c/master/svc-i3c-master.c
> > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > work_struct *work)
> > >  	switch (ibitype) {
> > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > >  		if (dev) {
> > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > -			master->ibi.tbq_slot = NULL;
> > > +			data = i3c_dev_get_master_data(dev);
> > > +			if (master->ibi.slots[data->ibi]) {
> > > +				i3c_master_queue_ibi(dev, master-
> > >ibi.tbq_slot);
> > > +				master->ibi.tbq_slot = NULL;
> > > +			}
> > >  		}
> > >  		svc_i3c_master_emit_stop(master);
> > >  		break;
> > > --
> > > 2.46.1
> > >
> > >
> > > --
> > > linux-i3c mailing list
> > > linux-i3c at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From manjunatha.venkatesh at nxp.com  Wed Mar  5 23:43:03 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu,  6 Mar 2025 13:13:03 +0530
Subject: [PATCH v2] svc-i3c-master: Fix read from unreadable memory at svc_i3c_master_ibi_work()
Message-ID: <20250306074303.239081-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v1:
  - Patch tittle updated as per the review feedback

 drivers/i3c/master/svc-i3c-master.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..98c4d2e5cd8d 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
 		if (dev) {
-			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
-			master->ibi.tbq_slot = NULL;
+			data = i3c_dev_get_master_data(dev);
+			if (master->ibi.slots[data->ibi]) {
+				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
+				master->ibi.tbq_slot = NULL;
+			}
 		}
 		svc_i3c_master_emit_stop(master);
 		break;
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Thu Mar  6 00:03:45 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu,  6 Mar 2025 13:33:45 +0530
Subject: [PATCH v2] svc-i3c-master: Fix read from unreadable memory at svc_i3c_master_ibi_work()
Message-ID: <20250306080345.243957-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v1:
  - Patch tittle updated as per the review feedback

 drivers/i3c/master/svc-i3c-master.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..98c4d2e5cd8d 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
 		if (dev) {
-			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
-			master->ibi.tbq_slot = NULL;
+			data = i3c_dev_get_master_data(dev);
+			if (master->ibi.slots[data->ibi]) {
+				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
+				master->ibi.tbq_slot = NULL;
+			}
 		}
 		svc_i3c_master_emit_stop(master);
 		break;
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Thu Mar  6 00:17:10 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu,  6 Mar 2025 13:47:10 +0530
Subject: [PATCH v2] svc-i3c-master: Fix read from unreadable memory at svc_i3c_master_ibi_work()
Message-ID: <20250306081710.247247-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v1:
  - Patch tittle updated as per the review feedback

 drivers/i3c/master/svc-i3c-master.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..98c4d2e5cd8d 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
 		if (dev) {
-			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
-			master->ibi.tbq_slot = NULL;
+			data = i3c_dev_get_master_data(dev);
+			if (master->ibi.slots[data->ibi]) {
+				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
+				master->ibi.tbq_slot = NULL;
+			}
 		}
 		svc_i3c_master_emit_stop(master);
 		break;
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Thu Mar  6 00:31:29 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu, 6 Mar 2025 08:31:29 +0000
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>

Hi Frank,

Please find my inline comments.

Regards,
Manju

> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Friday, February 28, 2025 9:19 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> 
> Subject should be "Fix read from unreadable memory at
> svc_i3c_master_ibi_work()"
> Or like below pattern:
> 	Do ... to fix ...
> 
[Manjunatha Venkatesh] Tittle updated as per the review comment.
> On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh wrote:
> > I3C Master driver svc-i3c-master
> 
> Needn't this line.
> 
[Manjunatha Venkatesh] Removed this line and submitted the new patch
> >
> > As part of I3C driver probing sequence for particular device instance,
> > While adding to queue it is trying to access ibi variable of dev which
> > is not yet initialized causing "Unable to handle kernel read from
> > unreadable memory" resulting in kernel panic.
> 
> Can you provide more detail information why/how this happen? which
> varible read cause this problem?
> 
[Manjunatha Venkatesh] : Below is the sequence where this issue happened.
1. During boot up sequence IBI is received at host  from the slave device before requesting for IBI, Usually will request IBI by calling i3c_device_request_ibi() during probe of slave driver.
2. Since master code trying to access IBI Variable for the particular device instance before actually it initialized by slave driver, due to this randomly accessing the address and causing kernel panic.
3. i3c_device_request_ibi() function invoked by the slave driver where dev->ibi = ibi; assigned as part of function call i3c_dev_request_ibi_locked().
4. But when IBI request sent by slave device, master code  trying to access this variable before its initialized due to this race condition situation kernel panic happened.


> Need fix tags and cc stable.
> 
[Manjunatha Venkatesh] : fix tags and cc stable updated in the commit message.
                                               
> Frank
> >
> > Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > ---
> >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > b/drivers/i3c/master/svc-i3c-master.c
> > index d6057d8c7dec..98c4d2e5cd8d 100644
> > --- a/drivers/i3c/master/svc-i3c-master.c
> > +++ b/drivers/i3c/master/svc-i3c-master.c
> > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> work_struct *work)
> >  	switch (ibitype) {
> >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> >  		if (dev) {
> > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > -			master->ibi.tbq_slot = NULL;
> > +			data = i3c_dev_get_master_data(dev);
> > +			if (master->ibi.slots[data->ibi]) {
> > +				i3c_master_queue_ibi(dev, master-
> >ibi.tbq_slot);
> > +				master->ibi.tbq_slot = NULL;
> > +			}
> >  		}
> >  		svc_i3c_master_emit_stop(master);
> >  		break;
> > --
> > 2.46.1
> >
> >
> > --
> > linux-i3c mailing list
> > linux-i3c at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-i3c


From alexandre.belloni at bootlin.com  Thu Mar  6 12:55:02 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Thu, 6 Mar 2025 21:55:02 +0100
Subject: [PATCH] dt-bindings: i3c: dw: Add power-domains
In-Reply-To: <fb8adcd318b1023ca6b90d294e46ae3b59dc1280.1740490666.git.michal.simek@amd.com>
References: <fb8adcd318b1023ca6b90d294e46ae3b59dc1280.1740490666.git.michal.simek@amd.com>
Message-ID: <174129444615.1163689.13836504837262083923.b4-ty@bootlin.com>

On Tue, 25 Feb 2025 14:37:48 +0100, Michal Simek wrote:
> Describe optional power-domains property.
> 
> 

Applied, thanks!

[1/1] dt-bindings: i3c: dw: Add power-domains
      https://git.kernel.org/abelloni/c/59f994e6e332

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Thu Mar  6 12:55:16 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Thu, 6 Mar 2025 21:55:16 +0100
Subject: [PATCH v7 0/5] Add support for Nuvoton npcm845 i3c controller
In-Reply-To: <20250306075429.2265183-1-yschu@nuvoton.com>
References: <20250306075429.2265183-1-yschu@nuvoton.com>
Message-ID: <174129444617.1163689.11942276093411687387.b4-ty@bootlin.com>

On Thu, 06 Mar 2025 15:54:24 +0800, Stanley Chu wrote:
> This patchset adds support for the Nuvoton npcm845
> Board Management controller (BMC) SoC family.
> 
> The Nuvoton npcm845 uses the same Silvico IP but an older version.
> This patchset adds fixes for the npcm845 specific hardware issues.
> 
> --
> v7:
>  - Fix kernel test robot build warning.
> 
> [...]

Applied, thanks!

[1/5] dt-bindings: i3c: silvaco: Add npcm845 compatible string
      https://git.kernel.org/abelloni/c/c24a084ab6a2
[2/5] i3c: master: svc: Add support for Nuvoton npcm845 i3c
      https://git.kernel.org/abelloni/c/98d87600a04e
[3/5] i3c: master: svc: Fix npcm845 FIFO empty issue
      https://git.kernel.org/abelloni/c/4008a74e0f9b
[4/5] i3c: master: svc: Fix npcm845 invalid slvstart event
      https://git.kernel.org/abelloni/c/4dd12e944f07
[5/5] i3c: master: svc: Fix npcm845 DAA process corruption
      https://git.kernel.org/abelloni/c/2a785307e41b

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From Frank.li at nxp.com  Thu Mar  6 13:08:54 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 6 Mar 2025 16:08:54 -0500
Subject: [PATCH v2] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <20250306074303.239081-1-manjunatha.venkatesh@nxp.com>
References: <20250306074303.239081-1-manjunatha.venkatesh@nxp.com>
Message-ID: <Z8oO5hTx59niiY1U@lizhi-Precision-Tower-5810>

On Thu, Mar 06, 2025 at 01:13:03PM +0530, Manjunatha Venkatesh wrote:
> As part of I3C driver probing sequence for particular device instance,
> While adding to queue it is trying to access ibi variable of dev which is
> not yet initialized causing "Unable to handle kernel read from unreadable
> memory" resulting in kernel panic.
>
> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> ---

You sent it 3 times.

Do you try my suggestion at v1?
https://lore.kernel.org/linux-i3c/Z8m%2FzE9JvyiNq1HG at lizhi-Precision-Tower-5810/T/#t

Before close above discussion, please not sent new version.

Still missied fix tag and cc stable.

Frank

> Changes since v1:
>   - Patch tittle updated as per the review feedback
>
>  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index d6057d8c7dec..98c4d2e5cd8d 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
>  	switch (ibitype) {
>  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
>  		if (dev) {
> -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> -			master->ibi.tbq_slot = NULL;
> +			data = i3c_dev_get_master_data(dev);
> +			if (master->ibi.slots[data->ibi]) {
> +				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> +				master->ibi.tbq_slot = NULL;
> +			}
>  		}
>  		svc_i3c_master_emit_stop(master);
>  		break;
> --
> 2.46.1
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From jarkko.nikula at linux.intel.com  Fri Mar  7 01:14:06 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Fri, 7 Mar 2025 11:14:06 +0200
Subject: [PATCH 1/4] i3c: mipi-i3c-hci: Allow only relevant INTR_STATUS
 bit updates
In-Reply-To: <Z8HduKx0dzRAqRev@lizhi-Precision-Tower-5810>
References: <20250228141802.1344453-1-jarkko.nikula@linux.intel.com>
 <Z8HduKx0dzRAqRev@lizhi-Precision-Tower-5810>
Message-ID: <6947fe08-f479-4692-a5d7-5b54496e4909@linux.intel.com>

Hi Frank

Sorry the delay, somehow I missed your comments to this patch :-|

On 2/28/25 6:00 PM, Frank Li wrote:
> On Fri, Feb 28, 2025 at 04:17:59PM +0200, Jarkko Nikula wrote:
>> Since MIPI I3C HCI specification version v0.8 INTR_STATUS bits 9:0 are
>> reserved. Version v0.5 has bits 9 and 5:0 in use but not handled by the
>> current driver code and not needed in DMA transfers.
>>
>> PIO transfers with v0.5 would require changes to both
>> core.c: i3c_hci_irq_handler() and pio.c: hci_pio_irq_handler() though.
> 
> If reasonable, why not change core.c and pio.c?
> 
I had two reasons for that. The v0.5 compatible IP I use in testing 
doesn't support PIO transfers and thus didn't want to add code that is 
not tested.

Then I believe perhaps nobody will release HW with this old IP and thus 
it would be dead code anyway.

>>
>> For these reasons don't enable signal updates from INTR_STATUS bits 9:0.
>>
>> This change is a no-op for specification versions v0.8 and beyond but
>> gets rid of "unexpected INTR_STATUS" errors if somebody (read me) wants
>> to run code on old v0.5 IP version.
> 
> I think, simple said
> "Get rid of "unexpected INTR_STATUS" errors at old v0.5 IP version and
> no-op for version above v0.8."
> 
Makes sense, will change.

>>
>> Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
>> ---
>>   drivers/i3c/master/mipi-i3c-hci/core.c | 5 +++--
>>   1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
>> index a71226d7ca59..e139d7e4d252 100644
>> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
>> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
>> @@ -699,9 +699,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
>>   	if (ret)
>>   		return -ENXIO;
>>
>> -	/* Disable all interrupts and allow all signal updates */
>> +	/* Disable all interrupts */
>>   	reg_write(INTR_SIGNAL_ENABLE, 0x0);
>> -	reg_write(INTR_STATUS_ENABLE, 0xffffffff);
>> +	/* Allow signal updates relevant to IP versions 0.8 and beyond */
>> +	reg_write(INTR_STATUS_ENABLE, GENMASK(31, 10));
> 
> Generally, just enable needed IRQ in driver. Define some BITS for
> difference type IRQs.
> 
I was thinking too these need changes too but decided those are better 
to do in another patch(es).

Currently all of these generic interrupt sources are disabled so they 
won't generate interrupt but their status will be printed when handler 
is called due to DMA/PIO interrupt. Known bits 10 INTR_HC_INTERNAL_ERR 
and 11 INTR_HC_SEQ_CANCEL will print their message and unknowns just 
"unexpected INTR_STATUS" with hex of unhandled status bits.

Bits 12:14 can be defined since v1.2 describes them. I'm open for ideas 
does it make more sense to allow signal updates only from known sources 
or keep all bits enabled so that in future IP versions "unexpected 
INTR_STATUS" can be seen from user reports if something odd happens and 
driver is not yet handling that.

Another change is should known generic interrupt sources be enabled so 
handler will be called immediately when that condition occurs.


From Frank.li at nxp.com  Fri Mar  7 07:18:01 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 7 Mar 2025 10:18:01 -0500
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>

On Fri, Mar 07, 2025 at 12:34:53PM +0000, Manjunatha Venkatesh wrote:
>
>
> > -----Original Message-----
> > From: Frank Li <frank.li at nxp.com>
> > Sent: Thursday, March 6, 2025 9:01 PM
> > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> >
> > On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh wrote:
> > > Hi Frank,
> > >
> > > Please find my inline comments.
> > >
> > > Regards,
> > > Manju
> >
> > Avoid top post for linux kernel mail list.
> >
> > >
> > > > -----Original Message-----
> > > > From: Frank Li <frank.li at nxp.com>
> > > > Sent: Friday, February 28, 2025 9:19 PM
> > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > > fixed
> > > >
> > > > Subject should be "Fix read from unreadable memory at
> > > > svc_i3c_master_ibi_work()"
> > > > Or like below pattern:
> > > > 	Do ... to fix ...
> > > >
> > > [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > > > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh
> > wrote:
> > > > > I3C Master driver svc-i3c-master
> > > >
> > > > Needn't this line.
> > > >
> > > [Manjunatha Venkatesh] Removed this line and submitted the new patch
> > > > >
> > > > > As part of I3C driver probing sequence for particular device
> > > > > instance, While adding to queue it is trying to access ibi
> > > > > variable of dev which is not yet initialized causing "Unable to
> > > > > handle kernel read from unreadable memory" resulting in kernel panic.
> > > >
> > > > Can you provide more detail information why/how this happen? which
> > > > varible read cause this problem?
> > > >
> > > [Manjunatha Venkatesh] : Below is the sequence where this issue
> > happened.
> > > 1. During boot up sequence IBI is received at host  from the slave device
> > before requesting for IBI, Usually will request IBI by calling
> > i3c_device_request_ibi() during probe of slave driver.
> > > 2. Since master code trying to access IBI Variable for the particular device
> > instance before actually it initialized by slave driver, due to this randomly
> > accessing the address and causing kernel panic.
> > > 3. i3c_device_request_ibi() function invoked by the slave driver where dev-
> > >ibi = ibi; assigned as part of function call i3c_dev_request_ibi_locked().
> > > 4. But when IBI request sent by slave device, master code  trying to access
> > this variable before its initialized due to this race condition situation kernel
> > panic happened.
> >
> > Write above reproduce steps to commit message.
> >
> [Manjunatha Venkatesh] : Next commit will update this description.
> > I think it is common problem for i3c framework.
> >
> > You'd better change i3c_master_queue_ibi()
> >
> > void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
> > {
> > 	if (!slot)
> > 		return;
> >
> >         atomic_inc(&dev->ibi->pending_ibis);
> >         queue_work(dev->ibi->wq, &slot->work); }
> >
> [Manjunatha Venkatesh] : Actual issue we have faced with respect to 'dev->ibi' variable.

How about
if (!dev->ibi || !slot) {
	dev_warning("...");
	return;
}

Frank

> Pointer variable 'slot' is with respect IBI received from slave device context and 'dev->ibi' is with respect to initialization of slave driver these 2 are asynchronous events.
> dev->ibi = ibi; is initialized at i3c_dev_request_ibi_locked(), this is invoked as part of slave driver IBI init sequence, this is what we want to check before processing the IBI request from the Slave device.
> master->ibi.slots[i] this is where all device ibi instance list are saved, so here our slave driver init IBI stored with respect dev->ibi index.
> So adding 'if (!slot)' will not help to resolve this issue.


Please wrap around at 80 char to read easily.


>
> > Frank
> > >
> > >
> > > > Need fix tags and cc stable.
> > > >
> > > [Manjunatha Venkatesh] : fix tags and cc stable updated in the commit
> > message.
> > >
> [Manjunatha Venkatesh] : Last commit message missed to update fix tags and cc stable.
> Will update that information as part of next commit message.
> > > > Frank
> > > > >
> > > > > Signed-off-by: Manjunatha Venkatesh
> > <manjunatha.venkatesh at nxp.com>
> > > > > ---
> > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > > > work_struct *work)
> > > > >  	switch (ibitype) {
> > > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > >  		if (dev) {
> > > > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > > > -			master->ibi.tbq_slot = NULL;
> > > > > +			data = i3c_dev_get_master_data(dev);
> > > > > +			if (master->ibi.slots[data->ibi]) {
> > > > > +				i3c_master_queue_ibi(dev, master-
> > > > >ibi.tbq_slot);
> > > > > +				master->ibi.tbq_slot = NULL;
> > > > > +			}
> > > > >  		}
> > > > >  		svc_i3c_master_emit_stop(master);
> > > > >  		break;
> > > > > --
> > > > > 2.46.1
> > > > >
> > > > >
> > > > > --
> > > > > linux-i3c mailing list
> > > > > linux-i3c at lists.infradead.org
> > > > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Fri Mar  7 12:24:26 2025
From: Frank.li at nxp.com (Frank Li)
Date: Fri, 7 Mar 2025 15:24:26 -0500
Subject: [PATCH 1/4] i3c: mipi-i3c-hci: Allow only relevant INTR_STATUS
 bit updates
In-Reply-To: <6947fe08-f479-4692-a5d7-5b54496e4909@linux.intel.com>
References: <20250228141802.1344453-1-jarkko.nikula@linux.intel.com>
 <Z8HduKx0dzRAqRev@lizhi-Precision-Tower-5810>
 <6947fe08-f479-4692-a5d7-5b54496e4909@linux.intel.com>
Message-ID: <Z8tV+sBt+q72pqgL@lizhi-Precision-Tower-5810>

On Fri, Mar 07, 2025 at 11:14:06AM +0200, Jarkko Nikula wrote:
> Hi Frank
>
> Sorry the delay, somehow I missed your comments to this patch :-|
>
> On 2/28/25 6:00 PM, Frank Li wrote:
> > On Fri, Feb 28, 2025 at 04:17:59PM +0200, Jarkko Nikula wrote:
> > > Since MIPI I3C HCI specification version v0.8 INTR_STATUS bits 9:0 are
> > > reserved. Version v0.5 has bits 9 and 5:0 in use but not handled by the
> > > current driver code and not needed in DMA transfers.
> > >
> > > PIO transfers with v0.5 would require changes to both
> > > core.c: i3c_hci_irq_handler() and pio.c: hci_pio_irq_handler() though.
> >
> > If reasonable, why not change core.c and pio.c?
> >
> I had two reasons for that. The v0.5 compatible IP I use in testing doesn't
> support PIO transfers and thus didn't want to add code that is not tested.
>
> Then I believe perhaps nobody will release HW with this old IP and thus it
> would be dead code anyway.
>
> > >
> > > For these reasons don't enable signal updates from INTR_STATUS bits 9:0.
> > >
> > > This change is a no-op for specification versions v0.8 and beyond but
> > > gets rid of "unexpected INTR_STATUS" errors if somebody (read me) wants
> > > to run code on old v0.5 IP version.
> >
> > I think, simple said
> > "Get rid of "unexpected INTR_STATUS" errors at old v0.5 IP version and
> > no-op for version above v0.8."
> >
> Makes sense, will change.
>
> > >
> > > Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
> > > ---
> > >   drivers/i3c/master/mipi-i3c-hci/core.c | 5 +++--
> > >   1 file changed, 3 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> > > index a71226d7ca59..e139d7e4d252 100644
> > > --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> > > +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> > > @@ -699,9 +699,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
> > >   	if (ret)
> > >   		return -ENXIO;
> > >
> > > -	/* Disable all interrupts and allow all signal updates */
> > > +	/* Disable all interrupts */
> > >   	reg_write(INTR_SIGNAL_ENABLE, 0x0);
> > > -	reg_write(INTR_STATUS_ENABLE, 0xffffffff);
> > > +	/* Allow signal updates relevant to IP versions 0.8 and beyond */
> > > +	reg_write(INTR_STATUS_ENABLE, GENMASK(31, 10));
> >
> > Generally, just enable needed IRQ in driver. Define some BITS for
> > difference type IRQs.
> >
> I was thinking too these need changes too but decided those are better to do
> in another patch(es).
>
> Currently all of these generic interrupt sources are disabled so they won't
> generate interrupt but their status will be printed when handler is called
> due to DMA/PIO interrupt. Known bits 10 INTR_HC_INTERNAL_ERR and 11
> INTR_HC_SEQ_CANCEL will print their message and unknowns just "unexpected
> INTR_STATUS" with hex of unhandled status bits.
>
> Bits 12:14 can be defined since v1.2 describes them. I'm open for ideas does
> it make more sense to allow signal updates only from known sources or keep
> all bits enabled so that in future IP versions "unexpected INTR_STATUS" can
> be seen from user reports if something odd happens and driver is not yet
> handling that.

I think we can defer it until someone really complain it. I am fine for
your current change.

Frank
>
> Another change is should known generic interrupt sources be enabled so
> handler will be called immediately when that condition occurs.
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From dan.carpenter at linaro.org  Sat Mar  8 03:16:51 2025
From: dan.carpenter at linaro.org (Dan Carpenter)
Date: Sat, 8 Mar 2025 14:16:51 +0300
Subject: [bug report] i3c: master: svc: Fix npcm845 FIFO empty issue
Message-ID: <029e5ac0-5444-4a8e-bca4-cec55950d2b9@stanley.mountain>

Hello Stanley Chu,

Commit 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty
issue") from Mar 6, 2025 (linux-next), leads to the following Smatch
static checker warning:

drivers/i3c/master/svc-i3c-master.c:1002 svc_i3c_master_do_daa_locked() warn: error code type promoted to positive: 'dyn_addr'
drivers/i3c/master/svc-i3c-master.c:1085 svc_i3c_master_do_daa_locked() error: uninitialized symbol 'dyn_addr'.

drivers/i3c/master/svc-i3c-master.c
   939  static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
   940                                          u8 *addrs, unsigned int *count)
   941  {
   942          u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
   943          unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
   944          u32 reg;
   945          int ret, i;
   946  
   947          svc_i3c_master_flush_fifo(master);
   948  
   949          while (true) {
   950                  /* clean SVC_I3C_MINT_IBIWON w1c bits */
   951                  writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
   952  
   953                  /* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA.
   954                   *
   955                   * ENTER DAA:
   956                   *   1 will issue START, 7E, ENTDAA, and then emits 7E/R to process first target.
   957                   *   2 Stops just before the new Dynamic Address (DA) is to be emitted.
   958                   *
   959                   * PROCESS DAA:
   960                   *   1 The DA is written using MWDATAB or ADDR bits 6:0.
   961                   *   2 ProcessDAA is requested again to write the new address, and then starts the
   962                   *     next (START, 7E, ENTDAA)  unless marked to STOP; an MSTATUS indicating NACK
   963                   *     means DA was not accepted (e.g. parity error). If PROCESSDAA is NACKed on the
   964                   *     7E/R, which means no more Slaves need a DA, then a COMPLETE will be signaled
   965                   *     (along with DONE), and a STOP issued automatically.
   966                   */
   967                  writel(SVC_I3C_MCTRL_REQUEST_PROC_DAA |
   968                         SVC_I3C_MCTRL_TYPE_I3C |
   969                         SVC_I3C_MCTRL_IBIRESP_NACK |
   970                         SVC_I3C_MCTRL_DIR(SVC_I3C_MCTRL_DIR_WRITE),
   971                         master->regs + SVC_I3C_MCTRL);
   972  
   973                  /*
   974                   * Either one slave will send its ID, or the assignment process
   975                   * is done.
   976                   */
   977                  ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS,
   978                                                  reg,
   979                                                  SVC_I3C_MSTATUS_RXPEND(reg) |
   980                                                  SVC_I3C_MSTATUS_MCTRLDONE(reg),
   981                                                  1, 1000);
   982                  if (ret)
   983                          break;
   984  
   985                  if (SVC_I3C_MSTATUS_RXPEND(reg)) {
   986                          u8 data[6];
   987  
   988                          /*
   989                           * One slave sends its ID to request for address assignment,
   990                           * prefilling the dynamic address can reduce SCL clock stalls
   991                           * and also fix the SVC_I3C_QUIRK_FIFO_EMPTY quirk.
   992                           *
   993                           * Ideally, prefilling before the processDAA command is better.
   994                           * However, it requires an additional check to write the dyn_addr
   995                           * at the right time because the driver needs to write the processDAA
   996                           * command twice for one assignment.
   997                           * Prefilling here is safe and efficient because the FIFO starts
   998                           * filling within a few hundred nanoseconds, which is significantly
   999                           * faster compared to the 64 SCL clock cycles.
  1000                           */
  1001                          dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
  1002                          if (dyn_addr < 0)
  1003                                  return -ENOSPC;

dyn_addr is unsigned so it can't be negative.  Also why return -ENOSPC
instead of propagating the error code?


  1004  
  1005                          writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
  1006  
  1007                          /*
  1008                           * We only care about the 48-bit provisioned ID yet to
  1009                           * be sure a device does not nack an address twice.
  1010                           * Otherwise, we would just need to flush the RX FIFO.
  1011                           */
  1012                          ret = svc_i3c_master_readb(master, data, 6);
  1013                          if (ret)
  1014                                  break;
  1015  
  1016                          for (i = 0; i < 6; i++)
  1017                                  prov_id[dev_nb] |= (u64)(data[i]) << (8 * (5 - i));
  1018  
  1019                          /* We do not care about the BCR and DCR yet */
  1020                          ret = svc_i3c_master_readb(master, data, 2);
  1021                          if (ret)
  1022                                  break;
  1023                  } else if (SVC_I3C_MSTATUS_IBIWON(reg)) {
  1024                          ret = svc_i3c_master_handle_ibi_won(master, reg);
  1025                          if (ret)
  1026                                  break;
  1027                          continue;
  1028                  } else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) {
  1029                          if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
  1030                              SVC_I3C_MSTATUS_COMPLETE(reg)) {
  1031                                  /*
  1032                                   * All devices received and acked they dynamic
  1033                                   * address, this is the natural end of the DAA
  1034                                   * procedure.
  1035                                   *
  1036                                   * Hardware will auto emit STOP at this case.
  1037                                   */
  1038                                  *count = dev_nb;
  1039                                  return 0;
  1040  
  1041                          } else if (SVC_I3C_MSTATUS_NACKED(reg)) {
  1042                                  /* No I3C devices attached */
  1043                                  if (dev_nb == 0) {
  1044                                          /*
  1045                                           * Hardware can't treat first NACK for ENTAA as normal
  1046                                           * COMPLETE. So need manual emit STOP.
  1047                                           */
  1048                                          ret = 0;
  1049                                          *count = 0;
  1050                                          break;
  1051                                  }
  1052  
  1053                                  /*
  1054                                   * A slave device nacked the address, this is
  1055                                   * allowed only once, DAA will be stopped and
  1056                                   * then resumed. The same device is supposed to
  1057                                   * answer again immediately and shall ack the
  1058                                   * address this time.
  1059                                   */
  1060                                  if (prov_id[dev_nb] == nacking_prov_id) {
  1061                                          ret = -EIO;
  1062                                          break;
  1063                                  }
  1064  
  1065                                  dev_nb--;
  1066                                  nacking_prov_id = prov_id[dev_nb];
  1067                                  svc_i3c_master_emit_stop(master);
  1068  
  1069                                  continue;
  1070                          } else {
  1071                                  break;
  1072                          }
  1073                  }

There isn't an else statement here.  dyn_addr could be uninitialized on
else.

  1074  
  1075                  /* Wait for the slave to be ready to receive its address */
  1076                  ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS,
  1077                                                  reg,
  1078                                                  SVC_I3C_MSTATUS_MCTRLDONE(reg) &&
  1079                                                  SVC_I3C_MSTATUS_STATE_DAA(reg) &&
  1080                                                  SVC_I3C_MSTATUS_BETWEEN(reg),
  1081                                                  0, 1000);
  1082                  if (ret)
  1083                          break;
  1084  
  1085                  addrs[dev_nb] = dyn_addr;
                                        ^^^^^^^^

  1086                  dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
  1086                  dev_dbg(master->dev, "DAA: device %d assigned to 0x%02x\n",
  1087                          dev_nb, addrs[dev_nb]);
  1088                  last_addr = addrs[dev_nb++];
  1089          }
  1090  
  1091          /* Need manual issue STOP except for Complete condition */
  1092          svc_i3c_master_emit_stop(master);
  1093          svc_i3c_master_flush_fifo(master);
  1094  
  1095          return ret;
  1096  }

regards,
dan carpenter


From stanley.chuys at gmail.com  Sun Mar  9 19:33:04 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Mon, 10 Mar 2025 10:33:04 +0800
Subject: [PATCH v1 1/1] i3c: master: svc: Fix i3c_master_get_free_addr return check
Message-ID: <20250310023304.2335792-1-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The return value of i3c_master_get_free_addr is assigned to a variable
with wrong type, so it can't be negative. Use a signed integer for the
return value. If the value is negative, break the process and propagate
the error code.

This commit also fixes the uninitialized symbol 'dyn_addr', reported
by Smatch static checker.

Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
Reported-by: Dan Carpenter <dan.carpenter at linaro.org>
Closes: https://lore.kernel.org/all/029e5ac0-5444-4a8e-bca4-cec55950d2b9 at stanley.mountain/
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index f22fb9e75142..1d1f351b9a85 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -940,7 +940,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 					u8 *addrs, unsigned int *count)
 {
 	u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
-	unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
+	unsigned int dev_nb = 0, last_addr = 0, dyn_addr = 0;
 	u32 reg;
 	int ret, i;
 
@@ -998,10 +998,11 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 			 * filling within a few hundred nanoseconds, which is significantly
 			 * faster compared to the 64 SCL clock cycles.
 			 */
-			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
-			if (dyn_addr < 0)
-				return -ENOSPC;
+			ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
+			if (ret < 0)
+				break;
 
+			dyn_addr = ret;
 			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
 
 			/*
-- 
2.34.1



From Frank.li at nxp.com  Mon Mar 10 07:34:30 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 10 Mar 2025 10:34:30 -0400
Subject: [PATCH v1 1/1] i3c: master: svc: Fix i3c_master_get_free_addr
 return check
In-Reply-To: <20250310023304.2335792-1-yschu@nuvoton.com>
References: <20250310023304.2335792-1-yschu@nuvoton.com>
Message-ID: <Z874dh9lV7P+GpkM@lizhi-Precision-Tower-5810>

On Mon, Mar 10, 2025 at 10:33:04AM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The return value of i3c_master_get_free_addr is assigned to a variable
> with wrong type, so it can't be negative. Use a signed integer for the
> return value. If the value is negative, break the process and propagate
> the error code.
>
> This commit also fixes the uninitialized symbol 'dyn_addr', reported
> by Smatch static checker.
>
> Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
> Reported-by: Dan Carpenter <dan.carpenter at linaro.org>
> Closes: https://lore.kernel.org/all/029e5ac0-5444-4a8e-bca4-cec55950d2b9 at stanley.mountain/
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> ---

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>  drivers/i3c/master/svc-i3c-master.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index f22fb9e75142..1d1f351b9a85 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -940,7 +940,7 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
>  					u8 *addrs, unsigned int *count)
>  {
>  	u64 prov_id[SVC_I3C_MAX_DEVS] = {}, nacking_prov_id = 0;
> -	unsigned int dev_nb = 0, last_addr = 0, dyn_addr;
> +	unsigned int dev_nb = 0, last_addr = 0, dyn_addr = 0;
>  	u32 reg;
>  	int ret, i;
>
> @@ -998,10 +998,11 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
>  			 * filling within a few hundred nanoseconds, which is significantly
>  			 * faster compared to the 64 SCL clock cycles.
>  			 */
> -			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> -			if (dyn_addr < 0)
> -				return -ENOSPC;
> +			ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> +			if (ret < 0)
> +				break;
>
> +			dyn_addr = ret;
>  			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
>
>  			/*
> --
> 2.34.1
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From manjunatha.venkatesh at nxp.com  Fri Mar  7 04:34:53 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Fri, 7 Mar 2025 12:34:53 +0000
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Thursday, March 6, 2025 9:01 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> 
> On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh wrote:
> > Hi Frank,
> >
> > Please find my inline comments.
> >
> > Regards,
> > Manju
> 
> Avoid top post for linux kernel mail list.
> 
> >
> > > -----Original Message-----
> > > From: Frank Li <frank.li at nxp.com>
> > > Sent: Friday, February 28, 2025 9:19 PM
> > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > fixed
> > >
> > > Subject should be "Fix read from unreadable memory at
> > > svc_i3c_master_ibi_work()"
> > > Or like below pattern:
> > > 	Do ... to fix ...
> > >
> > [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh
> wrote:
> > > > I3C Master driver svc-i3c-master
> > >
> > > Needn't this line.
> > >
> > [Manjunatha Venkatesh] Removed this line and submitted the new patch
> > > >
> > > > As part of I3C driver probing sequence for particular device
> > > > instance, While adding to queue it is trying to access ibi
> > > > variable of dev which is not yet initialized causing "Unable to
> > > > handle kernel read from unreadable memory" resulting in kernel panic.
> > >
> > > Can you provide more detail information why/how this happen? which
> > > varible read cause this problem?
> > >
> > [Manjunatha Venkatesh] : Below is the sequence where this issue
> happened.
> > 1. During boot up sequence IBI is received at host  from the slave device
> before requesting for IBI, Usually will request IBI by calling
> i3c_device_request_ibi() during probe of slave driver.
> > 2. Since master code trying to access IBI Variable for the particular device
> instance before actually it initialized by slave driver, due to this randomly
> accessing the address and causing kernel panic.
> > 3. i3c_device_request_ibi() function invoked by the slave driver where dev-
> >ibi = ibi; assigned as part of function call i3c_dev_request_ibi_locked().
> > 4. But when IBI request sent by slave device, master code  trying to access
> this variable before its initialized due to this race condition situation kernel
> panic happened.
> 
> Write above reproduce steps to commit message.
> 
[Manjunatha Venkatesh] : Next commit will update this description.
> I think it is common problem for i3c framework.
> 
> You'd better change i3c_master_queue_ibi()
> 
> void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
> {
> 	if (!slot)
> 		return;
> 
>         atomic_inc(&dev->ibi->pending_ibis);
>         queue_work(dev->ibi->wq, &slot->work); }
> 
[Manjunatha Venkatesh] : Actual issue we have faced with respect to 'dev->ibi' variable.
Pointer variable 'slot' is with respect IBI received from slave device context and 'dev->ibi' is with respect to initialization of slave driver these 2 are asynchronous events.
dev->ibi = ibi; is initialized at i3c_dev_request_ibi_locked(), this is invoked as part of slave driver IBI init sequence, this is what we want to check before processing the IBI request from the Slave device.
master->ibi.slots[i] this is where all device ibi instance list are saved, so here our slave driver init IBI stored with respect dev->ibi index.
So adding 'if (!slot)' will not help to resolve this issue.

> Frank
> >
> >
> > > Need fix tags and cc stable.
> > >
> > [Manjunatha Venkatesh] : fix tags and cc stable updated in the commit
> message.
> >
[Manjunatha Venkatesh] : Last commit message missed to update fix tags and cc stable.
Will update that information as part of next commit message.
> > > Frank
> > > >
> > > > Signed-off-by: Manjunatha Venkatesh
> <manjunatha.venkatesh at nxp.com>
> > > > ---
> > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > > work_struct *work)
> > > >  	switch (ibitype) {
> > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > >  		if (dev) {
> > > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > > -			master->ibi.tbq_slot = NULL;
> > > > +			data = i3c_dev_get_master_data(dev);
> > > > +			if (master->ibi.slots[data->ibi]) {
> > > > +				i3c_master_queue_ibi(dev, master-
> > > >ibi.tbq_slot);
> > > > +				master->ibi.tbq_slot = NULL;
> > > > +			}
> > > >  		}
> > > >  		svc_i3c_master_emit_stop(master);
> > > >  		break;
> > > > --
> > > > 2.46.1
> > > >
> > > >
> > > > --
> > > > linux-i3c mailing list
> > > > linux-i3c at lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From qasdev00 at gmail.com  Sun Mar  9 09:43:14 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Sun,  9 Mar 2025 16:43:14 +0000
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in dynamic address assignment
Message-ID: <20250309164314.15039-1-qasdev00@gmail.com>

svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int 
however it initialises it with i3c_master_get_free_addr() which 
returns a signed int type and then attempts to check if dyn_addr is 
less than 0. Unsigned integers cannot be less than 0, so the check 
is essentially redundant. Furthermore i3c_master_get_free_addr() 
could return -ENOMEM which an unsigned int cannot store.

Fix this by capturing the return value of i3c_master_get_free_addr() 
in a signed int ???dyn_addr_ret???. If that value is negative, return 
an error. Otherwise, assign it to the unsigned int ???dyn_addr??? once 
we know it???s valid.

Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/i3c/master/svc-i3c-master.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index f22fb9e75142..eea08f00d7ce 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -998,9 +998,11 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 			 * filling within a few hundred nanoseconds, which is significantly
 			 * faster compared to the 64 SCL clock cycles.
 			 */
-			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
-			if (dyn_addr < 0)
+			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
+
+			if (dyn_addr_ret < 0)
 				return -ENOSPC;
+			dyn_addr = dyn_addr_ret;
 
 			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
 
-- 
2.39.5



From jarkko.nikula at linux.intel.com  Wed Mar 12 04:10:47 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Wed, 12 Mar 2025 13:10:47 +0200
Subject: [PATCH v2 2/4] i3c: mipi-i3c-hci: Fix handling status of i3c_hci_irq_handler()
In-Reply-To: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
Message-ID: <20250312111049.197855-2-jarkko.nikula@linux.intel.com>

Return IRQ_HANDLED from the i3c_hci_irq_handler() only if some
INTR_STATUS bit was set or if DMA/PIO handler handled it.

Currently it returns IRQ_HANDLED in case INTR_STATUS is zero and IO
handler returns false. Which could be the case if interrupt comes from
other device or is spurious.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
 drivers/i3c/master/mipi-i3c-hci/core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index e139d7e4d252..e5593b6e897e 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -594,6 +594,7 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
 
 	if (val) {
 		reg_write(INTR_STATUS, val);
+		result = IRQ_HANDLED;
 	}
 
 	if (val & INTR_HC_RESET_CANCEL) {
@@ -605,12 +606,11 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
 		val &= ~INTR_HC_INTERNAL_ERR;
 	}
 
-	hci->io->irq_handler(hci);
+	if (hci->io->irq_handler(hci))
+		result = IRQ_HANDLED;
 
 	if (val)
 		dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val);
-	else
-		result = IRQ_HANDLED;
 
 	return result;
 }
-- 
2.47.2



From jarkko.nikula at linux.intel.com  Wed Mar 12 04:10:46 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Wed, 12 Mar 2025 13:10:46 +0200
Subject: [PATCH v2 1/4] i3c: mipi-i3c-hci: Allow only relevant INTR_STATUS bit updates
Message-ID: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>

Since MIPI I3C HCI specification version v0.8 INTR_STATUS bits 9:0 are
reserved. Version v0.5 has bits 9 and 5:0 in use but not handled by the
current driver code and not needed in DMA transfers.

PIO transfers with v0.5 would require changes to both
core.c: i3c_hci_irq_handler() and pio.c: hci_pio_irq_handler() though.

For these reasons don't enable signal updates from INTR_STATUS bits 9:0.

This change gets rid of "unexpected INTR_STATUS" on old v0.5 IP version
and is a no-op for later versions starting from v0.8.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
v2: Simplified the last sentence according to Frank Li's suggestion.
---
 drivers/i3c/master/mipi-i3c-hci/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index a71226d7ca59..e139d7e4d252 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -699,9 +699,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
 	if (ret)
 		return -ENXIO;
 
-	/* Disable all interrupts and allow all signal updates */
+	/* Disable all interrupts */
 	reg_write(INTR_SIGNAL_ENABLE, 0x0);
-	reg_write(INTR_STATUS_ENABLE, 0xffffffff);
+	/* Allow signal updates relevant to IP versions 0.8 and beyond */
+	reg_write(INTR_STATUS_ENABLE, GENMASK(31, 10));
 
 	/* Make sure our data ordering fits the host's */
 	regval = reg_read(HC_CONTROL);
-- 
2.47.2



From jarkko.nikula at linux.intel.com  Wed Mar 12 04:10:48 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Wed, 12 Mar 2025 13:10:48 +0200
Subject: [PATCH v2 3/4] i3c: mipi-i3c-hci: Change name of INTR_STATUS bit 11
In-Reply-To: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
Message-ID: <20250312111049.197855-3-jarkko.nikula@linux.intel.com>

INTR_STATUS bit 11 INTR_HC_RESET_CANCEL was probably projected for the
MIPI I3C HCI specification version 2 but was not ever implemented.

This bit is first time specified in the v1.2 as HC_SEQ_CANCEL_STAT
"Host Controller Cancelled Transaction Sequence". Update the definition
and debug print of it accordingly.

While at it, change DBG() print to dev_dbg().

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
 drivers/i3c/master/mipi-i3c-hci/core.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index e5593b6e897e..84c372740020 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -78,7 +78,7 @@
 #define INTR_SIGNAL_ENABLE		0x28
 #define INTR_FORCE			0x2c
 #define INTR_HC_CMD_SEQ_UFLOW_STAT	BIT(12)	/* Cmd Sequence Underflow */
-#define INTR_HC_RESET_CANCEL		BIT(11)	/* HC Cancelled Reset */
+#define INTR_HC_SEQ_CANCEL		BIT(11)	/* HC Cancelled Transaction Sequence */
 #define INTR_HC_INTERNAL_ERR		BIT(10)	/* HC Internal Error */
 
 #define DAT_SECTION			0x30	/* Device Address Table */
@@ -597,9 +597,10 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
 		result = IRQ_HANDLED;
 	}
 
-	if (val & INTR_HC_RESET_CANCEL) {
-		DBG("cancelled reset");
-		val &= ~INTR_HC_RESET_CANCEL;
+	if (val & INTR_HC_SEQ_CANCEL) {
+		dev_dbg(&hci->master.dev,
+			"Host Controller Cancelled Transaction Sequence\n");
+		val &= ~INTR_HC_SEQ_CANCEL;
 	}
 	if (val & INTR_HC_INTERNAL_ERR) {
 		dev_err(&hci->master.dev, "Host Controller Internal Error\n");
-- 
2.47.2



From jarkko.nikula at linux.intel.com  Wed Mar 12 04:10:49 2025
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Wed, 12 Mar 2025 13:10:49 +0200
Subject: [PATCH v2 4/4] i3c: mipi-i3c-hci: Move unexpected INTR_STATUS print before IO handler
In-Reply-To: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
Message-ID: <20250312111049.197855-4-jarkko.nikula@linux.intel.com>

Move "unexpected INTR_STATUS" error print before calling the IO handler
as it is more consistent that way. Otherwise it may be confusing if
generic interrupt related prints are mixed with IO handler prints.

Since this error print is more indication of missing code rather than
runtime error downgrade it to dev_warn_once().

Reviewed-by: Frank Li <Frank.Li at nxp.com>
Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
v2: Added Reviewed-by
---
 drivers/i3c/master/mipi-i3c-hci/core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index 84c372740020..5c173249c0ac 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -607,12 +607,13 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
 		val &= ~INTR_HC_INTERNAL_ERR;
 	}
 
+	if (val)
+		dev_warn_once(&hci->master.dev,
+			      "unexpected INTR_STATUS %#x\n", val);
+
 	if (hci->io->irq_handler(hci))
 		result = IRQ_HANDLED;
 
-	if (val)
-		dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val);
-
 	return result;
 }
 
-- 
2.47.2



From Frank.li at nxp.com  Wed Mar 12 07:42:00 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 12 Mar 2025 10:42:00 -0400
Subject: [PATCH v2 1/4] i3c: mipi-i3c-hci: Allow only relevant
 INTR_STATUS bit updates
In-Reply-To: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
Message-ID: <Z9GdOOage3rBf6aU@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 01:10:46PM +0200, Jarkko Nikula wrote:
> Since MIPI I3C HCI specification version v0.8 INTR_STATUS bits 9:0 are
> reserved. Version v0.5 has bits 9 and 5:0 in use but not handled by the
> current driver code and not needed in DMA transfers.
>
> PIO transfers with v0.5 would require changes to both
> core.c: i3c_hci_irq_handler() and pio.c: hci_pio_irq_handler() though.
>
> For these reasons don't enable signal updates from INTR_STATUS bits 9:0.
>
> This change gets rid of "unexpected INTR_STATUS" on old v0.5 IP version
> and is a no-op for later versions starting from v0.8.

submitting-patches.rst don't perfer words: "this change" or "this patch".

Get rid of "unexpected INTR_STATUS" on old v0.5 IP version ...

And below nit

Reviewed-by: Frank Li <Frank.Li at nxp.com>

>
> Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
> ---
> v2: Simplified the last sentence according to Frank Li's suggestion.
> ---
>  drivers/i3c/master/mipi-i3c-hci/core.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index a71226d7ca59..e139d7e4d252 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -699,9 +699,10 @@ static int i3c_hci_init(struct i3c_hci *hci)
>  	if (ret)
>  		return -ENXIO;
>
> -	/* Disable all interrupts and allow all signal updates */
> +	/* Disable all interrupts */
>  	reg_write(INTR_SIGNAL_ENABLE, 0x0);
> -	reg_write(INTR_STATUS_ENABLE, 0xffffffff);
> +	/* Allow signal updates relevant to IP versions 0.8 and beyond */

Nit:

Only allow bit 31:10 signal update because
Bit 0:9 is not neededed for DMA transfer when version >= 0.8
Bit 0:9 is not handled by pio driver when version < 0.8.

Frank
> +	reg_write(INTR_STATUS_ENABLE, GENMASK(31, 10));
>
>  	/* Make sure our data ordering fits the host's */
>  	regval = reg_read(HC_CONTROL);
> --
> 2.47.2
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Wed Mar 12 09:24:36 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 12 Mar 2025 12:24:36 -0400
Subject: [PATCH v2 3/4] i3c: mipi-i3c-hci: Change name of INTR_STATUS bit
 11
In-Reply-To: <20250312111049.197855-3-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
 <20250312111049.197855-3-jarkko.nikula@linux.intel.com>
Message-ID: <Z9G1RDI77BOR9dtX@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 01:10:48PM +0200, Jarkko Nikula wrote:
> INTR_STATUS bit 11 INTR_HC_RESET_CANCEL was probably projected for the
> MIPI I3C HCI specification version 2 but was not ever implemented.
>
> This bit is first time specified in the v1.2 as HC_SEQ_CANCEL_STAT
> "Host Controller Cancelled Transaction Sequence". Update the definition
> and debug print of it accordingly.
>
> While at it, change DBG() print to dev_dbg().
>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
> ---
>  drivers/i3c/master/mipi-i3c-hci/core.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index e5593b6e897e..84c372740020 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -78,7 +78,7 @@
>  #define INTR_SIGNAL_ENABLE		0x28
>  #define INTR_FORCE			0x2c
>  #define INTR_HC_CMD_SEQ_UFLOW_STAT	BIT(12)	/* Cmd Sequence Underflow */
> -#define INTR_HC_RESET_CANCEL		BIT(11)	/* HC Cancelled Reset */
> +#define INTR_HC_SEQ_CANCEL		BIT(11)	/* HC Cancelled Transaction Sequence */
>  #define INTR_HC_INTERNAL_ERR		BIT(10)	/* HC Internal Error */
>
>  #define DAT_SECTION			0x30	/* Device Address Table */
> @@ -597,9 +597,10 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
>  		result = IRQ_HANDLED;
>  	}
>
> -	if (val & INTR_HC_RESET_CANCEL) {
> -		DBG("cancelled reset");
> -		val &= ~INTR_HC_RESET_CANCEL;
> +	if (val & INTR_HC_SEQ_CANCEL) {
> +		dev_dbg(&hci->master.dev,
> +			"Host Controller Cancelled Transaction Sequence\n");
> +		val &= ~INTR_HC_SEQ_CANCEL;
>  	}
>  	if (val & INTR_HC_INTERNAL_ERR) {
>  		dev_err(&hci->master.dev, "Host Controller Internal Error\n");
> --
> 2.47.2
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Wed Mar 12 09:26:37 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 12 Mar 2025 12:26:37 -0400
Subject: [PATCH v2 2/4] i3c: mipi-i3c-hci: Fix handling status of
 i3c_hci_irq_handler()
In-Reply-To: <20250312111049.197855-2-jarkko.nikula@linux.intel.com>
References: <20250312111049.197855-1-jarkko.nikula@linux.intel.com>
 <20250312111049.197855-2-jarkko.nikula@linux.intel.com>
Message-ID: <Z9G1vTx5oeIA2uZF@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 01:10:47PM +0200, Jarkko Nikula wrote:
> Return IRQ_HANDLED from the i3c_hci_irq_handler() only if some
> INTR_STATUS bit was set or if DMA/PIO handler handled it.
>
> Currently it returns IRQ_HANDLED in case INTR_STATUS is zero and IO
> handler returns false. Which could be the case if interrupt comes from
> other device or is spurious.
>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
> ---
>  drivers/i3c/master/mipi-i3c-hci/core.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index e139d7e4d252..e5593b6e897e 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -594,6 +594,7 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
>
>  	if (val) {
>  		reg_write(INTR_STATUS, val);

I suggest move 'reg_write(INTR_STATUS, val);' out of if block later.

Frank

> +		result = IRQ_HANDLED;
>  	}
>
>  	if (val & INTR_HC_RESET_CANCEL) {
> @@ -605,12 +606,11 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id)
>  		val &= ~INTR_HC_INTERNAL_ERR;
>  	}
>
> -	hci->io->irq_handler(hci);
> +	if (hci->io->irq_handler(hci))
> +		result = IRQ_HANDLED;
>
>  	if (val)
>  		dev_err(&hci->master.dev, "unexpected INTR_STATUS %#x\n", val);
> -	else
> -		result = IRQ_HANDLED;
>
>  	return result;
>  }
> --
> 2.47.2
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Wed Mar 12 11:29:10 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 12 Mar 2025 14:29:10 -0400
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
Message-ID: <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>

On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh wrote:
> As part of I3C driver probing sequence for particular device instance,
> While adding to queue it is trying to access ibi variable of dev which is
> not yet initialized causing "Unable to handle kernel read from unreadable
> memory" resulting in kernel panic.
>
> Below is the sequence where this issue happened.
> 1. During boot up sequence IBI is received at host  from the slave device
>    before requesting for IBI, Usually will request IBI by calling
>    i3c_device_request_ibi() during probe of slave driver.
> 2. Since master code trying to access IBI Variable for the particular
>    device instance before actually it initialized by slave driver,
>    due to this randomly accessing the address and causing kernel panic.
> 3. i3c_device_request_ibi() function invoked by the slave driver where
>    dev->ibi = ibi; assigned as part of function call
>    i3c_dev_request_ibi_locked().
> 4. But when IBI request sent by slave device, master code  trying to access
>    this variable before its initialized due to this race condition
>    situation kernel panic happened.
>
> Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master driver")
> Cc: stable at vger.kernel.org
> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> ---
> Changes since v3:
>   - Description  updated typo "Fixes:"
>
>  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index d6057d8c7dec..98c4d2e5cd8d 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
>  	switch (ibitype) {
>  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
>  		if (dev) {
> -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> -			master->ibi.tbq_slot = NULL;
> +			data = i3c_dev_get_master_data(dev);
> +			if (master->ibi.slots[data->ibi]) {
> +				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> +				master->ibi.tbq_slot = NULL;
> +			}

You still not reply previous discussion:

https://lore.kernel.org/linux-i3c/Z8sOKZSjHeeP2mY5 at lizhi-Precision-Tower-5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417

This is not issue only at svc driver, which should be common problem for
other master controller drivers

Frank

>  		}
>  		svc_i3c_master_emit_stop(master);
>  		break;
> --
> 2.46.1
>


From Frank.li at nxp.com  Thu Mar 13 09:02:44 2025
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 13 Mar 2025 12:02:44 -0400
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <VI1PR04MB10049C80F0A1990551F97E25C8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049C80F0A1990551F97E25C8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <Z9MBpEvOqqsVkCwt@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 05:03:54AM +0000, Manjunatha Venkatesh wrote:
>
>
> > -----Original Message-----
> > From: Frank Li <frank.li at nxp.com>
> > Sent: Friday, March 7, 2025 8:48 PM
> > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> >
> > On Fri, Mar 07, 2025 at 12:34:53PM +0000, Manjunatha Venkatesh wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Frank Li <frank.li at nxp.com>
> > > > Sent: Thursday, March 6, 2025 9:01 PM
> > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > > fixed
> > > >
> > > > On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh
> > wrote:
> > > > > Hi Frank,
> > > > >
> > > > > Please find my inline comments.
> > > > >
> > > > > Regards,
> > > > > Manju
> > > >
> > > > Avoid top post for linux kernel mail list.
> > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Frank Li <frank.li at nxp.com>
> > > > > > Sent: Friday, February 28, 2025 9:19 PM
> > > > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org;
> > > > > > linux- kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > > > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > > > > fixed
> > > > > >
> > > > > > Subject should be "Fix read from unreadable memory at
> > > > > > svc_i3c_master_ibi_work()"
> > > > > > Or like below pattern:
> > > > > > 	Do ... to fix ...
> > > > > >
> > > > > [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > > > > > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh
> > > > wrote:
> > > > > > > I3C Master driver svc-i3c-master
> > > > > >
> > > > > > Needn't this line.
> > > > > >
> > > > > [Manjunatha Venkatesh] Removed this line and submitted the new
> > > > > patch
> > > > > > >
> > > > > > > As part of I3C driver probing sequence for particular device
> > > > > > > instance, While adding to queue it is trying to access ibi
> > > > > > > variable of dev which is not yet initialized causing "Unable
> > > > > > > to handle kernel read from unreadable memory" resulting in kernel
> > panic.
> > > > > >
> > > > > > Can you provide more detail information why/how this happen?
> > > > > > which varible read cause this problem?
> > > > > >
> > > > > [Manjunatha Venkatesh] : Below is the sequence where this issue
> > > > happened.
> > > > > 1. During boot up sequence IBI is received at host  from the slave
> > > > > device
> > > > before requesting for IBI, Usually will request IBI by calling
> > > > i3c_device_request_ibi() during probe of slave driver.
> > > > > 2. Since master code trying to access IBI Variable for the
> > > > > particular device
> > > > instance before actually it initialized by slave driver, due to this
> > > > randomly accessing the address and causing kernel panic.
> > > > > 3. i3c_device_request_ibi() function invoked by the slave driver
> > > > >where dev- ibi = ibi; assigned as part of function call
> > i3c_dev_request_ibi_locked().
> > > > > 4. But when IBI request sent by slave device, master code  trying
> > > > >to access
> > > > this variable before its initialized due to this race condition
> > > > situation kernel panic happened.
> > > >
> > > > Write above reproduce steps to commit message.
> > > >
> > > [Manjunatha Venkatesh] : Next commit will update this description.
> > > > I think it is common problem for i3c framework.
> > > >
> > > > You'd better change i3c_master_queue_ibi()
> > > >
> > > > void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct
> > > > i3c_ibi_slot *slot) {
> > > > 	if (!slot)
> > > > 		return;
> > > >
> > > >         atomic_inc(&dev->ibi->pending_ibis);
> > > >         queue_work(dev->ibi->wq, &slot->work); }
> > > >
> > > [Manjunatha Venkatesh] : Actual issue we have faced with respect to 'dev-
> > >ibi' variable.
> >
> > How about
> > if (!dev->ibi || !slot) {
> > 	dev_warning("...");
> > 	return;
> > }
> >
> [Manjunatha Venkatesh] : dev->ibi is not initialized to null, might be some random value be there.
> If it initialized to null at the right place then this check can be added.

This is abnormal. Where do you find it is not initalized to null.

i3c_master_alloc_i3c_dev(struct i3c_master_controller *master,
                         const struct i3c_device_info *info)
{
        struct i3c_dev_desc *dev;

        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	      ^^^^^^^
		whole i3c_dev_desc is zero by default.
}

Frank

>
> > Frank
> >
> > > Pointer variable 'slot' is with respect IBI received from slave device context
> > and 'dev->ibi' is with respect to initialization of slave driver these 2 are
> > asynchronous events.
> > > dev->ibi = ibi; is initialized at i3c_dev_request_ibi_locked(), this is invoked as
> > part of slave driver IBI init sequence, this is what we want to check before
> > processing the IBI request from the Slave device.
> > > master->ibi.slots[i] this is where all device ibi instance list are saved, so here
> > our slave driver init IBI stored with respect dev->ibi index.
> > > So adding 'if (!slot)' will not help to resolve this issue.
> >
> >
> > Please wrap around at 80 char to read easily.
> >
> >
> > >
> > > > Frank
> > > > >
> > > > >
> > > > > > Need fix tags and cc stable.
> > > > > >
> > > > > [Manjunatha Venkatesh] : fix tags and cc stable updated in the
> > > > > commit
> > > > message.
> > > > >
> > > [Manjunatha Venkatesh] : Last commit message missed to update fix tags
> > and cc stable.
> > > Will update that information as part of next commit message.
> > > > > > Frank
> > > > > > >
> > > > > > > Signed-off-by: Manjunatha Venkatesh
> > > > <manjunatha.venkatesh at nxp.com>
> > > > > > > ---
> > > > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > > > @@ -534,8 +534,11 @@ static void
> > > > > > > svc_i3c_master_ibi_work(struct
> > > > > > work_struct *work)
> > > > > > >  	switch (ibitype) {
> > > > > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > > > >  		if (dev) {
> > > > > > > -			i3c_master_queue_ibi(dev, master-
> > >ibi.tbq_slot);
> > > > > > > -			master->ibi.tbq_slot = NULL;
> > > > > > > +			data = i3c_dev_get_master_data(dev);
> > > > > > > +			if (master->ibi.slots[data->ibi]) {
> > > > > > > +				i3c_master_queue_ibi(dev, master-
> > > > > > >ibi.tbq_slot);
> > > > > > > +				master->ibi.tbq_slot = NULL;
> > > > > > > +			}
> > > > > > >  		}
> > > > > > >  		svc_i3c_master_emit_stop(master);
> > > > > > >  		break;
> > > > > > > --
> > > > > > > 2.46.1
> > > > > > >
> > > > > > >
> > > > > > > --
> > > > > > > linux-i3c mailing list
> > > > > > > linux-i3c at lists.infradead.org
> > > > > > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From stanley.chuys at gmail.com  Sun Mar 16 22:19:48 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Mon, 17 Mar 2025 13:19:48 +0800
Subject: [PATCH v1 0/3] Some fixes for Silvaco I3C controller driver
Message-ID: <20250317051951.3065011-1-yschu@nuvoton.com>

This patchset adds some fixes for the Silvaco I3C controller driver.

Stanley Chu (3):
  i3c: master: svc: Fix missing the IBI rules
  i3c: master: svc: Use readsb helper for reading MDB
  i3c: master: svc: Fix missing STOP for master request

 drivers/i3c/master/svc-i3c-master.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

-- 
2.34.1



From stanley.chuys at gmail.com  Sun Mar 16 22:19:49 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Mon, 17 Mar 2025 13:19:49 +0800
Subject: [PATCH v1 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <20250317051951.3065011-1-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
Message-ID: <20250317051951.3065011-2-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The code does not add IBI rules for devices with controller capability.
However, some target devices, such as secondary controller, also have
the controller capability.
Modify the code to add rules for devices capable of sending IBI requests.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 1d1f351b9a85..a72ba5a7edd4 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
 
 	/* Create the IBIRULES register for both cases */
 	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
-		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
+		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
 			continue;
 
 		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
-- 
2.34.1



From stanley.chuys at gmail.com  Sun Mar 16 22:19:50 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Mon, 17 Mar 2025 13:19:50 +0800
Subject: [PATCH v1 2/3] i3c: master: svc: Use readsb helper for reading MDB
In-Reply-To: <20250317051951.3065011-1-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
Message-ID: <20250317051951.3065011-3-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The target can send the MDB byte followed by additional data bytes.
The readl on MRDATAB reads one actual byte, but the readsl advances
the destination pointer by 4 bytes. This causes the subsequent payload
to be copied to wrong position in the destination buffer.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index a72ba5a7edd4..57b9dec6b5a8 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -425,7 +425,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
 	       slot->len < SVC_I3C_FIFO_SIZE) {
 		mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
 		count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl);
-		readsl(master->regs + SVC_I3C_MRDATAB, buf, count);
+		readsb(master->regs + SVC_I3C_MRDATAB, buf, count);
 		slot->len += count;
 		buf += count;
 	}
-- 
2.34.1



From stanley.chuys at gmail.com  Sun Mar 16 22:19:51 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Mon, 17 Mar 2025 13:19:51 +0800
Subject: [PATCH v1 3/3] i3c: master: svc: Fix missing STOP for master request
In-Reply-To: <20250317051951.3065011-1-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
Message-ID: <20250317051951.3065011-4-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The controller driver nacked the master request but didn't emit a
STOP to end the transaction. The driver shall refuse the unsupported
requests and return the controller state to IDLE by emitting a STOP.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 57b9dec6b5a8..e0cd3ce28b7f 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -592,6 +592,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 			queue_work(master->base.wq, &master->hj_work);
 		break;
 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+		svc_i3c_master_emit_stop(master);
 	default:
 		break;
 	}
-- 
2.34.1



From manjunatha.venkatesh at nxp.com  Wed Mar 12 06:32:38 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 12 Mar 2025 19:02:38 +0530
Subject: [PATCH v3] svc-i3c-master: Fix read from unreadable memory at svc_i3c_master_ibi_work
Message-ID: <20250312133238.2313772-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Below is the sequence where this issue happened.
1. During boot up sequence IBI is received at host  from the slave device
   before requesting for IBI, Usually will request IBI by calling
   i3c_device_request_ibi() during probe of slave driver.
2. Since master code trying to access IBI Variable for the particular
   device instance before actually it initialized by slave driver,
   due to this randomly accessing the address and causing kernel panic.
3. i3c_device_request_ibi() function invoked by the slave driver where
   dev->ibi = ibi; assigned as part of function call
   i3c_dev_request_ibi_locked().
4. But when IBI request sent by slave device, master code  trying to access
   this variable before its initialized due to this race condition
   situation kernel panic happened.

fixes: dd3c52846d595 (i3c: master: svc: Add Silvaco I3C master driver)
Cc: stable at vger.kernel.org
Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v2:
  - Description  updated as per the review feedback

 drivers/i3c/master/svc-i3c-master.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..98c4d2e5cd8d 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
 		if (dev) {
-			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
-			master->ibi.tbq_slot = NULL;
+			data = i3c_dev_get_master_data(dev);
+			if (master->ibi.slots[data->ibi]) {
+				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
+				master->ibi.tbq_slot = NULL;
+			}
 		}
 		svc_i3c_master_emit_stop(master);
 		break;
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Wed Mar 12 06:52:05 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 12 Mar 2025 13:52:05 +0000
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB10049251835D1D5C953CBE6CA8FD02@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Friday, March 7, 2025 8:48 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> 
> On Fri, Mar 07, 2025 at 12:34:53PM +0000, Manjunatha Venkatesh wrote:
> >
> >
> > > -----Original Message-----
> > > From: Frank Li <frank.li at nxp.com>
> > > Sent: Thursday, March 6, 2025 9:01 PM
> > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > fixed
> > >
> > > On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh
> wrote:
> > > > Hi Frank,
> > > >
> > > > Please find my inline comments.
> > > >
> > > > Regards,
> > > > Manju
> > >
> > > Avoid top post for linux kernel mail list.
> > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Frank Li <frank.li at nxp.com>
> > > > > Sent: Friday, February 28, 2025 9:19 PM
> > > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org;
> > > > > linux- kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > > > fixed
> > > > >
> > > > > Subject should be "Fix read from unreadable memory at
> > > > > svc_i3c_master_ibi_work()"
> > > > > Or like below pattern:
> > > > > 	Do ... to fix ...
> > > > >
> > > > [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > > > > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh
> > > wrote:
> > > > > > I3C Master driver svc-i3c-master
> > > > >
> > > > > Needn't this line.
> > > > >
> > > > [Manjunatha Venkatesh] Removed this line and submitted the new
> > > > patch
> > > > > >
> > > > > > As part of I3C driver probing sequence for particular device
> > > > > > instance, While adding to queue it is trying to access ibi
> > > > > > variable of dev which is not yet initialized causing "Unable
> > > > > > to handle kernel read from unreadable memory" resulting in kernel
> panic.
> > > > >
> > > > > Can you provide more detail information why/how this happen?
> > > > > which varible read cause this problem?
> > > > >
> > > > [Manjunatha Venkatesh] : Below is the sequence where this issue
> > > happened.
> > > > 1. During boot up sequence IBI is received at host  from the slave
> > > > device
> > > before requesting for IBI, Usually will request IBI by calling
> > > i3c_device_request_ibi() during probe of slave driver.
> > > > 2. Since master code trying to access IBI Variable for the
> > > > particular device
> > > instance before actually it initialized by slave driver, due to this
> > > randomly accessing the address and causing kernel panic.
> > > > 3. i3c_device_request_ibi() function invoked by the slave driver
> > > >where dev- ibi = ibi; assigned as part of function call
> i3c_dev_request_ibi_locked().
> > > > 4. But when IBI request sent by slave device, master code  trying
> > > >to access
> > > this variable before its initialized due to this race condition
> > > situation kernel panic happened.
> > >
> > > Write above reproduce steps to commit message.
> > >
> > [Manjunatha Venkatesh] : Next commit will update this description.
> > > I think it is common problem for i3c framework.
> > >
> > > You'd better change i3c_master_queue_ibi()
> > >
> > > void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct
> > > i3c_ibi_slot *slot) {
> > > 	if (!slot)
> > > 		return;
> > >
> > >         atomic_inc(&dev->ibi->pending_ibis);
> > >         queue_work(dev->ibi->wq, &slot->work); }
> > >
> > [Manjunatha Venkatesh] : Actual issue we have faced with respect to 'dev-
> >ibi' variable.
> 
> How about
> if (!dev->ibi || !slot) {
> 	dev_warning("...");
> 	return;
> }
> 
> Frank
> 
> > Pointer variable 'slot' is with respect IBI received from slave device context
> and 'dev->ibi' is with respect to initialization of slave driver these 2 are
> asynchronous events.
> > dev->ibi = ibi; is initialized at i3c_dev_request_ibi_locked(), this is invoked as
> part of slave driver IBI init sequence, this is what we want to check before
> processing the IBI request from the Slave device.
> > master->ibi.slots[i] this is where all device ibi instance list are saved, so here
> our slave driver init IBI stored with respect dev->ibi index.
> > So adding 'if (!slot)' will not help to resolve this issue.
> 
> 
> Please wrap around at 80 char to read easily.
> 
[Manjunatha Venkatesh] : I have corrected in the submitted patch.
Please ignore patch version 3 there were some typo in the description, submitted patch version4.
Consider Patch version4 for review. 
> 
> >
> > > Frank
> > > >
> > > >
> > > > > Need fix tags and cc stable.
> > > > >
> > > > [Manjunatha Venkatesh] : fix tags and cc stable updated in the
> > > > commit
> > > message.
> > > >
> > [Manjunatha Venkatesh] : Last commit message missed to update fix tags
> and cc stable.
> > Will update that information as part of next commit message.
> > > > > Frank
> > > > > >
> > > > > > Signed-off-by: Manjunatha Venkatesh
> > > <manjunatha.venkatesh at nxp.com>
> > > > > > ---
> > > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > > @@ -534,8 +534,11 @@ static void
> > > > > > svc_i3c_master_ibi_work(struct
> > > > > work_struct *work)
> > > > > >  	switch (ibitype) {
> > > > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > > >  		if (dev) {
> > > > > > -			i3c_master_queue_ibi(dev, master-
> >ibi.tbq_slot);
> > > > > > -			master->ibi.tbq_slot = NULL;
> > > > > > +			data = i3c_dev_get_master_data(dev);
> > > > > > +			if (master->ibi.slots[data->ibi]) {
> > > > > > +				i3c_master_queue_ibi(dev, master-
> > > > > >ibi.tbq_slot);
> > > > > > +				master->ibi.tbq_slot = NULL;
> > > > > > +			}
> > > > > >  		}
> > > > > >  		svc_i3c_master_emit_stop(master);
> > > > > >  		break;
> > > > > > --
> > > > > > 2.46.1
> > > > > >
> > > > > >
> > > > > > --
> > > > > > linux-i3c mailing list
> > > > > > linux-i3c at lists.infradead.org
> > > > > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From manjunatha.venkatesh at nxp.com  Wed Mar 12 06:53:56 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 12 Mar 2025 19:23:56 +0530
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at svc_i3c_master_ibi_work()
Message-ID: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Below is the sequence where this issue happened.
1. During boot up sequence IBI is received at host  from the slave device
   before requesting for IBI, Usually will request IBI by calling
   i3c_device_request_ibi() during probe of slave driver.
2. Since master code trying to access IBI Variable for the particular
   device instance before actually it initialized by slave driver,
   due to this randomly accessing the address and causing kernel panic.
3. i3c_device_request_ibi() function invoked by the slave driver where
   dev->ibi = ibi; assigned as part of function call
   i3c_dev_request_ibi_locked().
4. But when IBI request sent by slave device, master code  trying to access
   this variable before its initialized due to this race condition
   situation kernel panic happened.

Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master driver")
Cc: stable at vger.kernel.org
Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v3:
  - Description  updated typo "Fixes:"

 drivers/i3c/master/svc-i3c-master.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d6057d8c7dec..98c4d2e5cd8d 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_IBI:
 		if (dev) {
-			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
-			master->ibi.tbq_slot = NULL;
+			data = i3c_dev_get_master_data(dev);
+			if (master->ibi.slots[data->ibi]) {
+				i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
+				master->ibi.tbq_slot = NULL;
+			}
 		}
 		svc_i3c_master_emit_stop(master);
 		break;
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Wed Mar 12 22:03:54 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu, 13 Mar 2025 05:03:54 +0000
Subject: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
In-Reply-To: <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>
References: <20250224031754.1001101-1-manjunatha.venkatesh@nxp.com>
 <Z8Ha+T9Vc8Bhz25A@lizhi-Precision-Tower-5810>
 <VI1PR04MB100498A9CFBB48DF250CC73B98FCA2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8m/zE9JvyiNq1HG@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049E260B10FD83E57B2DCB78FD52@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z8sOKZSjHeeP2mY5@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB10049C80F0A1990551F97E25C8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Friday, March 7, 2025 8:48 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue fixed
> 
> On Fri, Mar 07, 2025 at 12:34:53PM +0000, Manjunatha Venkatesh wrote:
> >
> >
> > > -----Original Message-----
> > > From: Frank Li <frank.li at nxp.com>
> > > Sent: Thursday, March 6, 2025 9:01 PM
> > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > fixed
> > >
> > > On Thu, Mar 06, 2025 at 08:31:29AM +0000, Manjunatha Venkatesh
> wrote:
> > > > Hi Frank,
> > > >
> > > > Please find my inline comments.
> > > >
> > > > Regards,
> > > > Manju
> > >
> > > Avoid top post for linux kernel mail list.
> > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Frank Li <frank.li at nxp.com>
> > > > > Sent: Friday, February 28, 2025 9:19 PM
> > > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org;
> > > > > linux- kernel at vger.kernel.org; rvmanjumce at gmail.com
> > > > > Subject: Re: [PATCH] driver: svc-i3c-master: Kernel panic issue
> > > > > fixed
> > > > >
> > > > > Subject should be "Fix read from unreadable memory at
> > > > > svc_i3c_master_ibi_work()"
> > > > > Or like below pattern:
> > > > > 	Do ... to fix ...
> > > > >
> > > > [Manjunatha Venkatesh] Tittle updated as per the review comment.
> > > > > On Mon, Feb 24, 2025 at 08:47:54AM +0530, Manjunatha Venkatesh
> > > wrote:
> > > > > > I3C Master driver svc-i3c-master
> > > > >
> > > > > Needn't this line.
> > > > >
> > > > [Manjunatha Venkatesh] Removed this line and submitted the new
> > > > patch
> > > > > >
> > > > > > As part of I3C driver probing sequence for particular device
> > > > > > instance, While adding to queue it is trying to access ibi
> > > > > > variable of dev which is not yet initialized causing "Unable
> > > > > > to handle kernel read from unreadable memory" resulting in kernel
> panic.
> > > > >
> > > > > Can you provide more detail information why/how this happen?
> > > > > which varible read cause this problem?
> > > > >
> > > > [Manjunatha Venkatesh] : Below is the sequence where this issue
> > > happened.
> > > > 1. During boot up sequence IBI is received at host  from the slave
> > > > device
> > > before requesting for IBI, Usually will request IBI by calling
> > > i3c_device_request_ibi() during probe of slave driver.
> > > > 2. Since master code trying to access IBI Variable for the
> > > > particular device
> > > instance before actually it initialized by slave driver, due to this
> > > randomly accessing the address and causing kernel panic.
> > > > 3. i3c_device_request_ibi() function invoked by the slave driver
> > > >where dev- ibi = ibi; assigned as part of function call
> i3c_dev_request_ibi_locked().
> > > > 4. But when IBI request sent by slave device, master code  trying
> > > >to access
> > > this variable before its initialized due to this race condition
> > > situation kernel panic happened.
> > >
> > > Write above reproduce steps to commit message.
> > >
> > [Manjunatha Venkatesh] : Next commit will update this description.
> > > I think it is common problem for i3c framework.
> > >
> > > You'd better change i3c_master_queue_ibi()
> > >
> > > void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct
> > > i3c_ibi_slot *slot) {
> > > 	if (!slot)
> > > 		return;
> > >
> > >         atomic_inc(&dev->ibi->pending_ibis);
> > >         queue_work(dev->ibi->wq, &slot->work); }
> > >
> > [Manjunatha Venkatesh] : Actual issue we have faced with respect to 'dev-
> >ibi' variable.
> 
> How about
> if (!dev->ibi || !slot) {
> 	dev_warning("...");
> 	return;
> }
> 
[Manjunatha Venkatesh] : dev->ibi is not initialized to null, might be some random value be there.
If it initialized to null at the right place then this check can be added.

> Frank
> 
> > Pointer variable 'slot' is with respect IBI received from slave device context
> and 'dev->ibi' is with respect to initialization of slave driver these 2 are
> asynchronous events.
> > dev->ibi = ibi; is initialized at i3c_dev_request_ibi_locked(), this is invoked as
> part of slave driver IBI init sequence, this is what we want to check before
> processing the IBI request from the Slave device.
> > master->ibi.slots[i] this is where all device ibi instance list are saved, so here
> our slave driver init IBI stored with respect dev->ibi index.
> > So adding 'if (!slot)' will not help to resolve this issue.
> 
> 
> Please wrap around at 80 char to read easily.
> 
> 
> >
> > > Frank
> > > >
> > > >
> > > > > Need fix tags and cc stable.
> > > > >
> > > > [Manjunatha Venkatesh] : fix tags and cc stable updated in the
> > > > commit
> > > message.
> > > >
> > [Manjunatha Venkatesh] : Last commit message missed to update fix tags
> and cc stable.
> > Will update that information as part of next commit message.
> > > > > Frank
> > > > > >
> > > > > > Signed-off-by: Manjunatha Venkatesh
> > > <manjunatha.venkatesh at nxp.com>
> > > > > > ---
> > > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > > @@ -534,8 +534,11 @@ static void
> > > > > > svc_i3c_master_ibi_work(struct
> > > > > work_struct *work)
> > > > > >  	switch (ibitype) {
> > > > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > > >  		if (dev) {
> > > > > > -			i3c_master_queue_ibi(dev, master-
> >ibi.tbq_slot);
> > > > > > -			master->ibi.tbq_slot = NULL;
> > > > > > +			data = i3c_dev_get_master_data(dev);
> > > > > > +			if (master->ibi.slots[data->ibi]) {
> > > > > > +				i3c_master_queue_ibi(dev, master-
> > > > > >ibi.tbq_slot);
> > > > > > +				master->ibi.tbq_slot = NULL;
> > > > > > +			}
> > > > > >  		}
> > > > > >  		svc_i3c_master_emit_stop(master);
> > > > > >  		break;
> > > > > > --
> > > > > > 2.46.1
> > > > > >
> > > > > >
> > > > > > --
> > > > > > linux-i3c mailing list
> > > > > > linux-i3c at lists.infradead.org
> > > > > > http://lists.infradead.org/mailman/listinfo/linux-i3c


From manjunatha.venkatesh at nxp.com  Wed Mar 12 22:15:42 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Thu, 13 Mar 2025 05:15:42 +0000
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
 <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Wednesday, March 12, 2025 11:59 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
> svc_i3c_master_ibi_work()
> 
> On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh wrote:
> > As part of I3C driver probing sequence for particular device instance,
> > While adding to queue it is trying to access ibi variable of dev which
> > is not yet initialized causing "Unable to handle kernel read from
> > unreadable memory" resulting in kernel panic.
> >
> > Below is the sequence where this issue happened.
> > 1. During boot up sequence IBI is received at host  from the slave device
> >    before requesting for IBI, Usually will request IBI by calling
> >    i3c_device_request_ibi() during probe of slave driver.
> > 2. Since master code trying to access IBI Variable for the particular
> >    device instance before actually it initialized by slave driver,
> >    due to this randomly accessing the address and causing kernel panic.
> > 3. i3c_device_request_ibi() function invoked by the slave driver where
> >    dev->ibi = ibi; assigned as part of function call
> >    i3c_dev_request_ibi_locked().
> > 4. But when IBI request sent by slave device, master code  trying to access
> >    this variable before its initialized due to this race condition
> >    situation kernel panic happened.
> >
> > Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master
> > driver")
> > Cc: stable at vger.kernel.org
> > Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > ---
> > Changes since v3:
> >   - Description  updated typo "Fixes:"
> >
> >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > b/drivers/i3c/master/svc-i3c-master.c
> > index d6057d8c7dec..98c4d2e5cd8d 100644
> > --- a/drivers/i3c/master/svc-i3c-master.c
> > +++ b/drivers/i3c/master/svc-i3c-master.c
> > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> work_struct *work)
> >  	switch (ibitype) {
> >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> >  		if (dev) {
> > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > -			master->ibi.tbq_slot = NULL;
> > +			data = i3c_dev_get_master_data(dev);
> > +			if (master->ibi.slots[data->ibi]) {
> > +				i3c_master_queue_ibi(dev, master-
> >ibi.tbq_slot);
> > +				master->ibi.tbq_slot = NULL;
> > +			}
> 
> You still not reply previous discussion:
> 
> https://lore.kernel.org/linux-i3c/Z8sOKZSjHeeP2mY5 at lizhi-Precision-Tower-
> 5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417
> 
[Manjunatha Venkatesh] : In the last mail answered to this question.

> This is not issue only at svc driver, which should be common problem for
> other master controller drivers
> 
[Manjunatha Venkatesh] :Yes, you are right.
One of my project I3C interface is required, where we have used IMX board as reference platform.
As part of boot sequence we come across this issue and tried to fix that particular controller driver.

What is your conclusion on this? Is it not ok to take patch for SVC alone?
 
> Frank
> 
> >  		}
> >  		svc_i3c_master_emit_stop(master);
> >  		break;
> > --
> > 2.46.1
> >


From Frank.li at nxp.com  Mon Mar 17 06:26:49 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 17 Mar 2025 09:26:49 -0400
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
 <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810>

On Thu, Mar 13, 2025 at 05:15:42AM +0000, Manjunatha Venkatesh wrote:
>
>
> > -----Original Message-----
> > From: Frank Li <frank.li at nxp.com>
> > Sent: Wednesday, March 12, 2025 11:59 PM
> > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
> > svc_i3c_master_ibi_work()
> >
> > On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh wrote:
> > > As part of I3C driver probing sequence for particular device instance,
> > > While adding to queue it is trying to access ibi variable of dev which
> > > is not yet initialized causing "Unable to handle kernel read from
> > > unreadable memory" resulting in kernel panic.
> > >
> > > Below is the sequence where this issue happened.
> > > 1. During boot up sequence IBI is received at host  from the slave device
> > >    before requesting for IBI, Usually will request IBI by calling
> > >    i3c_device_request_ibi() during probe of slave driver.
> > > 2. Since master code trying to access IBI Variable for the particular
> > >    device instance before actually it initialized by slave driver,
> > >    due to this randomly accessing the address and causing kernel panic.
> > > 3. i3c_device_request_ibi() function invoked by the slave driver where
> > >    dev->ibi = ibi; assigned as part of function call
> > >    i3c_dev_request_ibi_locked().
> > > 4. But when IBI request sent by slave device, master code  trying to access
> > >    this variable before its initialized due to this race condition
> > >    situation kernel panic happened.
> > >
> > > Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master
> > > driver")
> > > Cc: stable at vger.kernel.org
> > > Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > ---
> > > Changes since v3:
> > >   - Description  updated typo "Fixes:"
> > >
> > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > b/drivers/i3c/master/svc-i3c-master.c
> > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > work_struct *work)
> > >  	switch (ibitype) {
> > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > >  		if (dev) {
> > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > -			master->ibi.tbq_slot = NULL;
> > > +			data = i3c_dev_get_master_data(dev);
> > > +			if (master->ibi.slots[data->ibi]) {
> > > +				i3c_master_queue_ibi(dev, master-
> > >ibi.tbq_slot);
> > > +				master->ibi.tbq_slot = NULL;
> > > +			}
> >
> > You still not reply previous discussion:
> >
> > https://lore.kernel.org/linux-i3c/Z8sOKZSjHeeP2mY5 at lizhi-Precision-Tower-
> > 5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417
> >
> [Manjunatha Venkatesh] : In the last mail answered to this question.
>
> > This is not issue only at svc driver, which should be common problem for
> > other master controller drivers
> >
> [Manjunatha Venkatesh] :Yes, you are right.
> One of my project I3C interface is required, where we have used IMX board as reference platform.
> As part of boot sequence we come across this issue and tried to fix that particular controller driver.
>
> What is your conclusion on this? Is it not ok to take patch for SVC alone?

I perfer fix at common framwork to avoid every driver copy the similar
logic code.

Frank

>
> > Frank
> >
> > >  		}
> > >  		svc_i3c_master_emit_stop(master);
> > >  		break;
> > > --
> > > 2.46.1
> > >
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From Frank.li at nxp.com  Mon Mar 17 06:36:20 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 17 Mar 2025 09:36:20 -0400
Subject: [PATCH v1 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <20250317051951.3065011-2-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-2-yschu@nuvoton.com>
Message-ID: <Z9glVBnpdwXuLwD7@lizhi-Precision-Tower-5810>

On Mon, Mar 17, 2025 at 01:19:49PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The code does not add IBI rules for devices with controller capability.
> However, some target devices, such as secondary controller, also have
                ^^ dual rule devices

OR

However, the second controller have the controller capablity and work at
target devices mode when the device probe. So add IBI rules for such
devices.


> the controller capability.
> Modify the code to add rules for devices capable of sending IBI requests.
>
> Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>


Reviewed-by: Frank Li <Frank.Li at nxp.com>


> ---
>  drivers/i3c/master/svc-i3c-master.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 1d1f351b9a85..a72ba5a7edd4 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
>
>  	/* Create the IBIRULES register for both cases */
>  	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
> -		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
> +		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
>  			continue;
>
>  		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
> --
> 2.34.1
>


From Frank.li at nxp.com  Mon Mar 17 06:38:23 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 17 Mar 2025 09:38:23 -0400
Subject: [PATCH v1 2/3] i3c: master: svc: Use readsb helper for reading
 MDB
In-Reply-To: <20250317051951.3065011-3-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-3-yschu@nuvoton.com>
Message-ID: <Z9glzwsAuwKJSlsn@lizhi-Precision-Tower-5810>

On Mon, Mar 17, 2025 at 01:19:50PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The target can send the MDB byte followed by additional data bytes.
> The readl on MRDATAB reads one actual byte, but the readsl advances
> the destination pointer by 4 bytes. This causes the subsequent payload
> to be copied to wrong position in the destination buffer.
>
> Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")


Cc stable?

> Signed-off-by: Stanley Chu <yschu at nuvoton.com>


strange, why this issue exists for so long time. Maybe we just use first
byte of IBI data.

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/i3c/master/svc-i3c-master.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index a72ba5a7edd4..57b9dec6b5a8 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -425,7 +425,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
>  	       slot->len < SVC_I3C_FIFO_SIZE) {
>  		mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
>  		count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl);
> -		readsl(master->regs + SVC_I3C_MRDATAB, buf, count);
> +		readsb(master->regs + SVC_I3C_MRDATAB, buf, count);
>  		slot->len += count;
>  		buf += count;
>  	}
> --
> 2.34.1
>


From Frank.li at nxp.com  Mon Mar 17 06:40:17 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 17 Mar 2025 09:40:17 -0400
Subject: [PATCH v1 3/3] i3c: master: svc: Fix missing STOP for master
 request
In-Reply-To: <20250317051951.3065011-4-yschu@nuvoton.com>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-4-yschu@nuvoton.com>
Message-ID: <Z9gmQef79VYvyIv9@lizhi-Precision-Tower-5810>

On Mon, Mar 17, 2025 at 01:19:51PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The controller driver nacked the master request but didn't emit a
> STOP to end the transaction. The driver shall refuse the unsupported
> requests and return the controller state to IDLE by emitting a STOP.
>
> Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")

Current framework code don't support master request. So it is not fixes.
needn't fixes tag.

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> ---
>  drivers/i3c/master/svc-i3c-master.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 57b9dec6b5a8..e0cd3ce28b7f 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -592,6 +592,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
>  			queue_work(master->base.wq, &master->hj_work);
>  		break;
>  	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
> +		svc_i3c_master_emit_stop(master);
>  	default:
>  		break;
>  	}
> --
> 2.34.1
>


From alexandre.belloni at bootlin.com  Mon Mar 17 10:39:22 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 17 Mar 2025 18:39:22 +0100
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <VI1PR04MB1004979B7D38486FD1E1CC8508FDF2@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
 <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810>
 <VI1PR04MB1004979B7D38486FD1E1CC8508FDF2@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <2025031717392264f19f1a@mail.local>

On 17/03/2025 15:46:52+0000, Manjunatha Venkatesh wrote:
> 
> 
> > -----Original Message-----
> > From: Frank Li <frank.li at nxp.com>
> > Sent: Monday, March 17, 2025 6:57 PM
> > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
> > svc_i3c_master_ibi_work()
> > 
> > On Thu, Mar 13, 2025 at 05:15:42AM +0000, Manjunatha Venkatesh wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Frank Li <frank.li at nxp.com>
> > > > Sent: Wednesday, March 12, 2025 11:59 PM
> > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > > kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> > > > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
> > > > memory at
> > > > svc_i3c_master_ibi_work()
> > > >
> > > > On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh
> > wrote:
> > > > > As part of I3C driver probing sequence for particular device
> > > > > instance, While adding to queue it is trying to access ibi
> > > > > variable of dev which is not yet initialized causing "Unable to
> > > > > handle kernel read from unreadable memory" resulting in kernel panic.
> > > > >
> > > > > Below is the sequence where this issue happened.
> > > > > 1. During boot up sequence IBI is received at host  from the slave device
> > > > >    before requesting for IBI, Usually will request IBI by calling
> > > > >    i3c_device_request_ibi() during probe of slave driver.
> > > > > 2. Since master code trying to access IBI Variable for the particular
> > > > >    device instance before actually it initialized by slave driver,
> > > > >    due to this randomly accessing the address and causing kernel panic.
> > > > > 3. i3c_device_request_ibi() function invoked by the slave driver where
> > > > >    dev->ibi = ibi; assigned as part of function call
> > > > >    i3c_dev_request_ibi_locked().
> > > > > 4. But when IBI request sent by slave device, master code  trying to
> > access
> > > > >    this variable before its initialized due to this race condition
> > > > >    situation kernel panic happened.
> > > > >
> > > > > Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master
> > > > > driver")
> > > > > Cc: stable at vger.kernel.org
> > > > > Signed-off-by: Manjunatha Venkatesh
> > <manjunatha.venkatesh at nxp.com>
> > > > > ---
> > > > > Changes since v3:
> > > > >   - Description  updated typo "Fixes:"
> > > > >
> > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > > > work_struct *work)
> > > > >  	switch (ibitype) {
> > > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > >  		if (dev) {
> > > > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > > > -			master->ibi.tbq_slot = NULL;
> > > > > +			data = i3c_dev_get_master_data(dev);
> > > > > +			if (master->ibi.slots[data->ibi]) {
> > > > > +				i3c_master_queue_ibi(dev, master-
> > > > >ibi.tbq_slot);
> > > > > +				master->ibi.tbq_slot = NULL;
> > > > > +			}
> > > >
> > > > You still not reply previous discussion:
> > > >
> > > > https://lore.kernel.org/linux-i3c/Z8sOKZSjHeeP2mY5 at lizhi-Precision-T
> > > > ower-
> > > > 5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417
> > > >
> > > [Manjunatha Venkatesh] : In the last mail answered to this question.
> > >
> > > > This is not issue only at svc driver, which should be common problem
> > > > for other master controller drivers
> > > >
> > > [Manjunatha Venkatesh] :Yes, you are right.
> > > One of my project I3C interface is required, where we have used IMX board
> > as reference platform.
> > > As part of boot sequence we come across this issue and tried to fix that
> > particular controller driver.
> > >
> > > What is your conclusion on this? Is it not ok to take patch for SVC alone?
> > 
> > I perfer fix at common framwork to avoid every driver copy the similar logic
> > code.
> > 
> [Manjunatha Venkatesh] : As per your suggestion tried the below patch at common framework api i3c_master_queue_ibi()
>  and looks working fine, didn't see any crash issue.
> if (!dev->ibi || !slot) {
>              dev_warning("...");

Do we really need a warning, what would be the user action after seeing
it?
>              return;
> }
> Will commit this change in next patch submission.
> 
> > Frank
> > 
> > >
> > > > Frank
> > > >
> > > > >  		}
> > > > >  		svc_i3c_master_emit_stop(master);
> > > > >  		break;
> > > > > --
> > > > > 2.46.1
> > > > >
> > >
> > > --
> > > linux-i3c mailing list
> > > linux-i3c at lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-i3c

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Mon Mar 17 15:44:40 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 17 Mar 2025 23:44:40 +0100
Subject: [PATCH v1 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <Z9glVBnpdwXuLwD7@lizhi-Precision-Tower-5810>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-2-yschu@nuvoton.com>
 <Z9glVBnpdwXuLwD7@lizhi-Precision-Tower-5810>
Message-ID: <20250317224440840e4117@mail.local>

Hello Frank,

On 17/03/2025 09:36:20-0400, Frank Li wrote:
> On Mon, Mar 17, 2025 at 01:19:49PM +0800, Stanley Chu wrote:
> > From: Stanley Chu <yschu at nuvoton.com>
> >
> > The code does not add IBI rules for devices with controller capability.
> > However, some target devices, such as secondary controller, also have
>                 ^^ dual rule devices
> 
> OR
> 
> However, the second controller have the controller capablity and work at
> target devices mode when the device probe. So add IBI rules for such
> devices.
> 
> 
> > the controller capability.
> > Modify the code to add rules for devices capable of sending IBI requests.
> >
> > Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> > Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> 
> 
> Reviewed-by: Frank Li <Frank.Li at nxp.com>

Please avoid adding you reviewed-by tag when you request changes, else
patch work will show the patch as being applicable. This is fine to do
it occasionally but not for all the patches you review. You can simply
wait for the next version to come.

> 
> 
> > ---
> >  drivers/i3c/master/svc-i3c-master.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > index 1d1f351b9a85..a72ba5a7edd4 100644
> > --- a/drivers/i3c/master/svc-i3c-master.c
> > +++ b/drivers/i3c/master/svc-i3c-master.c
> > @@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
> >
> >  	/* Create the IBIRULES register for both cases */
> >  	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
> > -		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
> > +		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
> >  			continue;
> >
> >  		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
> > --
> > 2.34.1
> >

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Mon Mar 17 15:46:29 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 17 Mar 2025 23:46:29 +0100
Subject: [PATCH v1 1/1] i3c: master: svc: Fix i3c_master_get_free_addr
 return check
In-Reply-To: <20250310023304.2335792-1-yschu@nuvoton.com>
References: <20250310023304.2335792-1-yschu@nuvoton.com>
Message-ID: <174225158210.1593610.10018812780731849409.b4-ty@bootlin.com>

On Mon, 10 Mar 2025 10:33:04 +0800, Stanley Chu wrote:
> The return value of i3c_master_get_free_addr is assigned to a variable
> with wrong type, so it can't be negative. Use a signed integer for the
> return value. If the value is negative, break the process and propagate
> the error code.
> 
> This commit also fixes the uninitialized symbol 'dyn_addr', reported
> by Smatch static checker.
> 
> [...]

Applied, thanks!

[1/1] i3c: master: svc: Fix i3c_master_get_free_addr return check
      https://git.kernel.org/abelloni/c/d6cb667b8e15

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From stanley.chuys at gmail.com  Mon Mar 17 22:36:03 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Tue, 18 Mar 2025 13:36:03 +0800
Subject: [PATCH v2 0/3] Some fixes for Silvaco I3C controller driver
Message-ID: <20250318053606.3087121-1-yschu@nuvoton.com>

This patchset adds some fixes for the Silvaco I3C controller driver.

Stanley Chu (3):
  i3c: master: svc: Fix missing the IBI rules
  i3c: master: svc: Use readsb helper for reading MDB
  i3c: master: svc: Fix missing STOP for master request

 drivers/i3c/master/svc-i3c-master.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

-- 
2.34.1



From stanley.chuys at gmail.com  Mon Mar 17 22:36:04 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Tue, 18 Mar 2025 13:36:04 +0800
Subject: [PATCH v2 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <20250318053606.3087121-1-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
Message-ID: <20250318053606.3087121-2-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The code does not add IBI rules for devices with controller capability.
However, the secondary controller has the controller capability and works
at target mode when the device is probed. Therefore, add IBI rules for
such devices.

Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 1d1f351b9a85..a72ba5a7edd4 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
 
 	/* Create the IBIRULES register for both cases */
 	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
-		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
+		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
 			continue;
 
 		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
-- 
2.34.1



From stanley.chuys at gmail.com  Mon Mar 17 22:36:05 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Tue, 18 Mar 2025 13:36:05 +0800
Subject: [PATCH v2 2/3] i3c: master: svc: Use readsb helper for reading MDB
In-Reply-To: <20250318053606.3087121-1-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
Message-ID: <20250318053606.3087121-3-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The target can send the MDB byte followed by additional data bytes.
The readl on MRDATAB reads one actual byte, but the readsl advances
the destination pointer by 4 bytes. This causes the subsequent payload
to be copied to wrong position in the destination buffer.

Cc: stable at kernel.org
Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index a72ba5a7edd4..57b9dec6b5a8 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -425,7 +425,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
 	       slot->len < SVC_I3C_FIFO_SIZE) {
 		mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
 		count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl);
-		readsl(master->regs + SVC_I3C_MRDATAB, buf, count);
+		readsb(master->regs + SVC_I3C_MRDATAB, buf, count);
 		slot->len += count;
 		buf += count;
 	}
-- 
2.34.1



From stanley.chuys at gmail.com  Mon Mar 17 22:36:06 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Tue, 18 Mar 2025 13:36:06 +0800
Subject: [PATCH v2 3/3] i3c: master: svc: Fix missing STOP for master request
In-Reply-To: <20250318053606.3087121-1-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
Message-ID: <20250318053606.3087121-4-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

The controller driver nacked the master request but didn't emit a
STOP to end the transaction. The driver shall refuse the unsupported
requests and return the controller state to IDLE by emitting a STOP.

Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 57b9dec6b5a8..e0cd3ce28b7f 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -592,6 +592,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 			queue_work(master->base.wq, &master->hj_work);
 		break;
 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+		svc_i3c_master_emit_stop(master);
 	default:
 		break;
 	}
-- 
2.34.1



From Frank.li at nxp.com  Tue Mar 18 06:31:53 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 18 Mar 2025 09:31:53 -0400
Subject: [PATCH v1 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <20250317224440840e4117@mail.local>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-2-yschu@nuvoton.com>
 <Z9glVBnpdwXuLwD7@lizhi-Precision-Tower-5810>
 <20250317224440840e4117@mail.local>
Message-ID: <Z9l1ycFFisuZn2zI@lizhi-Precision-Tower-5810>

On Mon, Mar 17, 2025 at 11:44:40PM +0100, Alexandre Belloni wrote:
> Hello Frank,
>
> On 17/03/2025 09:36:20-0400, Frank Li wrote:
> > On Mon, Mar 17, 2025 at 01:19:49PM +0800, Stanley Chu wrote:
> > > From: Stanley Chu <yschu at nuvoton.com>
> > >
> > > The code does not add IBI rules for devices with controller capability.
> > > However, some target devices, such as secondary controller, also have
> >                 ^^ dual rule devices
> >
> > OR
> >
> > However, the second controller have the controller capablity and work at
> > target devices mode when the device probe. So add IBI rules for such
> > devices.
> >
> >
> > > the controller capability.
> > > Modify the code to add rules for devices capable of sending IBI requests.
> > >
> > > Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> > > Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> >
> >
> > Reviewed-by: Frank Li <Frank.Li at nxp.com>
>
> Please avoid adding you reviewed-by tag when you request changes, else
> patch work will show the patch as being applicable. This is fine to do
> it occasionally but not for all the patches you review. You can simply
> wait for the next version to come.
>

Okay, I saw some device tree reviewer provide tag if only some minor
changes.

Frank

> >
> >
> > > ---
> > >  drivers/i3c/master/svc-i3c-master.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > > index 1d1f351b9a85..a72ba5a7edd4 100644
> > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > @@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
> > >
> > >  	/* Create the IBIRULES register for both cases */
> > >  	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
> > > -		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
> > > +		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
> > >  			continue;
> > >
> > >  		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
> > > --
> > > 2.34.1
> > >
>
> --
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com


From Frank.li at nxp.com  Tue Mar 18 06:33:26 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 18 Mar 2025 09:33:26 -0400
Subject: [PATCH v2 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <20250318053606.3087121-2-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
 <20250318053606.3087121-2-yschu@nuvoton.com>
Message-ID: <Z9l2JqcvxvtlRdBe@lizhi-Precision-Tower-5810>

On Tue, Mar 18, 2025 at 01:36:04PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The code does not add IBI rules for devices with controller capability.
> However, the secondary controller has the controller capability and works
> at target mode when the device is probed. Therefore, add IBI rules for
> such devices.
>
> Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/i3c/master/svc-i3c-master.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 1d1f351b9a85..a72ba5a7edd4 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -1106,7 +1106,7 @@ static int svc_i3c_update_ibirules(struct svc_i3c_master *master)
>
>  	/* Create the IBIRULES register for both cases */
>  	i3c_bus_for_each_i3cdev(&master->base.bus, dev) {
> -		if (I3C_BCR_DEVICE_ROLE(dev->info.bcr) == I3C_BCR_I3C_MASTER)
> +		if (!(dev->info.bcr & I3C_BCR_IBI_REQ_CAP))
>  			continue;
>
>  		if (dev->info.bcr & I3C_BCR_IBI_PAYLOAD) {
> --
> 2.34.1
>


From Frank.li at nxp.com  Tue Mar 18 06:34:11 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 18 Mar 2025 09:34:11 -0400
Subject: [PATCH v2 2/3] i3c: master: svc: Use readsb helper for reading
 MDB
In-Reply-To: <20250318053606.3087121-3-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
 <20250318053606.3087121-3-yschu@nuvoton.com>
Message-ID: <Z9l2U0lG28KlxPzX@lizhi-Precision-Tower-5810>

On Tue, Mar 18, 2025 at 01:36:05PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The target can send the MDB byte followed by additional data bytes.
> The readl on MRDATAB reads one actual byte, but the readsl advances
> the destination pointer by 4 bytes. This causes the subsequent payload
> to be copied to wrong position in the destination buffer.
>
> Cc: stable at kernel.org
> Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/i3c/master/svc-i3c-master.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index a72ba5a7edd4..57b9dec6b5a8 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -425,7 +425,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
>  	       slot->len < SVC_I3C_FIFO_SIZE) {
>  		mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL);
>  		count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl);
> -		readsl(master->regs + SVC_I3C_MRDATAB, buf, count);
> +		readsb(master->regs + SVC_I3C_MRDATAB, buf, count);
>  		slot->len += count;
>  		buf += count;
>  	}
> --
> 2.34.1
>


From Frank.li at nxp.com  Tue Mar 18 06:35:09 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 18 Mar 2025 09:35:09 -0400
Subject: [PATCH v2 3/3] i3c: master: svc: Fix missing STOP for master
 request
In-Reply-To: <20250318053606.3087121-4-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
 <20250318053606.3087121-4-yschu@nuvoton.com>
Message-ID: <Z9l2jeCB4hYiTmHk@lizhi-Precision-Tower-5810>

On Tue, Mar 18, 2025 at 01:36:06PM +0800, Stanley Chu wrote:
> From: Stanley Chu <yschu at nuvoton.com>
>
> The controller driver nacked the master request but didn't emit a
> STOP to end the transaction. The driver shall refuse the unsupported
> requests and return the controller state to IDLE by emitting a STOP.
>
> Signed-off-by: Stanley Chu <yschu at nuvoton.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/i3c/master/svc-i3c-master.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 57b9dec6b5a8..e0cd3ce28b7f 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -592,6 +592,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
>  			queue_work(master->base.wq, &master->hj_work);
>  		break;
>  	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
> +		svc_i3c_master_emit_stop(master);
>  	default:
>  		break;
>  	}
> --
> 2.34.1
>


From Frank.li at nxp.com  Tue Mar 18 06:40:17 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 18 Mar 2025 09:40:17 -0400
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in
 dynamic address assignment
In-Reply-To: <20250317101516.19157-1-qasdev00@gmail.com>
References: <20250317101516.19157-1-qasdev00@gmail.com>
Message-ID: <Z9l3waI5EdrWmYC3@lizhi-Precision-Tower-5810>

On Mon, Mar 17, 2025 at 10:15:16AM +0000, Qasim Ijaz wrote:
> svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int
> however it initialises it with i3c_master_get_free_addr() which
> returns a signed int type and then attempts to check if dyn_addr is
> less than 0. Unsigned integers cannot be less than 0, so the check
> is essentially redundant. Furthermore i3c_master_get_free_addr()
> could return -ENOMEM which an unsigned int cannot store.
>
> Fix this by capturing the return value of i3c_master_get_free_addr()
> in a signed int ?dyn_addr_ret?. If that value is negative, return
> an error. Otherwise, assign it to the unsigned int ?dyn_addr? once
> we know it?s valid.
>
> Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
> Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> ---

Thank you for your patch, but similar one was already applied
https://lore.kernel.org/linux-i3c/174225158210.1593610.10018812780731849409.b4-ty at bootlin.com/T/#m5120e1c362e7e57f4cab139a45410fde421c2f37

Frank
>  drivers/i3c/master/svc-i3c-master.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index f22fb9e75142..eea08f00d7ce 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -998,9 +998,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
>  			 * filling within a few hundred nanoseconds, which is significantly
>  			 * faster compared to the 64 SCL clock cycles.
>  			 */
> -			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> -			if (dyn_addr < 0)
> +			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> +			if (dyn_addr_ret < 0)
>  				return -ENOSPC;
> +			dyn_addr = dyn_addr_ret;
>
>  			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
>
> --
> 2.39.5
>


From qasdev00 at gmail.com  Mon Mar 17 03:15:16 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Mon, 17 Mar 2025 10:15:16 +0000
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in dynamic address assignment
Message-ID: <20250317101516.19157-1-qasdev00@gmail.com>

svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int
however it initialises it with i3c_master_get_free_addr() which
returns a signed int type and then attempts to check if dyn_addr is
less than 0. Unsigned integers cannot be less than 0, so the check
is essentially redundant. Furthermore i3c_master_get_free_addr()
could return -ENOMEM which an unsigned int cannot store.
 
Fix this by capturing the return value of i3c_master_get_free_addr()
in a signed int ???dyn_addr_ret???. If that value is negative, return
an error. Otherwise, assign it to the unsigned int ???dyn_addr??? once
we know it???s valid.
 
Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
---
 drivers/i3c/master/svc-i3c-master.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index f22fb9e75142..eea08f00d7ce 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -998,9 +998,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 			 * filling within a few hundred nanoseconds, which is significantly
 			 * faster compared to the 64 SCL clock cycles.
 			 */
-			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
-			if (dyn_addr < 0)
+			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
+			if (dyn_addr_ret < 0)
 				return -ENOSPC;
+			dyn_addr = dyn_addr_ret;
 
 			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
 
-- 
2.39.5



From manjunatha.venkatesh at nxp.com  Mon Mar 17 08:46:52 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Mon, 17 Mar 2025 15:46:52 +0000
Subject: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
 svc_i3c_master_ibi_work()
In-Reply-To: <Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
 <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB1004979B7D38486FD1E1CC8508FDF2@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Monday, March 17, 2025 6:57 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable memory at
> svc_i3c_master_ibi_work()
> 
> On Thu, Mar 13, 2025 at 05:15:42AM +0000, Manjunatha Venkatesh wrote:
> >
> >
> > > -----Original Message-----
> > > From: Frank Li <frank.li at nxp.com>
> > > Sent: Wednesday, March 12, 2025 11:59 PM
> > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> > > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
> > > memory at
> > > svc_i3c_master_ibi_work()
> > >
> > > On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh
> wrote:
> > > > As part of I3C driver probing sequence for particular device
> > > > instance, While adding to queue it is trying to access ibi
> > > > variable of dev which is not yet initialized causing "Unable to
> > > > handle kernel read from unreadable memory" resulting in kernel panic.
> > > >
> > > > Below is the sequence where this issue happened.
> > > > 1. During boot up sequence IBI is received at host  from the slave device
> > > >    before requesting for IBI, Usually will request IBI by calling
> > > >    i3c_device_request_ibi() during probe of slave driver.
> > > > 2. Since master code trying to access IBI Variable for the particular
> > > >    device instance before actually it initialized by slave driver,
> > > >    due to this randomly accessing the address and causing kernel panic.
> > > > 3. i3c_device_request_ibi() function invoked by the slave driver where
> > > >    dev->ibi = ibi; assigned as part of function call
> > > >    i3c_dev_request_ibi_locked().
> > > > 4. But when IBI request sent by slave device, master code  trying to
> access
> > > >    this variable before its initialized due to this race condition
> > > >    situation kernel panic happened.
> > > >
> > > > Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C master
> > > > driver")
> > > > Cc: stable at vger.kernel.org
> > > > Signed-off-by: Manjunatha Venkatesh
> <manjunatha.venkatesh at nxp.com>
> > > > ---
> > > > Changes since v3:
> > > >   - Description  updated typo "Fixes:"
> > > >
> > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > @@ -534,8 +534,11 @@ static void svc_i3c_master_ibi_work(struct
> > > work_struct *work)
> > > >  	switch (ibitype) {
> > > >  	case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > >  		if (dev) {
> > > > -			i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > > -			master->ibi.tbq_slot = NULL;
> > > > +			data = i3c_dev_get_master_data(dev);
> > > > +			if (master->ibi.slots[data->ibi]) {
> > > > +				i3c_master_queue_ibi(dev, master-
> > > >ibi.tbq_slot);
> > > > +				master->ibi.tbq_slot = NULL;
> > > > +			}
> > >
> > > You still not reply previous discussion:
> > >
> > > https://lore.kernel.org/linux-i3c/Z8sOKZSjHeeP2mY5 at lizhi-Precision-T
> > > ower-
> > > 5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417
> > >
> > [Manjunatha Venkatesh] : In the last mail answered to this question.
> >
> > > This is not issue only at svc driver, which should be common problem
> > > for other master controller drivers
> > >
> > [Manjunatha Venkatesh] :Yes, you are right.
> > One of my project I3C interface is required, where we have used IMX board
> as reference platform.
> > As part of boot sequence we come across this issue and tried to fix that
> particular controller driver.
> >
> > What is your conclusion on this? Is it not ok to take patch for SVC alone?
> 
> I perfer fix at common framwork to avoid every driver copy the similar logic
> code.
> 
[Manjunatha Venkatesh] : As per your suggestion tried the below patch at common framework api i3c_master_queue_ibi()
 and looks working fine, didn't see any crash issue.
if (!dev->ibi || !slot) {
             dev_warning("...");
             return;
}
Will commit this change in next patch submission.

> Frank
> 
> >
> > > Frank
> > >
> > > >  		}
> > > >  		svc_i3c_master_emit_stop(master);
> > > >  		break;
> > > > --
> > > > 2.46.1
> > > >
> >
> > --
> > linux-i3c mailing list
> > linux-i3c at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-i3c


From qasdev00 at gmail.com  Tue Mar 18 07:41:47 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Tue, 18 Mar 2025 14:41:47 +0000
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in
 dynamic address assignment
In-Reply-To: <Z9l3waI5EdrWmYC3@lizhi-Precision-Tower-5810>
References: <20250317101516.19157-1-qasdev00@gmail.com>
 <Z9l3waI5EdrWmYC3@lizhi-Precision-Tower-5810>
Message-ID: <Z9mGK0x8fsWvbTvo@qasdev.system>

On Tue, Mar 18, 2025 at 09:40:17AM -0400, Frank Li wrote:
> On Mon, Mar 17, 2025 at 10:15:16AM +0000, Qasim Ijaz wrote:
> > svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int
> > however it initialises it with i3c_master_get_free_addr() which
> > returns a signed int type and then attempts to check if dyn_addr is
> > less than 0. Unsigned integers cannot be less than 0, so the check
> > is essentially redundant. Furthermore i3c_master_get_free_addr()
> > could return -ENOMEM which an unsigned int cannot store.
> >
> > Fix this by capturing the return value of i3c_master_get_free_addr()
> > in a signed int ?dyn_addr_ret?. If that value is negative, return
> > an error. Otherwise, assign it to the unsigned int ?dyn_addr? once
> > we know it?s valid.
> >
> > Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
> > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > ---
> 
> Thank you for your patch, but similar one was already applied
> https://lore.kernel.org/linux-i3c/174225158210.1593610.10018812780731849409.b4-ty at bootlin.com/T/#m5120e1c362e7e57f4cab139a45410fde421c2f37
>

Hi Frank 
 
I sent a fix for this issue on the 9th March, which is before the patch
you linked which was sent on the 10th March.

You can view my orignal patch here:

https://lore.kernel.org/all/20250309164314.15039-1-qasdev00 at gmail.com/

Thanks
Qasim
> Frank
> >  drivers/i3c/master/svc-i3c-master.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > index f22fb9e75142..eea08f00d7ce 100644
> > --- a/drivers/i3c/master/svc-i3c-master.c
> > +++ b/drivers/i3c/master/svc-i3c-master.c
> > @@ -998,9 +998,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> >  			 * filling within a few hundred nanoseconds, which is significantly
> >  			 * faster compared to the 64 SCL clock cycles.
> >  			 */
> > -			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > -			if (dyn_addr < 0)
> > +			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > +			if (dyn_addr_ret < 0)
> >  				return -ENOSPC;
> > +			dyn_addr = dyn_addr_ret;
> >
> >  			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
> >
> > --
> > 2.39.5
> >


From qasdev00 at gmail.com  Tue Mar 18 07:51:49 2025
From: qasdev00 at gmail.com (Qasim Ijaz)
Date: Tue, 18 Mar 2025 14:51:49 +0000
Subject: [PATCH v1 1/1] i3c: master: svc: Fix i3c_master_get_free_addr
 return check
In-Reply-To: <174225158210.1593610.10018812780731849409.b4-ty@bootlin.com>
References: <20250310023304.2335792-1-yschu@nuvoton.com>
 <174225158210.1593610.10018812780731849409.b4-ty@bootlin.com>
Message-ID: <Z9mIUc6Ln59umJtT@qasdev.system>

On Mon, Mar 17, 2025 at 11:46:29PM +0100, Alexandre Belloni wrote:
> On Mon, 10 Mar 2025 10:33:04 +0800, Stanley Chu wrote:
> > The return value of i3c_master_get_free_addr is assigned to a variable
> > with wrong type, so it can't be negative. Use a signed integer for the
> > return value. If the value is negative, break the process and propagate
> > the error code.
> > 
> > This commit also fixes the uninitialized symbol 'dyn_addr', reported
> > by Smatch static checker.
> > 
> > [...]
> 
> Applied, thanks!
> 
> [1/1] i3c: master: svc: Fix i3c_master_get_free_addr return check
>       https://git.kernel.org/abelloni/c/d6cb667b8e15
> 
> Best regards,
> 
> -- 
> Alexandre Belloni, co-owner and COO, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com

Hi Alexandre,

I sent a fix for this issue on the 9th March, which is before the patch
Stanley sent which was sent on the 10th March.

You can view my orignal patch here:

https://lore.kernel.org/all/20250309164314.15039-1-qasdev00 at gmail.com/

Thanks
Qasim
> 
> -- 
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From alexandre.belloni at bootlin.com  Tue Mar 18 08:58:31 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Tue, 18 Mar 2025 16:58:31 +0100
Subject: [PATCH v1 1/1] i3c: master: svc: Fix i3c_master_get_free_addr
 return check
In-Reply-To: <Z9mIUc6Ln59umJtT@qasdev.system>
References: <20250310023304.2335792-1-yschu@nuvoton.com>
 <174225158210.1593610.10018812780731849409.b4-ty@bootlin.com>
 <Z9mIUc6Ln59umJtT@qasdev.system>
Message-ID: <202503181558316ef27a06@mail.local>

On 18/03/2025 14:51:49+0000, Qasim Ijaz wrote:
> On Mon, Mar 17, 2025 at 11:46:29PM +0100, Alexandre Belloni wrote:
> > On Mon, 10 Mar 2025 10:33:04 +0800, Stanley Chu wrote:
> > > The return value of i3c_master_get_free_addr is assigned to a variable
> > > with wrong type, so it can't be negative. Use a signed integer for the
> > > return value. If the value is negative, break the process and propagate
> > > the error code.
> > > 
> > > This commit also fixes the uninitialized symbol 'dyn_addr', reported
> > > by Smatch static checker.
> > > 
> > > [...]
> > 
> > Applied, thanks!
> > 
> > [1/1] i3c: master: svc: Fix i3c_master_get_free_addr return check
> >       https://git.kernel.org/abelloni/c/d6cb667b8e15
> > 
> > Best regards,
> > 
> > -- 
> > Alexandre Belloni, co-owner and COO, Bootlin
> > Embedded Linux and Kernel engineering
> > https://bootlin.com
> 
> Hi Alexandre,
> 
> I sent a fix for this issue on the 9th March, which is before the patch
> Stanley sent which was sent on the 10th March.
> 
> You can view my orignal patch here:
> 
> https://lore.kernel.org/all/20250309164314.15039-1-qasdev00 at gmail.com/
> 

The issue is that you then resent the patch with the same topic which
superseded your original patch. But the resend was missing a blank line
so I could not apply it immediately and I later applied the other one.


-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Tue Mar 18 09:03:03 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Tue, 18 Mar 2025 17:03:03 +0100
Subject: [PATCH v1 1/3] i3c: master: svc: Fix missing the IBI rules
In-Reply-To: <Z9l1ycFFisuZn2zI@lizhi-Precision-Tower-5810>
References: <20250317051951.3065011-1-yschu@nuvoton.com>
 <20250317051951.3065011-2-yschu@nuvoton.com>
 <Z9glVBnpdwXuLwD7@lizhi-Precision-Tower-5810>
 <20250317224440840e4117@mail.local>
 <Z9l1ycFFisuZn2zI@lizhi-Precision-Tower-5810>
Message-ID: <202503181603034c9ab59f@mail.local>

On 18/03/2025 09:31:53-0400, Frank Li wrote:
> On Mon, Mar 17, 2025 at 11:44:40PM +0100, Alexandre Belloni wrote:
> > Hello Frank,
> >
> > On 17/03/2025 09:36:20-0400, Frank Li wrote:
> > > On Mon, Mar 17, 2025 at 01:19:49PM +0800, Stanley Chu wrote:
> > > > From: Stanley Chu <yschu at nuvoton.com>
> > > >
> > > > The code does not add IBI rules for devices with controller capability.
> > > > However, some target devices, such as secondary controller, also have
> > >                 ^^ dual rule devices
> > >
> > > OR
> > >
> > > However, the second controller have the controller capablity and work at
> > > target devices mode when the device probe. So add IBI rules for such
> > > devices.
> > >
> > >
> > > > the controller capability.
> > > > Modify the code to add rules for devices capable of sending IBI requests.
> > > >
> > > > Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver")
> > > > Signed-off-by: Stanley Chu <yschu at nuvoton.com>
> > >
> > >
> > > Reviewed-by: Frank Li <Frank.Li at nxp.com>
> >
> > Please avoid adding you reviewed-by tag when you request changes, else
> > patch work will show the patch as being applicable. This is fine to do
> > it occasionally but not for all the patches you review. You can simply
> > wait for the next version to come.
> >
> 
> Okay, I saw some device tree reviewer provide tag if only some minor
> changes.
> 

Yes, that can be done sometimes but then the submitter would have to
collect the tags which didn't happen this time and there will always be
an extra review for the subsystem that will gate the patches.


-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Tue Mar 18 09:17:05 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Tue, 18 Mar 2025 17:17:05 +0100
Subject: [PATCH v2 0/3] Some fixes for Silvaco I3C controller driver
In-Reply-To: <20250318053606.3087121-1-yschu@nuvoton.com>
References: <20250318053606.3087121-1-yschu@nuvoton.com>
Message-ID: <174231461561.2047387.4537921401617051173.b4-ty@bootlin.com>

On Tue, 18 Mar 2025 13:36:03 +0800, Stanley Chu wrote:
> This patchset adds some fixes for the Silvaco I3C controller driver.
> 
> Stanley Chu (3):
>   i3c: master: svc: Fix missing the IBI rules
>   i3c: master: svc: Use readsb helper for reading MDB
>   i3c: master: svc: Fix missing STOP for master request
> 
> [...]

Applied, thanks!

[1/3] i3c: master: svc: Fix missing the IBI rules
      https://git.kernel.org/abelloni/c/9cecad134d84
[2/3] i3c: master: svc: Use readsb helper for reading MDB
      https://git.kernel.org/abelloni/c/c06acf7143bd
[3/3] i3c: master: svc: Fix missing STOP for master request
      https://git.kernel.org/abelloni/c/0430bf9bc1ac

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From Frank.li at nxp.com  Wed Mar 19 06:18:52 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 19 Mar 2025 09:18:52 -0400
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in
 dynamic address assignment
In-Reply-To: <Z9mGK0x8fsWvbTvo@qasdev.system>
References: <20250317101516.19157-1-qasdev00@gmail.com>
 <Z9l3waI5EdrWmYC3@lizhi-Precision-Tower-5810>
 <Z9mGK0x8fsWvbTvo@qasdev.system>
Message-ID: <Z9rEPLAmxrqP61sz@lizhi-Precision-Tower-5810>

On Tue, Mar 18, 2025 at 02:41:47PM +0000, Qasim Ijaz wrote:
> On Tue, Mar 18, 2025 at 09:40:17AM -0400, Frank Li wrote:
> > On Mon, Mar 17, 2025 at 10:15:16AM +0000, Qasim Ijaz wrote:
> > > svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int
> > > however it initialises it with i3c_master_get_free_addr() which
> > > returns a signed int type and then attempts to check if dyn_addr is
> > > less than 0. Unsigned integers cannot be less than 0, so the check
> > > is essentially redundant. Furthermore i3c_master_get_free_addr()
> > > could return -ENOMEM which an unsigned int cannot store.
> > >
> > > Fix this by capturing the return value of i3c_master_get_free_addr()
> > > in a signed int ?dyn_addr_ret?. If that value is negative, return
> > > an error. Otherwise, assign it to the unsigned int ?dyn_addr? once
> > > we know it?s valid.
> > >
> > > Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
> > > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > > ---
> >
> > Thank you for your patch, but similar one was already applied
> > https://lore.kernel.org/linux-i3c/174225158210.1593610.10018812780731849409.b4-ty at bootlin.com/T/#m5120e1c362e7e57f4cab139a45410fde421c2f37
> >
>
> Hi Frank
>
> I sent a fix for this issue on the 9th March, which is before the patch
> you linked which was sent on the 10th March.

Yes, but perfer original owner to fix this type minor fix.

https://lore.kernel.org/linux-i3c/174129444617.1163689.11942276093411687387.b4-ty at bootlin.com/T/#t

Frank
>
> You can view my orignal patch here:
>
> https://lore.kernel.org/all/20250309164314.15039-1-qasdev00 at gmail.com/
>
> Thanks
> Qasim
> > Frank
> > >  drivers/i3c/master/svc-i3c-master.c | 5 +++--
> > >  1 file changed, 3 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > > index f22fb9e75142..eea08f00d7ce 100644
> > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > @@ -998,9 +998,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> > >  			 * filling within a few hundred nanoseconds, which is significantly
> > >  			 * faster compared to the 64 SCL clock cycles.
> > >  			 */
> > > -			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > > -			if (dyn_addr < 0)
> > > +			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > > +			if (dyn_addr_ret < 0)
> > >  				return -ENOSPC;
> > > +			dyn_addr = dyn_addr_ret;
> > >
> > >  			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
> > >
> > > --
> > > 2.39.5
> > >
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From nathan at kernel.org  Wed Mar 19 09:08:01 2025
From: nathan at kernel.org (Nathan Chancellor)
Date: Wed, 19 Mar 2025 09:08:01 -0700
Subject: [PATCH] i3c: master: svc: Fix implicit fallthrough in
 svc_i3c_master_ibi_work()
Message-ID: <20250319-i3c-fix-clang-fallthrough-v1-1-d8e02be1ef5c@kernel.org>

Clang warns (or errors with CONFIG_WERROR=y):

  drivers/i3c/master/svc-i3c-master.c:596:2: error: unannotated fall-through between switch labels [-Werror,-Wimplicit-fallthrough]
    596 |         default:
        |         ^
  drivers/i3c/master/svc-i3c-master.c:596:2: note: insert 'break;' to avoid fall-through
    596 |         default:
        |         ^
        |         break;
  1 error generated.

Clang is a little more pedantic than GCC, which does not warn when
falling through to a case that is just break or return. Clang's version
is more in line with the kernel's own stance in deprecated.rst, which
states that all switch/case blocks must end in either break,
fallthrough, continue, goto, or return. Add the missing break to silence
the warning.

Fixes: 0430bf9bc1ac ("i3c: master: svc: Fix missing STOP for master request")
Signed-off-by: Nathan Chancellor <nathan at kernel.org>
---
 drivers/i3c/master/svc-i3c-master.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index e0cd3ce28b7f..85e16de208d3 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -593,6 +593,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 		break;
 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
 		svc_i3c_master_emit_stop(master);
+		break;
 	default:
 		break;
 	}

---
base-commit: 0430bf9bc1ac068c8b8c540eb93e5751872efc51
change-id: 20250319-i3c-fix-clang-fallthrough-9f5c7cf5e799

Best regards,
-- 
Nathan Chancellor <nathan at kernel.org>



From alexandre.belloni at bootlin.com  Thu Mar 20 15:01:31 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Thu, 20 Mar 2025 23:01:31 +0100
Subject: [PATCH] i3c: master: svc: fix signed/unsigned mismatch in
 dynamic address assignment
In-Reply-To: <Z9rEPLAmxrqP61sz@lizhi-Precision-Tower-5810>
References: <20250317101516.19157-1-qasdev00@gmail.com>
 <Z9l3waI5EdrWmYC3@lizhi-Precision-Tower-5810>
 <Z9mGK0x8fsWvbTvo@qasdev.system>
 <Z9rEPLAmxrqP61sz@lizhi-Precision-Tower-5810>
Message-ID: <2025032022013134061aaa@mail.local>

On 19/03/2025 09:18:52-0400, Frank Li wrote:
> On Tue, Mar 18, 2025 at 02:41:47PM +0000, Qasim Ijaz wrote:
> > On Tue, Mar 18, 2025 at 09:40:17AM -0400, Frank Li wrote:
> > > On Mon, Mar 17, 2025 at 10:15:16AM +0000, Qasim Ijaz wrote:
> > > > svc_i3c_master_do_daa_locked() declares dyn_addr as an unsigned int
> > > > however it initialises it with i3c_master_get_free_addr() which
> > > > returns a signed int type and then attempts to check if dyn_addr is
> > > > less than 0. Unsigned integers cannot be less than 0, so the check
> > > > is essentially redundant. Furthermore i3c_master_get_free_addr()
> > > > could return -ENOMEM which an unsigned int cannot store.
> > > >
> > > > Fix this by capturing the return value of i3c_master_get_free_addr()
> > > > in a signed int ?dyn_addr_ret?. If that value is negative, return
> > > > an error. Otherwise, assign it to the unsigned int ?dyn_addr? once
> > > > we know it?s valid.
> > > >
> > > > Fixes: 4008a74e0f9b ("i3c: master: svc: Fix npcm845 FIFO empty issue")
> > > > Signed-off-by: Qasim Ijaz <qasdev00 at gmail.com>
> > > > ---
> > >
> > > Thank you for your patch, but similar one was already applied
> > > https://lore.kernel.org/linux-i3c/174225158210.1593610.10018812780731849409.b4-ty at bootlin.com/T/#m5120e1c362e7e57f4cab139a45410fde421c2f37
> > >
> >
> > Hi Frank
> >
> > I sent a fix for this issue on the 9th March, which is before the patch
> > you linked which was sent on the 10th March.
> 
> Yes, but perfer original owner to fix this type minor fix.
> 

This is absolutely not what I said, the first one that is sent and is
applicable should be applied.

See how you didn't fix this trivial issue:

https://lore.kernel.org/linux-i3c/20250319-i3c-fix-clang-fallthrough-v1-1-d8e02be1ef5c at kernel.org/T/#u

> https://lore.kernel.org/linux-i3c/174129444617.1163689.11942276093411687387.b4-ty at bootlin.com/T/#t
> 
> Frank
> >
> > You can view my orignal patch here:
> >
> > https://lore.kernel.org/all/20250309164314.15039-1-qasdev00 at gmail.com/
> >
> > Thanks
> > Qasim
> > > Frank
> > > >  drivers/i3c/master/svc-i3c-master.c | 5 +++--
> > > >  1 file changed, 3 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> > > > index f22fb9e75142..eea08f00d7ce 100644
> > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > @@ -998,9 +998,10 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
> > > >  			 * filling within a few hundred nanoseconds, which is significantly
> > > >  			 * faster compared to the 64 SCL clock cycles.
> > > >  			 */
> > > > -			dyn_addr = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > > > -			if (dyn_addr < 0)
> > > > +			int dyn_addr_ret = i3c_master_get_free_addr(&master->base, last_addr + 1);
> > > > +			if (dyn_addr_ret < 0)
> > > >  				return -ENOSPC;
> > > > +			dyn_addr = dyn_addr_ret;
> > > >
> > > >  			writel(dyn_addr, master->regs + SVC_I3C_MWDATAB);
> > > >
> > > > --
> > > > 2.39.5
> > > >
> >
> > --
> > linux-i3c mailing list
> > linux-i3c at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-i3c
> 
> -- 
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From alexandre.belloni at bootlin.com  Thu Mar 20 15:03:05 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Thu, 20 Mar 2025 23:03:05 +0100
Subject: [PATCH] i3c: master: svc: Fix implicit fallthrough in
 svc_i3c_master_ibi_work()
In-Reply-To: <20250319-i3c-fix-clang-fallthrough-v1-1-d8e02be1ef5c@kernel.org>
References: <20250319-i3c-fix-clang-fallthrough-v1-1-d8e02be1ef5c@kernel.org>
Message-ID: <174250817539.3598269.2833694260995006704.b4-ty@bootlin.com>

On Wed, 19 Mar 2025 09:08:01 -0700, Nathan Chancellor wrote:
> Clang warns (or errors with CONFIG_WERROR=y):
> 
>   drivers/i3c/master/svc-i3c-master.c:596:2: error: unannotated fall-through between switch labels [-Werror,-Wimplicit-fallthrough]
>     596 |         default:
>         |         ^
>   drivers/i3c/master/svc-i3c-master.c:596:2: note: insert 'break;' to avoid fall-through
>     596 |         default:
>         |         ^
>         |         break;
>   1 error generated.
> 
> [...]

Applied, thanks!

[1/1] i3c: master: svc: Fix implicit fallthrough in svc_i3c_master_ibi_work()
      https://git.kernel.org/abelloni/c/e8d2d287e26d

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From andriy.shevchenko at linux.intel.com  Fri Mar 21 12:25:26 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri, 21 Mar 2025 21:25:26 +0200
Subject: [PATCH v1 1/1] i3c: master: Drop duplicate check before calling OF APIs
Message-ID: <20250321192527.457324-1-andriy.shevchenko@linux.intel.com>

OF APIs are usually NULL-aware and returns an error in case when
device node is not present or supported. We already have a check
for the returned value, no need to check for the parameter.

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/i3c/master.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d5dc4180afbc..1580e2630dfe 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2486,7 +2486,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
 	struct i2c_dev_desc *i2cdev;
 	struct i2c_dev_boardinfo *i2cboardinfo;
-	int ret, id = -ENODEV;
+	int ret, id;
 
 	adap->dev.parent = master->dev.parent;
 	adap->owner = master->dev.parent->driver->owner;
@@ -2497,9 +2497,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	adap->timeout = 1000;
 	adap->retries = 3;
 
-	if (master->dev.of_node)
-		id = of_alias_get_id(master->dev.of_node, "i2c");
-
+	id = of_alias_get_id(master->dev.of_node, "i2c");
 	if (id >= 0) {
 		adap->nr = id;
 		ret = i2c_add_numbered_adapter(adap);
-- 
2.47.2



From andriy.shevchenko at linux.intel.com  Fri Mar 21 12:30:06 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri, 21 Mar 2025 21:30:06 +0200
Subject: [PATCH v2 1/1] i3c: master: Drop duplicate check before calling OF APIs
Message-ID: <20250321193044.457649-1-andriy.shevchenko@linux.intel.com>

OF APIs are usually NULL-aware and returns an error in case when
device node is not present or supported. We already have a check
for the returned value, no need to check for the parameter.

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---

v2: added missed updates (hit 'send' too early in v1)

 drivers/i3c/master.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d5dc4180afbc..fd26c4bb8b34 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2276,7 +2276,7 @@ static int of_i3c_master_add_dev(struct i3c_master_controller *master,
 	u32 reg[3];
 	int ret;
 
-	if (!master || !node)
+	if (!master)
 		return -EINVAL;
 
 	ret = of_property_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
@@ -2369,14 +2369,10 @@ static u8 i3c_master_i2c_get_lvr(struct i2c_client *client)
 {
 	/* Fall back to no spike filters and FM bus mode. */
 	u8 lvr = I3C_LVR_I2C_INDEX(2) | I3C_LVR_I2C_FM_MODE;
+	u32 reg[3];
 
-	if (client->dev.of_node) {
-		u32 reg[3];
-
-		if (!of_property_read_u32_array(client->dev.of_node, "reg",
-						reg, ARRAY_SIZE(reg)))
-			lvr = reg[2];
-	}
+	if (!of_property_read_u32_array(client->dev.of_node, "reg", reg, ARRAY_SIZE(reg)))
+		lvr = reg[2];
 
 	return lvr;
 }
@@ -2486,7 +2482,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
 	struct i2c_dev_desc *i2cdev;
 	struct i2c_dev_boardinfo *i2cboardinfo;
-	int ret, id = -ENODEV;
+	int ret, id;
 
 	adap->dev.parent = master->dev.parent;
 	adap->owner = master->dev.parent->driver->owner;
@@ -2497,9 +2493,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	adap->timeout = 1000;
 	adap->retries = 3;
 
-	if (master->dev.of_node)
-		id = of_alias_get_id(master->dev.of_node, "i2c");
-
+	id = of_alias_get_id(master->dev.of_node, "i2c");
 	if (id >= 0) {
 		adap->nr = id;
 		ret = i2c_add_numbered_adapter(adap);
-- 
2.47.2



From andriy.shevchenko at linux.intel.com  Fri Mar 21 12:31:08 2025
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri, 21 Mar 2025 21:31:08 +0200
Subject: [PATCH v1 1/1] i3c: master: Drop duplicate check before calling
 OF APIs
In-Reply-To: <20250321192527.457324-1-andriy.shevchenko@linux.intel.com>
References: <20250321192527.457324-1-andriy.shevchenko@linux.intel.com>
Message-ID: <Z92-fNE5hrX7Oy0g@smile.fi.intel.com>

On Fri, Mar 21, 2025 at 09:25:26PM +0200, Andy Shevchenko wrote:
> OF APIs are usually NULL-aware and returns an error in case when
> device node is not present or supported. We already have a check
> for the returned value, no need to check for the parameter.

Ignore this, it is partially done.

-- 
With Best Regards,
Andy Shevchenko




From Frank.li at nxp.com  Mon Mar 24 12:39:58 2025
From: Frank.li at nxp.com (Frank Li)
Date: Mon, 24 Mar 2025 15:39:58 -0400
Subject: [PATCH v2 1/1] i3c: master: Drop duplicate check before calling
 OF APIs
In-Reply-To: <20250321193044.457649-1-andriy.shevchenko@linux.intel.com>
References: <20250321193044.457649-1-andriy.shevchenko@linux.intel.com>
Message-ID: <Z+G1Dn2XOx9gLRTw@lizhi-Precision-Tower-5810>

On Fri, Mar 21, 2025 at 09:30:06PM +0200, Andy Shevchenko wrote:
> OF APIs are usually NULL-aware and returns an error in case when
> device node is not present or supported. We already have a check
> for the returned value, no need to check for the parameter.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>
> v2: added missed updates (hit 'send' too early in v1)
>
>  drivers/i3c/master.c | 18 ++++++------------
>  1 file changed, 6 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index d5dc4180afbc..fd26c4bb8b34 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2276,7 +2276,7 @@ static int of_i3c_master_add_dev(struct i3c_master_controller *master,
>  	u32 reg[3];
>  	int ret;
>
> -	if (!master || !node)
> +	if (!master)
>  		return -EINVAL;
>
>  	ret = of_property_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg));
> @@ -2369,14 +2369,10 @@ static u8 i3c_master_i2c_get_lvr(struct i2c_client *client)
>  {
>  	/* Fall back to no spike filters and FM bus mode. */
>  	u8 lvr = I3C_LVR_I2C_INDEX(2) | I3C_LVR_I2C_FM_MODE;
> +	u32 reg[3];
>
> -	if (client->dev.of_node) {
> -		u32 reg[3];
> -
> -		if (!of_property_read_u32_array(client->dev.of_node, "reg",
> -						reg, ARRAY_SIZE(reg)))
> -			lvr = reg[2];
> -	}
> +	if (!of_property_read_u32_array(client->dev.of_node, "reg", reg, ARRAY_SIZE(reg)))
> +		lvr = reg[2];
>
>  	return lvr;
>  }
> @@ -2486,7 +2482,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>  	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
>  	struct i2c_dev_desc *i2cdev;
>  	struct i2c_dev_boardinfo *i2cboardinfo;
> -	int ret, id = -ENODEV;
> +	int ret, id;
>
>  	adap->dev.parent = master->dev.parent;
>  	adap->owner = master->dev.parent->driver->owner;
> @@ -2497,9 +2493,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>  	adap->timeout = 1000;
>  	adap->retries = 3;
>
> -	if (master->dev.of_node)
> -		id = of_alias_get_id(master->dev.of_node, "i2c");
> -
> +	id = of_alias_get_id(master->dev.of_node, "i2c");
>  	if (id >= 0) {
>  		adap->nr = id;
>  		ret = i2c_add_numbered_adapter(adap);
> --
> 2.47.2
>


From Frank.li at nxp.com  Tue Mar 25 07:43:08 2025
From: Frank.li at nxp.com (Frank Li)
Date: Tue, 25 Mar 2025 10:43:08 -0400
Subject: [PATCH v5] i3c: Fix read from unreadable memory at
 i3c_master_queue_ibi()
In-Reply-To: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
References: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
Message-ID: <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>

Subject should be

i3c: Add NULL pointer check in i3c_master_queue_ibi()

On Tue, Mar 25, 2025 at 03:53:32PM +0530, Manjunatha Venkatesh wrote:
> As part of I3C driver probing sequence for particular device instance,
> While adding to queue it is trying to access ibi variable of dev which is
> not yet initialized causing "Unable to handle kernel read from unreadable
> memory" resulting in kernel panic.
>
> Below is the sequence where this issue happened.
> 1. During boot up sequence IBI is received at host  from the slave device
>    before requesting for IBI, Usually will request IBI by calling
>    i3c_device_request_ibi() during probe of slave driver.
> 2. Since master code trying to access IBI Variable for the particular
>    device instance before actually it initialized by slave driver,
>    due to this randomly accessing the address and causing kernel panic.
> 3. i3c_device_request_ibi() function invoked by the slave driver where
>    dev->ibi = ibi; assigned as part of function call
>    i3c_dev_request_ibi_locked().
> 4. But when IBI request sent by slave device, master code  trying to access
>    this variable before its initialized due to this race condition
>    situation kernel panic happened.

How about commit message as:

The I3C master driver may receive an IBI from a target device that has not
been probed yet. In such cases, the master calls `i3c_master_queue_ibi()`
to queue an IBI work task, leading to "Unable to handle kernel read from
unreadable memory" and resulting in a kernel panic.

Typical IBI handling flow:
1. The I3C master scans target devices and probes their respective drivers.
2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
   and assigns `dev->ibi = ibi`.
3. The I3C master receives an IBI from the target device and calls
   `i3c_master_queue_ibi()` to queue the target device driver?s IBI handler
   task.

However, since target device events are asynchronous to the I3C probe
sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`,
leading to a kernel panic.

Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing
an uninitialized `dev->ibi`, ensuring stability.

>
> Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
> Cc: stable at vger.kernel.org
> Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-5810/
> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> ---
> Changes since v4:
>   - Fix added at generic places master.c which is applicable for all platforms
>
>  drivers/i3c/master.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index d5dc4180afbc..c65006aa0684 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
>   */
>  void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
>  {
> +	if (!dev->ibi || !slot)
> +		return;
> +
>  	atomic_inc(&dev->ibi->pending_ibis);
>  	queue_work(dev->ibi->wq, &slot->work);
>  }
> --
> 2.46.1
>


From quic_msavaliy at quicinc.com  Tue Mar 25 23:45:00 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 12:15:00 +0530
Subject: [PATCH v5] i3c: Fix read from unreadable memory at
 i3c_master_queue_ibi()
In-Reply-To: <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
References: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
 <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
Message-ID: <8c624cf0-febc-4ab9-8141-2372bfe4d577@quicinc.com>



On 3/25/2025 8:13 PM, Frank Li wrote:
> Subject should be
> 
> i3c: Add NULL pointer check in i3c_master_queue_ibi()
> 
yes, Aligned.
> On Tue, Mar 25, 2025 at 03:53:32PM +0530, Manjunatha Venkatesh wrote:
>> As part of I3C driver probing sequence for particular device instance,
>> While adding to queue it is trying to access ibi variable of dev which is
>> not yet initialized causing "Unable to handle kernel read from unreadable
>> memory" resulting in kernel panic.
>>
>> Below is the sequence where this issue happened.
>> 1. During boot up sequence IBI is received at host  from the slave device
>>     before requesting for IBI, Usually will request IBI by calling
>>     i3c_device_request_ibi() during probe of slave driver.
>> 2. Since master code trying to access IBI Variable for the particular
>>     device instance before actually it initialized by slave driver,
>>     due to this randomly accessing the address and causing kernel panic.
>> 3. i3c_device_request_ibi() function invoked by the slave driver where
>>     dev->ibi = ibi; assigned as part of function call
>>     i3c_dev_request_ibi_locked().
>> 4. But when IBI request sent by slave device, master code  trying to access
>>     this variable before its initialized due to this race condition
>>     situation kernel panic happened.
> 
> How about commit message as:
> 
> The I3C master driver may receive an IBI from a target device that has not
> been probed yet. In such cases, the master calls `i3c_master_queue_ibi()`
> to queue an IBI work task, leading to "Unable to handle kernel read from
> unreadable memory" and resulting in a kernel panic.
> 
> Typical IBI handling flow:
> 1. The I3C master scans target devices and probes their respective drivers.
> 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
>     and assigns `dev->ibi = ibi`.
> 3. The I3C master receives an IBI from the target device and calls
>     `i3c_master_queue_ibi()` to queue the target device driver?s IBI handler
>     task.
> 
> However, since target device events are asynchronous to the I3C probe
> sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`,
> leading to a kernel panic.
> 
> Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing
> an uninitialized `dev->ibi`, ensuring stability.
> 
>>
>> Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
>> Cc: stable at vger.kernel.org
>> Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-5810/
>> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
>> ---
>> Changes since v4:
>>    - Fix added at generic places master.c which is applicable for all platforms
>>
>>   drivers/i3c/master.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
>> index d5dc4180afbc..c65006aa0684 100644
>> --- a/drivers/i3c/master.c
>> +++ b/drivers/i3c/master.c
>> @@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
>>    */
>>   void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
>>   {
>> +	if (!dev->ibi || !slot)
>> +		return;
>> +
1. Shouldn't this be a Logical AND ? what if slot is non NULL but the 
IBI is NULL ?

2. This being void function, it doesn't say anything to caller if it's 
successful or failed ? Should we make this non void function ?
if not, i am thinking it may run into multiple attempts, no log too.
>>   	atomic_inc(&dev->ibi->pending_ibis);
>>   	queue_work(dev->ibi->wq, &slot->work);
>>   }
>> --
>> 2.46.1
>>
> 



From quic_msavaliy at quicinc.com  Wed Mar 26 00:10:34 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 12:40:34 +0530
Subject: [EXT] Re: [PATCH v5] i3c: Fix read from unreadable memory at
 i3c_master_queue_ibi()
In-Reply-To: <VI1PR04MB10049E90AC1CB4823F91D1D698FA62@VI1PR04MB10049.eurprd04.prod.outlook.com>
References: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
 <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
 <8c624cf0-febc-4ab9-8141-2372bfe4d577@quicinc.com>
 <VI1PR04MB10049E90AC1CB4823F91D1D698FA62@VI1PR04MB10049.eurprd04.prod.outlook.com>
Message-ID: <fc59e721-3e43-4b81-8c35-75b33e9e6fc9@quicinc.com>



On 3/26/2025 12:28 PM, Manjunatha Venkatesh wrote:
> 
> 
>> -----Original Message-----
>> From: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>> Sent: Wednesday, March 26, 2025 12:15 PM
>> To: Frank Li <frank.li at nxp.com>; Manjunatha Venkatesh
>> <manjunatha.venkatesh at nxp.com>
>> Cc: alexandre.belloni at bootlin.com; arnd at arndb.de;
>> gregkh at linuxfoundation.org; bbrezillon at kernel.org; linux-
>> i3c at lists.infradead.org; linux-kernel at vger.kernel.org;
>> rvmanjumce at gmail.com; stable at vger.kernel.org
>> Subject: [EXT] Re: [PATCH v5] i3c: Fix read from unreadable memory at
>> i3c_master_queue_ibi()
>>
>> Caution: This is an external email. Please take care when clicking links or
>> opening attachments. When in doubt, report the message using the 'Report
>> this email' button
>>
>>
>> On 3/25/2025 8:13 PM, Frank Li wrote:
>>> Subject should be
>>>
>>> i3c: Add NULL pointer check in i3c_master_queue_ibi()
>>>
>> yes, Aligned.
>>> On Tue, Mar 25, 2025 at 03:53:32PM +0530, Manjunatha Venkatesh wrote:
>>>> As part of I3C driver probing sequence for particular device
>>>> instance, While adding to queue it is trying to access ibi variable
>>>> of dev which is not yet initialized causing "Unable to handle kernel
>>>> read from unreadable memory" resulting in kernel panic.
>>>>
>>>> Below is the sequence where this issue happened.
>>>> 1. During boot up sequence IBI is received at host  from the slave device
>>>>      before requesting for IBI, Usually will request IBI by calling
>>>>      i3c_device_request_ibi() during probe of slave driver.
>>>> 2. Since master code trying to access IBI Variable for the particular
>>>>      device instance before actually it initialized by slave driver,
>>>>      due to this randomly accessing the address and causing kernel panic.
>>>> 3. i3c_device_request_ibi() function invoked by the slave driver where
>>>>      dev->ibi = ibi; assigned as part of function call
>>>>      i3c_dev_request_ibi_locked().
>>>> 4. But when IBI request sent by slave device, master code  trying to access
>>>>      this variable before its initialized due to this race condition
>>>>      situation kernel panic happened.
>>>
>>> How about commit message as:
>>>
>>> The I3C master driver may receive an IBI from a target device that has
>>> not been probed yet. In such cases, the master calls
>>> `i3c_master_queue_ibi()` to queue an IBI work task, leading to "Unable
>>> to handle kernel read from unreadable memory" and resulting in a kernel
>> panic.
>>>
>>> Typical IBI handling flow:
>>> 1. The I3C master scans target devices and probes their respective drivers.
>>> 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
>>>      and assigns `dev->ibi = ibi`.
>>> 3. The I3C master receives an IBI from the target device and calls
>>>      `i3c_master_queue_ibi()` to queue the target device driver's IBI handler
>>>      task.
>>>
>>> However, since target device events are asynchronous to the I3C probe
>>> sequence, step 3 may occur before step 2, causing `dev->ibi` to be
>>> `NULL`, leading to a kernel panic.
>>>
>>> Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent
>>> accessing an uninitialized `dev->ibi`, ensuring stability.
>>>
>>>>
>>>> Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
>>>> Cc: stable at vger.kernel.org
>>>> Link:
>>>> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flor
>>>> e.kernel.org%2Flkml%2FZ9gjGYudiYyl3bSe%40lizhi-Precision-Tower-
>> 5810%2
>>>>
>> F&data=05%7C02%7Cmanjunatha.venkatesh%40nxp.com%7Ceda8be8c7abc4
>> 3b4ab9
>>>>
>> 608dd6c31c8e7%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6387
>> 856832
>>>>
>> 77582903%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYi
>> OiIwLjAu
>>>>
>> MDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%
>> 7C%7C
>>>>
>> &sdata=oyc9Wv%2Fj8HMRFIiIGL9nIw0XvI6FsLK2SvsQJ55H7XI%3D&reserved=
>> 0
>>>> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
>>>> ---
>>>> Changes since v4:
>>>>     - Fix added at generic places master.c which is applicable for all
>>>> platforms
>>>>
>>>>    drivers/i3c/master.c | 3 +++
>>>>    1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index
>>>> d5dc4180afbc..c65006aa0684 100644
>>>> --- a/drivers/i3c/master.c
>>>> +++ b/drivers/i3c/master.c
>>>> @@ -2561,6 +2561,9 @@ static void
>> i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
>>>>     */
>>>>    void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot
>> *slot)
>>>>    {
>>>> +    if (!dev->ibi || !slot)
>>>> +            return;
>>>> +
>> 1. Shouldn't this be a Logical AND ? what if slot is non NULL but the IBI is
>> NULL ?
>>
> [Manjunatha Venkatesh] : I think Logical OR operation is correct,
>   Since if any one of the variable is NULL need to return before accessing those variables.
I agree, i was incorrect.
>> 2. This being void function, it doesn't say anything to caller if it's successful or
>> failed ? Should we make this non void function ?
>> if not, i am thinking it may run into multiple attempts, no log too.
> [Manjunatha Venkatesh] : If required we can add error print log, Others please confirm your opinion on this.
>>>>       atomic_inc(&dev->ibi->pending_ibis);
>>>>       queue_work(dev->ibi->wq, &slot->work);
>>>>    }
>>>> --
>>>> 2.46.1
>>>>
>>>
> 



From quic_msavaliy at quicinc.com  Wed Mar 26 07:16:38 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 19:46:38 +0530
Subject: [PATCH v2 0/3] Add Qualcomm i3c master controller driver support
Message-ID: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>

This patchset adds i3c controller support for the qualcomm's QUPV3 based 
Serial engine (SE) hardware controller. 

The I3C SE(Serial Engine) controller implements I3C master functionality
as defined in the MIPI Specifications for I3C, Version 1.0. 

This patchset was tested on Kailua SM8550 MTP device and data transfer
has been tested in I3C SDR mode.


Features tested and supported :
  Standard CCC commands.
  I3C SDR mode private transfers in PIO mode.
  I2C transfers in PIO mode.

Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
----
Link to v1: https://lore.kernel.org/lkml/20250205143109.2955321-1-quic_msavaliy at quicinc.com/

Changes in V3:
 - Removed bindings word from subject title of dt-bindings patch.
 - Use Controller name instead of Master as per MIPI alliance guidance and updated title.
 - Added description field for the i3c master into dt-bindings.
 - Changed title to "Qualcomm Geni based QUP I3C Controller".
 - Changed compatible to "qcom,i3c-master" matching dt-binding file and driver.
 - Changed "interrupts-extended" property to "interrupts" as suggested by krzysztof.
 - Dropped reg, clock minItems and added maxItems similar to other dt-bindings.
 - Removed clock-names property from dt-bindings suggested by Krzysztof, Bjorn.
 - Set "se-clock-frequency"  set it within drivers as suggested by Rob.
 - Removed "dfs-index" property and manage it within driver as suggested by Rob.
 - Removed "interrupts" maxItems as we need only 1 interrupt in this change.
 - Added comment for mutex lock mentioning purpose in sruct geni_i3c_dev .
 - Return with dev_err_probe() instead of error log and then return -ENXIO from probe().
 - Removed dev_dbg(&pdev->dev, "Geni I3C probed\n") print log as suggested by krzysztof.
 - Removed CONFIG_PM and else part around runtime PM operations following other drivers.
 - Removed Module alias MODULE_ALIAS("platform:geni_i3c_master").
 - Replaced MASTER with GENI in the Title of MAINTAINER file.
 - Removed duplications from the commit log and removed unwanted statement.
 - Formatted license and copyright similar to other files.
 - Removed SLV_ADDR_MSK and used FIELD_PREP/FIELD_GET instead of local bit shifting operations.
 - Used direct bit positions for each internal Error bit of DM_I3C_CB_ERR.
 - Removed Unused SLV_ADDR_MSK and added SLAVE_ADDR_MASK as GENMASK(15,9).
 - Renamed spinlock as irq_lock.
 - Removed dfs_idx from geni_i3c_dev and made it local inside qcom_geni_i3c_conf().
 - Use boolean cur_is_write instead of enum i3c_trans_dir/gi3c->cur_rnw.
 - Used DECLARE_BITMAP and related set/clear_bit APIs instead of manual operation.
 - Inline the error messages from geni_i3c_err_log directly to improve readability
   and avoid unnecessary jumps caused by the geni_i3c_err_code enum.
 - Converted clk_src_freq of struct geni_i3c_clk_settings to HZ.
 - Removed unwanted debug logs from geni_i3c_clk_map_idx().
 - clk_od_fld and itr renamed to clk_od_idx and clk_idx respectively to map actual usage.
 - Added se-clock-frequency to be read from DTSI, if none, then default to 100MHz source.
 - Changed Error log during bus_init() if OD and PP mode frequencies avaiable or not.
 - Used FIELD_PREP and standard BIT operations inside qcom_geni_i3c_conf() instead manual shifting.
 - Removed unnecessary parentheses from geni_i3c_irq().
 - Moved geni_se_abort_m_cmd() implementation to a new helper function geni_i3c_abort_xfer().
 - Removed unwanted reinitialization of cur_len, cur_idx, cur_rnw from _i3c_geni_execute_command().
 - Removed dev_dbg logs which were meant for developmental debug purpose.
 - Removed unnecessary check nxfers <= 0 from geni_i3c_master_priv_xfers().
 - Replaced devm_kzalloc() by kzalloc() inside geni_i3c_master_attach_i2c_dev() to use
   kfree() from counter function geni_i3c_master_detach_i2c_dev().
 - Replaced devm_kzalloc() by kzalloc() inside geni_i3c_master_attach_i3c_dev() to use
   kfree() from counter function geni_i3c_master_detach_i3c_dev().   
 - Removed geni_i3c_master_reattach_i3c_dev() function as default returns 0.
 - Removed goto label from geni_i3c_master_bus_init() by reorganizing internal code.
   Also used i3c_geni_runtime_get_mutex_lock()/unlock() instead of get_sync() similar to other places.
 - Added indent to fallthrough for switch cases inside geni_i3c_master_supports_ccc_cmd().
 - Renamed i3c_geni_rsrcs_init() to i3c_geni_resources_init().
 - Changed devm_ioremap_resource() to devm_platform_ioremap_resource(), removed platform_get_resource().
 - Replaced dev_err() with dev_err_probe() for core clock named se-clk.
 - Removed development debug prints for votings from gi3c->se.icc_paths.
 - Probe(): Changed all dev_err() to dev_error_probe() with proper log messages.
 - Probe(): Moved static resource allocation immediately after gi3c object allocation.
 - Probe(): Disabled PM if i3c master registration fails during probe().
 - Remove(): Unregister master first and then added Disable of PM as opposite to probe().
 - Removed I3C_CCC_ENTHDR support as it's not supported.
---
Mukesh Kumar Savaliya (3):
  dt-bindings: i3c: Add Qualcomm I3C master controller
  i3c: master: Add Qualcomm I3C controller driver
  MAINTAINERS: Add maintainer for Qualcomm's I3C driver

 .../bindings/i3c/qcom,i3c-master.yaml         |   60 +
 MAINTAINERS                                   |    8 +
 drivers/i3c/master/Kconfig                    |   12 +
 drivers/i3c/master/Makefile                   |    1 +
 drivers/i3c/master/qcom-i3c-master.c          | 1107 +++++++++++++++++
 5 files changed, 1188 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
 create mode 100644 drivers/i3c/master/qcom-i3c-master.c

-- 
2.25.1



From quic_msavaliy at quicinc.com  Wed Mar 26 07:16:39 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 19:46:39 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master controller
In-Reply-To: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
Message-ID: <20250326141641.3471906-2-quic_msavaliy@quicinc.com>

Add device tree bindings for the Qualcomm I3C controller. This includes
the necessary documentation and properties required to describe the
hardware in the device tree.

Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
---
 .../bindings/i3c/qcom,i3c-master.yaml         | 60 +++++++++++++++++++
 1 file changed, 60 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml

diff --git a/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
new file mode 100644
index 000000000000..af6b393f2327
--- /dev/null
+++ b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i3c/qcom,i3c-master.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Geni based QUP I3C Controller
+
+maintainers:
+  - Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
+
+description:
+  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
+  bus mode (I2C and I3C target devices on same i3c bus). It also supports
+  hotjoin, IBI mechanism.
+
+  I3C Controller nodes must be child of GENI based Qualcomm Universal
+  Peripharal. Please refer GENI based QUP wrapper controller node bindings
+  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
+
+allOf:
+  - $ref: i3c.yaml#
+
+properties:
+  compatible:
+    const: qcom,i3c-master
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - interrupts
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/qcom,sm8550-gcc.h>
+
+    i3c at 884000 {
+        compatible = "qcom,i3c-master";
+        reg = <0x00884000 0x4000>;
+        clocks = <&gcc GCC_QUPV3_WRAP2_S1_CLK>;
+        clock-names = "se-clk";
+        interrupts = <&intc GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+        #address-cells = <3>;
+        #size-cells = <0>;
+    };
+...
-- 
2.25.1



From quic_msavaliy at quicinc.com  Wed Mar 26 07:16:40 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 19:46:40 +0530
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
Message-ID: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>

Add support for the Qualcomm I3C controller driver, which implements
I3C master functionality as defined in the MIPI Alliance Specification
for I3C, Version 1.0.

This driver supports master role in SDR mode.

Unlike some other I3C master controllers, this implementation
does not support In-Band Interrupts (IBI) and Hot-join requests.

Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
---
 drivers/i3c/master/Kconfig           |   12 +
 drivers/i3c/master/Makefile          |    1 +
 drivers/i3c/master/qcom-i3c-master.c | 1107 ++++++++++++++++++++++++++
 3 files changed, 1120 insertions(+)
 create mode 100644 drivers/i3c/master/qcom-i3c-master.c

diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 77da199c7413..5370cadfe236 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -44,6 +44,18 @@ config SVC_I3C_MASTER
 	help
 	  Support for Silvaco I3C Dual-Role Master Controller.
 
+config QCOM_I3C_MASTER
+	tristate "Qualcomm Technologies Inc.'s I3C Master controller driver"
+	depends on I3C
+	help
+	This driver supports QUPV3 GENI based I3C controller in master
+	mode on the Qualcomm Technologies Inc.s SoCs. If you say yes to
+	this option, support will be included for the built-in I3C interface
+	on the Qualcomm Technologies Inc.s SoCs.
+
+	This driver can also be built as a module.  If so, the module
+	will be called qcom-i3c-master.
+
 config MIPI_I3C_HCI
 	tristate "MIPI I3C Host Controller Interface driver (EXPERIMENTAL)"
 	depends on I3C
diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
index 3e97960160bc..f6670a63b34f 100644
--- a/drivers/i3c/master/Makefile
+++ b/drivers/i3c/master/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DW_I3C_MASTER)		+= dw-i3c-master.o
 obj-$(CONFIG_AST2600_I3C_MASTER)	+= ast2600-i3c-master.o
 obj-$(CONFIG_SVC_I3C_MASTER)		+= svc-i3c-master.o
 obj-$(CONFIG_MIPI_I3C_HCI)		+= mipi-i3c-hci/
+obj-$(CONFIG_QCOM_I3C_MASTER)		+= qcom-i3c-master.o
diff --git a/drivers/i3c/master/qcom-i3c-master.c b/drivers/i3c/master/qcom-i3c-master.c
new file mode 100644
index 000000000000..54778a6baa70
--- /dev/null
+++ b/drivers/i3c/master/qcom-i3c-master.c
@@ -0,0 +1,1107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Author: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/i3c/master.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/geni-se.h>
+
+#define SE_I3C_SCL_HIGH                 0x268
+#define SE_I3C_TX_TRANS_LEN             0x26C
+#define SE_I3C_RX_TRANS_LEN             0x270
+#define SE_I3C_DELAY_COUNTER            0x274
+#define SE_I2C_SCL_COUNTERS             0x278
+#define SE_I3C_SCL_CYCLE                0x27C
+#define SE_GENI_HW_IRQ_EN               0x920
+#define SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE 0x924
+#define SE_GENI_HW_IRQ_CMD_PARAM_0      0x930
+
+/* HW I3C IBI interrupt enable */
+#define M_IBI_IRQ_EN BIT(0)
+
+/* M_IBI_IRQ_IGNORE */
+#define M_IBI_IRQ_IGNORE BIT(0)
+
+/* SE_GENI_M_CLK_CFG field shifts */
+#define	CLK_DIV_VALUE_MASK	GENMASK(23, 4)
+#define SER_CLK_EN		BIT(0)
+
+/* SE_GENI_HW_IRQ_CMD_PARAM_0 field bits */
+#define M_IBI_IRQ_PARAM_7E BIT(0)
+#define M_IBI_IRQ_PARAM_STOP_STALL BIT(1)
+/* SE_I2C_SCL_COUNTERS field shifts */
+#define I2C_SCL_HIGH_COUNTER_MASK	GENMASK(29, 20)
+#define I2C_SCL_LOW_COUNTER_MASK	GENMASK(19, 10)
+#define I2C_SCL_CYCLE_COUNTER_MASK	GENMASK(9, 0)
+
+#define SE_I3C_ERR  (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
+	M_CMD_ABORT_EN | M_GP_IRQ_0_EN | M_GP_IRQ_1_EN | M_GP_IRQ_2_EN | \
+	M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
+
+/* M_CMD OP codes for I2C/I3C */
+#define I3C_READ_IBI_HW          0
+#define I2C_WRITE                1
+#define I2C_READ                 2
+#define I2C_WRITE_READ           3
+#define I2C_ADDR_ONLY            4
+#define I3C_INBAND_RESET         5
+#define I2C_BUS_CLEAR            6
+#define I2C_STOP_ON_BUS          7
+#define I3C_HDR_DDR_EXIT         8
+#define I3C_PRIVATE_WRITE        9
+#define I3C_PRIVATE_READ         10
+#define I3C_HDR_DDR_WRITE        11
+#define I3C_HDR_DDR_READ         12
+#define I3C_DIRECT_CCC_ADDR_ONLY 13
+#define I3C_BCAST_CCC_ADDR_ONLY  14
+#define I3C_READ_IBI             15
+#define I3C_BCAST_CCC_WRITE      16
+#define I3C_DIRECT_CCC_WRITE     17
+#define I3C_DIRECT_CCC_READ      18
+
+/* M_CMD params for I3C */
+#define PRE_CMD_DELAY          BIT(0)
+#define TIMESTAMP_BEFORE       BIT(1)
+#define STOP_STRETCH           BIT(2)
+#define TIMESTAMP_AFTER        BIT(3)
+#define POST_COMMAND_DELAY     BIT(4)
+#define IGNORE_ADD_NACK        BIT(6)
+#define READ_FINISHED_WITH_ACK BIT(7)
+#define CONTINUOUS_MODE_DAA    BIT(8)
+
+#define SLAVE_ADDR_MASK           GENMASK(15, 9)
+#define SLV_ADDR_SHFT          9
+
+#define CCC_HDR_CMD_MSK        GENMASK(23, 16)
+#define CCC_HDR_CMD_SHFT       16
+#define IBI_NACK_TBL_CTRL      BIT(24)
+#define USE_7E                 BIT(25)
+#define BYPASS_ADDR_PHASE      BIT(26)
+
+/* GSI callback error fields - DMA_TX_IRQ_STAT */
+#define GP_IRQ0	BIT(5)
+#define GP_IRQ1	BIT(6)
+#define GP_IRQ2	BIT(7)
+#define GP_IRQ3	BIT(8)
+#define GP_IRQ4	BIT(9)
+#define GP_IRQ5	BIT(10)
+#define DM_I3C_CB_ERR   GENMASK(10, 5)
+
+#define I3C_AUTO_SUSPEND_DELAY  250
+#define KHZ(freq)               (1000 * (freq))
+#define PACKING_BYTES_PW        4
+#define XFER_TIMEOUT            250
+#define DFS_INDEX_MAX           7
+
+#define I3C_ADDR_MASK 0x7f
+
+enum geni_i3c_err_code {
+	RD_TERM,
+	NACK,
+	CRC_ERR,
+	BUS_PROTO,
+	NACK_7E,
+	NACK_IBI,
+	GENI_OVERRUN,
+	GENI_ILLEGAL_CMD,
+	GENI_ABORT_DONE,
+	GENI_TIMEOUT,
+};
+
+enum i3c_bus_phase {
+	OPEN_DRAIN_MODE  = 0,
+	PUSH_PULL_MODE   = 1
+};
+
+struct geni_i3c_dev {
+	struct geni_se se;
+	unsigned int tx_wm;
+	int irq;
+	int err;
+	struct i3c_master_controller ctrlr;
+	struct completion done;
+	/* Protects per device CCC command or transfer from get_mutex_lock()/unlock() wrapper */
+	struct mutex lock;
+	/* Per device protection between process and IRQ context */
+	spinlock_t irq_lock;
+	u32 clk_src_freq;
+	u8 *cur_buf;
+	bool cur_is_write;
+	int cur_len;
+	int cur_idx;
+	//unsigned long newaddrslots[(I3C_ADDR_MASK + 1) / BITS_PER_LONG];
+	DECLARE_BITMAP(newaddrslots, 64);
+
+	const struct geni_i3c_clk_settings *clk_cfg;
+	const struct geni_i3c_clk_settings *clk_od_cfg;
+};
+
+struct geni_i3c_i2c_dev_data {
+	u32 ibi_keeping;  /* Plan to save IBI information, keep as dummy for now */
+};
+
+struct geni_i3c_xfer_params {
+	enum geni_se_xfer_mode mode;
+	u32 m_cmd;
+	u32 m_param;
+};
+
+static inline struct geni_i3c_dev *to_geni_i3c_master(struct i3c_master_controller
+							*master)
+{
+	return container_of(master, struct geni_i3c_dev, ctrlr);
+}
+
+struct geni_i3c_clk_settings {
+	u32 clk_freq_out;
+	u32 clk_src_freq;
+	u8  clk_div;
+	u8  i2c_t_high_cnt;
+	u8  i2c_t_low_cnt;
+	u8  i3c_t_high_cnt;
+	u8  i3c_t_cycle_cnt;
+	u8  i2c_t_cycle_cnt;
+};
+
+/*
+ * Hardware uses the underlying formula to calculate time periods of
+ * SCL clock cycle. Firmware uses some additional cycles excluded from the
+ * below formula and it is confirmed that the time periods are within
+ * specification limits.
+ *
+ * time of high period of I2C SCL:
+ *         i2c_t_high = (i2c_t_high_cnt * clk_div) / source_clock
+ * time of low period of I2C SCL:
+ *         i2c_t_low = (i2c_t_low_cnt * clk_div) / source_clock
+ * time of full period of I2C SCL:
+ *         i2c_t_cycle = (i2c_t_cycle_cnt * clk_div) / source_clock
+ * time of high period of I3C SCL:
+ *         i3c_t_high = (i3c_t_high_cnt * clk_div) / source_clock
+ * time of full period of I3C SCL:
+ *         i3c_t_cycle = (i3c_t_cycle_cnt * clk_div) / source_clock
+ * clk_freq_out = t / t_cycle
+ */
+static const struct geni_i3c_clk_settings geni_i3c_clk_map[] = {
+/* op-freq,  src-freq,  div,  i2c_high,  i2c_low, i3c_high, i3c_cyc i2c_cyc */
+	{ KHZ(100),    KHZ(19200), 1, 76, 90, 7, 8, 192},
+	{ KHZ(400),    KHZ(19200), 1, 12, 24, 7, 8, 48},
+	{ KHZ(1000),   KHZ(19200), 1,  4,  9, 7, 0, 19},
+	{ KHZ(12500), KHZ(100000), 1, 45, 63, 6, 7, 110},
+};
+
+static int geni_i3c_clk_map_idx(struct geni_i3c_dev *gi3c)
+{
+	const struct geni_i3c_clk_settings *clk_idx = geni_i3c_clk_map;
+	struct i3c_master_controller *m = &gi3c->ctrlr;
+	struct i3c_bus *bus = i3c_master_get_bus(m);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(geni_i3c_clk_map); i++, clk_idx++) {
+		if ((!bus || clk_idx->clk_freq_out == bus->scl_rate.i3c) &&
+		    clk_idx->clk_src_freq == gi3c->clk_src_freq) {
+			gi3c->clk_cfg = clk_idx;
+		}
+
+		if (clk_idx->clk_freq_out == bus->scl_rate.i2c)
+			gi3c->clk_od_cfg = clk_idx;
+	}
+
+	if (!gi3c->clk_cfg || !gi3c->clk_od_cfg)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void set_new_addr_slot(unsigned long *addrslot, u8 addr)
+{
+	if (addr > I3C_ADDR_MASK)
+		return;
+
+	set_bit(addr, addrslot);
+}
+
+static void clear_new_addr_slot(unsigned long *addrslot, u8 addr)
+{
+	if (addr > I3C_ADDR_MASK)
+		return;
+
+	clear_bit(addr, addrslot);
+}
+
+static bool is_new_addr_slot_set(unsigned long *addrslot, u8 addr)
+{
+	if (addr > I3C_ADDR_MASK)
+		return false;
+
+	return test_bit(addr, addrslot);
+}
+
+static void qcom_geni_i3c_conf(struct geni_i3c_dev *gi3c, enum i3c_bus_phase bus_phase)
+{
+	const struct geni_i3c_clk_settings *clk_idx = gi3c->clk_cfg;
+	unsigned long freq;
+	u32 val, dfs_idx;
+	int ret;
+
+	if (bus_phase == OPEN_DRAIN_MODE)
+		clk_idx = gi3c->clk_od_cfg;
+
+	ret = geni_se_clk_freq_match(&gi3c->se, clk_idx->clk_src_freq,
+				     &dfs_idx, &freq, false);
+	if (ret)
+		dfs_idx = 0;
+
+	writel_relaxed(dfs_idx, gi3c->se.base + SE_GENI_CLK_SEL);
+
+	val = FIELD_PREP(CLK_DIV_VALUE_MASK, clk_idx->clk_div);
+	val |= SER_CLK_EN;
+	writel_relaxed(val, gi3c->se.base + GENI_SER_M_CLK_CFG);
+
+	val = FIELD_PREP(I2C_SCL_HIGH_COUNTER_MASK, clk_idx->i2c_t_high_cnt);
+	val |= FIELD_PREP(I2C_SCL_LOW_COUNTER_MASK, clk_idx->i2c_t_low_cnt);
+	val |= FIELD_PREP(I2C_SCL_CYCLE_COUNTER_MASK, clk_idx->i2c_t_cycle_cnt);
+	writel_relaxed(val, gi3c->se.base + SE_I2C_SCL_COUNTERS);
+
+	writel_relaxed(clk_idx->i3c_t_cycle_cnt, gi3c->se.base + SE_I3C_SCL_CYCLE);
+	writel_relaxed(clk_idx->i3c_t_high_cnt, gi3c->se.base + SE_I3C_SCL_HIGH);
+
+	writel_relaxed(M_IBI_IRQ_IGNORE, gi3c->se.base + SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE);
+
+	val = M_IBI_IRQ_PARAM_STOP_STALL | M_IBI_IRQ_PARAM_7E;
+	writel_relaxed(val, gi3c->se.base + SE_GENI_HW_IRQ_CMD_PARAM_0);
+
+	writel_relaxed(M_IBI_IRQ_EN, gi3c->se.base + SE_GENI_HW_IRQ_EN);
+}
+
+static void geni_i3c_handle_err(struct geni_i3c_dev *gi3c, u32 status)
+{
+	dev_dbg(gi3c->se.dev, "len:%d, %s\n",
+		gi3c->cur_len, gi3c->cur_is_write ? "write" : "read");
+
+	if (status & M_GP_IRQ_0_EN) {
+		gi3c->err = -EINVAL;
+		dev_dbg(gi3c->se.dev, "%s\n", "I3C slave early read termination");
+	}
+	if (status & M_GP_IRQ_1_EN) {
+		gi3c->err = -ENOTCONN;
+		dev_dbg(gi3c->se.dev, "%s\n", "NACK: slave unresponsive, check power/reset");
+	}
+	if (status & M_GP_IRQ_2_EN) {
+		gi3c->err = -EINVAL;
+		dev_dbg(gi3c->se.dev, "%s\n", "CRC or parity error");
+	}
+	if (status & M_GP_IRQ_3_EN) {
+		gi3c->err = -EPROTO;
+		dev_dbg(gi3c->se.dev, "%s\n", "Bus proto Error, noisy/unexpected start/stop");
+	}
+	if (status & M_GP_IRQ_4_EN) {
+		gi3c->err = -EBUSY;
+		dev_dbg(gi3c->se.dev, "%s\n", "NACK on 7E, unexpected protocol error");
+	}
+	if (status & M_GP_IRQ_5_EN) {
+		gi3c->err = -EINVAL;
+		dev_dbg(gi3c->se.dev, "%s\n", "NACK on IBI");
+	}
+	if (status & M_CMD_OVERRUN_EN) {
+		gi3c->err = -EIO;
+		dev_dbg(gi3c->se.dev, "%s\n", "Cmd overrun, check GENI cmd-state machine");
+	}
+	if (status & M_ILLEGAL_CMD_EN) {
+		gi3c->err = -EILSEQ;
+		dev_dbg(gi3c->se.dev, "%s\n", "Illegal cmd, check GENI cmd-state machine");
+	}
+	if (status & M_CMD_ABORT_EN) {
+		gi3c->err = -ETIMEDOUT;
+		dev_dbg(gi3c->se.dev, "%s\n", "Abort after timeout successful");
+	}
+	if (status & GENI_TIMEOUT) {
+		gi3c->err = -ETIMEDOUT;
+		dev_dbg(gi3c->se.dev, "%s\n", "I3C transaction timed out");
+	}
+}
+
+static irqreturn_t geni_i3c_irq(int irq, void *dev)
+{
+	u32 m_stat_mask, dm_tx_st, dm_rx_st, m_stat, rx_st, dma;
+	struct geni_i3c_dev *gi3c = dev;
+	unsigned long flags;
+	int j;
+
+	m_stat = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_STATUS);
+	m_stat_mask = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_EN);
+	rx_st = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFO_STATUS);
+	dm_tx_st = readl_relaxed(gi3c->se.base + SE_DMA_TX_IRQ_STAT);
+	dm_rx_st = readl_relaxed(gi3c->se.base + SE_DMA_RX_IRQ_STAT);
+	dma = readl_relaxed(gi3c->se.base + SE_GENI_DMA_MODE_EN);
+
+	spin_lock_irqsave(&gi3c->irq_lock, flags);
+
+	if (m_stat & SE_I3C_ERR || dm_rx_st & DM_I3C_CB_ERR) {
+		geni_i3c_handle_err(gi3c, m_stat);
+		/* Disable the TX Watermark interrupt to stop TX */
+		if (!dma)
+			writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
+		goto irqret;
+	}
+
+	if (dma) {
+		dev_dbg(gi3c->se.dev, "i3c dma tx:0x%x, dma rx:0x%x\n", dm_tx_st, dm_rx_st);
+		goto irqret;
+	}
+
+	if ((m_stat &
+		(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) &&
+		!gi3c->cur_is_write && gi3c->cur_buf) {
+		u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
+
+		for (j = 0; j < rxcnt; j++) {
+			u32 val;
+			int p = 0;
+
+			val = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFOn);
+			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
+				gi3c->cur_buf[gi3c->cur_idx++] = val & 0xff;
+				val >>= 8;
+				p++;
+			}
+			if (gi3c->cur_idx == gi3c->cur_len)
+				break;
+		}
+	} else if (m_stat & M_TX_FIFO_WATERMARK_EN &&
+		gi3c->cur_is_write && gi3c->cur_buf) {
+		for (j = 0; j < gi3c->tx_wm; j++) {
+			u32 temp;
+			u32 val = 0;
+			int p = 0;
+
+			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
+				temp = gi3c->cur_buf[gi3c->cur_idx++];
+				val |= temp << (p * 8);
+				p++;
+			}
+
+			writel_relaxed(val, gi3c->se.base + SE_GENI_TX_FIFOn);
+			if (gi3c->cur_idx == gi3c->cur_len) {
+				writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
+				break;
+			}
+		}
+	}
+
+irqret:
+	if (m_stat)
+		writel_relaxed(m_stat, gi3c->se.base + SE_GENI_M_IRQ_CLEAR);
+
+	if (dma) {
+		if (dm_tx_st)
+			writel_relaxed(dm_tx_st, gi3c->se.base + SE_DMA_TX_IRQ_CLR);
+		if (dm_rx_st)
+			writel_relaxed(dm_rx_st, gi3c->se.base + SE_DMA_RX_IRQ_CLR);
+	}
+
+	/* if this is err with done-bit not set, handle that through timeout. */
+	if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN) {
+		writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
+		complete(&gi3c->done);
+	} else if (dm_tx_st & TX_DMA_DONE || dm_rx_st & RX_DMA_DONE	||
+		dm_rx_st & RX_RESET_DONE) {
+		complete(&gi3c->done);
+	}
+
+	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
+	return IRQ_HANDLED;
+}
+
+static int i3c_geni_runtime_get_mutex_lock(struct geni_i3c_dev *gi3c)
+{
+	int ret;
+
+	mutex_lock(&gi3c->lock);
+	reinit_completion(&gi3c->done);
+	ret = pm_runtime_get_sync(gi3c->se.dev);
+	if (ret < 0) {
+		dev_err(gi3c->se.dev, "error turning on SE resources:%d\n", ret);
+		pm_runtime_put_noidle(gi3c->se.dev);
+		/* Set device in suspended since resume failed */
+		pm_runtime_set_suspended(gi3c->se.dev);
+		mutex_unlock(&gi3c->lock);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void i3c_geni_runtime_put_mutex_unlock(struct geni_i3c_dev *gi3c)
+{
+	pm_runtime_mark_last_busy(gi3c->se.dev);
+	pm_runtime_put_autosuspend(gi3c->se.dev);
+	mutex_unlock(&gi3c->lock);
+}
+
+static void geni_i3c_abort_xfer(struct geni_i3c_dev *gi3c)
+{
+	unsigned long time_remaining;
+	unsigned long flags;
+
+	reinit_completion(&gi3c->done);
+	spin_lock_irqsave(&gi3c->irq_lock, flags);
+	geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
+	geni_se_abort_m_cmd(&gi3c->se);
+	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
+	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
+	if (!time_remaining)
+		dev_err(gi3c->se.dev, "Timeout abort_m_cmd\n");
+}
+
+static int _i3c_geni_execute_command(struct geni_i3c_dev *gi3c, struct geni_i3c_xfer_params *xfer)
+{
+	bool is_write = gi3c->cur_is_write;
+	dma_addr_t tx_dma = 0, rx_dma = 0;
+	unsigned long time_remaining;
+	u32 len = gi3c->cur_len;
+	int ret;
+
+	geni_se_select_mode(&gi3c->se, xfer->mode);
+
+	gi3c->err = 0;
+	gi3c->cur_idx = 0;
+
+	if (!is_write) {
+		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x READ len:%d\n",
+			xfer->m_cmd, xfer->m_param, len);
+		writel_relaxed(len, gi3c->se.base + SE_I3C_RX_TRANS_LEN);
+		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
+		if (xfer->mode == GENI_SE_DMA) {
+			ret = geni_se_rx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &rx_dma);
+			if (ret) {
+				xfer->mode = GENI_SE_FIFO;
+				geni_se_select_mode(&gi3c->se, xfer->mode);
+			}
+		}
+	} else {
+		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x WRITE len:%d\n",
+			xfer->m_cmd, xfer->m_param, len);
+
+		writel_relaxed(len, gi3c->se.base + SE_I3C_TX_TRANS_LEN);
+		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
+
+		if (xfer->mode == GENI_SE_DMA) {
+			ret = geni_se_tx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &tx_dma);
+			if (ret) {
+				xfer->mode = GENI_SE_FIFO;
+				geni_se_select_mode(&gi3c->se, xfer->mode);
+			}
+		}
+
+		if (xfer->mode == GENI_SE_FIFO && len > 0) /* Get FIFO IRQ */
+			writel_relaxed(1, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
+	}
+
+	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
+	if (!time_remaining) {
+		unsigned long flags;
+
+		dev_dbg(gi3c->se.dev, "Timeout completing FIFO transfer\n");
+		spin_lock_irqsave(&gi3c->irq_lock, flags);
+		geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
+		gi3c->cur_buf = NULL;
+		spin_unlock_irqrestore(&gi3c->irq_lock, flags);
+		geni_i3c_abort_xfer(gi3c);
+	}
+
+	if (xfer->mode == GENI_SE_DMA) {
+		if (gi3c->err) {
+			if (is_write)
+				writel_relaxed(1, gi3c->se.base + SE_DMA_TX_FSM_RST);
+			else
+				writel_relaxed(1, gi3c->se.base + SE_DMA_RX_FSM_RST);
+
+			time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
+			dev_dbg(gi3c->se.dev, "Timeout completing DMA transfer\n");
+		}
+		geni_se_rx_dma_unprep(&gi3c->se, rx_dma, len);
+		geni_se_tx_dma_unprep(&gi3c->se, tx_dma, len);
+	}
+
+	ret = gi3c->err;
+	if (gi3c->err)
+		dev_err(gi3c->se.dev, "I3C transaction error :%d\n", gi3c->err);
+
+	gi3c->cur_buf = NULL;
+	gi3c->err = 0;
+
+	return ret;
+}
+
+static int i3c_geni_execute_read_command(struct geni_i3c_dev *gi3c,
+					 struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
+{
+	gi3c->cur_is_write = false;
+	gi3c->cur_buf = buf;
+	gi3c->cur_len = len;
+	return _i3c_geni_execute_command(gi3c, xfer);
+	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);
+}
+
+static int i3c_geni_execute_write_command(struct geni_i3c_dev *gi3c,
+					  struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
+{
+	gi3c->cur_is_write = true;
+	gi3c->cur_buf = buf;
+	gi3c->cur_len = len;
+	return _i3c_geni_execute_command(gi3c, xfer);
+	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);
+}
+
+static void geni_i3c_perform_daa(struct geni_i3c_dev *gi3c)
+{
+	u8 last_dyn_addr = 0;
+	int ret;
+
+	while (1) {
+		u8 rx_buf[8], tx_buf[8];
+		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
+		struct i3c_device_info info = { 0 };
+		struct i3c_dev_desc *i3cdev;
+		bool new_device = true;
+		u64 pid;
+		u8 bcr, dcr, addr;
+
+		xfer.m_cmd = I2C_READ;
+		xfer.m_param = STOP_STRETCH | CONTINUOUS_MODE_DAA | USE_7E;
+		ret = i3c_geni_execute_read_command(gi3c, &xfer, rx_buf, 8);
+		if (ret)
+			break;
+
+		dcr = rx_buf[7];
+		bcr = rx_buf[6];
+		pid = ((u64)rx_buf[0] << 40) |
+			((u64)rx_buf[1] << 32) |
+			((u64)rx_buf[2] << 24) |
+			((u64)rx_buf[3] << 16) |
+			((u64)rx_buf[4] <<  8) |
+			((u64)rx_buf[5]);
+
+		i3c_bus_for_each_i3cdev(&gi3c->ctrlr.bus, i3cdev) {
+			i3c_device_get_info(i3cdev->dev, &info);
+			if (pid == info.pid && dcr == info.dcr && bcr == info.bcr) {
+				new_device = false;
+				addr = (info.dyn_addr) ? info.dyn_addr :
+					info.static_addr;
+				break;
+			}
+		}
+
+		if (new_device) {
+			ret = i3c_master_get_free_addr(&gi3c->ctrlr, last_dyn_addr + 1);
+			if (ret < 0)
+				break;
+			addr = (u8)ret;
+			last_dyn_addr = (u8)ret;
+			set_new_addr_slot(gi3c->newaddrslots, addr);
+		}
+
+		tx_buf[0] = (addr & I3C_ADDR_MASK) << 1;
+		tx_buf[0] |= ~(hweight8(addr & I3C_ADDR_MASK) & 1);
+
+		xfer.m_cmd = I2C_WRITE;
+		xfer.m_param = STOP_STRETCH | BYPASS_ADDR_PHASE | USE_7E;
+
+		ret = i3c_geni_execute_write_command(gi3c, &xfer, tx_buf, 1);
+		if (ret)
+			break;
+	}
+}
+
+static int geni_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
+					struct i3c_ccc_cmd *cmd)
+{
+	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
+	int i, ret;
+
+	if (!(cmd->id & I3C_CCC_DIRECT) && cmd->ndests != 1)
+		return -EINVAL;
+
+	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
+	if (ret)
+		return ret;
+
+	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
+	for (i = 0; i < cmd->ndests; i++) {
+		int stall = (i < (cmd->ndests - 1)) ||
+			(cmd->id == I3C_CCC_ENTDAA);
+		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
+
+		xfer.m_param  = (stall ? STOP_STRETCH : 0);
+		xfer.m_param |= (cmd->id << CCC_HDR_CMD_SHFT);
+		xfer.m_param |= IBI_NACK_TBL_CTRL;
+		if (cmd->id & I3C_CCC_DIRECT) {
+			xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, cmd->dests[i].addr);
+			if (cmd->rnw) {
+				if (i == 0)
+					xfer.m_cmd = I3C_DIRECT_CCC_READ;
+				else
+					xfer.m_cmd = I3C_PRIVATE_READ;
+			} else {
+				if (i == 0)
+					xfer.m_cmd =
+					   (cmd->dests[i].payload.len > 0) ?
+						I3C_DIRECT_CCC_WRITE :
+						I3C_DIRECT_CCC_ADDR_ONLY;
+				else
+					xfer.m_cmd = I3C_PRIVATE_WRITE;
+			}
+		} else {
+			if (cmd->dests[i].payload.len > 0)
+				xfer.m_cmd = I3C_BCAST_CCC_WRITE;
+			else
+				xfer.m_cmd = I3C_BCAST_CCC_ADDR_ONLY;
+		}
+
+		if (i == 0)
+			xfer.m_param |= USE_7E;
+
+		if (cmd->rnw)
+			ret = i3c_geni_execute_read_command(gi3c, &xfer,
+							    cmd->dests[i].payload.data,
+							    cmd->dests[i].payload.len);
+		else
+			ret = i3c_geni_execute_write_command(gi3c, &xfer,
+							     cmd->dests[i].payload.data,
+							     cmd->dests[i].payload.len);
+		if (ret)
+			break;
+
+		if (cmd->id == I3C_CCC_ENTDAA)
+			geni_i3c_perform_daa(gi3c);
+	}
+
+	i3c_geni_runtime_put_mutex_unlock(gi3c);
+	return ret;
+}
+
+static int geni_i3c_master_priv_xfers(struct i3c_dev_desc *dev, struct i3c_priv_xfer *xfers,
+				      int nxfers)
+{
+	struct i3c_master_controller *m = i3c_dev_get_master(dev);
+	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
+	bool use_7e = false;
+	int i, ret;
+
+	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
+	if (ret)
+		return ret;
+
+	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
+
+	for (i = 0; i < nxfers; i++) {
+		bool stall = (i < (nxfers - 1));
+		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
+
+		xfer.m_param  = (stall ? STOP_STRETCH : 0);
+		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, dev->info.dyn_addr);
+		xfer.m_param |= (use_7e) ? USE_7E : 0;
+
+		/* use_7e = true only for last transfer */
+		use_7e = (i == nxfers - 1);
+
+		if (xfers[i].rnw) {
+			xfer.m_cmd = I3C_PRIVATE_READ;
+			ret = i3c_geni_execute_read_command(gi3c, &xfer, (u8 *)xfers[i].data.in,
+							    xfers[i].len);
+		} else {
+			xfer.m_cmd = I3C_PRIVATE_WRITE;
+			ret = i3c_geni_execute_write_command(gi3c, &xfer, (u8 *)xfers[i].data.out,
+							     xfers[i].len);
+		}
+
+		if (ret)
+			break;
+	}
+
+	dev_dbg(gi3c->se.dev, "i3c priv: txn ret:%d\n", ret);
+	i3c_geni_runtime_put_mutex_unlock(gi3c);
+	return ret;
+}
+
+static int geni_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, const struct i2c_msg *msgs, int num)
+{
+	struct i3c_master_controller *m = i2c_dev_get_master(dev);
+	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
+	int i, ret;
+
+	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
+	if (ret)
+		return ret;
+
+	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
+
+	for (i = 0; i < num; i++) {
+		struct geni_i3c_xfer_params xfer;
+
+		xfer.m_cmd    = (msgs[i].flags & I2C_M_RD) ? I2C_READ : I2C_WRITE;
+		xfer.m_param  = (i < (num - 1)) ? STOP_STRETCH : 0;
+		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, msgs[i].addr);
+		xfer.mode     = msgs[i].len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
+		if (msgs[i].flags & I2C_M_RD)
+			ret = i3c_geni_execute_read_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
+		else
+			ret = i3c_geni_execute_write_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
+		if (ret)
+			break;
+	}
+
+	dev_dbg(gi3c->se.dev, "i2c: txn ret:%d\n", ret);
+	i3c_geni_runtime_put_mutex_unlock(gi3c);
+	return ret;
+}
+
+static int geni_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
+{
+	struct geni_i3c_i2c_dev_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_dev_set_master_data(dev, data);
+	return 0;
+}
+
+static void geni_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
+{
+	struct geni_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev);
+
+	i2c_dev_set_master_data(dev, NULL);
+	kfree(data);
+}
+
+static int geni_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
+{
+	struct geni_i3c_i2c_dev_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i3c_dev_set_master_data(dev, data);
+	return 0;
+}
+
+static void geni_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
+{
+	struct geni_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
+
+	i3c_dev_set_master_data(dev, NULL);
+	kfree(data);
+}
+
+static int geni_i3c_master_do_daa(struct i3c_master_controller *m)
+{
+	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
+	u8 addr;
+	int ret;
+
+	ret = i3c_master_entdaa_locked(m);
+	if (ret && ret != I3C_ERROR_M2)
+		return ret;
+
+	for (addr = 0; addr <= I3C_ADDR_MASK; addr++) {
+		if (is_new_addr_slot_set(gi3c->newaddrslots, addr)) {
+			clear_new_addr_slot(gi3c->newaddrslots, addr);
+			i3c_master_add_i3c_dev_locked(m, addr);
+		}
+	}
+
+	return 0;
+}
+
+static int geni_i3c_master_bus_init(struct i3c_master_controller *m)
+{
+	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
+	struct i3c_bus *bus = i3c_master_get_bus(m);
+	struct i3c_device_info info = { };
+	int ret;
+
+	/* Get an address for the master. */
+	ret = i3c_master_get_free_addr(m, 0);
+	if (ret < 0)
+		dev_err(gi3c->se.dev, "%s: error No free addr:%d\n", __func__, ret);
+
+	info.dyn_addr = ret;
+	info.dcr = I3C_DCR_GENERIC_DEVICE;
+	info.bcr = I3C_BCR_I3C_MASTER | I3C_BCR_HDR_CAP;
+	info.pid = 0;
+
+	ret = geni_i3c_clk_map_idx(gi3c);
+	if (ret)
+		dev_err(gi3c->se.dev,
+			"Invalid clk frequency %d Hz src for %ld Hz bus: %d\n",
+			gi3c->clk_src_freq, bus->scl_rate.i3c, ret);
+
+	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
+	if (ret)
+		return ret;
+
+	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
+
+	ret = i3c_master_set_info(&gi3c->ctrlr, &info);
+	i3c_geni_runtime_put_mutex_unlock(gi3c);
+	return ret;
+}
+
+static bool geni_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
+					     const struct i3c_ccc_cmd *cmd)
+{
+	switch (cmd->id) {
+	case I3C_CCC_ENEC(true):
+		fallthrough;
+	case I3C_CCC_ENEC(false):
+		fallthrough;
+	case I3C_CCC_DISEC(true):
+		fallthrough;
+	case I3C_CCC_DISEC(false):
+		fallthrough;
+	case I3C_CCC_ENTAS(0, true):
+		fallthrough;
+	case I3C_CCC_ENTAS(0, false):
+		fallthrough;
+	case I3C_CCC_RSTDAA(true):
+		fallthrough;
+	case I3C_CCC_RSTDAA(false):
+		fallthrough;
+	case I3C_CCC_ENTDAA:
+		fallthrough;
+	case I3C_CCC_SETMWL(true):
+		fallthrough;
+	case I3C_CCC_SETMWL(false):
+		fallthrough;
+	case I3C_CCC_SETMRL(true):
+		fallthrough;
+	case I3C_CCC_SETMRL(false):
+		fallthrough;
+	case I3C_CCC_DEFSLVS:
+		fallthrough;
+	case I3C_CCC_SETDASA:
+		fallthrough;
+	case I3C_CCC_SETNEWDA:
+		fallthrough;
+	case I3C_CCC_GETMWL:
+		fallthrough;
+	case I3C_CCC_GETMRL:
+		fallthrough;
+	case I3C_CCC_GETPID:
+		fallthrough;
+	case I3C_CCC_GETBCR:
+		fallthrough;
+	case I3C_CCC_GETDCR:
+		fallthrough;
+	case I3C_CCC_GETSTATUS:
+		fallthrough;
+	case I3C_CCC_GETACCMST:
+		fallthrough;
+	case I3C_CCC_GETMXDS:
+		fallthrough;
+	case I3C_CCC_GETHDRCAP:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+static const struct i3c_master_controller_ops geni_i3c_master_ops = {
+	.bus_init = geni_i3c_master_bus_init,
+	.bus_cleanup = NULL,
+	.do_daa = geni_i3c_master_do_daa,
+	.attach_i3c_dev = geni_i3c_master_attach_i3c_dev,
+	.reattach_i3c_dev = NULL,
+	.detach_i3c_dev = geni_i3c_master_detach_i3c_dev,
+	.attach_i2c_dev = geni_i3c_master_attach_i2c_dev,
+	.detach_i2c_dev = geni_i3c_master_detach_i2c_dev,
+	.supports_ccc_cmd = geni_i3c_master_supports_ccc_cmd,
+	.send_ccc_cmd = geni_i3c_master_send_ccc_cmd,
+	.priv_xfers = geni_i3c_master_priv_xfers,
+	.i2c_xfers = geni_i3c_master_i2c_xfers,
+	.enable_ibi = NULL,
+	.disable_ibi = NULL,
+	.request_ibi = NULL,
+	.free_ibi = NULL,
+	.recycle_ibi_slot = NULL,
+};
+
+static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
+{
+	int ret;
+
+	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(gi3c->se.base))
+		return PTR_ERR(gi3c->se.base);
+
+	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");
+	if (IS_ERR(gi3c->se.clk))
+		return dev_err_probe(&pdev->dev, PTR_ERR(gi3c->se.clk),
+							"Unable to get serial engine core clock: %pe\n",
+							gi3c->se.clk);
+
+	ret = device_property_read_u32(&pdev->dev, "se-clock-frequency", &gi3c->clk_src_freq);
+	if (ret) {
+		dev_info(&pdev->dev, "SE clk freq not specified, default to 100 MHz.\n");
+		/* Default source clock freq is 100Mhz */
+		gi3c->clk_src_freq = KHZ(100000);
+	}
+
+	ret = geni_icc_get(&gi3c->se, NULL);
+	if (ret)
+		return ret;
+
+	/* Set the bus quota to a reasonable value for register access */
+	gi3c->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW;
+	gi3c->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
+	ret = geni_icc_set_bw(&gi3c->se);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int geni_i3c_probe(struct platform_device *pdev)
+{
+	u32 proto, tx_depth, fifo_disable;
+	struct geni_i3c_dev *gi3c;
+	int ret;
+
+	gi3c = devm_kzalloc(&pdev->dev, sizeof(*gi3c), GFP_KERNEL);
+	if (!gi3c)
+		return -ENOMEM;
+
+	gi3c->se.dev = &pdev->dev;
+	gi3c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
+
+	init_completion(&gi3c->done);
+	mutex_init(&gi3c->lock);
+	spin_lock_init(&gi3c->irq_lock);
+	platform_set_drvdata(pdev, gi3c);
+
+	ret = i3c_geni_resources_init(gi3c, pdev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Error Initializing GENI Resources\n");
+
+	gi3c->irq = platform_get_irq(pdev, 0);
+	if (gi3c->irq < 0)
+		return dev_err_probe(&pdev->dev, gi3c->irq, "Error getting IRQ number for I3C\n");
+
+	ret = devm_request_irq(&pdev->dev, gi3c->irq, geni_i3c_irq,
+			       IRQF_NO_AUTOEN, dev_name(&pdev->dev), gi3c);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Error registering core IRQ\n");
+
+	ret = geni_se_resources_on(&gi3c->se);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "Error turning resources ON\n");
+
+	proto = geni_se_read_proto(&gi3c->se);
+	if (proto != GENI_SE_I3C) {
+		geni_se_resources_off(&gi3c->se);
+		return dev_err_probe(&pdev->dev, -ENXIO, "Invalid proto %d\n", proto);
+	}
+
+	fifo_disable = readl_relaxed(gi3c->se.base + GENI_IF_DISABLE_RO);
+	if (fifo_disable) {
+		geni_se_resources_off(&gi3c->se);
+		return dev_err_probe(&pdev->dev, -ENXIO, "GPI DMA mode not supported\n");
+	}
+
+	tx_depth = geni_se_get_tx_fifo_depth(&gi3c->se);
+	gi3c->tx_wm = tx_depth - 1;
+	geni_se_init(&gi3c->se, gi3c->tx_wm, tx_depth);
+	geni_se_config_packing(&gi3c->se, BITS_PER_BYTE, PACKING_BYTES_PW, true, true, true);
+	geni_se_resources_off(&gi3c->se);
+	dev_dbg(&pdev->dev, "i3c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
+
+	pm_runtime_set_autosuspend_delay(gi3c->se.dev, I3C_AUTO_SUSPEND_DELAY);
+	pm_runtime_use_autosuspend(gi3c->se.dev);
+	pm_runtime_set_active(gi3c->se.dev);
+	pm_runtime_enable(gi3c->se.dev);
+
+	ret = i3c_master_register(&gi3c->ctrlr, &pdev->dev, &geni_i3c_master_ops, false);
+	if (ret) {
+		pm_runtime_disable(gi3c->se.dev);
+		pm_runtime_set_suspended(gi3c->se.dev);
+		pm_runtime_dont_use_autosuspend(gi3c->se.dev);
+		return ret;
+	}
+
+	return ret;
+}
+
+static void geni_i3c_remove(struct platform_device *pdev)
+{
+	struct geni_i3c_dev *gi3c = platform_get_drvdata(pdev);
+
+	i3c_master_unregister(&gi3c->ctrlr);
+	pm_runtime_disable(gi3c->se.dev);
+	pm_runtime_set_suspended(gi3c->se.dev);
+	pm_runtime_dont_use_autosuspend(gi3c->se.dev);
+}
+
+static int geni_i3c_runtime_suspend(struct device *dev)
+{
+	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
+
+	disable_irq(gi3c->irq);
+	geni_se_resources_off(&gi3c->se);
+	return 0;
+}
+
+static int geni_i3c_runtime_resume(struct device *dev)
+{
+	int ret;
+	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
+
+	ret = geni_se_resources_on(&gi3c->se);
+	if (ret)
+		return ret;
+	enable_irq(gi3c->irq);
+	return 0;
+}
+
+static const struct dev_pm_ops geni_i3c_pm_ops = {
+	SET_RUNTIME_PM_OPS(geni_i3c_runtime_suspend, geni_i3c_runtime_resume, NULL)
+};
+
+static const struct of_device_id geni_i3c_dt_match[] = {
+	{ .compatible = "qcom,i3c-master" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, geni_i3c_dt_match);
+
+static struct platform_driver geni_i3c_master = {
+	.probe  = geni_i3c_probe,
+	.remove = geni_i3c_remove,
+	.driver = {
+		.name = "geni_i3c_master",
+		.pm = &geni_i3c_pm_ops,
+		.of_match_table = geni_i3c_dt_match,
+	},
+};
+
+module_platform_driver(geni_i3c_master);
+
+MODULE_AUTHOR("Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>");
+MODULE_DESCRIPTION("Qualcomm I3C Controller Driver for GENI based QUP cores");
+MODULE_LICENSE("GPL");
-- 
2.25.1



From quic_msavaliy at quicinc.com  Wed Mar 26 07:16:41 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Wed, 26 Mar 2025 19:46:41 +0530
Subject: [PATCH v2 3/3] MAINTAINERS: Add maintainer for Qualcomm's I3C driver
In-Reply-To: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
Message-ID: <20250326141641.3471906-4-quic_msavaliy@quicinc.com>

Add a new entry for the I3C QCOM GENI driver to the MAINTAINERS file.
This entry includes the maintainer's name and contact information,
ensuring proper maintainership and communication for the new driver.

Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 3520ce6f9859..047d804122ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11016,6 +11016,14 @@ S:	Orphan
 F:	Documentation/devicetree/bindings/i3c/snps,dw-i3c-master.yaml
 F:	drivers/i3c/master/dw*
 
+I3C DRIVER FOR QUALCOMM GENI CONTROLLER IP
+M:	Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
+L:	linux-i3c at lists.infradead.org (moderated for non-subscribers)
+L:	linux-arm-msm at vger.kernel.org
+S:	Supported
+F:	Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
+F:	drivers/i3c/master/qcom-i3c-master.c
+
 I3C SUBSYSTEM
 M:	Alexandre Belloni <alexandre.belloni at bootlin.com>
 L:	linux-i3c at lists.infradead.org (moderated for non-subscribers)
-- 
2.25.1



From krzk at kernel.org  Wed Mar 26 07:23:08 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 26 Mar 2025 15:23:08 +0100
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
Message-ID: <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>

On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
> Add device tree bindings for the Qualcomm I3C controller. This includes
> the necessary documentation and properties required to describe the
> hardware in the device tree.
> 
> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
> ---
>  .../bindings/i3c/qcom,i3c-master.yaml         | 60 +++++++++++++++++++
>  1 file changed, 60 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
> 
> diff --git a/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
> new file mode 100644
> index 000000000000..af6b393f2327
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml

Naming: nothing improved.

> @@ -0,0 +1,60 @@
> +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/i3c/qcom,i3c-master.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm Geni based QUP I3C Controller
> +
> +maintainers:
> +  - Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
> +
> +description:
> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
> +  hotjoin, IBI mechanism.
> +
> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
> +
> +allOf:
> +  - $ref: i3c.yaml#
> +
> +properties:
> +  compatible:
> +    const: qcom,i3c-master

And this got worse. It makes also no sense either: how can you claim
that this covers all possible future I3C masters from Qualcomm?

What was the resolution of previous discussion?

Best regards,
Krzysztof


From krzk at kernel.org  Wed Mar 26 07:28:07 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Wed, 26 Mar 2025 15:28:07 +0100
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
Message-ID: <d0b178ab-ad22-4230-a790-6a19a6abfd89@kernel.org>

On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
> +
> +static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
> +{
> +	int ret;
> +
> +	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(gi3c->se.base))
> +		return PTR_ERR(gi3c->se.base);
> +
> +	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");

Never tested.

> +	if (IS_ERR(gi3c->se.clk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(gi3c->se.clk),
> +							"Unable to get serial engine core clock: %pe\n",
> +							gi3c->se.clk);
> +
> +	ret = device_property_read_u32(&pdev->dev, "se-clock-frequency", &gi3c->clk_src_freq);

I don't see previous comments implemented. Comment was: "Drop".

You did not test the DTS - again - even though I asked for that.

You claim you did internal review, but I have doubts because internal
review would tell you how to test it (there is comprehensive internal
guide - see go/upstream). Then the testing would point out this issue.

Such trivial things should not be in v1 even. But they happened so you
got the review. Now you sent v2 ignoring that public review.

Sorry guys, please improve internal processes instead of wasting
reviewers time.

NAK.

Best regards,
Krzysztof


From Frank.li at nxp.com  Wed Mar 26 13:03:13 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 26 Mar 2025 16:03:13 -0400
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
Message-ID: <Z+RdgfrQ2zs9Szt3@lizhi-Precision-Tower-5810>

On Wed, Mar 26, 2025 at 07:46:40PM +0530, Mukesh Kumar Savaliya wrote:
> Add support for the Qualcomm I3C controller driver, which implements
> I3C master functionality as defined in the MIPI Alliance Specification
> for I3C, Version 1.0.
>
> This driver supports master role in SDR mode.
>
> Unlike some other I3C master controllers, this implementation
> does not support In-Band Interrupts (IBI) and Hot-join requests.
>
> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
> ---
>  drivers/i3c/master/Kconfig           |   12 +
>  drivers/i3c/master/Makefile          |    1 +
>  drivers/i3c/master/qcom-i3c-master.c | 1107 ++++++++++++++++++++++++++
>  3 files changed, 1120 insertions(+)
>  create mode 100644 drivers/i3c/master/qcom-i3c-master.c
>
> diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
> index 77da199c7413..5370cadfe236 100644
> --- a/drivers/i3c/master/Kconfig
> +++ b/drivers/i3c/master/Kconfig
> @@ -44,6 +44,18 @@ config SVC_I3C_MASTER
>  	help
>  	  Support for Silvaco I3C Dual-Role Master Controller.
>
> +config QCOM_I3C_MASTER
> +	tristate "Qualcomm Technologies Inc.'s I3C Master controller driver"
> +	depends on I3C
> +	help
> +	This driver supports QUPV3 GENI based I3C controller in master

It should have extrn 2 space

	help
	  This driver ....

> +	mode on the Qualcomm Technologies Inc.s SoCs. If you say yes to
> +	this option, support will be included for the built-in I3C interface
> +	on the Qualcomm Technologies Inc.s SoCs.
> +
> +	This driver can also be built as a module.  If so, the module
> +	will be called qcom-i3c-master.
> +
>  config MIPI_I3C_HCI
>  	tristate "MIPI I3C Host Controller Interface driver (EXPERIMENTAL)"
>  	depends on I3C
> diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
> index 3e97960160bc..f6670a63b34f 100644
> --- a/drivers/i3c/master/Makefile
> +++ b/drivers/i3c/master/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_DW_I3C_MASTER)		+= dw-i3c-master.o
>  obj-$(CONFIG_AST2600_I3C_MASTER)	+= ast2600-i3c-master.o
>  obj-$(CONFIG_SVC_I3C_MASTER)		+= svc-i3c-master.o
>  obj-$(CONFIG_MIPI_I3C_HCI)		+= mipi-i3c-hci/
> +obj-$(CONFIG_QCOM_I3C_MASTER)		+= qcom-i3c-master.o
> diff --git a/drivers/i3c/master/qcom-i3c-master.c b/drivers/i3c/master/qcom-i3c-master.c
> new file mode 100644
> index 000000000000..54778a6baa70
> --- /dev/null
> +++ b/drivers/i3c/master/qcom-i3c-master.c
> @@ -0,0 +1,1107 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
> + *
> + * Author: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/i3c/master.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/soc/qcom/geni-se.h>
> +
> +#define SE_I3C_SCL_HIGH                 0x268
> +#define SE_I3C_TX_TRANS_LEN             0x26C
> +#define SE_I3C_RX_TRANS_LEN             0x270
> +#define SE_I3C_DELAY_COUNTER            0x274
> +#define SE_I2C_SCL_COUNTERS             0x278
> +#define SE_I3C_SCL_CYCLE                0x27C

please use low case hex value

> +#define SE_GENI_HW_IRQ_EN               0x920
> +#define SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE 0x924
> +#define SE_GENI_HW_IRQ_CMD_PARAM_0      0x930
> +
> +/* HW I3C IBI interrupt enable */
> +#define M_IBI_IRQ_EN BIT(0)
> +
> +/* M_IBI_IRQ_IGNORE */
> +#define M_IBI_IRQ_IGNORE BIT(0)
> +
> +/* SE_GENI_M_CLK_CFG field shifts */
> +#define	CLK_DIV_VALUE_MASK	GENMASK(23, 4)
> +#define SER_CLK_EN		BIT(0)
> +
> +/* SE_GENI_HW_IRQ_CMD_PARAM_0 field bits */
> +#define M_IBI_IRQ_PARAM_7E BIT(0)
> +#define M_IBI_IRQ_PARAM_STOP_STALL BIT(1)
> +/* SE_I2C_SCL_COUNTERS field shifts */
> +#define I2C_SCL_HIGH_COUNTER_MASK	GENMASK(29, 20)
> +#define I2C_SCL_LOW_COUNTER_MASK	GENMASK(19, 10)
> +#define I2C_SCL_CYCLE_COUNTER_MASK	GENMASK(9, 0)
> +
> +#define SE_I3C_ERR  (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
> +	M_CMD_ABORT_EN | M_GP_IRQ_0_EN | M_GP_IRQ_1_EN | M_GP_IRQ_2_EN | \
> +	M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
> +
> +/* M_CMD OP codes for I2C/I3C */
> +#define I3C_READ_IBI_HW          0
> +#define I2C_WRITE                1
> +#define I2C_READ                 2
> +#define I2C_WRITE_READ           3
> +#define I2C_ADDR_ONLY            4
> +#define I3C_INBAND_RESET         5
> +#define I2C_BUS_CLEAR            6
> +#define I2C_STOP_ON_BUS          7
> +#define I3C_HDR_DDR_EXIT         8
> +#define I3C_PRIVATE_WRITE        9
> +#define I3C_PRIVATE_READ         10
> +#define I3C_HDR_DDR_WRITE        11
> +#define I3C_HDR_DDR_READ         12
> +#define I3C_DIRECT_CCC_ADDR_ONLY 13
> +#define I3C_BCAST_CCC_ADDR_ONLY  14
> +#define I3C_READ_IBI             15
> +#define I3C_BCAST_CCC_WRITE      16
> +#define I3C_DIRECT_CCC_WRITE     17
> +#define I3C_DIRECT_CCC_READ      18
> +
> +/* M_CMD params for I3C */
> +#define PRE_CMD_DELAY          BIT(0)
> +#define TIMESTAMP_BEFORE       BIT(1)
> +#define STOP_STRETCH           BIT(2)
> +#define TIMESTAMP_AFTER        BIT(3)
> +#define POST_COMMAND_DELAY     BIT(4)
> +#define IGNORE_ADD_NACK        BIT(6)
> +#define READ_FINISHED_WITH_ACK BIT(7)
> +#define CONTINUOUS_MODE_DAA    BIT(8)
> +
> +#define SLAVE_ADDR_MASK           GENMASK(15, 9)
> +#define SLV_ADDR_SHFT          9
> +
> +#define CCC_HDR_CMD_MSK        GENMASK(23, 16)
> +#define CCC_HDR_CMD_SHFT       16
> +#define IBI_NACK_TBL_CTRL      BIT(24)
> +#define USE_7E                 BIT(25)
> +#define BYPASS_ADDR_PHASE      BIT(26)
> +
> +/* GSI callback error fields - DMA_TX_IRQ_STAT */
> +#define GP_IRQ0	BIT(5)
> +#define GP_IRQ1	BIT(6)
> +#define GP_IRQ2	BIT(7)
> +#define GP_IRQ3	BIT(8)
> +#define GP_IRQ4	BIT(9)
> +#define GP_IRQ5	BIT(10)
> +#define DM_I3C_CB_ERR   GENMASK(10, 5)
> +
> +#define I3C_AUTO_SUSPEND_DELAY  250
> +#define KHZ(freq)               (1000 * (freq))
> +#define PACKING_BYTES_PW        4
> +#define XFER_TIMEOUT            250
> +#define DFS_INDEX_MAX           7
> +
> +#define I3C_ADDR_MASK 0x7f
> +
> +enum geni_i3c_err_code {
> +	RD_TERM,
> +	NACK,
> +	CRC_ERR,
> +	BUS_PROTO,
> +	NACK_7E,
> +	NACK_IBI,
> +	GENI_OVERRUN,
> +	GENI_ILLEGAL_CMD,
> +	GENI_ABORT_DONE,
> +	GENI_TIMEOUT,
> +};
> +
> +enum i3c_bus_phase {
> +	OPEN_DRAIN_MODE  = 0,
> +	PUSH_PULL_MODE   = 1
> +};
> +
> +struct geni_i3c_dev {
> +	struct geni_se se;
> +	unsigned int tx_wm;
> +	int irq;
> +	int err;
> +	struct i3c_master_controller ctrlr;
> +	struct completion done;
> +	/* Protects per device CCC command or transfer from get_mutex_lock()/unlock() wrapper */
> +	struct mutex lock;
> +	/* Per device protection between process and IRQ context */
> +	spinlock_t irq_lock;
> +	u32 clk_src_freq;
> +	u8 *cur_buf;
> +	bool cur_is_write;
> +	int cur_len;
> +	int cur_idx;
> +	//unsigned long newaddrslots[(I3C_ADDR_MASK + 1) / BITS_PER_LONG];
> +	DECLARE_BITMAP(newaddrslots, 64);
> +
> +	const struct geni_i3c_clk_settings *clk_cfg;
> +	const struct geni_i3c_clk_settings *clk_od_cfg;
> +};
> +
> +struct geni_i3c_i2c_dev_data {
> +	u32 ibi_keeping;  /* Plan to save IBI information, keep as dummy for now */

Remove it, add it only when use it.

> +};
> +
> +struct geni_i3c_xfer_params {
> +	enum geni_se_xfer_mode mode;
> +	u32 m_cmd;
> +	u32 m_param;
> +};
> +
> +static inline struct geni_i3c_dev *to_geni_i3c_master(struct i3c_master_controller
> +							*master)
> +{
> +	return container_of(master, struct geni_i3c_dev, ctrlr);
> +}
> +
> +struct geni_i3c_clk_settings {
> +	u32 clk_freq_out;
> +	u32 clk_src_freq;
> +	u8  clk_div;
> +	u8  i2c_t_high_cnt;
> +	u8  i2c_t_low_cnt;
> +	u8  i3c_t_high_cnt;
> +	u8  i3c_t_cycle_cnt;
> +	u8  i2c_t_cycle_cnt;
> +};
> +
> +/*
> + * Hardware uses the underlying formula to calculate time periods of
> + * SCL clock cycle. Firmware uses some additional cycles excluded from the
> + * below formula and it is confirmed that the time periods are within
> + * specification limits.
> + *
> + * time of high period of I2C SCL:
> + *         i2c_t_high = (i2c_t_high_cnt * clk_div) / source_clock
> + * time of low period of I2C SCL:
> + *         i2c_t_low = (i2c_t_low_cnt * clk_div) / source_clock
> + * time of full period of I2C SCL:
> + *         i2c_t_cycle = (i2c_t_cycle_cnt * clk_div) / source_clock
> + * time of high period of I3C SCL:
> + *         i3c_t_high = (i3c_t_high_cnt * clk_div) / source_clock
> + * time of full period of I3C SCL:
> + *         i3c_t_cycle = (i3c_t_cycle_cnt * clk_div) / source_clock
> + * clk_freq_out = t / t_cycle
> + */
> +static const struct geni_i3c_clk_settings geni_i3c_clk_map[] = {
> +/* op-freq,  src-freq,  div,  i2c_high,  i2c_low, i3c_high, i3c_cyc i2c_cyc */
> +	{ KHZ(100),    KHZ(19200), 1, 76, 90, 7, 8, 192},
> +	{ KHZ(400),    KHZ(19200), 1, 12, 24, 7, 8, 48},
> +	{ KHZ(1000),   KHZ(19200), 1,  4,  9, 7, 0, 19},
> +	{ KHZ(12500), KHZ(100000), 1, 45, 63, 6, 7, 110},
> +};
> +
> +static int geni_i3c_clk_map_idx(struct geni_i3c_dev *gi3c)
> +{
> +	const struct geni_i3c_clk_settings *clk_idx = geni_i3c_clk_map;
> +	struct i3c_master_controller *m = &gi3c->ctrlr;
> +	struct i3c_bus *bus = i3c_master_get_bus(m);
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(geni_i3c_clk_map); i++, clk_idx++) {
> +		if ((!bus || clk_idx->clk_freq_out == bus->scl_rate.i3c) &&
> +		    clk_idx->clk_src_freq == gi3c->clk_src_freq) {
> +			gi3c->clk_cfg = clk_idx;
> +		}
> +
> +		if (clk_idx->clk_freq_out == bus->scl_rate.i2c)
> +			gi3c->clk_od_cfg = clk_idx;
> +	}
> +
> +	if (!gi3c->clk_cfg || !gi3c->clk_od_cfg)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void set_new_addr_slot(unsigned long *addrslot, u8 addr)
> +{
> +	if (addr > I3C_ADDR_MASK)
> +		return;
> +
> +	set_bit(addr, addrslot);
> +}
> +
> +static void clear_new_addr_slot(unsigned long *addrslot, u8 addr)
> +{
> +	if (addr > I3C_ADDR_MASK)
> +		return;
> +
> +	clear_bit(addr, addrslot);
> +}
> +
> +static bool is_new_addr_slot_set(unsigned long *addrslot, u8 addr)
> +{
> +	if (addr > I3C_ADDR_MASK)
> +		return false;
> +
> +	return test_bit(addr, addrslot);
> +}
> +
> +static void qcom_geni_i3c_conf(struct geni_i3c_dev *gi3c, enum i3c_bus_phase bus_phase)
> +{
> +	const struct geni_i3c_clk_settings *clk_idx = gi3c->clk_cfg;
> +	unsigned long freq;
> +	u32 val, dfs_idx;
> +	int ret;
> +
> +	if (bus_phase == OPEN_DRAIN_MODE)
> +		clk_idx = gi3c->clk_od_cfg;
> +
> +	ret = geni_se_clk_freq_match(&gi3c->se, clk_idx->clk_src_freq,
> +				     &dfs_idx, &freq, false);
> +	if (ret)
> +		dfs_idx = 0;
> +
> +	writel_relaxed(dfs_idx, gi3c->se.base + SE_GENI_CLK_SEL);
> +
> +	val = FIELD_PREP(CLK_DIV_VALUE_MASK, clk_idx->clk_div);
> +	val |= SER_CLK_EN;
> +	writel_relaxed(val, gi3c->se.base + GENI_SER_M_CLK_CFG);
> +
> +	val = FIELD_PREP(I2C_SCL_HIGH_COUNTER_MASK, clk_idx->i2c_t_high_cnt);
> +	val |= FIELD_PREP(I2C_SCL_LOW_COUNTER_MASK, clk_idx->i2c_t_low_cnt);
> +	val |= FIELD_PREP(I2C_SCL_CYCLE_COUNTER_MASK, clk_idx->i2c_t_cycle_cnt);
> +	writel_relaxed(val, gi3c->se.base + SE_I2C_SCL_COUNTERS);
> +
> +	writel_relaxed(clk_idx->i3c_t_cycle_cnt, gi3c->se.base + SE_I3C_SCL_CYCLE);
> +	writel_relaxed(clk_idx->i3c_t_high_cnt, gi3c->se.base + SE_I3C_SCL_HIGH);
> +
> +	writel_relaxed(M_IBI_IRQ_IGNORE, gi3c->se.base + SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE);
> +
> +	val = M_IBI_IRQ_PARAM_STOP_STALL | M_IBI_IRQ_PARAM_7E;
> +	writel_relaxed(val, gi3c->se.base + SE_GENI_HW_IRQ_CMD_PARAM_0);
> +
> +	writel_relaxed(M_IBI_IRQ_EN, gi3c->se.base + SE_GENI_HW_IRQ_EN);
> +}
> +
> +static void geni_i3c_handle_err(struct geni_i3c_dev *gi3c, u32 status)
> +{
> +	dev_dbg(gi3c->se.dev, "len:%d, %s\n",
> +		gi3c->cur_len, gi3c->cur_is_write ? "write" : "read");
> +
> +	if (status & M_GP_IRQ_0_EN) {
> +		gi3c->err = -EINVAL;
> +		dev_dbg(gi3c->se.dev, "%s\n", "I3C slave early read termination");
> +	}
> +	if (status & M_GP_IRQ_1_EN) {
> +		gi3c->err = -ENOTCONN;
> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK: slave unresponsive, check power/reset");
> +	}
> +	if (status & M_GP_IRQ_2_EN) {
> +		gi3c->err = -EINVAL;
> +		dev_dbg(gi3c->se.dev, "%s\n", "CRC or parity error");
> +	}
> +	if (status & M_GP_IRQ_3_EN) {
> +		gi3c->err = -EPROTO;
> +		dev_dbg(gi3c->se.dev, "%s\n", "Bus proto Error, noisy/unexpected start/stop");
> +	}
> +	if (status & M_GP_IRQ_4_EN) {
> +		gi3c->err = -EBUSY;
> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK on 7E, unexpected protocol error");
> +	}
> +	if (status & M_GP_IRQ_5_EN) {
> +		gi3c->err = -EINVAL;
> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK on IBI");
> +	}
> +	if (status & M_CMD_OVERRUN_EN) {
> +		gi3c->err = -EIO;
> +		dev_dbg(gi3c->se.dev, "%s\n", "Cmd overrun, check GENI cmd-state machine");
> +	}
> +	if (status & M_ILLEGAL_CMD_EN) {
> +		gi3c->err = -EILSEQ;
> +		dev_dbg(gi3c->se.dev, "%s\n", "Illegal cmd, check GENI cmd-state machine");
> +	}
> +	if (status & M_CMD_ABORT_EN) {
> +		gi3c->err = -ETIMEDOUT;
> +		dev_dbg(gi3c->se.dev, "%s\n", "Abort after timeout successful");
> +	}
> +	if (status & GENI_TIMEOUT) {
> +		gi3c->err = -ETIMEDOUT;
> +		dev_dbg(gi3c->se.dev, "%s\n", "I3C transaction timed out");
> +	}
> +}
> +
> +static irqreturn_t geni_i3c_irq(int irq, void *dev)
> +{
> +	u32 m_stat_mask, dm_tx_st, dm_rx_st, m_stat, rx_st, dma;
> +	struct geni_i3c_dev *gi3c = dev;
> +	unsigned long flags;
> +	int j;
> +
> +	m_stat = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_STATUS);
> +	m_stat_mask = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_EN);
> +	rx_st = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFO_STATUS);
> +	dm_tx_st = readl_relaxed(gi3c->se.base + SE_DMA_TX_IRQ_STAT);
> +	dm_rx_st = readl_relaxed(gi3c->se.base + SE_DMA_RX_IRQ_STAT);
> +	dma = readl_relaxed(gi3c->se.base + SE_GENI_DMA_MODE_EN);
> +
> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
> +
> +	if (m_stat & SE_I3C_ERR || dm_rx_st & DM_I3C_CB_ERR) {
> +		geni_i3c_handle_err(gi3c, m_stat);
> +		/* Disable the TX Watermark interrupt to stop TX */
> +		if (!dma)
> +			writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
> +		goto irqret;
> +	}
> +
> +	if (dma) {
> +		dev_dbg(gi3c->se.dev, "i3c dma tx:0x%x, dma rx:0x%x\n", dm_tx_st, dm_rx_st);
> +		goto irqret;
> +	}
> +
> +	if ((m_stat &
> +		(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) &&
> +		!gi3c->cur_is_write && gi3c->cur_buf) {
> +		u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
> +
> +		for (j = 0; j < rxcnt; j++) {
> +			u32 val;
> +			int p = 0;
> +
> +			val = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFOn);
> +			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
> +				gi3c->cur_buf[gi3c->cur_idx++] = val & 0xff;
> +				val >>= 8;
> +				p++;
> +			}
> +			if (gi3c->cur_idx == gi3c->cur_len)
> +				break;
> +		}
> +	} else if (m_stat & M_TX_FIFO_WATERMARK_EN &&
> +		gi3c->cur_is_write && gi3c->cur_buf) {
> +		for (j = 0; j < gi3c->tx_wm; j++) {
> +			u32 temp;
> +			u32 val = 0;
> +			int p = 0;
> +
> +			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
> +				temp = gi3c->cur_buf[gi3c->cur_idx++];
> +				val |= temp << (p * 8);
> +				p++;
> +			}
> +
> +			writel_relaxed(val, gi3c->se.base + SE_GENI_TX_FIFOn);
> +			if (gi3c->cur_idx == gi3c->cur_len) {
> +				writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
> +				break;
> +			}
> +		}
> +	}
> +
> +irqret:
> +	if (m_stat)
> +		writel_relaxed(m_stat, gi3c->se.base + SE_GENI_M_IRQ_CLEAR);
> +
> +	if (dma) {
> +		if (dm_tx_st)
> +			writel_relaxed(dm_tx_st, gi3c->se.base + SE_DMA_TX_IRQ_CLR);
> +		if (dm_rx_st)
> +			writel_relaxed(dm_rx_st, gi3c->se.base + SE_DMA_RX_IRQ_CLR);
> +	}
> +
> +	/* if this is err with done-bit not set, handle that through timeout. */
> +	if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN) {
> +		writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
> +		complete(&gi3c->done);
> +	} else if (dm_tx_st & TX_DMA_DONE || dm_rx_st & RX_DMA_DONE	||
> +		dm_rx_st & RX_RESET_DONE) {
> +		complete(&gi3c->done);
> +	}
> +
> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
> +	return IRQ_HANDLED;
> +}
> +
> +static int i3c_geni_runtime_get_mutex_lock(struct geni_i3c_dev *gi3c)
> +{
> +	int ret;
> +
> +	mutex_lock(&gi3c->lock);
> +	reinit_completion(&gi3c->done);
> +	ret = pm_runtime_get_sync(gi3c->se.dev);
> +	if (ret < 0) {
> +		dev_err(gi3c->se.dev, "error turning on SE resources:%d\n", ret);
> +		pm_runtime_put_noidle(gi3c->se.dev);
> +		/* Set device in suspended since resume failed */
> +		pm_runtime_set_suspended(gi3c->se.dev);
> +		mutex_unlock(&gi3c->lock);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void i3c_geni_runtime_put_mutex_unlock(struct geni_i3c_dev *gi3c)
> +{
> +	pm_runtime_mark_last_busy(gi3c->se.dev);
> +	pm_runtime_put_autosuspend(gi3c->se.dev);
> +	mutex_unlock(&gi3c->lock);
> +}
> +
> +static void geni_i3c_abort_xfer(struct geni_i3c_dev *gi3c)
> +{
> +	unsigned long time_remaining;
> +	unsigned long flags;
> +
> +	reinit_completion(&gi3c->done);
> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
> +	geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
> +	geni_se_abort_m_cmd(&gi3c->se);
> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
> +	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
> +	if (!time_remaining)
> +		dev_err(gi3c->se.dev, "Timeout abort_m_cmd\n");
> +}
> +
> +static int _i3c_geni_execute_command(struct geni_i3c_dev *gi3c, struct geni_i3c_xfer_params *xfer)
> +{
> +	bool is_write = gi3c->cur_is_write;
> +	dma_addr_t tx_dma = 0, rx_dma = 0;
> +	unsigned long time_remaining;
> +	u32 len = gi3c->cur_len;
> +	int ret;
> +
> +	geni_se_select_mode(&gi3c->se, xfer->mode);
> +
> +	gi3c->err = 0;
> +	gi3c->cur_idx = 0;
> +
> +	if (!is_write) {
> +		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x READ len:%d\n",
> +			xfer->m_cmd, xfer->m_param, len);
> +		writel_relaxed(len, gi3c->se.base + SE_I3C_RX_TRANS_LEN);
> +		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
> +		if (xfer->mode == GENI_SE_DMA) {
> +			ret = geni_se_rx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &rx_dma);
> +			if (ret) {
> +				xfer->mode = GENI_SE_FIFO;
> +				geni_se_select_mode(&gi3c->se, xfer->mode);
> +			}
> +		}
> +	} else {
> +		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x WRITE len:%d\n",
> +			xfer->m_cmd, xfer->m_param, len);
> +
> +		writel_relaxed(len, gi3c->se.base + SE_I3C_TX_TRANS_LEN);
> +		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
> +
> +		if (xfer->mode == GENI_SE_DMA) {
> +			ret = geni_se_tx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &tx_dma);
> +			if (ret) {
> +				xfer->mode = GENI_SE_FIFO;
> +				geni_se_select_mode(&gi3c->se, xfer->mode);
> +			}
> +		}
> +
> +		if (xfer->mode == GENI_SE_FIFO && len > 0) /* Get FIFO IRQ */
> +			writel_relaxed(1, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
> +	}
> +
> +	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
> +	if (!time_remaining) {
> +		unsigned long flags;
> +
> +		dev_dbg(gi3c->se.dev, "Timeout completing FIFO transfer\n");
> +		spin_lock_irqsave(&gi3c->irq_lock, flags);
> +		geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
> +		gi3c->cur_buf = NULL;
> +		spin_unlock_irqrestore(&gi3c->irq_lock, flags);
> +		geni_i3c_abort_xfer(gi3c);
> +	}
> +
> +	if (xfer->mode == GENI_SE_DMA) {
> +		if (gi3c->err) {
> +			if (is_write)
> +				writel_relaxed(1, gi3c->se.base + SE_DMA_TX_FSM_RST);
> +			else
> +				writel_relaxed(1, gi3c->se.base + SE_DMA_RX_FSM_RST);
> +
> +			time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
> +			dev_dbg(gi3c->se.dev, "Timeout completing DMA transfer\n");
> +		}
> +		geni_se_rx_dma_unprep(&gi3c->se, rx_dma, len);
> +		geni_se_tx_dma_unprep(&gi3c->se, tx_dma, len);
> +	}
> +
> +	ret = gi3c->err;
> +	if (gi3c->err)
> +		dev_err(gi3c->se.dev, "I3C transaction error :%d\n", gi3c->err);
> +
> +	gi3c->cur_buf = NULL;
> +	gi3c->err = 0;
> +
> +	return ret;
> +}
> +
> +static int i3c_geni_execute_read_command(struct geni_i3c_dev *gi3c,
> +					 struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
> +{
> +	gi3c->cur_is_write = false;
> +	gi3c->cur_buf = buf;
> +	gi3c->cur_len = len;
> +	return _i3c_geni_execute_command(gi3c, xfer);
> +	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);

remove these commented code.

> +}
> +
> +static int i3c_geni_execute_write_command(struct geni_i3c_dev *gi3c,
> +					  struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
> +{
> +	gi3c->cur_is_write = true;
> +	gi3c->cur_buf = buf;
> +	gi3c->cur_len = len;
> +	return _i3c_geni_execute_command(gi3c, xfer);
> +	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);
> +}
> +
> +static void geni_i3c_perform_daa(struct geni_i3c_dev *gi3c)
> +{
> +	u8 last_dyn_addr = 0;
> +	int ret;
> +
> +	while (1) {
> +		u8 rx_buf[8], tx_buf[8];
> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
> +		struct i3c_device_info info = { 0 };
> +		struct i3c_dev_desc *i3cdev;
> +		bool new_device = true;
> +		u64 pid;
> +		u8 bcr, dcr, addr;
> +
> +		xfer.m_cmd = I2C_READ;
> +		xfer.m_param = STOP_STRETCH | CONTINUOUS_MODE_DAA | USE_7E;
> +		ret = i3c_geni_execute_read_command(gi3c, &xfer, rx_buf, 8);
> +		if (ret)
> +			break;
> +
> +		dcr = rx_buf[7];
> +		bcr = rx_buf[6];
> +		pid = ((u64)rx_buf[0] << 40) |
> +			((u64)rx_buf[1] << 32) |
> +			((u64)rx_buf[2] << 24) |
> +			((u64)rx_buf[3] << 16) |
> +			((u64)rx_buf[4] <<  8) |
> +			((u64)rx_buf[5]);
> +
> +		i3c_bus_for_each_i3cdev(&gi3c->ctrlr.bus, i3cdev) {
> +			i3c_device_get_info(i3cdev->dev, &info);
> +			if (pid == info.pid && dcr == info.dcr && bcr == info.bcr) {
> +				new_device = false;
> +				addr = (info.dyn_addr) ? info.dyn_addr :
> +					info.static_addr;
> +				break;
> +			}
> +		}
> +
> +		if (new_device) {
> +			ret = i3c_master_get_free_addr(&gi3c->ctrlr, last_dyn_addr + 1);
> +			if (ret < 0)
> +				break;
> +			addr = (u8)ret;
> +			last_dyn_addr = (u8)ret;
> +			set_new_addr_slot(gi3c->newaddrslots, addr);
> +		}
> +
> +		tx_buf[0] = (addr & I3C_ADDR_MASK) << 1;
> +		tx_buf[0] |= ~(hweight8(addr & I3C_ADDR_MASK) & 1);
> +
> +		xfer.m_cmd = I2C_WRITE;
> +		xfer.m_param = STOP_STRETCH | BYPASS_ADDR_PHASE | USE_7E;
> +
> +		ret = i3c_geni_execute_write_command(gi3c, &xfer, tx_buf, 1);
> +		if (ret)
> +			break;
> +	}
> +}
> +
> +static int geni_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
> +					struct i3c_ccc_cmd *cmd)
> +{
> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
> +	int i, ret;
> +
> +	if (!(cmd->id & I3C_CCC_DIRECT) && cmd->ndests != 1)
> +		return -EINVAL;
> +
> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
> +	if (ret)
> +		return ret;
> +
> +	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
> +	for (i = 0; i < cmd->ndests; i++) {
> +		int stall = (i < (cmd->ndests - 1)) ||
> +			(cmd->id == I3C_CCC_ENTDAA);
> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
> +
> +		xfer.m_param  = (stall ? STOP_STRETCH : 0);
> +		xfer.m_param |= (cmd->id << CCC_HDR_CMD_SHFT);
> +		xfer.m_param |= IBI_NACK_TBL_CTRL;
> +		if (cmd->id & I3C_CCC_DIRECT) {
> +			xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, cmd->dests[i].addr);
> +			if (cmd->rnw) {
> +				if (i == 0)
> +					xfer.m_cmd = I3C_DIRECT_CCC_READ;
> +				else
> +					xfer.m_cmd = I3C_PRIVATE_READ;
> +			} else {
> +				if (i == 0)
> +					xfer.m_cmd =
> +					   (cmd->dests[i].payload.len > 0) ?
> +						I3C_DIRECT_CCC_WRITE :
> +						I3C_DIRECT_CCC_ADDR_ONLY;
> +				else
> +					xfer.m_cmd = I3C_PRIVATE_WRITE;
> +			}
> +		} else {
> +			if (cmd->dests[i].payload.len > 0)
> +				xfer.m_cmd = I3C_BCAST_CCC_WRITE;
> +			else
> +				xfer.m_cmd = I3C_BCAST_CCC_ADDR_ONLY;
> +		}
> +
> +		if (i == 0)
> +			xfer.m_param |= USE_7E;
> +
> +		if (cmd->rnw)
> +			ret = i3c_geni_execute_read_command(gi3c, &xfer,
> +							    cmd->dests[i].payload.data,
> +							    cmd->dests[i].payload.len);
> +		else
> +			ret = i3c_geni_execute_write_command(gi3c, &xfer,
> +							     cmd->dests[i].payload.data,
> +							     cmd->dests[i].payload.len);
> +		if (ret)
> +			break;
> +
> +		if (cmd->id == I3C_CCC_ENTDAA)
> +			geni_i3c_perform_daa(gi3c);
> +	}
> +
> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
> +	return ret;
> +}
> +
> +static int geni_i3c_master_priv_xfers(struct i3c_dev_desc *dev, struct i3c_priv_xfer *xfers,
> +				      int nxfers)
> +{
> +	struct i3c_master_controller *m = i3c_dev_get_master(dev);
> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
> +	bool use_7e = false;
> +	int i, ret;
> +
> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
> +	if (ret)
> +		return ret;
> +
> +	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
> +
> +	for (i = 0; i < nxfers; i++) {
> +		bool stall = (i < (nxfers - 1));
> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
> +
> +		xfer.m_param  = (stall ? STOP_STRETCH : 0);
> +		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, dev->info.dyn_addr);
> +		xfer.m_param |= (use_7e) ? USE_7E : 0;
> +
> +		/* use_7e = true only for last transfer */
> +		use_7e = (i == nxfers - 1);
> +
> +		if (xfers[i].rnw) {
> +			xfer.m_cmd = I3C_PRIVATE_READ;
> +			ret = i3c_geni_execute_read_command(gi3c, &xfer, (u8 *)xfers[i].data.in,
> +							    xfers[i].len);
> +		} else {
> +			xfer.m_cmd = I3C_PRIVATE_WRITE;
> +			ret = i3c_geni_execute_write_command(gi3c, &xfer, (u8 *)xfers[i].data.out,
> +							     xfers[i].len);
> +		}
> +
> +		if (ret)
> +			break;
> +	}
> +
> +	dev_dbg(gi3c->se.dev, "i3c priv: txn ret:%d\n", ret);
> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
> +	return ret;
> +}
> +
> +static int geni_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, const struct i2c_msg *msgs, int num)
> +{
> +	struct i3c_master_controller *m = i2c_dev_get_master(dev);
> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
> +	int i, ret;
> +
> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
> +	if (ret)
> +		return ret;
> +
> +	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
> +
> +	for (i = 0; i < num; i++) {
> +		struct geni_i3c_xfer_params xfer;
> +
> +		xfer.m_cmd    = (msgs[i].flags & I2C_M_RD) ? I2C_READ : I2C_WRITE;
> +		xfer.m_param  = (i < (num - 1)) ? STOP_STRETCH : 0;
> +		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, msgs[i].addr);
> +		xfer.mode     = msgs[i].len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
> +		if (msgs[i].flags & I2C_M_RD)
> +			ret = i3c_geni_execute_read_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
> +		else
> +			ret = i3c_geni_execute_write_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
> +		if (ret)
> +			break;
> +	}
> +
> +	dev_dbg(gi3c->se.dev, "i2c: txn ret:%d\n", ret);
> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
> +	return ret;
> +}
> +
> +static int geni_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
> +{
> +	struct geni_i3c_i2c_dev_data *data;
> +
> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	i2c_dev_set_master_data(dev, data);
> +	return 0;
> +}
> +
> +static void geni_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
> +{
> +	struct geni_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev);
> +
> +	i2c_dev_set_master_data(dev, NULL);
> +	kfree(data);
> +}
> +
> +static int geni_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
> +{
> +	struct geni_i3c_i2c_dev_data *data;
> +
> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	i3c_dev_set_master_data(dev, data);
> +	return 0;
> +}
> +
> +static void geni_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
> +{
> +	struct geni_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
> +
> +	i3c_dev_set_master_data(dev, NULL);
> +	kfree(data);
> +}
> +
> +static int geni_i3c_master_do_daa(struct i3c_master_controller *m)
> +{
> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
> +	u8 addr;
> +	int ret;
> +
> +	ret = i3c_master_entdaa_locked(m);
> +	if (ret && ret != I3C_ERROR_M2)
> +		return ret;
> +
> +	for (addr = 0; addr <= I3C_ADDR_MASK; addr++) {
> +		if (is_new_addr_slot_set(gi3c->newaddrslots, addr)) {
> +			clear_new_addr_slot(gi3c->newaddrslots, addr);
> +			i3c_master_add_i3c_dev_locked(m, addr);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int geni_i3c_master_bus_init(struct i3c_master_controller *m)
> +{
> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
> +	struct i3c_bus *bus = i3c_master_get_bus(m);
> +	struct i3c_device_info info = { };
> +	int ret;
> +
> +	/* Get an address for the master. */
> +	ret = i3c_master_get_free_addr(m, 0);
> +	if (ret < 0)
> +		dev_err(gi3c->se.dev, "%s: error No free addr:%d\n", __func__, ret);
> +
> +	info.dyn_addr = ret;
> +	info.dcr = I3C_DCR_GENERIC_DEVICE;
> +	info.bcr = I3C_BCR_I3C_MASTER | I3C_BCR_HDR_CAP;
> +	info.pid = 0;
> +
> +	ret = geni_i3c_clk_map_idx(gi3c);
> +	if (ret)
> +		dev_err(gi3c->se.dev,
> +			"Invalid clk frequency %d Hz src for %ld Hz bus: %d\n",
> +			gi3c->clk_src_freq, bus->scl_rate.i3c, ret);
> +
> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
> +	if (ret)
> +		return ret;
> +
> +	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
> +
> +	ret = i3c_master_set_info(&gi3c->ctrlr, &info);
> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
> +	return ret;
> +}
> +
> +static bool geni_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
> +					     const struct i3c_ccc_cmd *cmd)
> +{
> +	switch (cmd->id) {
> +	case I3C_CCC_ENEC(true):
> +		fallthrough;
> +	case I3C_CCC_ENEC(false):
> +		fallthrough;
> +	case I3C_CCC_DISEC(true):
> +		fallthrough;
> +	case I3C_CCC_DISEC(false):
> +		fallthrough;
> +	case I3C_CCC_ENTAS(0, true):
> +		fallthrough;
> +	case I3C_CCC_ENTAS(0, false):
> +		fallthrough;
> +	case I3C_CCC_RSTDAA(true):
> +		fallthrough;
> +	case I3C_CCC_RSTDAA(false):
> +		fallthrough;
> +	case I3C_CCC_ENTDAA:
> +		fallthrough;
> +	case I3C_CCC_SETMWL(true):
> +		fallthrough;
> +	case I3C_CCC_SETMWL(false):
> +		fallthrough;
> +	case I3C_CCC_SETMRL(true):
> +		fallthrough;
> +	case I3C_CCC_SETMRL(false):
> +		fallthrough;
> +	case I3C_CCC_DEFSLVS:
> +		fallthrough;
> +	case I3C_CCC_SETDASA:
> +		fallthrough;
> +	case I3C_CCC_SETNEWDA:
> +		fallthrough;
> +	case I3C_CCC_GETMWL:
> +		fallthrough;
> +	case I3C_CCC_GETMRL:
> +		fallthrough;
> +	case I3C_CCC_GETPID:
> +		fallthrough;
> +	case I3C_CCC_GETBCR:
> +		fallthrough;
> +	case I3C_CCC_GETDCR:
> +		fallthrough;
> +	case I3C_CCC_GETSTATUS:
> +		fallthrough;
> +	case I3C_CCC_GETACCMST:
> +		fallthrough;
> +	case I3C_CCC_GETMXDS:
> +		fallthrough;
> +	case I3C_CCC_GETHDRCAP:
> +		return true;
> +
> +	default:
> +		return false;
> +	}
> +}
> +
> +static const struct i3c_master_controller_ops geni_i3c_master_ops = {
> +	.bus_init = geni_i3c_master_bus_init,
> +	.bus_cleanup = NULL,
> +	.do_daa = geni_i3c_master_do_daa,
> +	.attach_i3c_dev = geni_i3c_master_attach_i3c_dev,
> +	.reattach_i3c_dev = NULL,
> +	.detach_i3c_dev = geni_i3c_master_detach_i3c_dev,
> +	.attach_i2c_dev = geni_i3c_master_attach_i2c_dev,
> +	.detach_i2c_dev = geni_i3c_master_detach_i2c_dev,
> +	.supports_ccc_cmd = geni_i3c_master_supports_ccc_cmd,
> +	.send_ccc_cmd = geni_i3c_master_send_ccc_cmd,
> +	.priv_xfers = geni_i3c_master_priv_xfers,
> +	.i2c_xfers = geni_i3c_master_i2c_xfers,
> +	.enable_ibi = NULL,
> +	.disable_ibi = NULL,
> +	.request_ibi = NULL,
> +	.free_ibi = NULL,
> +	.recycle_ibi_slot = NULL,
> +};
> +
> +static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
> +{
> +	int ret;
> +
> +	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(gi3c->se.base))
> +		return PTR_ERR(gi3c->se.base);
> +
> +	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");
> +	if (IS_ERR(gi3c->se.clk))
> +		return dev_err_probe(&pdev->dev, PTR_ERR(gi3c->se.clk),
> +							"Unable to get serial engine core clock: %pe\n",
> +							gi3c->se.clk);
> +
> +	ret = device_property_read_u32(&pdev->dev, "se-clock-frequency", &gi3c->clk_src_freq);
> +	if (ret) {
> +		dev_info(&pdev->dev, "SE clk freq not specified, default to 100 MHz.\n");
> +		/* Default source clock freq is 100Mhz */
> +		gi3c->clk_src_freq = KHZ(100000);
> +	}
> +
> +	ret = geni_icc_get(&gi3c->se, NULL);
> +	if (ret)
> +		return ret;
> +
> +	/* Set the bus quota to a reasonable value for register access */
> +	gi3c->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW;
> +	gi3c->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
> +	ret = geni_icc_set_bw(&gi3c->se);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +static int geni_i3c_probe(struct platform_device *pdev)
> +{
> +	u32 proto, tx_depth, fifo_disable;
> +	struct geni_i3c_dev *gi3c;
> +	int ret;
> +
> +	gi3c = devm_kzalloc(&pdev->dev, sizeof(*gi3c), GFP_KERNEL);
> +	if (!gi3c)
> +		return -ENOMEM;
> +
> +	gi3c->se.dev = &pdev->dev;
> +	gi3c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
> +
> +	init_completion(&gi3c->done);
> +	mutex_init(&gi3c->lock);
> +	spin_lock_init(&gi3c->irq_lock);
> +	platform_set_drvdata(pdev, gi3c);
> +
> +	ret = i3c_geni_resources_init(gi3c, pdev);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "Error Initializing GENI Resources\n");
> +
> +	gi3c->irq = platform_get_irq(pdev, 0);
> +	if (gi3c->irq < 0)
> +		return dev_err_probe(&pdev->dev, gi3c->irq, "Error getting IRQ number for I3C\n");
> +
> +	ret = devm_request_irq(&pdev->dev, gi3c->irq, geni_i3c_irq,
> +			       IRQF_NO_AUTOEN, dev_name(&pdev->dev), gi3c);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "Error registering core IRQ\n");
> +
> +	ret = geni_se_resources_on(&gi3c->se);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "Error turning resources ON\n");
> +
> +	proto = geni_se_read_proto(&gi3c->se);
> +	if (proto != GENI_SE_I3C) {
> +		geni_se_resources_off(&gi3c->se);
> +		return dev_err_probe(&pdev->dev, -ENXIO, "Invalid proto %d\n", proto);
> +	}
> +
> +	fifo_disable = readl_relaxed(gi3c->se.base + GENI_IF_DISABLE_RO);
> +	if (fifo_disable) {
> +		geni_se_resources_off(&gi3c->se);
> +		return dev_err_probe(&pdev->dev, -ENXIO, "GPI DMA mode not supported\n");
> +	}
> +
> +	tx_depth = geni_se_get_tx_fifo_depth(&gi3c->se);
> +	gi3c->tx_wm = tx_depth - 1;
> +	geni_se_init(&gi3c->se, gi3c->tx_wm, tx_depth);
> +	geni_se_config_packing(&gi3c->se, BITS_PER_BYTE, PACKING_BYTES_PW, true, true, true);
> +	geni_se_resources_off(&gi3c->se);
> +	dev_dbg(&pdev->dev, "i3c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
> +
> +	pm_runtime_set_autosuspend_delay(gi3c->se.dev, I3C_AUTO_SUSPEND_DELAY);
> +	pm_runtime_use_autosuspend(gi3c->se.dev);
> +	pm_runtime_set_active(gi3c->se.dev);
> +	pm_runtime_enable(gi3c->se.dev);
> +
> +	ret = i3c_master_register(&gi3c->ctrlr, &pdev->dev, &geni_i3c_master_ops, false);
> +	if (ret) {
> +		pm_runtime_disable(gi3c->se.dev);
> +		pm_runtime_set_suspended(gi3c->se.dev);
> +		pm_runtime_dont_use_autosuspend(gi3c->se.dev);
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
> +static void geni_i3c_remove(struct platform_device *pdev)
> +{
> +	struct geni_i3c_dev *gi3c = platform_get_drvdata(pdev);
> +
> +	i3c_master_unregister(&gi3c->ctrlr);
> +	pm_runtime_disable(gi3c->se.dev);
> +	pm_runtime_set_suspended(gi3c->se.dev);
> +	pm_runtime_dont_use_autosuspend(gi3c->se.dev);
> +}
> +
> +static int geni_i3c_runtime_suspend(struct device *dev)
> +{
> +	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
> +
> +	disable_irq(gi3c->irq);

why need disable irq here?

> +	geni_se_resources_off(&gi3c->se);
> +	return 0;
> +}
> +
> +static int geni_i3c_runtime_resume(struct device *dev)
> +{
> +	int ret;
> +	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
> +
> +	ret = geni_se_resources_on(&gi3c->se);
> +	if (ret)
> +		return ret;
> +	enable_irq(gi3c->irq);
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops geni_i3c_pm_ops = {
> +	SET_RUNTIME_PM_OPS(geni_i3c_runtime_suspend, geni_i3c_runtime_resume, NULL)
> +};
> +
> +static const struct of_device_id geni_i3c_dt_match[] = {
> +	{ .compatible = "qcom,i3c-master" },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, geni_i3c_dt_match);
> +
> +static struct platform_driver geni_i3c_master = {
> +	.probe  = geni_i3c_probe,
> +	.remove = geni_i3c_remove,
> +	.driver = {
> +		.name = "geni_i3c_master",
> +		.pm = &geni_i3c_pm_ops,
> +		.of_match_table = geni_i3c_dt_match,
> +	},
> +};
> +
> +module_platform_driver(geni_i3c_master);
> +
> +MODULE_AUTHOR("Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>");
> +MODULE_DESCRIPTION("Qualcomm I3C Controller Driver for GENI based QUP cores");
> +MODULE_LICENSE("GPL");
> --
> 2.25.1
>


From Frank.li at nxp.com  Wed Mar 26 13:06:11 2025
From: Frank.li at nxp.com (Frank Li)
Date: Wed, 26 Mar 2025 16:06:11 -0400
Subject: [PATCH v6] i3c: Add NULL pointer check in i3c_master_queue_ibi()
In-Reply-To: <20250326123047.2797946-1-manjunatha.venkatesh@nxp.com>
References: <20250326123047.2797946-1-manjunatha.venkatesh@nxp.com>
Message-ID: <Z+ReM0MYKuIz06De@lizhi-Precision-Tower-5810>

On Wed, Mar 26, 2025 at 06:00:46PM +0530, Manjunatha Venkatesh wrote:
> The I3C master driver may receive an IBI from a target device that has not
> been probed yet. In such cases, the master calls `i3c_master_queue_ibi()`
> to queue an IBI work task, leading to "Unable to handle kernel read from
> unreadable memory" and resulting in a kernel panic.
>
> Typical IBI handling flow:
> 1. The I3C master scans target devices and probes their respective drivers.
> 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
>    and assigns `dev->ibi = ibi`.
> 3. The I3C master receives an IBI from the target device and calls
>    `i3c_master_queue_ibi()` to queue the target device driver?s IBI
>    handler task.
>
> However, since target device events are asynchronous to the I3C probe
> sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`,
> leading to a kernel panic.
>
> Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing
> an uninitialized `dev->ibi`, ensuring stability.
>
> Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
> Cc: stable at vger.kernel.org
> Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-5810/
> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> ---

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> Changes since v5:
>   - Updated subject and commit message  with some more information.
>
>  drivers/i3c/master.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index d5dc4180afbc..c65006aa0684 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
>   */
>  void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
>  {
> +	if (!dev->ibi || !slot)
> +		return;
> +
>  	atomic_inc(&dev->ibi->pending_ibis);
>  	queue_work(dev->ibi->wq, &slot->work);
>  }
> --
> 2.46.1
>


From quic_msavaliy at quicinc.com  Fri Mar 28 07:28:21 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Fri, 28 Mar 2025 19:58:21 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
Message-ID: <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>

Thanks Krzysztof for immediate review !

On 3/26/2025 7:53 PM, Krzysztof Kozlowski wrote:
> On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
>> Add device tree bindings for the Qualcomm I3C controller. This includes
>> the necessary documentation and properties required to describe the
>> hardware in the device tree.
>>
>> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>> ---
>>   .../bindings/i3c/qcom,i3c-master.yaml         | 60 +++++++++++++++++++
>>   1 file changed, 60 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>> new file mode 100644
>> index 000000000000..af6b393f2327
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
> 
> Naming: nothing improved.
> 
Sorry, i didn't get exactly. To your comment "Filename matching 
compatible." i have Changed the compatible string to "qcom,i3c-master" 
and now it's matching to file name.

shall i make filename as qcom,i3c-master-qcom.yaml ? If this is wrong, 
please suggest.

Removed "bindings" from the subject line too. I have removed "master" 
from the description, shall i remove from subject also and keep only 
controller ? I kept master controller thinking it may be good as "master 
controller" instead "controller".


>> @@ -0,0 +1,60 @@
>> +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/i3c/qcom,i3c-master.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Qualcomm Geni based QUP I3C Controller
>> +
>> +maintainers:
>> +  - Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>> +
>> +description:
>> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
>> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
>> +  hotjoin, IBI mechanism.
>> +
>> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
>> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
>> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
>> +
>> +allOf:
>> +  - $ref: i3c.yaml#
>> +
>> +properties:
>> +  compatible:
>> +    const: qcom,i3c-master
> 
> And this got worse. It makes also no sense either: how can you claim
> that this covers all possible future I3C masters from Qualcomm?
> 
> What was the resolution of previous discussion?
>
Below was my understanding and reply.
"
I think i should remove const. kept it for now as no other compatible to 
be added as of now.
let me remove const.
SoC name is not required, as this compatible is generic to all the SOCs.
"

But i realized i missed to remove const, sorry for that.


I have also checked for qcom,spi-geni-qcom.yaml, it has below :
properties:
   compatible:
     const: qcom,geni-spi

Let me know if i can correct for SPI in separate new patch ?

> Best regards,
> Krzysztof
> 



From quic_msavaliy at quicinc.com  Fri Mar 28 07:28:52 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Fri, 28 Mar 2025 19:58:52 +0530
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <d0b178ab-ad22-4230-a790-6a19a6abfd89@kernel.org>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <d0b178ab-ad22-4230-a790-6a19a6abfd89@kernel.org>
Message-ID: <f6b0cec1-a20d-4ed8-84b2-06d464ae5e0c@quicinc.com>

Thanks Krzysztof for correcting !

On 3/26/2025 7:58 PM, Krzysztof Kozlowski wrote:
> On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
>> +
>> +static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
>> +{
>> +	int ret;
>> +
>> +	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
>> +	if (IS_ERR(gi3c->se.base))
>> +		return PTR_ERR(gi3c->se.base);
>> +
>> +	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");
> 
> Never tested.
> 
sorry, i ran and i got below error now:
i3c at 884000: Unevaluated properties are not allowed ('clock-names', 
'interrupts' were unexpected).

so i have made below change and ran dt_binding_check + dtbs_check, i 
could fix the issue. Let me have this review internally specific to 
dt-binding and will post next patch after internal review. So i can 
avoid such misses.

yaml :
+  clock-names:
+    const: se
+
-  - interrupts-extended
+  - interrupts

example:
clock-names = "se";

>> +	if (IS_ERR(gi3c->se.clk))
>> +		return dev_err_probe(&pdev->dev, PTR_ERR(gi3c->se.clk),
>> +							"Unable to get serial engine core clock: %pe\n",
>> +							gi3c->se.clk);
>> +
>> +	ret = device_property_read_u32(&pdev->dev, "se-clock-frequency", &gi3c->clk_src_freq);
> 
> I don't see previous comments implemented. Comment was: "Drop".
> 
> You did not test the DTS - again - even though I asked for that.
> 
Sorry for miss. I did test for this but what happened is while i worked 
for multiple other changes, i did miss merging of removal of 
se-clock-frequency from the driver code. I had hard-coded it instead of 
removing because we don't give this frequency selection to user right now.

> You claim you did internal review, but I have doubts because internal
> review would tell you how to test it (there is comprehensive internal
> guide - see go/upstream). Then the testing would point out this issue.
> 
> Such trivial things should not be in v1 even. But they happened so you
> got the review. Now you sent v2 ignoring that public review.
> 
> Sorry guys, please improve internal processes instead of wasting
> reviewers time.
> 
Sure, i agree there are misses. will have internal review with 
dt-bindings and related changes in driver, then will post V3.
> NAK.
> 
> Best regards,
> Krzysztof



From quic_msavaliy at quicinc.com  Fri Mar 28 07:29:33 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Fri, 28 Mar 2025 19:59:33 +0530
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
Message-ID: <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>

Thanks Markus for review and suggestion !

On 3/28/2025 6:49 PM, Markus Elfring wrote:
> ?
>> +++ b/drivers/i3c/master/qcom-i3c-master.c
>> @@ -0,0 +1,1107 @@
> ?
>> +static void geni_i3c_abort_xfer(struct geni_i3c_dev *gi3c)
>> +{
> ?
>> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
>> +	geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
>> +	geni_se_abort_m_cmd(&gi3c->se);
>> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
> ?
> 
> Under which circumstances would you become interested to apply a statement
> like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
Didn't get, hence a question.  Do you suggest to use DEFINE_LOCK_GUARD_1 
instead of existing method ?
> https://elixir.bootlin.com/linux/v6.14-rc6/source/include/linux/spinlock.h#L572
> 
> Regards,
> Markus
> 



From quic_msavaliy at quicinc.com  Fri Mar 28 07:29:44 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Fri, 28 Mar 2025 19:59:44 +0530
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <06545fa2-7f82-4154-a882-faddb53df4d9@web.de>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <06545fa2-7f82-4154-a882-faddb53df4d9@web.de>
Message-ID: <172b9848-0af6-44fc-83c2-8d2b94b74d51@quicinc.com>

Hi Markus, Thanks for review !

On 3/28/2025 6:58 PM, Markus Elfring wrote:
> ?
>> +++ b/drivers/i3c/master/qcom-i3c-master.c
>> @@ -0,0 +1,1107 @@
> ?
>> +/* M_CMD OP codes for I2C/I3C */
>> +#define I3C_READ_IBI_HW          0
>> +#define I2C_WRITE                1
>> +#define I2C_READ                 2
> ?
> 
> Can an enumeration become helpful here?
> 
No, these are hardware program defined op-codes not created for any 
software purpose. so Macro define looks fine to me.
> Regards,
> Markus



From krzk at kernel.org  Fri Mar 28 07:33:19 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 28 Mar 2025 15:33:19 +0100
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
Message-ID: <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>

On 28/03/2025 15:28, Mukesh Kumar Savaliya wrote:
> Thanks Krzysztof for immediate review !
> 
> On 3/26/2025 7:53 PM, Krzysztof Kozlowski wrote:
>> On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
>>> Add device tree bindings for the Qualcomm I3C controller. This includes
>>> the necessary documentation and properties required to describe the
>>> hardware in the device tree.
>>>
>>> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>>> ---
>>>   .../bindings/i3c/qcom,i3c-master.yaml         | 60 +++++++++++++++++++
>>>   1 file changed, 60 insertions(+)
>>>   create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>>
>>> diff --git a/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>> new file mode 100644
>>> index 000000000000..af6b393f2327
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>
>> Naming: nothing improved.
>>
> Sorry, i didn't get exactly. To your comment "Filename matching 
> compatible." i have Changed the compatible string to "qcom,i3c-master" 
> and now it's matching to file name.
> 
> shall i make filename as qcom,i3c-master-qcom.yaml ? If this is wrong, 
> please suggest.
> 
> Removed "bindings" from the subject line too. I have removed "master" 
> from the description, shall i remove from subject also and keep only 
> controller ? I kept master controller thinking it may be good as "master 
> controller" instead "controller".

I still see the "master" in the compatible and filename.

> 
> 
>>> @@ -0,0 +1,60 @@
>>> +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/i3c/qcom,i3c-master.yaml#
>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>> +
>>> +title: Qualcomm Geni based QUP I3C Controller
>>> +
>>> +maintainers:
>>> +  - Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>>> +
>>> +description:
>>> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
>>> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
>>> +  hotjoin, IBI mechanism.
>>> +
>>> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
>>> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
>>> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
>>> +
>>> +allOf:
>>> +  - $ref: i3c.yaml#
>>> +
>>> +properties:
>>> +  compatible:
>>> +    const: qcom,i3c-master
>>
>> And this got worse. It makes also no sense either: how can you claim
>> that this covers all possible future I3C masters from Qualcomm?
>>
>> What was the resolution of previous discussion?
>>
> Below was my understanding and reply.
> "
> I think i should remove const. kept it for now as no other compatible to 
> be added as of now.
> let me remove const.
> SoC name is not required, as this compatible is generic to all the SOCs.

I don't see any talks about const, what are you referring to?

> "
> 
> But i realized i missed to remove const, sorry for that.
> 
> 
> I have also checked for qcom,spi-geni-qcom.yaml, it has below :
> properties:
>    compatible:
>      const: qcom,geni-spi
> 
> Let me know if i can correct for SPI in separate new patch ?

I love such arguments - let's find whatever old bindings and whatever
antipattern.

What was the outcome of the discussion? I think was about geni, no? What
did Rob write? So how did it became i3c-master?

Best regards,
Krzysztof


From krzk at kernel.org  Fri Mar 28 07:35:32 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 28 Mar 2025 15:35:32 +0100
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <f6b0cec1-a20d-4ed8-84b2-06d464ae5e0c@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <d0b178ab-ad22-4230-a790-6a19a6abfd89@kernel.org>
 <f6b0cec1-a20d-4ed8-84b2-06d464ae5e0c@quicinc.com>
Message-ID: <f0bb768d-ee4e-46c1-b8cc-5d1c3627063e@kernel.org>

On 28/03/2025 15:28, Mukesh Kumar Savaliya wrote:
> Thanks Krzysztof for correcting !
> 
> On 3/26/2025 7:58 PM, Krzysztof Kozlowski wrote:
>> On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
>>> +
>>> +static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
>>> +{
>>> +	int ret;
>>> +
>>> +	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
>>> +	if (IS_ERR(gi3c->se.base))
>>> +		return PTR_ERR(gi3c->se.base);
>>> +
>>> +	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");
>>
>> Never tested.
>>
> sorry, i ran and i got below error now:

Please do the tests *before* you post changes You do not need community
reviewer to tell you to do static/compile time checks on your code.

> i3c at 884000: Unevaluated properties are not allowed ('clock-names', 
> 'interrupts' were unexpected).
> 
> so i have made below change and ran dt_binding_check + dtbs_check, i 
> could fix the issue. Let me have this review internally specific to 
> dt-binding and will post next patch after internal review. So i can 
> avoid such misses.
> 
> yaml :
> +  clock-names:
> +    const: se
> +
> -  - interrupts-extended
> +  - interrupts
> 
> example:
> clock-names = "se";

No, drop clock names entirely, not really useful for one entry using
block's name. Just get the first clock, like most of the drivers.
> 


Best regards,
Krzysztof


From quic_msavaliy at quicinc.com  Sat Mar 29 02:08:43 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Sat, 29 Mar 2025 14:38:43 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
Message-ID: <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>



On 3/28/2025 8:03 PM, Krzysztof Kozlowski wrote:
> On 28/03/2025 15:28, Mukesh Kumar Savaliya wrote:
>> Thanks Krzysztof for immediate review !
>>
>> On 3/26/2025 7:53 PM, Krzysztof Kozlowski wrote:
>>> On 26/03/2025 15:16, Mukesh Kumar Savaliya wrote:
>>>> Add device tree bindings for the Qualcomm I3C controller. This includes
>>>> the necessary documentation and properties required to describe the
>>>> hardware in the device tree.
>>>>
>>>> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>>>> ---
>>>>    .../bindings/i3c/qcom,i3c-master.yaml         | 60 +++++++++++++++++++
>>>>    1 file changed, 60 insertions(+)
>>>>    create mode 100644 Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>>> new file mode 100644
>>>> index 000000000000..af6b393f2327
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/i3c/qcom,i3c-master.yaml
>>>
>>> Naming: nothing improved.
>>>
>> Sorry, i didn't get exactly. To your comment "Filename matching
>> compatible." i have Changed the compatible string to "qcom,i3c-master"
>> and now it's matching to file name.
>>
>> shall i make filename as qcom,i3c-master-qcom.yaml ? If this is wrong,
>> please suggest.
>>
>> Removed "bindings" from the subject line too. I have removed "master"
>> from the description, shall i remove from subject also and keep only
>> controller ? I kept master controller thinking it may be good as "master
>> controller" instead "controller".
> 
> I still see the "master" in the compatible and filename.
> 
File Name : qcom,i3c-geni-qcom.yaml
Compatible name : "qcom,i3c-geni"
+
Remove master from subject too "dt-bindings: i3c: Add Qualcomm I3C 
controller"

will this be fine ?
>>
>>
>>>> @@ -0,0 +1,60 @@
>>>> +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/i3c/qcom,i3c-master.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Qualcomm Geni based QUP I3C Controller
>>>> +
>>>> +maintainers:
>>>> +  - Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>>>> +
>>>> +description:
>>>> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
>>>> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
>>>> +  hotjoin, IBI mechanism.
>>>> +
>>>> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
>>>> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
>>>> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
>>>> +
>>>> +allOf:
>>>> +  - $ref: i3c.yaml#
>>>> +
>>>> +properties:
>>>> +  compatible:
>>>> +    const: qcom,i3c-master
>>>
>>> And this got worse. It makes also no sense either: how can you claim
>>> that this covers all possible future I3C masters from Qualcomm?
>>>
>>> What was the resolution of previous discussion?
>>>
>> Below was my understanding and reply.
>> "
>> I think i should remove const. kept it for now as no other compatible to
>> be added as of now.
>> let me remove const.
>> SoC name is not required, as this compatible is generic to all the SOCs.
> 
> I don't see any talks about const, what are you referring to?
> 
+properties:
+  compatible:
+    : qcom,i3c-geni
will this be fine ?


>> "
>>
>> But i realized i missed to remove const, sorry for that.
>>
>>
>> I have also checked for qcom,spi-geni-qcom.yaml, it has below :
>> properties:
>>     compatible:
>>       const: qcom,geni-spi
>>
>> Let me know if i can correct for SPI in separate new patch ?
> 
> I love such arguments - let's find whatever old bindings and whatever
> antipattern.
Sure, once i know what should be the ideal pattern which is 
unique/should be unique, will share you other files.
> 
> What was the outcome of the discussion? I think was about geni, no? What
> did Rob write? So how did it became i3c-master?
> 
yes, so "qcom,i3c-geni" is fine ?

> Best regards,
> Krzysztof



From quic_msavaliy at quicinc.com  Sat Mar 29 02:08:14 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Sat, 29 Mar 2025 14:38:14 +0530
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
 <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
Message-ID: <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>

Hi Markus,

On 3/29/2025 12:34 AM, Markus Elfring wrote:
>>> Under which circumstances would you become interested to apply a statement
>>> like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
>> Didn't get, hence a question.? Do you suggest to use DEFINE_LOCK_GUARD_1 instead of existing method ?
> I propose to pick further opportunities up for benefits from scope-based resource management.
> 
Sorry, still not clear to me what should i add/change ? please share me 
some example.
> Regards,
> Markus



From quic_msavaliy at quicinc.com  Sat Mar 29 02:09:20 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Sat, 29 Mar 2025 14:39:20 +0530
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <Z+RdgfrQ2zs9Szt3@lizhi-Precision-Tower-5810>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <Z+RdgfrQ2zs9Szt3@lizhi-Precision-Tower-5810>
Message-ID: <00056e46-553c-4050-b363-25951a1191ac@quicinc.com>

Thanks Frank !

On 3/27/2025 1:33 AM, Frank Li wrote:
> On Wed, Mar 26, 2025 at 07:46:40PM +0530, Mukesh Kumar Savaliya wrote:
>> Add support for the Qualcomm I3C controller driver, which implements
>> I3C master functionality as defined in the MIPI Alliance Specification
>> for I3C, Version 1.0.
>>
>> This driver supports master role in SDR mode.
>>
>> Unlike some other I3C master controllers, this implementation
>> does not support In-Band Interrupts (IBI) and Hot-join requests.
>>
>> Signed-off-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>> ---
>>   drivers/i3c/master/Kconfig           |   12 +
>>   drivers/i3c/master/Makefile          |    1 +
>>   drivers/i3c/master/qcom-i3c-master.c | 1107 ++++++++++++++++++++++++++
>>   3 files changed, 1120 insertions(+)
>>   create mode 100644 drivers/i3c/master/qcom-i3c-master.c
>>
>> diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
>> index 77da199c7413..5370cadfe236 100644
>> --- a/drivers/i3c/master/Kconfig
>> +++ b/drivers/i3c/master/Kconfig
>> @@ -44,6 +44,18 @@ config SVC_I3C_MASTER
>>   	help
>>   	  Support for Silvaco I3C Dual-Role Master Controller.
>>
>> +config QCOM_I3C_MASTER
>> +	tristate "Qualcomm Technologies Inc.'s I3C Master controller driver"
>> +	depends on I3C
>> +	help
>> +	This driver supports QUPV3 GENI based I3C controller in master
> 
> It should have extrn 2 space
> 
> 	help
> 	  This driver ....
> 
Understood, will add this change in v3.
>> +	mode on the Qualcomm Technologies Inc.s SoCs. If you say yes to
>> +	this option, support will be included for the built-in I3C interface
>> +	on the Qualcomm Technologies Inc.s SoCs.
>> +
>> +	This driver can also be built as a module.  If so, the module
>> +	will be called qcom-i3c-master.
>> +
>>   config MIPI_I3C_HCI
>>   	tristate "MIPI I3C Host Controller Interface driver (EXPERIMENTAL)"
>>   	depends on I3C
>> diff --git a/drivers/i3c/master/Makefile b/drivers/i3c/master/Makefile
>> index 3e97960160bc..f6670a63b34f 100644
>> --- a/drivers/i3c/master/Makefile
>> +++ b/drivers/i3c/master/Makefile
>> @@ -4,3 +4,4 @@ obj-$(CONFIG_DW_I3C_MASTER)		+= dw-i3c-master.o
>>   obj-$(CONFIG_AST2600_I3C_MASTER)	+= ast2600-i3c-master.o
>>   obj-$(CONFIG_SVC_I3C_MASTER)		+= svc-i3c-master.o
>>   obj-$(CONFIG_MIPI_I3C_HCI)		+= mipi-i3c-hci/
>> +obj-$(CONFIG_QCOM_I3C_MASTER)		+= qcom-i3c-master.o
>> diff --git a/drivers/i3c/master/qcom-i3c-master.c b/drivers/i3c/master/qcom-i3c-master.c
>> new file mode 100644
>> index 000000000000..54778a6baa70
>> --- /dev/null
>> +++ b/drivers/i3c/master/qcom-i3c-master.c
>> @@ -0,0 +1,1107 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
>> + *
>> + * Author: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>> + */
>> +
>> +#include <linux/bits.h>
>> +#include <linux/clk.h>
>> +#include <linux/err.h>
>> +#include <linux/i3c/master.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/slab.h>
>> +#include <linux/soc/qcom/geni-se.h>
>> +
>> +#define SE_I3C_SCL_HIGH                 0x268
>> +#define SE_I3C_TX_TRANS_LEN             0x26C
>> +#define SE_I3C_RX_TRANS_LEN             0x270
>> +#define SE_I3C_DELAY_COUNTER            0x274
>> +#define SE_I2C_SCL_COUNTERS             0x278
>> +#define SE_I3C_SCL_CYCLE                0x27C
> 
> please use low case hex value
> 
>> +#define SE_GENI_HW_IRQ_EN               0x920
>> +#define SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE 0x924
>> +#define SE_GENI_HW_IRQ_CMD_PARAM_0      0x930
>> +
>> +/* HW I3C IBI interrupt enable */
>> +#define M_IBI_IRQ_EN BIT(0)
>> +
>> +/* M_IBI_IRQ_IGNORE */
>> +#define M_IBI_IRQ_IGNORE BIT(0)
>> +
>> +/* SE_GENI_M_CLK_CFG field shifts */
>> +#define	CLK_DIV_VALUE_MASK	GENMASK(23, 4)
>> +#define SER_CLK_EN		BIT(0)
>> +
>> +/* SE_GENI_HW_IRQ_CMD_PARAM_0 field bits */
>> +#define M_IBI_IRQ_PARAM_7E BIT(0)
>> +#define M_IBI_IRQ_PARAM_STOP_STALL BIT(1)
>> +/* SE_I2C_SCL_COUNTERS field shifts */
>> +#define I2C_SCL_HIGH_COUNTER_MASK	GENMASK(29, 20)
>> +#define I2C_SCL_LOW_COUNTER_MASK	GENMASK(19, 10)
>> +#define I2C_SCL_CYCLE_COUNTER_MASK	GENMASK(9, 0)
>> +
>> +#define SE_I3C_ERR  (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
>> +	M_CMD_ABORT_EN | M_GP_IRQ_0_EN | M_GP_IRQ_1_EN | M_GP_IRQ_2_EN | \
>> +	M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
>> +
>> +/* M_CMD OP codes for I2C/I3C */
>> +#define I3C_READ_IBI_HW          0
>> +#define I2C_WRITE                1
>> +#define I2C_READ                 2
>> +#define I2C_WRITE_READ           3
>> +#define I2C_ADDR_ONLY            4
>> +#define I3C_INBAND_RESET         5
>> +#define I2C_BUS_CLEAR            6
>> +#define I2C_STOP_ON_BUS          7
>> +#define I3C_HDR_DDR_EXIT         8
>> +#define I3C_PRIVATE_WRITE        9
>> +#define I3C_PRIVATE_READ         10
>> +#define I3C_HDR_DDR_WRITE        11
>> +#define I3C_HDR_DDR_READ         12
>> +#define I3C_DIRECT_CCC_ADDR_ONLY 13
>> +#define I3C_BCAST_CCC_ADDR_ONLY  14
>> +#define I3C_READ_IBI             15
>> +#define I3C_BCAST_CCC_WRITE      16
>> +#define I3C_DIRECT_CCC_WRITE     17
>> +#define I3C_DIRECT_CCC_READ      18
>> +
>> +/* M_CMD params for I3C */
>> +#define PRE_CMD_DELAY          BIT(0)
>> +#define TIMESTAMP_BEFORE       BIT(1)
>> +#define STOP_STRETCH           BIT(2)
>> +#define TIMESTAMP_AFTER        BIT(3)
>> +#define POST_COMMAND_DELAY     BIT(4)
>> +#define IGNORE_ADD_NACK        BIT(6)
>> +#define READ_FINISHED_WITH_ACK BIT(7)
>> +#define CONTINUOUS_MODE_DAA    BIT(8)
>> +
>> +#define SLAVE_ADDR_MASK           GENMASK(15, 9)
>> +#define SLV_ADDR_SHFT          9
>> +
>> +#define CCC_HDR_CMD_MSK        GENMASK(23, 16)
>> +#define CCC_HDR_CMD_SHFT       16
>> +#define IBI_NACK_TBL_CTRL      BIT(24)
>> +#define USE_7E                 BIT(25)
>> +#define BYPASS_ADDR_PHASE      BIT(26)
>> +
>> +/* GSI callback error fields - DMA_TX_IRQ_STAT */
>> +#define GP_IRQ0	BIT(5)
>> +#define GP_IRQ1	BIT(6)
>> +#define GP_IRQ2	BIT(7)
>> +#define GP_IRQ3	BIT(8)
>> +#define GP_IRQ4	BIT(9)
>> +#define GP_IRQ5	BIT(10)
>> +#define DM_I3C_CB_ERR   GENMASK(10, 5)
>> +
>> +#define I3C_AUTO_SUSPEND_DELAY  250
>> +#define KHZ(freq)               (1000 * (freq))
>> +#define PACKING_BYTES_PW        4
>> +#define XFER_TIMEOUT            250
>> +#define DFS_INDEX_MAX           7
>> +
>> +#define I3C_ADDR_MASK 0x7f
>> +
>> +enum geni_i3c_err_code {
>> +	RD_TERM,
>> +	NACK,
>> +	CRC_ERR,
>> +	BUS_PROTO,
>> +	NACK_7E,
>> +	NACK_IBI,
>> +	GENI_OVERRUN,
>> +	GENI_ILLEGAL_CMD,
>> +	GENI_ABORT_DONE,
>> +	GENI_TIMEOUT,
>> +};
>> +
>> +enum i3c_bus_phase {
>> +	OPEN_DRAIN_MODE  = 0,
>> +	PUSH_PULL_MODE   = 1
>> +};
>> +
>> +struct geni_i3c_dev {
>> +	struct geni_se se;
>> +	unsigned int tx_wm;
>> +	int irq;
>> +	int err;
>> +	struct i3c_master_controller ctrlr;
>> +	struct completion done;
>> +	/* Protects per device CCC command or transfer from get_mutex_lock()/unlock() wrapper */
>> +	struct mutex lock;
>> +	/* Per device protection between process and IRQ context */
>> +	spinlock_t irq_lock;
>> +	u32 clk_src_freq;
>> +	u8 *cur_buf;
>> +	bool cur_is_write;
>> +	int cur_len;
>> +	int cur_idx;
>> +	//unsigned long newaddrslots[(I3C_ADDR_MASK + 1) / BITS_PER_LONG];
>> +	DECLARE_BITMAP(newaddrslots, 64);
>> +
>> +	const struct geni_i3c_clk_settings *clk_cfg;
>> +	const struct geni_i3c_clk_settings *clk_od_cfg;
>> +};
>> +
>> +struct geni_i3c_i2c_dev_data {
>> +	u32 ibi_keeping;  /* Plan to save IBI information, keep as dummy for now */
> 
> Remove it, add it only when use it.
> 
>> +};
>> +
>> +struct geni_i3c_xfer_params {
>> +	enum geni_se_xfer_mode mode;
>> +	u32 m_cmd;
>> +	u32 m_param;
>> +};
>> +
>> +static inline struct geni_i3c_dev *to_geni_i3c_master(struct i3c_master_controller
>> +							*master)
>> +{
>> +	return container_of(master, struct geni_i3c_dev, ctrlr);
>> +}
>> +
>> +struct geni_i3c_clk_settings {
>> +	u32 clk_freq_out;
>> +	u32 clk_src_freq;
>> +	u8  clk_div;
>> +	u8  i2c_t_high_cnt;
>> +	u8  i2c_t_low_cnt;
>> +	u8  i3c_t_high_cnt;
>> +	u8  i3c_t_cycle_cnt;
>> +	u8  i2c_t_cycle_cnt;
>> +};
>> +
>> +/*
>> + * Hardware uses the underlying formula to calculate time periods of
>> + * SCL clock cycle. Firmware uses some additional cycles excluded from the
>> + * below formula and it is confirmed that the time periods are within
>> + * specification limits.
>> + *
>> + * time of high period of I2C SCL:
>> + *         i2c_t_high = (i2c_t_high_cnt * clk_div) / source_clock
>> + * time of low period of I2C SCL:
>> + *         i2c_t_low = (i2c_t_low_cnt * clk_div) / source_clock
>> + * time of full period of I2C SCL:
>> + *         i2c_t_cycle = (i2c_t_cycle_cnt * clk_div) / source_clock
>> + * time of high period of I3C SCL:
>> + *         i3c_t_high = (i3c_t_high_cnt * clk_div) / source_clock
>> + * time of full period of I3C SCL:
>> + *         i3c_t_cycle = (i3c_t_cycle_cnt * clk_div) / source_clock
>> + * clk_freq_out = t / t_cycle
>> + */
>> +static const struct geni_i3c_clk_settings geni_i3c_clk_map[] = {
>> +/* op-freq,  src-freq,  div,  i2c_high,  i2c_low, i3c_high, i3c_cyc i2c_cyc */
>> +	{ KHZ(100),    KHZ(19200), 1, 76, 90, 7, 8, 192},
>> +	{ KHZ(400),    KHZ(19200), 1, 12, 24, 7, 8, 48},
>> +	{ KHZ(1000),   KHZ(19200), 1,  4,  9, 7, 0, 19},
>> +	{ KHZ(12500), KHZ(100000), 1, 45, 63, 6, 7, 110},
>> +};
>> +
>> +static int geni_i3c_clk_map_idx(struct geni_i3c_dev *gi3c)
>> +{
>> +	const struct geni_i3c_clk_settings *clk_idx = geni_i3c_clk_map;
>> +	struct i3c_master_controller *m = &gi3c->ctrlr;
>> +	struct i3c_bus *bus = i3c_master_get_bus(m);
>> +	int i;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(geni_i3c_clk_map); i++, clk_idx++) {
>> +		if ((!bus || clk_idx->clk_freq_out == bus->scl_rate.i3c) &&
>> +		    clk_idx->clk_src_freq == gi3c->clk_src_freq) {
>> +			gi3c->clk_cfg = clk_idx;
>> +		}
>> +
>> +		if (clk_idx->clk_freq_out == bus->scl_rate.i2c)
>> +			gi3c->clk_od_cfg = clk_idx;
>> +	}
>> +
>> +	if (!gi3c->clk_cfg || !gi3c->clk_od_cfg)
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>> +
>> +static void set_new_addr_slot(unsigned long *addrslot, u8 addr)
>> +{
>> +	if (addr > I3C_ADDR_MASK)
>> +		return;
>> +
>> +	set_bit(addr, addrslot);
>> +}
>> +
>> +static void clear_new_addr_slot(unsigned long *addrslot, u8 addr)
>> +{
>> +	if (addr > I3C_ADDR_MASK)
>> +		return;
>> +
>> +	clear_bit(addr, addrslot);
>> +}
>> +
>> +static bool is_new_addr_slot_set(unsigned long *addrslot, u8 addr)
>> +{
>> +	if (addr > I3C_ADDR_MASK)
>> +		return false;
>> +
>> +	return test_bit(addr, addrslot);
>> +}
>> +
>> +static void qcom_geni_i3c_conf(struct geni_i3c_dev *gi3c, enum i3c_bus_phase bus_phase)
>> +{
>> +	const struct geni_i3c_clk_settings *clk_idx = gi3c->clk_cfg;
>> +	unsigned long freq;
>> +	u32 val, dfs_idx;
>> +	int ret;
>> +
>> +	if (bus_phase == OPEN_DRAIN_MODE)
>> +		clk_idx = gi3c->clk_od_cfg;
>> +
>> +	ret = geni_se_clk_freq_match(&gi3c->se, clk_idx->clk_src_freq,
>> +				     &dfs_idx, &freq, false);
>> +	if (ret)
>> +		dfs_idx = 0;
>> +
>> +	writel_relaxed(dfs_idx, gi3c->se.base + SE_GENI_CLK_SEL);
>> +
>> +	val = FIELD_PREP(CLK_DIV_VALUE_MASK, clk_idx->clk_div);
>> +	val |= SER_CLK_EN;
>> +	writel_relaxed(val, gi3c->se.base + GENI_SER_M_CLK_CFG);
>> +
>> +	val = FIELD_PREP(I2C_SCL_HIGH_COUNTER_MASK, clk_idx->i2c_t_high_cnt);
>> +	val |= FIELD_PREP(I2C_SCL_LOW_COUNTER_MASK, clk_idx->i2c_t_low_cnt);
>> +	val |= FIELD_PREP(I2C_SCL_CYCLE_COUNTER_MASK, clk_idx->i2c_t_cycle_cnt);
>> +	writel_relaxed(val, gi3c->se.base + SE_I2C_SCL_COUNTERS);
>> +
>> +	writel_relaxed(clk_idx->i3c_t_cycle_cnt, gi3c->se.base + SE_I3C_SCL_CYCLE);
>> +	writel_relaxed(clk_idx->i3c_t_high_cnt, gi3c->se.base + SE_I3C_SCL_HIGH);
>> +
>> +	writel_relaxed(M_IBI_IRQ_IGNORE, gi3c->se.base + SE_GENI_HW_IRQ_IGNORE_ON_ACTIVE);
>> +
>> +	val = M_IBI_IRQ_PARAM_STOP_STALL | M_IBI_IRQ_PARAM_7E;
>> +	writel_relaxed(val, gi3c->se.base + SE_GENI_HW_IRQ_CMD_PARAM_0);
>> +
>> +	writel_relaxed(M_IBI_IRQ_EN, gi3c->se.base + SE_GENI_HW_IRQ_EN);
>> +}
>> +
>> +static void geni_i3c_handle_err(struct geni_i3c_dev *gi3c, u32 status)
>> +{
>> +	dev_dbg(gi3c->se.dev, "len:%d, %s\n",
>> +		gi3c->cur_len, gi3c->cur_is_write ? "write" : "read");
>> +
>> +	if (status & M_GP_IRQ_0_EN) {
>> +		gi3c->err = -EINVAL;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "I3C slave early read termination");
>> +	}
>> +	if (status & M_GP_IRQ_1_EN) {
>> +		gi3c->err = -ENOTCONN;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK: slave unresponsive, check power/reset");
>> +	}
>> +	if (status & M_GP_IRQ_2_EN) {
>> +		gi3c->err = -EINVAL;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "CRC or parity error");
>> +	}
>> +	if (status & M_GP_IRQ_3_EN) {
>> +		gi3c->err = -EPROTO;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "Bus proto Error, noisy/unexpected start/stop");
>> +	}
>> +	if (status & M_GP_IRQ_4_EN) {
>> +		gi3c->err = -EBUSY;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK on 7E, unexpected protocol error");
>> +	}
>> +	if (status & M_GP_IRQ_5_EN) {
>> +		gi3c->err = -EINVAL;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "NACK on IBI");
>> +	}
>> +	if (status & M_CMD_OVERRUN_EN) {
>> +		gi3c->err = -EIO;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "Cmd overrun, check GENI cmd-state machine");
>> +	}
>> +	if (status & M_ILLEGAL_CMD_EN) {
>> +		gi3c->err = -EILSEQ;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "Illegal cmd, check GENI cmd-state machine");
>> +	}
>> +	if (status & M_CMD_ABORT_EN) {
>> +		gi3c->err = -ETIMEDOUT;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "Abort after timeout successful");
>> +	}
>> +	if (status & GENI_TIMEOUT) {
>> +		gi3c->err = -ETIMEDOUT;
>> +		dev_dbg(gi3c->se.dev, "%s\n", "I3C transaction timed out");
>> +	}
>> +}
>> +
>> +static irqreturn_t geni_i3c_irq(int irq, void *dev)
>> +{
>> +	u32 m_stat_mask, dm_tx_st, dm_rx_st, m_stat, rx_st, dma;
>> +	struct geni_i3c_dev *gi3c = dev;
>> +	unsigned long flags;
>> +	int j;
>> +
>> +	m_stat = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_STATUS);
>> +	m_stat_mask = readl_relaxed(gi3c->se.base + SE_GENI_M_IRQ_EN);
>> +	rx_st = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFO_STATUS);
>> +	dm_tx_st = readl_relaxed(gi3c->se.base + SE_DMA_TX_IRQ_STAT);
>> +	dm_rx_st = readl_relaxed(gi3c->se.base + SE_DMA_RX_IRQ_STAT);
>> +	dma = readl_relaxed(gi3c->se.base + SE_GENI_DMA_MODE_EN);
>> +
>> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
>> +
>> +	if (m_stat & SE_I3C_ERR || dm_rx_st & DM_I3C_CB_ERR) {
>> +		geni_i3c_handle_err(gi3c, m_stat);
>> +		/* Disable the TX Watermark interrupt to stop TX */
>> +		if (!dma)
>> +			writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
>> +		goto irqret;
>> +	}
>> +
>> +	if (dma) {
>> +		dev_dbg(gi3c->se.dev, "i3c dma tx:0x%x, dma rx:0x%x\n", dm_tx_st, dm_rx_st);
>> +		goto irqret;
>> +	}
>> +
>> +	if ((m_stat &
>> +		(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) &&
>> +		!gi3c->cur_is_write && gi3c->cur_buf) {
>> +		u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
>> +
>> +		for (j = 0; j < rxcnt; j++) {
>> +			u32 val;
>> +			int p = 0;
>> +
>> +			val = readl_relaxed(gi3c->se.base + SE_GENI_RX_FIFOn);
>> +			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
>> +				gi3c->cur_buf[gi3c->cur_idx++] = val & 0xff;
>> +				val >>= 8;
>> +				p++;
>> +			}
>> +			if (gi3c->cur_idx == gi3c->cur_len)
>> +				break;
>> +		}
>> +	} else if (m_stat & M_TX_FIFO_WATERMARK_EN &&
>> +		gi3c->cur_is_write && gi3c->cur_buf) {
>> +		for (j = 0; j < gi3c->tx_wm; j++) {
>> +			u32 temp;
>> +			u32 val = 0;
>> +			int p = 0;
>> +
>> +			while (gi3c->cur_idx < gi3c->cur_len && p < sizeof(val)) {
>> +				temp = gi3c->cur_buf[gi3c->cur_idx++];
>> +				val |= temp << (p * 8);
>> +				p++;
>> +			}
>> +
>> +			writel_relaxed(val, gi3c->se.base + SE_GENI_TX_FIFOn);
>> +			if (gi3c->cur_idx == gi3c->cur_len) {
>> +				writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
>> +				break;
>> +			}
>> +		}
>> +	}
>> +
>> +irqret:
>> +	if (m_stat)
>> +		writel_relaxed(m_stat, gi3c->se.base + SE_GENI_M_IRQ_CLEAR);
>> +
>> +	if (dma) {
>> +		if (dm_tx_st)
>> +			writel_relaxed(dm_tx_st, gi3c->se.base + SE_DMA_TX_IRQ_CLR);
>> +		if (dm_rx_st)
>> +			writel_relaxed(dm_rx_st, gi3c->se.base + SE_DMA_RX_IRQ_CLR);
>> +	}
>> +
>> +	/* if this is err with done-bit not set, handle that through timeout. */
>> +	if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN) {
>> +		writel_relaxed(0, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
>> +		complete(&gi3c->done);
>> +	} else if (dm_tx_st & TX_DMA_DONE || dm_rx_st & RX_DMA_DONE	||
>> +		dm_rx_st & RX_RESET_DONE) {
>> +		complete(&gi3c->done);
>> +	}
>> +
>> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
>> +	return IRQ_HANDLED;
>> +}
>> +
>> +static int i3c_geni_runtime_get_mutex_lock(struct geni_i3c_dev *gi3c)
>> +{
>> +	int ret;
>> +
>> +	mutex_lock(&gi3c->lock);
>> +	reinit_completion(&gi3c->done);
>> +	ret = pm_runtime_get_sync(gi3c->se.dev);
>> +	if (ret < 0) {
>> +		dev_err(gi3c->se.dev, "error turning on SE resources:%d\n", ret);
>> +		pm_runtime_put_noidle(gi3c->se.dev);
>> +		/* Set device in suspended since resume failed */
>> +		pm_runtime_set_suspended(gi3c->se.dev);
>> +		mutex_unlock(&gi3c->lock);
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void i3c_geni_runtime_put_mutex_unlock(struct geni_i3c_dev *gi3c)
>> +{
>> +	pm_runtime_mark_last_busy(gi3c->se.dev);
>> +	pm_runtime_put_autosuspend(gi3c->se.dev);
>> +	mutex_unlock(&gi3c->lock);
>> +}
>> +
>> +static void geni_i3c_abort_xfer(struct geni_i3c_dev *gi3c)
>> +{
>> +	unsigned long time_remaining;
>> +	unsigned long flags;
>> +
>> +	reinit_completion(&gi3c->done);
>> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
>> +	geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
>> +	geni_se_abort_m_cmd(&gi3c->se);
>> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
>> +	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
>> +	if (!time_remaining)
>> +		dev_err(gi3c->se.dev, "Timeout abort_m_cmd\n");
>> +}
>> +
>> +static int _i3c_geni_execute_command(struct geni_i3c_dev *gi3c, struct geni_i3c_xfer_params *xfer)
>> +{
>> +	bool is_write = gi3c->cur_is_write;
>> +	dma_addr_t tx_dma = 0, rx_dma = 0;
>> +	unsigned long time_remaining;
>> +	u32 len = gi3c->cur_len;
>> +	int ret;
>> +
>> +	geni_se_select_mode(&gi3c->se, xfer->mode);
>> +
>> +	gi3c->err = 0;
>> +	gi3c->cur_idx = 0;
>> +
>> +	if (!is_write) {
>> +		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x READ len:%d\n",
>> +			xfer->m_cmd, xfer->m_param, len);
>> +		writel_relaxed(len, gi3c->se.base + SE_I3C_RX_TRANS_LEN);
>> +		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
>> +		if (xfer->mode == GENI_SE_DMA) {
>> +			ret = geni_se_rx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &rx_dma);
>> +			if (ret) {
>> +				xfer->mode = GENI_SE_FIFO;
>> +				geni_se_select_mode(&gi3c->se, xfer->mode);
>> +			}
>> +		}
>> +	} else {
>> +		dev_dbg(gi3c->se.dev, "I3C cmd:0x%x param:0x%x WRITE len:%d\n",
>> +			xfer->m_cmd, xfer->m_param, len);
>> +
>> +		writel_relaxed(len, gi3c->se.base + SE_I3C_TX_TRANS_LEN);
>> +		geni_se_setup_m_cmd(&gi3c->se, xfer->m_cmd, xfer->m_param);
>> +
>> +		if (xfer->mode == GENI_SE_DMA) {
>> +			ret = geni_se_tx_dma_prep(&gi3c->se, gi3c->cur_buf, len, &tx_dma);
>> +			if (ret) {
>> +				xfer->mode = GENI_SE_FIFO;
>> +				geni_se_select_mode(&gi3c->se, xfer->mode);
>> +			}
>> +		}
>> +
>> +		if (xfer->mode == GENI_SE_FIFO && len > 0) /* Get FIFO IRQ */
>> +			writel_relaxed(1, gi3c->se.base + SE_GENI_TX_WATERMARK_REG);
>> +	}
>> +
>> +	time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
>> +	if (!time_remaining) {
>> +		unsigned long flags;
>> +
>> +		dev_dbg(gi3c->se.dev, "Timeout completing FIFO transfer\n");
>> +		spin_lock_irqsave(&gi3c->irq_lock, flags);
>> +		geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
>> +		gi3c->cur_buf = NULL;
>> +		spin_unlock_irqrestore(&gi3c->irq_lock, flags);
>> +		geni_i3c_abort_xfer(gi3c);
>> +	}
>> +
>> +	if (xfer->mode == GENI_SE_DMA) {
>> +		if (gi3c->err) {
>> +			if (is_write)
>> +				writel_relaxed(1, gi3c->se.base + SE_DMA_TX_FSM_RST);
>> +			else
>> +				writel_relaxed(1, gi3c->se.base + SE_DMA_RX_FSM_RST);
>> +
>> +			time_remaining = wait_for_completion_timeout(&gi3c->done, XFER_TIMEOUT);
>> +			dev_dbg(gi3c->se.dev, "Timeout completing DMA transfer\n");
>> +		}
>> +		geni_se_rx_dma_unprep(&gi3c->se, rx_dma, len);
>> +		geni_se_tx_dma_unprep(&gi3c->se, tx_dma, len);
>> +	}
>> +
>> +	ret = gi3c->err;
>> +	if (gi3c->err)
>> +		dev_err(gi3c->se.dev, "I3C transaction error :%d\n", gi3c->err);
>> +
>> +	gi3c->cur_buf = NULL;
>> +	gi3c->err = 0;
>> +
>> +	return ret;
>> +}
>> +
>> +static int i3c_geni_execute_read_command(struct geni_i3c_dev *gi3c,
>> +					 struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
>> +{
>> +	gi3c->cur_is_write = false;
>> +	gi3c->cur_buf = buf;
>> +	gi3c->cur_len = len;
>> +	return _i3c_geni_execute_command(gi3c, xfer);
>> +	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);
> 
> remove these commented code.
> 
>> +}
>> +
>> +static int i3c_geni_execute_write_command(struct geni_i3c_dev *gi3c,
>> +					  struct geni_i3c_xfer_params *xfer, u8 *buf, u32 len)
>> +{
>> +	gi3c->cur_is_write = true;
>> +	gi3c->cur_buf = buf;
>> +	gi3c->cur_len = len;
>> +	return _i3c_geni_execute_command(gi3c, xfer);
>> +	//return geni_i3c_fifo_dma_xfer(gi3c, xfer);
>> +}
>> +
>> +static void geni_i3c_perform_daa(struct geni_i3c_dev *gi3c)
>> +{
>> +	u8 last_dyn_addr = 0;
>> +	int ret;
>> +
>> +	while (1) {
>> +		u8 rx_buf[8], tx_buf[8];
>> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
>> +		struct i3c_device_info info = { 0 };
>> +		struct i3c_dev_desc *i3cdev;
>> +		bool new_device = true;
>> +		u64 pid;
>> +		u8 bcr, dcr, addr;
>> +
>> +		xfer.m_cmd = I2C_READ;
>> +		xfer.m_param = STOP_STRETCH | CONTINUOUS_MODE_DAA | USE_7E;
>> +		ret = i3c_geni_execute_read_command(gi3c, &xfer, rx_buf, 8);
>> +		if (ret)
>> +			break;
>> +
>> +		dcr = rx_buf[7];
>> +		bcr = rx_buf[6];
>> +		pid = ((u64)rx_buf[0] << 40) |
>> +			((u64)rx_buf[1] << 32) |
>> +			((u64)rx_buf[2] << 24) |
>> +			((u64)rx_buf[3] << 16) |
>> +			((u64)rx_buf[4] <<  8) |
>> +			((u64)rx_buf[5]);
>> +
>> +		i3c_bus_for_each_i3cdev(&gi3c->ctrlr.bus, i3cdev) {
>> +			i3c_device_get_info(i3cdev->dev, &info);
>> +			if (pid == info.pid && dcr == info.dcr && bcr == info.bcr) {
>> +				new_device = false;
>> +				addr = (info.dyn_addr) ? info.dyn_addr :
>> +					info.static_addr;
>> +				break;
>> +			}
>> +		}
>> +
>> +		if (new_device) {
>> +			ret = i3c_master_get_free_addr(&gi3c->ctrlr, last_dyn_addr + 1);
>> +			if (ret < 0)
>> +				break;
>> +			addr = (u8)ret;
>> +			last_dyn_addr = (u8)ret;
>> +			set_new_addr_slot(gi3c->newaddrslots, addr);
>> +		}
>> +
>> +		tx_buf[0] = (addr & I3C_ADDR_MASK) << 1;
>> +		tx_buf[0] |= ~(hweight8(addr & I3C_ADDR_MASK) & 1);
>> +
>> +		xfer.m_cmd = I2C_WRITE;
>> +		xfer.m_param = STOP_STRETCH | BYPASS_ADDR_PHASE | USE_7E;
>> +
>> +		ret = i3c_geni_execute_write_command(gi3c, &xfer, tx_buf, 1);
>> +		if (ret)
>> +			break;
>> +	}
>> +}
>> +
>> +static int geni_i3c_master_send_ccc_cmd(struct i3c_master_controller *m,
>> +					struct i3c_ccc_cmd *cmd)
>> +{
>> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
>> +	int i, ret;
>> +
>> +	if (!(cmd->id & I3C_CCC_DIRECT) && cmd->ndests != 1)
>> +		return -EINVAL;
>> +
>> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
>> +	for (i = 0; i < cmd->ndests; i++) {
>> +		int stall = (i < (cmd->ndests - 1)) ||
>> +			(cmd->id == I3C_CCC_ENTDAA);
>> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
>> +
>> +		xfer.m_param  = (stall ? STOP_STRETCH : 0);
>> +		xfer.m_param |= (cmd->id << CCC_HDR_CMD_SHFT);
>> +		xfer.m_param |= IBI_NACK_TBL_CTRL;
>> +		if (cmd->id & I3C_CCC_DIRECT) {
>> +			xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, cmd->dests[i].addr);
>> +			if (cmd->rnw) {
>> +				if (i == 0)
>> +					xfer.m_cmd = I3C_DIRECT_CCC_READ;
>> +				else
>> +					xfer.m_cmd = I3C_PRIVATE_READ;
>> +			} else {
>> +				if (i == 0)
>> +					xfer.m_cmd =
>> +					   (cmd->dests[i].payload.len > 0) ?
>> +						I3C_DIRECT_CCC_WRITE :
>> +						I3C_DIRECT_CCC_ADDR_ONLY;
>> +				else
>> +					xfer.m_cmd = I3C_PRIVATE_WRITE;
>> +			}
>> +		} else {
>> +			if (cmd->dests[i].payload.len > 0)
>> +				xfer.m_cmd = I3C_BCAST_CCC_WRITE;
>> +			else
>> +				xfer.m_cmd = I3C_BCAST_CCC_ADDR_ONLY;
>> +		}
>> +
>> +		if (i == 0)
>> +			xfer.m_param |= USE_7E;
>> +
>> +		if (cmd->rnw)
>> +			ret = i3c_geni_execute_read_command(gi3c, &xfer,
>> +							    cmd->dests[i].payload.data,
>> +							    cmd->dests[i].payload.len);
>> +		else
>> +			ret = i3c_geni_execute_write_command(gi3c, &xfer,
>> +							     cmd->dests[i].payload.data,
>> +							     cmd->dests[i].payload.len);
>> +		if (ret)
>> +			break;
>> +
>> +		if (cmd->id == I3C_CCC_ENTDAA)
>> +			geni_i3c_perform_daa(gi3c);
>> +	}
>> +
>> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
>> +	return ret;
>> +}
>> +
>> +static int geni_i3c_master_priv_xfers(struct i3c_dev_desc *dev, struct i3c_priv_xfer *xfers,
>> +				      int nxfers)
>> +{
>> +	struct i3c_master_controller *m = i3c_dev_get_master(dev);
>> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
>> +	bool use_7e = false;
>> +	int i, ret;
>> +
>> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
>> +
>> +	for (i = 0; i < nxfers; i++) {
>> +		bool stall = (i < (nxfers - 1));
>> +		struct geni_i3c_xfer_params xfer = { GENI_SE_FIFO };
>> +
>> +		xfer.m_param  = (stall ? STOP_STRETCH : 0);
>> +		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, dev->info.dyn_addr);
>> +		xfer.m_param |= (use_7e) ? USE_7E : 0;
>> +
>> +		/* use_7e = true only for last transfer */
>> +		use_7e = (i == nxfers - 1);
>> +
>> +		if (xfers[i].rnw) {
>> +			xfer.m_cmd = I3C_PRIVATE_READ;
>> +			ret = i3c_geni_execute_read_command(gi3c, &xfer, (u8 *)xfers[i].data.in,
>> +							    xfers[i].len);
>> +		} else {
>> +			xfer.m_cmd = I3C_PRIVATE_WRITE;
>> +			ret = i3c_geni_execute_write_command(gi3c, &xfer, (u8 *)xfers[i].data.out,
>> +							     xfers[i].len);
>> +		}
>> +
>> +		if (ret)
>> +			break;
>> +	}
>> +
>> +	dev_dbg(gi3c->se.dev, "i3c priv: txn ret:%d\n", ret);
>> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
>> +	return ret;
>> +}
>> +
>> +static int geni_i3c_master_i2c_xfers(struct i2c_dev_desc *dev, const struct i2c_msg *msgs, int num)
>> +{
>> +	struct i3c_master_controller *m = i2c_dev_get_master(dev);
>> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
>> +	int i, ret;
>> +
>> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qcom_geni_i3c_conf(gi3c, PUSH_PULL_MODE);
>> +
>> +	for (i = 0; i < num; i++) {
>> +		struct geni_i3c_xfer_params xfer;
>> +
>> +		xfer.m_cmd    = (msgs[i].flags & I2C_M_RD) ? I2C_READ : I2C_WRITE;
>> +		xfer.m_param  = (i < (num - 1)) ? STOP_STRETCH : 0;
>> +		xfer.m_param |= FIELD_PREP(SLAVE_ADDR_MASK, msgs[i].addr);
>> +		xfer.mode     = msgs[i].len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
>> +		if (msgs[i].flags & I2C_M_RD)
>> +			ret = i3c_geni_execute_read_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
>> +		else
>> +			ret = i3c_geni_execute_write_command(gi3c, &xfer, msgs[i].buf, msgs[i].len);
>> +		if (ret)
>> +			break;
>> +	}
>> +
>> +	dev_dbg(gi3c->se.dev, "i2c: txn ret:%d\n", ret);
>> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
>> +	return ret;
>> +}
>> +
>> +static int geni_i3c_master_attach_i2c_dev(struct i2c_dev_desc *dev)
>> +{
>> +	struct geni_i3c_i2c_dev_data *data;
>> +
>> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	i2c_dev_set_master_data(dev, data);
>> +	return 0;
>> +}
>> +
>> +static void geni_i3c_master_detach_i2c_dev(struct i2c_dev_desc *dev)
>> +{
>> +	struct geni_i3c_i2c_dev_data *data = i2c_dev_get_master_data(dev);
>> +
>> +	i2c_dev_set_master_data(dev, NULL);
>> +	kfree(data);
>> +}
>> +
>> +static int geni_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
>> +{
>> +	struct geni_i3c_i2c_dev_data *data;
>> +
>> +	data = kzalloc(sizeof(*data), GFP_KERNEL);
>> +	if (!data)
>> +		return -ENOMEM;
>> +
>> +	i3c_dev_set_master_data(dev, data);
>> +	return 0;
>> +}
>> +
>> +static void geni_i3c_master_detach_i3c_dev(struct i3c_dev_desc *dev)
>> +{
>> +	struct geni_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
>> +
>> +	i3c_dev_set_master_data(dev, NULL);
>> +	kfree(data);
>> +}
>> +
>> +static int geni_i3c_master_do_daa(struct i3c_master_controller *m)
>> +{
>> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
>> +	u8 addr;
>> +	int ret;
>> +
>> +	ret = i3c_master_entdaa_locked(m);
>> +	if (ret && ret != I3C_ERROR_M2)
>> +		return ret;
>> +
>> +	for (addr = 0; addr <= I3C_ADDR_MASK; addr++) {
>> +		if (is_new_addr_slot_set(gi3c->newaddrslots, addr)) {
>> +			clear_new_addr_slot(gi3c->newaddrslots, addr);
>> +			i3c_master_add_i3c_dev_locked(m, addr);
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int geni_i3c_master_bus_init(struct i3c_master_controller *m)
>> +{
>> +	struct geni_i3c_dev *gi3c = to_geni_i3c_master(m);
>> +	struct i3c_bus *bus = i3c_master_get_bus(m);
>> +	struct i3c_device_info info = { };
>> +	int ret;
>> +
>> +	/* Get an address for the master. */
>> +	ret = i3c_master_get_free_addr(m, 0);
>> +	if (ret < 0)
>> +		dev_err(gi3c->se.dev, "%s: error No free addr:%d\n", __func__, ret);
>> +
>> +	info.dyn_addr = ret;
>> +	info.dcr = I3C_DCR_GENERIC_DEVICE;
>> +	info.bcr = I3C_BCR_I3C_MASTER | I3C_BCR_HDR_CAP;
>> +	info.pid = 0;
>> +
>> +	ret = geni_i3c_clk_map_idx(gi3c);
>> +	if (ret)
>> +		dev_err(gi3c->se.dev,
>> +			"Invalid clk frequency %d Hz src for %ld Hz bus: %d\n",
>> +			gi3c->clk_src_freq, bus->scl_rate.i3c, ret);
>> +
>> +	ret = i3c_geni_runtime_get_mutex_lock(gi3c);
>> +	if (ret)
>> +		return ret;
>> +
>> +	qcom_geni_i3c_conf(gi3c, OPEN_DRAIN_MODE);
>> +
>> +	ret = i3c_master_set_info(&gi3c->ctrlr, &info);
>> +	i3c_geni_runtime_put_mutex_unlock(gi3c);
>> +	return ret;
>> +}
>> +
>> +static bool geni_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
>> +					     const struct i3c_ccc_cmd *cmd)
>> +{
>> +	switch (cmd->id) {
>> +	case I3C_CCC_ENEC(true):
>> +		fallthrough;
>> +	case I3C_CCC_ENEC(false):
>> +		fallthrough;
>> +	case I3C_CCC_DISEC(true):
>> +		fallthrough;
>> +	case I3C_CCC_DISEC(false):
>> +		fallthrough;
>> +	case I3C_CCC_ENTAS(0, true):
>> +		fallthrough;
>> +	case I3C_CCC_ENTAS(0, false):
>> +		fallthrough;
>> +	case I3C_CCC_RSTDAA(true):
>> +		fallthrough;
>> +	case I3C_CCC_RSTDAA(false):
>> +		fallthrough;
>> +	case I3C_CCC_ENTDAA:
>> +		fallthrough;
>> +	case I3C_CCC_SETMWL(true):
>> +		fallthrough;
>> +	case I3C_CCC_SETMWL(false):
>> +		fallthrough;
>> +	case I3C_CCC_SETMRL(true):
>> +		fallthrough;
>> +	case I3C_CCC_SETMRL(false):
>> +		fallthrough;
>> +	case I3C_CCC_DEFSLVS:
>> +		fallthrough;
>> +	case I3C_CCC_SETDASA:
>> +		fallthrough;
>> +	case I3C_CCC_SETNEWDA:
>> +		fallthrough;
>> +	case I3C_CCC_GETMWL:
>> +		fallthrough;
>> +	case I3C_CCC_GETMRL:
>> +		fallthrough;
>> +	case I3C_CCC_GETPID:
>> +		fallthrough;
>> +	case I3C_CCC_GETBCR:
>> +		fallthrough;
>> +	case I3C_CCC_GETDCR:
>> +		fallthrough;
>> +	case I3C_CCC_GETSTATUS:
>> +		fallthrough;
>> +	case I3C_CCC_GETACCMST:
>> +		fallthrough;
>> +	case I3C_CCC_GETMXDS:
>> +		fallthrough;
>> +	case I3C_CCC_GETHDRCAP:
>> +		return true;
>> +
>> +	default:
>> +		return false;
>> +	}
>> +}
>> +
>> +static const struct i3c_master_controller_ops geni_i3c_master_ops = {
>> +	.bus_init = geni_i3c_master_bus_init,
>> +	.bus_cleanup = NULL,
>> +	.do_daa = geni_i3c_master_do_daa,
>> +	.attach_i3c_dev = geni_i3c_master_attach_i3c_dev,
>> +	.reattach_i3c_dev = NULL,
>> +	.detach_i3c_dev = geni_i3c_master_detach_i3c_dev,
>> +	.attach_i2c_dev = geni_i3c_master_attach_i2c_dev,
>> +	.detach_i2c_dev = geni_i3c_master_detach_i2c_dev,
>> +	.supports_ccc_cmd = geni_i3c_master_supports_ccc_cmd,
>> +	.send_ccc_cmd = geni_i3c_master_send_ccc_cmd,
>> +	.priv_xfers = geni_i3c_master_priv_xfers,
>> +	.i2c_xfers = geni_i3c_master_i2c_xfers,
>> +	.enable_ibi = NULL,
>> +	.disable_ibi = NULL,
>> +	.request_ibi = NULL,
>> +	.free_ibi = NULL,
>> +	.recycle_ibi_slot = NULL,
>> +};
>> +
>> +static int i3c_geni_resources_init(struct geni_i3c_dev *gi3c, struct platform_device *pdev)
>> +{
>> +	int ret;
>> +
>> +	gi3c->se.base = devm_platform_ioremap_resource(pdev, 0);
>> +	if (IS_ERR(gi3c->se.base))
>> +		return PTR_ERR(gi3c->se.base);
>> +
>> +	gi3c->se.clk = devm_clk_get(&pdev->dev, "se-clk");
>> +	if (IS_ERR(gi3c->se.clk))
>> +		return dev_err_probe(&pdev->dev, PTR_ERR(gi3c->se.clk),
>> +							"Unable to get serial engine core clock: %pe\n",
>> +							gi3c->se.clk);
>> +
>> +	ret = device_property_read_u32(&pdev->dev, "se-clock-frequency", &gi3c->clk_src_freq);
>> +	if (ret) {
>> +		dev_info(&pdev->dev, "SE clk freq not specified, default to 100 MHz.\n");
>> +		/* Default source clock freq is 100Mhz */
>> +		gi3c->clk_src_freq = KHZ(100000);
>> +	}
>> +
>> +	ret = geni_icc_get(&gi3c->se, NULL);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* Set the bus quota to a reasonable value for register access */
>> +	gi3c->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW;
>> +	gi3c->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
>> +	ret = geni_icc_set_bw(&gi3c->se);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
>> +}
>> +
>> +static int geni_i3c_probe(struct platform_device *pdev)
>> +{
>> +	u32 proto, tx_depth, fifo_disable;
>> +	struct geni_i3c_dev *gi3c;
>> +	int ret;
>> +
>> +	gi3c = devm_kzalloc(&pdev->dev, sizeof(*gi3c), GFP_KERNEL);
>> +	if (!gi3c)
>> +		return -ENOMEM;
>> +
>> +	gi3c->se.dev = &pdev->dev;
>> +	gi3c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
>> +
>> +	init_completion(&gi3c->done);
>> +	mutex_init(&gi3c->lock);
>> +	spin_lock_init(&gi3c->irq_lock);
>> +	platform_set_drvdata(pdev, gi3c);
>> +
>> +	ret = i3c_geni_resources_init(gi3c, pdev);
>> +	if (ret)
>> +		return dev_err_probe(&pdev->dev, ret, "Error Initializing GENI Resources\n");
>> +
>> +	gi3c->irq = platform_get_irq(pdev, 0);
>> +	if (gi3c->irq < 0)
>> +		return dev_err_probe(&pdev->dev, gi3c->irq, "Error getting IRQ number for I3C\n");
>> +
>> +	ret = devm_request_irq(&pdev->dev, gi3c->irq, geni_i3c_irq,
>> +			       IRQF_NO_AUTOEN, dev_name(&pdev->dev), gi3c);
>> +	if (ret)
>> +		return dev_err_probe(&pdev->dev, ret, "Error registering core IRQ\n");
>> +
>> +	ret = geni_se_resources_on(&gi3c->se);
>> +	if (ret)
>> +		return dev_err_probe(&pdev->dev, ret, "Error turning resources ON\n");
>> +
>> +	proto = geni_se_read_proto(&gi3c->se);
>> +	if (proto != GENI_SE_I3C) {
>> +		geni_se_resources_off(&gi3c->se);
>> +		return dev_err_probe(&pdev->dev, -ENXIO, "Invalid proto %d\n", proto);
>> +	}
>> +
>> +	fifo_disable = readl_relaxed(gi3c->se.base + GENI_IF_DISABLE_RO);
>> +	if (fifo_disable) {
>> +		geni_se_resources_off(&gi3c->se);
>> +		return dev_err_probe(&pdev->dev, -ENXIO, "GPI DMA mode not supported\n");
>> +	}
>> +
>> +	tx_depth = geni_se_get_tx_fifo_depth(&gi3c->se);
>> +	gi3c->tx_wm = tx_depth - 1;
>> +	geni_se_init(&gi3c->se, gi3c->tx_wm, tx_depth);
>> +	geni_se_config_packing(&gi3c->se, BITS_PER_BYTE, PACKING_BYTES_PW, true, true, true);
>> +	geni_se_resources_off(&gi3c->se);
>> +	dev_dbg(&pdev->dev, "i3c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
>> +
>> +	pm_runtime_set_autosuspend_delay(gi3c->se.dev, I3C_AUTO_SUSPEND_DELAY);
>> +	pm_runtime_use_autosuspend(gi3c->se.dev);
>> +	pm_runtime_set_active(gi3c->se.dev);
>> +	pm_runtime_enable(gi3c->se.dev);
>> +
>> +	ret = i3c_master_register(&gi3c->ctrlr, &pdev->dev, &geni_i3c_master_ops, false);
>> +	if (ret) {
>> +		pm_runtime_disable(gi3c->se.dev);
>> +		pm_runtime_set_suspended(gi3c->se.dev);
>> +		pm_runtime_dont_use_autosuspend(gi3c->se.dev);
>> +		return ret;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static void geni_i3c_remove(struct platform_device *pdev)
>> +{
>> +	struct geni_i3c_dev *gi3c = platform_get_drvdata(pdev);
>> +
>> +	i3c_master_unregister(&gi3c->ctrlr);
>> +	pm_runtime_disable(gi3c->se.dev);
>> +	pm_runtime_set_suspended(gi3c->se.dev);
>> +	pm_runtime_dont_use_autosuspend(gi3c->se.dev);
>> +}
>> +
>> +static int geni_i3c_runtime_suspend(struct device *dev)
>> +{
>> +	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
>> +
>> +	disable_irq(gi3c->irq);
> 
> why need disable irq here?
> 
>> +	geni_se_resources_off(&gi3c->se);
>> +	return 0;
>> +}
>> +
>> +static int geni_i3c_runtime_resume(struct device *dev)
>> +{
>> +	int ret;
>> +	struct geni_i3c_dev *gi3c = dev_get_drvdata(dev);
>> +
>> +	ret = geni_se_resources_on(&gi3c->se);
>> +	if (ret)
>> +		return ret;
>> +	enable_irq(gi3c->irq);
>> +	return 0;
>> +}
>> +
>> +static const struct dev_pm_ops geni_i3c_pm_ops = {
>> +	SET_RUNTIME_PM_OPS(geni_i3c_runtime_suspend, geni_i3c_runtime_resume, NULL)
>> +};
>> +
>> +static const struct of_device_id geni_i3c_dt_match[] = {
>> +	{ .compatible = "qcom,i3c-master" },
>> +	{ }
>> +};
>> +MODULE_DEVICE_TABLE(of, geni_i3c_dt_match);
>> +
>> +static struct platform_driver geni_i3c_master = {
>> +	.probe  = geni_i3c_probe,
>> +	.remove = geni_i3c_remove,
>> +	.driver = {
>> +		.name = "geni_i3c_master",
>> +		.pm = &geni_i3c_pm_ops,
>> +		.of_match_table = geni_i3c_dt_match,
>> +	},
>> +};
>> +
>> +module_platform_driver(geni_i3c_master);
>> +
>> +MODULE_AUTHOR("Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>");
>> +MODULE_DESCRIPTION("Qualcomm I3C Controller Driver for GENI based QUP cores");
>> +MODULE_LICENSE("GPL");
>> --
>> 2.25.1
>>



From alexandre.belloni at bootlin.com  Sat Mar 29 03:48:12 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Sat, 29 Mar 2025 11:48:12 +0100
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
 <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
 <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
Message-ID: <20250329104812225f9ee5@mail.local>

On 29/03/2025 14:38:14+0530, Mukesh Kumar Savaliya wrote:
> Hi Markus,
> 
> On 3/29/2025 12:34 AM, Markus Elfring wrote:
> > > > Under which circumstances would you become interested to apply a statement
> > > > like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
> > > Didn't get, hence a question.? Do you suggest to use DEFINE_LOCK_GUARD_1 instead of existing method ?
> > I propose to pick further opportunities up for benefits from scope-based resource management.
> > 
> Sorry, still not clear to me what should i add/change ? please share me some
> example.

Don't change anything, Markus is wasting your time.

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From krzk at kernel.org  Sat Mar 29 04:06:34 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sat, 29 Mar 2025 12:06:34 +0100
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
 <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
Message-ID: <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>

On 29/03/2025 10:08, Mukesh Kumar Savaliya wrote:
>>>>> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
>>>>> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
>>>>> +  hotjoin, IBI mechanism.
>>>>> +
>>>>> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
>>>>> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
>>>>> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
>>>>> +
>>>>> +allOf:
>>>>> +  - $ref: i3c.yaml#
>>>>> +
>>>>> +properties:
>>>>> +  compatible:
>>>>> +    const: qcom,i3c-master
>>>>
>>>> And this got worse. It makes also no sense either: how can you claim
>>>> that this covers all possible future I3C masters from Qualcomm?
>>>>
>>>> What was the resolution of previous discussion?
>>>>
>>> Below was my understanding and reply.
>>> "
>>> I think i should remove const. kept it for now as no other compatible to
>>> be added as of now.
>>> let me remove const.
>>> SoC name is not required, as this compatible is generic to all the SOCs.
>>
>> I don't see any talks about const, what are you referring to?
>>
> +properties:
> +  compatible:
> +    : qcom,i3c-geni
> will this be fine ?

Yes, I think that was also suggested by Rob. Or rather follow existing
style so qcom,geni-i3c for the compatible and filename.


Best regards,
Krzysztof


From quic_msavaliy at quicinc.com  Sat Mar 29 07:27:22 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Sat, 29 Mar 2025 19:57:22 +0530
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250329104812225f9ee5@mail.local>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
 <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
 <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
 <20250329104812225f9ee5@mail.local>
Message-ID: <3d6738cf-fc4c-4bc6-b986-9a647867e76f@quicinc.com>



On 3/29/2025 4:18 PM, Alexandre Belloni wrote:
> On 29/03/2025 14:38:14+0530, Mukesh Kumar Savaliya wrote:
>> Hi Markus,
>>
>> On 3/29/2025 12:34 AM, Markus Elfring wrote:
>>>>> Under which circumstances would you become interested to apply a statement
>>>>> like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
>>>> Didn't get, hence a question.? Do you suggest to use DEFINE_LOCK_GUARD_1 instead of existing method ?
>>> I propose to pick further opportunities up for benefits from scope-based resource management.
>>>
>> Sorry, still not clear to me what should i add/change ? please share me some
>> example.
> 
> Don't change anything, Markus is wasting your time.
Clear to me. Thanks a lot !
> 



From quic_msavaliy at quicinc.com  Sat Mar 29 07:31:03 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Sat, 29 Mar 2025 20:01:03 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
 <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
 <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>
Message-ID: <838dfc8d-24c3-4f03-9c24-863259bb22b1@quicinc.com>



On 3/29/2025 4:36 PM, Krzysztof Kozlowski wrote:
> On 29/03/2025 10:08, Mukesh Kumar Savaliya wrote:
>>>>>> +  I3C in master mode supports up to 12.5MHz, SDR mode data transfer in mixed
>>>>>> +  bus mode (I2C and I3C target devices on same i3c bus). It also supports
>>>>>> +  hotjoin, IBI mechanism.
>>>>>> +
>>>>>> +  I3C Controller nodes must be child of GENI based Qualcomm Universal
>>>>>> +  Peripharal. Please refer GENI based QUP wrapper controller node bindings
>>>>>> +  described in Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.yaml.
>>>>>> +
>>>>>> +allOf:
>>>>>> +  - $ref: i3c.yaml#
>>>>>> +
>>>>>> +properties:
>>>>>> +  compatible:
>>>>>> +    const: qcom,i3c-master
>>>>>
>>>>> And this got worse. It makes also no sense either: how can you claim
>>>>> that this covers all possible future I3C masters from Qualcomm?
>>>>>
>>>>> What was the resolution of previous discussion?
>>>>>
>>>> Below was my understanding and reply.
>>>> "
>>>> I think i should remove const. kept it for now as no other compatible to
>>>> be added as of now.
>>>> let me remove const.
>>>> SoC name is not required, as this compatible is generic to all the SOCs.
>>>
>>> I don't see any talks about const, what are you referring to?
>>>
>> +properties:
>> +  compatible:
>> +    : qcom,i3c-geni
>> will this be fine ?
> 
> Yes, I think that was also suggested by Rob. Or rather follow existing
> style so qcom,geni-i3c for the compatible and filename.
> 
Sure, makes sense. With below i3c becomes similar in naming conventions 
to spi, i2c, serial uart.

Driver file name : i3c-qcom-geni.c
dt-binding file name: qcom,i3c-geni-qcom.yaml
compatible = "qcom,geni-i3c";
> 
> Best regards,
> Krzysztof



From krzk at kernel.org  Sun Mar 30 02:42:57 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Sun, 30 Mar 2025 11:42:57 +0200
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <838dfc8d-24c3-4f03-9c24-863259bb22b1@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
 <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
 <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>
 <838dfc8d-24c3-4f03-9c24-863259bb22b1@quicinc.com>
Message-ID: <b68559e6-fc2b-493b-9f37-3125ff924a65@kernel.org>

On 29/03/2025 15:31, Mukesh Kumar Savaliya wrote:
> dt-binding file name: qcom,i3c-geni-qcom.yaml

No. I already asked to use compatible as filename. Don't create your own
rules.

> compatible = "qcom,geni-i3c";
>>
>> Best regards,
>> Krzysztof
> 


Best regards,
Krzysztof


From quic_msavaliy at quicinc.com  Sun Mar 30 23:52:47 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Mon, 31 Mar 2025 12:22:47 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <b68559e6-fc2b-493b-9f37-3125ff924a65@kernel.org>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
 <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
 <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>
 <838dfc8d-24c3-4f03-9c24-863259bb22b1@quicinc.com>
 <b68559e6-fc2b-493b-9f37-3125ff924a65@kernel.org>
Message-ID: <c6370b99-efde-46ab-a1a4-65b979ca2dfa@quicinc.com>

Thanks Krzysztof  !

On 3/30/2025 3:12 PM, Krzysztof Kozlowski wrote:
> On 29/03/2025 15:31, Mukesh Kumar Savaliya wrote:
>> dt-binding file name: qcom,i3c-geni-qcom.yaml
> 
> No. I already asked to use compatible as filename. Don't create your own
> rules.
> 
okay, no problem. I was trying to follow previous i2c,spi, serial uart.
Let me make a cleanup patch for them also next as mentioned earlier.

For i3c, compatible will be "geni-i3c" as suggested by you , Rob.
dt-binding filename  "qcom,i3c-geni.yaml" OR "qcom,geni-i3c.yaml" ?
>> compatible = "qcom,geni-i3c";
>>>
>>> Best regards,
>>> Krzysztof
>>
> 
> 
> Best regards,
> Krzysztof



From quic_msavaliy at quicinc.com  Mon Mar 31 00:06:45 2025
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Mon, 31 Mar 2025 12:36:45 +0530
Subject: [PATCH v2 1/3] dt-bindings: i3c: Add Qualcomm I3C master
 controller
In-Reply-To: <c6370b99-efde-46ab-a1a4-65b979ca2dfa@quicinc.com>
References: <20250326141641.3471906-1-quic_msavaliy@quicinc.com>
 <20250326141641.3471906-2-quic_msavaliy@quicinc.com>
 <991b0652-76f2-40d6-b49b-1e6f76e254ac@kernel.org>
 <661e1a21-0f3a-497a-9b3b-fab284e30d19@quicinc.com>
 <36b67f9c-5905-4fa6-8190-ab980850b3a2@kernel.org>
 <e997bd15-728c-4316-8050-d461f115fd9f@quicinc.com>
 <04945ad2-1372-4c73-beae-fc6449fb9a76@kernel.org>
 <838dfc8d-24c3-4f03-9c24-863259bb22b1@quicinc.com>
 <b68559e6-fc2b-493b-9f37-3125ff924a65@kernel.org>
 <c6370b99-efde-46ab-a1a4-65b979ca2dfa@quicinc.com>
Message-ID: <336dc6ad-6e9e-439d-b7c4-7fea1c5cd8e9@quicinc.com>



On 3/31/2025 12:22 PM, Mukesh Kumar Savaliya wrote:
> Thanks Krzysztof? !
> 
> On 3/30/2025 3:12 PM, Krzysztof Kozlowski wrote:
>> On 29/03/2025 15:31, Mukesh Kumar Savaliya wrote:
>>> dt-binding file name: qcom,i3c-geni-qcom.yaml
>>
>> No. I already asked to use compatible as filename. Don't create your own
>> rules.
>>
> okay, no problem. I was trying to follow previous i2c,spi, serial uart.
> Let me make a cleanup patch for them also next as mentioned earlier.
> 
> For i3c, compatible will be "geni-i3c" as suggested by you , Rob.
> dt-binding filename? "qcom,i3c-geni.yaml" OR "qcom,geni-i3c.yaml" ?
>>> compatible = "qcom,geni-i3c";
Please Ignore previous ask. I will go with filename = qcom,geni-i3c.yaml

>>>>
>>>> Best regards,
>>>> Krzysztof
>>>
>>
>>
>> Best regards,
>> Krzysztof
> 
> 



From alexandre.belloni at bootlin.com  Mon Mar 31 02:42:12 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 31 Mar 2025 11:42:12 +0200
Subject: [PATCH v2 1/1] i3c: master: Drop duplicate check before calling
 OF APIs
In-Reply-To: <20250321193044.457649-1-andriy.shevchenko@linux.intel.com>
References: <20250321193044.457649-1-andriy.shevchenko@linux.intel.com>
Message-ID: <174341411812.1099775.9355586066348391329.b4-ty@bootlin.com>

On Fri, 21 Mar 2025 21:30:06 +0200, Andy Shevchenko wrote:
> OF APIs are usually NULL-aware and returns an error in case when
> device node is not present or supported. We already have a check
> for the returned value, no need to check for the parameter.
> 
> 

Applied, thanks!

[1/1] i3c: master: Drop duplicate check before calling OF APIs
      https://git.kernel.org/abelloni/c/465e5486aa5e

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From manjunatha.venkatesh at nxp.com  Tue Mar 25 01:30:28 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Tue, 25 Mar 2025 08:30:28 +0000
Subject: [EXT] Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
 memory at svc_i3c_master_ibi_work()
In-Reply-To: <2025031717392264f19f1a@mail.local>
References: <20250312135356.2318667-1-manjunatha.venkatesh@nxp.com>
 <Z9HSdtD1CkdCpGu9@lizhi-Precision-Tower-5810>
 <VI1PR04MB10049644F3287C378E9CC75EF8FD32@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810>
 <VI1PR04MB1004979B7D38486FD1E1CC8508FDF2@VI1PR04MB10049.eurprd04.prod.outlook.com>
 <2025031717392264f19f1a@mail.local>
Message-ID: <VI1PR04MB1004925DA8849F00F722EC8288FA72@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Alexandre Belloni <alexandre.belloni at bootlin.com>
> Sent: Monday, March 17, 2025 11:09 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: Frank Li <frank.li at nxp.com>; miquel.raynal at bootlin.com;
> conor.culhane at silvaco.com; linux-i3c at lists.infradead.org; linux-
> kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> Subject: [EXT] Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
> memory at svc_i3c_master_ibi_work()
> 
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
> 
> 
> On 17/03/2025 15:46:52+0000, Manjunatha Venkatesh wrote:
> >
> >
> > > -----Original Message-----
> > > From: Frank Li <frank.li at nxp.com>
> > > Sent: Monday, March 17, 2025 6:57 PM
> > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org; linux-
> > > kernel at vger.kernel.org; stable at vger.kernel.org; rvmanjumce at gmail.com
> > > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
> > > memory at
> > > svc_i3c_master_ibi_work()
> > >
> > > On Thu, Mar 13, 2025 at 05:15:42AM +0000, Manjunatha Venkatesh
> wrote:
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Frank Li <frank.li at nxp.com>
> > > > > Sent: Wednesday, March 12, 2025 11:59 PM
> > > > > To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > > > > Cc: miquel.raynal at bootlin.com; conor.culhane at silvaco.com;
> > > > > alexandre.belloni at bootlin.com; linux-i3c at lists.infradead.org;
> > > > > linux- kernel at vger.kernel.org; stable at vger.kernel.org;
> > > > > rvmanjumce at gmail.com
> > > > > Subject: Re: [PATCH v4] svc-i3c-master: Fix read from unreadable
> > > > > memory at
> > > > > svc_i3c_master_ibi_work()
> > > > >
> > > > > On Wed, Mar 12, 2025 at 07:23:56PM +0530, Manjunatha Venkatesh
> > > wrote:
> > > > > > As part of I3C driver probing sequence for particular device
> > > > > > instance, While adding to queue it is trying to access ibi
> > > > > > variable of dev which is not yet initialized causing "Unable
> > > > > > to handle kernel read from unreadable memory" resulting in kernel
> panic.
> > > > > >
> > > > > > Below is the sequence where this issue happened.
> > > > > > 1. During boot up sequence IBI is received at host  from the slave
> device
> > > > > >    before requesting for IBI, Usually will request IBI by calling
> > > > > >    i3c_device_request_ibi() during probe of slave driver.
> > > > > > 2. Since master code trying to access IBI Variable for the particular
> > > > > >    device instance before actually it initialized by slave driver,
> > > > > >    due to this randomly accessing the address and causing kernel
> panic.
> > > > > > 3. i3c_device_request_ibi() function invoked by the slave driver
> where
> > > > > >    dev->ibi = ibi; assigned as part of function call
> > > > > >    i3c_dev_request_ibi_locked().
> > > > > > 4. But when IBI request sent by slave device, master code
> > > > > > trying to
> > > access
> > > > > >    this variable before its initialized due to this race condition
> > > > > >    situation kernel panic happened.
> > > > > >
> > > > > > Fixes: dd3c52846d595 ("i3c: master: svc: Add Silvaco I3C
> > > > > > master
> > > > > > driver")
> > > > > > Cc: stable at vger.kernel.org
> > > > > > Signed-off-by: Manjunatha Venkatesh
> > > <manjunatha.venkatesh at nxp.com>
> > > > > > ---
> > > > > > Changes since v3:
> > > > > >   - Description  updated typo "Fixes:"
> > > > > >
> > > > > >  drivers/i3c/master/svc-i3c-master.c | 7 +++++--
> > > > > >  1 file changed, 5 insertions(+), 2 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/i3c/master/svc-i3c-master.c
> > > > > > b/drivers/i3c/master/svc-i3c-master.c
> > > > > > index d6057d8c7dec..98c4d2e5cd8d 100644
> > > > > > --- a/drivers/i3c/master/svc-i3c-master.c
> > > > > > +++ b/drivers/i3c/master/svc-i3c-master.c
> > > > > > @@ -534,8 +534,11 @@ static void
> > > > > > svc_i3c_master_ibi_work(struct
> > > > > work_struct *work)
> > > > > >       switch (ibitype) {
> > > > > >       case SVC_I3C_MSTATUS_IBITYPE_IBI:
> > > > > >               if (dev) {
> > > > > > -                     i3c_master_queue_ibi(dev, master->ibi.tbq_slot);
> > > > > > -                     master->ibi.tbq_slot = NULL;
> > > > > > +                     data = i3c_dev_get_master_data(dev);
> > > > > > +                     if (master->ibi.slots[data->ibi]) {
> > > > > > +                             i3c_master_queue_ibi(dev,
> > > > > > + master-
> > > > > >ibi.tbq_slot);
> > > > > > +                             master->ibi.tbq_slot = NULL;
> > > > > > +                     }
> > > > >
> > > > > You still not reply previous discussion:
> > > > >
> > > > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%
> > > > > 2Flore.kernel.org%2Flinux-i3c%2FZ8sOKZSjHeeP2mY5%40lizhi-Precisi
> > > > > on-
> T&data=05%7C02%7Cmanjunatha.venkatesh%40nxp.com%7Cf0ae17cf296
> > > > >
> 949cdd6c308dd657aa7e7%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C
> 0
> > > > > %7C638778299668550575%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0
> eU1hcGkiOn
> > > > >
> RydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIj
> > > > >
> oyfQ%3D%3D%7C0%7C%7C%7C&sdata=3da5keE%2FKv9NbsltjDxywErXAjU1Al
> nR
> > > > > DXi5GQlMDJw%3D&reserved=0
> > > > > ower-
> > > > > 5810/T/#mfd02d6ddca0a4b57bc823dcbfa7571c564800417
> > > > >
> > > > [Manjunatha Venkatesh] : In the last mail answered to this question.
> > > >
> > > > > This is not issue only at svc driver, which should be common
> > > > > problem for other master controller drivers
> > > > >
> > > > [Manjunatha Venkatesh] :Yes, you are right.
> > > > One of my project I3C interface is required, where we have used
> > > > IMX board
> > > as reference platform.
> > > > As part of boot sequence we come across this issue and tried to
> > > > fix that
> > > particular controller driver.
> > > >
> > > > What is your conclusion on this? Is it not ok to take patch for SVC alone?
> > >
> > > I perfer fix at common framwork to avoid every driver copy the
> > > similar logic code.
> > >
> > [Manjunatha Venkatesh] : As per your suggestion tried the below patch
> > at common framework api i3c_master_queue_ibi()  and looks working fine,
> didn't see any crash issue.
> > if (!dev->ibi || !slot) {
> >              dev_warning("...");
> 
> Do we really need a warning, what would be the user action after seeing it?
[Manjunatha Venkatesh] : Warning message may not required here, we can just return it.
> >              return;
> > }
> > Will commit this change in next patch submission.
> >
> > > Frank
> > >
> > > >
> > > > > Frank
> > > > >
> > > > > >               }
> > > > > >               svc_i3c_master_emit_stop(master);
> > > > > >               break;
> > > > > > --
> > > > > > 2.46.1
> > > > > >
> > > >
> > > > --
> > > > linux-i3c mailing list
> > > > linux-i3c at lists.infradead.org
> > > > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fl
> > > > ists.infradead.org%2Fmailman%2Flistinfo%2Flinux-
> i3c&data=05%7C02%7
> > > >
> Cmanjunatha.venkatesh%40nxp.com%7Cf0ae17cf296949cdd6c308dd657aa7e
> 7
> > > > %7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C638778299668
> 572303%7
> > > >
> CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMD
> AwMCI
> > > >
> sIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sd
> a
> > > >
> ta=NupPno%2BfuqIUr8LiV5rrrO%2FJt%2B3AHol0nokRJjauWc8%3D&reserved
> =0
> 
> --
> Alexandre Belloni, co-owner and COO, Bootlin Embedded Linux and Kernel
> engineering
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbootlin
> .com%2F&data=05%7C02%7Cmanjunatha.venkatesh%40nxp.com%7Cf0ae17c
> f296949cdd6c308dd657aa7e7%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0
> %7C0%7C638778299668585840%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0e
> U1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI
> sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=lqapWA3WfBkuFZvpdF%2BJjVc
> ncKNjG%2FR7u1n6dK88TcY%3D&reserved=0


From manjunatha.venkatesh at nxp.com  Tue Mar 25 03:23:32 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Tue, 25 Mar 2025 15:53:32 +0530
Subject: [PATCH v5] i3c: Fix read from unreadable memory at i3c_master_queue_ibi()
Message-ID: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>

As part of I3C driver probing sequence for particular device instance,
While adding to queue it is trying to access ibi variable of dev which is
not yet initialized causing "Unable to handle kernel read from unreadable
memory" resulting in kernel panic.

Below is the sequence where this issue happened.
1. During boot up sequence IBI is received at host  from the slave device
   before requesting for IBI, Usually will request IBI by calling
   i3c_device_request_ibi() during probe of slave driver.
2. Since master code trying to access IBI Variable for the particular
   device instance before actually it initialized by slave driver,
   due to this randomly accessing the address and causing kernel panic.
3. i3c_device_request_ibi() function invoked by the slave driver where
   dev->ibi = ibi; assigned as part of function call
   i3c_dev_request_ibi_locked().
4. But when IBI request sent by slave device, master code  trying to access
   this variable before its initialized due to this race condition
   situation kernel panic happened.

Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
Cc: stable at vger.kernel.org
Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-5810/
Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v4:
  - Fix added at generic places master.c which is applicable for all platforms

 drivers/i3c/master.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d5dc4180afbc..c65006aa0684 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
  */
 void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
 {
+	if (!dev->ibi || !slot)
+		return;
+
 	atomic_inc(&dev->ibi->pending_ibis);
 	queue_work(dev->ibi->wq, &slot->work);
 }
-- 
2.46.1



From manjunatha.venkatesh at nxp.com  Tue Mar 25 19:42:11 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 26 Mar 2025 02:42:11 +0000
Subject: [PATCH v5] i3c: Fix read from unreadable memory at
 i3c_master_queue_ibi()
In-Reply-To: <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
References: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
 <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
Message-ID: <VI1PR04MB10049D3A51688C4C7F42EAD798FA62@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Frank Li <frank.li at nxp.com>
> Sent: Tuesday, March 25, 2025 8:13 PM
> To: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> Cc: alexandre.belloni at bootlin.com; arnd at arndb.de;
> gregkh at linuxfoundation.org; bbrezillon at kernel.org; linux-
> i3c at lists.infradead.org; linux-kernel at vger.kernel.org;
> rvmanjumce at gmail.com; stable at vger.kernel.org
> Subject: Re: [PATCH v5] i3c: Fix read from unreadable memory at
> i3c_master_queue_ibi()
> 
> Subject should be
> 
> i3c: Add NULL pointer check in i3c_master_queue_ibi()
> 
[Manjunatha Venkatesh] : I will update the subject line in the next commit.

> On Tue, Mar 25, 2025 at 03:53:32PM +0530, Manjunatha Venkatesh wrote:
> > As part of I3C driver probing sequence for particular device instance,
> > While adding to queue it is trying to access ibi variable of dev which
> > is not yet initialized causing "Unable to handle kernel read from
> > unreadable memory" resulting in kernel panic.
> >
> > Below is the sequence where this issue happened.
> > 1. During boot up sequence IBI is received at host  from the slave device
> >    before requesting for IBI, Usually will request IBI by calling
> >    i3c_device_request_ibi() during probe of slave driver.
> > 2. Since master code trying to access IBI Variable for the particular
> >    device instance before actually it initialized by slave driver,
> >    due to this randomly accessing the address and causing kernel panic.
> > 3. i3c_device_request_ibi() function invoked by the slave driver where
> >    dev->ibi = ibi; assigned as part of function call
> >    i3c_dev_request_ibi_locked().
> > 4. But when IBI request sent by slave device, master code  trying to access
> >    this variable before its initialized due to this race condition
> >    situation kernel panic happened.
> 
> How about commit message as:
> 
> The I3C master driver may receive an IBI from a target device that has not
> been probed yet. In such cases, the master calls `i3c_master_queue_ibi()` to
> queue an IBI work task, leading to "Unable to handle kernel read from
> unreadable memory" and resulting in a kernel panic.
> 
> Typical IBI handling flow:
> 1. The I3C master scans target devices and probes their respective drivers.
> 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
>    and assigns `dev->ibi = ibi`.
> 3. The I3C master receives an IBI from the target device and calls
>    `i3c_master_queue_ibi()` to queue the target device driver?s IBI handler
>    task.
> 
> However, since target device events are asynchronous to the I3C probe
> sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`,
> leading to a kernel panic.
> 
> Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing an
> uninitialized `dev->ibi`, ensuring stability.
>
[Manjunatha Venkatesh] : This commit message looks better, will use the same in the next commit. 
 
> >
> > Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
> > Cc: stable at vger.kernel.org
> > Link:
> > https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-58
> > 10/
> > Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> > ---
> > Changes since v4:
> >   - Fix added at generic places master.c which is applicable for all
> > platforms
> >
> >  drivers/i3c/master.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index
> > d5dc4180afbc..c65006aa0684 100644
> > --- a/drivers/i3c/master.c
> > +++ b/drivers/i3c/master.c
> > @@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct
> i3c_master_controller *master)
> >   */
> >  void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct
> > i3c_ibi_slot *slot)  {
> > +	if (!dev->ibi || !slot)
> > +		return;
> > +
> >  	atomic_inc(&dev->ibi->pending_ibis);
> >  	queue_work(dev->ibi->wq, &slot->work);  }
> > --
> > 2.46.1
> >

From manjunatha.venkatesh at nxp.com  Tue Mar 25 23:58:48 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 26 Mar 2025 06:58:48 +0000
Subject: [EXT] Re: [PATCH v5] i3c: Fix read from unreadable memory at
 i3c_master_queue_ibi()
In-Reply-To: <8c624cf0-febc-4ab9-8141-2372bfe4d577@quicinc.com>
References: <20250325102332.2435069-1-manjunatha.venkatesh@nxp.com>
 <Z+LA/GASTPMMcVpC@lizhi-Precision-Tower-5810>
 <8c624cf0-febc-4ab9-8141-2372bfe4d577@quicinc.com>
Message-ID: <VI1PR04MB10049E90AC1CB4823F91D1D698FA62@VI1PR04MB10049.eurprd04.prod.outlook.com>



> -----Original Message-----
> From: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
> Sent: Wednesday, March 26, 2025 12:15 PM
> To: Frank Li <frank.li at nxp.com>; Manjunatha Venkatesh
> <manjunatha.venkatesh at nxp.com>
> Cc: alexandre.belloni at bootlin.com; arnd at arndb.de;
> gregkh at linuxfoundation.org; bbrezillon at kernel.org; linux-
> i3c at lists.infradead.org; linux-kernel at vger.kernel.org;
> rvmanjumce at gmail.com; stable at vger.kernel.org
> Subject: [EXT] Re: [PATCH v5] i3c: Fix read from unreadable memory at
> i3c_master_queue_ibi()
> 
> Caution: This is an external email. Please take care when clicking links or
> opening attachments. When in doubt, report the message using the 'Report
> this email' button
> 
> 
> On 3/25/2025 8:13 PM, Frank Li wrote:
> > Subject should be
> >
> > i3c: Add NULL pointer check in i3c_master_queue_ibi()
> >
> yes, Aligned.
> > On Tue, Mar 25, 2025 at 03:53:32PM +0530, Manjunatha Venkatesh wrote:
> >> As part of I3C driver probing sequence for particular device
> >> instance, While adding to queue it is trying to access ibi variable
> >> of dev which is not yet initialized causing "Unable to handle kernel
> >> read from unreadable memory" resulting in kernel panic.
> >>
> >> Below is the sequence where this issue happened.
> >> 1. During boot up sequence IBI is received at host  from the slave device
> >>     before requesting for IBI, Usually will request IBI by calling
> >>     i3c_device_request_ibi() during probe of slave driver.
> >> 2. Since master code trying to access IBI Variable for the particular
> >>     device instance before actually it initialized by slave driver,
> >>     due to this randomly accessing the address and causing kernel panic.
> >> 3. i3c_device_request_ibi() function invoked by the slave driver where
> >>     dev->ibi = ibi; assigned as part of function call
> >>     i3c_dev_request_ibi_locked().
> >> 4. But when IBI request sent by slave device, master code  trying to access
> >>     this variable before its initialized due to this race condition
> >>     situation kernel panic happened.
> >
> > How about commit message as:
> >
> > The I3C master driver may receive an IBI from a target device that has
> > not been probed yet. In such cases, the master calls
> > `i3c_master_queue_ibi()` to queue an IBI work task, leading to "Unable
> > to handle kernel read from unreadable memory" and resulting in a kernel
> panic.
> >
> > Typical IBI handling flow:
> > 1. The I3C master scans target devices and probes their respective drivers.
> > 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
> >     and assigns `dev->ibi = ibi`.
> > 3. The I3C master receives an IBI from the target device and calls
> >     `i3c_master_queue_ibi()` to queue the target device driver's IBI handler
> >     task.
> >
> > However, since target device events are asynchronous to the I3C probe
> > sequence, step 3 may occur before step 2, causing `dev->ibi` to be
> > `NULL`, leading to a kernel panic.
> >
> > Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent
> > accessing an uninitialized `dev->ibi`, ensuring stability.
> >
> >>
> >> Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
> >> Cc: stable at vger.kernel.org
> >> Link:
> >> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flor
> >> e.kernel.org%2Flkml%2FZ9gjGYudiYyl3bSe%40lizhi-Precision-Tower-
> 5810%2
> >>
> F&data=05%7C02%7Cmanjunatha.venkatesh%40nxp.com%7Ceda8be8c7abc4
> 3b4ab9
> >>
> 608dd6c31c8e7%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6387
> 856832
> >>
> 77582903%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYi
> OiIwLjAu
> >>
> MDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%
> 7C%7C
> >>
> &sdata=oyc9Wv%2Fj8HMRFIiIGL9nIw0XvI6FsLK2SvsQJ55H7XI%3D&reserved=
> 0
> >> Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
> >> ---
> >> Changes since v4:
> >>    - Fix added at generic places master.c which is applicable for all
> >> platforms
> >>
> >>   drivers/i3c/master.c | 3 +++
> >>   1 file changed, 3 insertions(+)
> >>
> >> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index
> >> d5dc4180afbc..c65006aa0684 100644
> >> --- a/drivers/i3c/master.c
> >> +++ b/drivers/i3c/master.c
> >> @@ -2561,6 +2561,9 @@ static void
> i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
> >>    */
> >>   void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot
> *slot)
> >>   {
> >> +    if (!dev->ibi || !slot)
> >> +            return;
> >> +
> 1. Shouldn't this be a Logical AND ? what if slot is non NULL but the IBI is
> NULL ?
> 
[Manjunatha Venkatesh] : I think Logical OR operation is correct,
 Since if any one of the variable is NULL need to return before accessing those variables.
> 2. This being void function, it doesn't say anything to caller if it's successful or
> failed ? Should we make this non void function ?
> if not, i am thinking it may run into multiple attempts, no log too.
[Manjunatha Venkatesh] : If required we can add error print log, Others please confirm your opinion on this.  
> >>      atomic_inc(&dev->ibi->pending_ibis);
> >>      queue_work(dev->ibi->wq, &slot->work);
> >>   }
> >> --
> >> 2.46.1
> >>
> >



From manjunatha.venkatesh at nxp.com  Wed Mar 26 05:30:46 2025
From: manjunatha.venkatesh at nxp.com (Manjunatha Venkatesh)
Date: Wed, 26 Mar 2025 18:00:46 +0530
Subject: [PATCH v6] i3c: Add NULL pointer check in i3c_master_queue_ibi()
Message-ID: <20250326123047.2797946-1-manjunatha.venkatesh@nxp.com>

The I3C master driver may receive an IBI from a target device that has not
been probed yet. In such cases, the master calls `i3c_master_queue_ibi()`
to queue an IBI work task, leading to "Unable to handle kernel read from
unreadable memory" and resulting in a kernel panic.

Typical IBI handling flow:
1. The I3C master scans target devices and probes their respective drivers.
2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
   and assigns `dev->ibi = ibi`.
3. The I3C master receives an IBI from the target device and calls
   `i3c_master_queue_ibi()` to queue the target device driver?s IBI
   handler task.

However, since target device events are asynchronous to the I3C probe
sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`,
leading to a kernel panic.

Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing
an uninitialized `dev->ibi`, ensuring stability.

Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure")
Cc: stable at vger.kernel.org
Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe at lizhi-Precision-Tower-5810/
Signed-off-by: Manjunatha Venkatesh <manjunatha.venkatesh at nxp.com>
---
Changes since v5:
  - Updated subject and commit message  with some more information.

 drivers/i3c/master.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index d5dc4180afbc..c65006aa0684 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2561,6 +2561,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
  */
 void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
 {
+	if (!dev->ibi || !slot)
+		return;
+
 	atomic_inc(&dev->ibi->pending_ibis);
 	queue_work(dev->ibi->wq, &slot->work);
 }
-- 
2.46.1



From Markus.Elfring at web.de  Fri Mar 28 06:19:39 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Fri, 28 Mar 2025 14:19:39 +0100
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
Message-ID: <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>

?
> +++ b/drivers/i3c/master/qcom-i3c-master.c
> @@ -0,0 +1,1107 @@
?
> +static void geni_i3c_abort_xfer(struct geni_i3c_dev *gi3c)
> +{
?
> +	spin_lock_irqsave(&gi3c->irq_lock, flags);
> +	geni_i3c_handle_err(gi3c, GENI_TIMEOUT);
> +	geni_se_abort_m_cmd(&gi3c->se);
> +	spin_unlock_irqrestore(&gi3c->irq_lock, flags);
?

Under which circumstances would you become interested to apply a statement
like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
https://elixir.bootlin.com/linux/v6.14-rc6/source/include/linux/spinlock.h#L572

Regards,
Markus


From Markus.Elfring at web.de  Fri Mar 28 06:28:13 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Fri, 28 Mar 2025 14:28:13 +0100
Subject: [PATCH v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
Message-ID: <06545fa2-7f82-4154-a882-faddb53df4d9@web.de>

?
> +++ b/drivers/i3c/master/qcom-i3c-master.c
> @@ -0,0 +1,1107 @@
?
> +/* M_CMD OP codes for I2C/I3C */
> +#define I3C_READ_IBI_HW          0
> +#define I2C_WRITE                1
> +#define I2C_READ                 2
?

Can an enumeration become helpful here?

Regards,
Markus


From Markus.Elfring at web.de  Fri Mar 28 12:04:56 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Fri, 28 Mar 2025 20:04:56 +0100
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
Message-ID: <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>

>> Under which circumstances would you become interested to apply a statement
>> like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
> Didn't get, hence a question.? Do you suggest to use DEFINE_LOCK_GUARD_1 instead of existing method ?
I propose to pick further opportunities up for benefits from scope-based resource management.

Regards,
Markus


From Markus.Elfring at web.de  Sat Mar 29 02:43:45 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 29 Mar 2025 10:43:45 +0100
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
 <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
 <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
Message-ID: <e728a653-dc12-4d2b-83a1-a186611c85be@web.de>

>>>> Under which circumstances would you become interested to apply a statement
>>>> like ?guard(spinlock_irqsave)(&gi3c->irq_lock);??
>>> Didn't get, hence a question.? Do you suggest to use DEFINE_LOCK_GUARD_1 instead of existing method ?
>> I propose to pick further opportunities up for benefits from scope-based resource management.
>>
> Sorry, still not clear to me what should i add/change ? please share me some example.
I pointed desirable statements out several times already.

See also related information sources once more:
* https://elixir.bootlin.com/linux/v6.14-rc6/A/ident/guard
* https://lore.kernel.org/linux-kernel/?q=spinlock_irqsave


Regards,
Markus


From Markus.Elfring at web.de  Sat Mar 29 06:16:12 2025
From: Markus.Elfring at web.de (Markus Elfring)
Date: Sat, 29 Mar 2025 14:16:12 +0100
Subject: [v2 2/3] i3c: master: Add Qualcomm I3C controller driver
In-Reply-To: <20250329104812225f9ee5@mail.local>
References: <20250326141641.3471906-3-quic_msavaliy@quicinc.com>
 <66d344b9-5cc6-4060-86ff-8100a00de477@web.de>
 <4161e6de-b16f-4371-be41-cc12adb3e9b8@quicinc.com>
 <e32324c8-1888-451b-8621-0e468ca61fd9@web.de>
 <a96511dc-5ba1-4302-acb0-f3b49bf8990c@quicinc.com>
 <20250329104812225f9ee5@mail.local>
Message-ID: <8a69d4c0-bd4e-4957-8b04-4a6130c82166@web.de>

> Don't change anything, Markus is wasting your time.
Can clarifications become more constructive also for the usage of scope-based resource management?

Regards,
Markus


From alexandre.belloni at bootlin.com  Mon Mar 31 02:44:24 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Mon, 31 Mar 2025 11:44:24 +0200
Subject: [PATCH v6] i3c: Add NULL pointer check in i3c_master_queue_ibi()
In-Reply-To: <20250326123047.2797946-1-manjunatha.venkatesh@nxp.com>
References: <20250326123047.2797946-1-manjunatha.venkatesh@nxp.com>
Message-ID: <174341425769.1100556.13422322396999492211.b4-ty@bootlin.com>

On Wed, 26 Mar 2025 18:00:46 +0530, Manjunatha Venkatesh wrote:
> The I3C master driver may receive an IBI from a target device that has not
> been probed yet. In such cases, the master calls `i3c_master_queue_ibi()`
> to queue an IBI work task, leading to "Unable to handle kernel read from
> unreadable memory" and resulting in a kernel panic.
> 
> Typical IBI handling flow:
> 1. The I3C master scans target devices and probes their respective drivers.
> 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI
>    and assigns `dev->ibi = ibi`.
> 3. The I3C master receives an IBI from the target device and calls
>    `i3c_master_queue_ibi()` to queue the target device driver?s IBI
>    handler task.
> 
> [...]

Applied, thanks!

[1/1] i3c: Add NULL pointer check in i3c_master_queue_ibi()
      https://git.kernel.org/abelloni/c/bd496a44f041

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From stanley.chuys at gmail.com  Mon Mar 31 23:34:06 2025
From: stanley.chuys at gmail.com (Stanley Chu)
Date: Tue,  1 Apr 2025 14:34:06 +0800
Subject: [PATCH v1] i3c: master: svc: Update actual read length
Message-ID: <20250401063406.3728534-1-yschu@nuvoton.com>

From: Stanley Chu <yschu at nuvoton.com>

Some drivers, such as mctp-i3c.c, reuse the i3c_priv_xfer.len as
the actual read len. Therefore, the controller driver should also
update the i3c_priv_xfer.len after the read transfer is completed.

Signed-off-by: Stanley Chu <yschu at nuvoton.com>
---
 drivers/i3c/master/svc-i3c-master.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 85e16de208d3..dd520f5d4c9f 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1470,9 +1470,16 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
 					  cmd->len, &cmd->actual_len,
 					  cmd->continued);
 		/* cmd->xfer is NULL if I2C or CCC transfer */
-		if (cmd->xfer)
+		if (cmd->xfer) {
 			cmd->xfer->actual_len = cmd->actual_len;
 
+			/*
+			 * Some i3c drivers reuse i3c_priv_xfer.len as
+			 * the actual read length.
+			 */
+			cmd->xfer->len = cmd->actual_len;
+		}
+
 		if (ret)
 			break;
 	}
-- 
2.34.1



