18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * RSS and Classifier helpers for Marvell PPv2 Network Controller 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Marvell 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Marcin Wojtas <mw@semihalf.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "mvpp2.h" 118c2ecf20Sopenharmony_ci#include "mvpp2_cls.h" 128c2ecf20Sopenharmony_ci#include "mvpp2_prs.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define MVPP2_DEF_FLOW(_type, _id, _opts, _ri, _ri_mask) \ 158c2ecf20Sopenharmony_ci{ \ 168c2ecf20Sopenharmony_ci .flow_type = _type, \ 178c2ecf20Sopenharmony_ci .flow_id = _id, \ 188c2ecf20Sopenharmony_ci .supported_hash_opts = _opts, \ 198c2ecf20Sopenharmony_ci .prs_ri = { \ 208c2ecf20Sopenharmony_ci .ri = _ri, \ 218c2ecf20Sopenharmony_ci .ri_mask = _ri_mask \ 228c2ecf20Sopenharmony_ci } \ 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = { 268c2ecf20Sopenharmony_ci /* TCP over IPv4 flows, Not fragmented, no vlan tag */ 278c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG, 288c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 298c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 | 308c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 318c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG, 348c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 358c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT | 368c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 378c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG, 408c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 418c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER | 428c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 438c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* TCP over IPv4 flows, Not fragmented, with vlan tag */ 468c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG, 478c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 488c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP, 498c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG, 528c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 538c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP, 548c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG, 578c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 588c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP, 598c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci /* TCP over IPv4 flows, fragmented, no vlan tag */ 628c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG, 638c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 648c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 | 658c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 668c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG, 698c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 708c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT | 718c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 728c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG, 758c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 768c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER | 778c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 788c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci /* TCP over IPv4 flows, fragmented, with vlan tag */ 818c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG, 828c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 838c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP, 848c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG, 878c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 888c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP, 898c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG, 928c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 938c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP, 948c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* UDP over IPv4 flows, Not fragmented, no vlan tag */ 978c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG, 988c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 998c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 | 1008c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1018c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG, 1048c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 1058c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT | 1068c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1078c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG, 1108c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T, 1118c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER | 1128c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1138c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* UDP over IPv4 flows, Not fragmented, with vlan tag */ 1168c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG, 1178c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 1188c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP, 1198c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG, 1228c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 1238c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP, 1248c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG, 1278c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED, 1288c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP, 1298c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* UDP over IPv4 flows, fragmented, no vlan tag */ 1328c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG, 1338c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 1348c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 | 1358c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1368c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG, 1398c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 1408c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT | 1418c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1428c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG, 1458c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 1468c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER | 1478c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 1488c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* UDP over IPv4 flows, fragmented, with vlan tag */ 1518c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG, 1528c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 1538c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP, 1548c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG, 1578c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 1588c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP, 1598c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG, 1628c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 1638c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP, 1648c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* TCP over IPv6 flows, not fragmented, no vlan tag */ 1678c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG, 1688c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T, 1698c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 | 1708c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 1718c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG, 1748c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T, 1758c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT | 1768c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 1778c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* TCP over IPv6 flows, not fragmented, with vlan tag */ 1808c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG, 1818c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED, 1828c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_TCP, 1838c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG, 1868c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED, 1878c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_TCP, 1888c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* TCP over IPv6 flows, fragmented, no vlan tag */ 1918c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG, 1928c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 1938c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 | 1948c2ecf20Sopenharmony_ci MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP, 1958c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG, 1988c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 1998c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT | 2008c2ecf20Sopenharmony_ci MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP, 2018c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci /* TCP over IPv6 flows, fragmented, with vlan tag */ 2048c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG, 2058c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 2068c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE | 2078c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 2088c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG, 2118c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 2128c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE | 2138c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_TCP, 2148c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* UDP over IPv6 flows, not fragmented, no vlan tag */ 2178c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG, 2188c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T, 2198c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 | 2208c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 2218c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG, 2248c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T, 2258c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT | 2268c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 2278c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* UDP over IPv6 flows, not fragmented, with vlan tag */ 2308c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG, 2318c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED, 2328c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_UDP, 2338c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG, 2368c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED, 2378c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_UDP, 2388c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* UDP over IPv6 flows, fragmented, no vlan tag */ 2418c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG, 2428c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 2438c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 | 2448c2ecf20Sopenharmony_ci MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP, 2458c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG, 2488c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 2498c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT | 2508c2ecf20Sopenharmony_ci MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP, 2518c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK), 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* UDP over IPv6 flows, fragmented, with vlan tag */ 2548c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG, 2558c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 2568c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE | 2578c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 2588c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG, 2618c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 2628c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE | 2638c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L4_UDP, 2648c2ecf20Sopenharmony_ci MVPP2_PRS_IP_MASK), 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* IPv4 flows, no vlan tag */ 2678c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG, 2688c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 2698c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4, 2708c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK), 2718c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG, 2728c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 2738c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT, 2748c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK), 2758c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG, 2768c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T, 2778c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER, 2788c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK), 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci /* IPv4 flows, with vlan tag */ 2818c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG, 2828c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 2838c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4, 2848c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_PROTO_MASK), 2858c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG, 2868c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 2878c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OPT, 2888c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_PROTO_MASK), 2898c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG, 2908c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED, 2918c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP4_OTHER, 2928c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_PROTO_MASK), 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* IPv6 flows, no vlan tag */ 2958c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG, 2968c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 2978c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6, 2988c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK), 2998c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG, 3008c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T, 3018c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6, 3028c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK), 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci /* IPv6 flows, with vlan tag */ 3058c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG, 3068c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 3078c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6, 3088c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_PROTO_MASK), 3098c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG, 3108c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED, 3118c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_IP6, 3128c2ecf20Sopenharmony_ci MVPP2_PRS_RI_L3_PROTO_MASK), 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* Non IP flow, no vlan tag */ 3158c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_UNTAG, 3168c2ecf20Sopenharmony_ci 0, 3178c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_NONE, 3188c2ecf20Sopenharmony_ci MVPP2_PRS_RI_VLAN_MASK), 3198c2ecf20Sopenharmony_ci /* Non IP flow, with vlan tag */ 3208c2ecf20Sopenharmony_ci MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG, 3218c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_OPT_VLAN, 3228c2ecf20Sopenharmony_ci 0, 0), 3238c2ecf20Sopenharmony_ci}; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ciu32 mvpp2_cls_flow_hits(struct mvpp2 *priv, int index) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CTRS_IDX, index); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return mvpp2_read(priv, MVPP2_CLS_FLOW_TBL_HIT_CTR); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_civoid mvpp2_cls_flow_read(struct mvpp2 *priv, int index, 3338c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry *fe) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci fe->index = index; 3368c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, index); 3378c2ecf20Sopenharmony_ci fe->data[0] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL0_REG); 3388c2ecf20Sopenharmony_ci fe->data[1] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL1_REG); 3398c2ecf20Sopenharmony_ci fe->data[2] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL2_REG); 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci/* Update classification flow table registers */ 3438c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_write(struct mvpp2 *priv, 3448c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry *fe) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index); 3478c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]); 3488c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]); 3498c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ciu32 mvpp2_cls_lookup_hits(struct mvpp2 *priv, int index) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CTRS_IDX, index); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return mvpp2_read(priv, MVPP2_CLS_DEC_TBL_HIT_CTR); 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_civoid mvpp2_cls_lookup_read(struct mvpp2 *priv, int lkpid, int way, 3608c2ecf20Sopenharmony_ci struct mvpp2_cls_lookup_entry *le) 3618c2ecf20Sopenharmony_ci{ 3628c2ecf20Sopenharmony_ci u32 val; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci val = (way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | lkpid; 3658c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val); 3668c2ecf20Sopenharmony_ci le->way = way; 3678c2ecf20Sopenharmony_ci le->lkpid = lkpid; 3688c2ecf20Sopenharmony_ci le->data = mvpp2_read(priv, MVPP2_CLS_LKP_TBL_REG); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/* Update classification lookup table register */ 3728c2ecf20Sopenharmony_cistatic void mvpp2_cls_lookup_write(struct mvpp2 *priv, 3738c2ecf20Sopenharmony_ci struct mvpp2_cls_lookup_entry *le) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci u32 val; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid; 3788c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val); 3798c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_LKP_TBL_REG, le->data); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/* Operations on flow entry */ 3838c2ecf20Sopenharmony_cistatic int mvpp2_cls_flow_hek_num_get(struct mvpp2_cls_flow_entry *fe) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci return fe->data[1] & MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK; 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_hek_num_set(struct mvpp2_cls_flow_entry *fe, 3898c2ecf20Sopenharmony_ci int num_of_fields) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK; 3928c2ecf20Sopenharmony_ci fe->data[1] |= MVPP2_CLS_FLOW_TBL1_N_FIELDS(num_of_fields); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_cistatic int mvpp2_cls_flow_hek_get(struct mvpp2_cls_flow_entry *fe, 3968c2ecf20Sopenharmony_ci int field_index) 3978c2ecf20Sopenharmony_ci{ 3988c2ecf20Sopenharmony_ci return (fe->data[2] >> MVPP2_CLS_FLOW_TBL2_FLD_OFFS(field_index)) & 3998c2ecf20Sopenharmony_ci MVPP2_CLS_FLOW_TBL2_FLD_MASK; 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_hek_set(struct mvpp2_cls_flow_entry *fe, 4038c2ecf20Sopenharmony_ci int field_index, int field_id) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci fe->data[2] &= ~MVPP2_CLS_FLOW_TBL2_FLD(field_index, 4068c2ecf20Sopenharmony_ci MVPP2_CLS_FLOW_TBL2_FLD_MASK); 4078c2ecf20Sopenharmony_ci fe->data[2] |= MVPP2_CLS_FLOW_TBL2_FLD(field_index, field_id); 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_eng_set(struct mvpp2_cls_flow_entry *fe, 4118c2ecf20Sopenharmony_ci int engine) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_ENG(MVPP2_CLS_FLOW_TBL0_ENG_MASK); 4148c2ecf20Sopenharmony_ci fe->data[0] |= MVPP2_CLS_FLOW_TBL0_ENG(engine); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ciint mvpp2_cls_flow_eng_get(struct mvpp2_cls_flow_entry *fe) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci return (fe->data[0] >> MVPP2_CLS_FLOW_TBL0_OFFS) & 4208c2ecf20Sopenharmony_ci MVPP2_CLS_FLOW_TBL0_ENG_MASK; 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_port_id_sel(struct mvpp2_cls_flow_entry *fe, 4248c2ecf20Sopenharmony_ci bool from_packet) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci if (from_packet) 4278c2ecf20Sopenharmony_ci fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL; 4288c2ecf20Sopenharmony_ci else 4298c2ecf20Sopenharmony_ci fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_last_set(struct mvpp2_cls_flow_entry *fe, 4338c2ecf20Sopenharmony_ci bool is_last) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_LAST; 4368c2ecf20Sopenharmony_ci fe->data[0] |= !!is_last; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_pri_set(struct mvpp2_cls_flow_entry *fe, int prio) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_PRIO(MVPP2_CLS_FLOW_TBL1_PRIO_MASK); 4428c2ecf20Sopenharmony_ci fe->data[1] |= MVPP2_CLS_FLOW_TBL1_PRIO(prio); 4438c2ecf20Sopenharmony_ci} 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_port_add(struct mvpp2_cls_flow_entry *fe, 4468c2ecf20Sopenharmony_ci u32 port) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID(port); 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_port_remove(struct mvpp2_cls_flow_entry *fe, 4528c2ecf20Sopenharmony_ci u32 port) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID(port); 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_lu_type_set(struct mvpp2_cls_flow_entry *fe, 4588c2ecf20Sopenharmony_ci u8 lu_type) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK); 4618c2ecf20Sopenharmony_ci fe->data[1] |= MVPP2_CLS_FLOW_TBL1_LU_TYPE(lu_type); 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci/* Initialize the parser entry for the given flow */ 4658c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_prs_init(struct mvpp2 *priv, 4668c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci mvpp2_prs_add_flow(priv, flow->flow_id, flow->prs_ri.ri, 4698c2ecf20Sopenharmony_ci flow->prs_ri.ri_mask); 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci/* Initialize the Lookup Id table entry for the given flow */ 4738c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv, 4748c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci struct mvpp2_cls_lookup_entry le; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci le.way = 0; 4798c2ecf20Sopenharmony_ci le.lkpid = flow->flow_id; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci /* The default RxQ for this port is set in the C2 lookup */ 4828c2ecf20Sopenharmony_ci le.data = 0; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci /* We point on the first lookup in the sequence for the flow, that is 4858c2ecf20Sopenharmony_ci * the C2 lookup. 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_CLS_FLT_FIRST(flow->flow_id)); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci /* CLS is always enabled, RSS is enabled/disabled in C2 lookup */ 4908c2ecf20Sopenharmony_ci le.data |= MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci mvpp2_cls_lookup_write(priv, &le); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cistatic void mvpp2_cls_c2_write(struct mvpp2 *priv, 4968c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry *c2) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci u32 val; 4998c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV); 5028c2ecf20Sopenharmony_ci if (c2->valid) 5038c2ecf20Sopenharmony_ci val &= ~MVPP22_CLS_C2_TCAM_INV_BIT; 5048c2ecf20Sopenharmony_ci else 5058c2ecf20Sopenharmony_ci val |= MVPP22_CLS_C2_TCAM_INV_BIT; 5068c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_INV, val); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]); 5118c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]); 5128c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]); 5138c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]); 5168c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]); 5178c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]); 5188c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]); 5198c2ecf20Sopenharmony_ci /* Writing TCAM_DATA4 flushes writes to TCAM_DATA0-4 and INV to HW */ 5208c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_civoid mvpp2_cls_c2_read(struct mvpp2 *priv, int index, 5248c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry *c2) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci u32 val; 5278c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci c2->index = index; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0); 5328c2ecf20Sopenharmony_ci c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1); 5338c2ecf20Sopenharmony_ci c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2); 5348c2ecf20Sopenharmony_ci c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3); 5358c2ecf20Sopenharmony_ci c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0); 5408c2ecf20Sopenharmony_ci c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1); 5418c2ecf20Sopenharmony_ci c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2); 5428c2ecf20Sopenharmony_ci c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV); 5458c2ecf20Sopenharmony_ci c2->valid = !(val & MVPP22_CLS_C2_TCAM_INV_BIT); 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int mvpp2_cls_ethtool_flow_to_type(int flow_type) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci switch (flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) { 5518c2ecf20Sopenharmony_ci case ETHER_FLOW: 5528c2ecf20Sopenharmony_ci return MVPP22_FLOW_ETHERNET; 5538c2ecf20Sopenharmony_ci case TCP_V4_FLOW: 5548c2ecf20Sopenharmony_ci return MVPP22_FLOW_TCP4; 5558c2ecf20Sopenharmony_ci case TCP_V6_FLOW: 5568c2ecf20Sopenharmony_ci return MVPP22_FLOW_TCP6; 5578c2ecf20Sopenharmony_ci case UDP_V4_FLOW: 5588c2ecf20Sopenharmony_ci return MVPP22_FLOW_UDP4; 5598c2ecf20Sopenharmony_ci case UDP_V6_FLOW: 5608c2ecf20Sopenharmony_ci return MVPP22_FLOW_UDP6; 5618c2ecf20Sopenharmony_ci case IPV4_FLOW: 5628c2ecf20Sopenharmony_ci return MVPP22_FLOW_IP4; 5638c2ecf20Sopenharmony_ci case IPV6_FLOW: 5648c2ecf20Sopenharmony_ci return MVPP22_FLOW_IP6; 5658c2ecf20Sopenharmony_ci default: 5668c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic int mvpp2_cls_c2_port_flow_index(struct mvpp2_port *port, int loc) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci return MVPP22_CLS_C2_RFS_LOC(port->id, loc); 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci/* Initialize the flow table entries for the given flow */ 5768c2ecf20Sopenharmony_cistatic void mvpp2_cls_flow_init(struct mvpp2 *priv, 5778c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 5808c2ecf20Sopenharmony_ci int i, pri = 0; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci /* Assign default values to all entries in the flow */ 5838c2ecf20Sopenharmony_ci for (i = MVPP2_CLS_FLT_FIRST(flow->flow_id); 5848c2ecf20Sopenharmony_ci i <= MVPP2_CLS_FLT_LAST(flow->flow_id); i++) { 5858c2ecf20Sopenharmony_ci memset(&fe, 0, sizeof(fe)); 5868c2ecf20Sopenharmony_ci fe.index = i; 5878c2ecf20Sopenharmony_ci mvpp2_cls_flow_pri_set(&fe, pri++); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (i == MVPP2_CLS_FLT_LAST(flow->flow_id)) 5908c2ecf20Sopenharmony_ci mvpp2_cls_flow_last_set(&fe, 1); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(priv, &fe); 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci /* RSS config C2 lookup */ 5968c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(priv, MVPP2_CLS_FLT_C2_RSS_ENTRY(flow->flow_id), 5978c2ecf20Sopenharmony_ci &fe); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C2); 6008c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_id_sel(&fe, true); 6018c2ecf20Sopenharmony_ci mvpp2_cls_flow_lu_type_set(&fe, MVPP22_CLS_LU_TYPE_ALL); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci /* Add all ports */ 6048c2ecf20Sopenharmony_ci for (i = 0; i < MVPP2_MAX_PORTS; i++) 6058c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_add(&fe, BIT(i)); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(priv, &fe); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* C3Hx lookups */ 6108c2ecf20Sopenharmony_ci for (i = 0; i < MVPP2_MAX_PORTS; i++) { 6118c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(priv, 6128c2ecf20Sopenharmony_ci MVPP2_CLS_FLT_HASH_ENTRY(i, flow->flow_id), 6138c2ecf20Sopenharmony_ci &fe); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci /* Set a default engine. Will be overwritten when setting the 6168c2ecf20Sopenharmony_ci * real HEK parameters 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_ci mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C3HA); 6198c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_id_sel(&fe, true); 6208c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_add(&fe, BIT(i)); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(priv, &fe); 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci/* Adds a field to the Header Extracted Key generation parameters*/ 6278c2ecf20Sopenharmony_cistatic int mvpp2_flow_add_hek_field(struct mvpp2_cls_flow_entry *fe, 6288c2ecf20Sopenharmony_ci u32 field_id) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci int nb_fields = mvpp2_cls_flow_hek_num_get(fe); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if (nb_fields == MVPP2_FLOW_N_FIELDS) 6338c2ecf20Sopenharmony_ci return -EINVAL; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci mvpp2_cls_flow_hek_set(fe, nb_fields, field_id); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci mvpp2_cls_flow_hek_num_set(fe, nb_fields + 1); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci return 0; 6408c2ecf20Sopenharmony_ci} 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_cistatic int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe, 6438c2ecf20Sopenharmony_ci unsigned long hash_opts) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci u32 field_id; 6468c2ecf20Sopenharmony_ci int i; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci /* Clear old fields */ 6498c2ecf20Sopenharmony_ci mvpp2_cls_flow_hek_num_set(fe, 0); 6508c2ecf20Sopenharmony_ci fe->data[2] = 0; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) { 6538c2ecf20Sopenharmony_ci switch (BIT(i)) { 6548c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_MAC_DA: 6558c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_MAC_DA; 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_VLAN: 6588c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_VLAN; 6598c2ecf20Sopenharmony_ci break; 6608c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_VLAN_PRI: 6618c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_VLAN_PRI; 6628c2ecf20Sopenharmony_ci break; 6638c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4SA: 6648c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_IP4SA; 6658c2ecf20Sopenharmony_ci break; 6668c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4DA: 6678c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_IP4DA; 6688c2ecf20Sopenharmony_ci break; 6698c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6SA: 6708c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_IP6SA; 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6DA: 6738c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_IP6DA; 6748c2ecf20Sopenharmony_ci break; 6758c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4SIP: 6768c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_L4SIP; 6778c2ecf20Sopenharmony_ci break; 6788c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4DIP: 6798c2ecf20Sopenharmony_ci field_id = MVPP22_CLS_FIELD_L4DIP; 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci default: 6828c2ecf20Sopenharmony_ci return -EINVAL; 6838c2ecf20Sopenharmony_ci } 6848c2ecf20Sopenharmony_ci if (mvpp2_flow_add_hek_field(fe, field_id)) 6858c2ecf20Sopenharmony_ci return -EINVAL; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci return 0; 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci/* Returns the size, in bits, of the corresponding HEK field */ 6928c2ecf20Sopenharmony_cistatic int mvpp2_cls_hek_field_size(u32 field) 6938c2ecf20Sopenharmony_ci{ 6948c2ecf20Sopenharmony_ci switch (field) { 6958c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_MAC_DA: 6968c2ecf20Sopenharmony_ci return 48; 6978c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_VLAN: 6988c2ecf20Sopenharmony_ci return 12; 6998c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_VLAN_PRI: 7008c2ecf20Sopenharmony_ci return 3; 7018c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4SA: 7028c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4DA: 7038c2ecf20Sopenharmony_ci return 32; 7048c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6SA: 7058c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6DA: 7068c2ecf20Sopenharmony_ci return 128; 7078c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4SIP: 7088c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4DIP: 7098c2ecf20Sopenharmony_ci return 16; 7108c2ecf20Sopenharmony_ci default: 7118c2ecf20Sopenharmony_ci return -1; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci} 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ciconst struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci if (flow >= MVPP2_N_PRS_FLOWS) 7188c2ecf20Sopenharmony_ci return NULL; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci return &cls_flows[flow]; 7218c2ecf20Sopenharmony_ci} 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci/* Set the hash generation options for the given traffic flow. 7248c2ecf20Sopenharmony_ci * One traffic flow (in the ethtool sense) has multiple classification flows, 7258c2ecf20Sopenharmony_ci * to handle specific cases such as fragmentation, or the presence of a 7268c2ecf20Sopenharmony_ci * VLAN / DSA Tag. 7278c2ecf20Sopenharmony_ci * 7288c2ecf20Sopenharmony_ci * Each of these individual flows has different constraints, for example we 7298c2ecf20Sopenharmony_ci * can't hash fragmented packets on L4 data (else we would risk having packet 7308c2ecf20Sopenharmony_ci * re-ordering), so each classification flows masks the options with their 7318c2ecf20Sopenharmony_ci * supported ones. 7328c2ecf20Sopenharmony_ci * 7338c2ecf20Sopenharmony_ci */ 7348c2ecf20Sopenharmony_cistatic int mvpp2_port_rss_hash_opts_set(struct mvpp2_port *port, int flow_type, 7358c2ecf20Sopenharmony_ci u16 requested_opts) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow; 7388c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 7398c2ecf20Sopenharmony_ci int i, engine, flow_index; 7408c2ecf20Sopenharmony_ci u16 hash_opts; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci for_each_cls_flow_id_with_type(i, flow_type) { 7438c2ecf20Sopenharmony_ci flow = mvpp2_cls_flow_get(i); 7448c2ecf20Sopenharmony_ci if (!flow) 7458c2ecf20Sopenharmony_ci return -EINVAL; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(port->priv, flow_index, &fe); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci hash_opts = flow->supported_hash_opts & requested_opts; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* Use C3HB engine to access L4 infos. This adds L4 infos to the 7548c2ecf20Sopenharmony_ci * hash parameters 7558c2ecf20Sopenharmony_ci */ 7568c2ecf20Sopenharmony_ci if (hash_opts & MVPP22_CLS_HEK_L4_OPTS) 7578c2ecf20Sopenharmony_ci engine = MVPP22_CLS_ENGINE_C3HB; 7588c2ecf20Sopenharmony_ci else 7598c2ecf20Sopenharmony_ci engine = MVPP22_CLS_ENGINE_C3HA; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (mvpp2_flow_set_hek_fields(&fe, hash_opts)) 7628c2ecf20Sopenharmony_ci return -EINVAL; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci mvpp2_cls_flow_eng_set(&fe, engine); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(port->priv, &fe); 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci return 0; 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ciu16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci u16 hash_opts = 0; 7758c2ecf20Sopenharmony_ci int n_fields, i, field; 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci n_fields = mvpp2_cls_flow_hek_num_get(fe); 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci for (i = 0; i < n_fields; i++) { 7808c2ecf20Sopenharmony_ci field = mvpp2_cls_flow_hek_get(fe, i); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci switch (field) { 7838c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_MAC_DA: 7848c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA; 7858c2ecf20Sopenharmony_ci break; 7868c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_VLAN: 7878c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_VLAN; 7888c2ecf20Sopenharmony_ci break; 7898c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_VLAN_PRI: 7908c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_VLAN_PRI; 7918c2ecf20Sopenharmony_ci break; 7928c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_L3_PROTO: 7938c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO; 7948c2ecf20Sopenharmony_ci break; 7958c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_IP4SA: 7968c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_IP4SA; 7978c2ecf20Sopenharmony_ci break; 7988c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_IP4DA: 7998c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_IP4DA; 8008c2ecf20Sopenharmony_ci break; 8018c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_IP6SA: 8028c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_IP6SA; 8038c2ecf20Sopenharmony_ci break; 8048c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_IP6DA: 8058c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_IP6DA; 8068c2ecf20Sopenharmony_ci break; 8078c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_L4SIP: 8088c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP; 8098c2ecf20Sopenharmony_ci break; 8108c2ecf20Sopenharmony_ci case MVPP22_CLS_FIELD_L4DIP: 8118c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP; 8128c2ecf20Sopenharmony_ci break; 8138c2ecf20Sopenharmony_ci default: 8148c2ecf20Sopenharmony_ci break; 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci return hash_opts; 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci/* Returns the hash opts for this flow. There are several classifier flows 8218c2ecf20Sopenharmony_ci * for one traffic flow, this returns an aggregation of all configurations. 8228c2ecf20Sopenharmony_ci */ 8238c2ecf20Sopenharmony_cistatic u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow; 8268c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 8278c2ecf20Sopenharmony_ci int i, flow_index; 8288c2ecf20Sopenharmony_ci u16 hash_opts = 0; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci for_each_cls_flow_id_with_type(i, flow_type) { 8318c2ecf20Sopenharmony_ci flow = mvpp2_cls_flow_get(i); 8328c2ecf20Sopenharmony_ci if (!flow) 8338c2ecf20Sopenharmony_ci return 0; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(port->priv, flow_index, &fe); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci hash_opts |= mvpp2_flow_get_hek_fields(&fe); 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci return hash_opts; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic void mvpp2_cls_port_init_flows(struct mvpp2 *priv) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow; 8488c2ecf20Sopenharmony_ci int i; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) { 8518c2ecf20Sopenharmony_ci flow = mvpp2_cls_flow_get(i); 8528c2ecf20Sopenharmony_ci if (!flow) 8538c2ecf20Sopenharmony_ci break; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci mvpp2_cls_flow_prs_init(priv, flow); 8568c2ecf20Sopenharmony_ci mvpp2_cls_flow_lkp_init(priv, flow); 8578c2ecf20Sopenharmony_ci mvpp2_cls_flow_init(priv, flow); 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_cistatic void mvpp2_port_c2_cls_init(struct mvpp2_port *port) 8628c2ecf20Sopenharmony_ci{ 8638c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 8648c2ecf20Sopenharmony_ci u8 qh, ql, pmap; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci memset(&c2, 0, sizeof(c2)); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci c2.index = MVPP22_CLS_C2_RSS_ENTRY(port->id); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci pmap = BIT(port->id); 8718c2ecf20Sopenharmony_ci c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap); 8728c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap)); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci /* Match on Lookup Type */ 8758c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK)); 8768c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(MVPP22_CLS_LU_TYPE_ALL); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci /* Update RSS status after matching this entry */ 8798c2ecf20Sopenharmony_ci c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* Mark packet as "forwarded to software", needed for RSS */ 8828c2ecf20Sopenharmony_ci c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* Configure the default rx queue : Update Queue Low and Queue High, but 8858c2ecf20Sopenharmony_ci * don't lock, since the rx queue selection might be overridden by RSS 8868c2ecf20Sopenharmony_ci */ 8878c2ecf20Sopenharmony_ci c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD) | 8888c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci qh = (port->first_rxq >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK; 8918c2ecf20Sopenharmony_ci ql = port->first_rxq & MVPP22_CLS_C2_ATTR0_QLOW_MASK; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) | 8948c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QLOW(ql); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci c2.valid = true; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(port->priv, &c2); 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci/* Classifier default initialization */ 9028c2ecf20Sopenharmony_civoid mvpp2_cls_init(struct mvpp2 *priv) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci struct mvpp2_cls_lookup_entry le; 9058c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 9068c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 9078c2ecf20Sopenharmony_ci int index; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci /* Enable classifier */ 9108c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci /* Clear classifier flow table */ 9138c2ecf20Sopenharmony_ci memset(&fe.data, 0, sizeof(fe.data)); 9148c2ecf20Sopenharmony_ci for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) { 9158c2ecf20Sopenharmony_ci fe.index = index; 9168c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(priv, &fe); 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* Clear classifier lookup table */ 9208c2ecf20Sopenharmony_ci le.data = 0; 9218c2ecf20Sopenharmony_ci for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) { 9228c2ecf20Sopenharmony_ci le.lkpid = index; 9238c2ecf20Sopenharmony_ci le.way = 0; 9248c2ecf20Sopenharmony_ci mvpp2_cls_lookup_write(priv, &le); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci le.way = 1; 9278c2ecf20Sopenharmony_ci mvpp2_cls_lookup_write(priv, &le); 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci /* Clear C2 TCAM engine table */ 9318c2ecf20Sopenharmony_ci memset(&c2, 0, sizeof(c2)); 9328c2ecf20Sopenharmony_ci c2.valid = false; 9338c2ecf20Sopenharmony_ci for (index = 0; index < MVPP22_CLS_C2_N_ENTRIES; index++) { 9348c2ecf20Sopenharmony_ci c2.index = index; 9358c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(priv, &c2); 9368c2ecf20Sopenharmony_ci } 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci /* Disable the FIFO stages in C2 engine, which are only used in BIST 9398c2ecf20Sopenharmony_ci * mode 9408c2ecf20Sopenharmony_ci */ 9418c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_CTRL, 9428c2ecf20Sopenharmony_ci MVPP22_CLS_C2_TCAM_BYPASS_FIFO); 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci mvpp2_cls_port_init_flows(priv); 9458c2ecf20Sopenharmony_ci} 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_civoid mvpp2_cls_port_config(struct mvpp2_port *port) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci struct mvpp2_cls_lookup_entry le; 9508c2ecf20Sopenharmony_ci u32 val; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* Set way for the port */ 9538c2ecf20Sopenharmony_ci val = mvpp2_read(port->priv, MVPP2_CLS_PORT_WAY_REG); 9548c2ecf20Sopenharmony_ci val &= ~MVPP2_CLS_PORT_WAY_MASK(port->id); 9558c2ecf20Sopenharmony_ci mvpp2_write(port->priv, MVPP2_CLS_PORT_WAY_REG, val); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci /* Pick the entry to be accessed in lookup ID decoding table 9588c2ecf20Sopenharmony_ci * according to the way and lkpid. 9598c2ecf20Sopenharmony_ci */ 9608c2ecf20Sopenharmony_ci le.lkpid = port->id; 9618c2ecf20Sopenharmony_ci le.way = 0; 9628c2ecf20Sopenharmony_ci le.data = 0; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* Set initial CPU queue for receiving packets */ 9658c2ecf20Sopenharmony_ci le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK; 9668c2ecf20Sopenharmony_ci le.data |= port->first_rxq; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* Disable classification engines */ 9698c2ecf20Sopenharmony_ci le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci /* Update lookup ID table entry */ 9728c2ecf20Sopenharmony_ci mvpp2_cls_lookup_write(port->priv, &le); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci mvpp2_port_c2_cls_init(port); 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ciu32 mvpp2_cls_c2_hit_count(struct mvpp2 *priv, int c2_index) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2_index); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci return mvpp2_read(priv, MVPP22_CLS_C2_HIT_CTR); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic void mvpp2_rss_port_c2_enable(struct mvpp2_port *port, u32 ctx) 9858c2ecf20Sopenharmony_ci{ 9868c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 9878c2ecf20Sopenharmony_ci u8 qh, ql; 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci /* The RxQ number is used to select the RSS table. It that case, we set 9928c2ecf20Sopenharmony_ci * it to be the ctx number. 9938c2ecf20Sopenharmony_ci */ 9948c2ecf20Sopenharmony_ci qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK; 9958c2ecf20Sopenharmony_ci ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) | 9988c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QLOW(ql); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(port->priv, &c2); 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic void mvpp2_rss_port_c2_disable(struct mvpp2_port *port) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 10088c2ecf20Sopenharmony_ci u8 qh, ql; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci /* Reset the default destination RxQ to the port's first rx queue. */ 10138c2ecf20Sopenharmony_ci qh = (port->first_rxq >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK; 10148c2ecf20Sopenharmony_ci ql = port->first_rxq & MVPP22_CLS_C2_ATTR0_QLOW_MASK; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) | 10178c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QLOW(ql); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci c2.attr[2] &= ~MVPP22_CLS_C2_ATTR2_RSS_EN; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(port->priv, &c2); 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic inline int mvpp22_rss_ctx(struct mvpp2_port *port, int port_rss_ctx) 10258c2ecf20Sopenharmony_ci{ 10268c2ecf20Sopenharmony_ci return port->rss_ctx[port_rss_ctx]; 10278c2ecf20Sopenharmony_ci} 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ciint mvpp22_port_rss_enable(struct mvpp2_port *port) 10308c2ecf20Sopenharmony_ci{ 10318c2ecf20Sopenharmony_ci if (mvpp22_rss_ctx(port, 0) < 0) 10328c2ecf20Sopenharmony_ci return -EINVAL; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci mvpp2_rss_port_c2_enable(port, mvpp22_rss_ctx(port, 0)); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci return 0; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ciint mvpp22_port_rss_disable(struct mvpp2_port *port) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci if (mvpp22_rss_ctx(port, 0) < 0) 10428c2ecf20Sopenharmony_ci return -EINVAL; 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci mvpp2_rss_port_c2_disable(port); 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci return 0; 10478c2ecf20Sopenharmony_ci} 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_cistatic void mvpp22_port_c2_lookup_disable(struct mvpp2_port *port, int entry) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci mvpp2_cls_c2_read(port->priv, entry, &c2); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci /* Clear the port map so that the entry doesn't match anymore */ 10568c2ecf20Sopenharmony_ci c2.tcam[4] &= ~(MVPP22_CLS_C2_PORT_ID(BIT(port->id))); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(port->priv, &c2); 10598c2ecf20Sopenharmony_ci} 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci/* Set CPU queue number for oversize packets */ 10628c2ecf20Sopenharmony_civoid mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port) 10638c2ecf20Sopenharmony_ci{ 10648c2ecf20Sopenharmony_ci u32 val; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id), 10678c2ecf20Sopenharmony_ci port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK); 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id), 10708c2ecf20Sopenharmony_ci (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS)); 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG); 10738c2ecf20Sopenharmony_ci val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id); 10748c2ecf20Sopenharmony_ci mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val); 10758c2ecf20Sopenharmony_ci} 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_cistatic int mvpp2_port_c2_tcam_rule_add(struct mvpp2_port *port, 10788c2ecf20Sopenharmony_ci struct mvpp2_rfs_rule *rule) 10798c2ecf20Sopenharmony_ci{ 10808c2ecf20Sopenharmony_ci struct flow_action_entry *act; 10818c2ecf20Sopenharmony_ci struct mvpp2_cls_c2_entry c2; 10828c2ecf20Sopenharmony_ci u8 qh, ql, pmap; 10838c2ecf20Sopenharmony_ci int index, ctx; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL)) 10868c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci memset(&c2, 0, sizeof(c2)); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci index = mvpp2_cls_c2_port_flow_index(port, rule->loc); 10918c2ecf20Sopenharmony_ci if (index < 0) 10928c2ecf20Sopenharmony_ci return -EINVAL; 10938c2ecf20Sopenharmony_ci c2.index = index; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci act = &rule->flow->action.entries[0]; 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci rule->c2_index = c2.index; 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci c2.tcam[3] = (rule->c2_tcam & 0xffff) | 11008c2ecf20Sopenharmony_ci ((rule->c2_tcam_mask & 0xffff) << 16); 11018c2ecf20Sopenharmony_ci c2.tcam[2] = ((rule->c2_tcam >> 16) & 0xffff) | 11028c2ecf20Sopenharmony_ci (((rule->c2_tcam_mask >> 16) & 0xffff) << 16); 11038c2ecf20Sopenharmony_ci c2.tcam[1] = ((rule->c2_tcam >> 32) & 0xffff) | 11048c2ecf20Sopenharmony_ci (((rule->c2_tcam_mask >> 32) & 0xffff) << 16); 11058c2ecf20Sopenharmony_ci c2.tcam[0] = ((rule->c2_tcam >> 48) & 0xffff) | 11068c2ecf20Sopenharmony_ci (((rule->c2_tcam_mask >> 48) & 0xffff) << 16); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci pmap = BIT(port->id); 11098c2ecf20Sopenharmony_ci c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap); 11108c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap)); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci /* Match on Lookup Type */ 11138c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK)); 11148c2ecf20Sopenharmony_ci c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(rule->loc); 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci if (act->id == FLOW_ACTION_DROP) { 11178c2ecf20Sopenharmony_ci c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_RED_LOCK); 11188c2ecf20Sopenharmony_ci } else { 11198c2ecf20Sopenharmony_ci /* We want to keep the default color derived from the Header 11208c2ecf20Sopenharmony_ci * Parser drop entries, for VLAN and MAC filtering. This will 11218c2ecf20Sopenharmony_ci * assign a default color of Green or Red, and we want matches 11228c2ecf20Sopenharmony_ci * with a non-drop action to keep that color. 11238c2ecf20Sopenharmony_ci */ 11248c2ecf20Sopenharmony_ci c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_NO_UPD_LOCK); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci /* Update RSS status after matching this entry */ 11278c2ecf20Sopenharmony_ci if (act->queue.ctx) 11288c2ecf20Sopenharmony_ci c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci /* Always lock the RSS_EN decision. We might have high prio 11318c2ecf20Sopenharmony_ci * rules steering to an RXQ, and a lower one steering to RSS, 11328c2ecf20Sopenharmony_ci * we don't want the low prio RSS rule overwriting this flag. 11338c2ecf20Sopenharmony_ci */ 11348c2ecf20Sopenharmony_ci c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci /* Mark packet as "forwarded to software", needed for RSS */ 11378c2ecf20Sopenharmony_ci c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD_LOCK) | 11408c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD_LOCK); 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci if (act->queue.ctx) { 11438c2ecf20Sopenharmony_ci /* Get the global ctx number */ 11448c2ecf20Sopenharmony_ci ctx = mvpp22_rss_ctx(port, act->queue.ctx); 11458c2ecf20Sopenharmony_ci if (ctx < 0) 11468c2ecf20Sopenharmony_ci return -EINVAL; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK; 11498c2ecf20Sopenharmony_ci ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK; 11508c2ecf20Sopenharmony_ci } else { 11518c2ecf20Sopenharmony_ci qh = ((act->queue.index + port->first_rxq) >> 3) & 11528c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QHIGH_MASK; 11538c2ecf20Sopenharmony_ci ql = (act->queue.index + port->first_rxq) & 11548c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QLOW_MASK; 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) | 11588c2ecf20Sopenharmony_ci MVPP22_CLS_C2_ATTR0_QLOW(ql); 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci c2.valid = true; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci mvpp2_cls_c2_write(port->priv, &c2); 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return 0; 11668c2ecf20Sopenharmony_ci} 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cistatic int mvpp2_port_c2_rfs_rule_insert(struct mvpp2_port *port, 11698c2ecf20Sopenharmony_ci struct mvpp2_rfs_rule *rule) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci return mvpp2_port_c2_tcam_rule_add(port, rule); 11728c2ecf20Sopenharmony_ci} 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic int mvpp2_port_cls_rfs_rule_remove(struct mvpp2_port *port, 11758c2ecf20Sopenharmony_ci struct mvpp2_rfs_rule *rule) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow; 11788c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 11798c2ecf20Sopenharmony_ci int index, i; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci for_each_cls_flow_id_containing_type(i, rule->flow_type) { 11828c2ecf20Sopenharmony_ci flow = mvpp2_cls_flow_get(i); 11838c2ecf20Sopenharmony_ci if (!flow) 11848c2ecf20Sopenharmony_ci return 0; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(port->priv, index, &fe); 11898c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_remove(&fe, BIT(port->id)); 11908c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(port->priv, &fe); 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci if (rule->c2_index >= 0) 11948c2ecf20Sopenharmony_ci mvpp22_port_c2_lookup_disable(port, rule->c2_index); 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci return 0; 11978c2ecf20Sopenharmony_ci} 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_cistatic int mvpp2_port_flt_rfs_rule_insert(struct mvpp2_port *port, 12008c2ecf20Sopenharmony_ci struct mvpp2_rfs_rule *rule) 12018c2ecf20Sopenharmony_ci{ 12028c2ecf20Sopenharmony_ci const struct mvpp2_cls_flow *flow; 12038c2ecf20Sopenharmony_ci struct mvpp2 *priv = port->priv; 12048c2ecf20Sopenharmony_ci struct mvpp2_cls_flow_entry fe; 12058c2ecf20Sopenharmony_ci int index, ret, i; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci if (rule->engine != MVPP22_CLS_ENGINE_C2) 12088c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci ret = mvpp2_port_c2_rfs_rule_insert(port, rule); 12118c2ecf20Sopenharmony_ci if (ret) 12128c2ecf20Sopenharmony_ci return ret; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci for_each_cls_flow_id_containing_type(i, rule->flow_type) { 12158c2ecf20Sopenharmony_ci flow = mvpp2_cls_flow_get(i); 12168c2ecf20Sopenharmony_ci if (!flow) 12178c2ecf20Sopenharmony_ci return 0; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci if ((rule->hek_fields & flow->supported_hash_opts) != rule->hek_fields) 12208c2ecf20Sopenharmony_ci continue; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci mvpp2_cls_flow_read(priv, index, &fe); 12258c2ecf20Sopenharmony_ci mvpp2_cls_flow_eng_set(&fe, rule->engine); 12268c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_id_sel(&fe, true); 12278c2ecf20Sopenharmony_ci mvpp2_flow_set_hek_fields(&fe, rule->hek_fields); 12288c2ecf20Sopenharmony_ci mvpp2_cls_flow_lu_type_set(&fe, rule->loc); 12298c2ecf20Sopenharmony_ci mvpp2_cls_flow_port_add(&fe, 0xf); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci mvpp2_cls_flow_write(priv, &fe); 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci return 0; 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_cistatic int mvpp2_cls_c2_build_match(struct mvpp2_rfs_rule *rule) 12388c2ecf20Sopenharmony_ci{ 12398c2ecf20Sopenharmony_ci struct flow_rule *flow = rule->flow; 12408c2ecf20Sopenharmony_ci int offs = 0; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* The order of insertion in C2 tcam must match the order in which 12438c2ecf20Sopenharmony_ci * the fields are found in the header 12448c2ecf20Sopenharmony_ci */ 12458c2ecf20Sopenharmony_ci if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_VLAN)) { 12468c2ecf20Sopenharmony_ci struct flow_match_vlan match; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci flow_rule_match_vlan(flow, &match); 12498c2ecf20Sopenharmony_ci if (match.mask->vlan_id) { 12508c2ecf20Sopenharmony_ci rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci rule->c2_tcam |= ((u64)match.key->vlan_id) << offs; 12538c2ecf20Sopenharmony_ci rule->c2_tcam_mask |= ((u64)match.mask->vlan_id) << offs; 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci /* Don't update the offset yet */ 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci if (match.mask->vlan_priority) { 12598c2ecf20Sopenharmony_ci rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN_PRI; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci /* VLAN pri is always at offset 13 relative to the 12628c2ecf20Sopenharmony_ci * current offset 12638c2ecf20Sopenharmony_ci */ 12648c2ecf20Sopenharmony_ci rule->c2_tcam |= ((u64)match.key->vlan_priority) << 12658c2ecf20Sopenharmony_ci (offs + 13); 12668c2ecf20Sopenharmony_ci rule->c2_tcam_mask |= ((u64)match.mask->vlan_priority) << 12678c2ecf20Sopenharmony_ci (offs + 13); 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci if (match.mask->vlan_dei) 12718c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci /* vlan id and prio always seem to take a full 16-bit slot in 12748c2ecf20Sopenharmony_ci * the Header Extracted Key. 12758c2ecf20Sopenharmony_ci */ 12768c2ecf20Sopenharmony_ci offs += 16; 12778c2ecf20Sopenharmony_ci } 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_PORTS)) { 12808c2ecf20Sopenharmony_ci struct flow_match_ports match; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci flow_rule_match_ports(flow, &match); 12838c2ecf20Sopenharmony_ci if (match.mask->src) { 12848c2ecf20Sopenharmony_ci rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4SIP; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci rule->c2_tcam |= ((u64)ntohs(match.key->src)) << offs; 12878c2ecf20Sopenharmony_ci rule->c2_tcam_mask |= ((u64)ntohs(match.mask->src)) << offs; 12888c2ecf20Sopenharmony_ci offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4SIP); 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci if (match.mask->dst) { 12928c2ecf20Sopenharmony_ci rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4DIP; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci rule->c2_tcam |= ((u64)ntohs(match.key->dst)) << offs; 12958c2ecf20Sopenharmony_ci rule->c2_tcam_mask |= ((u64)ntohs(match.mask->dst)) << offs; 12968c2ecf20Sopenharmony_ci offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4DIP); 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci if (hweight16(rule->hek_fields) > MVPP2_FLOW_N_FIELDS) 13018c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci return 0; 13048c2ecf20Sopenharmony_ci} 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_cistatic int mvpp2_cls_rfs_parse_rule(struct mvpp2_rfs_rule *rule) 13078c2ecf20Sopenharmony_ci{ 13088c2ecf20Sopenharmony_ci struct flow_rule *flow = rule->flow; 13098c2ecf20Sopenharmony_ci struct flow_action_entry *act; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL)) 13128c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci act = &flow->action.entries[0]; 13158c2ecf20Sopenharmony_ci if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP) 13168c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci /* When both an RSS context and an queue index are set, the index 13198c2ecf20Sopenharmony_ci * is considered as an offset to be added to the indirection table 13208c2ecf20Sopenharmony_ci * entries. We don't support this, so reject this rule. 13218c2ecf20Sopenharmony_ci */ 13228c2ecf20Sopenharmony_ci if (act->queue.ctx && act->queue.index) 13238c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* For now, only use the C2 engine which has a HEK size limited to 64 13268c2ecf20Sopenharmony_ci * bits for TCAM matching. 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci rule->engine = MVPP22_CLS_ENGINE_C2; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci if (mvpp2_cls_c2_build_match(rule)) 13318c2ecf20Sopenharmony_ci return -EINVAL; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci return 0; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ciint mvpp2_ethtool_cls_rule_get(struct mvpp2_port *port, 13378c2ecf20Sopenharmony_ci struct ethtool_rxnfc *rxnfc) 13388c2ecf20Sopenharmony_ci{ 13398c2ecf20Sopenharmony_ci struct mvpp2_ethtool_fs *efs; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci if (rxnfc->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW) 13428c2ecf20Sopenharmony_ci return -EINVAL; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci efs = port->rfs_rules[rxnfc->fs.location]; 13458c2ecf20Sopenharmony_ci if (!efs) 13468c2ecf20Sopenharmony_ci return -ENOENT; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci memcpy(rxnfc, &efs->rxnfc, sizeof(efs->rxnfc)); 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci return 0; 13518c2ecf20Sopenharmony_ci} 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ciint mvpp2_ethtool_cls_rule_ins(struct mvpp2_port *port, 13548c2ecf20Sopenharmony_ci struct ethtool_rxnfc *info) 13558c2ecf20Sopenharmony_ci{ 13568c2ecf20Sopenharmony_ci struct ethtool_rx_flow_spec_input input = {}; 13578c2ecf20Sopenharmony_ci struct ethtool_rx_flow_rule *ethtool_rule; 13588c2ecf20Sopenharmony_ci struct mvpp2_ethtool_fs *efs, *old_efs; 13598c2ecf20Sopenharmony_ci int ret = 0; 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW) 13628c2ecf20Sopenharmony_ci return -EINVAL; 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci efs = kzalloc(sizeof(*efs), GFP_KERNEL); 13658c2ecf20Sopenharmony_ci if (!efs) 13668c2ecf20Sopenharmony_ci return -ENOMEM; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci input.fs = &info->fs; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci /* We need to manually set the rss_ctx, since this info isn't present 13718c2ecf20Sopenharmony_ci * in info->fs 13728c2ecf20Sopenharmony_ci */ 13738c2ecf20Sopenharmony_ci if (info->fs.flow_type & FLOW_RSS) 13748c2ecf20Sopenharmony_ci input.rss_ctx = info->rss_context; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci ethtool_rule = ethtool_rx_flow_rule_create(&input); 13778c2ecf20Sopenharmony_ci if (IS_ERR(ethtool_rule)) { 13788c2ecf20Sopenharmony_ci ret = PTR_ERR(ethtool_rule); 13798c2ecf20Sopenharmony_ci goto clean_rule; 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci efs->rule.flow = ethtool_rule->rule; 13838c2ecf20Sopenharmony_ci efs->rule.flow_type = mvpp2_cls_ethtool_flow_to_type(info->fs.flow_type); 13848c2ecf20Sopenharmony_ci if (efs->rule.flow_type < 0) { 13858c2ecf20Sopenharmony_ci ret = efs->rule.flow_type; 13868c2ecf20Sopenharmony_ci goto clean_rule; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci ret = mvpp2_cls_rfs_parse_rule(&efs->rule); 13908c2ecf20Sopenharmony_ci if (ret) 13918c2ecf20Sopenharmony_ci goto clean_eth_rule; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci efs->rule.loc = info->fs.location; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci /* Replace an already existing rule */ 13968c2ecf20Sopenharmony_ci if (port->rfs_rules[efs->rule.loc]) { 13978c2ecf20Sopenharmony_ci old_efs = port->rfs_rules[efs->rule.loc]; 13988c2ecf20Sopenharmony_ci ret = mvpp2_port_cls_rfs_rule_remove(port, &old_efs->rule); 13998c2ecf20Sopenharmony_ci if (ret) 14008c2ecf20Sopenharmony_ci goto clean_eth_rule; 14018c2ecf20Sopenharmony_ci kfree(old_efs); 14028c2ecf20Sopenharmony_ci port->n_rfs_rules--; 14038c2ecf20Sopenharmony_ci } 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci ret = mvpp2_port_flt_rfs_rule_insert(port, &efs->rule); 14068c2ecf20Sopenharmony_ci if (ret) 14078c2ecf20Sopenharmony_ci goto clean_eth_rule; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci ethtool_rx_flow_rule_destroy(ethtool_rule); 14108c2ecf20Sopenharmony_ci efs->rule.flow = NULL; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci memcpy(&efs->rxnfc, info, sizeof(*info)); 14138c2ecf20Sopenharmony_ci port->rfs_rules[efs->rule.loc] = efs; 14148c2ecf20Sopenharmony_ci port->n_rfs_rules++; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci return ret; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ciclean_eth_rule: 14198c2ecf20Sopenharmony_ci ethtool_rx_flow_rule_destroy(ethtool_rule); 14208c2ecf20Sopenharmony_ciclean_rule: 14218c2ecf20Sopenharmony_ci kfree(efs); 14228c2ecf20Sopenharmony_ci return ret; 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ciint mvpp2_ethtool_cls_rule_del(struct mvpp2_port *port, 14268c2ecf20Sopenharmony_ci struct ethtool_rxnfc *info) 14278c2ecf20Sopenharmony_ci{ 14288c2ecf20Sopenharmony_ci struct mvpp2_ethtool_fs *efs; 14298c2ecf20Sopenharmony_ci int ret; 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW) 14328c2ecf20Sopenharmony_ci return -EINVAL; 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci efs = port->rfs_rules[info->fs.location]; 14358c2ecf20Sopenharmony_ci if (!efs) 14368c2ecf20Sopenharmony_ci return -EINVAL; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci /* Remove the rule from the engines. */ 14398c2ecf20Sopenharmony_ci ret = mvpp2_port_cls_rfs_rule_remove(port, &efs->rule); 14408c2ecf20Sopenharmony_ci if (ret) 14418c2ecf20Sopenharmony_ci return ret; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci port->n_rfs_rules--; 14448c2ecf20Sopenharmony_ci port->rfs_rules[info->fs.location] = NULL; 14458c2ecf20Sopenharmony_ci kfree(efs); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci return 0; 14488c2ecf20Sopenharmony_ci} 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic inline u32 mvpp22_rxfh_indir(struct mvpp2_port *port, u32 rxq) 14518c2ecf20Sopenharmony_ci{ 14528c2ecf20Sopenharmony_ci int nrxqs, cpu, cpus = num_possible_cpus(); 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* Number of RXQs per CPU */ 14558c2ecf20Sopenharmony_ci nrxqs = port->nrxqs / cpus; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* CPU that will handle this rx queue */ 14588c2ecf20Sopenharmony_ci cpu = rxq / nrxqs; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci if (!cpu_online(cpu)) 14618c2ecf20Sopenharmony_ci return port->first_rxq; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* Indirection to better distribute the paquets on the CPUs when 14648c2ecf20Sopenharmony_ci * configuring the RSS queues. 14658c2ecf20Sopenharmony_ci */ 14668c2ecf20Sopenharmony_ci return port->first_rxq + ((rxq * nrxqs + rxq / cpus) % port->nrxqs); 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic void mvpp22_rss_fill_table(struct mvpp2_port *port, 14708c2ecf20Sopenharmony_ci struct mvpp2_rss_table *table, 14718c2ecf20Sopenharmony_ci u32 rss_ctx) 14728c2ecf20Sopenharmony_ci{ 14738c2ecf20Sopenharmony_ci struct mvpp2 *priv = port->priv; 14748c2ecf20Sopenharmony_ci int i; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) { 14778c2ecf20Sopenharmony_ci u32 sel = MVPP22_RSS_INDEX_TABLE(rss_ctx) | 14788c2ecf20Sopenharmony_ci MVPP22_RSS_INDEX_TABLE_ENTRY(i); 14798c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RSS_INDEX, sel); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY, 14828c2ecf20Sopenharmony_ci mvpp22_rxfh_indir(port, table->indir[i])); 14838c2ecf20Sopenharmony_ci } 14848c2ecf20Sopenharmony_ci} 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_cistatic int mvpp22_rss_context_create(struct mvpp2_port *port, u32 *rss_ctx) 14878c2ecf20Sopenharmony_ci{ 14888c2ecf20Sopenharmony_ci struct mvpp2 *priv = port->priv; 14898c2ecf20Sopenharmony_ci u32 ctx; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci /* Find the first free RSS table */ 14928c2ecf20Sopenharmony_ci for (ctx = 0; ctx < MVPP22_N_RSS_TABLES; ctx++) { 14938c2ecf20Sopenharmony_ci if (!priv->rss_tables[ctx]) 14948c2ecf20Sopenharmony_ci break; 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci if (ctx == MVPP22_N_RSS_TABLES) 14988c2ecf20Sopenharmony_ci return -EINVAL; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci priv->rss_tables[ctx] = kzalloc(sizeof(*priv->rss_tables[ctx]), 15018c2ecf20Sopenharmony_ci GFP_KERNEL); 15028c2ecf20Sopenharmony_ci if (!priv->rss_tables[ctx]) 15038c2ecf20Sopenharmony_ci return -ENOMEM; 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci *rss_ctx = ctx; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci /* Set the table width: replace the whole classifier Rx queue number 15088c2ecf20Sopenharmony_ci * with the ones configured in RSS table entries. 15098c2ecf20Sopenharmony_ci */ 15108c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(ctx)); 15118c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RSS_WIDTH, 8); 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(ctx)); 15148c2ecf20Sopenharmony_ci mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE, MVPP22_RSS_TABLE_POINTER(ctx)); 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci return 0; 15178c2ecf20Sopenharmony_ci} 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ciint mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *port_ctx) 15208c2ecf20Sopenharmony_ci{ 15218c2ecf20Sopenharmony_ci u32 rss_ctx; 15228c2ecf20Sopenharmony_ci int ret, i; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci ret = mvpp22_rss_context_create(port, &rss_ctx); 15258c2ecf20Sopenharmony_ci if (ret) 15268c2ecf20Sopenharmony_ci return ret; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci /* Find the first available context number in the port, starting from 1. 15298c2ecf20Sopenharmony_ci * Context 0 on each port is reserved for the default context. 15308c2ecf20Sopenharmony_ci */ 15318c2ecf20Sopenharmony_ci for (i = 1; i < MVPP22_N_RSS_TABLES; i++) { 15328c2ecf20Sopenharmony_ci if (port->rss_ctx[i] < 0) 15338c2ecf20Sopenharmony_ci break; 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci if (i == MVPP22_N_RSS_TABLES) 15378c2ecf20Sopenharmony_ci return -EINVAL; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci port->rss_ctx[i] = rss_ctx; 15408c2ecf20Sopenharmony_ci *port_ctx = i; 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci return 0; 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_cistatic struct mvpp2_rss_table *mvpp22_rss_table_get(struct mvpp2 *priv, 15468c2ecf20Sopenharmony_ci int rss_ctx) 15478c2ecf20Sopenharmony_ci{ 15488c2ecf20Sopenharmony_ci if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES) 15498c2ecf20Sopenharmony_ci return NULL; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci return priv->rss_tables[rss_ctx]; 15528c2ecf20Sopenharmony_ci} 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ciint mvpp22_port_rss_ctx_delete(struct mvpp2_port *port, u32 port_ctx) 15558c2ecf20Sopenharmony_ci{ 15568c2ecf20Sopenharmony_ci struct mvpp2 *priv = port->priv; 15578c2ecf20Sopenharmony_ci struct ethtool_rxnfc *rxnfc; 15588c2ecf20Sopenharmony_ci int i, rss_ctx, ret; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci rss_ctx = mvpp22_rss_ctx(port, port_ctx); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES) 15638c2ecf20Sopenharmony_ci return -EINVAL; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci /* Invalidate any active classification rule that use this context */ 15668c2ecf20Sopenharmony_ci for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) { 15678c2ecf20Sopenharmony_ci if (!port->rfs_rules[i]) 15688c2ecf20Sopenharmony_ci continue; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci rxnfc = &port->rfs_rules[i]->rxnfc; 15718c2ecf20Sopenharmony_ci if (!(rxnfc->fs.flow_type & FLOW_RSS) || 15728c2ecf20Sopenharmony_ci rxnfc->rss_context != port_ctx) 15738c2ecf20Sopenharmony_ci continue; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci ret = mvpp2_ethtool_cls_rule_del(port, rxnfc); 15768c2ecf20Sopenharmony_ci if (ret) { 15778c2ecf20Sopenharmony_ci netdev_warn(port->dev, 15788c2ecf20Sopenharmony_ci "couldn't remove classification rule %d associated to this context", 15798c2ecf20Sopenharmony_ci rxnfc->fs.location); 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci kfree(priv->rss_tables[rss_ctx]); 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci priv->rss_tables[rss_ctx] = NULL; 15868c2ecf20Sopenharmony_ci port->rss_ctx[port_ctx] = -1; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci return 0; 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ciint mvpp22_port_rss_ctx_indir_set(struct mvpp2_port *port, u32 port_ctx, 15928c2ecf20Sopenharmony_ci const u32 *indir) 15938c2ecf20Sopenharmony_ci{ 15948c2ecf20Sopenharmony_ci int rss_ctx = mvpp22_rss_ctx(port, port_ctx); 15958c2ecf20Sopenharmony_ci struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv, 15968c2ecf20Sopenharmony_ci rss_ctx); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci if (!rss_table) 15998c2ecf20Sopenharmony_ci return -EINVAL; 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci memcpy(rss_table->indir, indir, 16028c2ecf20Sopenharmony_ci MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0])); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci mvpp22_rss_fill_table(port, rss_table, rss_ctx); 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci return 0; 16078c2ecf20Sopenharmony_ci} 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ciint mvpp22_port_rss_ctx_indir_get(struct mvpp2_port *port, u32 port_ctx, 16108c2ecf20Sopenharmony_ci u32 *indir) 16118c2ecf20Sopenharmony_ci{ 16128c2ecf20Sopenharmony_ci int rss_ctx = mvpp22_rss_ctx(port, port_ctx); 16138c2ecf20Sopenharmony_ci struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv, 16148c2ecf20Sopenharmony_ci rss_ctx); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci if (!rss_table) 16178c2ecf20Sopenharmony_ci return -EINVAL; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci memcpy(indir, rss_table->indir, 16208c2ecf20Sopenharmony_ci MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0])); 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci return 0; 16238c2ecf20Sopenharmony_ci} 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_ciint mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info) 16268c2ecf20Sopenharmony_ci{ 16278c2ecf20Sopenharmony_ci u16 hash_opts = 0; 16288c2ecf20Sopenharmony_ci u32 flow_type; 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci switch (flow_type) { 16338c2ecf20Sopenharmony_ci case MVPP22_FLOW_TCP4: 16348c2ecf20Sopenharmony_ci case MVPP22_FLOW_UDP4: 16358c2ecf20Sopenharmony_ci case MVPP22_FLOW_TCP6: 16368c2ecf20Sopenharmony_ci case MVPP22_FLOW_UDP6: 16378c2ecf20Sopenharmony_ci if (info->data & RXH_L4_B_0_1) 16388c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP; 16398c2ecf20Sopenharmony_ci if (info->data & RXH_L4_B_2_3) 16408c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP; 16418c2ecf20Sopenharmony_ci fallthrough; 16428c2ecf20Sopenharmony_ci case MVPP22_FLOW_IP4: 16438c2ecf20Sopenharmony_ci case MVPP22_FLOW_IP6: 16448c2ecf20Sopenharmony_ci if (info->data & RXH_L2DA) 16458c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA; 16468c2ecf20Sopenharmony_ci if (info->data & RXH_VLAN) 16478c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_VLAN; 16488c2ecf20Sopenharmony_ci if (info->data & RXH_L3_PROTO) 16498c2ecf20Sopenharmony_ci hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO; 16508c2ecf20Sopenharmony_ci if (info->data & RXH_IP_SRC) 16518c2ecf20Sopenharmony_ci hash_opts |= (MVPP22_CLS_HEK_OPT_IP4SA | 16528c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_OPT_IP6SA); 16538c2ecf20Sopenharmony_ci if (info->data & RXH_IP_DST) 16548c2ecf20Sopenharmony_ci hash_opts |= (MVPP22_CLS_HEK_OPT_IP4DA | 16558c2ecf20Sopenharmony_ci MVPP22_CLS_HEK_OPT_IP6DA); 16568c2ecf20Sopenharmony_ci break; 16578c2ecf20Sopenharmony_ci default: return -EOPNOTSUPP; 16588c2ecf20Sopenharmony_ci } 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci return mvpp2_port_rss_hash_opts_set(port, flow_type, hash_opts); 16618c2ecf20Sopenharmony_ci} 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ciint mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci unsigned long hash_opts; 16668c2ecf20Sopenharmony_ci u32 flow_type; 16678c2ecf20Sopenharmony_ci int i; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type); 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_ci hash_opts = mvpp2_port_rss_hash_opts_get(port, flow_type); 16728c2ecf20Sopenharmony_ci info->data = 0; 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) { 16758c2ecf20Sopenharmony_ci switch (BIT(i)) { 16768c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_MAC_DA: 16778c2ecf20Sopenharmony_ci info->data |= RXH_L2DA; 16788c2ecf20Sopenharmony_ci break; 16798c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_VLAN: 16808c2ecf20Sopenharmony_ci info->data |= RXH_VLAN; 16818c2ecf20Sopenharmony_ci break; 16828c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L3_PROTO: 16838c2ecf20Sopenharmony_ci info->data |= RXH_L3_PROTO; 16848c2ecf20Sopenharmony_ci break; 16858c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4SA: 16868c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6SA: 16878c2ecf20Sopenharmony_ci info->data |= RXH_IP_SRC; 16888c2ecf20Sopenharmony_ci break; 16898c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP4DA: 16908c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_IP6DA: 16918c2ecf20Sopenharmony_ci info->data |= RXH_IP_DST; 16928c2ecf20Sopenharmony_ci break; 16938c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4SIP: 16948c2ecf20Sopenharmony_ci info->data |= RXH_L4_B_0_1; 16958c2ecf20Sopenharmony_ci break; 16968c2ecf20Sopenharmony_ci case MVPP22_CLS_HEK_OPT_L4DIP: 16978c2ecf20Sopenharmony_ci info->data |= RXH_L4_B_2_3; 16988c2ecf20Sopenharmony_ci break; 16998c2ecf20Sopenharmony_ci default: 17008c2ecf20Sopenharmony_ci return -EINVAL; 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci } 17038c2ecf20Sopenharmony_ci return 0; 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ciint mvpp22_port_rss_init(struct mvpp2_port *port) 17078c2ecf20Sopenharmony_ci{ 17088c2ecf20Sopenharmony_ci struct mvpp2_rss_table *table; 17098c2ecf20Sopenharmony_ci u32 context = 0; 17108c2ecf20Sopenharmony_ci int i, ret; 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci for (i = 0; i < MVPP22_N_RSS_TABLES; i++) 17138c2ecf20Sopenharmony_ci port->rss_ctx[i] = -1; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci ret = mvpp22_rss_context_create(port, &context); 17168c2ecf20Sopenharmony_ci if (ret) 17178c2ecf20Sopenharmony_ci return ret; 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci table = mvpp22_rss_table_get(port->priv, context); 17208c2ecf20Sopenharmony_ci if (!table) 17218c2ecf20Sopenharmony_ci return -EINVAL; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci port->rss_ctx[0] = context; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci /* Configure the first table to evenly distribute the packets across 17268c2ecf20Sopenharmony_ci * real Rx Queues. The table entries map a hash to a port Rx Queue. 17278c2ecf20Sopenharmony_ci */ 17288c2ecf20Sopenharmony_ci for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) 17298c2ecf20Sopenharmony_ci table->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci mvpp22_rss_fill_table(port, table, mvpp22_rss_ctx(port, 0)); 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci /* Configure default flows */ 17348c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP4, MVPP22_CLS_HEK_IP4_2T); 17358c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP6, MVPP22_CLS_HEK_IP6_2T); 17368c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP4, MVPP22_CLS_HEK_IP4_5T); 17378c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP6, MVPP22_CLS_HEK_IP6_5T); 17388c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP4, MVPP22_CLS_HEK_IP4_5T); 17398c2ecf20Sopenharmony_ci mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP6, MVPP22_CLS_HEK_IP6_5T); 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci return 0; 17428c2ecf20Sopenharmony_ci} 1743