[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAOiHx=nSEP=4s2xZuPtLEO43YDbkNEYzw6V11JbXG0H2iPn7Ag@mail.gmail.com>
Date: Tue, 28 Oct 2025 21:19:53 +0100
From: Jonas Gorski <jonas.gorski@...il.com>
To: Caleb James DeLisle <cjd@...ns.fr>
Cc: nbd@....name, lorenzo@...nel.org, ryder.lee@...iatek.com,
shayne.chen@...iatek.com, sean.wang@...iatek.com, matthias.bgg@...il.com,
angelogioacchino.delregno@...labora.com, linux-wireless@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-mediatek@...ts.infradead.org
Subject: Re: [PATCH] wifi: mt76: mmio_(read|write)_copy byte swap when on Big Endian
Hi,
On Mon, Oct 27, 2025 at 6:19 PM Caleb James DeLisle <cjd@...ns.fr> wrote:
>
> When on a Big Endian machine, PCI swaps words to/from LE when
> reading/writing them. This presents a problem when we're trying
> to copy an opaque byte array such as firmware or encryption key.
>
> Byte-swapping during copy results in two swaps, but solves the
> problem.
>
> Fixes:
> mt76x2e 0000:02:00.0: ROM patch build: 20141115060606a
> mt76x2e 0000:02:00.0: Firmware Version: 0.0.00
> mt76x2e 0000:02:00.0: Build: 1
> mt76x2e 0000:02:00.0: Build Time: 201607111443____
> mt76x2e 0000:02:00.0: Firmware failed to start
> mt76x2e 0000:02:00.0: probe with driver mt76x2e failed with error -145
>
> Signed-off-by: Caleb James DeLisle <cjd@...ns.fr>
> ---
> drivers/net/wireless/mediatek/mt76/mmio.c | 34 +++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c
> index cd2e9737c3bf..776dbaacc8a3 100644
> --- a/drivers/net/wireless/mediatek/mt76/mmio.c
> +++ b/drivers/net/wireless/mediatek/mt76/mmio.c
> @@ -30,15 +30,49 @@ static u32 mt76_mmio_rmw(struct mt76_dev *dev, u32 offset, u32 mask, u32 val)
> return val;
> }
>
> +static void mt76_mmio_write_copy_portable(void __iomem *dst,
> + const u8 *src, int len)
> +{
> + __le32 val;
> + int i = 0;
> +
> + for (i = 0; i < ALIGN(len, 4); i += 4) {
> + memcpy(&val, src + i, sizeof(val));
> + writel(cpu_to_le32(val), dst + i);
> + }
> +}
> +
> static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,
> const void *data, int len)
> {
> + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
> + mt76_mmio_write_copy_portable(dev->mmio.regs + offset, data,
> + len);
> + return;
> + }
> __iowrite32_copy(dev->mmio.regs + offset, data, DIV_ROUND_UP(len, 4));
Maybe just replace this with memcpy_toio() which does no swapping at
all instead of double swapping on BE?
> }
>
> +static void mt76_mmio_read_copy_portable(u8 *dst,
> + const void __iomem *src, int len)
> +{
> + u32 val;
> + int i;
> +
> + for (i = 0; i < ALIGN(len, 4); i += 4) {
> + val = le32_to_cpu(readl(src + i));
> + memcpy(dst + i, &val, sizeof(val));
> + }
> +}
> +
> static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
> void *data, int len)
> {
> + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
> + mt76_mmio_read_copy_portable(data, dev->mmio.regs + offset,
> + len);
> + return;
> + }
> __ioread32_copy(data, dev->mmio.regs + offset, DIV_ROUND_UP(len, 4));
And memcpy_fromio() here.
Best regards,
Jonas
Powered by blists - more mailing lists