* [PATCH] ARM: move Risc PC-specific <asm/hardware/iomd.h> header into mach-rpc
From: Ethan Nelson-Moore @ 2026-05-10 3:10 UTC (permalink / raw)
To: linux-arm-kernel, linux-i2c, linux-input, linux-fbdev
Cc: Russell King, Ethan Nelson-Moore, Andi Shyti, Dmitry Torokhov,
Helge Deller, Kees Cook
The <asm/hardware/iomd.h> header is specific to the IOMD chip used on
the Risc PC. Move it into mach-rpc to avoid polluting asm/hardware/
with machine-specific headers.
Also take the opportunity to remove a comment with the file path from
the header, which is bad style.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
MAINTAINERS | 1 -
arch/arm/mach-rpc/dma.c | 2 +-
arch/arm/{include/asm/hardware => mach-rpc/include/mach}/iomd.h | 2 --
arch/arm/mach-rpc/irq.c | 2 +-
arch/arm/mach-rpc/riscpc.c | 2 +-
arch/arm/mach-rpc/time.c | 2 +-
drivers/i2c/busses/i2c-acorn.c | 2 +-
drivers/input/mouse/rpcmouse.c | 2 +-
drivers/input/serio/rpckbd.c | 2 +-
drivers/video/fbdev/acornfb.h | 2 +-
10 files changed, 8 insertions(+), 11 deletions(-)
rename arch/arm/{include/asm/hardware => mach-rpc/include/mach}/iomd.h (98%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 211cc683e25b..6a1da8903c04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3398,7 +3398,6 @@ M: Russell King <linux@armlinux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: http://www.armlinux.org.uk/
-F: arch/arm/include/asm/hardware/iomd.h
F: arch/arm/mach-rpc/
F: drivers/net/ethernet/8390/etherh.c
F: drivers/net/ethernet/i825xx/ether1*
diff --git a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c
index 50e0f97afd75..717a81475670 100644
--- a/arch/arm/mach-rpc/dma.c
+++ b/arch/arm/mach-rpc/dma.c
@@ -20,7 +20,7 @@
#include <linux/uaccess.h>
#include <asm/mach/dma.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
struct iomd_dma {
struct dma_struct dma;
diff --git a/arch/arm/include/asm/hardware/iomd.h b/arch/arm/mach-rpc/include/mach/iomd.h
similarity index 98%
rename from arch/arm/include/asm/hardware/iomd.h
rename to arch/arm/mach-rpc/include/mach/iomd.h
index e3f130345ebc..2a3f4a5f3fd9 100644
--- a/arch/arm/include/asm/hardware/iomd.h
+++ b/arch/arm/mach-rpc/include/mach/iomd.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * arch/arm/include/asm/hardware/iomd.h
- *
* Copyright (C) 1999 Russell King
*
* This file contains information out the IOMD ASIC used in the
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index e924c9b813ab..649d81874c86 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -4,7 +4,7 @@
#include <linux/io.h>
#include <asm/mach/irq.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
#include <asm/irq.h>
#include <asm/fiq.h>
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index f70fb9c4b0cb..d068f5e4873d 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -22,7 +22,7 @@
#include <asm/elf.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
#include <asm/page.h>
#include <asm/domain.h>
#include <asm/setup.h>
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index ad93c4dfafcd..566113f9774f 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -17,7 +17,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
#include <asm/mach/time.h>
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 99b6b1c3fd9e..703b4a42f466 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -13,7 +13,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
#define FORCE_ONES 0xdc
#define SCL 0x02
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 6774029e0a1a..475c3ca22fd4 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -23,7 +23,7 @@
#include <mach/hardware.h>
#include <asm/irq.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
MODULE_AUTHOR("Vojtech Pavlik, Russell King");
MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index 4d817850ba3b..e452ad07e2fa 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -17,7 +17,7 @@
#include <linux/slab.h>
#include <mach/hardware.h>
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
MODULE_AUTHOR("Vojtech Pavlik, Russell King");
MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
diff --git a/drivers/video/fbdev/acornfb.h b/drivers/video/fbdev/acornfb.h
index f8df4ecb4fd7..e65388587f80 100644
--- a/drivers/video/fbdev/acornfb.h
+++ b/drivers/video/fbdev/acornfb.h
@@ -7,7 +7,7 @@
* Frame buffer code for Acorn platforms
*/
#if defined(HAS_VIDC20)
-#include <asm/hardware/iomd.h>
+#include <mach/iomd.h>
#define VIDC_PALETTE_SIZE 256
#define VIDC_NAME "VIDC20"
#endif
--
2.43.0
^ permalink raw reply related
* Re: [PATCH/RFC 10/14] dt-bindings: power: Document Renesas R-Car X5H Module Controller
From: Marek Vasut @ 2026-05-10 3:02 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Sudeep Holla, Cristian Marussi, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Magnus Damm, Saravana Kannan, Michael Turquette,
Stephen Boyd, Philipp Zabel, Ulf Hansson, Rafael J . Wysocki,
Kevin Hilman, Florian Fainelli, Wolfram Sang, Kuninori Morimoto,
arm-scmi, linux-arm-kernel, linux-renesas-soc, linux-clk,
devicetree, linux-pm, linux-kernel
In-Reply-To: <CAMuHMdUU=RohST4LDDD27W5dj=HwJFApMcDpsXATQ1MaMH-tUA@mail.gmail.com>
On 5/8/26 10:26 AM, Geert Uytterhoeven wrote:
Hello Geert,
>> Since there are up to 32 MPDG registers, and 256 resets, can we encode
>> both into a single cell ?
>>
>> (mpdg_register_offset << 16) | (reset_bit_offset << 0)
>
> We could. I did consider it (with a shift of 8 cfr. 256 modules),
> but see below...
>
>> I cannot tell whether this is much better, but it at least ties the PD
>> components (power domain and clock domain) into a single value, which
>> matches reality a bit better. The current split power domain and clock
>> domain description in two cells gives me the illusion that it is
>> possible to mix and match power domains and clock domains in DT
>> description, but in fact the two cells are strongly tied together.
>
> They are only tied together in the sense that a module (hardware block)
> is part of a power domain, and has module standby (clock) control.
> Some power domains are backed by MDLC hardware registers,
> others are not, hence the need for the additional definitions in
> <dt-bindings/power/renesas,r8a78000-mdlc.h>.
> I am not aware (yet) of modules that are part of a power domain,
> but do not have module standby control. If these exist, we
> need an additional definition (R8A78000_MDLC_MODULE_NONE?) in
> <dt-bindings/power/renesas,r8a78000-mdlc.h>.
Maybe TAUJ3 in AON domain? I think HSCN also has abundance of examples.
> Due to this separation, and due to a possible future need for expansion
> (R8A78000_MDLC_MODULE_NONE, MDLCs with more than 256 modules, ...),
> I went for two cells.
I think I won't push for a single cell either, two cells are OK with me too.
>> If we cannot encode the two into a single cell, maybe we can at least
>> have some sort of macro for this, e.g. this (0xff as no MPDG register
>> bits for this block):
>> #define R8A78000_MDLC_PD_HSCIF0 (0xff << 16) ((0x5 << 4) | (0x3 << 0))
>>
>> What do you think ?
>
> I (and I believe the DT maintainers) are not so fond of defines for
> numbers that can be (more or less) just read from the documentation.
OK
> (and 0xff should be R8A78000_MDLC_PD_APL?)
I think AON would have to be 0xff , since it is superdomain of APL ?
>>> So perhaps I will clarify like this:
>>>
>>> - The first power domain specifier cell is the power domain part, and
>>> must be either the Module Power Domain Gating (MPDG) register index
>>
>> ... for power domains which are backed by MDPG bits, and which can be
>> controlled in that manner ...
>
> OK.
>
>>> (0x00-0x3f) from the datasheet, or a Power Domain number, as defined in
>>> <dt-bindings/power/renesas,r8a78000-mdlc.h>,
>>
>> ... for power domains which are always on, and for which there are no
>> MPDG bits which can be used to control them ...
>
> OK,
>
>>
>>> - The second power domain specifier cell is the clock domain part, and
>
> Upon second thought: s/clock domain/module standby/
If you could even mention that this refers to "Module STOP" column bit,
that would even clearer.
>>> must be the module number (0x00-0xff), composed of the Module System
>>> Reset (MSRES) register index in the high nibble, and the Module Reset
>>> Destination bitfield index in the low nibble.
>>
>> I can understand this.
>>
>>>>> + '#reset-cells':
>>>>> + description:
>>>>> + The single reset specifier cell must be the module number (0x00-0xff).
>>>>> + const: 1
>>>>
>>>> [...]
>>>>
>>>>> +#ifndef __DT_BINDINGS_POWER_RENESAS_R8A78000_MDLC_H__
>>>>> +#define __DT_BINDINGS_POWER_RENESAS_R8A78000_MDLC_H__
>>>>> +
>>>>> +/* R-Car X5H MDLC Power Domains */
>>>>> +
>>>>> +#define R8A78000_MDLC_PD_AON 0x40
>>>>> +#define R8A78000_MDLC_PD_SCP 0x41
>>>>> +#define R8A78000_MDLC_PD_APL 0x42
>>>>> +#define R8A78000_MDLC_PD_CMN 0x43
>>>>> +#define R8A78000_MDLC_PD_ACL 0x44
>>>> ... what do these numbers represent ? Shouldn't those be register
>>>> offsets from MDLC MPDG00 according to power-domain-cells ?
>>>
>>> These are Power Domains that are not backed by any of the 64 Module
>>> Power Domain Gating (MPDG) registers in MDLC blocks.
>>
>> I suspect that might not be entirely correct for all of them, please
>> read on and see CMN below.
>
> Thanks, looks like R8A78000_MDLC_PD_CMN should be dropped.
>
>> Let's take PD_AC00 , AP core 0 , as a domain of interest. My
>> understanding is, that the domain structure for PD_AC00 looks as follows:
>>
>> PD_AON {
>> PD_SCP { };
>> PD_APL {
>> hierarchy is SYSSS
>> always-power-on
>> PD_CMN {
>> hierarchy is CMNN
>> power-gating-bit is MDLC_CMNN 20
>> PD_APU0 {
>> hierarchy is SYSSS
>> power-gating is done by APMU
>> PD_ACL0 {
>> hierarchy is CMNN
>> power-gating-bit is MDLC_CMNN 16
>> PD_AC00 {
>> hierarchy is CMNN
>> power-gating-bit is MDLC_CMNN 0
>> };
>> ...
>> };
>> ...
>> };
>> ...
>> };
>> ...
>> PD_HSCIF0 {
>> hierarchy is PERW
>> power-gating-bit is MDLC_PERW 23
>> };
>> };
>> ...
>> };
>>
>> With this in mind, I think CPU 0 DT node should refer to the PD_AC00
>> power domain this way:
>>
>> cpu@0 {
>> ...
>> power-domains = <&mdlc_cmnn R8A78000_MDLC_PD_AC00>;
>> ...
>> };
>
> So we do have a few modules (I found a few more) that are part of
> power domains, but do no support module standby. One more reason to
> decouple them in power-domains.
I think HSCN is a really good example ?
> However, CPU cores are controlled through PSCI (the slightly less evil
> brother of SCMI? ;-), so
> Documentation/devicetree/bindings/arm/psci.yaml applies, too?
We can indeed control cores purely via PSCI , yes.
(Upstream TFA needs one more platform patch to make this operable)
>> The MDLC driver would pass the PD_AC00 domain ID to matching SCMI power
>> domain management protocol call, or, for bare-metal MDLC driver, would
>> have to internally encode PD hierarchy, walk it, and apply PD operations
>> in each step.
>>
>> I think even for SCIF/HSCIF, the power domain reference should be
>> something along the lines of the following description. The MDLC driver
>> should internally encode that R8A78000_MLDC_PD_HSCIF0 is a sub-domain of
>> R8A78000_MDLC_PD_APL .
>>
>> serial@c0710000 {
>> ...
>> power-domains = <&mdlc_perw R8A78000_MDLC_PD_HSCIF0>;
>> ...
>> };
>
> R8A78000_MLDC_PD_HSCIF0 is a not a full sub-domain, but merely standby
> (clock) control inside the PD_APL clock domain?
Do you consider R8A78000_MDLC_PD_AC00 a full sub-domain ? Because that
one looks very similar to R8A78000_MDLC_PD_HSCIF0 , except the former
controls a core, the later an UART IP.
^ permalink raw reply
* [PATCH] ARM: riscpc: use iomd.h everywhere and remove redundant ioc.h header
From: Ethan Nelson-Moore @ 2026-05-10 2:56 UTC (permalink / raw)
To: linux-arm-kernel, linux-i2c; +Cc: Russell King, Ethan Nelson-Moore, Andi Shyti
The <asm/hardware/ioc.h> header contains a subset of the definitions of
the <asm/hardware/iomd.h> header, just with different names. This is
because the IOC chip (used in 26-bit Acorn computers) contains a subset
of the functionality of the later IOMD chip used in the Risc PC. Linux
formerly supported 26-bit Acorn computers, but that support was removed
in commit 99eb8a550dbc ("Remove the arm26 port") because it had
bitrotted to the extent that it did not even compile.
Adjust all references to ioc.h to use iomd.h and its constants and
remove the redundant ioc.h header. Also correct formatting on
affected lines and remove the now-unused IOC_BASE constant.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
MAINTAINERS | 1 -
arch/arm/include/asm/hardware/ioc.h | 69 -----------------------
arch/arm/include/asm/hardware/iomd.h | 2 +-
arch/arm/mach-rpc/fiq.S | 4 +-
arch/arm/mach-rpc/include/mach/hardware.h | 1 -
arch/arm/mach-rpc/irq.c | 6 +-
arch/arm/mach-rpc/time.c | 18 +++---
drivers/i2c/busses/i2c-acorn.c | 18 +++---
8 files changed, 24 insertions(+), 95 deletions(-)
delete mode 100644 arch/arm/include/asm/hardware/ioc.h
diff --git a/MAINTAINERS b/MAINTAINERS
index b865ad67fda3..211cc683e25b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3398,7 +3398,6 @@ M: Russell King <linux@armlinux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: http://www.armlinux.org.uk/
-F: arch/arm/include/asm/hardware/ioc.h
F: arch/arm/include/asm/hardware/iomd.h
F: arch/arm/mach-rpc/
F: drivers/net/ethernet/8390/etherh.c
diff --git a/arch/arm/include/asm/hardware/ioc.h b/arch/arm/include/asm/hardware/ioc.h
deleted file mode 100644
index 6edd27fcd048..000000000000
--- a/arch/arm/include/asm/hardware/ioc.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/include/asm/hardware/ioc.h
- *
- * Copyright (C) Russell King
- *
- * Use these macros to read/write the IOC. All it does is perform the actual
- * read/write.
- */
-#ifndef __ASMARM_HARDWARE_IOC_H
-#define __ASMARM_HARDWARE_IOC_H
-
-#ifndef __ASSEMBLY__
-
-/*
- * We use __raw_base variants here so that we give the compiler the
- * chance to keep IOC_BASE in a register.
- */
-#define ioc_readb(off) __raw_readb(IOC_BASE + (off))
-#define ioc_writeb(val,off) __raw_writeb(val, IOC_BASE + (off))
-
-#endif
-
-#define IOC_CONTROL (0x00)
-#define IOC_KARTTX (0x04)
-#define IOC_KARTRX (0x04)
-
-#define IOC_IRQSTATA (0x10)
-#define IOC_IRQREQA (0x14)
-#define IOC_IRQCLRA (0x14)
-#define IOC_IRQMASKA (0x18)
-
-#define IOC_IRQSTATB (0x20)
-#define IOC_IRQREQB (0x24)
-#define IOC_IRQMASKB (0x28)
-
-#define IOC_FIQSTAT (0x30)
-#define IOC_FIQREQ (0x34)
-#define IOC_FIQMASK (0x38)
-
-#define IOC_T0CNTL (0x40)
-#define IOC_T0LTCHL (0x40)
-#define IOC_T0CNTH (0x44)
-#define IOC_T0LTCHH (0x44)
-#define IOC_T0GO (0x48)
-#define IOC_T0LATCH (0x4c)
-
-#define IOC_T1CNTL (0x50)
-#define IOC_T1LTCHL (0x50)
-#define IOC_T1CNTH (0x54)
-#define IOC_T1LTCHH (0x54)
-#define IOC_T1GO (0x58)
-#define IOC_T1LATCH (0x5c)
-
-#define IOC_T2CNTL (0x60)
-#define IOC_T2LTCHL (0x60)
-#define IOC_T2CNTH (0x64)
-#define IOC_T2LTCHH (0x64)
-#define IOC_T2GO (0x68)
-#define IOC_T2LATCH (0x6c)
-
-#define IOC_T3CNTL (0x70)
-#define IOC_T3LTCHL (0x70)
-#define IOC_T3CNTH (0x74)
-#define IOC_T3LTCHH (0x74)
-#define IOC_T3GO (0x78)
-#define IOC_T3LATCH (0x7c)
-
-#endif
diff --git a/arch/arm/include/asm/hardware/iomd.h b/arch/arm/include/asm/hardware/iomd.h
index 53006ba5350f..e3f130345ebc 100644
--- a/arch/arm/include/asm/hardware/iomd.h
+++ b/arch/arm/include/asm/hardware/iomd.h
@@ -15,7 +15,7 @@
/*
* We use __raw_base variants here so that we give the compiler the
- * chance to keep IOC_BASE in a register.
+ * chance to keep IOMD_BASE in a register.
*/
#define iomd_readb(off) __raw_readb(IOMD_BASE + (off))
#define iomd_readl(off) __raw_readl(IOMD_BASE + (off))
diff --git a/arch/arm/mach-rpc/fiq.S b/arch/arm/mach-rpc/fiq.S
index 087bdf4bc093..a600761c3dfd 100644
--- a/arch/arm/mach-rpc/fiq.S
+++ b/arch/arm/mach-rpc/fiq.S
@@ -3,8 +3,8 @@
#include <asm/assembler.h>
#include <mach/hardware.h>
- .equ ioc_base_high, IOC_BASE & 0xff000000
- .equ ioc_base_low, IOC_BASE & 0x00ff0000
+ .equ ioc_base_high, IOMD_BASE & 0xff000000
+ .equ ioc_base_low, IOMD_BASE & 0x00ff0000
.text
.global rpc_default_fiq_end
diff --git a/arch/arm/mach-rpc/include/mach/hardware.h b/arch/arm/mach-rpc/include/mach/hardware.h
index 6f197706f979..22d62a198559 100644
--- a/arch/arm/mach-rpc/include/mach/hardware.h
+++ b/arch/arm/mach-rpc/include/mach/hardware.h
@@ -48,7 +48,6 @@
#define ECARD_IOC4_BASE (IO_BASE + 0x00270000)
#define ECARD_IOC_BASE (IO_BASE + 0x00240000)
#define IOMD_BASE (IO_BASE + 0x00200000)
-#define IOC_BASE (IO_BASE + 0x00200000)
#define ECARD_MEMC8_BASE (IO_BASE + 0x0002b000)
#define FLOPPYDMA_BASE (IO_BASE + 0x0002a000)
#define PCIO_BASE (IO_BASE + 0x00010000)
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index dc29384b6ef8..e924c9b813ab 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -77,19 +77,19 @@ static int iomd_get_irq_nr(void)
u8 reg;
/* get highest priority first */
- reg = readb(IOC_BASE + IOMD_IRQREQB);
+ reg = readb(IOMD_BASE + IOMD_IRQREQB);
irq = irq_prio_h[reg];
if (irq)
return irq;
/* get DMA */
- reg = readb(IOC_BASE + IOMD_DMAREQ);
+ reg = readb(IOMD_BASE + IOMD_DMAREQ);
irq = irq_prio_d[reg];
if (irq)
return irq;
/* get low priority */
- reg = readb(IOC_BASE + IOMD_IRQREQA);
+ reg = readb(IOMD_BASE + IOMD_IRQREQA);
irq = irq_prio_l[reg];
if (irq)
return irq;
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 9f8edcfe9357..ad93c4dfafcd 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -17,7 +17,7 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/hardware/ioc.h>
+#include <asm/hardware/iomd.h>
#include <asm/mach/time.h>
@@ -33,15 +33,15 @@ static u64 ioc_timer_read(struct clocksource *cs)
u32 ticks;
local_irq_save(flags);
- ioc_writeb (0, IOC_T0LATCH);
+ iomd_writeb(0, IOMD_T0LATCH);
barrier ();
- count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+ count1 = iomd_readb(IOMD_T0CNTL) | (iomd_readb(IOMD_T0CNTH) << 8);
barrier ();
- status = ioc_readb(IOC_IRQREQA);
+ status = iomd_readb(IOMD_IRQREQA);
barrier ();
- ioc_writeb (0, IOC_T0LATCH);
+ iomd_writeb(0, IOMD_T0LATCH);
barrier ();
- count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+ count2 = iomd_readb(IOMD_T0CNTL) | (iomd_readb(IOMD_T0CNTH) << 8);
ticks = ioc_time + RPC_LATCH - count2;
local_irq_restore(flags);
@@ -72,9 +72,9 @@ static struct clocksource ioctime_clocksource = {
void __init ioctime_init(void)
{
- ioc_writeb(RPC_LATCH & 255, IOC_T0LTCHL);
- ioc_writeb(RPC_LATCH >> 8, IOC_T0LTCHH);
- ioc_writeb(0, IOC_T0GO);
+ iomd_writeb(RPC_LATCH & 255, IOMD_T0LTCHL);
+ iomd_writeb(RPC_LATCH >> 8, IOMD_T0LTCHH);
+ iomd_writeb(0, IOMD_T0GO);
}
static irqreturn_t
diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c
index 34bbbb8c52f6..99b6b1c3fd9e 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -13,23 +13,23 @@
#include <linux/io.h>
#include <mach/hardware.h>
-#include <asm/hardware/ioc.h>
+#include <asm/hardware/iomd.h>
#define FORCE_ONES 0xdc
#define SCL 0x02
#define SDA 0x01
/*
- * We must preserve all non-i2c output bits in IOC_CONTROL.
+ * We must preserve all non-i2c output bits in IOMD_CONTROL.
* Note also that we need to preserve the value of SCL and
* SDA outputs as well (which may be different from the
- * values read back from IOC_CONTROL).
+ * values read back from IOMD_CONTROL).
*/
static u_int force_ones;
static void ioc_setscl(void *data, int state)
{
- u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
+ u_int iomd_control = iomd_readb(IOMD_CONTROL) & ~(SCL | SDA);
u_int ones = force_ones;
if (state)
@@ -39,12 +39,12 @@ static void ioc_setscl(void *data, int state)
force_ones = ones;
- ioc_writeb(ioc_control | ones, IOC_CONTROL);
+ iomd_writeb(iomd_control | ones, IOMD_CONTROL);
}
static void ioc_setsda(void *data, int state)
{
- u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA);
+ u_int iomd_control = iomd_readb(IOMD_CONTROL) & ~(SCL | SDA);
u_int ones = force_ones;
if (state)
@@ -54,17 +54,17 @@ static void ioc_setsda(void *data, int state)
force_ones = ones;
- ioc_writeb(ioc_control | ones, IOC_CONTROL);
+ iomd_writeb(iomd_control | ones, IOMD_CONTROL);
}
static int ioc_getscl(void *data)
{
- return (ioc_readb(IOC_CONTROL) & SCL) != 0;
+ return (iomd_readb(IOMD_CONTROL) & SCL) != 0;
}
static int ioc_getsda(void *data)
{
- return (ioc_readb(IOC_CONTROL) & SDA) != 0;
+ return (iomd_readb(IOMD_CONTROL) & SDA) != 0;
}
static struct i2c_algo_bit_data ioc_data = {
--
2.43.0
^ permalink raw reply related
* [PATCH] ARM: remove unused <asm/hardware/memc.h> header
From: Ethan Nelson-Moore @ 2026-05-10 2:48 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel; +Cc: Russell King, Ethan Nelson-Moore
The <asm/hardware/memc.h> header is not used by any code in the kernel.
It contains definitions for the MEMC memory controllers used in 26-bit
Acorn computers.
Linux formerly supported these computers, but that support was removed
in commit 99eb8a550dbc ("Remove the arm26 port") because it had
bitrotted to the extent that it did not even compile.
Remove this unused header.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
MAINTAINERS | 1 -
arch/arm/include/asm/hardware/memc.h | 23 -----------------------
2 files changed, 24 deletions(-)
delete mode 100644 arch/arm/include/asm/hardware/memc.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 5d8a887c868e..b865ad67fda3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3400,7 +3400,6 @@ S: Maintained
W: http://www.armlinux.org.uk/
F: arch/arm/include/asm/hardware/ioc.h
F: arch/arm/include/asm/hardware/iomd.h
-F: arch/arm/include/asm/hardware/memc.h
F: arch/arm/mach-rpc/
F: drivers/net/ethernet/8390/etherh.c
F: drivers/net/ethernet/i825xx/ether1*
diff --git a/arch/arm/include/asm/hardware/memc.h b/arch/arm/include/asm/hardware/memc.h
deleted file mode 100644
index 1d4ebe0a9678..000000000000
--- a/arch/arm/include/asm/hardware/memc.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * arch/arm/include/asm/hardware/memc.h
- *
- * Copyright (C) Russell King.
- */
-#define VDMA_ALIGNMENT PAGE_SIZE
-#define VDMA_XFERSIZE 16
-#define VDMA_INIT 0
-#define VDMA_START 1
-#define VDMA_END 2
-
-#ifndef __ASSEMBLY__
-extern void memc_write(unsigned int reg, unsigned long val);
-
-#define video_set_dma(start,end,offset) \
-do { \
- memc_write (VDMA_START, (start >> 2)); \
- memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2); \
- memc_write (VDMA_INIT, (offset >> 2)); \
-} while (0)
-
-#endif
--
2.43.0
^ permalink raw reply related
* [PATCH] arm: lib/delay-loop.S: remove unnecessary ARMv4 selection for ARCH_RPC
From: Ethan Nelson-Moore @ 2026-05-10 2:46 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel; +Cc: Russell King, Ethan Nelson-Moore
This was done because Risc PC kernels were compiled as ARMv3, which
does not support long multiply instructions used in this file, to work
around the fact that the Risc PC's bus does not handle half-word
accesses. However, Risc PC kernels were changed to compile as ARMv3M
(ARMv3 with long multiply) in commit 8403bcb779a0 ("ARM: 8801/1:
makefile: use ARMv3M mode for RiscPC"), so selecting ARMv4 for this
file is no longer necessary. Drop this unnecessary code.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
arch/arm/lib/delay-loop.S | 4 ----
1 file changed, 4 deletions(-)
diff --git a/arch/arm/lib/delay-loop.S b/arch/arm/lib/delay-loop.S
index 33b08ca1c242..56f9eea56268 100644
--- a/arch/arm/lib/delay-loop.S
+++ b/arch/arm/lib/delay-loop.S
@@ -9,10 +9,6 @@
#include <asm/assembler.h>
#include <asm/delay.h>
-#ifdef CONFIG_ARCH_RPC
- .arch armv4
-#endif
-
.text
.LC0: .word loops_per_jiffy
--
2.43.0
^ permalink raw reply related
* [PATCH] ARM: mach-rpc: fix zImage build after recent font-related changes
From: Ethan Nelson-Moore @ 2026-05-10 2:39 UTC (permalink / raw)
To: linux-arm-kernel, linux-fbdev
Cc: Russell King, Ethan Nelson-Moore, Helge Deller, Thomas Zimmermann,
Kees Cook
The text display code used in the Risc PC kernel image decompression
code uses arch/arm/boot/compressed/font.c, which includes
lib/fonts/font_acorn_8x8.c, which further includes <linux/font.h>.
Since commit 97df8960240a ("lib/fonts: Provide helpers for calculating
glyph pitch and size") <linux/font.h> contains inline functions that
require __do_div64, which is not linked into the ARM kernel
decompressor. This makes Risc PC zImages fail to build.
Resolve this issue in the least intrusive way possible by preventing
the inclusion of <linux/font.h> (and the definition of a struct that
relies on it) when the decompressor is being built.
Fixes: 97df8960240a ("lib/fonts: Provide helpers for calculating glyph pitch and size")
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
arch/arm/boot/compressed/Makefile | 6 +++++-
lib/fonts/font_acorn_8x8.c | 2 ++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index a159120d1e42..0e198a6ce447 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -157,4 +157,8 @@ $(obj)/piggy_data: $(obj)/../Image FORCE
$(obj)/piggy.o: $(obj)/piggy_data
-CFLAGS_font.o := -Dstatic=
+# Defining _VIDEO_FONT_H prevents including <linux/font.h>, which contains
+# inline functions that require __do_div64, which is not linked into the
+# decompressor. OMIT_FONT_DESC is used in lib/fonts/font_acorn_8x8.c to omit the
+# definition of the font's font_desc structure, which requires <linux/font.h>.
+CFLAGS_font.o := -Dstatic= -D_VIDEO_FONT_H -DOMIT_FONT_DESC
diff --git a/lib/fonts/font_acorn_8x8.c b/lib/fonts/font_acorn_8x8.c
index 36c51016769d..6b5291c23fc8 100644
--- a/lib/fonts/font_acorn_8x8.c
+++ b/lib/fonts/font_acorn_8x8.c
@@ -265,6 +265,7 @@ static const struct font_data acorndata_8x8 = {
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
} };
+#ifndef OMIT_FONT_DESC /* Used by arch/arm/boot/compressed/Makefile */
const struct font_desc font_acorn_8x8 = {
.idx = ACORN8x8_IDX,
.name = "Acorn8x8",
@@ -278,3 +279,4 @@ const struct font_desc font_acorn_8x8 = {
.pref = 0,
#endif
};
+#endif /* OMIT_FONT_DESC */
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next 08/12] dt-bindings: net: toshiba,tc965x-dwmac: add TC956x Ethernet bridge
From: Bjorn Andersson @ 2026-05-10 2:25 UTC (permalink / raw)
To: Alex Elder
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, maxime.chevallier,
rmk+kernel, konradybcio, robh, krzk+dt, conor+dt, linusw, brgl,
arnd, gregkh, Daniel Thompson, mohd.anwar, a0987203069,
alexandre.torgue, ast, boon.khai.ng, chenchuangyu, chenhuacai,
daniel, hawk, hkallweit1, inochiama, john.fastabend, julianbraha,
livelycarpet87, matthew.gerlach, mcoquelin.stm32, me,
prabhakar.mahadev-lad.rj, richardcochran, rohan.g.thomas, sdf,
siyanteng, weishangjuan, wens, netdev, bpf, linux-arm-msm,
devicetree, linux-gpio, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <3c78f48c-6478-46d0-87c2-581bb58637dd@riscstar.com>
On Thu, May 07, 2026 at 01:37:09PM -0500, Alex Elder wrote:
> On 5/7/26 9:12 AM, Bjorn Andersson wrote:
> > On Fri, May 01, 2026 at 10:54:16AM -0500, Alex Elder wrote:
> > > diff --git a/Documentation/devicetree/bindings/net/toshiba,tc956x-dwmac.yaml b/Documentation/devicetree/bindings/net/toshiba,tc956x-dwmac.yaml
> > [..]
> > > +
> > > + gpio-controller: true
> >
> > I don't have any concern with the use of a proper gpio driver to model
> > the implementation, but if I understand correctly this relationship
> > between gpio controller and gpio consumer is strictly internal to "the
> > PCI device".
>
> (I think you're already cool with this but I still wanted to respond.)
>
Thank you for the further clarifications, and added details, Alex. This
does look reasonable to me.
Regards,
Bjorn
> That is not correct. These GPIO lines are used two ways for the
> RB3gen2:
> - drivers/pci/pwrctrl/pci-pwrctrl-tc9563.c uses GPIOs 2 and 3 to
> assert/deassert the reset lines associated with the two exposed
> downstream PCIe ports on the PCIe switch within the TC956x.
>
> - Each of the Ethernet PHYs has a reset GPIO. On the RB3gen2, the
> GPIOs used for the purpose come from the GPIO controller embedded
> in the TC9564 (00 and 01).
>
> These are therefore "exposed" (they are *not* strictly internal).
>
> > Is this connection variable or is the link merely expressed in
> > DeviceTree to mitigate the fact that you choose to implement the
> > responsibilities of the two parts split into two device drivers?
>
> It is variable. These resets might be implemented by other GPIO
> controllers on other platforms.
>
> > Are there other consumers of these TC956x gpios which would result in a
> > board designer (and hence dts author) to ever reference this
> > gpio-controller in a different way?
>
> They could. Nine of these GPIOs are exposed by the TC956x pins
> (GPIO00-06, GPIO12, GPIO35 and GPIO36). The RB3gen2 uses 00-03
> (and possibly 04 but that's for a PHY we haven't tested yet).
>
> -Alex
>
> > Regards,
> > Bjorn
>
^ permalink raw reply
* Re: [PATCH] sound: soc: fsl: eukrea-tlv320: update board checks to use the DT
From: Mark Brown @ 2026-05-10 1:25 UTC (permalink / raw)
To: Ethan Nelson-Moore
Cc: linux-arm-kernel, linux-sound, Russell King, Liam Girdwood,
Jaroslav Kysela, Takashi Iwai
In-Reply-To: <20260509214622.38319-1-enelsonmoore@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 617 bytes --]
On Sat, May 09, 2026 at 02:46:19PM -0700, Ethan Nelson-Moore wrote:
> The eukrea-tlv320 driver contains checks for ARM machine IDs via
> machine_is_*() macros. The boards concerned now support only FDT
> booting, which does not use machine IDs, and therefore the code should
> be updated to check the DT compatible property instead.
Please submit patches using subject lines reflecting the style for the
subsystem, this makes it easier for people to identify relevant patches.
Look at what existing commits in the area you're changing are doing and
make sure your subject lines visually resemble what they're doing.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] sound: soc: ti: rx51: remove stale reference to machine_is_nokia_rx51()
From: Mark Brown @ 2026-05-10 1:22 UTC (permalink / raw)
To: Ethan Nelson-Moore
Cc: linux-arm-kernel, linux-sound, linux-omap, Russell King,
Peter Ujfalusi, Jarkko Nikula, Liam Girdwood, Jaroslav Kysela,
Takashi Iwai
In-Reply-To: <20260509012247.14990-1-enelsonmoore@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 766 bytes --]
On Fri, May 08, 2026 at 06:22:46PM -0700, Ethan Nelson-Moore wrote:
> The rx51 driver relies on the machine_is_nokia_rx51() macro, which is
> always false since commit 9b7141d01a76 ("ARM: OMAP2+: Drop legacy board
> file for n900"). Its presence prevents the removal of boards no longer
> present in the kernel from arch/arm/tools/mach-types, because the
> machine_is_*() macros are generated from mach-types. Drop this unused
> code.
Please submit patches using subject lines reflecting the style for the
subsystem, this makes it easier for people to identify relevant patches.
Look at what existing commits in the area you're changing are doing and
make sure your subject lines visually resemble what they're doing.
There's no need to resubmit to fix this alone.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v6 05/25] iommu/arm-smmu-v3: Move IDR parsing to common functions
From: Jason Gunthorpe @ 2026-05-09 23:34 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <afxlufh3t3hRe4-G@google.com>
On Thu, May 07, 2026 at 10:13:13AM +0000, Mostafa Saleh wrote:
> > I was thinking more like
> >
> > #define arm_smmu arm_pkvm_smmu
> >
> > Before the pkvm compile of the shared code.
>
> Oh, so we rely on arm_pkvm_smmu and arm_smmu having the same field
> names and types?
Just for the shared code, yes.
For instance this patch would require the features field be present in
both, and then all you do is directly copy all the smmu->features
logic into the shared file and that's it.
> I don’t think that’s better for maintainability, I can look into it
> if Robin and Will are OK with that.
I think maintainability here means pkvm minimizes how much it changes
the code of the main driver.
Copying a bunch of functions into a shared .c file exactly as it is,
then compiling the shared file with some #ifdef'ery at is going to be
long term better than trying to mangle the whole thing to avoid using
any of the core types and not directly share the code, IMHO.
Like my tlbi point for instance, it is not a good idea to rip out a
little bit of the invalidation logic then open code a pkvm
version. Use the exact driver code. But to do this you need to pass an
arm_smmu through to to the pkvm specific queue management functions.
> > How does pkvm compilation work anyhow? Is it all rolled into a unique
> > link, or do you have to worry about symbol conflicts with the main
> > kernel?
>
> All pkvm symbols are prefixed with __kvm_nvhe_ in the main kernel.
So automatically with objcopy or something like that during the build?
Jason
^ permalink raw reply
* Re: [PATCH v6 04/25] iommu/arm-smmu-v3: Move TLB range invalidation into common code
From: Jason Gunthorpe @ 2026-05-09 23:29 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <afxd8Km40A5ulZvd@google.com>
On Thu, May 07, 2026 at 09:40:00AM +0000, Mostafa Saleh wrote:
> But that doesn’t solve the problem, which is: At some point, whether
> eagerly from the page table code, through gather sync or a fancy
> invalidation array, the driver will need to populate a range
> invalidation command (tg, ttl, scale...) and this logic is better
> shared with the main driver which is this patch does.
My point is this patch doesn't share enough. If you do need to issue
invalidations then share everything below the top level tlbi entry
point and don't try to make a pkvm version of the entire logic just by
ripping out the range logic.
There is no reason for pkvm to need a different algorithm
here. Especially when you get to supporting ATS and multiple devices
and smmus you may as well just use the whole thing.
Which is why I suggested to copy the entire call chain into a shared
file
Jason
^ permalink raw reply
* Re: [PATCH v6 08/25] KVM: arm64: iommu: Shadow host stage-2 page table
From: Jason Gunthorpe @ 2026-05-09 23:27 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <afiRB3e3o0G1oZvY@google.com>
On Mon, May 04, 2026 at 12:28:55PM +0000, Mostafa Saleh wrote:
> So far this is the list of requirements/changes needed share the
> stage-2 page table (besides the obvious: same page table format,
> granularity, endianness...)
>
> 1) HW BBM is not supported in the hypervisor page table, that’s
> because it can generate TLB conflict aborts, which the hypervisor
> can not handle because of the limited syndrome information.
> We can rely on FEAT_BBML3 which was newly introduced to work
> around that, it’s quite niche and not supported in KVM yet or
> have an allow list similar to the kernel
> (as in cpu_supports_bbml2_noabort()) which also limits the number
> of CPUs that can run this.
Do you think pkvm will need BBM? Hitless replace of a PTE is already a
pretty advanced feature and the SMMU has its own support matrix there
too. Is it for shared/private conversion?
> 2) Handling page faults, devices must be able to stall and let the
> hypervisor handle the page fault (which has to proxy through the
> kernel as the hypervisor doesn’t handle interrupts), this includes
> also IO page faults which are hard to get right from the HW which
> and may lead to system stability issues or lockups.
No.. once you turn on IO like this you don't have page faults
anymore. Everything must be permantently mapped into the SMMU view, it
can never be made non-present and you must run without page
faults. That's what you have in the io-pgtable constructed table,
right?
> Alternatively, we can pin the stage-2 pages, that would require some
> hypercalls, hacks to the driver/IOMMU API and possibly new semantics
> in the DMA-API for IDENTITY devices as they will still need to pin
> the pages as they are actually in stage-2 translation and not bypass.
?? Then how does this series work?
> 3) SMMUv3 must be coherent.
Yes for sure.
> 4) Support BTM/DVM for TLB invalidation, otherwise some hooks are
> still required (although not io-pgtable-arm)
SW needs to forward invalidations, BTM is rare..
> IMO, 1, 2 are the most tricky parts. It's more work and runs on very
> limited systems, However, it can be implemented as an optimization)
> which is my plan.
I think unless you can do it without these HW features (excluding 3)
don't bother.
> I am not sure how CCA deals with that, I’d expect they have a lot of
> constraints on CPUs/SMMUs and DMA capable devices on those systems.
3 is not supported. The entire S2 is permanently mapped and doesn't
really change alot at runtime. No page faults, not sure if the RMM
private/shard conversion would require BMM..
Jason
^ permalink raw reply
* Re: [PATCH v6 06/25] iommu/io-pgtable-arm: Rework to use the iommu-pages API
From: Jason Gunthorpe @ 2026-05-09 23:21 UTC (permalink / raw)
To: Mostafa Saleh
Cc: linux-arm-kernel, linux-kernel, kvmarm, iommu, catalin.marinas,
will, maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
joro, jean-philippe, mark.rutland, qperret, tabba, vdonnefort,
sebastianene, keirf
In-Reply-To: <afiO2WL4ILGfmUui@google.com>
On Mon, May 04, 2026 at 12:19:37PM +0000, Mostafa Saleh wrote:
> > So.. I suggest you update it to use the iommu_pages API, #ifdef out
> > the allocator so the pkvm pkvm doesn't need to deal with it. Then
> > compile a special iommu-pages for the pkvm side presenting the same
> > API.
>
> I see, we still need to leave the DMA-API calls for the custom config,
> as I am not sure if it can use pages not backed by the vmemmap, I
> pushed that into a separate function so it’s easily compiled out.
Yeah..
> Without this patch, now it looks like:
Seems reasonable, and then i'd probably just put something like
#define dma_map(...)
#define dma_umap(...)
To effectively take it out of the pkvm build
Then have a pkvm compile of iommu-pages to provide the functions in a
pkvm compatible way. I guess you can't actually fully do this, but
can do enough to support this file at least.
> > You should have a pkvm shim header that provides
> > kmalloc/kfree/virt_to_phys in the normal way and just #include that in
> > io-pgtable when doing a pkvm build instead of hacking up all the code.
>
> Ok, I can do that in another change, but I believe it's better to
> change the usage in this file to arm_lpae_*(virt_to_phys...) so it's
> clear which parts are intended for that.
IDK, why? virt_to_phys() is part of the iommu-pages API, I'd just
leave it.. If you want to narrow it then #define it for pkvm when
compiling this file..
Jason
^ permalink raw reply
* [PATCH] arm: boot: ep93xx: don't rely on machine_is_*() for removed board files
From: Ethan Nelson-Moore @ 2026-05-09 22:38 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Russell King, Ethan Nelson-Moore, Hartley Sweeten,
Alexander Sverdlin, Nikita Shubin
Code in misc-ep93xx.h relies on machine_is_*() macros for several
boards that no longer have legacy board files. They were removed in
commit e5ef574dda70 ("ARM: ep93xx: delete all boardfiles"). This
prevents the removal of machine IDs no longer used by the kernel from
mach-types. To resolve this issue, create local copies of these macros.
(The checks themselves are still valid because the IDs are still passed
in by the bootloader on these machines.) Also take the opportunity to
remove three repeated checks for the same ID.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
arch/arm/boot/compressed/misc-ep93xx.h | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/compressed/misc-ep93xx.h b/arch/arm/boot/compressed/misc-ep93xx.h
index 65b4121d1490..b0a1b42aab31 100644
--- a/arch/arm/boot/compressed/misc-ep93xx.h
+++ b/arch/arm/boot/compressed/misc-ep93xx.h
@@ -3,7 +3,22 @@
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
*/
-#include <asm/mach-types.h>
+/*
+ * These machine IDs are no longer used by the kernel since EP93xx was converted
+ * to DT booting, but they are still passed in by bootloaders, so we use our own
+ * local definitions of the relevant macros.
+ */
+#define machine_is_bk3() (__machine_arch_type == 1880)
+#define machine_is_edb9301() (__machine_arch_type == 462)
+#define machine_is_edb9302a() (__machine_arch_type == 1127)
+#define machine_is_edb9302() (__machine_arch_type == 538)
+#define machine_is_edb9307a() (__machine_arch_type == 1128)
+#define machine_is_edb9307() (__machine_arch_type == 607)
+#define machine_is_edb9312() (__machine_arch_type == 451)
+#define machine_is_edb9315a() (__machine_arch_type == 772)
+#define machine_is_edb9315() (__machine_arch_type == 463)
+#define machine_is_ts72xx() (__machine_arch_type == 673)
+#define machine_is_vision_ep9307() (__machine_arch_type == 1578)
static inline unsigned int __raw_readl(unsigned int ptr)
{
@@ -60,14 +75,11 @@ static inline void ep93xx_decomp_setup(void)
if (machine_is_edb9301() ||
machine_is_edb9302() ||
machine_is_edb9302a() ||
- machine_is_edb9302a() ||
machine_is_edb9307() ||
machine_is_edb9307a() ||
- machine_is_edb9307a() ||
machine_is_edb9312() ||
machine_is_edb9315() ||
machine_is_edb9315a() ||
- machine_is_edb9315a() ||
machine_is_ts72xx() ||
machine_is_bk3() ||
machine_is_vision_ep9307())
--
2.43.0
^ permalink raw reply related
* [PATCH] sound: soc: fsl: eukrea-tlv320: update board checks to use the DT
From: Ethan Nelson-Moore @ 2026-05-09 21:46 UTC (permalink / raw)
To: linux-arm-kernel, linux-sound
Cc: Russell King, Ethan Nelson-Moore, Liam Girdwood, Mark Brown,
Jaroslav Kysela, Takashi Iwai
The eukrea-tlv320 driver contains checks for ARM machine IDs via
machine_is_*() macros. The boards concerned now support only FDT
booting, which does not use machine IDs, and therefore the code should
be updated to check the DT compatible property instead.
Non-DT booting support for these machines was removed in these
commits:
commit f2f55499942a ("ARM: imx: Remove eukrea_mbimxsd35 non-dt support")
commit 3877942b0c7f ("ARM: imx25: Remove eukrea mx25 board files")
commit 7c5deaf77526 ("ARM: i.MX: Remove mach-cpuimx27sd board file")
commit 8da4d6b2f798 ("ARM: mx51: Remove mach-cpuimx51sd board file")
The presence of these machine ID checks prevents the removal of
machine IDs no longer used by the kernel from arch/arm/tools/mach-types,
because the machine_is_*() macros are generated from mach-types. To
resolve this issue, use of_machine_is_compatible() instead.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
sound/soc/fsl/eukrea-tlv320.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 6be074ea0b3f..2e6abd620571 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -142,7 +142,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
eukrea_tlv320.name = "cpuimx-audio";
}
- if (machine_is_eukrea_cpuimx27() ||
+ if (of_machine_is_compatible("eukrea,cpuimx27") ||
(tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux"))) {
imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
IMX_AUDMUX_V1_PCR_SYN |
@@ -159,12 +159,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
);
of_node_put(tmp_np);
- } else if (machine_is_eukrea_cpuimx25sd() ||
- machine_is_eukrea_cpuimx35sd() ||
- machine_is_eukrea_cpuimx51sd() ||
+ } else if (of_machine_is_compatible("eukrea,cpuimx25") ||
+ of_machine_is_compatible("eukrea,cpuimx35") ||
+ of_machine_is_compatible("eukrea,cpuimx51") ||
(tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux"))) {
if (!np)
- ext_port = machine_is_eukrea_cpuimx25sd() ?
+ ext_port = of_machine_is_compatible("eukrea,cpuimx25") ?
4 : 3;
imx_audmux_v2_configure_port(int_port,
--
2.43.0
^ permalink raw reply related
* [PATCH] arm: mm: init: update checks for Integrator boards to use the DT
From: Ethan Nelson-Moore @ 2026-05-09 21:14 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Russell King, Ethan Nelson-Moore, Andrew Morton,
Mike Rapoport (Microsoft)
arch/arm/mm/init.c contains two checks for ARM machine IDs via
machine_is_*() macros. The two boards concerned now support only FDT
booting, which does not use machine IDs, and therefore the code should
be updated to check the DT compatible property instead.
Non-DT booting support for these machines was removed in
commit d7057e1de8d6 ("ARM: integrator: delete non-devicetree boot
path"). The presence of these machine ID checks prevents the removal of
machine IDs no longer used by the kernel from arch/arm/tools/mach-types,
because the machine_is_*() macros are generated from mach-types. To
resolve this issue, use of_machine_is_compatible() instead.
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
arch/arm/mm/init.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 0cc1bf04686d..a44b16b3c273 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -14,6 +14,7 @@
#include <linux/export.h>
#include <linux/nodemask.h>
#include <linux/initrd.h>
+#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
@@ -25,7 +26,6 @@
#include <linux/execmem.h>
#include <asm/cp15.h>
-#include <asm/mach-types.h>
#include <asm/memblock.h>
#include <asm/page.h>
#include <asm/prom.h>
@@ -415,7 +415,8 @@ void free_initmem(void)
fix_kernmem_perms();
poison_init_mem(__init_begin, __init_end - __init_begin);
- if (!machine_is_integrator() && !machine_is_cintegrator())
+ if (!of_machine_is_compatible("arm,integrator-ap") &&
+ !of_machine_is_compatible("arm,integrator-cp"))
free_initmem_default(-1);
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 8/8] ARM: Remove hacked-up asm/types.h header
From: Arnd Bergmann @ 2026-05-09 20:33 UTC (permalink / raw)
To: Eric Biggers, Ard Biesheuvel
Cc: linux-arm-kernel, linux-crypto, linux-raid, Ard Biesheuvel,
Christoph Hellwig, Russell King
In-Reply-To: <20260509200503.GC11883@quark>
On Sat, May 9, 2026, at 22:05, Eric Biggers wrote:
> On Wed, Apr 22, 2026 at 07:17:04PM +0200, Ard Biesheuvel wrote:
>> From: Ard Biesheuvel <ardb@kernel.org>
>>
>> ARM has a special version of asm/types.h which contains overrides for
>> certain #define's related to the C types used to back C99 types such as
>> uint32_t and uintptr_t.
>>
>> This is only needed when pulling in system headers such as stdint.h
>> during the build, and this only happens when using NEON intrinsics,
>> for which there is now a dedicated header file.
>>
>> So drop this header entirely, and revert to the asm-generic one.
>>
>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
> This is actually a UAPI header. I guess it got put there accidentally
> and isn't actually needed there?
Yes, commit ed79c9d34f4f ("ARM: put types.h in uapi") has some
explanations.
I can't think of any case where this would actually be used
from userland, and lots of ways it could cause trouble in
theory, even if it never has in practice.
Arnd
^ permalink raw reply
* Re: [PATCH 7/8] lib/raid6: Include asm/neon-intrinsics.h rather than arm_neon.h
From: Eric Biggers @ 2026-05-09 20:23 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Ard Biesheuvel, linux-arm-kernel, linux-crypto, linux-raid,
Ard Biesheuvel, Russell King, Arnd Bergmann
In-Reply-To: <20260423074712.GC31018@lst.de>
On Thu, Apr 23, 2026 at 09:47:12AM +0200, Christoph Hellwig wrote:
> On Wed, Apr 22, 2026 at 07:17:03PM +0200, Ard Biesheuvel wrote:
> > From: Ard Biesheuvel <ardb@kernel.org>
> >
> > arm_neon.h is a compiler header which needs some scaffolding to work
> > correctly in the linux context, and so it is better not to include it
> > directly. Both ARM and arm64 now provide asm/neon-intrinsics.h which
> > takes care of this.
>
>
> This could potentially clash with the raid6 library rework I'm doing
> for 7.2. Although git has become pretty good about renamed files, so
> maybe it won't be so bad.
>
I think this patch also breaks the userspace build of lib/raid6/. Which
is going away in Christoph's series anyway, but maybe it would make
sense to drop this patch (and patch 8 which depends on this, I think)
from this series for now? That would make it a bit easier to take the
rest through crc-next.
- Eric
^ permalink raw reply
* Re: [PATCH 8/8] ARM: Remove hacked-up asm/types.h header
From: Eric Biggers @ 2026-05-09 20:05 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: linux-arm-kernel, linux-crypto, linux-raid, Ard Biesheuvel,
Christoph Hellwig, Russell King, Arnd Bergmann
In-Reply-To: <20260422171655.3437334-18-ardb+git@google.com>
On Wed, Apr 22, 2026 at 07:17:04PM +0200, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
>
> ARM has a special version of asm/types.h which contains overrides for
> certain #define's related to the C types used to back C99 types such as
> uint32_t and uintptr_t.
>
> This is only needed when pulling in system headers such as stdint.h
> during the build, and this only happens when using NEON intrinsics,
> for which there is now a dedicated header file.
>
> So drop this header entirely, and revert to the asm-generic one.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
> arch/arm/include/uapi/asm/types.h | 41 --------------------
> 1 file changed, 41 deletions(-)
>
This is actually a UAPI header. I guess it got put there accidentally
and isn't actually needed there?
- Eric
^ permalink raw reply
* [PATCH v2 0/8] drm/sun4i: update DE33 support
From: Jernej Skrabec @ 2026-05-09 19:00 UTC (permalink / raw)
To: wens, samuel
Cc: mripard, maarten.lankhorst, tzimmermann, airlied, simona, robh,
krzk+dt, conor+dt, mturquette, sboyd, dri-devel, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk,
jernej.skrabec, Jernej Skrabec
This is second series out of tree which aims at properly introducing
support for H616 Display Engine 3.3. Previous series [1] reorganized
driver so proper DE33 support can be easily implemented.
H616 DE33 support was actually introduced a while back, but it was done
without fully understanding hardware design. Fortunately, no user of
H616 DE33 binding was introduced, so we have a chance to update bindings
and introduce proper DE33 support. Issue with existing binding is that it
considers planes as resource which is hardwired to each mixer as it was
done on older Display Engine generations (DE3 and lower). That is not the
case anymore. This series introduces new driver for planes management,
which allows doing proper plane assignments.
Remaining patches, which introduce all the missing bits to fully support
display pipeline on H616 SoC, will be sent once this series is merged.
WIP patches, which can be used for testing purposes, can be found at [2].
Please take a look.
Best regards,
Jernej
Link to v1: https://lore.kernel.org/linux-sunxi/20251115141347.13087-1-jernej.skrabec@gmail.com/
[1] https://lore.kernel.org/linux-sunxi/20251104180942.61538-1-jernej.skrabec@gmail.com/T/#t
[2] https://github.com/jernejsk/linux-1/commits/sun4i-drm-refactor/
Jernej Skrabec (8):
clk: sunxi-ng: de2: Fix Display Engine 3.3 definitions
clk: sunxi-ng: de2: Export register regmap for DE33
drm/sun4i: Add support for DE33 CSC
drm/sun4i: vi_layer: Limit formats for DE33
dt-bindings: display: allwinner: Add DE33 planes
drm/sun4i: Add planes driver
dt-bindings: display: allwinner: Split H616 DE33 layer reg space
drm/sun4i: switch DE33 to new bindings
.../allwinner,sun50i-h616-de33-planes.yaml | 46 ++++
.../allwinner,sun8i-a83t-de2-mixer.yaml | 16 +-
drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 87 +++++++-
drivers/gpu/drm/sun4i/Makefile | 3 +-
drivers/gpu/drm/sun4i/sun50i_planes.c | 201 ++++++++++++++++++
drivers/gpu/drm/sun4i/sun50i_planes.h | 41 ++++
drivers/gpu/drm/sun4i/sun8i_csc.c | 71 +++++++
drivers/gpu/drm/sun4i/sun8i_csc.h | 5 +
drivers/gpu/drm/sun4i/sun8i_mixer.c | 131 ++++++------
drivers/gpu/drm/sun4i/sun8i_mixer.h | 10 +-
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 40 +++-
11 files changed, 567 insertions(+), 84 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/allwinner,sun50i-h616-de33-planes.yaml
create mode 100644 drivers/gpu/drm/sun4i/sun50i_planes.c
create mode 100644 drivers/gpu/drm/sun4i/sun50i_planes.h
--
2.54.0
^ permalink raw reply
* [PATCH v3] dt-bindings: mfd: st,stmpe: fix PWM schema and drop legacy binding
From: Manish Baing @ 2026-05-09 19:39 UTC (permalink / raw)
To: lee, ukleinek, linusw, robh, krzk+dt, conor+dt
Cc: mcoquelin.stm32, alexandre.torgue, devicetree, linux-stm32,
linux-arm-kernel, linux-kernel, linux-pwm, manishbaing2789
The st,stmpe-pwm binding is already covered by the MFD schema in
Documentation/devicetree/bindings/mfd/st,stmpe.yaml. However, the
PWM subnode was missing a 'required' properties block. This allowed
Device Tree nodes to pass validation even if the 'compatible'
string was omitted. This omission could lead to probe failures
at runtime.
Fix the schema by adding the missing 'required' block and
remove the obsolete and redundant text binding file.
Signed-off-by: Manish Baing <manishbaing2789@gmail.com>
---
Changes in v3:
- Added 'required' properties to the pwm subnode in st,stmpe.yaml
to close a validation gap identified by the Sashiko.
- Updated commit message and description to reflect MFD subsystem changes.
Changes in v2:
- Droppped the TXT file instead of converting to YAML, as the
functionality is already covered by st,stmpe.yaml.
.../devicetree/bindings/mfd/st,stmpe.yaml | 4 ++++
.../devicetree/bindings/pwm/st,stmpe-pwm.txt | 18 ------------------
2 files changed, 4 insertions(+), 18 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
diff --git a/Documentation/devicetree/bindings/mfd/st,stmpe.yaml b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
index df43878fbe18..4bb05d544901 100644
--- a/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stmpe.yaml
@@ -127,6 +127,10 @@ properties:
"#pwm-cells":
const: 2
+ required:
+ - compatible
+ - "#pwm-cells"
+
touchscreen:
type: object
$ref: /schemas/input/touchscreen/touchscreen.yaml#
diff --git a/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt b/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
deleted file mode 100644
index f401316e0248..000000000000
--- a/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-== ST STMPE PWM controller ==
-
-This is a PWM block embedded in the ST Microelectronics STMPE
-(ST Multi-Purpose Expander) chips. The PWM is registered as a
-subdevices of the STMPE MFD device.
-
-Required properties:
-- compatible: should be:
- - "st,stmpe-pwm"
-- #pwm-cells: should be 2. See pwm.yaml in this directory for a description of
- the cells format.
-
-Example:
-
-pwm0: pwm {
- compatible = "st,stmpe-pwm";
- #pwm-cells = <2>;
-};
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/8] clk: sunxi-ng: de2: Fix Display Engine 3.3 definitions
From: Jernej Skrabec @ 2026-05-09 19:00 UTC (permalink / raw)
To: wens, samuel
Cc: mripard, maarten.lankhorst, tzimmermann, airlied, simona, robh,
krzk+dt, conor+dt, mturquette, sboyd, dri-devel, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-clk,
jernej.skrabec
In-Reply-To: <20260509190015.79086-1-jernej.skrabec@siol.net>
From: Jernej Skrabec <jernej.skrabec@gmail.com>
Positions of clocks and resets changed when version 3.3 was introduced.
However, old positions still work, just by luck.
Fix Display Engine 3.3 resets and clocks according vendor driver.
Fixes: be0e9a372787 ("clk: sunxi-ng: ccu: add Display Engine 3.3 (DE33) support")
Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com>
---
Changes from v1:
- new patch
drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 39 +++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index a6cd0f988859..6ec6c0dc4c26 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -36,6 +36,13 @@ static SUNXI_CCU_GATE(wb_clk, "wb", "wb-div",
static SUNXI_CCU_GATE(rot_clk, "rot", "rot-div",
0x00, BIT(3), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer0_h616_clk, "mixer0", "de",
+ 0x04, BIT(0), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(mixer1_h616_clk, "mixer1", "de",
+ 0x04, BIT(1), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(wb_h616_clk, "wb", "de",
+ 0x04, BIT(4), CLK_SET_RATE_PARENT);
+
static SUNXI_CCU_M(mixer0_div_clk, "mixer0-div", "de", 0x0c, 0, 4,
CLK_SET_RATE_PARENT);
static SUNXI_CCU_M(mixer1_div_clk, "mixer1-div", "de", 0x0c, 4, 4,
@@ -54,6 +61,9 @@ static SUNXI_CCU_M(wb_div_a83_clk, "wb-div", "pll-de", 0x0c, 8, 4,
static SUNXI_CCU_M(rot_div_a83_clk, "rot-div", "pll-de", 0x0c, 0x0c, 4,
CLK_SET_RATE_PARENT);
+static SUNXI_CCU_GATE(bus_mixer0_h616_clk, "bus-mixer0", "bus-de",
+ 0x08, BIT(0), 0);
+
static struct ccu_common *sun8i_de2_ccu_clks[] = {
&mixer0_clk.common,
&mixer1_clk.common,
@@ -74,6 +84,12 @@ static struct ccu_common *sun8i_de2_ccu_clks[] = {
&mixer1_div_a83_clk.common,
&wb_div_a83_clk.common,
&rot_div_a83_clk.common,
+
+ &mixer0_h616_clk.common,
+ &mixer1_h616_clk.common,
+ &wb_h616_clk.common,
+
+ &bus_mixer0_h616_clk.common
};
static struct clk_hw_onecell_data sun8i_a83t_de2_hw_clks = {
@@ -147,6 +163,17 @@ static struct clk_hw_onecell_data sun50i_a64_de2_hw_clks = {
.num = CLK_NUMBER_WITH_ROT,
};
+static struct clk_hw_onecell_data sun50i_h616_de33_hw_clks = {
+ .hws = {
+ [CLK_MIXER0] = &mixer0_h616_clk.common.hw,
+ [CLK_MIXER1] = &mixer1_h616_clk.common.hw,
+ [CLK_WB] = &wb_h616_clk.common.hw,
+
+ [CLK_BUS_MIXER0] = &bus_mixer0_h616_clk.common.hw,
+ },
+ .num = CLK_NUMBER_WITHOUT_ROT,
+};
+
static const struct ccu_reset_map sun8i_a83t_de2_resets[] = {
[RST_MIXER0] = { 0x08, BIT(0) },
/*
@@ -180,6 +207,12 @@ static const struct ccu_reset_map sun50i_h5_de2_resets[] = {
[RST_WB] = { 0x08, BIT(2) },
};
+static const struct ccu_reset_map sun50i_h616_de33_resets[] = {
+ [RST_MIXER0] = { 0x00, BIT(0) },
+ [RST_MIXER1] = { 0x00, BIT(1) },
+ [RST_WB] = { 0x00, BIT(4) },
+};
+
static const struct sunxi_ccu_desc sun8i_a83t_de2_clk_desc = {
.ccu_clks = sun8i_de2_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks),
@@ -244,10 +277,10 @@ static const struct sunxi_ccu_desc sun50i_h616_de33_clk_desc = {
.ccu_clks = sun8i_de2_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun8i_de2_ccu_clks),
- .hw_clks = &sun8i_h3_de2_hw_clks,
+ .hw_clks = &sun50i_h616_de33_hw_clks,
- .resets = sun50i_h5_de2_resets,
- .num_resets = ARRAY_SIZE(sun50i_h5_de2_resets),
+ .resets = sun50i_h616_de33_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_de33_resets),
};
static int sunxi_de2_clk_probe(struct platform_device *pdev)
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2] dt-bindings: iio: adc: Convert xilinx-xadc bindings to YAML schema
From: Rob Herring (Arm) @ 2026-05-09 19:24 UTC (permalink / raw)
To: Pramod Maurya
Cc: Andy Shevchenko, David Lechner, devicetree, Krzysztof Kozlowski,
Conor Dooley, linux-iio, linux-kernel, linux-arm-kernel, jic23,
Lars-Peter Clausen, Nuno Sá, Michal Simek
In-Reply-To: <20260509180719.53704-1-pramod.nexgen@gmail.com>
On Sat, 09 May 2026 14:07:14 -0400, Pramod Maurya wrote:
> Convert the Xilinx XADC and UltraScale System Monitor device tree binding
> from the legacy plain-text format to a YAML schema, enabling automated
> validation with dt-schema.
>
> The new binding covers the same hardware and compatible strings:
> - xlnx,zynq-xadc-1.00.a (ZYNQ hardmacro)
> - xlnx,axi-xadc-1.00.a (AXI softmacro)
> - xlnx,system-management-wiz-1.3 (UltraScale System Management Wizard)
>
> Signed-off-by: Pramod Maurya <pramod.nexgen@gmail.com>
> ---
> Changes in v2:
> - Fix patternProperties regex to use lowercase hex unit addresses
> (channel@a through channel@f) instead of decimal; correct range
> is now "^channel@([0-9a-f]|10)$"
> - Add allOf/if/then conditional to enforce xlnx,external-mux-channel
> is required when xlnx,external-mux is "single" or "dual"
>
> .../bindings/iio/adc/xilinx-xadc.txt | 141 ------------
> .../bindings/iio/adc/xlnx,xadc.yaml | 204 ++++++++++++++++++
> MAINTAINERS | 7 +
> 3 files changed, 211 insertions(+), 141 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/iio/adc/xilinx-xadc.txt
> create mode 100644 Documentation/devicetree/bindings/iio/adc/xlnx,xadc.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/iio/adc/xlnx,xadc.yaml: properties:xlnx,channels:type: 'boolean' was expected
hint: A vendor boolean property can use "type: boolean"
from schema $id: http://devicetree.org/meta-schemas/vendor-props.yaml
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/20260509180719.53704-1-pramod.nexgen@gmail.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply
* [net-next v8 2/3] net: ethernet: mtk_eth_soc: Add RSS support
From: Frank Wunderlich @ 2026-05-09 19:09 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, Russell King
Cc: Frank Wunderlich, netdev, linux-kernel, linux-arm-kernel,
linux-mediatek, Mason Chang, Daniel Golle
In-Reply-To: <20260509190938.169290-1-linux@fw-web.de>
From: Mason Chang <mason-cw.chang@mediatek.com>
Add support for Receive Side Scaling.
We can adjust SMP affinity with the following command:
echo [CPU bitmap num] > /proc/irq/[virtual IRQ ID]/smp_affinity,
with interrupts evenly assigned to 4 CPUs, we were able to measure
an RX throughput of 7.3Gbps using iperf3 on the MT7988. Further
optimizations will be carried out in the future.
The experimental command is as follows:
PC: iperf3 -c [IP] -P 10
DUT: iperf3 -s
The entire indirection table can be imagined as 128 buckets, we
can use the ethtool command to mark which RX ring we want to send
the packets in these buckets to.
Show RSS RX ring parameters in indirection table and RSS hash key:
ethtool -x [interface]
Change RSS RX rings weight under uniform distribution:
ethtool --set-rxfh-indir [interface] equal [ring num]
Change RSS RX rings weight under non-uniform distribution:
ethtool --set-rxfh-indir [interface] weight [ring0 weight]
[ring1 weight] [ring2 weight] [ring3 weight]
Signed-off-by: Mason Chang <mason-cw.chang@mediatek.com>
Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
---
v6:
- e33bd8dd7f1f ("net: mediatek: convert to use .get_rx_ring_count") moved
ETHTOOL_GRXRINGS handling from mtk_get_rxnfc to mtk_get_rx_ring_count
move changes to this new function too
- fix some Macro argument '...' may be better as '(...)' to avoid precedence issues
v5:
- fix too long line reported by checkpatch
MTK_RSS_HASH_KEY_DW
MTK_RSS_INDR_TABLE_DW
MTK_LRO_CTRL_DW[123]_CFG
v4:
- drop unrelated file
- rss-changes suggested by andrew
- fix MTK_HW_LRO_RING_NUM macro (add eth)
- fix MTK_LRO_CTRL_DW[123]_CFG (add reg_map param)
- fix MTK_RX_DONE_INT (add eth param)
v3:
- changes requested by jakub
- readded rss fix for mt7986
- name all PDMA-IRQ the same way
v2:
- drop wrong change (MTK_CDMP_IG_CTRL is only netsys v1)
- Fix immutable string IRQ setup (thx to Emilia Schotte)
- drop link to no more existent 6.6 patch in comment
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 544 +++++++++++++++-----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 98 +++-
2 files changed, 496 insertions(+), 146 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index d25e0b96c26e..908fd88287ac 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1297,6 +1297,7 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd,
if (mtk_is_netsys_v3_or_greater(eth)) {
rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
+ rxd->rxd7 = READ_ONCE(dma_rxd->rxd7);
}
return true;
@@ -1864,47 +1865,9 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
-static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
+static void mtk_update_rx_cpu_idx(struct mtk_eth *eth, struct mtk_rx_ring *ring)
{
- int i;
- struct mtk_rx_ring *ring;
- int idx;
-
- if (!eth->hwlro)
- return ð->rx_ring[0];
-
- for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
- struct mtk_rx_dma *rxd;
-
- ring = ð->rx_ring[i];
- idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
- rxd = ring->dma + idx * eth->soc->rx.desc_size;
- if (rxd->rxd2 & RX_DMA_DONE) {
- ring->calc_idx_update = true;
- return ring;
- }
- }
-
- return NULL;
-}
-
-static void mtk_update_rx_cpu_idx(struct mtk_eth *eth)
-{
- struct mtk_rx_ring *ring;
- int i;
-
- if (!eth->hwlro) {
- ring = ð->rx_ring[0];
- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
- } else {
- for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) {
- ring = ð->rx_ring[i];
- if (ring->calc_idx_update) {
- ring->calc_idx_update = false;
- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
- }
- }
- }
+ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg);
}
static bool mtk_page_pool_enabled(struct mtk_eth *eth)
@@ -1935,7 +1898,7 @@ static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth,
return pp;
err = __xdp_rxq_info_reg(xdp_q, eth->dummy_dev, id,
- eth->rx_napi.napi_id, PAGE_SIZE);
+ eth->rx_napi[id].napi.napi_id, PAGE_SIZE);
if (err < 0)
goto err_free_pp;
@@ -2224,7 +2187,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
struct mtk_eth *eth)
{
struct dim_sample dim_sample = {};
- struct mtk_rx_ring *ring;
+ struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi);
+ struct mtk_rx_ring *ring = rx_napi->rx_ring;
bool xdp_flush = false;
int idx;
struct sk_buff *skb;
@@ -2235,16 +2199,15 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
dma_addr_t dma_addr = DMA_MAPPING_ERROR;
int ppe_idx = 0;
+ if (unlikely(!ring))
+ goto rx_done;
+
while (done < budget) {
unsigned int pktlen, *rxdcsum;
struct net_device *netdev;
u32 hash, reason;
int mac = 0;
- ring = mtk_get_rx_ring(eth);
- if (unlikely(!ring))
- goto rx_done;
-
idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
rxd = ring->dma + idx * eth->soc->rx.desc_size;
data = ring->data[idx];
@@ -2436,7 +2399,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
* we continue
*/
wmb();
- mtk_update_rx_cpu_idx(eth);
+ mtk_update_rx_cpu_idx(eth, ring);
}
eth->rx_packets += done;
@@ -2645,7 +2608,9 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget)
static int mtk_napi_rx(struct napi_struct *napi, int budget)
{
- struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi);
+ struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi);
+ struct mtk_eth *eth = rx_napi->eth;
+ struct mtk_rx_ring *ring = rx_napi->rx_ring;
const struct mtk_reg_map *reg_map = eth->soc->reg_map;
int rx_done_total = 0;
@@ -2654,7 +2619,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget)
do {
int rx_done;
- mtk_w32(eth, eth->soc->rx.irq_done_mask,
+ mtk_w32(eth, MTK_RX_DONE_INT(eth, ring->ring_no),
reg_map->pdma.irq_status);
rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth);
rx_done_total += rx_done;
@@ -2670,10 +2635,10 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget)
return budget;
} while (mtk_r32(eth, reg_map->pdma.irq_status) &
- eth->soc->rx.irq_done_mask);
+ MTK_RX_DONE_INT(eth, ring->ring_no));
if (napi_complete_done(napi, rx_done_total))
- mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask);
+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(eth, ring->ring_no));
return rx_done_total;
}
@@ -2918,6 +2883,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
else
ring->crx_idx_reg = reg_map->pdma.pcrx_ptr +
ring_no * MTK_QRX_OFFSET;
+ ring->ring_no = ring_no;
/* make sure that all changes to the dma ring are flushed before we
* continue
*/
@@ -2986,6 +2952,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_
static int mtk_hwlro_rx_init(struct mtk_eth *eth)
{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
int i;
u32 ring_ctrl_dw1 = 0, ring_ctrl_dw2 = 0, ring_ctrl_dw3 = 0;
u32 lro_ctrl_dw0 = 0, lro_ctrl_dw3 = 0;
@@ -3008,9 +2975,9 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
ring_ctrl_dw3 |= MTK_RING_MAX_AGG_CNT_H;
for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
- mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(i));
- mtk_w32(eth, ring_ctrl_dw2, MTK_LRO_CTRL_DW2_CFG(i));
- mtk_w32(eth, ring_ctrl_dw3, MTK_LRO_CTRL_DW3_CFG(i));
+ mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(reg_map, i));
+ mtk_w32(eth, ring_ctrl_dw2, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
+ mtk_w32(eth, ring_ctrl_dw3, MTK_LRO_CTRL_DW3_CFG(reg_map, i));
}
/* IPv4 checksum update enable */
@@ -3046,6 +3013,7 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
int i;
u32 val;
@@ -3064,7 +3032,7 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
/* invalidate lro rings */
for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
- mtk_w32(eth, 0, MTK_LRO_CTRL_DW2_CFG(i));
+ mtk_w32(eth, 0, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
/* disable HW LRO */
mtk_w32(eth, 0, MTK_PDMA_LRO_CTRL_DW0);
@@ -3072,27 +3040,29 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip)
{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
u32 reg_val;
- reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
+ reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
/* invalidate the IP setting */
- mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+ mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
mtk_w32(eth, ip, MTK_LRO_DIP_DW0_CFG(idx));
/* validate the IP setting */
- mtk_w32(eth, (reg_val | MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+ mtk_w32(eth, (reg_val | MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
}
static void mtk_hwlro_inval_ipaddr(struct mtk_eth *eth, int idx)
{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
u32 reg_val;
- reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx));
+ reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
/* invalidate the IP setting */
- mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(idx));
+ mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
mtk_w32(eth, 0, MTK_LRO_DIP_DW0_CFG(idx));
}
@@ -3222,6 +3192,105 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev,
return 0;
}
+static u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index)
+{
+ u32 val = 0;
+ int i;
+
+ for (i = 16 * index; i < 16 * index + 16; i++)
+ val |= (rss_params->indirection_table[i] << (2 * (i % 16)));
+
+ return val;
+}
+
+static int mtk_rss_init(struct mtk_eth *eth)
+{
+ const struct mtk_soc_data *soc = eth->soc;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ u32 val;
+ int i;
+
+ netdev_rss_key_fill(rss_params->hash_key, MTK_RSS_HASH_KEYSIZE);
+
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rss_params->indirection_table[i] = ethtool_rxfh_indir_default(i, eth->soc->rss_num);
+
+ if (soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
+ /* Set RSS rings to PSE modes */
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++) {
+ val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
+ val |= MTK_RING_PSE_MODE;
+ mtk_w32(eth, val, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
+ }
+
+ /* Enable non-lro multiple rx */
+ val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0);
+ val |= MTK_NON_LRO_MULTI_EN;
+ mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
+
+ /* Enable RSS dly int supoort */
+ val |= MTK_LRO_DLY_INT_EN;
+ mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0);
+ }
+
+ /* Hash Type */
+ val = mtk_r32(eth, reg_map->pdma.rss_glo_cfg);
+ val |= MTK_RSS_IPV4_STATIC_HASH;
+ val |= MTK_RSS_IPV6_STATIC_HASH;
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Hash Key */
+ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
+ mtk_w32(eth, rss_params->hash_key[i], MTK_RSS_HASH_KEY_DW(reg_map, i));
+
+ /* Select the size of indirection table */
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
+ mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
+ MTK_RSS_INDR_TABLE_DW(reg_map, i));
+
+ /* Pause */
+ val |= MTK_RSS_CFG_REQ;
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Enable RSS */
+ val |= MTK_RSS_EN;
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Release pause */
+ val &= ~(MTK_RSS_CFG_REQ);
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Set perRSS GRP INT */
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)),
+ MTK_RX_DONE_INT(eth, MTK_RSS_RING(1)), reg_map->pdma.int_grp);
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(2)),
+ MTK_RX_DONE_INT(eth, MTK_RSS_RING(2)), reg_map->pdma.int_grp + 0x4);
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(3)),
+ MTK_RX_DONE_INT(eth, MTK_RSS_RING(3)), reg_map->pdma.int_grp3);
+
+ return 0;
+}
+
+static void mtk_rss_uninit(struct mtk_eth *eth)
+{
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ u32 val;
+
+ /* Pause */
+ val = mtk_r32(eth, reg_map->pdma.rss_glo_cfg);
+ val |= MTK_RSS_CFG_REQ;
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Disable RSS */
+ val &= ~(MTK_RSS_EN);
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+
+ /* Release pause */
+ val &= ~(MTK_RSS_CFG_REQ);
+ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg);
+}
+
static netdev_features_t mtk_fix_features(struct net_device *dev,
netdev_features_t features)
{
@@ -3312,6 +3381,17 @@ static int mtk_dma_init(struct mtk_eth *eth)
return err;
}
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
+ err = mtk_rx_alloc(eth, MTK_RSS_RING(i), MTK_RX_FLAGS_NORMAL);
+ if (err)
+ return err;
+ }
+ err = mtk_rss_init(eth);
+ if (err)
+ return err;
+ }
+
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) {
/* Enable random early drop and set drop threshold
* automatically
@@ -3358,6 +3438,12 @@ static void mtk_dma_free(struct mtk_eth *eth)
mtk_rx_clean(eth, ð->rx_ring[i], false);
}
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ mtk_rss_uninit(eth);
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++)
+ mtk_rx_clean(eth, ð->rx_ring[MTK_RSS_RING(i)], true);
+ }
+
for (i = 0; i < DIV_ROUND_UP(soc->tx.fq_dma_size, MTK_FQ_DMA_LENGTH); i++) {
kfree(eth->scratch_head[i]);
eth->scratch_head[i] = NULL;
@@ -3390,23 +3476,23 @@ static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue)
schedule_work(ð->pending_work);
}
-static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)
+static int mtk_get_irqs_fe(struct platform_device *pdev, struct mtk_eth *eth)
{
int i;
/* future SoCs beginning with MT7988 should use named IRQs in dts */
- eth->irq[MTK_FE_IRQ_TX] = platform_get_irq_byname_optional(pdev, "fe1");
- eth->irq[MTK_FE_IRQ_RX] = platform_get_irq_byname_optional(pdev, "fe2");
- if (eth->irq[MTK_FE_IRQ_TX] >= 0 && eth->irq[MTK_FE_IRQ_RX] >= 0)
+ eth->irq_fe[MTK_FE_IRQ_TX] = platform_get_irq_byname_optional(pdev, "fe1");
+ eth->irq_fe[MTK_FE_IRQ_RX] = platform_get_irq_byname_optional(pdev, "fe2");
+ if (eth->irq_fe[MTK_FE_IRQ_TX] >= 0 && eth->irq_fe[MTK_FE_IRQ_RX] >= 0)
return 0;
/* only use legacy mode if platform_get_irq_byname_optional returned -ENXIO */
- if (eth->irq[MTK_FE_IRQ_TX] != -ENXIO)
- return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_TX],
+ if (eth->irq_fe[MTK_FE_IRQ_TX] != -ENXIO)
+ return dev_err_probe(&pdev->dev, eth->irq_fe[MTK_FE_IRQ_TX],
"Error requesting FE TX IRQ\n");
- if (eth->irq[MTK_FE_IRQ_RX] != -ENXIO)
- return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_RX],
+ if (eth->irq_fe[MTK_FE_IRQ_RX] != -ENXIO)
+ return dev_err_probe(&pdev->dev, eth->irq_fe[MTK_FE_IRQ_RX],
"Error requesting FE RX IRQ\n");
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT))
@@ -3421,14 +3507,14 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)
for (i = 0; i < MTK_FE_IRQ_NUM; i++) {
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
if (i == MTK_FE_IRQ_SHARED)
- eth->irq[MTK_FE_IRQ_SHARED] = platform_get_irq(pdev, i);
+ eth->irq_fe[MTK_FE_IRQ_SHARED] = platform_get_irq(pdev, i);
else
- eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED];
+ eth->irq_fe[i] = eth->irq_fe[MTK_FE_IRQ_SHARED];
} else {
- eth->irq[i] = platform_get_irq(pdev, i + 1);
+ eth->irq_fe[i] = platform_get_irq(pdev, i + 1);
}
- if (eth->irq[i] < 0) {
+ if (eth->irq_fe[i] < 0) {
dev_err(&pdev->dev, "no IRQ%d resource found\n", i);
return -ENXIO;
}
@@ -3437,14 +3523,36 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)
return 0;
}
-static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
+static int mtk_get_irqs_pdma(struct platform_device *pdev, struct mtk_eth *eth)
{
- struct mtk_eth *eth = _eth;
+ char rxring[] = "pdma0";
+ int i;
+
+ for (i = 0; i < MTK_PDMA_IRQ_NUM; i++) {
+ rxring[4] = '0' + i;
+ eth->irq_pdma[i] = platform_get_irq_byname(pdev, rxring);
+ if (eth->irq_pdma[i] < 0)
+ return eth->irq_pdma[i];
+ }
+
+ return 0;
+}
+
+static irqreturn_t mtk_handle_irq_rx(int irq, void *priv)
+{
+ struct mtk_napi *rx_napi = priv;
+ struct mtk_eth *eth = rx_napi->eth;
+ struct mtk_rx_ring *ring = rx_napi->rx_ring;
eth->rx_events++;
- if (likely(napi_schedule_prep(ð->rx_napi))) {
- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
- __napi_schedule(ð->rx_napi);
+ if (unlikely(!(mtk_r32(eth, eth->soc->reg_map->pdma.irq_status) &
+ mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask) &
+ MTK_RX_DONE_INT(eth, ring->ring_no))))
+ return IRQ_NONE;
+
+ if (likely(napi_schedule_prep(&rx_napi->napi))) {
+ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, ring->ring_no));
+ __napi_schedule(&rx_napi->napi);
}
return IRQ_HANDLED;
@@ -3469,10 +3577,10 @@ static irqreturn_t mtk_handle_irq(int irq, void *_eth)
const struct mtk_reg_map *reg_map = eth->soc->reg_map;
if (mtk_r32(eth, reg_map->pdma.irq_mask) &
- eth->soc->rx.irq_done_mask) {
+ MTK_RX_DONE_INT(eth, 0)) {
if (mtk_r32(eth, reg_map->pdma.irq_status) &
- eth->soc->rx.irq_done_mask)
- mtk_handle_irq_rx(irq, _eth);
+ MTK_RX_DONE_INT(eth, 0))
+ mtk_handle_irq_rx(irq, ð->rx_napi[0]);
}
if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) {
if (mtk_r32(eth, reg_map->tx_irq_status) & MTK_TX_DONE_INT)
@@ -3489,10 +3597,10 @@ static void mtk_poll_controller(struct net_device *dev)
struct mtk_eth *eth = mac->hw;
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
- mtk_handle_irq_rx(eth->irq[MTK_FE_IRQ_RX], dev);
+ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, 0));
+ mtk_handle_irq_rx(eth->irq_fe[MTK_FE_IRQ_RX], ð->rx_napi[0]);
mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
- mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask);
+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(eth, 0));
}
#endif
@@ -3679,9 +3787,17 @@ static int mtk_open(struct net_device *dev)
mtk_ppe_update_mtu(eth->ppe[i], mtu);
napi_enable(ð->tx_napi);
- napi_enable(ð->rx_napi);
+ napi_enable(ð->rx_napi[0].napi);
mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
- mtk_rx_irq_enable(eth, soc->rx.irq_done_mask);
+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(eth, 0));
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
+ napi_enable(ð->rx_napi[MTK_RSS_RING(i)].napi);
+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(i)));
+ }
+ }
+
refcount_set(ð->dma_refcnt, 1);
} else {
refcount_inc(ð->dma_refcnt);
@@ -3766,9 +3882,16 @@ static int mtk_stop(struct net_device *dev)
mtk_gdm_config(eth, i, MTK_GDMA_DROP_ALL);
mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
+ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, 0));
napi_disable(ð->tx_napi);
- napi_disable(ð->rx_napi);
+ napi_disable(ð->rx_napi[0].napi);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
+ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, MTK_RSS_RING(i)));
+ napi_disable(ð->rx_napi[MTK_RSS_RING(i)].napi);
+ }
+ }
cancel_work_sync(ð->rx_dim.work);
cancel_work_sync(ð->tx_dim.work);
@@ -3888,9 +4011,7 @@ static void mtk_dim_rx(struct work_struct *work)
dim->profile_ix);
spin_lock_bh(ð->dim_lock);
- val = mtk_r32(eth, reg_map->pdma.delay_irq);
- val &= MTK_PDMA_DELAY_TX_MASK;
- val |= MTK_PDMA_DELAY_RX_EN;
+ val = MTK_PDMA_DELAY_RX_EN;
cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK);
val |= cur << MTK_PDMA_DELAY_RX_PTIME_SHIFT;
@@ -3898,9 +4019,19 @@ static void mtk_dim_rx(struct work_struct *work)
cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK);
val |= cur << MTK_PDMA_DELAY_RX_PINT_SHIFT;
- mtk_w32(eth, val, reg_map->pdma.delay_irq);
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
- mtk_w32(eth, val, reg_map->qdma.delay_irq);
+ mtk_m32(eth, MTK_PDMA_DELAY_TX_MASK,
+ val << MTK_PDMA_DELAY_TX_PTIME_SHIFT, reg_map->qdma.delay_irq);
+
+ if (eth->soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
+ mtk_m32(eth, MTK_PDMA_DELAY_RX_MASK, val, reg_map->pdma.delay_irq);
+ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int);
+ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x4);
+ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x8);
+ } else {
+ val = val | (val << MTK_PDMA_DELAY_RX_RING_SHIFT);
+ mtk_w32(eth, val, reg_map->pdma.rx_delay_irq);
+ }
spin_unlock_bh(ð->dim_lock);
@@ -3919,9 +4050,7 @@ static void mtk_dim_tx(struct work_struct *work)
dim->profile_ix);
spin_lock_bh(ð->dim_lock);
- val = mtk_r32(eth, reg_map->pdma.delay_irq);
- val &= MTK_PDMA_DELAY_RX_MASK;
- val |= MTK_PDMA_DELAY_TX_EN;
+ val = MTK_PDMA_DELAY_TX_EN;
cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK);
val |= cur << MTK_PDMA_DELAY_TX_PTIME_SHIFT;
@@ -3929,9 +4058,16 @@ static void mtk_dim_tx(struct work_struct *work)
cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK);
val |= cur << MTK_PDMA_DELAY_TX_PINT_SHIFT;
- mtk_w32(eth, val, reg_map->pdma.delay_irq);
if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
- mtk_w32(eth, val, reg_map->qdma.delay_irq);
+ mtk_m32(eth, MTK_PDMA_DELAY_RX_MASK,
+ val >> MTK_PDMA_DELAY_TX_PTIME_SHIFT, reg_map->qdma.delay_irq);
+
+ if (eth->soc->rx.desc_size == sizeof(struct mtk_rx_dma)) {
+ mtk_m32(eth, MTK_PDMA_DELAY_TX_MASK, val, reg_map->pdma.delay_irq);
+ } else {
+ mtk_w32(eth, val >> MTK_PDMA_DELAY_TX_PTIME_SHIFT,
+ reg_map->pdma.tx_delay_irq);
+ }
spin_unlock_bh(ð->dim_lock);
@@ -4149,6 +4285,25 @@ static void mtk_hw_reset_monitor_work(struct work_struct *work)
MTK_DMA_MONITOR_TIMEOUT);
}
+static int mtk_napi_init(struct mtk_eth *eth)
+{
+ struct mtk_napi *rx_napi = ð->rx_napi[0];
+ int i;
+
+ rx_napi->eth = eth;
+ rx_napi->rx_ring = ð->rx_ring[0];
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
+ rx_napi = ð->rx_napi[MTK_RSS_RING(i)];
+ rx_napi->eth = eth;
+ rx_napi->rx_ring = ð->rx_ring[MTK_RSS_RING(i)];
+ }
+ }
+
+ return 0;
+}
+
static int mtk_hw_init(struct mtk_eth *eth, bool reset)
{
u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA |
@@ -4238,12 +4393,11 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
*/
val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
- if (mtk_is_netsys_v1(eth)) {
- val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
- mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+ val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
+ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
+ if (mtk_is_netsys_v1(eth))
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
- }
/* set interrupt delays based on current Net DIM sample */
mtk_dim_rx(ð->rx_dim.work);
@@ -4254,11 +4408,17 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
mtk_rx_irq_disable(eth, ~0);
/* FE int grouping */
- mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp);
- mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4);
+
mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp);
- mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4);
- mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
+ mtk_w32(eth, MTK_RX_DONE_INT(eth, 0), reg_map->qdma.int_grp + 4);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+ mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP);
+ } else {
+ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp);
+ mtk_w32(eth, MTK_RX_DONE_INT(eth, 0), reg_map->pdma.int_grp + 4);
+ mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
+ }
if (mtk_is_netsys_v3_or_greater(eth)) {
/* PSE dummy page mechanism */
@@ -4700,8 +4860,13 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
static u32 mtk_get_rx_ring_count(struct net_device *dev)
{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+
if (dev->hw_features & NETIF_F_LRO)
return MTK_MAX_RX_RING_NUM;
+ else if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS))
+ return MTK_RX_RSS_NUM(eth);
return 0;
}
@@ -4784,6 +4949,70 @@ static int mtk_set_eee(struct net_device *dev, struct ethtool_keee *eee)
return phylink_ethtool_set_eee(mac->phylink, eee);
}
+static u32 mtk_get_rxfh_key_size(struct net_device *dev)
+{
+ return MTK_RSS_HASH_KEYSIZE;
+}
+
+static u32 mtk_get_rxfh_indir_size(struct net_device *dev)
+{
+ return MTK_RSS_MAX_INDIRECTION_TABLE;
+}
+
+static int mtk_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ int i;
+
+ rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
+
+ if (rxfh->key) {
+ memcpy(rxfh->key, rss_params->hash_key,
+ sizeof(rss_params->hash_key));
+ }
+
+ if (rxfh->indir) {
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rxfh->indir[i] = rss_params->indirection_table[i];
+ }
+
+ return 0;
+}
+
+static int mtk_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_rss_params *rss_params = ð->rss_params;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ int i;
+
+ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+ rxfh->hfunc != ETH_RSS_HASH_TOP)
+ return -EOPNOTSUPP;
+
+ if (rxfh->key) {
+ memcpy(rss_params->hash_key, rxfh->key,
+ sizeof(rss_params->hash_key));
+ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++)
+ mtk_w32(eth, rss_params->hash_key[i],
+ MTK_RSS_HASH_KEY_DW(reg_map, i));
+ }
+
+ if (rxfh->indir) {
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++)
+ rss_params->indirection_table[i] = rxfh->indir[i];
+ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++)
+ mtk_w32(eth, mtk_rss_indr_table(rss_params, i),
+ MTK_RSS_INDR_TABLE_DW(reg_map, i));
+ }
+
+ return 0;
+}
+
static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev)
{
@@ -4819,6 +5048,10 @@ static const struct ethtool_ops mtk_ethtool_ops = {
.get_rx_ring_count = mtk_get_rx_ring_count,
.get_eee = mtk_get_eee,
.set_eee = mtk_set_eee,
+ .get_rxfh_key_size = mtk_get_rxfh_key_size,
+ .get_rxfh_indir_size = mtk_get_rxfh_indir_size,
+ .get_rxfh = mtk_get_rxfh,
+ .set_rxfh = mtk_set_rxfh,
};
static const struct net_device_ops mtk_netdev_ops = {
@@ -5012,7 +5245,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
eth->netdev[id]->features |= eth->soc->hw_features;
eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops;
- eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED];
+ eth->netdev[id]->irq = eth->irq_fe[MTK_FE_IRQ_SHARED];
eth->netdev[id]->dev.of_node = np;
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
@@ -5120,6 +5353,7 @@ static int mtk_probe(struct platform_device *pdev)
struct resource *res = NULL;
struct device_node *mac_np;
struct mtk_eth *eth;
+ char *irqname;
int err, i;
eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL);
@@ -5251,10 +5485,16 @@ static int mtk_probe(struct platform_device *pdev)
}
}
- err = mtk_get_irqs(pdev, eth);
+ err = mtk_get_irqs_fe(pdev, eth);
if (err)
goto err_wed_exit;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+ err = mtk_get_irqs_pdma(pdev, eth);
+ if (err)
+ goto err_wed_exit;
+ }
+
for (i = 0; i < ARRAY_SIZE(eth->clks); i++) {
eth->clks[i] = devm_clk_get(eth->dev,
mtk_clks_source_name[i]);
@@ -5297,23 +5537,56 @@ static int mtk_probe(struct platform_device *pdev)
}
}
+ err = mtk_napi_init(eth);
+ if (err)
+ goto err_free_dev;
+
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) {
- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_SHARED],
+ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_SHARED],
mtk_handle_irq, 0,
dev_name(eth->dev), eth);
} else {
- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_TX],
+ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s TX",
+ dev_name(eth->dev));
+ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_TX],
mtk_handle_irq_tx, 0,
- dev_name(eth->dev), eth);
+ irqname, eth);
if (err)
goto err_free_dev;
- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_RX],
- mtk_handle_irq_rx, 0,
- dev_name(eth->dev), eth);
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) {
+ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s PDMA RX %d",
+ dev_name(eth->dev), 0);
+ err = devm_request_irq(eth->dev, eth->irq_pdma[0],
+ mtk_handle_irq_rx, IRQF_SHARED,
+ irqname, ð->rx_napi[0]);
+ if (err)
+ goto err_free_dev;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++) {
+ irqname = devm_kasprintf(eth->dev, GFP_KERNEL,
+ "%s PDMA RX %d",
+ dev_name(eth->dev), i);
+ err = devm_request_irq(eth->dev,
+ eth->irq_pdma[MTK_RSS_RING(i)],
+ mtk_handle_irq_rx, IRQF_SHARED,
+ irqname,
+ ð->rx_napi[MTK_RSS_RING(i)]);
+ if (err)
+ goto err_free_dev;
+ }
+ }
+ } else {
+ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s RX",
+ dev_name(eth->dev));
+ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_RX],
+ mtk_handle_irq_rx, 0,
+ irqname, ð->rx_napi[0]);
+ if (err)
+ goto err_free_dev;
+ }
}
- if (err)
- goto err_free_dev;
/* No MT7628/88 support yet */
if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
@@ -5354,7 +5627,7 @@ static int mtk_probe(struct platform_device *pdev)
} else
netif_info(eth, probe, eth->netdev[i],
"mediatek frame engine at 0x%08lx, irq %d\n",
- eth->netdev[i]->base_addr, eth->irq[MTK_FE_IRQ_SHARED]);
+ eth->netdev[i]->base_addr, eth->irq_fe[MTK_FE_IRQ_SHARED]);
}
/* we run 2 devices on the same DMA ring so we need a dummy device
@@ -5367,7 +5640,13 @@ static int mtk_probe(struct platform_device *pdev)
goto err_unreg_netdev;
}
netif_napi_add(eth->dummy_dev, ð->tx_napi, mtk_napi_tx);
- netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx);
+ netif_napi_add(eth->dummy_dev, ð->rx_napi[0].napi, mtk_napi_rx);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++)
+ netif_napi_add(eth->dummy_dev, ð->rx_napi[MTK_RSS_RING(i)].napi,
+ mtk_napi_rx);
+ }
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
@@ -5411,7 +5690,12 @@ static void mtk_remove(struct platform_device *pdev)
mtk_hw_deinit(eth);
netif_napi_del(ð->tx_napi);
- netif_napi_del(ð->rx_napi);
+ netif_napi_del(ð->rx_napi[0].napi);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
+ for (i = 1; i < MTK_RX_RSS_NUM(eth); i++)
+ netif_napi_del(ð->rx_napi[MTK_RSS_RING(i)].napi);
+ }
mtk_cleanup(eth);
free_netdev(eth->dummy_dev);
mtk_mdio_cleanup(eth);
@@ -5424,6 +5708,7 @@ static const struct mtk_soc_data mt2701_data = {
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
.version = 1,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5433,7 +5718,6 @@ static const struct mtk_soc_data mt2701_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5452,6 +5736,7 @@ static const struct mtk_soc_data mt7621_data = {
.ppe_num = 1,
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5461,7 +5746,6 @@ static const struct mtk_soc_data mt7621_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5482,6 +5766,7 @@ static const struct mtk_soc_data mt7622_data = {
.hash_offset = 2,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5491,7 +5776,6 @@ static const struct mtk_soc_data mt7622_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5511,6 +5795,7 @@ static const struct mtk_soc_data mt7623_data = {
.hash_offset = 2,
.foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
.disable_pll_modes = true,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5520,7 +5805,6 @@ static const struct mtk_soc_data mt7623_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5537,6 +5821,7 @@ static const struct mtk_soc_data mt7629_data = {
.required_pctl = false,
.has_accounting = true,
.version = 1,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5546,7 +5831,6 @@ static const struct mtk_soc_data mt7629_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID,
.dma_size = MTK_DMA_SIZE(2K),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5567,16 +5851,16 @@ static const struct mtk_soc_data mt7981_data = {
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
+ .rss_num = 4,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
- .dma_size = MTK_DMA_SIZE(2K),
+ .dma_size = MTK_DMA_SIZE(4K),
.fq_dma_size = MTK_DMA_SIZE(2K),
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@@ -5597,6 +5881,7 @@ static const struct mtk_soc_data mt7986_data = {
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
+ .rss_num = 4,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
@@ -5606,7 +5891,6 @@ static const struct mtk_soc_data mt7986_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
@@ -5627,20 +5911,20 @@ static const struct mtk_soc_data mt7988_data = {
.hash_offset = 4,
.has_accounting = true,
.foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
+ .rss_num = 4,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma_v2),
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
- .dma_size = MTK_DMA_SIZE(2K),
+ .dma_size = MTK_DMA_SIZE(4K),
.fq_dma_size = MTK_DMA_SIZE(4K),
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma_v2),
- .irq_done_mask = MTK_RX_DONE_INT_V2,
.dma_l4_valid = RX_DMA_L4_VALID_V2,
.dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
.dma_len_offset = 8,
- .dma_size = MTK_DMA_SIZE(2K),
+ .dma_size = MTK_DMA_SIZE(1K),
},
};
@@ -5651,6 +5935,7 @@ static const struct mtk_soc_data rt5350_data = {
.required_clks = MT7628_CLKS_BITMAP,
.required_pctl = false,
.version = 1,
+ .rss_num = 0,
.tx = {
.desc_size = sizeof(struct mtk_tx_dma),
.dma_max_len = MTK_TX_DMA_BUF_LEN,
@@ -5659,7 +5944,6 @@ static const struct mtk_soc_data rt5350_data = {
},
.rx = {
.desc_size = sizeof(struct mtk_rx_dma),
- .irq_done_mask = MTK_RX_DONE_INT,
.dma_l4_valid = RX_DMA_L4_VALID_PDMA,
.dma_max_len = MTK_TX_DMA_BUF_LEN,
.dma_len_offset = 16,
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 334625814b97..378cf47913ef 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -76,6 +76,8 @@
#define MTK_HW_LRO_BW_THRE 3000
#define MTK_HW_LRO_REPLACE_DELTA 1000
#define MTK_HW_LRO_SDL_REMAIN_ROOM 1522
+#define MTK_RSS_HASH_KEYSIZE 40
+#define MTK_RSS_MAX_INDIRECTION_TABLE 128
/* Frame Engine Global Configuration */
#define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00)
@@ -97,6 +99,8 @@
#define MTK_GDM1_AF BIT(28)
#define MTK_GDM2_AF BIT(29)
+#define MTK_PDMA_IRQ_NUM (4)
+
/* PDMA HW LRO Alter Flow Timer Register */
#define MTK_PDMA_LRO_ALT_REFRESH_TIMER 0x1c
@@ -179,7 +183,10 @@
/* PDMA HW LRO Control Registers */
#define MTK_PDMA_LRO_CTRL_DW0 0x980
+#define MTK_HW_LRO_RING_NUM(eth) (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3)
#define MTK_LRO_EN BIT(0)
+#define MTK_NON_LRO_MULTI_EN BIT(2)
+#define MTK_LRO_DLY_INT_EN BIT(5)
#define MTK_L3_CKS_UPD_EN BIT(7)
#define MTK_L3_CKS_UPD_EN_V2 BIT(19)
#define MTK_LRO_ALT_PKT_CNT_MODE BIT(21)
@@ -198,6 +205,19 @@
#define MTK_MULTI_EN BIT(10)
#define MTK_PDMA_SIZE_8DWORDS (1 << 4)
+/* PDMA RSS Control Registers */
+#define MTK_RX_NAPI_NUM (4)
+#define MTK_RX_RSS_NUM(eth) ((eth)->soc->rss_num)
+#define MTK_RSS_RING(x) (x)
+#define MTK_RSS_EN BIT(0)
+#define MTK_RSS_CFG_REQ BIT(2)
+#define MTK_RSS_IPV6_STATIC_HASH (0x7 << 8)
+#define MTK_RSS_IPV4_STATIC_HASH (0x7 << 12)
+#define MTK_RSS_HASH_KEY_DW(reg_map, x) ((reg_map)->pdma.rss_glo_cfg + \
+ 0x20 + ((x) * 0x4))
+#define MTK_RSS_INDR_TABLE_DW(reg_map, x) ((reg_map)->pdma.rss_glo_cfg + \
+ 0x50 + ((x) * 0x4))
+
/* PDMA Global Configuration Register */
#define MTK_PDMA_LRO_SDL 0x3000
#define MTK_RX_CFG_SDL_OFFSET 16
@@ -209,6 +229,7 @@
/* PDMA Delay Interrupt Register */
#define MTK_PDMA_DELAY_RX_MASK GENMASK(15, 0)
#define MTK_PDMA_DELAY_RX_EN BIT(15)
+#define MTK_PDMA_DELAY_RX_RING_SHIFT 16
#define MTK_PDMA_DELAY_RX_PINT_SHIFT 8
#define MTK_PDMA_DELAY_RX_PTIME_SHIFT 0
@@ -229,14 +250,15 @@
#define MTK_RING_MYIP_VLD BIT(9)
/* PDMA HW LRO Ring Control Registers */
-#define MTK_LRO_RX_RING0_CTRL_DW1 0xb28
-#define MTK_LRO_RX_RING0_CTRL_DW2 0xb2c
-#define MTK_LRO_RX_RING0_CTRL_DW3 0xb30
-#define MTK_LRO_CTRL_DW1_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW1 + (x * 0x40))
-#define MTK_LRO_CTRL_DW2_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW2 + (x * 0x40))
-#define MTK_LRO_CTRL_DW3_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW3 + (x * 0x40))
+#define MTK_LRO_CTRL_DW1_CFG(reg_map, x) ((reg_map)->pdma.lro_ring_ctrl_dw1 + \
+ ((x) * 0x40))
+#define MTK_LRO_CTRL_DW2_CFG(reg_map, x) ((reg_map)->pdma.lro_ring_ctrl_dw1 + \
+ 0x4 + ((x) * 0x40))
+#define MTK_LRO_CTRL_DW3_CFG(reg_map, x) ((reg_map)->pdma.lro_ring_ctrl_dw1 + \
+ 0x8 + ((x) * 0x40))
#define MTK_RING_AGE_TIME_L ((MTK_HW_LRO_AGE_TIME & 0x3ff) << 22)
#define MTK_RING_AGE_TIME_H ((MTK_HW_LRO_AGE_TIME >> 10) & 0x3f)
+#define MTK_RING_PSE_MODE BIT(6)
#define MTK_RING_AUTO_LERAN_MODE (3 << 6)
#define MTK_RING_VLD BIT(8)
#define MTK_RING_MAX_AGG_TIME ((MTK_HW_LRO_AGG_TIME & 0xffff) << 10)
@@ -290,7 +312,20 @@
#define FC_THRES_MIN 0x4444
/* QDMA Interrupt Status Register */
-#define MTK_RX_DONE_DLY BIT(30)
+#define MTK_RX_DONE_INT_V1(ring_no) \
+ ( \
+ (ring_no) ? \
+ BIT(24 + (ring_no)) : \
+ BIT(30) \
+ )
+
+#define MTK_RX_DONE_INT_V2(ring_no) BIT(24 + (ring_no))
+
+#define MTK_RX_DONE_INT(eth, ring_no) \
+ (mtk_is_netsys_v3_or_greater(eth) ? \
+ MTK_RX_DONE_INT_V2(ring_no) : \
+ MTK_RX_DONE_INT_V1(ring_no))
+
#define MTK_TX_DONE_DLY BIT(28)
#define MTK_RX_DONE_INT3 BIT(19)
#define MTK_RX_DONE_INT2 BIT(18)
@@ -300,11 +335,8 @@
#define MTK_TX_DONE_INT2 BIT(2)
#define MTK_TX_DONE_INT1 BIT(1)
#define MTK_TX_DONE_INT0 BIT(0)
-#define MTK_RX_DONE_INT MTK_RX_DONE_DLY
#define MTK_TX_DONE_INT MTK_TX_DONE_DLY
-#define MTK_RX_DONE_INT_V2 BIT(14)
-
#define MTK_CDM_TXFIFO_RDY BIT(7)
/* QDMA Interrupt grouping registers */
@@ -942,6 +974,7 @@ struct mtk_tx_ring {
struct mtk_tx_dma *dma_pdma; /* For MT7628/88 PDMA handling */
dma_addr_t phys_pdma;
int cpu_idx;
+ bool in_sram;
};
/* PDMA rx ring mode */
@@ -967,13 +1000,38 @@ struct mtk_rx_ring {
u16 buf_size;
u16 dma_size;
bool calc_idx_update;
+ bool in_sram;
u16 calc_idx;
u32 crx_idx_reg;
+ u32 ring_no;
/* page_pool */
struct page_pool *page_pool;
struct xdp_rxq_info xdp_q;
};
+/* struct mtk_rss_params - This is the structure holding parameters
+ * for the RSS ring
+ * @hash_key The element is used to record the
+ * secret key for the RSS ring
+ * indirection_table The element is used to record the
+ * indirection table for the RSS ring
+ */
+struct mtk_rss_params {
+ u32 hash_key[MTK_RSS_HASH_KEYSIZE / sizeof(u32)];
+ u8 indirection_table[MTK_RSS_MAX_INDIRECTION_TABLE];
+};
+
+/* struct mtk_napi - This is the structure holding NAPI-related information,
+ * and a mtk_napi struct is binding to one interrupt group
+ * @napi: The NAPI struct
+ * @rx_ring: Pointer to the memory holding info about the RX ring
+ */
+struct mtk_napi {
+ struct napi_struct napi;
+ struct mtk_eth *eth;
+ struct mtk_rx_ring *rx_ring;
+};
+
enum mkt_eth_capabilities {
MTK_RGMII_BIT = 0,
MTK_TRGMII_BIT,
@@ -985,7 +1043,9 @@ enum mkt_eth_capabilities {
MTK_INFRA_BIT,
MTK_SHARED_SGMII_BIT,
MTK_HWLRO_BIT,
+ MTK_RSS_BIT,
MTK_SHARED_INT_BIT,
+ MTK_PDMA_INT_BIT,
MTK_TRGMII_MT7621_CLK_BIT,
MTK_QDMA_BIT,
MTK_SOC_MT7628_BIT,
@@ -1025,7 +1085,9 @@ enum mkt_eth_capabilities {
#define MTK_INFRA BIT_ULL(MTK_INFRA_BIT)
#define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT)
#define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT)
+#define MTK_RSS BIT_ULL(MTK_RSS_BIT)
#define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT)
+#define MTK_PDMA_INT BIT_ULL(MTK_PDMA_INT_BIT)
#define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT)
#define MTK_QDMA BIT_ULL(MTK_QDMA_BIT)
#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT)
@@ -1117,15 +1179,15 @@ enum mkt_eth_capabilities {
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
- MTK_RSTCTRL_PPE1 | MTK_SRAM)
+ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT)
#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
- MTK_RSTCTRL_PPE1 | MTK_SRAM)
+ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT)
#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC2_2P5GPHY | \
MTK_MUX_GMAC2_TO_2P5GPHY | MTK_QDMA | MTK_RSTCTRL_PPE1 | \
- MTK_RSTCTRL_PPE2 | MTK_SRAM)
+ MTK_RSTCTRL_PPE2 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS)
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
@@ -1223,6 +1285,7 @@ struct mtk_reg_map {
struct mtk_soc_data {
const struct mtk_reg_map *reg_map;
u32 ana_rgc3;
+ u32 rss_num;
u64 caps;
u64 required_clks;
bool required_pctl;
@@ -1270,7 +1333,8 @@ struct mtk_soc_data {
* dummy for NAPI to work
* @netdev: The netdev instances
* @mac: Each netdev is linked to a physical MAC
- * @irq: The IRQ that we are using
+ * @irq_fe: Array of IRQs of the frame engine
+ * @irq_pdma: Array of IRQs of the PDMA used for RSS
* @msg_enable: Ethtool msg level
* @ethsys: The register map pointing at the range used to setup
* MII modes
@@ -1314,7 +1378,8 @@ struct mtk_eth {
struct net_device *dummy_dev;
struct net_device *netdev[MTK_MAX_DEVS];
struct mtk_mac *mac[MTK_MAX_DEVS];
- int irq[MTK_FE_IRQ_NUM];
+ int irq_fe[MTK_FE_IRQ_NUM];
+ int irq_pdma[MTK_PDMA_IRQ_NUM];
u32 msg_enable;
unsigned long sysclk;
struct regmap *ethsys;
@@ -1327,7 +1392,8 @@ struct mtk_eth {
struct mtk_rx_ring rx_ring[MTK_MAX_RX_RING_NUM];
struct mtk_rx_ring rx_ring_qdma;
struct napi_struct tx_napi;
- struct napi_struct rx_napi;
+ struct mtk_napi rx_napi[MTK_RX_NAPI_NUM];
+ struct mtk_rss_params rss_params;
void *scratch_ring;
dma_addr_t phy_scratch_ring;
void *scratch_head[MTK_FQ_DMA_HEAD];
--
2.43.0
^ permalink raw reply related
* [net-next v8 3/3] net: ethernet: mtk_eth_soc: Add LRO support
From: Frank Wunderlich @ 2026-05-09 19:09 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, Russell King
Cc: Frank Wunderlich, netdev, linux-kernel, linux-arm-kernel,
linux-mediatek, Mason Chang, Daniel Golle
In-Reply-To: <20260509190938.169290-1-linux@fw-web.de>
From: Mason Chang <mason-cw.chang@mediatek.com>
Add Large Receive Offload support to mediatek ethernet driver and
activate it for MT7988.
Signed-off-by: Mason Chang <mason-cw.chang@mediatek.com>
Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
---
v8:
- fix u32 vs. be32 completely (with sparse check) except one unrelated one
v7:
- fix u32 vs. be32 reported by patchwork check
- add L4 PSH check
https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/7521c42b0bd5be20d52e20b110daea8c756fc069%5E%21/#F1
- Add HW LRO max 4-depth VLAN support including switch special tag.
https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/35490cec6a2e5982532935fb0a1c884f7c4efdb0%5E%21/#F2
v6:
- fix some Macro argument '...' may be better as '(...)' to avoid precedence issues for LRO
- drop unused MTK_CTRL_DW0_SDL_MASK
v5:
- fix too long lines reported by checkpatch
MTK_LRO_RING_RELINQUISH_REQ
MTK_LRO_RING_RELINQUISH_DONE
irq handling (MTK_HW_LRO_IRQ + MTK_HW_LRO_RING)
v4:
- fix lro reverse christmas tree and LRO params suggested by andrew
- drop mtk_hwlro_stats_ebl and unused IS_HW_LRO_RING (only used in
properitary debugfs)
v2:
- drop link to commit for 6.6 patch
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 263 +++++++++++++++++---
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 53 ++--
2 files changed, 254 insertions(+), 62 deletions(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 908fd88287ac..8035fc2557de 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2793,7 +2793,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
if (rx_flag == MTK_RX_FLAGS_HWLRO) {
rx_data_len = MTK_MAX_LRO_RX_LENGTH;
- rx_dma_size = MTK_HW_LRO_DMA_SIZE;
+ rx_dma_size = MTK_HW_LRO_DMA_SIZE(eth);
} else {
rx_data_len = ETH_DATA_LEN;
rx_dma_size = soc->rx.dma_size;
@@ -2806,7 +2806,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
if (!ring->data)
return -ENOMEM;
- if (mtk_page_pool_enabled(eth)) {
+ if (mtk_page_pool_enabled(eth) && rcu_access_pointer(eth->prog)) {
struct page_pool *pp;
pp = mtk_create_page_pool(eth, &ring->xdp_q, ring_no,
@@ -2952,10 +2952,11 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_
static int mtk_hwlro_rx_init(struct mtk_eth *eth)
{
- const struct mtk_reg_map *reg_map = eth->soc->reg_map;
- int i;
u32 ring_ctrl_dw1 = 0, ring_ctrl_dw2 = 0, ring_ctrl_dw3 = 0;
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+ const struct mtk_soc_data *soc = eth->soc;
u32 lro_ctrl_dw0 = 0, lro_ctrl_dw3 = 0;
+ int i, val;
/* set LRO rings to auto-learn modes */
ring_ctrl_dw2 |= MTK_RING_AUTO_LERAN_MODE;
@@ -2974,30 +2975,50 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
ring_ctrl_dw2 |= MTK_RING_MAX_AGG_CNT_L;
ring_ctrl_dw3 |= MTK_RING_MAX_AGG_CNT_H;
- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++) {
mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(reg_map, i));
mtk_w32(eth, ring_ctrl_dw2, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
mtk_w32(eth, ring_ctrl_dw3, MTK_LRO_CTRL_DW3_CFG(reg_map, i));
}
/* IPv4 checksum update enable */
- lro_ctrl_dw0 |= MTK_L3_CKS_UPD_EN;
+ lro_ctrl_dw0 |= MTK_L3_CKS_UPD_EN(eth);
/* switch priority comparison to packet count mode */
lro_ctrl_dw0 |= MTK_LRO_ALT_PKT_CNT_MODE;
+ /* enable L4 PSH flag check */
+ lro_ctrl_dw0 |= MTK_LRO_L4_CTRL_PSH_EN;
+
/* bandwidth threshold setting */
- mtk_w32(eth, MTK_HW_LRO_BW_THRE, MTK_PDMA_LRO_CTRL_DW2);
+ mtk_w32(eth, MTK_HW_LRO_BW_THRE, MTK_PDMA_LRO_CTRL_DW2(reg_map));
/* auto-learn score delta setting */
- mtk_w32(eth, MTK_HW_LRO_REPLACE_DELTA, MTK_PDMA_LRO_ALT_SCORE_DELTA);
+ mtk_w32(eth, MTK_HW_LRO_REPLACE_DELTA, MTK_PDMA_LRO_ALT_SCORE_DELTA(reg_map));
/* set refresh timer for altering flows to 1 sec. (unit: 20us) */
mtk_w32(eth, (MTK_HW_LRO_TIMER_UNIT << 16) | MTK_HW_LRO_REFRESH_TIME,
MTK_PDMA_LRO_ALT_REFRESH_TIMER);
- /* set HW LRO mode & the max aggregation count for rx packets */
- lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff);
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+ val = mtk_r32(eth, reg_map->pdma.rx_cfg);
+ mtk_w32(eth, val | ((MTK_PDMA_LRO_SDL + MTK_MAX_RX_LENGTH) <<
+ MTK_RX_CFG_SDL_OFFSET), reg_map->pdma.rx_cfg);
+
+ lro_ctrl_dw0 |= MTK_PDMA_LRO_SDL << MTK_CTRL_DW0_SDL_OFFSET;
+
+ /* enable cpu reason black list */
+ lro_ctrl_dw0 |= MTK_LRO_CRSN_BNW(eth);
+
+ /* no use PPE cpu reason */
+ mtk_w32(eth, 0xffffffff, MTK_PDMA_LRO_CTRL_DW1(reg_map));
+ } else {
+ /* set HW LRO mode & the max aggregation count for rx packets */
+ lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff);
+ }
+
+ /* enable max 4-depth VLAN support including switch special tag */
+ lro_ctrl_dw3 |= MTK_LRO_VLAN_VID_CMP_DEPTH | MTK_LRO_VLAN_EN;
/* the minimal remaining room of SDL0 in RXD for lro aggregation */
lro_ctrl_dw3 |= MTK_LRO_MIN_RXD_SDL;
@@ -3005,8 +3026,19 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
/* enable HW LRO */
lro_ctrl_dw0 |= MTK_LRO_EN;
- mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3);
- mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0);
+ mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3(reg_map));
+ mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0(reg_map));
+
+ if (mtk_is_netsys_v2_or_greater(eth)) {
+ i = (soc->rx.desc_size == sizeof(struct mtk_rx_dma_v2)) ? 1 : 0;
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)),
+ MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)), reg_map->pdma.int_grp);
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 1)),
+ MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 1)),
+ reg_map->pdma.int_grp + 0x4);
+ mtk_m32(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 2)),
+ MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i + 2)), reg_map->pdma.int_grp3);
+ }
return 0;
}
@@ -3014,16 +3046,16 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth)
static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
{
const struct mtk_reg_map *reg_map = eth->soc->reg_map;
- int i;
u32 val;
+ int i;
/* relinquish lro rings, flush aggregated packets */
- mtk_w32(eth, MTK_LRO_RING_RELINQUISH_REQ, MTK_PDMA_LRO_CTRL_DW0);
+ mtk_w32(eth, MTK_LRO_RING_RELINQUISH_REQ(eth), MTK_PDMA_LRO_CTRL_DW0(reg_map));
/* wait for relinquishments done */
for (i = 0; i < 10; i++) {
- val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0);
- if (val & MTK_LRO_RING_RELINQUISH_DONE) {
+ val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0(reg_map));
+ if (val & MTK_LRO_RING_RELINQUISH_DONE(eth)) {
msleep(20);
continue;
}
@@ -3031,14 +3063,14 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth)
}
/* invalidate lro rings */
- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
+ for (i = 1; i <= MTK_HW_LRO_RING_NUM(eth); i++)
mtk_w32(eth, 0, MTK_LRO_CTRL_DW2_CFG(reg_map, i));
/* disable HW LRO */
- mtk_w32(eth, 0, MTK_PDMA_LRO_CTRL_DW0);
+ mtk_w32(eth, 0, MTK_PDMA_LRO_CTRL_DW0(reg_map));
}
-static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip)
+static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, u32 ip)
{
const struct mtk_reg_map *reg_map = eth->soc->reg_map;
u32 reg_val;
@@ -3048,7 +3080,7 @@ static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip)
/* invalidate the IP setting */
mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
- mtk_w32(eth, ip, MTK_LRO_DIP_DW0_CFG(idx));
+ mtk_w32(eth, ip, MTK_LRO_DIP_DW0_CFG(reg_map, idx));
/* validate the IP setting */
mtk_w32(eth, (reg_val | MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
@@ -3064,7 +3096,7 @@ static void mtk_hwlro_inval_ipaddr(struct mtk_eth *eth, int idx)
/* invalidate the IP setting */
mtk_w32(eth, (reg_val & ~MTK_RING_MYIP_VLD), MTK_LRO_CTRL_DW2_CFG(reg_map, idx));
- mtk_w32(eth, 0, MTK_LRO_DIP_DW0_CFG(idx));
+ mtk_w32(eth, 0, MTK_LRO_DIP_DW0_CFG(reg_map, idx));
}
static int mtk_hwlro_get_ip_cnt(struct mtk_mac *mac)
@@ -3080,6 +3112,65 @@ static int mtk_hwlro_get_ip_cnt(struct mtk_mac *mac)
return cnt;
}
+static int mtk_hwlro_add_ipaddr_idx(struct net_device *dev, u32 ip4dst)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ const struct mtk_reg_map *reg_map;
+ struct mtk_eth *eth = mac->hw;
+ u32 reg_val;
+ int i;
+
+ reg_map = eth->soc->reg_map;
+
+ /* check for duplicate IP address in the current DIP list */
+ for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(reg_map, i));
+ if (reg_val == ip4dst)
+ break;
+ }
+
+ if (i < MTK_HW_LRO_DIP_NUM(eth) + 1) {
+ netdev_warn(dev, "Duplicate IP address at DIP(%d)!\n", i);
+ return -EEXIST;
+ }
+
+ /* find out available DIP index */
+ for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(reg_map, i));
+ if (reg_val == 0UL)
+ break;
+ }
+
+ if (i >= MTK_HW_LRO_DIP_NUM(eth) + 1) {
+ netdev_warn(dev, "DIP index is currently out of resource!\n");
+ return -EBUSY;
+ }
+
+ return i;
+}
+
+static int mtk_hwlro_get_ipaddr_idx(struct net_device *dev, u32 ip4dst)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ u32 reg_val;
+ int i;
+
+ /* find out DIP index that matches the given IP address */
+ for (i = 1; i <= MTK_HW_LRO_DIP_NUM(eth); i++) {
+ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(eth->soc->reg_map, i));
+ if (reg_val == ip4dst)
+ break;
+ }
+
+ if (i >= MTK_HW_LRO_DIP_NUM(eth) + 1) {
+ netdev_warn(dev, "DIP address is not exist!\n");
+ return -ENOENT;
+ }
+
+ return i;
+}
+
static int mtk_hwlro_add_ipaddr(struct net_device *dev,
struct ethtool_rxnfc *cmd)
{
@@ -3088,18 +3179,22 @@ static int mtk_hwlro_add_ipaddr(struct net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
int hwlro_idx;
+ u32 ip4dst;
if ((fsp->flow_type != TCP_V4_FLOW) ||
(!fsp->h_u.tcp_ip4_spec.ip4dst) ||
(fsp->location > 1))
return -EINVAL;
- mac->hwlro_ip[fsp->location] = htonl(fsp->h_u.tcp_ip4_spec.ip4dst);
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+ ip4dst = ntohl(fsp->h_u.tcp_ip4_spec.ip4dst);
+ hwlro_idx = mtk_hwlro_add_ipaddr_idx(dev, ip4dst);
+ if (hwlro_idx < 0)
+ return hwlro_idx;
+ mac->hwlro_ip[fsp->location] = ip4dst;
mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
- mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[fsp->location]);
+ mtk_hwlro_val_ipaddr(eth, hwlro_idx, ip4dst);
return 0;
}
@@ -3112,13 +3207,17 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
int hwlro_idx;
+ u32 ip4dst;
if (fsp->location > 1)
return -EINVAL;
- mac->hwlro_ip[fsp->location] = 0;
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location;
+ ip4dst = mac->hwlro_ip[fsp->location];
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, ip4dst);
+ if (hwlro_idx < 0)
+ return hwlro_idx;
+ mac->hwlro_ip[fsp->location] = 0;
mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac);
mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
@@ -3126,6 +3225,24 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev,
return 0;
}
+static void mtk_hwlro_netdev_enable(struct net_device *dev)
+{
+ struct mtk_mac *mac = netdev_priv(dev);
+ struct mtk_eth *eth = mac->hw;
+ int i, hwlro_idx;
+
+ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i] == 0)
+ continue;
+
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
+ if (hwlro_idx < 0)
+ continue;
+
+ mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[i]);
+ }
+}
+
static void mtk_hwlro_netdev_disable(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
@@ -3133,8 +3250,14 @@ static void mtk_hwlro_netdev_disable(struct net_device *dev)
int i, hwlro_idx;
for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+ if (mac->hwlro_ip[i] == 0)
+ continue;
+
+ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]);
+ if (hwlro_idx < 0)
+ continue;
+
mac->hwlro_ip[i] = 0;
- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + i;
mtk_hwlro_inval_ipaddr(eth, hwlro_idx);
}
@@ -3154,15 +3277,15 @@ static int mtk_hwlro_get_fdir_entry(struct net_device *dev,
/* only tcp dst ipv4 is meaningful, others are meaningless */
fsp->flow_type = TCP_V4_FLOW;
- fsp->h_u.tcp_ip4_spec.ip4dst = ntohl(mac->hwlro_ip[fsp->location]);
+ fsp->h_u.tcp_ip4_spec.ip4dst = htonl(mac->hwlro_ip[fsp->location]);
fsp->m_u.tcp_ip4_spec.ip4dst = 0;
fsp->h_u.tcp_ip4_spec.ip4src = 0;
- fsp->m_u.tcp_ip4_spec.ip4src = 0xffffffff;
+ fsp->m_u.tcp_ip4_spec.ip4src = htonl(~0U);
fsp->h_u.tcp_ip4_spec.psrc = 0;
- fsp->m_u.tcp_ip4_spec.psrc = 0xffff;
+ fsp->m_u.tcp_ip4_spec.psrc = htons(~0);
fsp->h_u.tcp_ip4_spec.pdst = 0;
- fsp->m_u.tcp_ip4_spec.pdst = 0xffff;
+ fsp->m_u.tcp_ip4_spec.pdst = htons(~0);
fsp->h_u.tcp_ip4_spec.tos = 0;
fsp->m_u.tcp_ip4_spec.tos = 0xff;
@@ -3314,6 +3437,8 @@ static int mtk_set_features(struct net_device *dev, netdev_features_t features)
if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO))
mtk_hwlro_netdev_disable(dev);
+ else if ((diff & NETIF_F_LRO) && (features & NETIF_F_LRO))
+ mtk_hwlro_netdev_enable(dev);
return 0;
}
@@ -3371,8 +3496,8 @@ static int mtk_dma_init(struct mtk_eth *eth)
return err;
if (eth->hwlro) {
- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) {
- err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO);
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ err = mtk_rx_alloc(eth, MTK_HW_LRO_RING(eth, i), MTK_RX_FLAGS_HWLRO);
if (err)
return err;
}
@@ -3434,8 +3559,8 @@ static void mtk_dma_free(struct mtk_eth *eth)
if (eth->hwlro) {
mtk_hwlro_rx_uninit(eth);
- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++)
- mtk_rx_clean(eth, ð->rx_ring[i], false);
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++)
+ mtk_rx_clean(eth, ð->rx_ring[MTK_HW_LRO_RING(eth, i)], false);
}
if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) {
@@ -3630,16 +3755,21 @@ static int mtk_start_dma(struct mtk_eth *eth)
val |= MTK_RX_BT_32DWORDS;
mtk_w32(eth, val, reg_map->qdma.glo_cfg);
- mtk_w32(eth,
- MTK_RX_DMA_EN | rx_2b_offset |
- MTK_RX_BT_32DWORDS | MTK_MULTI_EN,
- reg_map->pdma.glo_cfg);
+ val = mtk_r32(eth, reg_map->pdma.glo_cfg);
+ val |= MTK_RX_DMA_EN | rx_2b_offset |
+ MTK_RX_BT_32DWORDS | MTK_MULTI_EN;
+ mtk_w32(eth, val, reg_map->pdma.glo_cfg);
} else {
mtk_w32(eth, MTK_TX_WB_DDONE | MTK_TX_DMA_EN | MTK_RX_DMA_EN |
MTK_MULTI_EN | MTK_PDMA_SIZE_8DWORDS,
reg_map->pdma.glo_cfg);
}
+ if (eth->hwlro && mtk_is_netsys_v3_or_greater(eth)) {
+ val = mtk_r32(eth, reg_map->pdma.glo_cfg);
+ mtk_w32(eth, val | MTK_RX_DMA_LRO_EN, reg_map->pdma.glo_cfg);
+ }
+
return 0;
}
@@ -3798,6 +3928,14 @@ static int mtk_open(struct net_device *dev)
}
}
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ napi_enable(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
+ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(eth,
+ MTK_HW_LRO_RING(eth, i)));
+ }
+ }
+
refcount_set(ð->dma_refcnt, 1);
} else {
refcount_inc(ð->dma_refcnt);
@@ -3893,6 +4031,14 @@ static int mtk_stop(struct net_device *dev)
}
}
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(eth, MTK_HW_LRO_RING(eth, i)));
+ napi_synchronize(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
+ napi_disable(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
+ }
+ }
+
cancel_work_sync(ð->rx_dim.work);
cancel_work_sync(ð->tx_dim.work);
@@ -4301,6 +4447,14 @@ static int mtk_napi_init(struct mtk_eth *eth)
}
}
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ rx_napi = ð->rx_napi[MTK_HW_LRO_RING(eth, i)];
+ rx_napi->eth = eth;
+ rx_napi->rx_ring = ð->rx_ring[MTK_HW_LRO_RING(eth, i)];
+ }
+ }
+
return 0;
}
@@ -5352,6 +5506,7 @@ static int mtk_probe(struct platform_device *pdev)
{
struct resource *res = NULL;
struct device_node *mac_np;
+ u8 lro_irq, lro_ring;
struct mtk_eth *eth;
char *irqname;
int err, i;
@@ -5577,6 +5732,23 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
}
+
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ lro_irq = MTK_HW_LRO_IRQ(eth, i);
+ lro_ring = MTK_HW_LRO_RING(eth, i);
+ irqname = devm_kasprintf(eth->dev, GFP_KERNEL,
+ "%s LRO RX %d",
+ dev_name(eth->dev), i);
+ err = devm_request_irq(eth->dev,
+ eth->irq_pdma[lro_irq],
+ mtk_handle_irq_rx, IRQF_SHARED,
+ irqname,
+ ð->rx_napi[lro_ring]);
+ if (err)
+ goto err_free_dev;
+ }
+ }
} else {
irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s RX",
dev_name(eth->dev));
@@ -5648,6 +5820,13 @@ static int mtk_probe(struct platform_device *pdev)
mtk_napi_rx);
}
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++) {
+ netif_napi_add(eth->dummy_dev, ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi,
+ mtk_napi_rx);
+ }
+ }
+
platform_set_drvdata(pdev, eth);
schedule_delayed_work(ð->reset.monitor_work,
MTK_DMA_MONITOR_TIMEOUT);
@@ -5696,6 +5875,12 @@ static void mtk_remove(struct platform_device *pdev)
for (i = 1; i < MTK_RX_RSS_NUM(eth); i++)
netif_napi_del(ð->rx_napi[MTK_RSS_RING(i)].napi);
}
+
+ if (eth->hwlro) {
+ for (i = 0; i < MTK_HW_LRO_RING_NUM(eth); i++)
+ netif_napi_del(ð->rx_napi[MTK_HW_LRO_RING(eth, i)].napi);
+ }
+
mtk_cleanup(eth);
free_netdev(eth->dummy_dev);
mtk_mdio_cleanup(eth);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 378cf47913ef..f7e7299fef6b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -35,7 +35,7 @@
#define MTK_DMA_SIZE(x) (SZ_##x)
#define MTK_FQ_DMA_HEAD 32
#define MTK_FQ_DMA_LENGTH 2048
-#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN)
+#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN)
#define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
#define MTK_DMA_DUMMY_DESC 0xffffffff
#define MTK_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | \
@@ -63,10 +63,9 @@
#define MTK_QRX_OFFSET 0x10
-#define MTK_MAX_RX_RING_NUM 4
-#define MTK_HW_LRO_DMA_SIZE 8
-
-#define MTK_MAX_LRO_RX_LENGTH (4096 * 3)
+#define MTK_MAX_RX_RING_NUM (8)
+#define MTK_HW_LRO_DMA_SIZE(eth) (mtk_is_netsys_v3_or_greater(eth) ? 64 : 8)
+#define MTK_MAX_LRO_RX_LENGTH (4096 * 3 + MTK_MAX_RX_LENGTH)
#define MTK_MAX_LRO_IP_CNT 2
#define MTK_HW_LRO_TIMER_UNIT 1 /* 20 us */
#define MTK_HW_LRO_REFRESH_TIME 50000 /* 1 sec. */
@@ -182,31 +181,39 @@
#define MTK_CDMM_THRES 0x165c
/* PDMA HW LRO Control Registers */
-#define MTK_PDMA_LRO_CTRL_DW0 0x980
-#define MTK_HW_LRO_RING_NUM(eth) (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3)
+#define MTK_HW_LRO_DIP_NUM(eth) (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3)
+#define MTK_HW_LRO_RING_NUM(eth) (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3)
+#define MTK_HW_LRO_RING(eth, x) ((x) + (mtk_is_netsys_v3_or_greater(eth) ? 4 : 1))
+#define MTK_HW_LRO_IRQ(eth, x) ((x) + (mtk_is_netsys_v3_or_greater(eth) ? 0 : 1))
+#define MTK_LRO_CRSN_BNW(eth) BIT((mtk_is_netsys_v3_or_greater(eth) ? 22 : 6))
#define MTK_LRO_EN BIT(0)
#define MTK_NON_LRO_MULTI_EN BIT(2)
#define MTK_LRO_DLY_INT_EN BIT(5)
-#define MTK_L3_CKS_UPD_EN BIT(7)
-#define MTK_L3_CKS_UPD_EN_V2 BIT(19)
+#define MTK_L3_CKS_UPD_EN(eth) BIT(mtk_is_netsys_v3_or_greater(eth) ? 19 : 7)
#define MTK_LRO_ALT_PKT_CNT_MODE BIT(21)
-#define MTK_LRO_RING_RELINQUISH_REQ (0x7 << 26)
-#define MTK_LRO_RING_RELINQUISH_REQ_V2 (0xf << 24)
-#define MTK_LRO_RING_RELINQUISH_DONE (0x7 << 29)
-#define MTK_LRO_RING_RELINQUISH_DONE_V2 (0xf << 28)
-
-#define MTK_PDMA_LRO_CTRL_DW1 0x984
-#define MTK_PDMA_LRO_CTRL_DW2 0x988
-#define MTK_PDMA_LRO_CTRL_DW3 0x98c
+#define MTK_LRO_RING_RELINQUISH_REQ(eth) (mtk_is_netsys_v3_or_greater(eth) ? \
+ 0xf << 24 : 0x7 << 26)
+#define MTK_LRO_RING_RELINQUISH_DONE(eth) (mtk_is_netsys_v3_or_greater(eth) ? \
+ 0xf << 28 : 0x7 << 29)
+
+#define MTK_PDMA_LRO_CTRL_DW0(reg_map) ((reg_map)->pdma.lro_ctrl_dw0)
+#define MTK_PDMA_LRO_CTRL_DW1(reg_map) ((reg_map)->pdma.lro_ctrl_dw0 + 0x04)
+#define MTK_PDMA_LRO_CTRL_DW2(reg_map) ((reg_map)->pdma.lro_ctrl_dw0 + 0x08)
+#define MTK_PDMA_LRO_CTRL_DW3(reg_map) ((reg_map)->pdma.lro_ctrl_dw0 + 0x0c)
+#define MTK_LRO_VLAN_EN (0xf << 8)
+#define MTK_LRO_VLAN_VID_CMP_DEPTH (0x3 << 12)
+#define MTK_LRO_L4_CTRL_PSH_EN BIT(23)
#define MTK_ADMA_MODE BIT(15)
#define MTK_LRO_MIN_RXD_SDL (MTK_HW_LRO_SDL_REMAIN_ROOM << 16)
+#define MTK_CTRL_DW0_SDL_OFFSET (3)
+
#define MTK_RX_DMA_LRO_EN BIT(8)
#define MTK_MULTI_EN BIT(10)
#define MTK_PDMA_SIZE_8DWORDS (1 << 4)
/* PDMA RSS Control Registers */
-#define MTK_RX_NAPI_NUM (4)
+#define MTK_RX_NAPI_NUM (8)
#define MTK_RX_RSS_NUM(eth) ((eth)->soc->rss_num)
#define MTK_RSS_RING(x) (x)
#define MTK_RSS_EN BIT(0)
@@ -242,11 +249,10 @@
#define MTK_PDMA_DELAY_PTIME_MASK 0xff
/* PDMA HW LRO Alter Flow Delta Register */
-#define MTK_PDMA_LRO_ALT_SCORE_DELTA 0xa4c
+#define MTK_PDMA_LRO_ALT_SCORE_DELTA(reg_map) ((reg_map)->pdma.lro_alt_score_delta)
/* PDMA HW LRO IP Setting Registers */
-#define MTK_LRO_RX_RING0_DIP_DW0 0xb04
-#define MTK_LRO_DIP_DW0_CFG(x) (MTK_LRO_RX_RING0_DIP_DW0 + (x * 0x40))
+#define MTK_LRO_DIP_DW0_CFG(reg_map, x) ((reg_map)->pdma.lro_ring_dip_dw0 + ((x) * 0x40))
#define MTK_RING_MYIP_VLD BIT(9)
/* PDMA HW LRO Ring Control Registers */
@@ -1187,7 +1193,8 @@ enum mkt_eth_capabilities {
#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC2_2P5GPHY | \
MTK_MUX_GMAC2_TO_2P5GPHY | MTK_QDMA | MTK_RSTCTRL_PPE1 | \
- MTK_RSTCTRL_PPE2 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS)
+ MTK_RSTCTRL_PPE2 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS | \
+ MTK_HWLRO)
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
@@ -1454,7 +1461,7 @@ struct mtk_mac {
struct phylink_config phylink_config;
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
- __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
+ u32 hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
unsigned int syscfg0;
struct notifier_block device_notifier;
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox