2024-05-06 16:40:40

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 1/3] i3c: Add comment for -EAGAIN in i3c_device_do_priv_xfers()

In accordance with I3C spec ver 1.1.1 09-Jun-2021, section: 5.1.2.2.3, if
a target requests hot join (HJ), In-Band Interrupt (IBI), or controller
role request (CRR) during the emission of an I3C address in
i3c_device_do_priv_xfers(), the target may win bus arbitration. In such
cases, it is imperative to notify the I3C client driver and retry
i3c_device_do_priv_xfers() after some delay.

Signed-off-by: Frank Li <[email protected]>
---

Notes:
Change from v1 to v2
- new patch

drivers/i3c/device.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index 1a6a8703dbc3a..b04a55a1337d4 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -27,6 +27,10 @@
* This function can sleep and thus cannot be called in atomic context.
*
* Return: 0 in case of success, a negative error core otherwise.
+ * -EAGAIN: controller lost address arbitration. Target
+ * (IBI, HJ or controller role request) win the bus. Client
+ * driver need resend this 'xfers' some time later.
+ * See I3C spec ver 1.1.1 09-Jun-2021. Section: 5.1.2.2.3.
*/
int i3c_device_do_priv_xfers(struct i3c_device *dev,
struct i3c_priv_xfer *xfers,
--
2.34.1



2024-05-06 16:41:00

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 2/3] i3c: master: svc: change ENXIO to EAGAIN when IBI occurs during start frame

svc_i3c_master_xfer() returns error ENXIO if an In-Band Interrupt (IBI)
occurs when the host starts the frame.

Change error code to EAGAIN to inform the client driver that this
situation has occurred and to try again sometime later.

Fixes: 5e5e3c92e748 ("i3c: master: svc: fix wrong data return when IBI happen during start frame")
Signed-off-by: Frank Li <[email protected]>
---

Notes:
change from v1 to v2
- none

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 fd8de54b13667..94e4954509558 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1080,7 +1080,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
* and yield the above events handler.
*/
if (SVC_I3C_MSTATUS_IBIWON(reg)) {
- ret = -ENXIO;
+ ret = -EAGAIN;
*actual_len = 0;
goto emit_stop;
}
--
2.34.1


2024-05-06 16:41:03

by Frank Li

[permalink] [raw]
Subject: [PATCH v2 3/3] i3c: master: svc: fix invalidate IBI type and miss call client IBI handler

In an In-Band Interrupt (IBI) handle, the code logic is as follows:

1: writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI | SVC_I3C_MCTRL_IBIRESP_AUTO,
master->regs + SVC_I3C_MCTRL);

2: ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
...
3: ibitype = SVC_I3C_MSTATUS_IBITYPE(status);
ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status);

SVC_I3C_MSTATUS_IBIWON may be set before step 1. Thus, step 2 will return
immediately, and the I3C controller has not sent out the 9th SCL yet.
Consequently, ibitype and ibiaddr are 0, resulting in an unknown IBI type
occurrence and missing call I3C client driver's IBI handler.

A typical case is that SVC_I3C_MSTATUS_IBIWON is set when an IBI occurs
during the controller send start frame in svc_i3c_master_xfer().

Clear SVC_I3C_MSTATUS_IBIWON before issue SVC_I3C_MCTRL_REQUEST_AUTO_IBI
to fix this issue.

Cc: [email protected]
Fixes: 5e5e3c92e748 ("i3c: master: svc: fix wrong data return when IBI happen during start frame")
Signed-off-by: Frank Li <[email protected]>
---

Notes:
Change from v1 to v2
- improve comments.

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

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 94e4954509558..032fe032ec433 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -415,6 +415,19 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
int ret;

mutex_lock(&master->lock);
+ /*
+ * IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
+ * readl_relaxed_poll_timeout() to return immediately. Consequently,
+ * ibitype will be 0 since it was last updated only after the 8th SCL
+ * cycle, leading to missed client IBI handlers.
+ *
+ * A typical scenario is when IBIWON occurs and bus arbitration is lost
+ * at svc_i3c_master_priv_xfers().
+ *
+ * Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI.
+ */
+ writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+
/* Acknowledge the incoming interrupt with the AUTOIBI mechanism */
writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI |
SVC_I3C_MCTRL_IBIRESP_AUTO,
@@ -429,9 +442,6 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
goto reenable_ibis;
}

- /* Clear the interrupt status */
- writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
-
status = readl(master->regs + SVC_I3C_MSTATUS);
ibitype = SVC_I3C_MSTATUS_IBITYPE(status);
ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status);
--
2.34.1


2024-05-07 08:03:39

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH v2 1/3] i3c: Add comment for -EAGAIN in i3c_device_do_priv_xfers()

Hi Frank,

[email protected] wrote on Mon, 6 May 2024 12:40:07 -0400:

> In accordance with I3C spec ver 1.1.1 09-Jun-2021, section: 5.1.2.2.3, if
> a target requests hot join (HJ), In-Band Interrupt (IBI), or controller
> role request (CRR) during the emission of an I3C address in
> i3c_device_do_priv_xfers(), the target may win bus arbitration. In such
> cases, it is imperative to notify the I3C client driver and retry
> i3c_device_do_priv_xfers() after some delay.
>
> Signed-off-by: Frank Li <[email protected]>
> ---
>
> Notes:
> Change from v1 to v2
> - new patch
>
> drivers/i3c/device.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
> index 1a6a8703dbc3a..b04a55a1337d4 100644
> --- a/drivers/i3c/device.c
> +++ b/drivers/i3c/device.c
> @@ -27,6 +27,10 @@
> * This function can sleep and thus cannot be called in atomic context.
> *
> * Return: 0 in case of success, a negative error core otherwise.
> + * -EAGAIN: controller lost address arbitration. Target
> + * (IBI, HJ or controller role request) win the bus. Client
> + * driver need resend this 'xfers' some time later.

needs to resend the 'xfers'

> + * See I3C spec ver 1.1.1 09-Jun-2021. Section: 5.1.2.2.3.
> */
> int i3c_device_do_priv_xfers(struct i3c_device *dev,
> struct i3c_priv_xfer *xfers,


With this little nit,

Reviewed-by: Miquel Raynal <[email protected]>


Thanks,
Miquèl

2024-05-07 08:03:55

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH v2 2/3] i3c: master: svc: change ENXIO to EAGAIN when IBI occurs during start frame

Hi Frank,

[email protected] wrote on Mon, 6 May 2024 12:40:08 -0400:

> svc_i3c_master_xfer() returns error ENXIO if an In-Band Interrupt (IBI)
> occurs when the host starts the frame.
>
> Change error code to EAGAIN to inform the client driver that this
> situation has occurred and to try again sometime later.
>
> Fixes: 5e5e3c92e748 ("i3c: master: svc: fix wrong data return when IBI happen during start frame")
> Signed-off-by: Frank Li <[email protected]>

Reviewed-by: Miquel Raynal <[email protected]>


Thanks,
Miquèl

2024-05-07 08:04:45

by Miquel Raynal

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] i3c: master: svc: fix invalidate IBI type and miss call client IBI handler

Hi Frank,

[email protected] wrote on Mon, 6 May 2024 12:40:09 -0400:

> In an In-Band Interrupt (IBI) handle, the code logic is as follows:
>
> 1: writel(SVC_I3C_MCTRL_REQUEST_AUTO_IBI | SVC_I3C_MCTRL_IBIRESP_AUTO,
> master->regs + SVC_I3C_MCTRL);
>
> 2: ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
> SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
> ...
> 3: ibitype = SVC_I3C_MSTATUS_IBITYPE(status);
> ibiaddr = SVC_I3C_MSTATUS_IBIADDR(status);
>
> SVC_I3C_MSTATUS_IBIWON may be set before step 1. Thus, step 2 will return
> immediately, and the I3C controller has not sent out the 9th SCL yet.
> Consequently, ibitype and ibiaddr are 0, resulting in an unknown IBI type
> occurrence and missing call I3C client driver's IBI handler.
>
> A typical case is that SVC_I3C_MSTATUS_IBIWON is set when an IBI occurs
> during the controller send start frame in svc_i3c_master_xfer().
>
> Clear SVC_I3C_MSTATUS_IBIWON before issue SVC_I3C_MCTRL_REQUEST_AUTO_IBI
> to fix this issue.
>
> Cc: [email protected]
> Fixes: 5e5e3c92e748 ("i3c: master: svc: fix wrong data return when IBI happen during start frame")
> Signed-off-by: Frank Li <[email protected]>
> ---
>
> Notes:
> Change from v1 to v2
> - improve comments.
>
> drivers/i3c/master/svc-i3c-master.c | 16 +++++++++++++---
> 1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
> index 94e4954509558..032fe032ec433 100644
> --- a/drivers/i3c/master/svc-i3c-master.c
> +++ b/drivers/i3c/master/svc-i3c-master.c
> @@ -415,6 +415,19 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
> int ret;
>
> mutex_lock(&master->lock);
> + /*
> + * IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
> + * readl_relaxed_poll_timeout() to return immediately. Consequently,
> + * ibitype will be 0 since it was last updated only after the 8th SCL
> + * cycle, leading to missed client IBI handlers.
> + *
> + * A typical scenario is when IBIWON occurs and bus arbitration is lost
> + * at svc_i3c_master_priv_xfers().
> + *
> + * Clear SVC_I3C_MINT_IBIWON before sending SVC_I3C_MCTRL_REQUEST_AUTO_IBI.
> + */

Thanks a lot.

Reviewed-by: Miquel Raynal <[email protected]>

Thanks,
Miquèl

2024-05-07 20:28:45

by Alexandre Belloni

[permalink] [raw]
Subject: Re: [PATCH v2 1/3] i3c: Add comment for -EAGAIN in i3c_device_do_priv_xfers()

On Mon, 06 May 2024 12:40:07 -0400, Frank Li wrote:
> In accordance with I3C spec ver 1.1.1 09-Jun-2021, section: 5.1.2.2.3, if
> a target requests hot join (HJ), In-Band Interrupt (IBI), or controller
> role request (CRR) during the emission of an I3C address in
> i3c_device_do_priv_xfers(), the target may win bus arbitration. In such
> cases, it is imperative to notify the I3C client driver and retry
> i3c_device_do_priv_xfers() after some delay.
>
> [...]

Applied, thanks!

[1/3] i3c: Add comment for -EAGAIN in i3c_device_do_priv_xfers()
https://git.kernel.org/abelloni/c/5e45614ef8ae
[2/3] i3c: master: svc: change ENXIO to EAGAIN when IBI occurs during start frame
https://git.kernel.org/abelloni/c/75cb32046b5d
[3/3] i3c: master: svc: fix invalidate IBI type and miss call client IBI handler
https://git.kernel.org/abelloni/c/677a7b0e3ae4

Best regards,

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