* [PATCH net-next 0/2] net: stmmac: dwmac4: Auto-discover UC filter size
@ 2026-08-31 7:01 Maxime Chevallier
2026-08-31 7:01 ` [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities Maxime Chevallier
2026-08-31 7:01 ` [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter Maxime Chevallier
0 siblings, 2 replies; 16+ messages in thread
From: Maxime Chevallier @ 2026-08-31 7:01 UTC (permalink / raw)
To: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King
Cc: Maxime Chevallier, thomas.petazzoni, Alexis Lothoré, netdev,
linux-kernel, linux-arm-kernel, linux-stm32
Following my attempts to get clean ethtool selftests runs on stmmac [1],
several issues were found with the unicast filtering.
[1]: https://lore.kernel.org/netdev/20260827134004.45ffb57e@kernel.org/
This lead to the discovery that on dwmac4 platforms, the unicast filter
size is always falling back to the default value of 1 entry. On older
variants, the size comes from devicetree.
With a single-entry filter, we directly fallback to unicast promisc as
soon as any entry is added in the dev->uc list.
dwmac4 exposes through the HW_Features0 register the actual size of the
unicast filter, which is made of 3 banks (details in patch 2). Let's use
this feature to grab the filter size.
Results on actual hardware :
- imx8mp : goes from 1 entry to 64
- stm32mp1 : goes from 1 entry to 4
- jh7110 : goes from 1 entry to 9
- yt6801 : still 1 single entry, on extra implemented in HW
Maxime Chevallier (2):
net: stmmac: dwmac4: Read the UC filter size from hardware
capabilities
net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
drivers/net/ethernet/stmicro/stmmac/common.h | 5 ++
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 6 +-
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 60 +++++++++++++++----
.../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 +
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 39 ++++++++++++
5 files changed, 99 insertions(+), 13 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 7:01 [PATCH net-next 0/2] net: stmmac: dwmac4: Auto-discover UC filter size Maxime Chevallier
@ 2026-08-31 7:01 ` Maxime Chevallier
2026-08-31 12:04 ` Nicolai Buchwitz
2026-08-31 7:01 ` [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter Maxime Chevallier
1 sibling, 1 reply; 16+ messages in thread
From: Maxime Chevallier @ 2026-08-31 7:01 UTC (permalink / raw)
To: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King
Cc: Maxime Chevallier, thomas.petazzoni, Alexis Lothoré, netdev,
linux-kernel, linux-arm-kernel, linux-stm32
dwmac4 has multiple banks of perfect filter entries, independently
configurable during IP integration.
The multi_addr bank reports a number between 0 and 31 corresponding to
the actual number of entries in that bank, while the 32 and 64 banks
are all-or-nothing.
Expose these caps over debugfs as well.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 4 +++-
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 ++++++++++++
4 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 927ea6230073..77bd47a83357 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -419,6 +419,8 @@ struct dma_features {
unsigned int half_duplex;
unsigned int hash_filter;
unsigned int multi_addr;
+ unsigned int additional_32_addr;
+ unsigned int additional_64_addr;
unsigned int pcs;
unsigned int sma_mdio;
unsigned int pmt_remote_wake_up;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index 6382836828ba..89368e34a388 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -176,7 +176,9 @@ enum power_event {
/* MAC HW features0 bitmap */
#define GMAC_HW_FEAT_SAVLANINS BIT(27)
-#define GMAC_HW_FEAT_ADDMAC BIT(18)
+#define GMAC_HW_FEAT_MACADR64SEL BIT(24)
+#define GMAC_HW_FEAT_MACADR32SEL BIT(23)
+#define GMAC_HW_FEAT_ADDMAC GENMASK(22, 18)
#define GMAC_HW_FEAT_RXCOESEL BIT(16)
#define GMAC_HW_FEAT_TXCOSEL BIT(14)
#define GMAC_HW_FEAT_EEESEL BIT(13)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 23ffe1adcd0d..14ac3f0e51f7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -388,6 +388,8 @@ static int dwmac4_get_hw_feature(void __iomem *ioaddr,
dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
dma_cap->vlhash = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
+ dma_cap->additional_32_addr = (hw_cap & GMAC_HW_FEAT_MACADR32SEL) >> 23;
+ dma_cap->additional_64_addr = (hw_cap & GMAC_HW_FEAT_MACADR64SEL) >> 24;
dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index f2fc89176654..a885f8cfef21 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6580,6 +6580,18 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
seq_printf(seq,
"\tNumber of Additional MAC address registers: %d\n",
priv->dma_cap.multi_addr);
+ } else if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
+ seq_printf(seq,
+ "\tNumber of MAC address registers (1-31): %d\n",
+ priv->dma_cap.multi_addr);
+ seq_printf(seq,
+ "\tAdditional 32 MAC address registers (32-63): %s\n",
+ priv->dma_cap.additional_32_addr ? "Y" : "N");
+ seq_printf(seq,
+ "\tAdditional 64 MAC address registers (64-127): %s\n",
+ priv->dma_cap.additional_64_addr ? "Y" : "N");
+ seq_printf(seq, "\tHash Filter: %s\n",
+ (priv->dma_cap.hash_filter) ? "Y" : "N");
} else {
seq_printf(seq, "\tHash Filter: %s\n",
(priv->dma_cap.hash_filter) ? "Y" : "N");
--
2.55.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-08-31 7:01 [PATCH net-next 0/2] net: stmmac: dwmac4: Auto-discover UC filter size Maxime Chevallier
2026-08-31 7:01 ` [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities Maxime Chevallier
@ 2026-08-31 7:01 ` Maxime Chevallier
2026-08-31 12:06 ` Nicolai Buchwitz
2026-09-01 0:12 ` Andrew Lunn
1 sibling, 2 replies; 16+ messages in thread
From: Maxime Chevallier @ 2026-08-31 7:01 UTC (permalink / raw)
To: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King
Cc: Maxime Chevallier, thomas.petazzoni, Alexis Lothoré, netdev,
linux-kernel, linux-arm-kernel, linux-stm32
Contrary to dwmac1000 that gets its number of perfect filter entries
through the 'snps,perfect-filter-entries' property, dwmac4 allows
reading the filter size from the HW features registers.
Perfect filter is used for Unicast filtering, and can contain up to 128
entries, each having its own set of registers to access it.
The registers are always at the same location in the map, regardless
whether or not the entry is implemented in hardware. Accessing a register
for an un-implemented entry just doesn't do anything.
The filter is made of one always-available entry, and 3 configurable
banks :
Entry 0 : Always implemented, stores the primary MAC address
Entry 1 \
... + -- Can contain between 0 and 31 entries. Number of available
Entry 31 / entries in HW_Features0[18:22].
Entry 32 \
... + -- Additional 32 entries, all or nothing. Availability is
Entry 63 / specified by HW_Features0[23]
Entry 64 \
... + - Additional 64 entries, all or nothing. Availability is
Entry 127 / specified by HW_Features0[24].
Each of the 3 configurable banks are independently selectable, meaning
we can have gaps in the register banks.
For instance, a setup with 50 addresses enabled will have 17 entries in
the first bank and the additional 32 bank enabled (50 = 32 + 17 + 1).
Another example with 70 addresses : 64 addr bank on, 5 addresses in the
first bank (70 = 64 + 5 + 1).
While I haven't seen HW with gaps in the banks, Synopsys confirmed this
is a real possibility.
Let's therefore introduce a dwmac4 helper to get the physical slot
number of a given entry, allowing to configure the correct bank when
populating the filter. As we need the HW feature-set to compute the
index, store the bank info in the mac_device_info struct.
The total number of available entries is computed based on the
discovered parameters, instead of using the default value of 1.
Results on HW that uses dwmac4 :
- imx8mp : goes from 1 entry to 64 (1 + 31 + 32)
- stm32mp1 : goes from 1 entry to 4 (1 + 3)
- jh7110 : goes from 1 entry to 9 (1 + 8)
- yt6801 : goes from 1 entry to hum, 1 entry (no extra addresses)
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/ethernet/stmicro/stmmac/common.h | 3 +
drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 2 -
.../net/ethernet/stmicro/stmmac/dwmac4_core.c | 60 +++++++++++++++----
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++++++++
4 files changed, 80 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 77bd47a83357..1729fb29ece3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -629,6 +629,7 @@ struct mac_device_info {
void __iomem *pcsr; /* vpointer to device CSRs */
unsigned int multicast_filter_bins;
unsigned int unicast_filter_entries;
+ unsigned int multi_addr;
unsigned int mcast_bits_log2;
unsigned int rx_csum;
unsigned int num_vlan;
@@ -637,6 +638,8 @@ struct mac_device_info {
u8 vlan_fail_q;
bool hw_vlan_en;
bool reverse_sgmii_enable;
+ bool additional_32_addr;
+ bool additional_64_addr;
/* This spinlock protects read-modify-write of the interrupt
* mask/enable registers.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index 89368e34a388..696846531229 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -75,8 +75,6 @@
#define GMAC_PACKET_FILTER_IPFE BIT(20)
#define GMAC_PACKET_FILTER_RA BIT(31)
-#define GMAC_MAX_PERFECT_ADDRESSES 128
-
/* MAC RX Queue Enable */
#define GMAC_RX_QUEUE_CLEAR(queue) ~(GENMASK(1, 0) << ((queue) * 2))
#define GMAC_RX_AV_QUEUE_ENABLE(queue) BIT((queue) * 2)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 18b357b257cc..fb5b96a43505 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -365,22 +365,63 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode)
writel(pmt, ioaddr + GMAC_PMT);
}
+/**
+ * dwmac4_umac_addr_slot - Get the UC filter slot for the Nth MAC address
+ * @hw: The MAC device info
+ * @reg_n: The MAC address's index in the UC list
+ *
+ * On dwmac4 the slots available for Unicast MAC filtering are configured when
+ * integrating the IP.
+ *
+ * - Slot 0 is always available, used to store the primary MAC address
+ * - From 1 to 31, the number of implemented slots is set in hw->multi_addr
+ * - From 32 to 63, the range is available if hw->additional_32_addr
+ * is set
+ * - From 64 to 127, the range is available if hw->additional_64_addr is set
+ *
+ * All the ranges can be configured independently (e.g. 64 -> 127 can be
+ * available, but not 32 -> 63)
+ *
+ * Returns: The physical slot index in the UC filter
+ */
+static unsigned int dwmac4_umac_addr_slot(struct mac_device_info *hw,
+ unsigned int reg_n)
+{
+ unsigned int empty_slots = 0;
+
+ /* reg_n is in the 1-31 bank : 1 to 1 mapping */
+ if (reg_n < (hw->multi_addr + 1))
+ return reg_n;
+
+ /* Gap between the last address in the 1->31 range and the next slot */
+ if (hw->additional_32_addr)
+ empty_slots = 32 - (hw->multi_addr + 1);
+ else if (hw->additional_64_addr)
+ empty_slots = 64 - (hw->multi_addr + 1);
+
+ return reg_n + empty_slots;
+}
+
static void dwmac4_set_umac_addr(struct mac_device_info *hw,
const unsigned char *addr, unsigned int reg_n)
{
void __iomem *ioaddr = hw->pcsr;
+ unsigned int slot;
- stmmac_dwmac4_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
- GMAC_ADDR_LOW(reg_n));
+ slot = dwmac4_umac_addr_slot(hw, reg_n);
+ stmmac_dwmac4_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(slot),
+ GMAC_ADDR_LOW(slot));
}
static void dwmac4_get_umac_addr(struct mac_device_info *hw,
unsigned char *addr, unsigned int reg_n)
{
void __iomem *ioaddr = hw->pcsr;
+ unsigned int slot;
- stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
- GMAC_ADDR_LOW(reg_n));
+ slot = dwmac4_umac_addr_slot(hw, reg_n);
+ stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(slot),
+ GMAC_ADDR_LOW(slot));
}
static int dwmac4_set_lpi_mode(struct mac_device_info *hw,
@@ -522,9 +563,6 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
/* Handle multiple unicast addresses */
if (netdev_uc_count(dev) + 1 > hw->unicast_filter_entries) {
- /* Switch to promiscuous mode if more than 128 addrs
- * are required
- */
value |= GMAC_PACKET_FILTER_PR;
} else {
struct netdev_hw_addr *ha;
@@ -535,9 +573,11 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
reg++;
}
- while (reg < GMAC_MAX_PERFECT_ADDRESSES) {
- writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
- writel(0, ioaddr + GMAC_ADDR_LOW(reg));
+ while (reg < hw->unicast_filter_entries) {
+ unsigned int slot = dwmac4_umac_addr_slot(hw, reg);
+
+ writel(0, ioaddr + GMAC_ADDR_HIGH(slot));
+ writel(0, ioaddr + GMAC_ADDR_LOW(slot));
reg++;
}
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index a885f8cfef21..80413ba8df55 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7492,6 +7492,33 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
priv->plat->tx_fifo_size = priv->dma_cap.tx_fifo_size;
}
+ /* On DWMAC4 we can get the exact number of perfect filter entries from
+ * the HW_Features.
+ */
+ if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
+ priv->hw->multi_addr = priv->dma_cap.multi_addr;
+ priv->hw->additional_32_addr =
+ !!priv->dma_cap.additional_32_addr;
+ priv->hw->additional_64_addr =
+ !!priv->dma_cap.additional_64_addr;
+
+ /* We always have one slot for the primary MAC */
+ priv->hw->unicast_filter_entries = 1;
+
+ /* How many slots in the 1 -> 31 range */
+ priv->hw->unicast_filter_entries += priv->hw->multi_addr;
+
+ /* Additional 32 entries in the 32 -> 63 range */
+ if (priv->hw->additional_32_addr)
+ priv->hw->unicast_filter_entries += 32;
+
+ /* Additional 64 entries in the 64 -> 127 range, can be enabled
+ * independently of the 32 -> 63 range
+ */
+ if (priv->hw->additional_64_addr)
+ priv->hw->unicast_filter_entries += 64;
+ }
+
priv->hw->vlan_fail_q_en =
(priv->plat->flags & STMMAC_FLAG_VLAN_FAIL_Q_EN);
priv->hw->vlan_fail_q = priv->plat->vlan_fail_q;
--
2.55.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 7:01 ` [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities Maxime Chevallier
@ 2026-08-31 12:04 ` Nicolai Buchwitz
2026-08-31 12:15 ` Maxime Chevallier
2026-09-01 7:08 ` Maxime Chevallier
0 siblings, 2 replies; 16+ messages in thread
From: Nicolai Buchwitz @ 2026-08-31 12:04 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
Hi Maxime
On 31.8.2026 09:01, Maxime Chevallier wrote:
> dwmac4 has multiple banks of perfect filter entries, independently
> configurable during IP integration.
>
> The multi_addr bank reports a number between 0 and 31 corresponding to
> the actual number of entries in that bank, while the 32 and 64 banks
> are all-or-nothing.
>
> Expose these caps over debugfs as well.
>
> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> ---
> [...]
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
> index 6382836828ba..89368e34a388 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
> @@ -176,7 +176,9 @@ enum power_event {
>
> /* MAC HW features0 bitmap */
> #define GMAC_HW_FEAT_SAVLANINS BIT(27)
> -#define GMAC_HW_FEAT_ADDMAC BIT(18)
> +#define GMAC_HW_FEAT_MACADR64SEL BIT(24)
> +#define GMAC_HW_FEAT_MACADR32SEL BIT(23)
> +#define GMAC_HW_FEAT_ADDMAC GENMASK(22, 18)
> #define GMAC_HW_FEAT_RXCOESEL BIT(16)
> #define GMAC_HW_FEAT_TXCOSEL BIT(14)
> #define GMAC_HW_FEAT_EEESEL BIT(13)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> index 23ffe1adcd0d..14ac3f0e51f7 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
> @@ -388,6 +388,8 @@ static int dwmac4_get_hw_feature(void __iomem
> *ioaddr,
> dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
> dma_cap->vlhash = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
> dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
Now that ADDMAC has grown from single bit to a mask, the hardcoded 18
has to match
dwmac4.h. So IMHO it would make sense to use FIELD_GET() here (like
actphyif)?
> + dma_cap->additional_32_addr = (hw_cap & GMAC_HW_FEAT_MACADR32SEL) >>
> 23;
> + dma_cap->additional_64_addr = (hw_cap & GMAC_HW_FEAT_MACADR64SEL) >>
> 24;
> dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
> dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
> dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index f2fc89176654..a885f8cfef21 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -6580,6 +6580,18 @@ static int stmmac_dma_cap_show(struct seq_file
> *seq, void *v)
> seq_printf(seq,
> "\tNumber of Additional MAC address registers: %d\n",
> priv->dma_cap.multi_addr);
> + } else if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
> + seq_printf(seq,
> + "\tNumber of MAC address registers (1-31): %d\n",
> + priv->dma_cap.multi_addr);
> + seq_printf(seq,
> + "\tAdditional 32 MAC address registers (32-63): %s\n",
> + priv->dma_cap.additional_32_addr ? "Y" : "N");
> + seq_printf(seq,
> + "\tAdditional 64 MAC address registers (64-127): %s\n",
> + priv->dma_cap.additional_64_addr ? "Y" : "N");
> + seq_printf(seq, "\tHash Filter: %s\n",
> + (priv->dma_cap.hash_filter) ? "Y" : "N");
hash_filter seems to be only set in dwmac1000_dma.c? So on dwmac4 it
would always print N?
> } else {
> seq_printf(seq, "\tHash Filter: %s\n",
> (priv->dma_cap.hash_filter) ? "Y" : "N");
Thanks,
Nicolai
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-08-31 7:01 ` [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter Maxime Chevallier
@ 2026-08-31 12:06 ` Nicolai Buchwitz
2026-09-01 0:12 ` Andrew Lunn
1 sibling, 0 replies; 16+ messages in thread
From: Nicolai Buchwitz @ 2026-08-31 12:06 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
Hi Maxime
On 31.8.2026 09:01, Maxime Chevallier wrote:
> Contrary to dwmac1000 that gets its number of perfect filter entries
> through the 'snps,perfect-filter-entries' property, dwmac4 allows
> reading the filter size from the HW features registers.
>
> Perfect filter is used for Unicast filtering, and can contain up to 128
> entries, each having its own set of registers to access it.
>
> The registers are always at the same location in the map, regardless
> whether or not the entry is implemented in hardware. Accessing a
> register
> for an un-implemented entry just doesn't do anything.
>
> The filter is made of one always-available entry, and 3 configurable
> banks :
>
> Entry 0 : Always implemented, stores the primary MAC address
>
> Entry 1 \
> ... + -- Can contain between 0 and 31 entries. Number of
> available
> Entry 31 / entries in HW_Features0[18:22].
>
> Entry 32 \
> ... + -- Additional 32 entries, all or nothing. Availability is
> Entry 63 / specified by HW_Features0[23]
>
> Entry 64 \
> ... + - Additional 64 entries, all or nothing. Availability is
> Entry 127 / specified by HW_Features0[24].
>
> Each of the 3 configurable banks are independently selectable, meaning
> we can have gaps in the register banks.
>
> For instance, a setup with 50 addresses enabled will have 17 entries in
> the first bank and the additional 32 bank enabled (50 = 32 + 17 + 1).
>
> Another example with 70 addresses : 64 addr bank on, 5 addresses in the
> first bank (70 = 64 + 5 + 1).
>
> While I haven't seen HW with gaps in the banks, Synopsys confirmed this
> is a real possibility.
>
> Let's therefore introduce a dwmac4 helper to get the physical slot
> number of a given entry, allowing to configure the correct bank when
> populating the filter. As we need the HW feature-set to compute the
> index, store the bank info in the mac_device_info struct.
>
> The total number of available entries is computed based on the
> discovered parameters, instead of using the default value of 1.
>
> Results on HW that uses dwmac4 :
>
> - imx8mp : goes from 1 entry to 64 (1 + 31 + 32)
> - stm32mp1 : goes from 1 entry to 4 (1 + 3)
> - jh7110 : goes from 1 entry to 9 (1 + 8)
> - yt6801 : goes from 1 entry to hum, 1 entry (no extra addresses)
>
> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> ---
> [...]
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks,
Nicolai
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 12:04 ` Nicolai Buchwitz
@ 2026-08-31 12:15 ` Maxime Chevallier
2026-08-31 12:26 ` Nicolai Buchwitz
2026-09-01 0:26 ` Andrew Lunn
2026-09-01 7:08 ` Maxime Chevallier
1 sibling, 2 replies; 16+ messages in thread
From: Maxime Chevallier @ 2026-08-31 12:15 UTC (permalink / raw)
To: Nicolai Buchwitz
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
On 8/31/26 14:04, Nicolai Buchwitz wrote:
> Hi Maxime
>
> On 31.8.2026 09:01, Maxime Chevallier wrote:
>> dwmac4 has multiple banks of perfect filter entries, independently
>> configurable during IP integration.
>>
>> The multi_addr bank reports a number between 0 and 31 corresponding to
>> the actual number of entries in that bank, while the 32 and 64 banks
>> are all-or-nothing.
>>
>> Expose these caps over debugfs as well.
>>
>> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
>> ---
>
>> [...]
>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> index 6382836828ba..89368e34a388 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> @@ -176,7 +176,9 @@ enum power_event {
>>
>> /* MAC HW features0 bitmap */
>> #define GMAC_HW_FEAT_SAVLANINS BIT(27)
>> -#define GMAC_HW_FEAT_ADDMAC BIT(18)
>> +#define GMAC_HW_FEAT_MACADR64SEL BIT(24)
>> +#define GMAC_HW_FEAT_MACADR32SEL BIT(23)
>> +#define GMAC_HW_FEAT_ADDMAC GENMASK(22, 18)
>> #define GMAC_HW_FEAT_RXCOESEL BIT(16)
>> #define GMAC_HW_FEAT_TXCOSEL BIT(14)
>> #define GMAC_HW_FEAT_EEESEL BIT(13)
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> index 23ffe1adcd0d..14ac3f0e51f7 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> @@ -388,6 +388,8 @@ static int dwmac4_get_hw_feature(void __iomem *ioaddr,
>> dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
>> dma_cap->vlhash = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
>> dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
>
> Now that ADDMAC has grown from single bit to a mask, the hardcoded 18 has to match
> dwmac4.h. So IMHO it would make sense to use FIELD_GET() here (like actphyif)?
It's hardcoded all over, if you look at how all the other fields from the features
are read. I can change it if you really think it's worth, however I'd rather
do a proper cleanup of how all the properties are read at once :)
>
>> + dma_cap->additional_32_addr = (hw_cap & GMAC_HW_FEAT_MACADR32SEL) >> 23;
>> + dma_cap->additional_64_addr = (hw_cap & GMAC_HW_FEAT_MACADR64SEL) >> 24;
>> dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
>> dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
>> dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6;
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index f2fc89176654..a885f8cfef21 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -6580,6 +6580,18 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
>> seq_printf(seq,
>> "\tNumber of Additional MAC address registers: %d\n",
>> priv->dma_cap.multi_addr);
>> + } else if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
>> + seq_printf(seq,
>> + "\tNumber of MAC address registers (1-31): %d\n",
>> + priv->dma_cap.multi_addr);
>> + seq_printf(seq,
>> + "\tAdditional 32 MAC address registers (32-63): %s\n",
>> + priv->dma_cap.additional_32_addr ? "Y" : "N");
>> + seq_printf(seq,
>> + "\tAdditional 64 MAC address registers (64-127): %s\n",
>> + priv->dma_cap.additional_64_addr ? "Y" : "N");
>> + seq_printf(seq, "\tHash Filter: %s\n",
>> + (priv->dma_cap.hash_filter) ? "Y" : "N");
>
> hash_filter seems to be only set in dwmac1000_dma.c? So on dwmac4 it would always print N?
Yeah but dwmac4 has a hash filter, but same as the UC filter it's just not plumbed
in :/
Let's leave this flag here, hash filter addition for MC filtering is coming-up, so let's not
drop it now only to re-enable it after, one of the other wonderful discoveries found by
running the selftests...
>
>> } else {
>> seq_printf(seq, "\tHash Filter: %s\n",
>> (priv->dma_cap.hash_filter) ? "Y" : "N");
>
> Thanks,
> Nicolai
Maxime
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 12:15 ` Maxime Chevallier
@ 2026-08-31 12:26 ` Nicolai Buchwitz
2026-09-01 0:26 ` Andrew Lunn
1 sibling, 0 replies; 16+ messages in thread
From: Nicolai Buchwitz @ 2026-08-31 12:26 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
On 31.8.2026 14:15, Maxime Chevallier wrote:
> On 8/31/26 14:04, Nicolai Buchwitz wrote:
>> Hi Maxime
>>
>> On 31.8.2026 09:01, Maxime Chevallier wrote:
>>> dwmac4 has multiple banks of perfect filter entries, independently
>>> configurable during IP integration.
>>>
>>> The multi_addr bank reports a number between 0 and 31 corresponding
>>> to
>>> the actual number of entries in that bank, while the 32 and 64 banks
>>> are all-or-nothing.
>>>
>>> Expose these caps over debugfs as well.
>>>
>>> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
>>> ---
>>
>>> [...]
>>
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>>> index 6382836828ba..89368e34a388 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>>> @@ -176,7 +176,9 @@ enum power_event {
>>>
>>> /* MAC HW features0 bitmap */
>>> #define GMAC_HW_FEAT_SAVLANINS BIT(27)
>>> -#define GMAC_HW_FEAT_ADDMAC BIT(18)
>>> +#define GMAC_HW_FEAT_MACADR64SEL BIT(24)
>>> +#define GMAC_HW_FEAT_MACADR32SEL BIT(23)
>>> +#define GMAC_HW_FEAT_ADDMAC GENMASK(22, 18)
>>> #define GMAC_HW_FEAT_RXCOESEL BIT(16)
>>> #define GMAC_HW_FEAT_TXCOSEL BIT(14)
>>> #define GMAC_HW_FEAT_EEESEL BIT(13)
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> index 23ffe1adcd0d..14ac3f0e51f7 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>>> @@ -388,6 +388,8 @@ static int dwmac4_get_hw_feature(void __iomem
>>> *ioaddr,
>>> dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
>>> dma_cap->vlhash = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
>>> dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
>>
>> Now that ADDMAC has grown from single bit to a mask, the hardcoded 18
>> has to match
>> dwmac4.h. So IMHO it would make sense to use FIELD_GET() here (like
>> actphyif)?
>
> It's hardcoded all over, if you look at how all the other fields from
> the features
> are read. I can change it if you really think it's worth, however I'd
> rather
> do a proper cleanup of how all the properties are read at once :)
Perfectly fine for me. Ran into a similar, but unrelated issue recently,
so I just
wanted to flag it (for the future) :)
>
>>
>>> + dma_cap->additional_32_addr = (hw_cap &
>>> GMAC_HW_FEAT_MACADR32SEL) >> 23;
>>> + dma_cap->additional_64_addr = (hw_cap &
>>> GMAC_HW_FEAT_MACADR64SEL) >> 24;
>>> dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
>>> dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
>>> dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >>
>>> 6;
>>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> index f2fc89176654..a885f8cfef21 100644
>>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>>> @@ -6580,6 +6580,18 @@ static int stmmac_dma_cap_show(struct seq_file
>>> *seq, void *v)
>>> seq_printf(seq,
>>> "\tNumber of Additional MAC address registers: %d\n",
>>> priv->dma_cap.multi_addr);
>>> + } else if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
>>> + seq_printf(seq,
>>> + "\tNumber of MAC address registers (1-31): %d\n",
>>> + priv->dma_cap.multi_addr);
>>> + seq_printf(seq,
>>> + "\tAdditional 32 MAC address registers (32-63):
>>> %s\n",
>>> + priv->dma_cap.additional_32_addr ? "Y" : "N");
>>> + seq_printf(seq,
>>> + "\tAdditional 64 MAC address registers (64-127):
>>> %s\n",
>>> + priv->dma_cap.additional_64_addr ? "Y" : "N");
>>> + seq_printf(seq, "\tHash Filter: %s\n",
>>> + (priv->dma_cap.hash_filter) ? "Y" : "N");
>>
>> hash_filter seems to be only set in dwmac1000_dma.c? So on dwmac4 it
>> would always print N?
>
> Yeah but dwmac4 has a hash filter, but same as the UC filter it's just
> not plumbed
> in :/
>
> Let's leave this flag here, hash filter addition for MC filtering is
> coming-up, so let's not
> drop it now only to re-enable it after, one of the other wonderful
> discoveries found by
> running the selftests...
Also fine with me.
>
>>
>>> } else {
>>> seq_printf(seq, "\tHash Filter: %s\n",
>>> (priv->dma_cap.hash_filter) ? "Y" : "N");
>>
>> Thanks,
>> Nicolai
>
> Maxime
With both comments addressed and agreed to keep it as is until a cleanup
in the future:
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Thanks,
Nicolai
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-08-31 7:01 ` [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter Maxime Chevallier
2026-08-31 12:06 ` Nicolai Buchwitz
@ 2026-09-01 0:12 ` Andrew Lunn
2026-09-01 6:37 ` Maxime Chevallier
1 sibling, 1 reply; 16+ messages in thread
From: Andrew Lunn @ 2026-09-01 0:12 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
On Mon, Aug 31, 2026 at 09:01:20AM +0200, Maxime Chevallier wrote:
> Contrary to dwmac1000 that gets its number of perfect filter entries
> through the 'snps,perfect-filter-entries' property, dwmac4 allows
> reading the filter size from the HW features registers.
Does dwmac4 take any notice of "snps,perfect-filter-entries"? Should
it be marked deprecated?
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 12:15 ` Maxime Chevallier
2026-08-31 12:26 ` Nicolai Buchwitz
@ 2026-09-01 0:26 ` Andrew Lunn
2026-09-01 7:04 ` Maxime Chevallier
1 sibling, 1 reply; 16+ messages in thread
From: Andrew Lunn @ 2026-09-01 0:26 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Nicolai Buchwitz, Andrew Lunn, Jakub Kicinski, davem,
Eric Dumazet, Paolo Abeni, Simon Horman, Maxime Coquelin,
Alexandre Torgue, Russell King, thomas.petazzoni,
Alexis Lothoré, netdev, linux-kernel, linux-arm-kernel,
linux-stm32
> Yeah but dwmac4 has a hash filter, but same as the UC filter it's just not plumbed
> in :/
>
> Let's leave this flag here, hash filter addition for MC filtering is coming-up, so let's not
> drop it now only to re-enable it after, one of the other wonderful discoveries found by
> running the selftests...
I assume you can put a MC address in a perfect match filter? You can
perfectly match a multicast address just as well as a unicast address.
The hash filter is less accurate, but again can be used to match a
unicast or multicast address, and then you need additional filtering
in software, which Linux will do.
So it seems to me, you should use a perfect match filters if you have
one available, independent of unicast or multicast, and only use a
hash filter if you have run out of perfect match filters.
A IPv6 interface will be listening on a multicast address for
Neighbour discovery. It would be good to do a perfect match on it...
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-09-01 0:12 ` Andrew Lunn
@ 2026-09-01 6:37 ` Maxime Chevallier
2026-09-01 12:21 ` Andrew Lunn
0 siblings, 1 reply; 16+ messages in thread
From: Maxime Chevallier @ 2026-09-01 6:37 UTC (permalink / raw)
To: Andrew Lunn
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
Hi,
On 9/1/26 02:12, Andrew Lunn wrote:
> On Mon, Aug 31, 2026 at 09:01:20AM +0200, Maxime Chevallier wrote:
>> Contrary to dwmac1000 that gets its number of perfect filter entries
>> through the 'snps,perfect-filter-entries' property, dwmac4 allows
>> reading the filter size from the HW features registers.
>
> Does dwmac4 take any notice of "snps,perfect-filter-entries"? Should
> it be marked deprecated?
It's only used on :
"st,spear600-gmac"
"snps,dwmac-3.50a"
"snps,dwmac-3.70a"
"snps,dwmac-3.72a"
"snps,dwmac"
So, dwmac1000.
I'd say, we can definitely deprecate on IPs that don't match these.
Interestingly, there are _some_ dwmac4 devicetrees out there that use
this property. It achieves nothing, and even worse, doesn't match what
the HW reports :
In arch/riscv/boot/dts/starfive/jh7110.dtsi for example :
gmac1: ethernet@16040000 {
compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
[...]
snps,perfect-filter-entries = <256>;
}
To my knowledge, 256 isn't even possible, there's only 128 MAC address
registers available :/
perfect filter size discovery on real HW says there's on 8 available,
I haven't measured the actual size of the filter though but it seems
more plausible than 256.
Maxime
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-09-01 0:26 ` Andrew Lunn
@ 2026-09-01 7:04 ` Maxime Chevallier
2026-09-01 12:38 ` Andrew Lunn
0 siblings, 1 reply; 16+ messages in thread
From: Maxime Chevallier @ 2026-09-01 7:04 UTC (permalink / raw)
To: Andrew Lunn
Cc: Nicolai Buchwitz, Andrew Lunn, Jakub Kicinski, davem,
Eric Dumazet, Paolo Abeni, Simon Horman, Maxime Coquelin,
Alexandre Torgue, Russell King, thomas.petazzoni,
Alexis Lothoré, netdev, linux-kernel, linux-arm-kernel,
linux-stm32
On 9/1/26 02:26, Andrew Lunn wrote:
>> Yeah but dwmac4 has a hash filter, but same as the UC filter it's just not plumbed
>> in :/
>>
>> Let's leave this flag here, hash filter addition for MC filtering is coming-up, so let's not
>> drop it now only to re-enable it after, one of the other wonderful discoveries found by
>> running the selftests...
>
> I assume you can put a MC address in a perfect match filter? You can
> perfectly match a multicast address just as well as a unicast address.
>
> The hash filter is less accurate, but again can be used to match a
> unicast or multicast address, and then you need additional filtering
> in software, which Linux will do.
>
> So it seems to me, you should use a perfect match filters if you have
> one available, independent of unicast or multicast, and only use a
> hash filter if you have run out of perfect match filters.
That's an interesting point. The HW supports that, we have 3 control knobs
for that in the MAC_PACKET_FILTER register :
- HPF (bit 10) : Use Hash or Perfect Match for filtering.
0 : Match UC and MC against hash filter
1 : Match UC and MC according to HMC and HUC
- HMC (bit 2) : Use Hash or Perfect Match for MC filtering
0 : Match MC against perfect filter
1 : Match MC against Hash table
- HUC (bit 1) : Use Hash of PF for UC filtering
0 : Match UC against PF
1 : Match UC against Hash table
I don't know though how this all interacts with the primary MAC address. We
always have one entry in PF for the device's own MAC address, we should
probably always perfect match that one.
But as the UC Perfect Filter toggle is global for All UC addresses it means
we're stuck with perfect filter for all UC then ?
For MC, this is a good point, but I'm worried about the complexity vs gain.
If we consider the 4 dwmac boards I have (may not be a very representative sample),
we have :
- imx8mp : 64 PF (Perfect Fitler) entries
- jh7110 : 9 PF entries
- stm32mp1 : 4 PF entries
- yt6801 : 1 PF entry
On a simple setup, between the IPv4 and IPv6 multicast, we very easily have at
least 3 multicast addresses assigned to our interface when it's brought up :
# ip maddr show eth0
2: eth0
link 33:33:00:00:00:01
link 01:00:5e:00:00:01
link 33:33:ff:00:af:d7
[...]
So on STM32MP1 this is already enough to fill the perfect fitler, any addition
trips either the promisc logic, or a more complex logic to re-split UC and MC into
Hash and Perfect filters separately
On YT8601, 1 PF entry, all MC to Hash, and any additional UC trips the UC-promisc mode.
I think in a typical setup, the UC table has more chance of getting filled than the hash
table, so a simpler option could be :
- Always use hash for MC
- Use perfect match for UC when possible
- If perfect filter is full, use Hash for UC and MC matching, with
the idea that hash is still better than going UC-promisc ?
Maxime
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-08-31 12:04 ` Nicolai Buchwitz
2026-08-31 12:15 ` Maxime Chevallier
@ 2026-09-01 7:08 ` Maxime Chevallier
1 sibling, 0 replies; 16+ messages in thread
From: Maxime Chevallier @ 2026-09-01 7:08 UTC (permalink / raw)
To: Nicolai Buchwitz
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
Hi again Nicolai,
On 8/31/26 14:04, Nicolai Buchwitz wrote:
> Hi Maxime
>
> On 31.8.2026 09:01, Maxime Chevallier wrote:
>> dwmac4 has multiple banks of perfect filter entries, independently
>> configurable during IP integration.
>>
>> The multi_addr bank reports a number between 0 and 31 corresponding to
>> the actual number of entries in that bank, while the 32 and 64 banks
>> are all-or-nothing.
>>
>> Expose these caps over debugfs as well.
>>
>> Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
>> ---
>
>> [...]
>
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> index 6382836828ba..89368e34a388 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
>> @@ -176,7 +176,9 @@ enum power_event {
>>
>> /* MAC HW features0 bitmap */
>> #define GMAC_HW_FEAT_SAVLANINS BIT(27)
>> -#define GMAC_HW_FEAT_ADDMAC BIT(18)
>> +#define GMAC_HW_FEAT_MACADR64SEL BIT(24)
>> +#define GMAC_HW_FEAT_MACADR32SEL BIT(23)
>> +#define GMAC_HW_FEAT_ADDMAC GENMASK(22, 18)
>> #define GMAC_HW_FEAT_RXCOESEL BIT(16)
>> #define GMAC_HW_FEAT_TXCOSEL BIT(14)
>> #define GMAC_HW_FEAT_EEESEL BIT(13)
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> index 23ffe1adcd0d..14ac3f0e51f7 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
>> @@ -388,6 +388,8 @@ static int dwmac4_get_hw_feature(void __iomem *ioaddr,
>> dma_cap->half_duplex = (hw_cap & GMAC_HW_FEAT_HDSEL) >> 2;
>> dma_cap->vlhash = (hw_cap & GMAC_HW_FEAT_VLHASH) >> 4;
>> dma_cap->multi_addr = (hw_cap & GMAC_HW_FEAT_ADDMAC) >> 18;
>
> Now that ADDMAC has grown from single bit to a mask, the hardcoded 18 has to match
> dwmac4.h. So IMHO it would make sense to use FIELD_GET() here (like actphyif)?
>
>> + dma_cap->additional_32_addr = (hw_cap & GMAC_HW_FEAT_MACADR32SEL) >> 23;
>> + dma_cap->additional_64_addr = (hw_cap & GMAC_HW_FEAT_MACADR64SEL) >> 24;
>> dma_cap->pcs = (hw_cap & GMAC_HW_FEAT_PCSSEL) >> 3;
>> dma_cap->sma_mdio = (hw_cap & GMAC_HW_FEAT_SMASEL) >> 5;
>> dma_cap->pmt_remote_wake_up = (hw_cap & GMAC_HW_FEAT_RWKSEL) >> 6;
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index f2fc89176654..a885f8cfef21 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> @@ -6580,6 +6580,18 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
>> seq_printf(seq,
>> "\tNumber of Additional MAC address registers: %d\n",
>> priv->dma_cap.multi_addr);
>> + } else if (priv->plat->core_type == DWMAC_CORE_GMAC4) {
>> + seq_printf(seq,
>> + "\tNumber of MAC address registers (1-31): %d\n",
>> + priv->dma_cap.multi_addr);
>> + seq_printf(seq,
>> + "\tAdditional 32 MAC address registers (32-63): %s\n",
>> + priv->dma_cap.additional_32_addr ? "Y" : "N");
>> + seq_printf(seq,
>> + "\tAdditional 64 MAC address registers (64-127): %s\n",
>> + priv->dma_cap.additional_64_addr ? "Y" : "N");
>> + seq_printf(seq, "\tHash Filter: %s\n",
>> + (priv->dma_cap.hash_filter) ? "Y" : "N");
>
> hash_filter seems to be only set in dwmac1000_dma.c? So on dwmac4 it would always print N?
I stand corrected actually, after looking deeper, you're right :)
On dwmac1000, the feature bit 4 is HASHSEL, whereas on dwmac4, bit4 of HW_Features0 is
VLHASH, 2 different Hash tables :)
dwmac4 doesn't seem to have a bit just to say "there's a hash table", but instead directly
reports the sizeof of the hash table.
So I'll ditch that as you recommend, maybe in its own patch.
Maxime
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-09-01 6:37 ` Maxime Chevallier
@ 2026-09-01 12:21 ` Andrew Lunn
2026-09-01 12:27 ` Maxime Chevallier
0 siblings, 1 reply; 16+ messages in thread
From: Andrew Lunn @ 2026-09-01 12:21 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
On Tue, Sep 01, 2026 at 08:37:20AM +0200, Maxime Chevallier wrote:
> Hi,
>
> On 9/1/26 02:12, Andrew Lunn wrote:
> > On Mon, Aug 31, 2026 at 09:01:20AM +0200, Maxime Chevallier wrote:
> >> Contrary to dwmac1000 that gets its number of perfect filter entries
> >> through the 'snps,perfect-filter-entries' property, dwmac4 allows
> >> reading the filter size from the HW features registers.
> >
> > Does dwmac4 take any notice of "snps,perfect-filter-entries"? Should
> > it be marked deprecated?
>
> It's only used on :
>
> "st,spear600-gmac"
> "snps,dwmac-3.50a"
> "snps,dwmac-3.70a"
> "snps,dwmac-3.72a"
> "snps,dwmac"
>
> So, dwmac1000.
>
> I'd say, we can definitely deprecate on IPs that don't match these.
>
> Interestingly, there are _some_ dwmac4 devicetrees out there that use
> this property. It achieves nothing, and even worse, doesn't match what
> the HW reports :
>
> In arch/riscv/boot/dts/starfive/jh7110.dtsi for example :
>
> gmac1: ethernet@16040000 {
> compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
> [...]
> snps,perfect-filter-entries = <256>;
> }
So another thing for the TODO list, extend the YAML description to
make properties conditional on the IP core version, so the validator
tools will pick this up.
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-09-01 12:21 ` Andrew Lunn
@ 2026-09-01 12:27 ` Maxime Chevallier
2026-09-01 12:50 ` Andrew Lunn
0 siblings, 1 reply; 16+ messages in thread
From: Maxime Chevallier @ 2026-09-01 12:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
On 9/1/26 14:21, Andrew Lunn wrote:
> On Tue, Sep 01, 2026 at 08:37:20AM +0200, Maxime Chevallier wrote:
>> Hi,
>>
>> On 9/1/26 02:12, Andrew Lunn wrote:
>>> On Mon, Aug 31, 2026 at 09:01:20AM +0200, Maxime Chevallier wrote:
>>>> Contrary to dwmac1000 that gets its number of perfect filter entries
>>>> through the 'snps,perfect-filter-entries' property, dwmac4 allows
>>>> reading the filter size from the HW features registers.
>>>
>>> Does dwmac4 take any notice of "snps,perfect-filter-entries"? Should
>>> it be marked deprecated?
>>
>> It's only used on :
>>
>> "st,spear600-gmac"
>> "snps,dwmac-3.50a"
>> "snps,dwmac-3.70a"
>> "snps,dwmac-3.72a"
>> "snps,dwmac"
>>
>> So, dwmac1000.
>>
>> I'd say, we can definitely deprecate on IPs that don't match these.
>>
>> Interestingly, there are _some_ dwmac4 devicetrees out there that use
>> this property. It achieves nothing, and even worse, doesn't match what
>> the HW reports :
>>
>> In arch/riscv/boot/dts/starfive/jh7110.dtsi for example :
>>
>> gmac1: ethernet@16040000 {
>> compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
>> [...]
>> snps,perfect-filter-entries = <256>;
>> }
>
> So another thing for the TODO list, extend the YAML description to
> make properties conditional on the IP core version, so the validator
> tools will pick this up.
Looks like it yes. I'm starting to wonder if we should maintain this kind
of TODO list in the kdoc. I know these types of lists have a nasty
tendancy of falling into disrepair, but this could help.
Maxime
>
> Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities
2026-09-01 7:04 ` Maxime Chevallier
@ 2026-09-01 12:38 ` Andrew Lunn
0 siblings, 0 replies; 16+ messages in thread
From: Andrew Lunn @ 2026-09-01 12:38 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Nicolai Buchwitz, Andrew Lunn, Jakub Kicinski, davem,
Eric Dumazet, Paolo Abeni, Simon Horman, Maxime Coquelin,
Alexandre Torgue, Russell King, thomas.petazzoni,
Alexis Lothoré, netdev, linux-kernel, linux-arm-kernel,
linux-stm32
On Tue, Sep 01, 2026 at 09:04:28AM +0200, Maxime Chevallier wrote:
>
>
> On 9/1/26 02:26, Andrew Lunn wrote:
> >> Yeah but dwmac4 has a hash filter, but same as the UC filter it's just not plumbed
> >> in :/
> >>
> >> Let's leave this flag here, hash filter addition for MC filtering is coming-up, so let's not
> >> drop it now only to re-enable it after, one of the other wonderful discoveries found by
> >> running the selftests...
> >
> > I assume you can put a MC address in a perfect match filter? You can
> > perfectly match a multicast address just as well as a unicast address.
> >
> > The hash filter is less accurate, but again can be used to match a
> > unicast or multicast address, and then you need additional filtering
> > in software, which Linux will do.
> >
> > So it seems to me, you should use a perfect match filters if you have
> > one available, independent of unicast or multicast, and only use a
> > hash filter if you have run out of perfect match filters.
>
> That's an interesting point. The HW supports that, we have 3 control knobs
> for that in the MAC_PACKET_FILTER register :
>
> - HPF (bit 10) : Use Hash or Perfect Match for filtering.
> 0 : Match UC and MC against hash filter
> 1 : Match UC and MC according to HMC and HUC
>
> - HMC (bit 2) : Use Hash or Perfect Match for MC filtering
> 0 : Match MC against perfect filter
> 1 : Match MC against Hash table
>
> - HUC (bit 1) : Use Hash of PF for UC filtering
> 0 : Match UC against PF
> 1 : Match UC against Hash table
>
> I don't know though how this all interacts with the primary MAC address. We
> always have one entry in PF for the device's own MAC address, we should
> probably always perfect match that one.
Yes, i agree, the primary should be a perfect match.
> But as the UC Perfect Filter toggle is global for All UC addresses it means
> we're stuck with perfect filter for all UC then ?
> For MC, this is a good point, but I'm worried about the complexity vs gain.
>
> If we consider the 4 dwmac boards I have (may not be a very representative sample),
> we have :
>
> - imx8mp : 64 PF (Perfect Fitler) entries
> - jh7110 : 9 PF entries
> - stm32mp1 : 4 PF entries
> - yt6801 : 1 PF entry
I assume the imx8mp is using bank 1 and back 2? The designers of this
device seem to think the use cases for the device include lots of UC
and MC addresses.
Maybe, reserve bank 0 for UC, but allow both UC and MC in bank 1 and
2? That would allow imx8mp to make use of its hardware in an efficient
way, but it also keeps things simple and efficient for the more
restricted devices like the yt6801 and stm32mp1.
This discussion should however not effect this patchset. This sort of
optimisations can come later.
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter
2026-09-01 12:27 ` Maxime Chevallier
@ 2026-09-01 12:50 ` Andrew Lunn
0 siblings, 0 replies; 16+ messages in thread
From: Andrew Lunn @ 2026-09-01 12:50 UTC (permalink / raw)
To: Maxime Chevallier
Cc: Andrew Lunn, Jakub Kicinski, davem, Eric Dumazet, Paolo Abeni,
Simon Horman, Maxime Coquelin, Alexandre Torgue, Russell King,
thomas.petazzoni, Alexis Lothoré, netdev, linux-kernel,
linux-arm-kernel, linux-stm32
> Looks like it yes. I'm starting to wonder if we should maintain this
> kind of TODO list in the kdoc. I know these types of lists have a
> nasty tendancy of falling into disrepair, but this could help.
drivers/staging has such lists. You could follow that format.
Andrew
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-09-01 12:50 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 7:01 [PATCH net-next 0/2] net: stmmac: dwmac4: Auto-discover UC filter size Maxime Chevallier
2026-08-31 7:01 ` [PATCH net-next 1/2] net: stmmac: dwmac4: Read the UC filter size from hardware capabilities Maxime Chevallier
2026-08-31 12:04 ` Nicolai Buchwitz
2026-08-31 12:15 ` Maxime Chevallier
2026-08-31 12:26 ` Nicolai Buchwitz
2026-09-01 0:26 ` Andrew Lunn
2026-09-01 7:04 ` Maxime Chevallier
2026-09-01 12:38 ` Andrew Lunn
2026-09-01 7:08 ` Maxime Chevallier
2026-08-31 7:01 ` [PATCH net-next 2/2] net: stmmac: dwmac4: Use the full perfect filter ability for UC filter Maxime Chevallier
2026-08-31 12:06 ` Nicolai Buchwitz
2026-09-01 0:12 ` Andrew Lunn
2026-09-01 6:37 ` Maxime Chevallier
2026-09-01 12:21 ` Andrew Lunn
2026-09-01 12:27 ` Maxime Chevallier
2026-09-01 12:50 ` Andrew Lunn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox