Skip to content

Commit 4dbbe8d

Browse files
joabreudavem330
authored andcommitted
net: stmmac: Add support for U32 TC filter using Flexible RX Parser
This adds support for U32 filter by using an HW only feature called Flexible RX Parser. This allow us to match any given packet field with a pattern and accept/reject or even route the packet to a specific DMA channel. Right now we only support acception or rejection of frame and we only support simple rules. Though, the Parser has the flexibility of jumping to specific rules as an if condition so complex rules can be established. This is only supported in GMAC5.10+. The following commands can be used to test this code: 1) Setup an ingress qdisk: # tc qdisc add dev eth0 handle ffff: ingress 2) Setup a filter (e.g. filter by IP): # tc filter add dev eth0 parent ffff: protocol ip u32 match ip \ src 192.168.0.3 skip_sw action drop In every tests performed we always used the "skip_sw" flag to make sure only the RX Parser was involved. Signed-off-by: Jose Abreu <[email protected]> Cc: David S. Miller <[email protected]> Cc: Joao Pinto <[email protected]> Cc: Vitor Soares <[email protected]> Cc: Giuseppe Cavallaro <[email protected]> Cc: Alexandre Torgue <[email protected]> Cc: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b2641e2 commit 4dbbe8d

File tree

12 files changed

+636
-3
lines changed

12 files changed

+636
-3
lines changed

drivers/net/ethernet/stmicro/stmmac/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
55
dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o \
66
mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o \
77
dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
8-
$(stmmac-y)
8+
stmmac_tc.o $(stmmac-y)
99

1010
# Ordering matters. Generic driver must be last.
1111
obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o

drivers/net/ethernet/stmicro/stmmac/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ struct dma_features {
353353
unsigned int rx_fifo_size;
354354
/* Automotive Safety Package */
355355
unsigned int asp;
356+
/* RX Parser */
357+
unsigned int frpsel;
358+
unsigned int frpbs;
359+
unsigned int frpes;
356360
};
357361

358362
/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
@@ -412,6 +416,7 @@ struct mac_device_info {
412416
const struct stmmac_dma_ops *dma;
413417
const struct stmmac_mode_ops *mode;
414418
const struct stmmac_hwtimestamp *ptp;
419+
const struct stmmac_tc_ops *tc;
415420
struct mii_regs mii; /* MII register Addresses */
416421
struct mac_link link;
417422
void __iomem *pcsr; /* vpointer to device CSRs */

drivers/net/ethernet/stmicro/stmmac/dwmac4.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ enum power_event {
194194

195195
/* MAC HW features3 bitmap */
196196
#define GMAC_HW_FEAT_ASP GENMASK(29, 28)
197+
#define GMAC_HW_FEAT_FRPES GENMASK(14, 13)
198+
#define GMAC_HW_FEAT_FRPBS GENMASK(12, 11)
199+
#define GMAC_HW_FEAT_FRPSEL BIT(10)
197200

198201
/* MAC HW ADDR regs */
199202
#define GMAC_HI_DCS GENMASK(18, 16)
@@ -202,6 +205,7 @@ enum power_event {
202205

203206
/* MTL registers */
204207
#define MTL_OPERATION_MODE 0x00000c00
208+
#define MTL_FRPE BIT(15)
205209
#define MTL_OPERATION_SCHALG_MASK GENMASK(6, 5)
206210
#define MTL_OPERATION_SCHALG_WRR (0x0 << 5)
207211
#define MTL_OPERATION_SCHALG_WFQ (0x1 << 5)

drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ const struct stmmac_ops dwmac510_ops = {
795795
.safety_feat_config = dwmac5_safety_feat_config,
796796
.safety_feat_irq_status = dwmac5_safety_feat_irq_status,
797797
.safety_feat_dump = dwmac5_safety_feat_dump,
798+
.rxp_config = dwmac5_rxp_config,
798799
};
799800

800801
int dwmac4_setup(struct stmmac_priv *priv)

drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
379379

380380
/* 5.10 Features */
381381
dma_cap->asp = (hw_cap & GMAC_HW_FEAT_ASP) >> 28;
382+
dma_cap->frpes = (hw_cap & GMAC_HW_FEAT_FRPES) >> 13;
383+
dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
384+
dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
382385
}
383386

384387
/* Enable/disable TSO feature and set MSS */

drivers/net/ethernet/stmicro/stmmac/dwmac5.c

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "common.h"
88
#include "dwmac4.h"
99
#include "dwmac5.h"
10+
#include "stmmac.h"
1011

1112
struct dwmac5_error_desc {
1213
bool valid;
@@ -299,3 +300,197 @@ int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,
299300
*desc = dwmac5_all_errors[module].desc[offset].desc;
300301
return 0;
301302
}
303+
304+
static int dwmac5_rxp_disable(void __iomem *ioaddr)
305+
{
306+
u32 val;
307+
int ret;
308+
309+
val = readl(ioaddr + MTL_OPERATION_MODE);
310+
val &= ~MTL_FRPE;
311+
writel(val, ioaddr + MTL_OPERATION_MODE);
312+
313+
ret = readl_poll_timeout(ioaddr + MTL_RXP_CONTROL_STATUS, val,
314+
val & RXPI, 1, 10000);
315+
if (ret)
316+
return ret;
317+
return 0;
318+
}
319+
320+
static void dwmac5_rxp_enable(void __iomem *ioaddr)
321+
{
322+
u32 val;
323+
324+
val = readl(ioaddr + MTL_OPERATION_MODE);
325+
val |= MTL_FRPE;
326+
writel(val, ioaddr + MTL_OPERATION_MODE);
327+
}
328+
329+
static int dwmac5_rxp_update_single_entry(void __iomem *ioaddr,
330+
struct stmmac_tc_entry *entry,
331+
int pos)
332+
{
333+
int ret, i;
334+
335+
for (i = 0; i < (sizeof(entry->val) / sizeof(u32)); i++) {
336+
int real_pos = pos * (sizeof(entry->val) / sizeof(u32)) + i;
337+
u32 val;
338+
339+
/* Wait for ready */
340+
ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
341+
val, !(val & STARTBUSY), 1, 10000);
342+
if (ret)
343+
return ret;
344+
345+
/* Write data */
346+
val = *((u32 *)&entry->val + i);
347+
writel(val, ioaddr + MTL_RXP_IACC_DATA);
348+
349+
/* Write pos */
350+
val = real_pos & ADDR;
351+
writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
352+
353+
/* Write OP */
354+
val |= WRRDN;
355+
writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
356+
357+
/* Start Write */
358+
val |= STARTBUSY;
359+
writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
360+
361+
/* Wait for done */
362+
ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
363+
val, !(val & STARTBUSY), 1, 10000);
364+
if (ret)
365+
return ret;
366+
}
367+
368+
return 0;
369+
}
370+
371+
static struct stmmac_tc_entry *
372+
dwmac5_rxp_get_next_entry(struct stmmac_tc_entry *entries, unsigned int count,
373+
u32 curr_prio)
374+
{
375+
struct stmmac_tc_entry *entry;
376+
u32 min_prio = ~0x0;
377+
int i, min_prio_idx;
378+
bool found = false;
379+
380+
for (i = count - 1; i >= 0; i--) {
381+
entry = &entries[i];
382+
383+
/* Do not update unused entries */
384+
if (!entry->in_use)
385+
continue;
386+
/* Do not update already updated entries (i.e. fragments) */
387+
if (entry->in_hw)
388+
continue;
389+
/* Let last entry be updated last */
390+
if (entry->is_last)
391+
continue;
392+
/* Do not return fragments */
393+
if (entry->is_frag)
394+
continue;
395+
/* Check if we already checked this prio */
396+
if (entry->prio < curr_prio)
397+
continue;
398+
/* Check if this is the minimum prio */
399+
if (entry->prio < min_prio) {
400+
min_prio = entry->prio;
401+
min_prio_idx = i;
402+
found = true;
403+
}
404+
}
405+
406+
if (found)
407+
return &entries[min_prio_idx];
408+
return NULL;
409+
}
410+
411+
int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
412+
unsigned int count)
413+
{
414+
struct stmmac_tc_entry *entry, *frag;
415+
int i, ret, nve = 0;
416+
u32 curr_prio = 0;
417+
u32 old_val, val;
418+
419+
/* Force disable RX */
420+
old_val = readl(ioaddr + GMAC_CONFIG);
421+
val = old_val & ~GMAC_CONFIG_RE;
422+
writel(val, ioaddr + GMAC_CONFIG);
423+
424+
/* Disable RX Parser */
425+
ret = dwmac5_rxp_disable(ioaddr);
426+
if (ret)
427+
goto re_enable;
428+
429+
/* Set all entries as NOT in HW */
430+
for (i = 0; i < count; i++) {
431+
entry = &entries[i];
432+
entry->in_hw = false;
433+
}
434+
435+
/* Update entries by reverse order */
436+
while (1) {
437+
entry = dwmac5_rxp_get_next_entry(entries, count, curr_prio);
438+
if (!entry)
439+
break;
440+
441+
curr_prio = entry->prio;
442+
frag = entry->frag_ptr;
443+
444+
/* Set special fragment requirements */
445+
if (frag) {
446+
entry->val.af = 0;
447+
entry->val.rf = 0;
448+
entry->val.nc = 1;
449+
entry->val.ok_index = nve + 2;
450+
}
451+
452+
ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
453+
if (ret)
454+
goto re_enable;
455+
456+
entry->table_pos = nve++;
457+
entry->in_hw = true;
458+
459+
if (frag && !frag->in_hw) {
460+
ret = dwmac5_rxp_update_single_entry(ioaddr, frag, nve);
461+
if (ret)
462+
goto re_enable;
463+
frag->table_pos = nve++;
464+
frag->in_hw = true;
465+
}
466+
}
467+
468+
if (!nve)
469+
goto re_enable;
470+
471+
/* Update all pass entry */
472+
for (i = 0; i < count; i++) {
473+
entry = &entries[i];
474+
if (!entry->is_last)
475+
continue;
476+
477+
ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
478+
if (ret)
479+
goto re_enable;
480+
481+
entry->table_pos = nve++;
482+
}
483+
484+
/* Assume n. of parsable entries == n. of valid entries */
485+
val = (nve << 16) & NPE;
486+
val |= nve & NVE;
487+
writel(val, ioaddr + MTL_RXP_CONTROL_STATUS);
488+
489+
/* Enable RX Parser */
490+
dwmac5_rxp_enable(ioaddr);
491+
492+
re_enable:
493+
/* Re-enable RX */
494+
writel(old_val, ioaddr + GMAC_CONFIG);
495+
return ret;
496+
}

drivers/net/ethernet/stmicro/stmmac/dwmac5.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111
#define PRTYEN BIT(1)
1212
#define TMOUTEN BIT(0)
1313

14+
#define MTL_RXP_CONTROL_STATUS 0x00000ca0
15+
#define RXPI BIT(31)
16+
#define NPE GENMASK(23, 16)
17+
#define NVE GENMASK(7, 0)
18+
#define MTL_RXP_IACC_CTRL_STATUS 0x00000cb0
19+
#define STARTBUSY BIT(31)
20+
#define RXPEIEC GENMASK(22, 21)
21+
#define RXPEIEE BIT(20)
22+
#define WRRDN BIT(16)
23+
#define ADDR GENMASK(15, 0)
24+
#define MTL_RXP_IACC_DATA 0x00000cb4
1425
#define MTL_ECC_CONTROL 0x00000cc0
1526
#define TSOEE BIT(4)
1627
#define MRXPEE BIT(3)
@@ -48,5 +59,7 @@ int dwmac5_safety_feat_irq_status(struct net_device *ndev,
4859
struct stmmac_safety_stats *stats);
4960
int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,
5061
int index, unsigned long *count, const char **desc);
62+
int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
63+
unsigned int count);
5164

5265
#endif /* __DWMAC5_H__ */

drivers/net/ethernet/stmicro/stmmac/hwif.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static const struct stmmac_hwif_entry {
7777
const void *mac;
7878
const void *hwtimestamp;
7979
const void *mode;
80+
const void *tc;
8081
int (*setup)(struct stmmac_priv *priv);
8182
int (*quirks)(struct stmmac_priv *priv);
8283
} stmmac_hw[] = {
@@ -90,6 +91,7 @@ static const struct stmmac_hwif_entry {
9091
.mac = &dwmac100_ops,
9192
.hwtimestamp = &stmmac_ptp,
9293
.mode = NULL,
94+
.tc = NULL,
9395
.setup = dwmac100_setup,
9496
.quirks = stmmac_dwmac1_quirks,
9597
}, {
@@ -101,6 +103,7 @@ static const struct stmmac_hwif_entry {
101103
.mac = &dwmac1000_ops,
102104
.hwtimestamp = &stmmac_ptp,
103105
.mode = NULL,
106+
.tc = NULL,
104107
.setup = dwmac1000_setup,
105108
.quirks = stmmac_dwmac1_quirks,
106109
}, {
@@ -112,6 +115,7 @@ static const struct stmmac_hwif_entry {
112115
.mac = &dwmac4_ops,
113116
.hwtimestamp = &stmmac_ptp,
114117
.mode = NULL,
118+
.tc = NULL,
115119
.setup = dwmac4_setup,
116120
.quirks = stmmac_dwmac4_quirks,
117121
}, {
@@ -123,6 +127,7 @@ static const struct stmmac_hwif_entry {
123127
.mac = &dwmac410_ops,
124128
.hwtimestamp = &stmmac_ptp,
125129
.mode = &dwmac4_ring_mode_ops,
130+
.tc = NULL,
126131
.setup = dwmac4_setup,
127132
.quirks = NULL,
128133
}, {
@@ -134,6 +139,7 @@ static const struct stmmac_hwif_entry {
134139
.mac = &dwmac410_ops,
135140
.hwtimestamp = &stmmac_ptp,
136141
.mode = &dwmac4_ring_mode_ops,
142+
.tc = NULL,
137143
.setup = dwmac4_setup,
138144
.quirks = NULL,
139145
}, {
@@ -145,6 +151,7 @@ static const struct stmmac_hwif_entry {
145151
.mac = &dwmac510_ops,
146152
.hwtimestamp = &stmmac_ptp,
147153
.mode = &dwmac4_ring_mode_ops,
154+
.tc = &dwmac510_tc_ops,
148155
.setup = dwmac4_setup,
149156
.quirks = NULL,
150157
}
@@ -196,6 +203,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
196203
mac->mac = entry->mac;
197204
mac->ptp = entry->hwtimestamp;
198205
mac->mode = entry->mode;
206+
mac->tc = entry->tc;
199207

200208
priv->hw = mac;
201209

0 commit comments

Comments
 (0)