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        memset(&c2, 0, sizeof(c2));
1086
1087        index = mvpp2_cls_c2_port_flow_index(port, rule->loc);
1088        if (index < 0)
1089                return -EINVAL;
1090        c2.index = index;
1091
1092        act = &rule->flow->action.entries[0];
1093
1094        rule->c2_index = c2.index;
1095
1096        c2.tcam[3] = (rule->c2_tcam & 0xffff) |
1097                     ((rule->c2_tcam_mask & 0xffff) << 16);
1098        c2.tcam[2] = ((rule->c2_tcam >> 16) & 0xffff) |
1099                     (((rule->c2_tcam_mask >> 16) & 0xffff) << 16);
1100        c2.tcam[1] = ((rule->c2_tcam >> 32) & 0xffff) |
1101                     (((rule->c2_tcam_mask >> 32) & 0xffff) << 16);
1102        c2.tcam[0] = ((rule->c2_tcam >> 48) & 0xffff) |
1103                     (((rule->c2_tcam_mask >> 48) & 0xffff) << 16);
1104
1105        pmap = BIT(port->id);
1106        c2.tcam[4] = MVPP22_CLS_C2_PORT_ID(pmap);
1107        c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_PORT_ID(pmap));
1108
1109        /* Match on Lookup Type */
1110        c2.tcam[4] |= MVPP22_CLS_C2_TCAM_EN(MVPP22_CLS_C2_LU_TYPE(MVPP2_CLS_LU_TYPE_MASK));
1111        c2.tcam[4] |= MVPP22_CLS_C2_LU_TYPE(rule->loc);
1112
1113        if (act->id == FLOW_ACTION_DROP) {
1114                c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_RED_LOCK);
1115        } else {
1116                /* We want to keep the default color derived from the Header
1117                 * Parser drop entries, for VLAN and MAC filtering. This will
1118                 * assign a default color of Green or Red, and we want matches
1119                 * with a non-drop action to keep that color.
1120                 */
1121                c2.act = MVPP22_CLS_C2_ACT_COLOR(MVPP22_C2_COL_NO_UPD_LOCK);
1122
1123                /* Update RSS status after matching this entry */
1124                if (act->queue.ctx)
1125                        c2.attr[2] |= MVPP22_CLS_C2_ATTR2_RSS_EN;
1126
1127                /* Always lock the RSS_EN decision. We might have high prio
1128                 * rules steering to an RXQ, and a lower one steering to RSS,
1129                 * we don't want the low prio RSS rule overwriting this flag.
1130                 */
1131                c2.act = MVPP22_CLS_C2_ACT_RSS_EN(MVPP22_C2_UPD_LOCK);
1132
1133                /* Mark packet as "forwarded to software", needed for RSS */
1134                c2.act |= MVPP22_CLS_C2_ACT_FWD(MVPP22_C2_FWD_SW_LOCK);
1135
1136                c2.act |= MVPP22_CLS_C2_ACT_QHIGH(MVPP22_C2_UPD_LOCK) |
1137                           MVPP22_CLS_C2_ACT_QLOW(MVPP22_C2_UPD_LOCK);
1138
1139                if (act->queue.ctx) {
1140                        /* Get the global ctx number */
1141                        ctx = mvpp22_rss_ctx(port, act->queue.ctx);
1142                        if (ctx < 0)
1143                                return -EINVAL;
1144
1145                        qh = (ctx >> 3) & MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
1146                        ql = ctx & MVPP22_CLS_C2_ATTR0_QLOW_MASK;
1147                } else {
1148                        qh = ((act->queue.index + port->first_rxq) >> 3) &
1149                              MVPP22_CLS_C2_ATTR0_QHIGH_MASK;
1150                        ql = (act->queue.index + port->first_rxq) &
1151                              MVPP22_CLS_C2_ATTR0_QLOW_MASK;
1152                }
1153
1154                c2.attr[0] = MVPP22_CLS_C2_ATTR0_QHIGH(qh) |
1155                              MVPP22_CLS_C2_ATTR0_QLOW(ql);
1156        }
1157
1158        c2.valid = true;
1159
1160        mvpp2_cls_c2_write(port->priv, &c2);
1161
1162        return 0;
1163}
1164
1165static int mvpp2_port_c2_rfs_rule_insert(struct mvpp2_port *port,
1166                                         struct mvpp2_rfs_rule *rule)
1167{
1168        return mvpp2_port_c2_tcam_rule_add(port, rule);
1169}
1170
1171static int mvpp2_port_cls_rfs_rule_remove(struct mvpp2_port *port,
1172                                          struct mvpp2_rfs_rule *rule)
1173{
1174        const struct mvpp2_cls_flow *flow;
1175        struct mvpp2_cls_flow_entry fe;
1176        int index, i;
1177
1178        for_each_cls_flow_id_containing_type(i, rule->flow_type) {
1179                flow = mvpp2_cls_flow_get(i);
1180                if (!flow)
1181                        return 0;
1182
1183                index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
1184
1185                mvpp2_cls_flow_read(port->priv, index, &fe);
1186                mvpp2_cls_flow_port_remove(&fe, BIT(port->id));
1187                mvpp2_cls_flow_write(port->priv, &fe);
1188        }
1189
1190        if (rule->c2_index >= 0)
1191                mvpp22_port_c2_lookup_disable(port, rule->c2_index);
1192
1193        return 0;
1194}
1195
1196static int mvpp2_port_flt_rfs_rule_insert(struct mvpp2_port *port,
1197                                          struct mvpp2_rfs_rule *rule)
1198{
1199        const struct mvpp2_cls_flow *flow;
1200        struct mvpp2 *priv = port->priv;
1201        struct mvpp2_cls_flow_entry fe;
1202        int index, ret, i;
1203
1204        if (rule->engine != MVPP22_CLS_ENGINE_C2)
1205                return -EOPNOTSUPP;
1206
1207        ret = mvpp2_port_c2_rfs_rule_insert(port, rule);
1208        if (ret)
1209                return ret;
1210
1211        for_each_cls_flow_id_containing_type(i, rule->flow_type) {
1212                flow = mvpp2_cls_flow_get(i);
1213                if (!flow)
1214                        return 0;
1215
1216                if ((rule->hek_fields & flow->supported_hash_opts) != rule->hek_fields)
1217                        continue;
1218
1219                index = MVPP2_CLS_FLT_C2_RFS(port->id, flow->flow_id, rule->loc);
1220
1221                mvpp2_cls_flow_read(priv, index, &fe);
1222                mvpp2_cls_flow_eng_set(&fe, rule->engine);
1223                mvpp2_cls_flow_port_id_sel(&fe, true);
1224                mvpp2_flow_set_hek_fields(&fe, rule->hek_fields);
1225                mvpp2_cls_flow_lu_type_set(&fe, rule->loc);
1226                mvpp2_cls_flow_port_add(&fe, 0xf);
1227
1228                mvpp2_cls_flow_write(priv, &fe);
1229        }
1230
1231        return 0;
1232}
1233
1234static int mvpp2_cls_c2_build_match(struct mvpp2_rfs_rule *rule)
1235{
1236        struct flow_rule *flow = rule->flow;
1237        int offs = 0;
1238
1239        /* The order of insertion in C2 tcam must match the order in which
1240         * the fields are found in the header
1241         */
1242        if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_VLAN)) {
1243                struct flow_match_vlan match;
1244
1245                flow_rule_match_vlan(flow, &match);
1246                if (match.mask->vlan_id) {
1247                        rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN;
1248
1249                        rule->c2_tcam |= ((u64)match.key->vlan_id) << offs;
1250                        rule->c2_tcam_mask |= ((u64)match.mask->vlan_id) << offs;
1251
1252                        /* Don't update the offset yet */
1253                }
1254
1255                if (match.mask->vlan_priority) {
1256                        rule->hek_fields |= MVPP22_CLS_HEK_OPT_VLAN_PRI;
1257
1258                        /* VLAN pri is always at offset 13 relative to the
1259                         * current offset
1260                         */
1261                        rule->c2_tcam |= ((u64)match.key->vlan_priority) <<
1262                                (offs + 13);
1263                        rule->c2_tcam_mask |= ((u64)match.mask->vlan_priority) <<
1264                                (offs + 13);
1265                }
1266
1267                if (match.mask->vlan_dei)
1268                        return -EOPNOTSUPP;
1269
1270                /* vlan id and prio always seem to take a full 16-bit slot in
1271                 * the Header Extracted Key.
1272                 */
1273                offs += 16;
1274        }
1275
1276        if (flow_rule_match_key(flow, FLOW_DISSECTOR_KEY_PORTS)) {
1277                struct flow_match_ports match;
1278
1279                flow_rule_match_ports(flow, &match);
1280                if (match.mask->src) {
1281                        rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4SIP;
1282
1283                        rule->c2_tcam |= ((u64)ntohs(match.key->src)) << offs;
1284                        rule->c2_tcam_mask |= ((u64)ntohs(match.mask->src)) << offs;
1285                        offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4SIP);
1286                }
1287
1288                if (match.mask->dst) {
1289                        rule->hek_fields |= MVPP22_CLS_HEK_OPT_L4DIP;
1290
1291                        rule->c2_tcam |= ((u64)ntohs(match.key->dst)) << offs;
1292                        rule->c2_tcam_mask |= ((u64)ntohs(match.mask->dst)) << offs;
1293                        offs += mvpp2_cls_hek_field_size(MVPP22_CLS_HEK_OPT_L4DIP);
1294                }
1295        }
1296
1297        if (hweight16(rule->hek_fields) > MVPP2_FLOW_N_FIELDS)
1298                return -EOPNOTSUPP;
1299
1300        return 0;
1301}
1302
1303static int mvpp2_cls_rfs_parse_rule(struct mvpp2_rfs_rule *rule)
1304{
1305        struct flow_rule *flow = rule->flow;
1306        struct flow_action_entry *act;
1307
1308        act = &flow->action.entries[0];
1309        if (act->id != FLOW_ACTION_QUEUE && act->id != FLOW_ACTION_DROP)
1310                return -EOPNOTSUPP;
1311
1312        /* When both an RSS context and an queue index are set, the index
1313         * is considered as an offset to be added to the indirection table
1314         * entries. We don't support this, so reject this rule.
1315         */
1316        if (act->queue.ctx && act->queue.index)
1317                return -EOPNOTSUPP;
1318
1319        /* For now, only use the C2 engine which has a HEK size limited to 64
1320         * bits for TCAM matching.
1321         */
1322        rule->engine = MVPP22_CLS_ENGINE_C2;
1323
1324        if (mvpp2_cls_c2_build_match(rule))
1325                return -EINVAL;
1326
1327        return 0;
1328}
1329
1330int mvpp2_ethtool_cls_rule_get(struct mvpp2_port *port,
1331                               struct ethtool_rxnfc *rxnfc)
1332{
1333        struct mvpp2_ethtool_fs *efs;
1334
1335        if (rxnfc->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
1336                return -EINVAL;
1337
1338        efs = port->rfs_rules[rxnfc->fs.location];
1339        if (!efs)
1340                return -ENOENT;
1341
1342        memcpy(rxnfc, &efs->rxnfc, sizeof(efs->rxnfc));
1343
1344        return 0;
1345}
1346
1347int mvpp2_ethtool_cls_rule_ins(struct mvpp2_port *port,
1348                               struct ethtool_rxnfc *info)
1349{
1350        struct ethtool_rx_flow_spec_input input = {};
1351        struct ethtool_rx_flow_rule *ethtool_rule;
1352        struct mvpp2_ethtool_fs *efs, *old_efs;
1353        int ret = 0;
1354
1355        if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
1356                return -EINVAL;
1357
1358        efs = kzalloc(sizeof(*efs), GFP_KERNEL);
1359        if (!efs)
1360                return -ENOMEM;
1361
1362        input.fs = &info->fs;
1363
1364        /* We need to manually set the rss_ctx, since this info isn't present
1365         * in info->fs
1366         */
1367        if (info->fs.flow_type & FLOW_RSS)
1368                input.rss_ctx = info->rss_context;
1369
1370        ethtool_rule = ethtool_rx_flow_rule_create(&input);
1371        if (IS_ERR(ethtool_rule)) {
1372                ret = PTR_ERR(ethtool_rule);
1373                goto clean_rule;
1374        }
1375
1376        efs->rule.flow = ethtool_rule->rule;
1377        efs->rule.flow_type = mvpp2_cls_ethtool_flow_to_type(info->fs.flow_type);
1378        if (efs->rule.flow_type < 0) {
1379                ret = efs->rule.flow_type;
1380                goto clean_rule;
1381        }
1382
1383        ret = mvpp2_cls_rfs_parse_rule(&efs->rule);
1384        if (ret)
1385                goto clean_eth_rule;
1386
1387        efs->rule.loc = info->fs.location;
1388
1389        /* Replace an already existing rule */
1390        if (port->rfs_rules[efs->rule.loc]) {
1391                old_efs = port->rfs_rules[efs->rule.loc];
1392                ret = mvpp2_port_cls_rfs_rule_remove(port, &old_efs->rule);
1393                if (ret)
1394                        goto clean_eth_rule;
1395                kfree(old_efs);
1396                port->n_rfs_rules--;
1397        }
1398
1399        ret = mvpp2_port_flt_rfs_rule_insert(port, &efs->rule);
1400        if (ret)
1401                goto clean_eth_rule;
1402
1403        ethtool_rx_flow_rule_destroy(ethtool_rule);
1404        efs->rule.flow = NULL;
1405
1406        memcpy(&efs->rxnfc, info, sizeof(*info));
1407        port->rfs_rules[efs->rule.loc] = efs;
1408        port->n_rfs_rules++;
1409
1410        return ret;
1411
1412clean_eth_rule:
1413        ethtool_rx_flow_rule_destroy(ethtool_rule);
1414clean_rule:
1415        kfree(efs);
1416        return ret;
1417}
1418
1419int mvpp2_ethtool_cls_rule_del(struct mvpp2_port *port,
1420                               struct ethtool_rxnfc *info)
1421{
1422        struct mvpp2_ethtool_fs *efs;
1423        int ret;
1424
1425        efs = port->rfs_rules[info->fs.location];
1426        if (!efs)
1427                return -EINVAL;
1428
1429        /* Remove the rule from the engines. */
1430        ret = mvpp2_port_cls_rfs_rule_remove(port, &efs->rule);
1431        if (ret)
1432                return ret;
1433
1434        port->n_rfs_rules--;
1435        port->rfs_rules[info->fs.location] = NULL;
1436        kfree(efs);
1437
1438        return 0;
1439}
1440
1441static inline u32 mvpp22_rxfh_indir(struct mvpp2_port *port, u32 rxq)
1442{
1443        int nrxqs, cpu, cpus = num_possible_cpus();
1444
1445        /* Number of RXQs per CPU */
1446        nrxqs = port->nrxqs / cpus;
1447
1448        /* CPU that will handle this rx queue */
1449        cpu = rxq / nrxqs;
1450
1451        if (!cpu_online(cpu))
1452                return port->first_rxq;
1453
1454        /* Indirection to better distribute the paquets on the CPUs when
1455         * configuring the RSS queues.
1456         */
1457        return port->first_rxq + ((rxq * nrxqs + rxq / cpus) % port->nrxqs);
1458}
1459
1460static void mvpp22_rss_fill_table(struct mvpp2_port *port,
1461                                  struct mvpp2_rss_table *table,
1462                                  u32 rss_ctx)
1463{
1464        struct mvpp2 *priv = port->priv;
1465        int i;
1466
1467        for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
1468                u32 sel = MVPP22_RSS_INDEX_TABLE(rss_ctx) |
1469                          MVPP22_RSS_INDEX_TABLE_ENTRY(i);
1470                mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
1471
1472                mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY,
1473                            mvpp22_rxfh_indir(port, table->indir[i]));
1474        }
1475}
1476
1477static int mvpp22_rss_context_create(struct mvpp2_port *port, u32 *rss_ctx)
1478{
1479        struct mvpp2 *priv = port->priv;
1480        u32 ctx;
1481
1482        /* Find the first free RSS table */
1483        for (ctx = 0; ctx < MVPP22_N_RSS_TABLES; ctx++) {
1484                if (!priv->rss_tables[ctx])
1485                        break;
1486        }
1487
1488        if (ctx == MVPP22_N_RSS_TABLES)
1489                return -EINVAL;
1490
1491        priv->rss_tables[ctx] = kzalloc(sizeof(*priv->rss_tables[ctx]),
1492                                        GFP_KERNEL);
1493        if (!priv->rss_tables[ctx])
1494                return -ENOMEM;
1495
1496        *rss_ctx = ctx;
1497
1498        /* Set the table width: replace the whole classifier Rx queue number
1499         * with the ones configured in RSS table entries.
1500         */
1501        mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_TABLE(ctx));
1502        mvpp2_write(priv, MVPP22_RSS_WIDTH, 8);
1503
1504        mvpp2_write(priv, MVPP22_RSS_INDEX, MVPP22_RSS_INDEX_QUEUE(ctx));
1505        mvpp2_write(priv, MVPP22_RXQ2RSS_TABLE, MVPP22_RSS_TABLE_POINTER(ctx));
1506
1507        return 0;
1508}
1509
1510int mvpp22_port_rss_ctx_create(struct mvpp2_port *port, u32 *port_ctx)
1511{
1512        u32 rss_ctx;
1513        int ret, i;
1514
1515        ret = mvpp22_rss_context_create(port, &rss_ctx);
1516        if (ret)
1517                return ret;
1518
1519        /* Find the first available context number in the port, starting from 1.
1520         * Context 0 on each port is reserved for the default context.
1521         */
1522        for (i = 1; i < MVPP22_N_RSS_TABLES; i++) {
1523                if (port->rss_ctx[i] < 0)
1524                        break;
1525        }
1526
1527        if (i == MVPP22_N_RSS_TABLES)
1528                return -EINVAL;
1529
1530        port->rss_ctx[i] = rss_ctx;
1531        *port_ctx = i;
1532
1533        return 0;
1534}
1535
1536static struct mvpp2_rss_table *mvpp22_rss_table_get(struct mvpp2 *priv,
1537                                                    int rss_ctx)
1538{
1539        if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
1540                return NULL;
1541
1542        return priv->rss_tables[rss_ctx];
1543}
1544
1545int mvpp22_port_rss_ctx_delete(struct mvpp2_port *port, u32 port_ctx)
1546{
1547        struct mvpp2 *priv = port->priv;
1548        struct ethtool_rxnfc *rxnfc;
1549        int i, rss_ctx, ret;
1550
1551        rss_ctx = mvpp22_rss_ctx(port, port_ctx);
1552
1553        if (rss_ctx < 0 || rss_ctx >= MVPP22_N_RSS_TABLES)
1554                return -EINVAL;
1555
1556        /* Invalidate any active classification rule that use this context */
1557        for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
1558                if (!port->rfs_rules[i])
1559                        continue;
1560
1561                rxnfc = &port->rfs_rules[i]->rxnfc;
1562                if (!(rxnfc->fs.flow_type & FLOW_RSS) ||
1563                    rxnfc->rss_context != port_ctx)
1564                        continue;
1565
1566                ret = mvpp2_ethtool_cls_rule_del(port, rxnfc);
1567                if (ret) {
1568                        netdev_warn(port->dev,
1569                                    "couldn't remove classification rule %d associated to this context",
1570                                    rxnfc->fs.location);
1571                }
1572        }
1573
1574        kfree(priv->rss_tables[rss_ctx]);
1575
1576        priv->rss_tables[rss_ctx] = NULL;
1577        port->rss_ctx[port_ctx] = -1;
1578
1579        return 0;
1580}
1581
1582int mvpp22_port_rss_ctx_indir_set(struct mvpp2_port *port, u32 port_ctx,
1583                                  const u32 *indir)
1584{
1585        int rss_ctx = mvpp22_rss_ctx(port, port_ctx);
1586        struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
1587                                                                 rss_ctx);
1588
1589        if (!rss_table)
1590                return -EINVAL;
1591
1592        memcpy(rss_table->indir, indir,
1593               MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
1594
1595        mvpp22_rss_fill_table(port, rss_table, rss_ctx);
1596
1597        return 0;
1598}
1599
1600int mvpp22_port_rss_ctx_indir_get(struct mvpp2_port *port, u32 port_ctx,
1601                                  u32 *indir)
1602{
1603        int rss_ctx =  mvpp22_rss_ctx(port, port_ctx);
1604        struct mvpp2_rss_table *rss_table = mvpp22_rss_table_get(port->priv,
1605                                                                 rss_ctx);
1606
1607        if (!rss_table)
1608                return -EINVAL;
1609
1610        memcpy(indir, rss_table->indir,
1611               MVPP22_RSS_TABLE_ENTRIES * sizeof(rss_table->indir[0]));
1612
1613        return 0;
1614}
1615
1616int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info)
1617{
1618        u16 hash_opts = 0;
1619        u32 flow_type;
1620
1621        flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
1622
1623        switch (flow_type) {
1624        case MVPP22_FLOW_TCP4:
1625        case MVPP22_FLOW_UDP4:
1626        case MVPP22_FLOW_TCP6:
1627        case MVPP22_FLOW_UDP6:
1628                if (info->data & RXH_L4_B_0_1)
1629                        hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP;
1630                if (info->data & RXH_L4_B_2_3)
1631                        hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP;
1632                /* Fallthrough */
1633        case MVPP22_FLOW_IP4:
1634        case MVPP22_FLOW_IP6:
1635                if (info->data & RXH_L2DA)
1636                        hash_opts |= MVPP22_CLS_HEK_OPT_MAC_DA;
1637                if (info->data & RXH_VLAN)
1638                        hash_opts |= MVPP22_CLS_HEK_OPT_VLAN;
1639                if (info->data & RXH_L3_PROTO)
1640                        hash_opts |= MVPP22_CLS_HEK_OPT_L3_PROTO;
1641                if (info->data & RXH_IP_SRC)
1642                        hash_opts |= (MVPP22_CLS_HEK_OPT_IP4SA |
1643                                     MVPP22_CLS_HEK_OPT_IP6SA);
1644                if (info->data & RXH_IP_DST)
1645                        hash_opts |= (MVPP22_CLS_HEK_OPT_IP4DA |
1646                                     MVPP22_CLS_HEK_OPT_IP6DA);
1647                break;
1648        default: return -EOPNOTSUPP;
1649        }
1650
1651        return mvpp2_port_rss_hash_opts_set(port, flow_type, hash_opts);
1652}
1653
1654int mvpp2_ethtool_rxfh_get(struct mvpp2_port *port, struct ethtool_rxnfc *info)
1655{
1656        unsigned long hash_opts;
1657        u32 flow_type;
1658        int i;
1659
1660        flow_type = mvpp2_cls_ethtool_flow_to_type(info->flow_type);
1661
1662        hash_opts = mvpp2_port_rss_hash_opts_get(port, flow_type);
1663        info->data = 0;
1664
1665        for_each_set_bit(i, &hash_opts, MVPP22_CLS_HEK_N_FIELDS) {
1666                switch (BIT(i)) {
1667                case MVPP22_CLS_HEK_OPT_MAC_DA:
1668                        info->data |= RXH_L2DA;
1669                        break;
1670                case MVPP22_CLS_HEK_OPT_VLAN:
1671                        info->data |= RXH_VLAN;
1672                        break;
1673                case MVPP22_CLS_HEK_OPT_L3_PROTO:
1674                        info->data |= RXH_L3_PROTO;
1675                        break;
1676                case MVPP22_CLS_HEK_OPT_IP4SA:
1677                case MVPP22_CLS_HEK_OPT_IP6SA:
1678                        info->data |= RXH_IP_SRC;
1679                        break;
1680                case MVPP22_CLS_HEK_OPT_IP4DA:
1681                case MVPP22_CLS_HEK_OPT_IP6DA:
1682                        info->data |= RXH_IP_DST;
1683                        break;
1684                case MVPP22_CLS_HEK_OPT_L4SIP:
1685                        info->data |= RXH_L4_B_0_1;
1686                        break;
1687                case MVPP22_CLS_HEK_OPT_L4DIP:
1688                        info->data |= RXH_L4_B_2_3;
1689                        break;
1690                default:
1691                        return -EINVAL;
1692                }
1693        }
1694        return 0;
1695}
1696
1697int mvpp22_port_rss_init(struct mvpp2_port *port)
1698{
1699        struct mvpp2_rss_table *table;
1700        u32 context = 0;
1701        int i, ret;
1702
1703        for (i = 0; i < MVPP22_N_RSS_TABLES; i++)
1704                port->rss_ctx[i] = -1;
1705
1706        ret = mvpp22_rss_context_create(port, &context);
1707        if (ret)
1708                return ret;
1709
1710        table = mvpp22_rss_table_get(port->priv, context);
1711        if (!table)
1712                return -EINVAL;
1713
1714        port->rss_ctx[0] = context;
1715
1716        /* Configure the first table to evenly distribute the packets across
1717         * real Rx Queues. The table entries map a hash to a port Rx Queue.
1718         */
1719        for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++)
1720                table->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs);
1721
1722        mvpp22_rss_fill_table(port, table, mvpp22_rss_ctx(port, 0));
1723
1724        /* Configure default flows */
1725        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP4, MVPP22_CLS_HEK_IP4_2T);
1726        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_IP6, MVPP22_CLS_HEK_IP6_2T);
1727        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP4, MVPP22_CLS_HEK_IP4_5T);
1728        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_TCP6, MVPP22_CLS_HEK_IP6_5T);
1729        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP4, MVPP22_CLS_HEK_IP4_5T);
1730        mvpp2_port_rss_hash_opts_set(port, MVPP22_FLOW_UDP6, MVPP22_CLS_HEK_IP6_5T);
1731
1732        return 0;
1733}
1734