linux/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
<<
>>
Prefs
   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}
1743