aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c')
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c1174
1 files changed, 300 insertions, 874 deletions
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
index 41d935d1aaf6..8e7d4046cc4a 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
@@ -22,302 +22,302 @@
} \
}
-static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
+static struct mvpp2_cls_flow cls_flows[MVPP2_N_FLOWS] = {
/* TCP over IPv4 flows, Not fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* TCP over IPv4 flows, Not fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
/* TCP over IPv4 flows, fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* TCP over IPv4 flows, fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V4_FLOW, MVPP2_FL_IP4_TCP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
/* UDP over IPv4 flows, Not fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_UNTAG,
MVPP22_CLS_HEK_IP4_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* UDP over IPv4 flows, Not fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
- MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_NF_TAG,
+ MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
/* UDP over IPv4 flows, fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* UDP over IPv4 flows, fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V4_FLOW, MVPP2_FL_IP4_UDP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
/* TCP over IPv6 flows, not fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_NF_UNTAG,
MVPP22_CLS_HEK_IP6_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_NF_UNTAG,
MVPP22_CLS_HEK_IP6_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* TCP over IPv6 flows, not fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG,
- MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_NF_TAG,
+ MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG,
- MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_NF_TAG,
+ MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
/* TCP over IPv6 flows, fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* TCP over IPv6 flows, fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(TCP_V6_FLOW, MVPP2_FL_IP6_TCP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE |
MVPP2_PRS_RI_L4_TCP,
MVPP2_PRS_IP_MASK),
/* UDP over IPv6 flows, not fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_NF_UNTAG,
MVPP22_CLS_HEK_IP6_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_NF_UNTAG,
MVPP22_CLS_HEK_IP6_5T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* UDP over IPv6 flows, not fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG,
- MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_NF_TAG,
+ MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG,
- MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_NF_TAG,
+ MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
/* UDP over IPv6 flows, fragmented, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
/* UDP over IPv6 flows, fragmented, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(UDP_V6_FLOW, MVPP2_FL_IP6_UDP_FRAG_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE |
MVPP2_PRS_RI_L4_UDP,
MVPP2_PRS_IP_MASK),
/* IPv4 flows, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4,
MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT,
MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_UNTAG,
MVPP22_CLS_HEK_IP4_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER,
MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
/* IPv4 flows, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4,
MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OPT,
MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
- MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(IPV4_FLOW, MVPP2_FL_IP4_TAG,
+ MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP4_OTHER,
MVPP2_PRS_RI_L3_PROTO_MASK),
/* IPv6 flows, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG,
+ MVPP2_DEF_FLOW(IPV6_FLOW, MVPP2_FL_IP6_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6,
MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG,
+ MVPP2_DEF_FLOW(IPV6_FLOW, MVPP2_FL_IP6_UNTAG,
MVPP22_CLS_HEK_IP6_2T,
MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6,
MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
/* IPv6 flows, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(IPV6_FLOW, MVPP2_FL_IP6_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6,
MVPP2_PRS_RI_L3_PROTO_MASK),
- MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG,
- MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
+ MVPP2_DEF_FLOW(IPV6_FLOW, MVPP2_FL_IP6_TAG,
+ MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_OPT_VLAN,
MVPP2_PRS_RI_L3_IP6,
MVPP2_PRS_RI_L3_PROTO_MASK),
/* Non IP flow, no vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_UNTAG,
+ MVPP2_DEF_FLOW(ETHER_FLOW, MVPP2_FL_NON_IP_UNTAG,
0,
MVPP2_PRS_RI_VLAN_NONE,
MVPP2_PRS_RI_VLAN_MASK),
/* Non IP flow, with vlan tag */
- MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG,
+ MVPP2_DEF_FLOW(ETHER_FLOW, MVPP2_FL_NON_IP_TAG,
MVPP22_CLS_HEK_OPT_VLAN,
0, 0),
};
@@ -344,9 +344,9 @@ static void mvpp2_cls_flow_write(struct mvpp2 *priv,
struct mvpp2_cls_flow_entry *fe)
{
mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
- mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
- mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
- mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
+ mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
}
u32 mvpp2_cls_lookup_hits(struct mvpp2 *priv, int index)
@@ -436,6 +436,19 @@ static void mvpp2_cls_flow_last_set(struct mvpp2_cls_flow_entry *fe,
fe->data[0] |= !!is_last;
}
+static bool mvpp2_cls_flow_last_get(struct mvpp2_cls_flow_entry *fe)
+{
+ return (fe->data[0] & MVPP2_CLS_FLOW_TBL0_LAST);
+}
+
+static void mvpp2_cls_flow_lkp_type_set(struct mvpp2_cls_flow_entry *fe,
+ int lkp_type)
+{
+ fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_LKP_TYPE(
+ MVPP2_CLS_FLOW_TBL1_LKP_TYPE_MASK);
+ fe->data[1] |= MVPP2_CLS_FLOW_TBL1_LKP_TYPE(lkp_type);
+}
+
static void mvpp2_cls_flow_pri_set(struct mvpp2_cls_flow_entry *fe, int prio)
{
fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_PRIO(MVPP2_CLS_FLOW_TBL1_PRIO_MASK);
@@ -448,22 +461,14 @@ static void mvpp2_cls_flow_port_add(struct mvpp2_cls_flow_entry *fe,
fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID(port);
}
-static void mvpp2_cls_flow_port_remove(struct mvpp2_cls_flow_entry *fe,
- u32 port)
-{
- fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID(port);
-}
-
-static void mvpp2_cls_flow_lu_type_set(struct mvpp2_cls_flow_entry *fe,
- u8 lu_type)
+static int mvpp2_cls_flow_port_get(struct mvpp2_cls_flow_entry *fe)
{
- fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK);
- fe->data[1] |= MVPP2_CLS_FLOW_TBL1_LU_TYPE(lu_type);
+ return ((fe->data[0] >> 4) & MVPP2_CLS_FLOW_TBL0_PORT_ID_MASK);
}
/* Initialize the parser entry for the given flow */
static void mvpp2_cls_flow_prs_init(struct mvpp2 *priv,
- const struct mvpp2_cls_flow *flow)
+ struct mvpp2_cls_flow *flow)
{
mvpp2_prs_add_flow(priv, flow->flow_id, flow->prs_ri.ri,
flow->prs_ri.ri_mask);
@@ -471,7 +476,7 @@ static void mvpp2_cls_flow_prs_init(struct mvpp2 *priv,
/* Initialize the Lookup Id table entry for the given flow */
static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
- const struct mvpp2_cls_flow *flow)
+ struct mvpp2_cls_flow *flow)
{
struct mvpp2_cls_lookup_entry le;
@@ -484,7 +489,7 @@ static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
/* We point on the first lookup in the sequence for the flow, that is
* the C2 lookup.
*/
- le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_CLS_FLT_FIRST(flow->flow_id));
+ le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_FLOW_C2_ENTRY(flow->flow_id));
/* CLS is always enabled, RSS is enabled/disabled in C2 lookup */
le.data |= MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
@@ -492,113 +497,21 @@ static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
mvpp2_cls_lookup_write(priv, &le);
}
-static void mvpp2_cls_c2_write(struct mvpp2 *priv,
- struct mvpp2_cls_c2_entry *c2)
-{
- u32 val;
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index);
-
- val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
- if (c2->valid)
- val &= ~MVPP22_CLS_C2_TCAM_INV_BIT;
- else
- val |= MVPP22_CLS_C2_TCAM_INV_BIT;
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_INV, val);
-
- mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act);
-
- mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]);
- mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]);
- mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]);
- mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]);
-
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]);
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]);
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]);
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]);
- /* Writing TCAM_DATA4 flushes writes to TCAM_DATA0-4 and INV to HW */
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]);
-}
-
-void mvpp2_cls_c2_read(struct mvpp2 *priv, int index,
- struct mvpp2_cls_c2_entry *c2)
-{
- u32 val;
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);
-
- c2->index = index;
-
- c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0);
- c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1);
- c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2);
- c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3);
- c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4);
-
- c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT);
-
- c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0);
- c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1);
- c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2);
- c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3);
-
- val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
- c2->valid = !(val & MVPP22_CLS_C2_TCAM_INV_BIT);
-}
-
-static int mvpp2_cls_ethtool_flow_to_type(int flow_type)
-{
- switch (flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) {
- case ETHER_FLOW:
- return MVPP22_FLOW_ETHERNET;
- case TCP_V4_FLOW:
- return MVPP22_FLOW_TCP4;
- case TCP_V6_FLOW:
- return MVPP22_FLOW_TCP6;
- case UDP_V4_FLOW:
- return MVPP22_FLOW_UDP4;
- case UDP_V6_FLOW:
- return MVPP22_FLOW_UDP6;
- case IPV4_FLOW:
- return MVPP22_FLOW_IP4;
- case IPV6_FLOW:
- return MVPP22_FLOW_IP6;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static int mvpp2_cls_c2_port_flow_index(struct mvpp2_port *port, int loc)
-{
- return MVPP22_CLS_C2_RFS_LOC(port->id, loc);
-}
-
/* Initialize the flow table entries for the given flow */
-static void mvpp2_cls_flow_init(struct mvpp2 *priv,
- const struct mvpp2_cls_flow *flow)
+static void mvpp2_cls_flow_init(struct mvpp2 *priv, struct mvpp2_cls_flow *flow)
{
struct mvpp2_cls_flow_entry fe;
- int i, pri = 0;
-
- /* Assign default values to all entries in the flow */
- for (i = MVPP2_CLS_FLT_FIRST(flow->flow_id);
- i <= MVPP2_CLS_FLT_LAST(flow->flow_id); i++) {
- memset(&fe, 0, sizeof(fe));
- fe.index = i;
- mvpp2_cls_flow_pri_set(&fe, pri++);
-
- if (i == MVPP2_CLS_FLT_LAST(flow->flow_id))
- mvpp2_cls_flow_last_set(&fe, 1);
-
- mvpp2_cls_flow_write(priv, &fe);
- }
+ int i;
- /* RSS config C2 lookup */
- mvpp2_cls_flow_read(priv, MVPP2_CLS_FLT_C2_RSS_ENTRY(flow->flow_id),
- &fe);
+ /* C2 lookup */
+ memset(&fe, 0, sizeof(fe));
+ fe.index = MVPP2_FLOW_C2_ENTRY(flow->flow_id);
mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C2);
mvpp2_cls_flow_port_id_sel(&fe, true);
- mvpp2_cls_flow_lu_type_set(&fe, MVPP22_CLS_LU_TYPE_ALL);
+ mvpp2_cls_flow_last_set(&fe, 0);
+ mvpp2_cls_flow_pri_set(&fe, 0);
+ mvpp2_cls_flow_lkp_type_set(&fe, MVPP2_CLS_LKP_DEFAULT);
/* Add all ports */
for (i = 0; i < MVPP2_MAX_PORTS; i++)
@@ -608,19 +521,22 @@ static void mvpp2_cls_flow_init(struct mvpp2 *priv,
/* C3Hx lookups */
for (i = 0; i < MVPP2_MAX_PORTS; i++) {
- mvpp2_cls_flow_read(priv,
- MVPP2_CLS_FLT_HASH_ENTRY(i, flow->flow_id),
- &fe);
+ memset(&fe, 0, sizeof(fe));
+ fe.index = MVPP2_PORT_FLOW_INDEX(i, flow->flow_id);
- /* Set a default engine. Will be overwritten when setting the
- * real HEK parameters
- */
mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C3HA);
mvpp2_cls_flow_port_id_sel(&fe, true);
+ mvpp2_cls_flow_pri_set(&fe, i + 1);
mvpp2_cls_flow_port_add(&fe, BIT(i));
+ mvpp2_cls_flow_lkp_type_set(&fe, MVPP2_CLS_LKP_HASH);
mvpp2_cls_flow_write(priv, &fe);
}
+
+ /* Update the last entry */
+ mvpp2_cls_flow_last_set(&fe, 1);
+
+ mvpp2_cls_flow_write(priv, &fe);
}
/* Adds a field to the Header Extracted Key generation parameters*/
@@ -639,6 +555,20 @@ static int mvpp2_flow_add_hek_field(struct mvpp2_cls_flow_entry *fe,
return 0;
}
+static void mvpp2_cls_c2_inv_set(struct mvpp2 *priv,
+ int index)
+{
+ /* write index reg */
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);
+
+ /* set invalid bit */
+ mvpp2_write(priv, MVPP2_CLS2_TCAM_INV_REG,
+ (1 << MVPP2_CLS2_TCAM_INV_INVALID));
+
+ /* trigger */
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, 0);
+}
+
static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,
unsigned long hash_opts)
{
@@ -651,15 +581,9 @@ static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,
for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
switch (BIT(i)) {
- case MVPP22_CLS_HEK_OPT_MAC_DA:
- field_id = MVPP22_CLS_FIELD_MAC_DA;
- break;
case MVPP22_CLS_HEK_OPT_VLAN:
field_id = MVPP22_CLS_FIELD_VLAN;
break;
- case MVPP22_CLS_HEK_OPT_VLAN_PRI:
- field_id = MVPP22_CLS_FIELD_VLAN_PRI;
- break;
case MVPP22_CLS_HEK_OPT_IP4SA:
field_id = MVPP22_CLS_FIELD_IP4SA;
break;
@@ -688,36 +612,42 @@ static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,
return 0;
}
-/* Returns the size, in bits, of the corresponding HEK field */
-static int mvpp2_cls_hek_field_size(u32 field)
+struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
{
- switch (field) {
- case MVPP22_CLS_HEK_OPT_MAC_DA:
- return 48;
- case MVPP22_CLS_HEK_OPT_VLAN:
- return 12;
- case MVPP22_CLS_HEK_OPT_VLAN_PRI:
- return 3;
- case MVPP22_CLS_HEK_OPT_IP4SA:
- case MVPP22_CLS_HEK_OPT_IP4DA:
- return 32;
- case MVPP22_CLS_HEK_OPT_IP6SA:
- case MVPP22_CLS_HEK_OPT_IP6DA:
- return 128;
- case MVPP22_CLS_HEK_OPT_L4SIP:
- case MVPP22_CLS_HEK_OPT_L4DIP:
- return 16;
- default:
- return -1;
- }
+ if (flow >= MVPP2_N_FLOWS)
+ return NULL;
+
+ return &cls_flows[flow];
}
-const struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
+int mvpp2_cls_flow_hash_find(struct mvpp2_port *port,
+ struct mvpp2_cls_flow *flow,
+ struct mvpp2_cls_flow_entry *fe,
+ int *flow_index)
{
- if (flow >= MVPP2_N_PRS_FLOWS)
- return NULL;
+ int engine, flow_offset, port_bm, idx = 0, is_last = 0;
- return &cls_flows[flow];
+ flow_offset = 0;
+ do {
+ idx = MVPP2_PORT_FLOW_INDEX(flow_offset, flow->flow_id);
+ if (idx >= MVPP2_CLS_FLOWS_TBL_SIZE)
+ break;
+ mvpp2_cls_flow_read(port->priv, idx, fe);
+ engine = mvpp2_cls_flow_eng_get(fe);
+ port_bm = mvpp2_cls_flow_port_get(fe);
+ is_last = mvpp2_cls_flow_last_get(fe);
+ if ((engine == MVPP22_CLS_ENGINE_C3HA ||
+ engine == MVPP22_CLS_ENGINE_C3HB) &&
+ (port_bm & BIT(port->id)))
+ break;
+ flow_offset++;
+ } while (!is_last);
+
+ *flow_index = idx;
+ if (is_last)
+ return -EINVAL;
+
+ return 0;
}
/* Set the hash generation options for the given traffic flow.
@@ -734,17 +664,21 @@ const struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
static int mvpp2_port_rss_hash_opts_set(struct mvpp2_port *port, int flow_type,
u16 requested_opts)
{
- const struct mvpp2_cls_flow *flow;
struct mvpp2_cls_flow_entry fe;
+ struct mvpp2_cls_flow *flow;
int i, engine, flow_index;
u16 hash_opts;
- for_each_cls_flow_id_with_type(i, flow_type) {
+ for (i = 0; i < MVPP2_N_FLOWS; i++) {
flow = mvpp2_cls_flow_get(i);
if (!flow)
return -EINVAL;
- flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);
+ if (flow->flow_type != flow_type)
+ continue;
+
+ if (mvpp2_cls_flow_hash_find(port, flow, &fe, &flow_index))
+ return -EINVAL;
mvpp2_cls_flow_read(port->priv, flow_index, &fe);
@@ -786,9 +720,6 @@ u16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe)
case MVPP22_CLS_FIELD_VLAN:
hash_opts |= MVPP22_CLS_HEK_OPT_VLAN;
break;
- case MVPP22_CLS_FIELD_VLAN_PRI:
- hash_opts |= MVPP22_CLS_HEK_OPT_VLAN_PRI;
- break;
case MVPP22_CLS_FIELD_L3_PROTO:
hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO;
break;
@@ -822,17 +753,21 @@ u16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe)
*/
static u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type)
{
- const struct mvpp2_cls_flow *flow;
struct mvpp2_cls_flow_entry fe;
+ struct mvpp2_cls_flow *flow;
int i, flow_index;
u16 hash_opts = 0;
- for_each_cls_flow_id_with_type(i, flow_type) {
+ for (i = 0; i < MVPP2_N_FLOWS; i++) {
flow = mvpp2_cls_flow_get(i);
if (!flow)
return 0;
- flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);
+ if (flow->flow_type != flow_type)
+ continue;
+
+ if (mvpp2_cls_flow_hash_find(port, flow, &fe, &flow_index))
+ return 0;
mvpp2_cls_flow_read(port->priv, flow_index, &fe);
@@ -844,10 +779,10 @@ static u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type)
static void mvpp2_cls_port_init_flows(struct mvpp2 *priv)
{
- const struct mvpp2_cls_flow *flow;
+ struct mvpp2_cls_flow *flow;
int i;
- for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
+ for (i = 0; i < MVPP2_N_FLOWS; i++) {
flow = mvpp2_cls_flow_get(i);
if (!flow)
break;
@@ -858,6 +793,51 @@ static void mvpp2_cls_port_init_flows(struct mvpp2 *priv)
}
}
+static void mvpp2_cls_c2_write(struct mvpp2 *priv,
+ struct mvpp2_cls_c2_entry *c2)
+{
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index);
+
+ mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act);
+
+ mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]);
+ mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]);
+ mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]);
+ mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]);
+
+ /* write valid bit*/
+ mvpp2_write(priv, MVPP2_CLS2_TCAM_INV_REG,
+ (0 << MVPP2_CLS2_TCAM_INV_INVALID));
+
+ /* Write TCAM */
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]);
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]);
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]);
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]);
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]);
+}
+
+void mvpp2_cls_c2_read(struct mvpp2 *priv, int index,
+ struct mvpp2_cls_c2_entry *c2)
+{
+ mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);
+
+ c2->index = index;
+
+ c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0);
+ c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1);
+ c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2);
+ c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3);
+ c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4);
+
+ c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT);
+
+ c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0);
+ c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1);
+ c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2);
+ c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3);
+}
+
static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
{
struct mvpp2_cls_c2_entry c2;
@@ -871,9 +851,9 @@ static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));
- /* Match on Lookup Type */
- c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
- c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(MVPP22_CLS_LU_TYPE_ALL);
+ /* Set lkp_type */
+ c2.tcam[4] |= MVPP22_CLS_C2_LKP_TYPE(MVPP2_CLS_LKP_DEFAULT);
+ c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LKP_TYPE_MASK);
/* Update RSS status after matching this entry */
c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);
@@ -893,17 +873,27 @@ static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
MVPP22_CLS_C2_ATTR0_QLOW(ql);
- c2.valid = true;
-
mvpp2_cls_c2_write(port->priv, &c2);
}
+static void mvpp2_cls_c2_init(struct mvpp2 *priv)
+{
+ int index;
+
+ /* Toggle C2 from Built-In Self-Test mode to Functional mode */
+ mvpp2_write(priv, MVPP2_CLS2_TCAM_CTRL_REG,
+ MVPP2_CLS2_TCAM_CTRL_BYPASS_FIFO_STAGES);
+
+ /* Invalidate all C2 entries */
+ for (index = 0; index < MVPP22_CLS_C2_MAX_ENTRIES; index++)
+ mvpp2_cls_c2_inv_set(priv, index);
+}
+
/* Classifier default initialization */
void mvpp2_cls_init(struct mvpp2 *priv)
{
struct mvpp2_cls_lookup_entry le;
struct mvpp2_cls_flow_entry fe;
- struct mvpp2_cls_c2_entry c2;
int index;
/* Enable classifier */
@@ -927,21 +917,15 @@ void mvpp2_cls_init(struct mvpp2 *priv)
mvpp2_cls_lookup_write(priv, &le);
}
- /* Clear C2 TCAM engine table */
- memset(&c2, 0, sizeof(c2));
- c2.valid = false;
- for (index = 0; index < MVPP22_CLS_C2_N_ENTRIES; index++) {
- c2.index = index;
- mvpp2_cls_c2_write(priv, &c2);
- }
-
- /* Disable the FIFO stages in C2 engine, which are only used in BIST
- * mode
+ /* Clear CLS_SWFWD_PCTRL register - value of QueueHigh is defined by
+ * the Classifier
*/
- mvpp2_write(priv, MVPP22_CLS_C2_TCAM_CTRL,
- MVPP22_CLS_C2_TCAM_BYPASS_FIFO);
+ mvpp2_write(priv, MVPP2_CLS_SWFWD_PCTRL_REG, 0);
mvpp2_cls_port_init_flows(priv);
+
+ /* Initialize C2 */
+ mvpp2_cls_c2_init(priv);
}
void mvpp2_cls_port_config(struct mvpp2_port *port)
@@ -981,22 +965,12 @@ u32 mvpp2_cls_c2_hit_count(struct mvpp2 *priv, int c2_index)
return mvpp2_read(priv, MVPP22_CLS_C2_HIT_CTR);
}
-static void mvpp2_rss_port_c2_enable(struct mvpp2_port *port, u32 ctx)
+static void mvpp2_rss_port_c2_enable(struct mvpp2_port *port)
{
struct mvpp2_cls_c2_entry c2;
- u8 qh, ql;
mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2);
- /* The RxQ number is used to select the RSS table. It that case, we set
- * it to be the ctx number.
- */
- qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
- ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
-
- c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
- MVPP22_CLS_C2_ATTR0_QLOW(ql);
-
c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN;
mvpp2_cls_c2_write(port->priv, &c2);
@@ -1005,446 +979,29 @@ static void mvpp2_rss_port_c2_enable(struct mvpp2_port *port, u32 ctx)
static void mvpp2_rss_port_c2_disable(struct mvpp2_port *port)
{
struct mvpp2_cls_c2_entry c2;
- u8 qh, ql;
mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2);
- /* Reset the default destination RxQ to the port's first rx queue. */
- qh = (port->first_rxq >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
- ql = port->first_rxq & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
-
- c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
- MVPP22_CLS_C2_ATTR0_QLOW(ql);
-
c2.attr[2] &= ~MVPP22_CLS_C2_ATTR2_RSS_EN;
mvpp2_cls_c2_write(port->priv, &c2);
}
-static inline int mvpp22_rss_ctx(struct mvpp2_port *port, int port_rss_ctx)
-{
- return port->rss_ctx[port_rss_ctx];
-}
-
-int mvpp22_port_rss_enable(struct mvpp2_port *port)
+void mvpp22_rss_enable(struct mvpp2_port *port)
{
- if (mvpp22_rss_ctx(port, 0) < 0)
- return -EINVAL;
-
- mvpp2_rss_port_c2_enable(port, mvpp22_rss_ctx(port, 0));
-
- return 0;
+ mvpp2_rss_port_c2_enable(port);
}
-int mvpp22_port_rss_disable(struct mvpp2_port *port)
+void mvpp22_rss_disable(struct mvpp2_port *port)
{
- if (mvpp22_rss_ctx(port, 0) < 0)
- return -EINVAL;
-
mvpp2_rss_port_c2_disable(port);
-
- return 0;
-}
-
-static void mvpp22_port_c2_lookup_disable(struct mvpp2_port *port, int entry)
-{
- struct mvpp2_cls_c2_entry c2;
-
- mvpp2_cls_c2_read(port->priv, entry, &c2);
-
- /* Clear the port map so that the entry doesn't match anymore */
- c2.tcam[4] &= ~(MVPP22_CLS_C2_PORT_ID(BIT(port->id)));
-
- mvpp2_cls_c2_write(port->priv, &c2);
}
/* Set CPU queue number for oversize packets */
void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
{
- u32 val;
-
mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id),
port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
-
- mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
- (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
-
- val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
- val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
- mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
-}
-
-static int mvpp2_port_c2_tcam_rule_add(struct mvpp2_port *port,
- struct mvpp2_rfs_rule *rule)
-{
- struct flow_action_entry *act;
- struct mvpp2_cls_c2_entry c2;
- u8 qh, ql, pmap;
- int index, ctx;
-
- if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL))
- return -EOPNOTSUPP;
-
- memset(&c2, 0, sizeof(c2));
-
- index = mvpp2_cls_c2_port_flow_index(port, rule->loc);
- if (index < 0)
- return -EINVAL;
- c2.index = index;
-
- act = &rule->flow->action.entries[0];
-
- rule->c2_index = c2.index;
-
- c2.tcam[3] = (rule->c2_tcam & 0xffff) |
- ((rule->c2_tcam_mask & 0xffff) << 16);
- c2.tcam[2] = ((rule->c2_tcam >> 16) & 0xffff) |
- (((rule->c2_tcam_mask >> 16) & 0xffff) << 16);
- c2.tcam[1] = ((rule->c2_tcam >> 32) & 0xffff) |
- (((rule->c2_tcam_mask >> 32) & 0xffff) << 16);
- c2.tcam[0] = ((rule->c2_tcam >> 48) & 0xffff) |
- (((rule->c2_tcam_mask >> 48) & 0xffff) << 16);
-
- pmap = BIT(port->id);
- c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
- c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));
-
- /* Match on Lookup Type */
- c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
- c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(rule->loc);
-
- if (act->id == FLOW_ACTION_DROP) {
- c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_RED_LOCK);
- } else {
- /* We want to keep the default color derived from the Header
- * Parser drop entries, for VLAN and MAC filtering. This will
- * assign a default color of Green or Red, and we want matches
- * with a non-drop action to keep that color.
- */
- c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_NO_UPD_LOCK);
-
- /* Update RSS status after matching this entry */
- if (act->queue.ctx)
- c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN;
-
- /* Always lock the RSS_EN decision. We might have high prio
- * rules steering to an RXQ, and a lower one steering to RSS,
- * we don't want the low prio RSS rule overwriting this flag.
- */
- c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);
-
- /* Mark packet as "forwarded to software", needed for RSS */
- c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK);
-
- c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD_LOCK) |
- MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD_LOCK);
-
- if (act->queue.ctx) {
- /* Get the global ctx number */
- ctx = mvpp22_rss_ctx(port, act->queue.ctx);
- if (ctx < 0)
- return -EINVAL;
-
- qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
- ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
- } else {
- qh = ((act->queue.index + port->first_rxq) >> 3) &
- MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
- ql = (act->queue.index + port->first_rxq) &
- MVPP22_CLS_C2_ATTR0_QLOW_MASK;
- }
-
- c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
- MVPP22_CLS_C2_ATTR0_QLOW(ql);
- }
-
- c2.valid = true;
-
- mvpp2_cls_c2_write(port->priv, &c2);
-
- return 0;
-}
-
-static int mvpp2_port_c2_rfs_rule_insert(struct mvpp2_port *port,
- struct mvpp2_rfs_rule *rule)
-{
- return mvpp2_port_c2_tcam_rule_add(port, rule);
-}
-
-static int mvpp2_port_cls_rfs_rule_remove(struct mvpp2_port *port,
- struct mvpp2_rfs_rule *rule)
-{
- const struct mvpp2_cls_flow *flow;
- struct mvpp2_cls_flow_entry fe;
- int index, i;
-
- for_each_cls_flow_id_containing_type(i, rule->flow_type) {
- flow = mvpp2_cls_flow_get(i);
- if (!flow)
- return 0;
-
- index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
-
- mvpp2_cls_flow_read(port->priv, index, &fe);
- mvpp2_cls_flow_port_remove(&fe, BIT(port->id));
- mvpp2_cls_flow_write(port->priv, &fe);
- }
-
- if (rule->c2_index >= 0)
- mvpp22_port_c2_lookup_disable(port, rule->c2_index);
-
- return 0;
-}
-
-static int mvpp2_port_flt_rfs_rule_insert(struct mvpp2_port *port,
- struct mvpp2_rfs_rule *rule)
-{
- const struct mvpp2_cls_flow *flow;
- struct mvpp2 *priv = port->priv;
- struct mvpp2_cls_flow_entry fe;
- int index, ret, i;
-
- if (rule->engine != MVPP22_CLS_ENGINE_C2)
- return -EOPNOTSUPP;
-
- ret = mvpp2_port_c2_rfs_rule_insert(port, rule);
- if (ret)
- return ret;
-
- for_each_cls_flow_id_containing_type(i, rule->flow_type) {
- flow = mvpp2_cls_flow_get(i);
- if (!flow)
- return 0;
-
- if ((rule->hek_fields & flow->supported_hash_opts) != rule->hek_fields)
- continue;
-
- index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
-
- mvpp2_cls_flow_read(priv, index, &fe);
- mvpp2_cls_flow_eng_set(&fe, rule->engine);
- mvpp2_cls_flow_port_id_sel(&fe, true);
- mvpp2_flow_set_hek_fields(&fe, rule->hek_fields);
- mvpp2_cls_flow_lu_type_set(&fe, rule->loc);
- mvpp2_cls_flow_port_add(&fe, 0xf);
-
- mvpp2_cls_flow_write(priv, &fe);
- }
-
- return 0;
-}
-
-static int mvpp2_cls_c2_build_match(struct mvpp2_rfs_rule *rule)
-{
- struct flow_rule *flow = rule->flow;
- int offs = 0;
-
- /* The order of insertion in C2 tcam must match the order in which
- * the fields are found in the header
- */
- if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_VLAN)) {
- struct flow_match_vlan match;
-
- flow_rule_match_vlan(flow, &match);
- if (match.mask->vlan_id) {
- rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN;
-
- rule->c2_tcam |= ((u64)match.key->vlan_id) << offs;
- rule->c2_tcam_mask |= ((u64)match.mask->vlan_id) << offs;
-
- /* Don't update the offset yet */
- }
-
- if (match.mask->vlan_priority) {
- rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN_PRI;
-
- /* VLAN pri is always at offset 13 relative to the
- * current offset
- */
- rule->c2_tcam |= ((u64)match.key->vlan_priority) <<
- (offs + 13);
- rule->c2_tcam_mask |= ((u64)match.mask->vlan_priority) <<
- (offs + 13);
- }
-
- if (match.mask->vlan_dei)
- return -EOPNOTSUPP;
-
- /* vlan id and prio always seem to take a full 16-bit slot in
- * the Header Extracted Key.
- */
- offs += 16;
- }
-
- if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_PORTS)) {
- struct flow_match_ports match;
-
- flow_rule_match_ports(flow, &match);
- if (match.mask->src) {
- rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4SIP;
-
- rule->c2_tcam |= ((u64)ntohs(match.key->src)) << offs;
- rule->c2_tcam_mask |= ((u64)ntohs(match.mask->src)) << offs;
- offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4SIP);
- }
-
- if (match.mask->dst) {
- rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4DIP;
-
- rule->c2_tcam |= ((u64)ntohs(match.key->dst)) << offs;
- rule->c2_tcam_mask |= ((u64)ntohs(match.mask->dst)) << offs;
- offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4DIP);
- }
- }
-
- if (hweight16(rule->hek_fields) > MVPP2_FLOW_N_FIELDS)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
-static int mvpp2_cls_rfs_parse_rule(struct mvpp2_rfs_rule *rule)
-{
- struct flow_rule *flow = rule->flow;
- struct flow_action_entry *act;
-
- if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL))
- return -EOPNOTSUPP;
-
- act = &flow->action.entries[0];
- if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP)
- return -EOPNOTSUPP;
-
- /* When both an RSS context and an queue index are set, the index
- * is considered as an offset to be added to the indirection table
- * entries. We don't support this, so reject this rule.
- */
- if (act->queue.ctx && act->queue.index)
- return -EOPNOTSUPP;
-
- /* For now, only use the C2 engine which has a HEK size limited to 64
- * bits for TCAM matching.
- */
- rule->engine = MVPP22_CLS_ENGINE_C2;
-
- if (mvpp2_cls_c2_build_match(rule))
- return -EINVAL;
-
- return 0;
-}
-
-int mvpp2_ethtool_cls_rule_get(struct mvpp2_port *port,
- struct ethtool_rxnfc *rxnfc)
-{
- struct mvpp2_ethtool_fs *efs;
-
- if (rxnfc->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
- return -EINVAL;
-
- efs = port->rfs_rules[rxnfc->fs.location];
- if (!efs)
- return -ENOENT;
-
- memcpy(rxnfc, &efs->rxnfc, sizeof(efs->rxnfc));
-
- return 0;
-}
-
-int mvpp2_ethtool_cls_rule_ins(struct mvpp2_port *port,
- struct ethtool_rxnfc *info)
-{
- struct ethtool_rx_flow_spec_input input = {};
- struct ethtool_rx_flow_rule *ethtool_rule;
- struct mvpp2_ethtool_fs *efs, *old_efs;
- int ret = 0;
-
- if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
- return -EINVAL;
-
- efs = kzalloc(sizeof(*efs), GFP_KERNEL);
- if (!efs)
- return -ENOMEM;
-
- input.fs = &info->fs;
-
- /* We need to manually set the rss_ctx, since this info isn't present
- * in info->fs
- */
- if (info->fs.flow_type & FLOW_RSS)
- input.rss_ctx = info->rss_context;
-
- ethtool_rule = ethtool_rx_flow_rule_create(&input);
- if (IS_ERR(ethtool_rule)) {
- ret = PTR_ERR(ethtool_rule);
- goto clean_rule;
- }
-
- efs->rule.flow = ethtool_rule->rule;
- efs->rule.flow_type = mvpp2_cls_ethtool_flow_to_type(info->fs.flow_type);
- if (efs->rule.flow_type < 0) {
- ret = efs->rule.flow_type;
- goto clean_rule;
- }
-
- ret = mvpp2_cls_rfs_parse_rule(&efs->rule);
- if (ret)
- goto clean_eth_rule;
-
- efs->rule.loc = info->fs.location;
-
- /* Replace an already existing rule */
- if (port->rfs_rules[efs->rule.loc]) {
- old_efs = port->rfs_rules[efs->rule.loc];
- ret = mvpp2_port_cls_rfs_rule_remove(port, &old_efs->rule);
- if (ret)
- goto clean_eth_rule;
- kfree(old_efs);
- port->n_rfs_rules--;
- }
-
- ret = mvpp2_port_flt_rfs_rule_insert(port, &efs->rule);
- if (ret)
- goto clean_eth_rule;
-
- ethtool_rx_flow_rule_destroy(ethtool_rule);
- efs->rule.flow = NULL;
-
- memcpy(&efs->rxnfc, info, sizeof(*info));
- port->rfs_rules[efs->rule.loc] = efs;
- port->n_rfs_rules++;
-
- return ret;
-
-clean_eth_rule:
- ethtool_rx_flow_rule_destroy(ethtool_rule);
-clean_rule:
- kfree(efs);
- return ret;
-}
-
-int mvpp2_ethtool_cls_rule_del(struct mvpp2_port *port,
- struct ethtool_rxnfc *info)
-{
- struct mvpp2_ethtool_fs *efs;
- int ret;
-
- if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
- return -EINVAL;
-
- efs = port->rfs_rules[info->fs.location];
- if (!efs)
- return -EINVAL;
-
- /* Remove the rule from the engines. */
- ret = mvpp2_port_cls_rfs_rule_remove(port, &efs->rule);
- if (ret)
- return ret;
-
- port->n_rfs_rules--;
- port->rfs_rules[info->fs.location] = NULL;
- kfree(efs);
-
- return 0;
}
static inline u32 mvpp22_rxfh_indir(struct mvpp2_port *port, u32 rxq)
@@ -1466,181 +1023,37 @@ static inline u32 mvpp22_rxfh_indir(struct mvpp2_port *port, u32 rxq)
return port->first_rxq + ((rxq * nrxqs + rxq / cpus) % port->nrxqs);
}
-static void mvpp22_rss_fill_table(struct mvpp2_port *port,
- struct mvpp2_rss_table *table,
- u32 rss_ctx)
+void mvpp22_rss_fill_table(struct mvpp2_port *port, u32 table)
{
struct mvpp2 *priv = port->priv;
int i;
for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
- u32 sel = MVPP22_RSS_INDEX_TABLE(rss_ctx) |
+ u32 sel = MVPP22_RSS_INDEX_TABLE(table) |
MVPP22_RSS_INDEX_TABLE_ENTRY(i);
mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY,
- mvpp22_rxfh_indir(port, table->indir[i]));
- }
-}
-
-static int mvpp22_rss_context_create(struct mvpp2_port *port, u32 *rss_ctx)
-{
- struct mvpp2 *priv = port->priv;
- u32 ctx;
-
- /* Find the first free RSS table */
- for (ctx = 0; ctx < MVPP22_N_RSS_TABLES; ctx++) {
- if (!priv->rss_tables[ctx])
- break;
- }
-
- if (ctx == MVPP22_N_RSS_TABLES)
- return -EINVAL;
-
- priv->rss_tables[ctx] = kzalloc(sizeof(*priv->rss_tables[ctx]),
- GFP_KERNEL);
- if (!priv->rss_tables[ctx])
- return -ENOMEM;
-
- *rss_ctx = ctx;
-
- /* Set the table width: replace the whole classifier Rx queue number
- * with the ones configured in RSS table entries.
- */
- mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(ctx));
- mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
-
- mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(ctx));
- mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE, MVPP22_RSS_TABLE_POINTER(ctx));
-
- return 0;
-}
-
-int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *port_ctx)
-{
- u32 rss_ctx;
- int ret, i;
-
- ret = mvpp22_rss_context_create(port, &rss_ctx);
- if (ret)
- return ret;
-
- /* Find the first available context number in the port, starting from 1.
- * Context 0 on each port is reserved for the default context.
- */
- for (i = 1; i < MVPP22_N_RSS_TABLES; i++) {
- if (port->rss_ctx[i] < 0)
- break;
- }
-
- if (i == MVPP22_N_RSS_TABLES)
- return -EINVAL;
-
- port->rss_ctx[i] = rss_ctx;
- *port_ctx = i;
-
- return 0;
-}
-
-static struct mvpp2_rss_table *mvpp22_rss_table_get(struct mvpp2 *priv,
- int rss_ctx)
-{
- if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
- return NULL;
-
- return priv->rss_tables[rss_ctx];
-}
-
-int mvpp22_port_rss_ctx_delete(struct mvpp2_port *port, u32 port_ctx)
-{
- struct mvpp2 *priv = port->priv;
- struct ethtool_rxnfc *rxnfc;
- int i, rss_ctx, ret;
-
- rss_ctx = mvpp22_rss_ctx(port, port_ctx);
-
- if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
- return -EINVAL;
-
- /* Invalidate any active classification rule that use this context */
- for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
- if (!port->rfs_rules[i])
- continue;
-
- rxnfc = &port->rfs_rules[i]->rxnfc;
- if (!(rxnfc->fs.flow_type & FLOW_RSS) ||
- rxnfc->rss_context != port_ctx)
- continue;
-
- ret = mvpp2_ethtool_cls_rule_del(port, rxnfc);
- if (ret) {
- netdev_warn(port->dev,
- "couldn't remove classification rule %d associated to this context",
- rxnfc->fs.location);
- }
+ mvpp22_rxfh_indir(port, port->indir[i]));
}
-
- kfree(priv->rss_tables[rss_ctx]);
-
- priv->rss_tables[rss_ctx] = NULL;
- port->rss_ctx[port_ctx] = -1;
-
- return 0;
-}
-
-int mvpp22_port_rss_ctx_indir_set(struct mvpp2_port *port, u32 port_ctx,
- const u32 *indir)
-{
- int rss_ctx = mvpp22_rss_ctx(port, port_ctx);
- struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
- rss_ctx);
-
- if (!rss_table)
- return -EINVAL;
-
- memcpy(rss_table->indir, indir,
- MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
-
- mvpp22_rss_fill_table(port, rss_table, rss_ctx);
-
- return 0;
-}
-
-int mvpp22_port_rss_ctx_indir_get(struct mvpp2_port *port, u32 port_ctx,
- u32 *indir)
-{
- int rss_ctx = mvpp22_rss_ctx(port, port_ctx);
- struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
- rss_ctx);
-
- if (!rss_table)
- return -EINVAL;
-
- memcpy(indir, rss_table->indir,
- MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
-
- return 0;
}
int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info)
{
u16 hash_opts = 0;
- u32 flow_type;
- flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
-
- switch (flow_type) {
- case MVPP22_FLOW_TCP4:
- case MVPP22_FLOW_UDP4:
- case MVPP22_FLOW_TCP6:
- case MVPP22_FLOW_UDP6:
+ switch (info->flow_type) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ case TCP_V6_FLOW:
+ case UDP_V6_FLOW:
if (info->data & RXH_L4_B_0_1)
hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP;
if (info->data & RXH_L4_B_2_3)
hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP;
fallthrough;
- case MVPP22_FLOW_IP4:
- case MVPP22_FLOW_IP6:
+ case IPV4_FLOW:
+ case IPV6_FLOW:
if (info->data & RXH_L2DA)
hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA;
if (info->data & RXH_VLAN)
@@ -1657,18 +1070,15 @@ int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info)
default: return -EOPNOTSUPP;
}
- return mvpp2_port_rss_hash_opts_set(port, flow_type, hash_opts);
+ return mvpp2_port_rss_hash_opts_set(port, info->flow_type, hash_opts);
}
int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info)
{
unsigned long hash_opts;
- u32 flow_type;
int i;
- flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
-
- hash_opts = mvpp2_port_rss_hash_opts_get(port, flow_type);
+ hash_opts = mvpp2_port_rss_hash_opts_get(port, info->flow_type);
info->data = 0;
for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
@@ -1703,40 +1113,56 @@ int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info)
return 0;
}
-int mvpp22_port_rss_init(struct mvpp2_port *port)
+void mvpp22_rss_port_init(struct mvpp2_port *port)
{
- struct mvpp2_rss_table *table;
- u32 context = 0;
- int i, ret;
-
- for (i = 0; i < MVPP22_N_RSS_TABLES; i++)
- port->rss_ctx[i] = -1;
+ struct mvpp2 *priv = port->priv;
+ int i;
- ret = mvpp22_rss_context_create(port, &context);
- if (ret)
- return ret;
+ /* Set the table width: replace the whole classifier Rx queue number
+ * with the ones configured in RSS table entries.
+ */
+ mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(port->id));
+ mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
- table = mvpp22_rss_table_get(port->priv, context);
- if (!table)
- return -EINVAL;
+ if (port->num_tc_queues > 1) {
+ int rxq;
+ u32 tc_width;
+ int tc_mask;
- port->rss_ctx[0] = context;
+ tc_width = mvpp2_get_tc_width(port);
+ tc_mask = ((1 << tc_width) - 1);
+ for (rxq = 0; rxq < port->nrxqs; rxq++) {
+ mvpp2_write(priv, MVPP22_RSS_INDEX,
+ MVPP22_RSS_INDEX_QUEUE(port->rxqs[rxq]->id));
+ mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE,
+ MVPP22_RSS_TABLE_POINTER(port->rxqs[rxq]->id & tc_mask));
+ }
+ } else {
+ /* The default RxQ is used as a key to select the RSS table to use.
+ * We use one RSS table per port.
+ */
+ mvpp2_write(priv, MVPP22_RSS_INDEX,
+ MVPP22_RSS_INDEX_QUEUE(port->first_rxq));
+ mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE,
+ MVPP22_RSS_TABLE_POINTER(port->id));
+ }
/* Configure the first table to evenly distribute the packets across
* real Rx Queues. The table entries map a hash to a port Rx Queue.
*/
for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++)
- table->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs);
+ port->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs);
- mvpp22_rss_fill_table(port, table, mvpp22_rss_ctx(port, 0));
+ if (port->num_tc_queues > 1)
+ mvpp22_rss_fill_table_per_tc(port);
+ else
+ mvpp22_rss_fill_table(port, port->id);
/* Configure default flows */
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP4, MVPP22_CLS_HEK_IP4_2T);
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP6, MVPP22_CLS_HEK_IP6_2T);
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP4, MVPP22_CLS_HEK_IP4_5T);
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP6, MVPP22_CLS_HEK_IP6_5T);
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP4, MVPP22_CLS_HEK_IP4_5T);
- mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP6, MVPP22_CLS_HEK_IP6_5T);
-
- return 0;
+ mvpp2_port_rss_hash_opts_set(port, IPV4_FLOW, MVPP22_CLS_HEK_IP4_2T);
+ mvpp2_port_rss_hash_opts_set(port, IPV6_FLOW, MVPP22_CLS_HEK_IP6_2T);
+ mvpp2_port_rss_hash_opts_set(port, TCP_V4_FLOW, MVPP22_CLS_HEK_IP4_5T);
+ mvpp2_port_rss_hash_opts_set(port, TCP_V6_FLOW, MVPP22_CLS_HEK_IP6_5T);
+ mvpp2_port_rss_hash_opts_set(port, UDP_V4_FLOW, MVPP22_CLS_HEK_IP4_5T);
+ mvpp2_port_rss_hash_opts_set(port, UDP_V6_FLOW, MVPP22_CLS_HEK_IP6_5T);
}