* [PATCH] [v2] i3c: fix big-endian FIFO transfers
@ 2025-09-24 20:18 Arnd Bergmann
2025-09-25 7:16 ` Jorge Marques
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Arnd Bergmann @ 2025-09-24 20:18 UTC (permalink / raw)
To: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li
Cc: Arnd Bergmann, Manikanta Guntupalli, linux-i3c, linux-kernel
From: Arnd Bergmann <arnd@arndb.de>
Short MMIO transfers that are not a multiple of four bytes in size need
a special case for the final bytes, however the existing implementation
is not endian-safe and introduces an incorrect byteswap on big-endian
kernels.
This usually does not cause problems because most systems are
little-endian and most transfers are multiple of four bytes long, but
still needs to be fixed to avoid the extra byteswap.
Change the special case for both i3c_writel_fifo() and i3c_readl_fifo()
to use non-byteswapping writesl() and readsl() with a single element
instead of the byteswapping writel()/readl() that are meant for individual
MMIO registers. As data is copied between a FIFO and a memory buffer,
the writesl()/readsl() loops are typically based on __raw_readl()/
__raw_writel(), resulting in the order of bytes in the FIFO to match
the order in the buffer, regardless of the CPU endianess.
The earlier versions in the dw-i3c and i3c-master-cdns had a correct
implementation, but the generic version that was recently added broke it.
Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and i3c_writel_fifo()")
Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
This was a recent regression, the version in 6.16 still works,
but 6.17-rc is broken.
v2 changes:
- add code comments
- write correct data buffer
---
drivers/i3c/internals.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
index 0d857cc68cc5..79ceaa5f5afd 100644
--- a/drivers/i3c/internals.h
+++ b/drivers/i3c/internals.h
@@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
u32 tmp = 0;
memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
- writel(tmp, addr);
+ /*
+ * writesl() instead of writel() to keep FIFO
+ * byteorder on big-endian targets
+ */
+ writesl(addr, &tmp, 1);
}
}
@@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem *addr, void *buf,
if (nbytes & 3) {
u32 tmp;
- tmp = readl(addr);
+ /*
+ * readsl() instead of readl() to keep FIFO
+ * byteorder on big-endian targets
+ */
+ readsl(addr, &tmp, 1);
memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
}
}
--
2.39.5
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-24 20:18 [PATCH] [v2] i3c: fix big-endian FIFO transfers Arnd Bergmann
@ 2025-09-25 7:16 ` Jorge Marques
2025-09-25 7:37 ` Guntupalli, Manikanta
2025-09-25 15:09 ` Frank Li
2025-09-28 22:19 ` Alexandre Belloni
2 siblings, 1 reply; 12+ messages in thread
From: Jorge Marques @ 2025-09-25 7:16 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
Arnd Bergmann, Manikanta Guntupalli, linux-i3c, linux-kernel
On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> Short MMIO transfers that are not a multiple of four bytes in size need
> a special case for the final bytes, however the existing implementation
> is not endian-safe and introduces an incorrect byteswap on big-endian
> kernels.
>
> This usually does not cause problems because most systems are
> little-endian and most transfers are multiple of four bytes long, but
> still needs to be fixed to avoid the extra byteswap.
>
> Change the special case for both i3c_writel_fifo() and i3c_readl_fifo()
> to use non-byteswapping writesl() and readsl() with a single element
> instead of the byteswapping writel()/readl() that are meant for individual
> MMIO registers. As data is copied between a FIFO and a memory buffer,
> the writesl()/readsl() loops are typically based on __raw_readl()/
> __raw_writel(), resulting in the order of bytes in the FIFO to match
> the order in the buffer, regardless of the CPU endianess.
>
> The earlier versions in the dw-i3c and i3c-master-cdns had a correct
> implementation, but the generic version that was recently added broke it.
>
> Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and i3c_writel_fifo()")
> Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> This was a recent regression, the version in 6.16 still works,
> but 6.17-rc is broken.
>
> v2 changes:
> - add code comments
> - write correct data buffer
> ---
> drivers/i3c/internals.h | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
> index 0d857cc68cc5..79ceaa5f5afd 100644
> --- a/drivers/i3c/internals.h
> +++ b/drivers/i3c/internals.h
> @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
> u32 tmp = 0;
>
> memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> - writel(tmp, addr);
> + /*
> + * writesl() instead of writel() to keep FIFO
> + * byteorder on big-endian targets
> + */
> + writesl(addr, &tmp, 1);
> }
> }
>
> @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem *addr, void *buf,
> if (nbytes & 3) {
> u32 tmp;
>
> - tmp = readl(addr);
> + /*
> + * readsl() instead of readl() to keep FIFO
> + * byteorder on big-endian targets
> + */
> + readsl(addr, &tmp, 1);
> memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> }
> }
Reviewed-by: Jorge Marques <jorge.marques@analog.com>
> --
> 2.39.5
>
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 7:16 ` Jorge Marques
@ 2025-09-25 7:37 ` Guntupalli, Manikanta
2025-09-25 7:51 ` Nuno Sá
2025-09-25 8:55 ` Arnd Bergmann
0 siblings, 2 replies; 12+ messages in thread
From: Guntupalli, Manikanta @ 2025-09-25 7:37 UTC (permalink / raw)
To: Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
Arnd Bergmann, linux-i3c@lists.infradead.org,
linux-kernel@vger.kernel.org, git (AMD-Xilinx), Simek, Michal
[Public]
Hi,
> -----Original Message-----
> From: Jorge Marques <gastmaier@gmail.com>
> Sent: Thursday, September 25, 2025 12:47 PM
> To: Arnd Bergmann <arnd@kernel.org>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> <arnd@arndb.de>; Guntupalli, Manikanta <manikanta.guntupalli@amd.com>; linux-
> i3c@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
>
> On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > Short MMIO transfers that are not a multiple of four bytes in size
> > need a special case for the final bytes, however the existing
> > implementation is not endian-safe and introduces an incorrect byteswap
> > on big-endian kernels.
> >
> > This usually does not cause problems because most systems are
> > little-endian and most transfers are multiple of four bytes long, but
> > still needs to be fixed to avoid the extra byteswap.
> >
> > Change the special case for both i3c_writel_fifo() and
> > i3c_readl_fifo() to use non-byteswapping writesl() and readsl() with a
> > single element instead of the byteswapping writel()/readl() that are
> > meant for individual MMIO registers. As data is copied between a FIFO
> > and a memory buffer, the writesl()/readsl() loops are typically based
> > on __raw_readl()/ __raw_writel(), resulting in the order of bytes in
> > the FIFO to match the order in the buffer, regardless of the CPU endianess.
> >
> > The earlier versions in the dw-i3c and i3c-master-cdns had a correct
> > implementation, but the generic version that was recently added broke it.
> >
> > Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and
> > i3c_writel_fifo()")
> > Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > ---
> > This was a recent regression, the version in 6.16 still works, but
> > 6.17-rc is broken.
> >
> > v2 changes:
> > - add code comments
> > - write correct data buffer
> > ---
> > drivers/i3c/internals.h | 12 ++++++++++--
> > 1 file changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h index
> > 0d857cc68cc5..79ceaa5f5afd 100644
> > --- a/drivers/i3c/internals.h
> > +++ b/drivers/i3c/internals.h
> > @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr, const
> void *buf,
> > u32 tmp = 0;
> >
> > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > - writel(tmp, addr);
> > + /*
> > + * writesl() instead of writel() to keep FIFO
> > + * byteorder on big-endian targets
> > + */
> > + writesl(addr, &tmp, 1);
> > }
> > }
> >
> > @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem *addr,
> void *buf,
> > if (nbytes & 3) {
> > u32 tmp;
> >
> > - tmp = readl(addr);
> > + /*
> > + * readsl() instead of readl() to keep FIFO
> > + * byteorder on big-endian targets
> > + */
> > + readsl(addr, &tmp, 1);
> > memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> > }
> > }
> Reviewed-by: Jorge Marques <jorge.marques@analog.com>
> > --
> > 2.39.5
> >
This patch fixes the sub-word transfer case on big-endian kernels, but it still does not address the scenario of little-endian kernels accessing big-endian FIFOs.
With the current version, i3c_writel_fifo() and i3c_readl_fifo() only work when the FIFO has the same endianness as the CPU. On platforms such as the ZCU102 (Zynq UltraScale+ MPSoC, Cortex-A53, little-endian), the I3C FIFOs are big-endian, and this patch alone is not sufficient - transfers fail in that configuration.
We have validated this on ZCU102, and the mismatch between LE kernel and BE FIFO is still an issue.
On top of this fix, explicit FIFO endianness support is required, as proposed in [PATCH v7 3/4] "i3c: master: Add endianness support for i3c_readl_fifo() and i3c_writel_fifo()". That approach adds an endian argument and uses writesl_be()/readsl_be() where necessary, e.g.:
static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
int nbytes, enum i3c_fifo_endian endian)
{
if (endian)
writesl_be(addr, buf, nbytes / 4);
else
writesl(addr, buf, nbytes / 4);
if (nbytes & 3) {
u32 tmp = 0;
memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
if (endian)
writesl_be(addr, &tmp, 1);
else
writesl(addr, &tmp, 1);
}
}
Thanks,
Manikanta.
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 7:37 ` Guntupalli, Manikanta
@ 2025-09-25 7:51 ` Nuno Sá
2025-09-25 8:47 ` Guntupalli, Manikanta
2025-09-25 8:55 ` Arnd Bergmann
1 sibling, 1 reply; 12+ messages in thread
From: Nuno Sá @ 2025-09-25 7:51 UTC (permalink / raw)
To: Guntupalli, Manikanta, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
Arnd Bergmann, linux-i3c@lists.infradead.org,
linux-kernel@vger.kernel.org, git (AMD-Xilinx), Simek, Michal
On Thu, 2025-09-25 at 07:37 +0000, Guntupalli, Manikanta wrote:
> [Public]
>
> Hi,
>
> > -----Original Message-----
> > From: Jorge Marques <gastmaier@gmail.com>
> > Sent: Thursday, September 25, 2025 12:47 PM
> > To: Arnd Bergmann <arnd@kernel.org>
> > Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> > <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> > engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> > <arnd@arndb.de>; Guntupalli, Manikanta <manikanta.guntupalli@amd.com>;
> > linux-
> > i3c@lists.infradead.org; linux-kernel@vger.kernel.org
> > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> >
> > On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > > From: Arnd Bergmann <arnd@arndb.de>
> > >
> > > Short MMIO transfers that are not a multiple of four bytes in size
> > > need a special case for the final bytes, however the existing
> > > implementation is not endian-safe and introduces an incorrect byteswap
> > > on big-endian kernels.
> > >
> > > This usually does not cause problems because most systems are
> > > little-endian and most transfers are multiple of four bytes long, but
> > > still needs to be fixed to avoid the extra byteswap.
> > >
> > > Change the special case for both i3c_writel_fifo() and
> > > i3c_readl_fifo() to use non-byteswapping writesl() and readsl() with a
> > > single element instead of the byteswapping writel()/readl() that are
> > > meant for individual MMIO registers. As data is copied between a FIFO
> > > and a memory buffer, the writesl()/readsl() loops are typically based
> > > on __raw_readl()/ __raw_writel(), resulting in the order of bytes in
> > > the FIFO to match the order in the buffer, regardless of the CPU
> > > endianess.
> > >
> > > The earlier versions in the dw-i3c and i3c-master-cdns had a correct
> > > implementation, but the generic version that was recently added broke it.
> > >
> > > Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and
> > > i3c_writel_fifo()")
> > > Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > ---
> > > This was a recent regression, the version in 6.16 still works, but
> > > 6.17-rc is broken.
> > >
> > > v2 changes:
> > > - add code comments
> > > - write correct data buffer
> > > ---
> > > drivers/i3c/internals.h | 12 ++++++++++--
> > > 1 file changed, 10 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h index
> > > 0d857cc68cc5..79ceaa5f5afd 100644
> > > --- a/drivers/i3c/internals.h
> > > +++ b/drivers/i3c/internals.h
> > > @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr,
> > > const
> > void *buf,
> > > u32 tmp = 0;
> > >
> > > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > > - writel(tmp, addr);
> > > + /*
> > > + * writesl() instead of writel() to keep FIFO
> > > + * byteorder on big-endian targets
> > > + */
> > > + writesl(addr, &tmp, 1);
> > > }
> > > }
> > >
> > > @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem
> > > *addr,
> > void *buf,
> > > if (nbytes & 3) {
> > > u32 tmp;
> > >
> > > - tmp = readl(addr);
> > > + /*
> > > + * readsl() instead of readl() to keep FIFO
> > > + * byteorder on big-endian targets
> > > + */
> > > + readsl(addr, &tmp, 1);
> > > memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> > > }
> > > }
> > Reviewed-by: Jorge Marques <jorge.marques@analog.com>
> > > --
> > > 2.39.5
> > >
>
> This patch fixes the sub-word transfer case on big-endian kernels, but it
> still does not address the scenario of little-endian kernels accessing big-
> endian FIFOs.
>
I would argue that's something for callers of these functions to care about.
- Nuno Sá
> With the current version, i3c_writel_fifo() and i3c_readl_fifo() only work
> when the FIFO has the same endianness as the CPU. On platforms such as the
> ZCU102 (Zynq UltraScale+ MPSoC, Cortex-A53, little-endian), the I3C FIFOs are
> big-endian, and this patch alone is not sufficient - transfers fail in that
> configuration.
>
> We have validated this on ZCU102, and the mismatch between LE kernel and BE
> FIFO is still an issue.
>
> On top of this fix, explicit FIFO endianness support is required, as proposed
> in [PATCH v7 3/4] "i3c: master: Add endianness support for i3c_readl_fifo()
> and i3c_writel_fifo()". That approach adds an endian argument and uses
> writesl_be()/readsl_be() where necessary, e.g.:
>
> static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
> int nbytes, enum i3c_fifo_endian endian)
> {
> if (endian)
> writesl_be(addr, buf, nbytes / 4);
> else
> writesl(addr, buf, nbytes / 4);
>
> if (nbytes & 3) {
> u32 tmp = 0;
>
> memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
>
> if (endian)
> writesl_be(addr, &tmp, 1);
> else
> writesl(addr, &tmp, 1);
> }
> }
>
>
> Thanks,
> Manikanta.
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 7:51 ` Nuno Sá
@ 2025-09-25 8:47 ` Guntupalli, Manikanta
2025-09-25 8:58 ` Nuno Sá
0 siblings, 1 reply; 12+ messages in thread
From: Guntupalli, Manikanta @ 2025-09-25 8:47 UTC (permalink / raw)
To: Nuno Sá, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
Arnd Bergmann, linux-i3c@lists.infradead.org,
linux-kernel@vger.kernel.org, git (AMD-Xilinx), Simek, Michal
[Public]
Hi,
> -----Original Message-----
> From: Nuno Sá <noname.nuno@gmail.com>
> Sent: Thursday, September 25, 2025 1:22 PM
> To: Guntupalli, Manikanta <manikanta.guntupalli@amd.com>; Jorge Marques
> <gastmaier@gmail.com>; Arnd Bergmann <arnd@kernel.org>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> <arnd@arndb.de>; linux-i3c@lists.infradead.org; linux-kernel@vger.kernel.org; git
> (AMD-Xilinx) <git@amd.com>; Simek, Michal <michal.simek@amd.com>
> Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
>
> On Thu, 2025-09-25 at 07:37 +0000, Guntupalli, Manikanta wrote:
> > [Public]
> >
> > Hi,
> >
> > > -----Original Message-----
> > > From: Jorge Marques <gastmaier@gmail.com>
> > > Sent: Thursday, September 25, 2025 12:47 PM
> > > To: Arnd Bergmann <arnd@kernel.org>
> > > Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> > > <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> > > engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> > > <arnd@arndb.de>; Guntupalli, Manikanta
> > > <manikanta.guntupalli@amd.com>;
> > > linux-
> > > i3c@lists.infradead.org; linux-kernel@vger.kernel.org
> > > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> > >
> > > On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > > > From: Arnd Bergmann <arnd@arndb.de>
> > > >
> > > > Short MMIO transfers that are not a multiple of four bytes in size
> > > > need a special case for the final bytes, however the existing
> > > > implementation is not endian-safe and introduces an incorrect
> > > > byteswap on big-endian kernels.
> > > >
> > > > This usually does not cause problems because most systems are
> > > > little-endian and most transfers are multiple of four bytes long,
> > > > but still needs to be fixed to avoid the extra byteswap.
> > > >
> > > > Change the special case for both i3c_writel_fifo() and
> > > > i3c_readl_fifo() to use non-byteswapping writesl() and readsl()
> > > > with a single element instead of the byteswapping writel()/readl()
> > > > that are meant for individual MMIO registers. As data is copied
> > > > between a FIFO and a memory buffer, the writesl()/readsl() loops
> > > > are typically based on __raw_readl()/ __raw_writel(), resulting in
> > > > the order of bytes in the FIFO to match the order in the buffer,
> > > > regardless of the CPU endianess.
> > > >
> > > > The earlier versions in the dw-i3c and i3c-master-cdns had a
> > > > correct implementation, but the generic version that was recently added broke
> it.
> > > >
> > > > Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and
> > > > i3c_writel_fifo()")
> > > > Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> > > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > > ---
> > > > This was a recent regression, the version in 6.16 still works, but
> > > > 6.17-rc is broken.
> > > >
> > > > v2 changes:
> > > > - add code comments
> > > > - write correct data buffer
> > > > ---
> > > > drivers/i3c/internals.h | 12 ++++++++++--
> > > > 1 file changed, 10 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
> > > > index 0d857cc68cc5..79ceaa5f5afd 100644
> > > > --- a/drivers/i3c/internals.h
> > > > +++ b/drivers/i3c/internals.h
> > > > @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem
> > > > *addr, const
> > > void *buf,
> > > > u32 tmp = 0;
> > > >
> > > > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > > > - writel(tmp, addr);
> > > > + /*
> > > > + * writesl() instead of writel() to keep FIFO
> > > > + * byteorder on big-endian targets
> > > > + */
> > > > + writesl(addr, &tmp, 1);
> > > > }
> > > > }
> > > >
> > > > @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void
> > > > __iomem *addr,
> > > void *buf,
> > > > if (nbytes & 3) {
> > > > u32 tmp;
> > > >
> > > > - tmp = readl(addr);
> > > > + /*
> > > > + * readsl() instead of readl() to keep FIFO
> > > > + * byteorder on big-endian targets
> > > > + */
> > > > + readsl(addr, &tmp, 1);
> > > > memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> > > > }
> > > > }
> > > Reviewed-by: Jorge Marques <jorge.marques@analog.com>
> > > > --
> > > > 2.39.5
> > > >
> >
> > This patch fixes the sub-word transfer case on big-endian kernels, but
> > it still does not address the scenario of little-endian kernels
> > accessing big- endian FIFOs.
> >
>
> I would argue that's something for callers of these functions to care about.
If each I3C driver has to handle FIFO endianness individually, it introduces unnecessary duplication and overhead across drivers. Centralizing this in the FIFO access helpers keeps the logic consistent, avoids repeated boilerplate, and reduces the chance of subtle bugs.
>
> > With the current version, i3c_writel_fifo() and i3c_readl_fifo() only
> > work when the FIFO has the same endianness as the CPU. On platforms
> > such as the
> > ZCU102 (Zynq UltraScale+ MPSoC, Cortex-A53, little-endian), the I3C
> > FIFOs are big-endian, and this patch alone is not sufficient -
> > transfers fail in that configuration.
> >
> > We have validated this on ZCU102, and the mismatch between LE kernel
> > and BE FIFO is still an issue.
> >
> > On top of this fix, explicit FIFO endianness support is required, as
> > proposed in [PATCH v7 3/4] "i3c: master: Add endianness support for
> > i3c_readl_fifo() and i3c_writel_fifo()". That approach adds an endian
> > argument and uses
> > writesl_be()/readsl_be() where necessary, e.g.:
> >
> > static inline void i3c_writel_fifo(void __iomem *addr, const void
> > *buf,
> > int nbytes, enum i3c_fifo_endian
> > endian) {
> > if (endian)
> > writesl_be(addr, buf, nbytes / 4);
> > else
> > writesl(addr, buf, nbytes / 4);
> >
> > if (nbytes & 3) {
> > u32 tmp = 0;
> >
> > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> >
> > if (endian)
> > writesl_be(addr, &tmp, 1);
> > else
> > writesl(addr, &tmp, 1);
> > }
> > }
> >
> >
Thanks,
Manikanta.
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 7:37 ` Guntupalli, Manikanta
2025-09-25 7:51 ` Nuno Sá
@ 2025-09-25 8:55 ` Arnd Bergmann
1 sibling, 0 replies; 12+ messages in thread
From: Arnd Bergmann @ 2025-09-25 8:55 UTC (permalink / raw)
To: Manikanta Guntupalli, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
linux-i3c@lists.infradead.org, linux-kernel@vger.kernel.org,
git (AMD-Xilinx), Michal Simek
On Thu, Sep 25, 2025, at 09:37, Guntupalli, Manikanta wrote:
>
> This patch fixes the sub-word transfer case on big-endian kernels, but
> it still does not address the scenario of little-endian kernels
> accessing big-endian FIFOs.
>
> With the current version, i3c_writel_fifo() and i3c_readl_fifo() only
> work when the FIFO has the same endianness as the CPU. On platforms
> such as the ZCU102 (Zynq UltraScale+ MPSoC, Cortex-A53, little-endian),
> the I3C FIFOs are big-endian, and this patch alone is not sufficient -
> transfers fail in that configuration.
>
> We have validated this on ZCU102, and the mismatch between LE kernel
> and BE FIFO is still an issue.
Hi Manikanta,
Thanks a lot for testing my patch and the description of
how you tested it. I think there is still a communication
problem because the term "big-endian FIFO" makes no sense
to me.
If you need an extra byteswap on a little-endian arm64 kernel,
what you have is what I would describe as a "byte-reversed FIFO",
presumably as the result of a peripheral that was initially
designed for big-endian MMIO access, but then adapted for use with
little-endian readl() helpers by adding a data swizzle in front
of each MMIO access including both the MMIO registers and the FIFO.
The result of that is that FIFO data comes out reversed in readsl(),
but does so on both little-endian and big-endian arm64 kernels,
because the hardware byte-reverse remains in place regardless of
the CPUs internal state.
If I'm interpreting this correctly, the function you'd
actually need to make the driver work on both big-endian
and little-endian (arm64) kernels would look roughly
like
static inline void i3c_writel_fifo_bytereversed(void __iomem *addr,
const void *buf, int nbytes)
{
/*
* byteswap each 32-bit word to work around FIFO quirk.
* Note: this is different from iowrite32be(), which
* would only swap on little-endian kernels.
*/
while (nbytes >= 4) {
__raw_writel(swab32p(buf), addr);
buf += 4;
nbytes -= 4;
}
if (nbytes > 0) {
u32 tmp = 0;
memcpy(&tmp, buf, nbytes);
swab32s(&tmp);
__raw_writel(addr, &tmp, 1);
}
}
The idea here is to have a function that works the same
way as i3c_writel_fifo() but instead of never swapping the
FIFO data, it would always swap it regardless of the CPU
state, making it portable to (most of) the architectures we
support in Linux. In your version of writesl_be(), the
swap would happen on little-endian kernels but not happen
on big-endian kernels, which is inconsistent with the
documented writesl() behavior, and still makes no sense to
me conceptually.
I think the i3c_writel_fifo_bytereversed() function would
be obscure enough that we don't need it (or the
underlying writesl_bytereversed() helper) and could
be part of your own driver as you had in the original
versions, but that is something for the i3c maintainers
to decide.
Are you able to test big-endian arm64 kernels to verify this?
Linux-next now has a patch to disallow that configuration,
but you should be able to still use v6.17 and earlier if you
have access to big-endian userspace.
Arnd
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 8:47 ` Guntupalli, Manikanta
@ 2025-09-25 8:58 ` Nuno Sá
2025-09-25 9:35 ` Arnd Bergmann
0 siblings, 1 reply; 12+ messages in thread
From: Nuno Sá @ 2025-09-25 8:58 UTC (permalink / raw)
To: Guntupalli, Manikanta, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
Arnd Bergmann, linux-i3c@lists.infradead.org,
linux-kernel@vger.kernel.org, git (AMD-Xilinx), Simek, Michal
On Thu, 2025-09-25 at 08:47 +0000, Guntupalli, Manikanta wrote:
> [Public]
>
> Hi,
>
> > -----Original Message-----
> > From: Nuno Sá <noname.nuno@gmail.com>
> > Sent: Thursday, September 25, 2025 1:22 PM
> > To: Guntupalli, Manikanta <manikanta.guntupalli@amd.com>; Jorge Marques
> > <gastmaier@gmail.com>; Arnd Bergmann <arnd@kernel.org>
> > Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> > <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> > engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> > <arnd@arndb.de>; linux-i3c@lists.infradead.org;
> > linux-kernel@vger.kernel.org; git
> > (AMD-Xilinx) <git@amd.com>; Simek, Michal <michal.simek@amd.com>
> > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> >
> > On Thu, 2025-09-25 at 07:37 +0000, Guntupalli, Manikanta wrote:
> > > [Public]
> > >
> > > Hi,
> > >
> > > > -----Original Message-----
> > > > From: Jorge Marques <gastmaier@gmail.com>
> > > > Sent: Thursday, September 25, 2025 12:47 PM
> > > > To: Arnd Bergmann <arnd@kernel.org>
> > > > Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> > > > <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> > > > engineering.com>; Frank Li <Frank.Li@nxp.com>; Arnd Bergmann
> > > > <arnd@arndb.de>; Guntupalli, Manikanta
> > > > <manikanta.guntupalli@amd.com>;
> > > > linux-
> > > > i3c@lists.infradead.org; linux-kernel@vger.kernel.org
> > > > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> > > >
> > > > On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > > > > From: Arnd Bergmann <arnd@arndb.de>
> > > > >
> > > > > Short MMIO transfers that are not a multiple of four bytes in size
> > > > > need a special case for the final bytes, however the existing
> > > > > implementation is not endian-safe and introduces an incorrect
> > > > > byteswap on big-endian kernels.
> > > > >
> > > > > This usually does not cause problems because most systems are
> > > > > little-endian and most transfers are multiple of four bytes long,
> > > > > but still needs to be fixed to avoid the extra byteswap.
> > > > >
> > > > > Change the special case for both i3c_writel_fifo() and
> > > > > i3c_readl_fifo() to use non-byteswapping writesl() and readsl()
> > > > > with a single element instead of the byteswapping writel()/readl()
> > > > > that are meant for individual MMIO registers. As data is copied
> > > > > between a FIFO and a memory buffer, the writesl()/readsl() loops
> > > > > are typically based on __raw_readl()/ __raw_writel(), resulting in
> > > > > the order of bytes in the FIFO to match the order in the buffer,
> > > > > regardless of the CPU endianess.
> > > > >
> > > > > The earlier versions in the dw-i3c and i3c-master-cdns had a
> > > > > correct implementation, but the generic version that was recently
> > > > > added broke
> > it.
> > > > >
> > > > > Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and
> > > > > i3c_writel_fifo()")
> > > > > Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> > > > > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > > > > ---
> > > > > This was a recent regression, the version in 6.16 still works, but
> > > > > 6.17-rc is broken.
> > > > >
> > > > > v2 changes:
> > > > > - add code comments
> > > > > - write correct data buffer
> > > > > ---
> > > > > drivers/i3c/internals.h | 12 ++++++++++--
> > > > > 1 file changed, 10 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
> > > > > index 0d857cc68cc5..79ceaa5f5afd 100644
> > > > > --- a/drivers/i3c/internals.h
> > > > > +++ b/drivers/i3c/internals.h
> > > > > @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem
> > > > > *addr, const
> > > > void *buf,
> > > > > u32 tmp = 0;
> > > > >
> > > > > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > > > > - writel(tmp, addr);
> > > > > + /*
> > > > > + * writesl() instead of writel() to keep FIFO
> > > > > + * byteorder on big-endian targets
> > > > > + */
> > > > > + writesl(addr, &tmp, 1);
> > > > > }
> > > > > }
> > > > >
> > > > > @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void
> > > > > __iomem *addr,
> > > > void *buf,
> > > > > if (nbytes & 3) {
> > > > > u32 tmp;
> > > > >
> > > > > - tmp = readl(addr);
> > > > > + /*
> > > > > + * readsl() instead of readl() to keep FIFO
> > > > > + * byteorder on big-endian targets
> > > > > + */
> > > > > + readsl(addr, &tmp, 1);
> > > > > memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> > > > > }
> > > > > }
> > > > Reviewed-by: Jorge Marques <jorge.marques@analog.com>
> > > > > --
> > > > > 2.39.5
> > > > >
> > >
> > > This patch fixes the sub-word transfer case on big-endian kernels, but
> > > it still does not address the scenario of little-endian kernels
> > > accessing big- endian FIFOs.
> > >
> >
> > I would argue that's something for callers of these functions to care about.
> If each I3C driver has to handle FIFO endianness individually, it introduces
> unnecessary duplication and overhead across drivers. Centralizing this in the
> FIFO access helpers keeps the logic consistent, avoids repeated boilerplate,
> and reduces the chance of subtle bugs.
I mean, that's what spi and i2c drivers do already. With enum i3c_fifo_endian
you're already forcing users to care (or know) about endianism so they might as
well just pass the data in the proper order already (not sure if it's such a big
'burden').
That said, I'm not really in the loop for i3c so not sure what the expectations
are. IOW, have no strong feeling about this at all :)
- Nuno Sá
> >
> > > With the current version, i3c_writel_fifo() and i3c_readl_fifo() only
> > > work when the FIFO has the same endianness as the CPU. On platforms
> > > such as the
> > > ZCU102 (Zynq UltraScale+ MPSoC, Cortex-A53, little-endian), the I3C
> > > FIFOs are big-endian, and this patch alone is not sufficient -
> > > transfers fail in that configuration.
> > >
> > > We have validated this on ZCU102, and the mismatch between LE kernel
> > > and BE FIFO is still an issue.
> > >
> > > On top of this fix, explicit FIFO endianness support is required, as
> > > proposed in [PATCH v7 3/4] "i3c: master: Add endianness support for
> > > i3c_readl_fifo() and i3c_writel_fifo()". That approach adds an endian
> > > argument and uses
> > > writesl_be()/readsl_be() where necessary, e.g.:
> > >
> > > static inline void i3c_writel_fifo(void __iomem *addr, const void
> > > *buf,
> > > int nbytes, enum i3c_fifo_endian
> > > endian) {
> > > if (endian)
> > > writesl_be(addr, buf, nbytes / 4);
> > > else
> > > writesl(addr, buf, nbytes / 4);
> > >
> > > if (nbytes & 3) {
> > > u32 tmp = 0;
> > >
> > > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > >
> > > if (endian)
> > > writesl_be(addr, &tmp, 1);
> > > else
> > > writesl(addr, &tmp, 1);
> > > }
> > > }
> > >
> > >
> Thanks,
> Manikanta.
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 8:58 ` Nuno Sá
@ 2025-09-25 9:35 ` Arnd Bergmann
2025-09-25 10:13 ` Nuno Sá
0 siblings, 1 reply; 12+ messages in thread
From: Arnd Bergmann @ 2025-09-25 9:35 UTC (permalink / raw)
To: Nuno Sá, Manikanta Guntupalli, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
linux-i3c@lists.infradead.org, linux-kernel@vger.kernel.org,
git (AMD-Xilinx), Michal Simek
On Thu, Sep 25, 2025, at 10:58, Nuno Sá wrote:
> On Thu, 2025-09-25 at 08:47 +0000, Guntupalli, Manikanta wrote:
>> > (AMD-Xilinx) <git@amd.com>; Simek, Michal <michal.simek@amd.com>
>> > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
>> > On Thu, 2025-09-25 at 07:37 +0000, Guntupalli, Manikanta wrote:
>> > > > i3c@lists.infradead.org; linux-kernel@vger.kernel.org
>> > > > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
>> > > > On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
>> >
>> > I would argue that's something for callers of these functions to care about.
>> If each I3C driver has to handle FIFO endianness individually, it introduces
>> unnecessary duplication and overhead across drivers. Centralizing this in the
>> FIFO access helpers keeps the logic consistent, avoids repeated boilerplate,
>> and reduces the chance of subtle bugs.
>
> I mean, that's what spi and i2c drivers do already. With enum i3c_fifo_endian
> you're already forcing users to care (or know) about endianism so they might as
> well just pass the data in the proper order already (not sure if it's such a big
> 'burden').
Can you give an example of an spi or i2c driver handles a similar
situation to the new i3c driver? As far as I can tell, swapping
the bytes in a FIFO register is very unusual for a hardware design
and probably a mistake rather than an intentional decision.
On the other hand, I can find drivers that are obviously wrong
on big-endian kernels, such as Tegra's i2c_writesl_vi() function
being unintentionally swapped from i2c_writesl() on big-endian.
For the i3c helper, I think Jorge's current version with my
fix should work for every normal driver, and I would not
want to make it more complicated for an obscure case. The
version for the AMD driver can just be in that driver, or
it could be a separate function name in the common header
if there is a chance we'll need it again.
Arnd
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 9:35 ` Arnd Bergmann
@ 2025-09-25 10:13 ` Nuno Sá
0 siblings, 0 replies; 12+ messages in thread
From: Nuno Sá @ 2025-09-25 10:13 UTC (permalink / raw)
To: Arnd Bergmann, Manikanta Guntupalli, Jorge Marques, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Frank Li,
linux-i3c@lists.infradead.org, linux-kernel@vger.kernel.org,
git (AMD-Xilinx), Michal Simek
On Thu, 2025-09-25 at 11:35 +0200, Arnd Bergmann wrote:
> On Thu, Sep 25, 2025, at 10:58, Nuno Sá wrote:
> > On Thu, 2025-09-25 at 08:47 +0000, Guntupalli, Manikanta wrote:
> > > > (AMD-Xilinx) <git@amd.com>; Simek, Michal <michal.simek@amd.com>
> > > > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> > > > On Thu, 2025-09-25 at 07:37 +0000, Guntupalli, Manikanta wrote:
> > > > > > i3c@lists.infradead.org; linux-kernel@vger.kernel.org
> > > > > > Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
> > > > > > On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > > >
> > > > I would argue that's something for callers of these functions to care
> > > > about.
> > > If each I3C driver has to handle FIFO endianness individually, it
> > > introduces
> > > unnecessary duplication and overhead across drivers. Centralizing this in
> > > the
> > > FIFO access helpers keeps the logic consistent, avoids repeated
> > > boilerplate,
> > > and reduces the chance of subtle bugs.
> >
> > I mean, that's what spi and i2c drivers do already. With enum
> > i3c_fifo_endian
> > you're already forcing users to care (or know) about endianism so they might
> > as
> > well just pass the data in the proper order already (not sure if it's such a
> > big
> > 'burden').
>
> Can you give an example of an spi or i2c driver handles a similar
> situation to the new i3c driver? As far as I can tell, swapping
> the bytes in a FIFO register is very unusual for a hardware design
> and probably a mistake rather than an intentional decision.
>
I meant that i2c and spi drivers (and I meant on the device side) already are
the ones having to care about putting the data in the proper endianism so that
controllers don't have to care (AFAIK).
But I so see now that the above is kind of unrelated.
> On the other hand, I can find drivers that are obviously wrong
> on big-endian kernels, such as Tegra's i2c_writesl_vi() function
> being unintentionally swapped from i2c_writesl() on big-endian.
>
> For the i3c helper, I think Jorge's current version with my
> fix should work for every normal driver, and I would not
> want to make it more complicated for an obscure case. The
> version for the AMD driver can just be in that driver, or
> it could be a separate function name in the common header
> if there is a chance we'll need it again.
>
I do agree with the above.
- Nuno Sá
> Arnd
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-24 20:18 [PATCH] [v2] i3c: fix big-endian FIFO transfers Arnd Bergmann
2025-09-25 7:16 ` Jorge Marques
@ 2025-09-25 15:09 ` Frank Li
2025-09-26 10:38 ` Guntupalli, Manikanta
2025-09-28 22:19 ` Alexandre Belloni
2 siblings, 1 reply; 12+ messages in thread
From: Frank Li @ 2025-09-25 15:09 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Arnd Bergmann,
Manikanta Guntupalli, linux-i3c, linux-kernel
On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> Short MMIO transfers that are not a multiple of four bytes in size need
> a special case for the final bytes, however the existing implementation
> is not endian-safe and introduces an incorrect byteswap on big-endian
> kernels.
>
> This usually does not cause problems because most systems are
> little-endian and most transfers are multiple of four bytes long, but
> still needs to be fixed to avoid the extra byteswap.
>
> Change the special case for both i3c_writel_fifo() and i3c_readl_fifo()
> to use non-byteswapping writesl() and readsl() with a single element
> instead of the byteswapping writel()/readl() that are meant for individual
> MMIO registers. As data is copied between a FIFO and a memory buffer,
> the writesl()/readsl() loops are typically based on __raw_readl()/
> __raw_writel(), resulting in the order of bytes in the FIFO to match
> the order in the buffer, regardless of the CPU endianess.
>
> The earlier versions in the dw-i3c and i3c-master-cdns had a correct
> implementation, but the generic version that was recently added broke it.
>
> Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and i3c_writel_fifo()")
> Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> This was a recent regression, the version in 6.16 still works,
> but 6.17-rc is broken.
>
> v2 changes:
> - add code comments
> - write correct data buffer
> ---
> drivers/i3c/internals.h | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
> index 0d857cc68cc5..79ceaa5f5afd 100644
> --- a/drivers/i3c/internals.h
> +++ b/drivers/i3c/internals.h
> @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr, const void *buf,
> u32 tmp = 0;
>
> memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> - writel(tmp, addr);
> + /*
> + * writesl() instead of writel() to keep FIFO
> + * byteorder on big-endian targets
> + */
endian look like how CPU decode byte order to MSB to LSB.
targets FIFO define look like
BIT 31..24 23..16 15..8 7..0
B3 B2 B1 B0
regardless CPU is big endian or little endian system, data in memory should
be
0x000 B0
0x004 B1
0x008 B2
0x00c B3
I think your sentence in commit message is better
/* writesl() instead of writel() to keep FIFO byte orderer to match the order
in the buffer regardless of the CPU endianess.
*/
Frank
> + writesl(addr, &tmp, 1);
> }
> }
>
> @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem *addr, void *buf,
> if (nbytes & 3) {
> u32 tmp;
>
> - tmp = readl(addr);
> + /*
> + * readsl() instead of readl() to keep FIFO
> + * byteorder on big-endian targets
> + */
> + readsl(addr, &tmp, 1);
> memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> }
> }
> --
> 2.39.5
>
>
> --
> linux-i3c mailing list
> linux-i3c@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-25 15:09 ` Frank Li
@ 2025-09-26 10:38 ` Guntupalli, Manikanta
0 siblings, 0 replies; 12+ messages in thread
From: Guntupalli, Manikanta @ 2025-09-26 10:38 UTC (permalink / raw)
To: Frank Li, Arnd Bergmann
Cc: Alexandre Belloni, Jorge Marques, Wolfram Sang, Arnd Bergmann,
linux-i3c@lists.infradead.org, linux-kernel@vger.kernel.org,
git (AMD-Xilinx), Simek, Michal
[Public]
Hi,
> -----Original Message-----
> From: Frank Li <Frank.li@nxp.com>
> Sent: Thursday, September 25, 2025 8:39 PM
> To: Arnd Bergmann <arnd@kernel.org>
> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>; Jorge Marques
> <jorge.marques@analog.com>; Wolfram Sang <wsa+renesas@sang-
> engineering.com>; Arnd Bergmann <arnd@arndb.de>; Guntupalli, Manikanta
> <manikanta.guntupalli@amd.com>; linux-i3c@lists.infradead.org; linux-
> kernel@vger.kernel.org
> Subject: Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
>
> On Wed, Sep 24, 2025 at 10:18:33PM +0200, Arnd Bergmann wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > Short MMIO transfers that are not a multiple of four bytes in size
> > need a special case for the final bytes, however the existing
> > implementation is not endian-safe and introduces an incorrect byteswap
> > on big-endian kernels.
> >
> > This usually does not cause problems because most systems are
> > little-endian and most transfers are multiple of four bytes long, but
> > still needs to be fixed to avoid the extra byteswap.
> >
> > Change the special case for both i3c_writel_fifo() and
> > i3c_readl_fifo() to use non-byteswapping writesl() and readsl() with a
> > single element instead of the byteswapping writel()/readl() that are
> > meant for individual MMIO registers. As data is copied between a FIFO
> > and a memory buffer, the writesl()/readsl() loops are typically based
> > on __raw_readl()/ __raw_writel(), resulting in the order of bytes in
> > the FIFO to match the order in the buffer, regardless of the CPU endianess.
> >
> > The earlier versions in the dw-i3c and i3c-master-cdns had a correct
> > implementation, but the generic version that was recently added broke it.
> >
> > Fixes: 733b439375b4 ("i3c: master: Add inline i3c_readl_fifo() and
> > i3c_writel_fifo()")
> > Cc: Manikanta Guntupalli <manikanta.guntupalli@amd.com>
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > ---
> > This was a recent regression, the version in 6.16 still works, but
> > 6.17-rc is broken.
> >
> > v2 changes:
> > - add code comments
> > - write correct data buffer
> > ---
> > drivers/i3c/internals.h | 12 ++++++++++--
> > 1 file changed, 10 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h index
> > 0d857cc68cc5..79ceaa5f5afd 100644
> > --- a/drivers/i3c/internals.h
> > +++ b/drivers/i3c/internals.h
> > @@ -38,7 +38,11 @@ static inline void i3c_writel_fifo(void __iomem *addr, const
> void *buf,
> > u32 tmp = 0;
> >
> > memcpy(&tmp, buf + (nbytes & ~3), nbytes & 3);
> > - writel(tmp, addr);
> > + /*
> > + * writesl() instead of writel() to keep FIFO
> > + * byteorder on big-endian targets
> > + */
>
> endian look like how CPU decode byte order to MSB to LSB.
> targets FIFO define look like
>
> BIT 31..24 23..16 15..8 7..0
> B3 B2 B1 B0
>
> regardless CPU is big endian or little endian system, data in memory should be
>
> 0x000 B0
> 0x004 B1
> 0x008 B2
> 0x00c B3
>
> I think your sentence in commit message is better
>
> /* writesl() instead of writel() to keep FIFO byte orderer to match the order in the
> buffer regardless of the CPU endianess.
> */
>
> Frank
> > + writesl(addr, &tmp, 1);
> > }
> > }
> >
> > @@ -55,7 +59,11 @@ static inline void i3c_readl_fifo(const void __iomem *addr,
> void *buf,
> > if (nbytes & 3) {
> > u32 tmp;
> >
> > - tmp = readl(addr);
> > + /*
> > + * readsl() instead of readl() to keep FIFO
> > + * byteorder on big-endian targets
> > + */
> > + readsl(addr, &tmp, 1);
> > memcpy(buf + (nbytes & ~3), &tmp, nbytes & 3);
> > }
> > }
> > --
> > 2.39.5
> >
> >
> > --
> > linux-i3c mailing list
> > linux-i3c@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-i3c
We will include this patch as part of "[PATCH V8 0/5] Add AMD I3C master controller driver and bindings", since the patch series depends on it.
Thanks,
Manikanta.
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] [v2] i3c: fix big-endian FIFO transfers
2025-09-24 20:18 [PATCH] [v2] i3c: fix big-endian FIFO transfers Arnd Bergmann
2025-09-25 7:16 ` Jorge Marques
2025-09-25 15:09 ` Frank Li
@ 2025-09-28 22:19 ` Alexandre Belloni
2 siblings, 0 replies; 12+ messages in thread
From: Alexandre Belloni @ 2025-09-28 22:19 UTC (permalink / raw)
To: Jorge Marques, Wolfram Sang, Frank Li, Arnd Bergmann
Cc: Arnd Bergmann, Manikanta Guntupalli, linux-i3c, linux-kernel
On Wed, 24 Sep 2025 22:18:33 +0200, Arnd Bergmann wrote:
> Short MMIO transfers that are not a multiple of four bytes in size need
> a special case for the final bytes, however the existing implementation
> is not endian-safe and introduces an incorrect byteswap on big-endian
> kernels.
>
> This usually does not cause problems because most systems are
> little-endian and most transfers are multiple of four bytes long, but
> still needs to be fixed to avoid the extra byteswap.
>
> [...]
Applied, thanks!
[1/1] i3c: fix big-endian FIFO transfers
https://git.kernel.org/i3c/c/d6ddd9beb1a5
Best regards,
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-09-28 22:19 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-24 20:18 [PATCH] [v2] i3c: fix big-endian FIFO transfers Arnd Bergmann
2025-09-25 7:16 ` Jorge Marques
2025-09-25 7:37 ` Guntupalli, Manikanta
2025-09-25 7:51 ` Nuno Sá
2025-09-25 8:47 ` Guntupalli, Manikanta
2025-09-25 8:58 ` Nuno Sá
2025-09-25 9:35 ` Arnd Bergmann
2025-09-25 10:13 ` Nuno Sá
2025-09-25 8:55 ` Arnd Bergmann
2025-09-25 15:09 ` Frank Li
2025-09-26 10:38 ` Guntupalli, Manikanta
2025-09-28 22:19 ` Alexandre Belloni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox