cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mvpp2_cls.c (50125B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * RSS and Classifier helpers for Marvell PPv2 Network Controller
      4 *
      5 * Copyright (C) 2014 Marvell
      6 *
      7 * Marcin Wojtas <mw@semihalf.com>
      8 */
      9
     10#include "mvpp2.h"
     11#include "mvpp2_cls.h"
     12#include "mvpp2_prs.h"
     13
     14#define MVPP2_DEF_FLOW(_type, _id, _opts, _ri, _ri_mask)	\
     15{								\
     16	.flow_type = _type,					\
     17	.flow_id = _id,						\
     18	.supported_hash_opts = _opts,				\
     19	.prs_ri = {						\
     20		.ri = _ri,					\
     21		.ri_mask = _ri_mask				\
     22	}							\
     23}
     24
     25static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
     26	/* TCP over IPv4 flows, Not fragmented, no vlan tag */
     27	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
     28		       MVPP22_CLS_HEK_IP4_5T,
     29		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
     30		       MVPP2_PRS_RI_L4_TCP,
     31		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     32
     33	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
     34		       MVPP22_CLS_HEK_IP4_5T,
     35		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
     36		       MVPP2_PRS_RI_L4_TCP,
     37		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     38
     39	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_UNTAG,
     40		       MVPP22_CLS_HEK_IP4_5T,
     41		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
     42		       MVPP2_PRS_RI_L4_TCP,
     43		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     44
     45	/* TCP over IPv4 flows, Not fragmented, with vlan tag */
     46	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
     47		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
     48		       MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP,
     49		       MVPP2_PRS_IP_MASK),
     50
     51	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
     52		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
     53		       MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP,
     54		       MVPP2_PRS_IP_MASK),
     55
     56	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_NF_TAG,
     57		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
     58		       MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP,
     59		       MVPP2_PRS_IP_MASK),
     60
     61	/* TCP over IPv4 flows, fragmented, no vlan tag */
     62	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
     63		       MVPP22_CLS_HEK_IP4_2T,
     64		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
     65		       MVPP2_PRS_RI_L4_TCP,
     66		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     67
     68	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
     69		       MVPP22_CLS_HEK_IP4_2T,
     70		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
     71		       MVPP2_PRS_RI_L4_TCP,
     72		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     73
     74	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_UNTAG,
     75		       MVPP22_CLS_HEK_IP4_2T,
     76		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
     77		       MVPP2_PRS_RI_L4_TCP,
     78		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
     79
     80	/* TCP over IPv4 flows, fragmented, with vlan tag */
     81	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
     82		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
     83		       MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_TCP,
     84		       MVPP2_PRS_IP_MASK),
     85
     86	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
     87		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
     88		       MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_TCP,
     89		       MVPP2_PRS_IP_MASK),
     90
     91	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP4, MVPP2_FL_IP4_TCP_FRAG_TAG,
     92		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
     93		       MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_TCP,
     94		       MVPP2_PRS_IP_MASK),
     95
     96	/* UDP over IPv4 flows, Not fragmented, no vlan tag */
     97	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
     98		       MVPP22_CLS_HEK_IP4_5T,
     99		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
    100		       MVPP2_PRS_RI_L4_UDP,
    101		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    102
    103	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
    104		       MVPP22_CLS_HEK_IP4_5T,
    105		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
    106		       MVPP2_PRS_RI_L4_UDP,
    107		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    108
    109	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_UNTAG,
    110		       MVPP22_CLS_HEK_IP4_5T,
    111		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
    112		       MVPP2_PRS_RI_L4_UDP,
    113		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    114
    115	/* UDP over IPv4 flows, Not fragmented, with vlan tag */
    116	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
    117		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
    118		       MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP,
    119		       MVPP2_PRS_IP_MASK),
    120
    121	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
    122		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
    123		       MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP,
    124		       MVPP2_PRS_IP_MASK),
    125
    126	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_NF_TAG,
    127		       MVPP22_CLS_HEK_IP4_5T | MVPP22_CLS_HEK_TAGGED,
    128		       MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP,
    129		       MVPP2_PRS_IP_MASK),
    130
    131	/* UDP over IPv4 flows, fragmented, no vlan tag */
    132	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
    133		       MVPP22_CLS_HEK_IP4_2T,
    134		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4 |
    135		       MVPP2_PRS_RI_L4_UDP,
    136		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    137
    138	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
    139		       MVPP22_CLS_HEK_IP4_2T,
    140		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT |
    141		       MVPP2_PRS_RI_L4_UDP,
    142		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    143
    144	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_UNTAG,
    145		       MVPP22_CLS_HEK_IP4_2T,
    146		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER |
    147		       MVPP2_PRS_RI_L4_UDP,
    148		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    149
    150	/* UDP over IPv4 flows, fragmented, with vlan tag */
    151	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
    152		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    153		       MVPP2_PRS_RI_L3_IP4 | MVPP2_PRS_RI_L4_UDP,
    154		       MVPP2_PRS_IP_MASK),
    155
    156	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
    157		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    158		       MVPP2_PRS_RI_L3_IP4_OPT | MVPP2_PRS_RI_L4_UDP,
    159		       MVPP2_PRS_IP_MASK),
    160
    161	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP4, MVPP2_FL_IP4_UDP_FRAG_TAG,
    162		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    163		       MVPP2_PRS_RI_L3_IP4_OTHER | MVPP2_PRS_RI_L4_UDP,
    164		       MVPP2_PRS_IP_MASK),
    165
    166	/* TCP over IPv6 flows, not fragmented, no vlan tag */
    167	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG,
    168		       MVPP22_CLS_HEK_IP6_5T,
    169		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
    170		       MVPP2_PRS_RI_L4_TCP,
    171		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    172
    173	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_UNTAG,
    174		       MVPP22_CLS_HEK_IP6_5T,
    175		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
    176		       MVPP2_PRS_RI_L4_TCP,
    177		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    178
    179	/* TCP over IPv6 flows, not fragmented, with vlan tag */
    180	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG,
    181		       MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
    182		       MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_TCP,
    183		       MVPP2_PRS_IP_MASK),
    184
    185	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_NF_TAG,
    186		       MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
    187		       MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_TCP,
    188		       MVPP2_PRS_IP_MASK),
    189
    190	/* TCP over IPv6 flows, fragmented, no vlan tag */
    191	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
    192		       MVPP22_CLS_HEK_IP6_2T,
    193		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
    194		       MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
    195		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    196
    197	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_UNTAG,
    198		       MVPP22_CLS_HEK_IP6_2T,
    199		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
    200		       MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_TCP,
    201		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    202
    203	/* TCP over IPv6 flows, fragmented, with vlan tag */
    204	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG,
    205		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    206		       MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE |
    207		       MVPP2_PRS_RI_L4_TCP,
    208		       MVPP2_PRS_IP_MASK),
    209
    210	MVPP2_DEF_FLOW(MVPP22_FLOW_TCP6, MVPP2_FL_IP6_TCP_FRAG_TAG,
    211		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    212		       MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE |
    213		       MVPP2_PRS_RI_L4_TCP,
    214		       MVPP2_PRS_IP_MASK),
    215
    216	/* UDP over IPv6 flows, not fragmented, no vlan tag */
    217	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG,
    218		       MVPP22_CLS_HEK_IP6_5T,
    219		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
    220		       MVPP2_PRS_RI_L4_UDP,
    221		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    222
    223	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_UNTAG,
    224		       MVPP22_CLS_HEK_IP6_5T,
    225		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
    226		       MVPP2_PRS_RI_L4_UDP,
    227		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    228
    229	/* UDP over IPv6 flows, not fragmented, with vlan tag */
    230	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG,
    231		       MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
    232		       MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_L4_UDP,
    233		       MVPP2_PRS_IP_MASK),
    234
    235	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_NF_TAG,
    236		       MVPP22_CLS_HEK_IP6_5T | MVPP22_CLS_HEK_TAGGED,
    237		       MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_L4_UDP,
    238		       MVPP2_PRS_IP_MASK),
    239
    240	/* UDP over IPv6 flows, fragmented, no vlan tag */
    241	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
    242		       MVPP22_CLS_HEK_IP6_2T,
    243		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6 |
    244		       MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
    245		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    246
    247	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_UNTAG,
    248		       MVPP22_CLS_HEK_IP6_2T,
    249		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6_EXT |
    250		       MVPP2_PRS_RI_IP_FRAG_TRUE | MVPP2_PRS_RI_L4_UDP,
    251		       MVPP2_PRS_IP_MASK | MVPP2_PRS_RI_VLAN_MASK),
    252
    253	/* UDP over IPv6 flows, fragmented, with vlan tag */
    254	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG,
    255		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    256		       MVPP2_PRS_RI_L3_IP6 | MVPP2_PRS_RI_IP_FRAG_TRUE |
    257		       MVPP2_PRS_RI_L4_UDP,
    258		       MVPP2_PRS_IP_MASK),
    259
    260	MVPP2_DEF_FLOW(MVPP22_FLOW_UDP6, MVPP2_FL_IP6_UDP_FRAG_TAG,
    261		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    262		       MVPP2_PRS_RI_L3_IP6_EXT | MVPP2_PRS_RI_IP_FRAG_TRUE |
    263		       MVPP2_PRS_RI_L4_UDP,
    264		       MVPP2_PRS_IP_MASK),
    265
    266	/* IPv4 flows, no vlan tag */
    267	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
    268		       MVPP22_CLS_HEK_IP4_2T,
    269		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4,
    270		       MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
    271	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
    272		       MVPP22_CLS_HEK_IP4_2T,
    273		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OPT,
    274		       MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
    275	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_UNTAG,
    276		       MVPP22_CLS_HEK_IP4_2T,
    277		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP4_OTHER,
    278		       MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
    279
    280	/* IPv4 flows, with vlan tag */
    281	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
    282		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    283		       MVPP2_PRS_RI_L3_IP4,
    284		       MVPP2_PRS_RI_L3_PROTO_MASK),
    285	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
    286		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    287		       MVPP2_PRS_RI_L3_IP4_OPT,
    288		       MVPP2_PRS_RI_L3_PROTO_MASK),
    289	MVPP2_DEF_FLOW(MVPP22_FLOW_IP4, MVPP2_FL_IP4_TAG,
    290		       MVPP22_CLS_HEK_IP4_2T | MVPP22_CLS_HEK_TAGGED,
    291		       MVPP2_PRS_RI_L3_IP4_OTHER,
    292		       MVPP2_PRS_RI_L3_PROTO_MASK),
    293
    294	/* IPv6 flows, no vlan tag */
    295	MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG,
    296		       MVPP22_CLS_HEK_IP6_2T,
    297		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6,
    298		       MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
    299	MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_UNTAG,
    300		       MVPP22_CLS_HEK_IP6_2T,
    301		       MVPP2_PRS_RI_VLAN_NONE | MVPP2_PRS_RI_L3_IP6,
    302		       MVPP2_PRS_RI_VLAN_MASK | MVPP2_PRS_RI_L3_PROTO_MASK),
    303
    304	/* IPv6 flows, with vlan tag */
    305	MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG,
    306		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    307		       MVPP2_PRS_RI_L3_IP6,
    308		       MVPP2_PRS_RI_L3_PROTO_MASK),
    309	MVPP2_DEF_FLOW(MVPP22_FLOW_IP6, MVPP2_FL_IP6_TAG,
    310		       MVPP22_CLS_HEK_IP6_2T | MVPP22_CLS_HEK_TAGGED,
    311		       MVPP2_PRS_RI_L3_IP6,
    312		       MVPP2_PRS_RI_L3_PROTO_MASK),
    313
    314	/* Non IP flow, no vlan tag */
    315	MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_UNTAG,
    316		       0,
    317		       MVPP2_PRS_RI_VLAN_NONE,
    318		       MVPP2_PRS_RI_VLAN_MASK),
    319	/* Non IP flow, with vlan tag */
    320	MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG,
    321		       MVPP22_CLS_HEK_OPT_VLAN,
    322		       0, 0),
    323};
    324
    325u32 mvpp2_cls_flow_hits(struct mvpp2 *priv, int index)
    326{
    327	mvpp2_write(priv, MVPP2_CTRS_IDX, index);
    328
    329	return mvpp2_read(priv, MVPP2_CLS_FLOW_TBL_HIT_CTR);
    330}
    331
    332void mvpp2_cls_flow_read(struct mvpp2 *priv, int index,
    333			 struct mvpp2_cls_flow_entry *fe)
    334{
    335	fe->index = index;
    336	mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, index);
    337	fe->data[0] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL0_REG);
    338	fe->data[1] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL1_REG);
    339	fe->data[2] = mvpp2_read(priv, MVPP2_CLS_FLOW_TBL2_REG);
    340}
    341
    342/* Update classification flow table registers */
    343static void mvpp2_cls_flow_write(struct mvpp2 *priv,
    344				 struct mvpp2_cls_flow_entry *fe)
    345{
    346	mvpp2_write(priv, MVPP2_CLS_FLOW_INDEX_REG, fe->index);
    347	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL0_REG, fe->data[0]);
    348	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL1_REG, fe->data[1]);
    349	mvpp2_write(priv, MVPP2_CLS_FLOW_TBL2_REG, fe->data[2]);
    350}
    351
    352u32 mvpp2_cls_lookup_hits(struct mvpp2 *priv, int index)
    353{
    354	mvpp2_write(priv, MVPP2_CTRS_IDX, index);
    355
    356	return mvpp2_read(priv, MVPP2_CLS_DEC_TBL_HIT_CTR);
    357}
    358
    359void mvpp2_cls_lookup_read(struct mvpp2 *priv, int lkpid, int way,
    360			   struct mvpp2_cls_lookup_entry *le)
    361{
    362	u32 val;
    363
    364	val = (way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | lkpid;
    365	mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val);
    366	le->way = way;
    367	le->lkpid = lkpid;
    368	le->data = mvpp2_read(priv, MVPP2_CLS_LKP_TBL_REG);
    369}
    370
    371/* Update classification lookup table register */
    372static void mvpp2_cls_lookup_write(struct mvpp2 *priv,
    373				   struct mvpp2_cls_lookup_entry *le)
    374{
    375	u32 val;
    376
    377	val = (le->way << MVPP2_CLS_LKP_INDEX_WAY_OFFS) | le->lkpid;
    378	mvpp2_write(priv, MVPP2_CLS_LKP_INDEX_REG, val);
    379	mvpp2_write(priv, MVPP2_CLS_LKP_TBL_REG, le->data);
    380}
    381
    382/* Operations on flow entry */
    383static int mvpp2_cls_flow_hek_num_get(struct mvpp2_cls_flow_entry *fe)
    384{
    385	return fe->data[1] & MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK;
    386}
    387
    388static void mvpp2_cls_flow_hek_num_set(struct mvpp2_cls_flow_entry *fe,
    389				       int num_of_fields)
    390{
    391	fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_N_FIELDS_MASK;
    392	fe->data[1] |= MVPP2_CLS_FLOW_TBL1_N_FIELDS(num_of_fields);
    393}
    394
    395static int mvpp2_cls_flow_hek_get(struct mvpp2_cls_flow_entry *fe,
    396				  int field_index)
    397{
    398	return (fe->data[2] >> MVPP2_CLS_FLOW_TBL2_FLD_OFFS(field_index)) &
    399		MVPP2_CLS_FLOW_TBL2_FLD_MASK;
    400}
    401
    402static void mvpp2_cls_flow_hek_set(struct mvpp2_cls_flow_entry *fe,
    403				   int field_index, int field_id)
    404{
    405	fe->data[2] &= ~MVPP2_CLS_FLOW_TBL2_FLD(field_index,
    406						MVPP2_CLS_FLOW_TBL2_FLD_MASK);
    407	fe->data[2] |= MVPP2_CLS_FLOW_TBL2_FLD(field_index, field_id);
    408}
    409
    410static void mvpp2_cls_flow_eng_set(struct mvpp2_cls_flow_entry *fe,
    411				   int engine)
    412{
    413	fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_ENG(MVPP2_CLS_FLOW_TBL0_ENG_MASK);
    414	fe->data[0] |= MVPP2_CLS_FLOW_TBL0_ENG(engine);
    415}
    416
    417int mvpp2_cls_flow_eng_get(struct mvpp2_cls_flow_entry *fe)
    418{
    419	return (fe->data[0] >> MVPP2_CLS_FLOW_TBL0_OFFS) &
    420		MVPP2_CLS_FLOW_TBL0_ENG_MASK;
    421}
    422
    423static void mvpp2_cls_flow_port_id_sel(struct mvpp2_cls_flow_entry *fe,
    424				       bool from_packet)
    425{
    426	if (from_packet)
    427		fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL;
    428	else
    429		fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID_SEL;
    430}
    431
    432static void mvpp2_cls_flow_last_set(struct mvpp2_cls_flow_entry *fe,
    433				    bool is_last)
    434{
    435	fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_LAST;
    436	fe->data[0] |= !!is_last;
    437}
    438
    439static void mvpp2_cls_flow_pri_set(struct mvpp2_cls_flow_entry *fe, int prio)
    440{
    441	fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_PRIO(MVPP2_CLS_FLOW_TBL1_PRIO_MASK);
    442	fe->data[1] |= MVPP2_CLS_FLOW_TBL1_PRIO(prio);
    443}
    444
    445static void mvpp2_cls_flow_port_add(struct mvpp2_cls_flow_entry *fe,
    446				    u32 port)
    447{
    448	fe->data[0] |= MVPP2_CLS_FLOW_TBL0_PORT_ID(port);
    449}
    450
    451static void mvpp2_cls_flow_port_remove(struct mvpp2_cls_flow_entry *fe,
    452				       u32 port)
    453{
    454	fe->data[0] &= ~MVPP2_CLS_FLOW_TBL0_PORT_ID(port);
    455}
    456
    457static void mvpp2_cls_flow_lu_type_set(struct mvpp2_cls_flow_entry *fe,
    458				       u8 lu_type)
    459{
    460	fe->data[1] &= ~MVPP2_CLS_FLOW_TBL1_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK);
    461	fe->data[1] |= MVPP2_CLS_FLOW_TBL1_LU_TYPE(lu_type);
    462}
    463
    464/* Initialize the parser entry for the given flow */
    465static void mvpp2_cls_flow_prs_init(struct mvpp2 *priv,
    466				    const struct mvpp2_cls_flow *flow)
    467{
    468	mvpp2_prs_add_flow(priv, flow->flow_id, flow->prs_ri.ri,
    469			   flow->prs_ri.ri_mask);
    470}
    471
    472/* Initialize the Lookup Id table entry for the given flow */
    473static void mvpp2_cls_flow_lkp_init(struct mvpp2 *priv,
    474				    const struct mvpp2_cls_flow *flow)
    475{
    476	struct mvpp2_cls_lookup_entry le;
    477
    478	le.way = 0;
    479	le.lkpid = flow->flow_id;
    480
    481	/* The default RxQ for this port is set in the C2 lookup */
    482	le.data = 0;
    483
    484	/* We point on the first lookup in the sequence for the flow, that is
    485	 * the C2 lookup.
    486	 */
    487	le.data |= MVPP2_CLS_LKP_FLOW_PTR(MVPP2_CLS_FLT_FIRST(flow->flow_id));
    488
    489	/* CLS is always enabled, RSS is enabled/disabled in C2 lookup */
    490	le.data |= MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
    491
    492	mvpp2_cls_lookup_write(priv, &le);
    493}
    494
    495static void mvpp2_cls_c2_write(struct mvpp2 *priv,
    496			       struct mvpp2_cls_c2_entry *c2)
    497{
    498	u32 val;
    499	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2->index);
    500
    501	val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
    502	if (c2->valid)
    503		val &= ~MVPP22_CLS_C2_TCAM_INV_BIT;
    504	else
    505		val |= MVPP22_CLS_C2_TCAM_INV_BIT;
    506	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_INV, val);
    507
    508	mvpp2_write(priv, MVPP22_CLS_C2_ACT, c2->act);
    509
    510	mvpp2_write(priv, MVPP22_CLS_C2_ATTR0, c2->attr[0]);
    511	mvpp2_write(priv, MVPP22_CLS_C2_ATTR1, c2->attr[1]);
    512	mvpp2_write(priv, MVPP22_CLS_C2_ATTR2, c2->attr[2]);
    513	mvpp2_write(priv, MVPP22_CLS_C2_ATTR3, c2->attr[3]);
    514
    515	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA0, c2->tcam[0]);
    516	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA1, c2->tcam[1]);
    517	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA2, c2->tcam[2]);
    518	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA3, c2->tcam[3]);
    519	/* Writing TCAM_DATA4 flushes writes to TCAM_DATA0-4 and INV to HW */
    520	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_DATA4, c2->tcam[4]);
    521}
    522
    523void mvpp2_cls_c2_read(struct mvpp2 *priv, int index,
    524		       struct mvpp2_cls_c2_entry *c2)
    525{
    526	u32 val;
    527	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, index);
    528
    529	c2->index = index;
    530
    531	c2->tcam[0] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA0);
    532	c2->tcam[1] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA1);
    533	c2->tcam[2] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA2);
    534	c2->tcam[3] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA3);
    535	c2->tcam[4] = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_DATA4);
    536
    537	c2->act = mvpp2_read(priv, MVPP22_CLS_C2_ACT);
    538
    539	c2->attr[0] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR0);
    540	c2->attr[1] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR1);
    541	c2->attr[2] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR2);
    542	c2->attr[3] = mvpp2_read(priv, MVPP22_CLS_C2_ATTR3);
    543
    544	val = mvpp2_read(priv, MVPP22_CLS_C2_TCAM_INV);
    545	c2->valid = !(val & MVPP22_CLS_C2_TCAM_INV_BIT);
    546}
    547
    548static int mvpp2_cls_ethtool_flow_to_type(int flow_type)
    549{
    550	switch (flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) {
    551	case ETHER_FLOW:
    552		return MVPP22_FLOW_ETHERNET;
    553	case TCP_V4_FLOW:
    554		return MVPP22_FLOW_TCP4;
    555	case TCP_V6_FLOW:
    556		return MVPP22_FLOW_TCP6;
    557	case UDP_V4_FLOW:
    558		return MVPP22_FLOW_UDP4;
    559	case UDP_V6_FLOW:
    560		return MVPP22_FLOW_UDP6;
    561	case IPV4_FLOW:
    562		return MVPP22_FLOW_IP4;
    563	case IPV6_FLOW:
    564		return MVPP22_FLOW_IP6;
    565	default:
    566		return -EOPNOTSUPP;
    567	}
    568}
    569
    570static int mvpp2_cls_c2_port_flow_index(struct mvpp2_port *port, int loc)
    571{
    572	return MVPP22_CLS_C2_RFS_LOC(port->id, loc);
    573}
    574
    575/* Initialize the flow table entries for the given flow */
    576static void mvpp2_cls_flow_init(struct mvpp2 *priv,
    577				const struct mvpp2_cls_flow *flow)
    578{
    579	struct mvpp2_cls_flow_entry fe;
    580	int i, pri = 0;
    581
    582	/* Assign default values to all entries in the flow */
    583	for (i = MVPP2_CLS_FLT_FIRST(flow->flow_id);
    584	     i <= MVPP2_CLS_FLT_LAST(flow->flow_id); i++) {
    585		memset(&fe, 0, sizeof(fe));
    586		fe.index = i;
    587		mvpp2_cls_flow_pri_set(&fe, pri++);
    588
    589		if (i == MVPP2_CLS_FLT_LAST(flow->flow_id))
    590			mvpp2_cls_flow_last_set(&fe, 1);
    591
    592		mvpp2_cls_flow_write(priv, &fe);
    593	}
    594
    595	/* RSS config C2 lookup */
    596	mvpp2_cls_flow_read(priv, MVPP2_CLS_FLT_C2_RSS_ENTRY(flow->flow_id),
    597			    &fe);
    598
    599	mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C2);
    600	mvpp2_cls_flow_port_id_sel(&fe, true);
    601	mvpp2_cls_flow_lu_type_set(&fe, MVPP22_CLS_LU_TYPE_ALL);
    602
    603	/* Add all ports */
    604	for (i = 0; i < MVPP2_MAX_PORTS; i++)
    605		mvpp2_cls_flow_port_add(&fe, BIT(i));
    606
    607	mvpp2_cls_flow_write(priv, &fe);
    608
    609	/* C3Hx lookups */
    610	for (i = 0; i < MVPP2_MAX_PORTS; i++) {
    611		mvpp2_cls_flow_read(priv,
    612				    MVPP2_CLS_FLT_HASH_ENTRY(i, flow->flow_id),
    613				    &fe);
    614
    615		/* Set a default engine. Will be overwritten when setting the
    616		 * real HEK parameters
    617		 */
    618		mvpp2_cls_flow_eng_set(&fe, MVPP22_CLS_ENGINE_C3HA);
    619		mvpp2_cls_flow_port_id_sel(&fe, true);
    620		mvpp2_cls_flow_port_add(&fe, BIT(i));
    621
    622		mvpp2_cls_flow_write(priv, &fe);
    623	}
    624}
    625
    626/* Adds a field to the Header Extracted Key generation parameters*/
    627static int mvpp2_flow_add_hek_field(struct mvpp2_cls_flow_entry *fe,
    628				    u32 field_id)
    629{
    630	int nb_fields = mvpp2_cls_flow_hek_num_get(fe);
    631
    632	if (nb_fields == MVPP2_FLOW_N_FIELDS)
    633		return -EINVAL;
    634
    635	mvpp2_cls_flow_hek_set(fe, nb_fields, field_id);
    636
    637	mvpp2_cls_flow_hek_num_set(fe, nb_fields + 1);
    638
    639	return 0;
    640}
    641
    642static int mvpp2_flow_set_hek_fields(struct mvpp2_cls_flow_entry *fe,
    643				     unsigned long hash_opts)
    644{
    645	u32 field_id;
    646	int i;
    647
    648	/* Clear old fields */
    649	mvpp2_cls_flow_hek_num_set(fe, 0);
    650	fe->data[2] = 0;
    651
    652	for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
    653		switch (BIT(i)) {
    654		case MVPP22_CLS_HEK_OPT_MAC_DA:
    655			field_id = MVPP22_CLS_FIELD_MAC_DA;
    656			break;
    657		case MVPP22_CLS_HEK_OPT_VLAN:
    658			field_id = MVPP22_CLS_FIELD_VLAN;
    659			break;
    660		case MVPP22_CLS_HEK_OPT_VLAN_PRI:
    661			field_id = MVPP22_CLS_FIELD_VLAN_PRI;
    662			break;
    663		case MVPP22_CLS_HEK_OPT_IP4SA:
    664			field_id = MVPP22_CLS_FIELD_IP4SA;
    665			break;
    666		case MVPP22_CLS_HEK_OPT_IP4DA:
    667			field_id = MVPP22_CLS_FIELD_IP4DA;
    668			break;
    669		case MVPP22_CLS_HEK_OPT_IP6SA:
    670			field_id = MVPP22_CLS_FIELD_IP6SA;
    671			break;
    672		case MVPP22_CLS_HEK_OPT_IP6DA:
    673			field_id = MVPP22_CLS_FIELD_IP6DA;
    674			break;
    675		case MVPP22_CLS_HEK_OPT_L4SIP:
    676			field_id = MVPP22_CLS_FIELD_L4SIP;
    677			break;
    678		case MVPP22_CLS_HEK_OPT_L4DIP:
    679			field_id = MVPP22_CLS_FIELD_L4DIP;
    680			break;
    681		default:
    682			return -EINVAL;
    683		}
    684		if (mvpp2_flow_add_hek_field(fe, field_id))
    685			return -EINVAL;
    686	}
    687
    688	return 0;
    689}
    690
    691/* Returns the size, in bits, of the corresponding HEK field */
    692static int mvpp2_cls_hek_field_size(u32 field)
    693{
    694	switch (field) {
    695	case MVPP22_CLS_HEK_OPT_MAC_DA:
    696		return 48;
    697	case MVPP22_CLS_HEK_OPT_VLAN:
    698		return 12;
    699	case MVPP22_CLS_HEK_OPT_VLAN_PRI:
    700		return 3;
    701	case MVPP22_CLS_HEK_OPT_IP4SA:
    702	case MVPP22_CLS_HEK_OPT_IP4DA:
    703		return 32;
    704	case MVPP22_CLS_HEK_OPT_IP6SA:
    705	case MVPP22_CLS_HEK_OPT_IP6DA:
    706		return 128;
    707	case MVPP22_CLS_HEK_OPT_L4SIP:
    708	case MVPP22_CLS_HEK_OPT_L4DIP:
    709		return 16;
    710	default:
    711		return -1;
    712	}
    713}
    714
    715const struct mvpp2_cls_flow *mvpp2_cls_flow_get(int flow)
    716{
    717	if (flow >= MVPP2_N_PRS_FLOWS)
    718		return NULL;
    719
    720	return &cls_flows[flow];
    721}
    722
    723/* Set the hash generation options for the given traffic flow.
    724 * One traffic flow (in the ethtool sense) has multiple classification flows,
    725 * to handle specific cases such as fragmentation, or the presence of a
    726 * VLAN / DSA Tag.
    727 *
    728 * Each of these individual flows has different constraints, for example we
    729 * can't hash fragmented packets on L4 data (else we would risk having packet
    730 * re-ordering), so each classification flows masks the options with their
    731 * supported ones.
    732 *
    733 */
    734static int mvpp2_port_rss_hash_opts_set(struct mvpp2_port *port, int flow_type,
    735					u16 requested_opts)
    736{
    737	const struct mvpp2_cls_flow *flow;
    738	struct mvpp2_cls_flow_entry fe;
    739	int i, engine, flow_index;
    740	u16 hash_opts;
    741
    742	for_each_cls_flow_id_with_type(i, flow_type) {
    743		flow = mvpp2_cls_flow_get(i);
    744		if (!flow)
    745			return -EINVAL;
    746
    747		flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);
    748
    749		mvpp2_cls_flow_read(port->priv, flow_index, &fe);
    750
    751		hash_opts = flow->supported_hash_opts & requested_opts;
    752
    753		/* Use C3HB engine to access L4 infos. This adds L4 infos to the
    754		 * hash parameters
    755		 */
    756		if (hash_opts & MVPP22_CLS_HEK_L4_OPTS)
    757			engine = MVPP22_CLS_ENGINE_C3HB;
    758		else
    759			engine = MVPP22_CLS_ENGINE_C3HA;
    760
    761		if (mvpp2_flow_set_hek_fields(&fe, hash_opts))
    762			return -EINVAL;
    763
    764		mvpp2_cls_flow_eng_set(&fe, engine);
    765
    766		mvpp2_cls_flow_write(port->priv, &fe);
    767	}
    768
    769	return 0;
    770}
    771
    772u16 mvpp2_flow_get_hek_fields(struct mvpp2_cls_flow_entry *fe)
    773{
    774	u16 hash_opts = 0;
    775	int n_fields, i, field;
    776
    777	n_fields = mvpp2_cls_flow_hek_num_get(fe);
    778
    779	for (i = 0; i < n_fields; i++) {
    780		field = mvpp2_cls_flow_hek_get(fe, i);
    781
    782		switch (field) {
    783		case MVPP22_CLS_FIELD_MAC_DA:
    784			hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA;
    785			break;
    786		case MVPP22_CLS_FIELD_VLAN:
    787			hash_opts |= MVPP22_CLS_HEK_OPT_VLAN;
    788			break;
    789		case MVPP22_CLS_FIELD_VLAN_PRI:
    790			hash_opts |= MVPP22_CLS_HEK_OPT_VLAN_PRI;
    791			break;
    792		case MVPP22_CLS_FIELD_L3_PROTO:
    793			hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO;
    794			break;
    795		case MVPP22_CLS_FIELD_IP4SA:
    796			hash_opts |= MVPP22_CLS_HEK_OPT_IP4SA;
    797			break;
    798		case MVPP22_CLS_FIELD_IP4DA:
    799			hash_opts |= MVPP22_CLS_HEK_OPT_IP4DA;
    800			break;
    801		case MVPP22_CLS_FIELD_IP6SA:
    802			hash_opts |= MVPP22_CLS_HEK_OPT_IP6SA;
    803			break;
    804		case MVPP22_CLS_FIELD_IP6DA:
    805			hash_opts |= MVPP22_CLS_HEK_OPT_IP6DA;
    806			break;
    807		case MVPP22_CLS_FIELD_L4SIP:
    808			hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP;
    809			break;
    810		case MVPP22_CLS_FIELD_L4DIP:
    811			hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP;
    812			break;
    813		default:
    814			break;
    815		}
    816	}
    817	return hash_opts;
    818}
    819
    820/* Returns the hash opts for this flow. There are several classifier flows
    821 * for one traffic flow, this returns an aggregation of all configurations.
    822 */
    823static u16 mvpp2_port_rss_hash_opts_get(struct mvpp2_port *port, int flow_type)
    824{
    825	const struct mvpp2_cls_flow *flow;
    826	struct mvpp2_cls_flow_entry fe;
    827	int i, flow_index;
    828	u16 hash_opts = 0;
    829
    830	for_each_cls_flow_id_with_type(i, flow_type) {
    831		flow = mvpp2_cls_flow_get(i);
    832		if (!flow)
    833			return 0;
    834
    835		flow_index = MVPP2_CLS_FLT_HASH_ENTRY(port->id, flow->flow_id);
    836
    837		mvpp2_cls_flow_read(port->priv, flow_index, &fe);
    838
    839		hash_opts |= mvpp2_flow_get_hek_fields(&fe);
    840	}
    841
    842	return hash_opts;
    843}
    844
    845static void mvpp2_cls_port_init_flows(struct mvpp2 *priv)
    846{
    847	const struct mvpp2_cls_flow *flow;
    848	int i;
    849
    850	for (i = 0; i < MVPP2_N_PRS_FLOWS; i++) {
    851		flow = mvpp2_cls_flow_get(i);
    852		if (!flow)
    853			break;
    854
    855		mvpp2_cls_flow_prs_init(priv, flow);
    856		mvpp2_cls_flow_lkp_init(priv, flow);
    857		mvpp2_cls_flow_init(priv, flow);
    858	}
    859}
    860
    861static void mvpp2_port_c2_cls_init(struct mvpp2_port *port)
    862{
    863	struct mvpp2_cls_c2_entry c2;
    864	u8 qh, ql, pmap;
    865
    866	memset(&c2, 0, sizeof(c2));
    867
    868	c2.index = MVPP22_CLS_C2_RSS_ENTRY(port->id);
    869
    870	pmap = BIT(port->id);
    871	c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
    872	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));
    873
    874	/* Match on Lookup Type */
    875	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
    876	c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(MVPP22_CLS_LU_TYPE_ALL);
    877
    878	/* Update RSS status after matching this entry */
    879	c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);
    880
    881	/* Mark packet as "forwarded to software", needed for RSS */
    882	c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK);
    883
    884	/* Configure the default rx queue : Update Queue Low and Queue High, but
    885	 * don't lock, since the rx queue selection might be overridden by RSS
    886	 */
    887	c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD) |
    888		   MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD);
    889
    890	qh = (port->first_rxq >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
    891	ql = port->first_rxq & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
    892
    893	c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
    894		      MVPP22_CLS_C2_ATTR0_QLOW(ql);
    895
    896	c2.valid = true;
    897
    898	mvpp2_cls_c2_write(port->priv, &c2);
    899}
    900
    901/* Classifier default initialization */
    902void mvpp2_cls_init(struct mvpp2 *priv)
    903{
    904	struct mvpp2_cls_lookup_entry le;
    905	struct mvpp2_cls_flow_entry fe;
    906	struct mvpp2_cls_c2_entry c2;
    907	int index;
    908
    909	/* Enable classifier */
    910	mvpp2_write(priv, MVPP2_CLS_MODE_REG, MVPP2_CLS_MODE_ACTIVE_MASK);
    911
    912	/* Clear classifier flow table */
    913	memset(&fe.data, 0, sizeof(fe.data));
    914	for (index = 0; index < MVPP2_CLS_FLOWS_TBL_SIZE; index++) {
    915		fe.index = index;
    916		mvpp2_cls_flow_write(priv, &fe);
    917	}
    918
    919	/* Clear classifier lookup table */
    920	le.data = 0;
    921	for (index = 0; index < MVPP2_CLS_LKP_TBL_SIZE; index++) {
    922		le.lkpid = index;
    923		le.way = 0;
    924		mvpp2_cls_lookup_write(priv, &le);
    925
    926		le.way = 1;
    927		mvpp2_cls_lookup_write(priv, &le);
    928	}
    929
    930	/* Clear C2 TCAM engine table */
    931	memset(&c2, 0, sizeof(c2));
    932	c2.valid = false;
    933	for (index = 0; index < MVPP22_CLS_C2_N_ENTRIES; index++) {
    934		c2.index = index;
    935		mvpp2_cls_c2_write(priv, &c2);
    936	}
    937
    938	/* Disable the FIFO stages in C2 engine, which are only used in BIST
    939	 * mode
    940	 */
    941	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_CTRL,
    942		    MVPP22_CLS_C2_TCAM_BYPASS_FIFO);
    943
    944	mvpp2_cls_port_init_flows(priv);
    945}
    946
    947void mvpp2_cls_port_config(struct mvpp2_port *port)
    948{
    949	struct mvpp2_cls_lookup_entry le;
    950	u32 val;
    951
    952	/* Set way for the port */
    953	val = mvpp2_read(port->priv, MVPP2_CLS_PORT_WAY_REG);
    954	val &= ~MVPP2_CLS_PORT_WAY_MASK(port->id);
    955	mvpp2_write(port->priv, MVPP2_CLS_PORT_WAY_REG, val);
    956
    957	/* Pick the entry to be accessed in lookup ID decoding table
    958	 * according to the way and lkpid.
    959	 */
    960	le.lkpid = port->id;
    961	le.way = 0;
    962	le.data = 0;
    963
    964	/* Set initial CPU queue for receiving packets */
    965	le.data &= ~MVPP2_CLS_LKP_TBL_RXQ_MASK;
    966	le.data |= port->first_rxq;
    967
    968	/* Disable classification engines */
    969	le.data &= ~MVPP2_CLS_LKP_TBL_LOOKUP_EN_MASK;
    970
    971	/* Update lookup ID table entry */
    972	mvpp2_cls_lookup_write(port->priv, &le);
    973
    974	mvpp2_port_c2_cls_init(port);
    975}
    976
    977u32 mvpp2_cls_c2_hit_count(struct mvpp2 *priv, int c2_index)
    978{
    979	mvpp2_write(priv, MVPP22_CLS_C2_TCAM_IDX, c2_index);
    980
    981	return mvpp2_read(priv, MVPP22_CLS_C2_HIT_CTR);
    982}
    983
    984static void mvpp2_rss_port_c2_enable(struct mvpp2_port *port, u32 ctx)
    985{
    986	struct mvpp2_cls_c2_entry c2;
    987	u8 qh, ql;
    988
    989	mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2);
    990
    991	/* The RxQ number is used to select the RSS table. It that case, we set
    992	 * it to be the ctx number.
    993	 */
    994	qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
    995	ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
    996
    997	c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
    998		     MVPP22_CLS_C2_ATTR0_QLOW(ql);
    999
   1000	c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN;
   1001
   1002	mvpp2_cls_c2_write(port->priv, &c2);
   1003}
   1004
   1005static void mvpp2_rss_port_c2_disable(struct mvpp2_port *port)
   1006{
   1007	struct mvpp2_cls_c2_entry c2;
   1008	u8 qh, ql;
   1009
   1010	mvpp2_cls_c2_read(port->priv, MVPP22_CLS_C2_RSS_ENTRY(port->id), &c2);
   1011
   1012	/* Reset the default destination RxQ to the port's first rx queue. */
   1013	qh = (port->first_rxq >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
   1014	ql = port->first_rxq & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
   1015
   1016	c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
   1017		      MVPP22_CLS_C2_ATTR0_QLOW(ql);
   1018
   1019	c2.attr[2] &= ~MVPP22_CLS_C2_ATTR2_RSS_EN;
   1020
   1021	mvpp2_cls_c2_write(port->priv, &c2);
   1022}
   1023
   1024static inline int mvpp22_rss_ctx(struct mvpp2_port *port, int port_rss_ctx)
   1025{
   1026	return port->rss_ctx[port_rss_ctx];
   1027}
   1028
   1029int mvpp22_port_rss_enable(struct mvpp2_port *port)
   1030{
   1031	if (mvpp22_rss_ctx(port, 0) < 0)
   1032		return -EINVAL;
   1033
   1034	mvpp2_rss_port_c2_enable(port, mvpp22_rss_ctx(port, 0));
   1035
   1036	return 0;
   1037}
   1038
   1039int mvpp22_port_rss_disable(struct mvpp2_port *port)
   1040{
   1041	if (mvpp22_rss_ctx(port, 0) < 0)
   1042		return -EINVAL;
   1043
   1044	mvpp2_rss_port_c2_disable(port);
   1045
   1046	return 0;
   1047}
   1048
   1049static void mvpp22_port_c2_lookup_disable(struct mvpp2_port *port, int entry)
   1050{
   1051	struct mvpp2_cls_c2_entry c2;
   1052
   1053	mvpp2_cls_c2_read(port->priv, entry, &c2);
   1054
   1055	/* Clear the port map so that the entry doesn't match anymore */
   1056	c2.tcam[4] &= ~(MVPP22_CLS_C2_PORT_ID(BIT(port->id)));
   1057
   1058	mvpp2_cls_c2_write(port->priv, &c2);
   1059}
   1060
   1061/* Set CPU queue number for oversize packets */
   1062void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
   1063{
   1064	u32 val;
   1065
   1066	mvpp2_write(port->priv, MVPP2_CLS_OVERSIZE_RXQ_LOW_REG(port->id),
   1067		    port->first_rxq & MVPP2_CLS_OVERSIZE_RXQ_LOW_MASK);
   1068
   1069	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_P2HQ_REG(port->id),
   1070		    (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
   1071
   1072	val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
   1073	val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
   1074	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
   1075}
   1076
   1077static int mvpp2_port_c2_tcam_rule_add(struct mvpp2_port *port,
   1078				       struct mvpp2_rfs_rule *rule)
   1079{
   1080	struct flow_action_entry *act;
   1081	struct mvpp2_cls_c2_entry c2;
   1082	u8 qh, ql, pmap;
   1083	int index, ctx;
   1084
   1085	if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL))
   1086		return -EOPNOTSUPP;
   1087
   1088	memset(&c2, 0, sizeof(c2));
   1089
   1090	index = mvpp2_cls_c2_port_flow_index(port, rule->loc);
   1091	if (index < 0)
   1092		return -EINVAL;
   1093	c2.index = index;
   1094
   1095	act = &rule->flow->action.entries[0];
   1096
   1097	rule->c2_index = c2.index;
   1098
   1099	c2.tcam[3] = (rule->c2_tcam & 0xffff) |
   1100		     ((rule->c2_tcam_mask & 0xffff) << 16);
   1101	c2.tcam[2] = ((rule->c2_tcam >> 16) & 0xffff) |
   1102		     (((rule->c2_tcam_mask >> 16) & 0xffff) << 16);
   1103	c2.tcam[1] = ((rule->c2_tcam >> 32) & 0xffff) |
   1104		     (((rule->c2_tcam_mask >> 32) & 0xffff) << 16);
   1105	c2.tcam[0] = ((rule->c2_tcam >> 48) & 0xffff) |
   1106		     (((rule->c2_tcam_mask >> 48) & 0xffff) << 16);
   1107
   1108	pmap = BIT(port->id);
   1109	c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
   1110	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));
   1111
   1112	/* Match on Lookup Type */
   1113	c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
   1114	c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(rule->loc);
   1115
   1116	if (act->id == FLOW_ACTION_DROP) {
   1117		c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_RED_LOCK);
   1118	} else {
   1119		/* We want to keep the default color derived from the Header
   1120		 * Parser drop entries, for VLAN and MAC filtering. This will
   1121		 * assign a default color of Green or Red, and we want matches
   1122		 * with a non-drop action to keep that color.
   1123		 */
   1124		c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_NO_UPD_LOCK);
   1125
   1126		/* Update RSS status after matching this entry */
   1127		if (act->queue.ctx)
   1128			c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN;
   1129
   1130		/* Always lock the RSS_EN decision. We might have high prio
   1131		 * rules steering to an RXQ, and a lower one steering to RSS,
   1132		 * we don't want the low prio RSS rule overwriting this flag.
   1133		 */
   1134		c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);
   1135
   1136		/* Mark packet as "forwarded to software", needed for RSS */
   1137		c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK);
   1138
   1139		c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD_LOCK) |
   1140			   MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD_LOCK);
   1141
   1142		if (act->queue.ctx) {
   1143			/* Get the global ctx number */
   1144			ctx = mvpp22_rss_ctx(port, act->queue.ctx);
   1145			if (ctx < 0)
   1146				return -EINVAL;
   1147
   1148			qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
   1149			ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
   1150		} else {
   1151			qh = ((act->queue.index + port->first_rxq) >> 3) &
   1152			      MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
   1153			ql = (act->queue.index + port->first_rxq) &
   1154			      MVPP22_CLS_C2_ATTR0_QLOW_MASK;
   1155		}
   1156
   1157		c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
   1158			      MVPP22_CLS_C2_ATTR0_QLOW(ql);
   1159	}
   1160
   1161	c2.valid = true;
   1162
   1163	mvpp2_cls_c2_write(port->priv, &c2);
   1164
   1165	return 0;
   1166}
   1167
   1168static int mvpp2_port_c2_rfs_rule_insert(struct mvpp2_port *port,
   1169					 struct mvpp2_rfs_rule *rule)
   1170{
   1171	return mvpp2_port_c2_tcam_rule_add(port, rule);
   1172}
   1173
   1174static int mvpp2_port_cls_rfs_rule_remove(struct mvpp2_port *port,
   1175					  struct mvpp2_rfs_rule *rule)
   1176{
   1177	const struct mvpp2_cls_flow *flow;
   1178	struct mvpp2_cls_flow_entry fe;
   1179	int index, i;
   1180
   1181	for_each_cls_flow_id_containing_type(i, rule->flow_type) {
   1182		flow = mvpp2_cls_flow_get(i);
   1183		if (!flow)
   1184			return 0;
   1185
   1186		index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
   1187
   1188		mvpp2_cls_flow_read(port->priv, index, &fe);
   1189		mvpp2_cls_flow_port_remove(&fe, BIT(port->id));
   1190		mvpp2_cls_flow_write(port->priv, &fe);
   1191	}
   1192
   1193	if (rule->c2_index >= 0)
   1194		mvpp22_port_c2_lookup_disable(port, rule->c2_index);
   1195
   1196	return 0;
   1197}
   1198
   1199static int mvpp2_port_flt_rfs_rule_insert(struct mvpp2_port *port,
   1200					  struct mvpp2_rfs_rule *rule)
   1201{
   1202	const struct mvpp2_cls_flow *flow;
   1203	struct mvpp2 *priv = port->priv;
   1204	struct mvpp2_cls_flow_entry fe;
   1205	int index, ret, i;
   1206
   1207	if (rule->engine != MVPP22_CLS_ENGINE_C2)
   1208		return -EOPNOTSUPP;
   1209
   1210	ret = mvpp2_port_c2_rfs_rule_insert(port, rule);
   1211	if (ret)
   1212		return ret;
   1213
   1214	for_each_cls_flow_id_containing_type(i, rule->flow_type) {
   1215		flow = mvpp2_cls_flow_get(i);
   1216		if (!flow)
   1217			return 0;
   1218
   1219		if ((rule->hek_fields & flow->supported_hash_opts) != rule->hek_fields)
   1220			continue;
   1221
   1222		index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
   1223
   1224		mvpp2_cls_flow_read(priv, index, &fe);
   1225		mvpp2_cls_flow_eng_set(&fe, rule->engine);
   1226		mvpp2_cls_flow_port_id_sel(&fe, true);
   1227		mvpp2_flow_set_hek_fields(&fe, rule->hek_fields);
   1228		mvpp2_cls_flow_lu_type_set(&fe, rule->loc);
   1229		mvpp2_cls_flow_port_add(&fe, 0xf);
   1230
   1231		mvpp2_cls_flow_write(priv, &fe);
   1232	}
   1233
   1234	return 0;
   1235}
   1236
   1237static int mvpp2_cls_c2_build_match(struct mvpp2_rfs_rule *rule)
   1238{
   1239	struct flow_rule *flow = rule->flow;
   1240	int offs = 0;
   1241
   1242	/* The order of insertion in C2 tcam must match the order in which
   1243	 * the fields are found in the header
   1244	 */
   1245	if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_VLAN)) {
   1246		struct flow_match_vlan match;
   1247
   1248		flow_rule_match_vlan(flow, &match);
   1249		if (match.mask->vlan_id) {
   1250			rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN;
   1251
   1252			rule->c2_tcam |= ((u64)match.key->vlan_id) << offs;
   1253			rule->c2_tcam_mask |= ((u64)match.mask->vlan_id) << offs;
   1254
   1255			/* Don't update the offset yet */
   1256		}
   1257
   1258		if (match.mask->vlan_priority) {
   1259			rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN_PRI;
   1260
   1261			/* VLAN pri is always at offset 13 relative to the
   1262			 * current offset
   1263			 */
   1264			rule->c2_tcam |= ((u64)match.key->vlan_priority) <<
   1265				(offs + 13);
   1266			rule->c2_tcam_mask |= ((u64)match.mask->vlan_priority) <<
   1267				(offs + 13);
   1268		}
   1269
   1270		if (match.mask->vlan_dei)
   1271			return -EOPNOTSUPP;
   1272
   1273		/* vlan id and prio always seem to take a full 16-bit slot in
   1274		 * the Header Extracted Key.
   1275		 */
   1276		offs += 16;
   1277	}
   1278
   1279	if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_PORTS)) {
   1280		struct flow_match_ports match;
   1281
   1282		flow_rule_match_ports(flow, &match);
   1283		if (match.mask->src) {
   1284			rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4SIP;
   1285
   1286			rule->c2_tcam |= ((u64)ntohs(match.key->src)) << offs;
   1287			rule->c2_tcam_mask |= ((u64)ntohs(match.mask->src)) << offs;
   1288			offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4SIP);
   1289		}
   1290
   1291		if (match.mask->dst) {
   1292			rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4DIP;
   1293
   1294			rule->c2_tcam |= ((u64)ntohs(match.key->dst)) << offs;
   1295			rule->c2_tcam_mask |= ((u64)ntohs(match.mask->dst)) << offs;
   1296			offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4DIP);
   1297		}
   1298	}
   1299
   1300	if (hweight16(rule->hek_fields) > MVPP2_FLOW_N_FIELDS)
   1301		return -EOPNOTSUPP;
   1302
   1303	return 0;
   1304}
   1305
   1306static int mvpp2_cls_rfs_parse_rule(struct mvpp2_rfs_rule *rule)
   1307{
   1308	struct flow_rule *flow = rule->flow;
   1309	struct flow_action_entry *act;
   1310
   1311	if (!flow_action_basic_hw_stats_check(&rule->flow->action, NULL))
   1312		return -EOPNOTSUPP;
   1313
   1314	act = &flow->action.entries[0];
   1315	if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP)
   1316		return -EOPNOTSUPP;
   1317
   1318	/* When both an RSS context and an queue index are set, the index
   1319	 * is considered as an offset to be added to the indirection table
   1320	 * entries. We don't support this, so reject this rule.
   1321	 */
   1322	if (act->queue.ctx && act->queue.index)
   1323		return -EOPNOTSUPP;
   1324
   1325	/* For now, only use the C2 engine which has a HEK size limited to 64
   1326	 * bits for TCAM matching.
   1327	 */
   1328	rule->engine = MVPP22_CLS_ENGINE_C2;
   1329
   1330	if (mvpp2_cls_c2_build_match(rule))
   1331		return -EINVAL;
   1332
   1333	return 0;
   1334}
   1335
   1336int mvpp2_ethtool_cls_rule_get(struct mvpp2_port *port,
   1337			       struct ethtool_rxnfc *rxnfc)
   1338{
   1339	struct mvpp2_ethtool_fs *efs;
   1340
   1341	if (rxnfc->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
   1342		return -EINVAL;
   1343
   1344	efs = port->rfs_rules[rxnfc->fs.location];
   1345	if (!efs)
   1346		return -ENOENT;
   1347
   1348	memcpy(rxnfc, &efs->rxnfc, sizeof(efs->rxnfc));
   1349
   1350	return 0;
   1351}
   1352
   1353int mvpp2_ethtool_cls_rule_ins(struct mvpp2_port *port,
   1354			       struct ethtool_rxnfc *info)
   1355{
   1356	struct ethtool_rx_flow_spec_input input = {};
   1357	struct ethtool_rx_flow_rule *ethtool_rule;
   1358	struct mvpp2_ethtool_fs *efs, *old_efs;
   1359	int ret = 0;
   1360
   1361	if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
   1362		return -EINVAL;
   1363
   1364	efs = kzalloc(sizeof(*efs), GFP_KERNEL);
   1365	if (!efs)
   1366		return -ENOMEM;
   1367
   1368	input.fs = &info->fs;
   1369
   1370	/* We need to manually set the rss_ctx, since this info isn't present
   1371	 * in info->fs
   1372	 */
   1373	if (info->fs.flow_type & FLOW_RSS)
   1374		input.rss_ctx = info->rss_context;
   1375
   1376	ethtool_rule = ethtool_rx_flow_rule_create(&input);
   1377	if (IS_ERR(ethtool_rule)) {
   1378		ret = PTR_ERR(ethtool_rule);
   1379		goto clean_rule;
   1380	}
   1381
   1382	efs->rule.flow = ethtool_rule->rule;
   1383	efs->rule.flow_type = mvpp2_cls_ethtool_flow_to_type(info->fs.flow_type);
   1384	if (efs->rule.flow_type < 0) {
   1385		ret = efs->rule.flow_type;
   1386		goto clean_rule;
   1387	}
   1388
   1389	ret = mvpp2_cls_rfs_parse_rule(&efs->rule);
   1390	if (ret)
   1391		goto clean_eth_rule;
   1392
   1393	efs->rule.loc = info->fs.location;
   1394
   1395	/* Replace an already existing rule */
   1396	if (port->rfs_rules[efs->rule.loc]) {
   1397		old_efs = port->rfs_rules[efs->rule.loc];
   1398		ret = mvpp2_port_cls_rfs_rule_remove(port, &old_efs->rule);
   1399		if (ret)
   1400			goto clean_eth_rule;
   1401		kfree(old_efs);
   1402		port->n_rfs_rules--;
   1403	}
   1404
   1405	ret = mvpp2_port_flt_rfs_rule_insert(port, &efs->rule);
   1406	if (ret)
   1407		goto clean_eth_rule;
   1408
   1409	ethtool_rx_flow_rule_destroy(ethtool_rule);
   1410	efs->rule.flow = NULL;
   1411
   1412	memcpy(&efs->rxnfc, info, sizeof(*info));
   1413	port->rfs_rules[efs->rule.loc] = efs;
   1414	port->n_rfs_rules++;
   1415
   1416	return ret;
   1417
   1418clean_eth_rule:
   1419	ethtool_rx_flow_rule_destroy(ethtool_rule);
   1420clean_rule:
   1421	kfree(efs);
   1422	return ret;
   1423}
   1424
   1425int mvpp2_ethtool_cls_rule_del(struct mvpp2_port *port,
   1426			       struct ethtool_rxnfc *info)
   1427{
   1428	struct mvpp2_ethtool_fs *efs;
   1429	int ret;
   1430
   1431	if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
   1432		return -EINVAL;
   1433
   1434	efs = port->rfs_rules[info->fs.location];
   1435	if (!efs)
   1436		return -EINVAL;
   1437
   1438	/* Remove the rule from the engines. */
   1439	ret = mvpp2_port_cls_rfs_rule_remove(port, &efs->rule);
   1440	if (ret)
   1441		return ret;
   1442
   1443	port->n_rfs_rules--;
   1444	port->rfs_rules[info->fs.location] = NULL;
   1445	kfree(efs);
   1446
   1447	return 0;
   1448}
   1449
   1450static inline u32 mvpp22_rxfh_indir(struct mvpp2_port *port, u32 rxq)
   1451{
   1452	int nrxqs, cpu, cpus = num_possible_cpus();
   1453
   1454	/* Number of RXQs per CPU */
   1455	nrxqs = port->nrxqs / cpus;
   1456
   1457	/* CPU that will handle this rx queue */
   1458	cpu = rxq / nrxqs;
   1459
   1460	if (!cpu_online(cpu))
   1461		return port->first_rxq;
   1462
   1463	/* Indirection to better distribute the paquets on the CPUs when
   1464	 * configuring the RSS queues.
   1465	 */
   1466	return port->first_rxq + ((rxq * nrxqs + rxq / cpus) % port->nrxqs);
   1467}
   1468
   1469static void mvpp22_rss_fill_table(struct mvpp2_port *port,
   1470				  struct mvpp2_rss_table *table,
   1471				  u32 rss_ctx)
   1472{
   1473	struct mvpp2 *priv = port->priv;
   1474	int i;
   1475
   1476	for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
   1477		u32 sel = MVPP22_RSS_INDEX_TABLE(rss_ctx) |
   1478			  MVPP22_RSS_INDEX_TABLE_ENTRY(i);
   1479		mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
   1480
   1481		mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY,
   1482			    mvpp22_rxfh_indir(port, table->indir[i]));
   1483	}
   1484}
   1485
   1486static int mvpp22_rss_context_create(struct mvpp2_port *port, u32 *rss_ctx)
   1487{
   1488	struct mvpp2 *priv = port->priv;
   1489	u32 ctx;
   1490
   1491	/* Find the first free RSS table */
   1492	for (ctx = 0; ctx < MVPP22_N_RSS_TABLES; ctx++) {
   1493		if (!priv->rss_tables[ctx])
   1494			break;
   1495	}
   1496
   1497	if (ctx == MVPP22_N_RSS_TABLES)
   1498		return -EINVAL;
   1499
   1500	priv->rss_tables[ctx] = kzalloc(sizeof(*priv->rss_tables[ctx]),
   1501					GFP_KERNEL);
   1502	if (!priv->rss_tables[ctx])
   1503		return -ENOMEM;
   1504
   1505	*rss_ctx = ctx;
   1506
   1507	/* Set the table width: replace the whole classifier Rx queue number
   1508	 * with the ones configured in RSS table entries.
   1509	 */
   1510	mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(ctx));
   1511	mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
   1512
   1513	mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(ctx));
   1514	mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE, MVPP22_RSS_TABLE_POINTER(ctx));
   1515
   1516	return 0;
   1517}
   1518
   1519int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *port_ctx)
   1520{
   1521	u32 rss_ctx;
   1522	int ret, i;
   1523
   1524	ret = mvpp22_rss_context_create(port, &rss_ctx);
   1525	if (ret)
   1526		return ret;
   1527
   1528	/* Find the first available context number in the port, starting from 1.
   1529	 * Context 0 on each port is reserved for the default context.
   1530	 */
   1531	for (i = 1; i < MVPP22_N_RSS_TABLES; i++) {
   1532		if (port->rss_ctx[i] < 0)
   1533			break;
   1534	}
   1535
   1536	if (i == MVPP22_N_RSS_TABLES)
   1537		return -EINVAL;
   1538
   1539	port->rss_ctx[i] = rss_ctx;
   1540	*port_ctx = i;
   1541
   1542	return 0;
   1543}
   1544
   1545static struct mvpp2_rss_table *mvpp22_rss_table_get(struct mvpp2 *priv,
   1546						    int rss_ctx)
   1547{
   1548	if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
   1549		return NULL;
   1550
   1551	return priv->rss_tables[rss_ctx];
   1552}
   1553
   1554int mvpp22_port_rss_ctx_delete(struct mvpp2_port *port, u32 port_ctx)
   1555{
   1556	struct mvpp2 *priv = port->priv;
   1557	struct ethtool_rxnfc *rxnfc;
   1558	int i, rss_ctx, ret;
   1559
   1560	rss_ctx = mvpp22_rss_ctx(port, port_ctx);
   1561
   1562	if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
   1563		return -EINVAL;
   1564
   1565	/* Invalidate any active classification rule that use this context */
   1566	for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
   1567		if (!port->rfs_rules[i])
   1568			continue;
   1569
   1570		rxnfc = &port->rfs_rules[i]->rxnfc;
   1571		if (!(rxnfc->fs.flow_type & FLOW_RSS) ||
   1572		    rxnfc->rss_context != port_ctx)
   1573			continue;
   1574
   1575		ret = mvpp2_ethtool_cls_rule_del(port, rxnfc);
   1576		if (ret) {
   1577			netdev_warn(port->dev,
   1578				    "couldn't remove classification rule %d associated to this context",
   1579				    rxnfc->fs.location);
   1580		}
   1581	}
   1582
   1583	kfree(priv->rss_tables[rss_ctx]);
   1584
   1585	priv->rss_tables[rss_ctx] = NULL;
   1586	port->rss_ctx[port_ctx] = -1;
   1587
   1588	return 0;
   1589}
   1590
   1591int mvpp22_port_rss_ctx_indir_set(struct mvpp2_port *port, u32 port_ctx,
   1592				  const u32 *indir)
   1593{
   1594	int rss_ctx = mvpp22_rss_ctx(port, port_ctx);
   1595	struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
   1596								 rss_ctx);
   1597
   1598	if (!rss_table)
   1599		return -EINVAL;
   1600
   1601	memcpy(rss_table->indir, indir,
   1602	       MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
   1603
   1604	mvpp22_rss_fill_table(port, rss_table, rss_ctx);
   1605
   1606	return 0;
   1607}
   1608
   1609int mvpp22_port_rss_ctx_indir_get(struct mvpp2_port *port, u32 port_ctx,
   1610				  u32 *indir)
   1611{
   1612	int rss_ctx =  mvpp22_rss_ctx(port, port_ctx);
   1613	struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
   1614								 rss_ctx);
   1615
   1616	if (!rss_table)
   1617		return -EINVAL;
   1618
   1619	memcpy(indir, rss_table->indir,
   1620	       MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
   1621
   1622	return 0;
   1623}
   1624
   1625int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info)
   1626{
   1627	u16 hash_opts = 0;
   1628	u32 flow_type;
   1629
   1630	flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
   1631
   1632	switch (flow_type) {
   1633	case MVPP22_FLOW_TCP4:
   1634	case MVPP22_FLOW_UDP4:
   1635	case MVPP22_FLOW_TCP6:
   1636	case MVPP22_FLOW_UDP6:
   1637		if (info->data & RXH_L4_B_0_1)
   1638			hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP;
   1639		if (info->data & RXH_L4_B_2_3)
   1640			hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP;
   1641		fallthrough;
   1642	case MVPP22_FLOW_IP4:
   1643	case MVPP22_FLOW_IP6:
   1644		if (info->data & RXH_L2DA)
   1645			hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA;
   1646		if (info->data & RXH_VLAN)
   1647			hash_opts |= MVPP22_CLS_HEK_OPT_VLAN;
   1648		if (info->data & RXH_L3_PROTO)
   1649			hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO;
   1650		if (info->data & RXH_IP_SRC)
   1651			hash_opts |= (MVPP22_CLS_HEK_OPT_IP4SA |
   1652				     MVPP22_CLS_HEK_OPT_IP6SA);
   1653		if (info->data & RXH_IP_DST)
   1654			hash_opts |= (MVPP22_CLS_HEK_OPT_IP4DA |
   1655				     MVPP22_CLS_HEK_OPT_IP6DA);
   1656		break;
   1657	default: return -EOPNOTSUPP;
   1658	}
   1659
   1660	return mvpp2_port_rss_hash_opts_set(port, flow_type, hash_opts);
   1661}
   1662
   1663int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info)
   1664{
   1665	unsigned long hash_opts;
   1666	u32 flow_type;
   1667	int i;
   1668
   1669	flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
   1670
   1671	hash_opts = mvpp2_port_rss_hash_opts_get(port, flow_type);
   1672	info->data = 0;
   1673
   1674	for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
   1675		switch (BIT(i)) {
   1676		case MVPP22_CLS_HEK_OPT_MAC_DA:
   1677			info->data |= RXH_L2DA;
   1678			break;
   1679		case MVPP22_CLS_HEK_OPT_VLAN:
   1680			info->data |= RXH_VLAN;
   1681			break;
   1682		case MVPP22_CLS_HEK_OPT_L3_PROTO:
   1683			info->data |= RXH_L3_PROTO;
   1684			break;
   1685		case MVPP22_CLS_HEK_OPT_IP4SA:
   1686		case MVPP22_CLS_HEK_OPT_IP6SA:
   1687			info->data |= RXH_IP_SRC;
   1688			break;
   1689		case MVPP22_CLS_HEK_OPT_IP4DA:
   1690		case MVPP22_CLS_HEK_OPT_IP6DA:
   1691			info->data |= RXH_IP_DST;
   1692			break;
   1693		case MVPP22_CLS_HEK_OPT_L4SIP:
   1694			info->data |= RXH_L4_B_0_1;
   1695			break;
   1696		case MVPP22_CLS_HEK_OPT_L4DIP:
   1697			info->data |= RXH_L4_B_2_3;
   1698			break;
   1699		default:
   1700			return -EINVAL;
   1701		}
   1702	}
   1703	return 0;
   1704}
   1705
   1706int mvpp22_port_rss_init(struct mvpp2_port *port)
   1707{
   1708	struct mvpp2_rss_table *table;
   1709	u32 context = 0;
   1710	int i, ret;
   1711
   1712	for (i = 0; i < MVPP22_N_RSS_TABLES; i++)
   1713		port->rss_ctx[i] = -1;
   1714
   1715	ret = mvpp22_rss_context_create(port, &context);
   1716	if (ret)
   1717		return ret;
   1718
   1719	table = mvpp22_rss_table_get(port->priv, context);
   1720	if (!table)
   1721		return -EINVAL;
   1722
   1723	port->rss_ctx[0] = context;
   1724
   1725	/* Configure the first table to evenly distribute the packets across
   1726	 * real Rx Queues. The table entries map a hash to a port Rx Queue.
   1727	 */
   1728	for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++)
   1729		table->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs);
   1730
   1731	mvpp22_rss_fill_table(port, table, mvpp22_rss_ctx(port, 0));
   1732
   1733	/* Configure default flows */
   1734	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP4, MVPP22_CLS_HEK_IP4_2T);
   1735	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP6, MVPP22_CLS_HEK_IP6_2T);
   1736	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP4, MVPP22_CLS_HEK_IP4_5T);
   1737	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP6, MVPP22_CLS_HEK_IP6_5T);
   1738	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP4, MVPP22_CLS_HEK_IP4_5T);
   1739	mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP6, MVPP22_CLS_HEK_IP6_5T);
   1740
   1741	return 0;
   1742}