From: Simon Horman <horms@kernel.org>
To: Ahmad Fatoum <a.fatoum@pengutronix.de>
Cc: Mark Brown <broonie@kernel.org>, Shawn Guo <shawnguo@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
jiada wang <jiada_wang@mentor.com>,
linux-spi@vger.kernel.org, NXP Linux Team <linux-imx@nxp.com>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH] spi: imx: correct handling of MXC_CSPIRXDATA value endianness
Date: Fri, 26 May 2023 17:13:00 +0200 [thread overview]
Message-ID: <ZHDMfC1d5GyhaUb1@kernel.org> (raw)
In-Reply-To: <dd601c80-87dc-c032-4b75-5ac368981f64@pengutronix.de> <d29db298-0484-ea6f-3554-fa02b3a077dd@pengutronix.de>
On Fri, May 26, 2023 at 04:09:48PM +0200, Ahmad Fatoum wrote:
> Hello Simon,
>
> On 26.05.23 16:03, Simon Horman wrote:
> > The existing code seems be intended to handle MXC_CSPIRXDATA values
> > which are in big endian. However, it seems that this is only
> > handled correctly in the case where the host is little endian.
> >
> > First, consider the read case.
> >
> > u32 val = be32_to_cpu(readl(...))
> >
> > readl() will read a 32bit value and return it after applying le32_to_cpu().
> > On a little endian host le32_to_cpu() is a noop. So the raw value is
> > returned. This is then converted from big endian to host byte-order -
> > the value is byte-swapped - using be32_to_cpu(). Assuming the raw value
> > is big endian a host byte-order value is obtained. This seems correct.
> >
> > However, on a big endian system, le32_to_cpu() will perform a byte-swap,
> > while be32_to_cpu() is a noop. Assuming the underlying value is big
> > endian this is incorrect, because it should not be byte-swapped to
> > obtain the value in host byte-order - big endian.
> >
> > Surveying other kernel code it seems that a correct approach is:
> >
> > be32_to_cpu((__force __be32)__raw_readl(...))
>
> How about using ioread32be?
...
On Fri, May 26, 2023 at 04:12:46PM +0200, Ahmad Fatoum wrote:
> On 26.05.23 16:09, Ahmad Fatoum wrote:
> >> - writel(val, spi_imx->base + MXC_CSPITXDATA);
> >> + __raw_writel((__force u32)cpu_to_be32(val),
> >> + spi_imx->base + MXC_CSPITXDATA);
> >> }
>
> On more thing: __raw_writel doesn't involve a write barrier (at least
> on ARM). That means above code introduces a bug as the CPU may now reorder
> writes that were sequential before. Both iowrite32be() and readl()
> have a __iowmb(); on ARM before doing the write itself.
Thanks Ahmad,
I agree that ioread32be() and iowrite32be() look like a better solution.
I'll plan to spin a v2 accordingly.
WARNING: multiple messages have this Message-ID (diff)
From: Simon Horman <horms@kernel.org>
To: Ahmad Fatoum <a.fatoum@pengutronix.de>
Cc: Mark Brown <broonie@kernel.org>, Shawn Guo <shawnguo@kernel.org>,
Sascha Hauer <s.hauer@pengutronix.de>,
jiada wang <jiada_wang@mentor.com>,
linux-spi@vger.kernel.org, NXP Linux Team <linux-imx@nxp.com>,
Pengutronix Kernel Team <kernel@pengutronix.de>,
Fabio Estevam <festevam@gmail.com>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH] spi: imx: correct handling of MXC_CSPIRXDATA value endianness
Date: Fri, 26 May 2023 17:13:00 +0200 [thread overview]
Message-ID: <ZHDMfC1d5GyhaUb1@kernel.org> (raw)
In-Reply-To: <dd601c80-87dc-c032-4b75-5ac368981f64@pengutronix.de> <d29db298-0484-ea6f-3554-fa02b3a077dd@pengutronix.de>
On Fri, May 26, 2023 at 04:09:48PM +0200, Ahmad Fatoum wrote:
> Hello Simon,
>
> On 26.05.23 16:03, Simon Horman wrote:
> > The existing code seems be intended to handle MXC_CSPIRXDATA values
> > which are in big endian. However, it seems that this is only
> > handled correctly in the case where the host is little endian.
> >
> > First, consider the read case.
> >
> > u32 val = be32_to_cpu(readl(...))
> >
> > readl() will read a 32bit value and return it after applying le32_to_cpu().
> > On a little endian host le32_to_cpu() is a noop. So the raw value is
> > returned. This is then converted from big endian to host byte-order -
> > the value is byte-swapped - using be32_to_cpu(). Assuming the raw value
> > is big endian a host byte-order value is obtained. This seems correct.
> >
> > However, on a big endian system, le32_to_cpu() will perform a byte-swap,
> > while be32_to_cpu() is a noop. Assuming the underlying value is big
> > endian this is incorrect, because it should not be byte-swapped to
> > obtain the value in host byte-order - big endian.
> >
> > Surveying other kernel code it seems that a correct approach is:
> >
> > be32_to_cpu((__force __be32)__raw_readl(...))
>
> How about using ioread32be?
...
On Fri, May 26, 2023 at 04:12:46PM +0200, Ahmad Fatoum wrote:
> On 26.05.23 16:09, Ahmad Fatoum wrote:
> >> - writel(val, spi_imx->base + MXC_CSPITXDATA);
> >> + __raw_writel((__force u32)cpu_to_be32(val),
> >> + spi_imx->base + MXC_CSPITXDATA);
> >> }
>
> On more thing: __raw_writel doesn't involve a write barrier (at least
> on ARM). That means above code introduces a bug as the CPU may now reorder
> writes that were sequential before. Both iowrite32be() and readl()
> have a __iowmb(); on ARM before doing the write itself.
Thanks Ahmad,
I agree that ioread32be() and iowrite32be() look like a better solution.
I'll plan to spin a v2 accordingly.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-05-26 15:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-26 14:03 [PATCH] spi: imx: correct handling of MXC_CSPIRXDATA value endianness Simon Horman
2023-05-26 14:03 ` Simon Horman
2023-05-26 14:09 ` Ahmad Fatoum
2023-05-26 14:09 ` Ahmad Fatoum
2023-05-26 14:12 ` Ahmad Fatoum
2023-05-26 14:12 ` Ahmad Fatoum
2023-05-26 15:13 ` Simon Horman [this message]
2023-05-26 15:13 ` Simon Horman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZHDMfC1d5GyhaUb1@kernel.org \
--to=horms@kernel.org \
--cc=a.fatoum@pengutronix.de \
--cc=broonie@kernel.org \
--cc=festevam@gmail.com \
--cc=jiada_wang@mentor.com \
--cc=kernel@pengutronix.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-imx@nxp.com \
--cc=linux-spi@vger.kernel.org \
--cc=s.hauer@pengutronix.de \
--cc=shawnguo@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.