linux/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2021, Intel Corporation. */
   3
   4#include "ice.h"
   5#include "ice_base.h"
   6#include "ice_lib.h"
   7#include "ice_flow.h"
   8
   9#define to_fltr_conf_from_desc(p) \
  10        container_of(p, struct virtchnl_fdir_fltr_conf, input)
  11
  12#define ICE_FLOW_PROF_TYPE_S    0
  13#define ICE_FLOW_PROF_TYPE_M    (0xFFFFFFFFULL << ICE_FLOW_PROF_TYPE_S)
  14#define ICE_FLOW_PROF_VSI_S     32
  15#define ICE_FLOW_PROF_VSI_M     (0xFFFFFFFFULL << ICE_FLOW_PROF_VSI_S)
  16
  17/* Flow profile ID format:
  18 * [0:31] - flow type, flow + tun_offs
  19 * [32:63] - VSI index
  20 */
  21#define ICE_FLOW_PROF_FD(vsi, flow, tun_offs) \
  22        ((u64)(((((flow) + (tun_offs)) & ICE_FLOW_PROF_TYPE_M)) | \
  23              (((u64)(vsi) << ICE_FLOW_PROF_VSI_S) & ICE_FLOW_PROF_VSI_M)))
  24
  25#define GTPU_TEID_OFFSET 4
  26#define GTPU_EH_QFI_OFFSET 1
  27#define GTPU_EH_QFI_MASK 0x3F
  28#define PFCP_S_OFFSET 0
  29#define PFCP_S_MASK 0x1
  30#define PFCP_PORT_NR 8805
  31
  32#define FDIR_INSET_FLAG_ESP_S 0
  33#define FDIR_INSET_FLAG_ESP_M BIT_ULL(FDIR_INSET_FLAG_ESP_S)
  34#define FDIR_INSET_FLAG_ESP_UDP BIT_ULL(FDIR_INSET_FLAG_ESP_S)
  35#define FDIR_INSET_FLAG_ESP_IPSEC (0ULL << FDIR_INSET_FLAG_ESP_S)
  36
  37enum ice_fdir_tunnel_type {
  38        ICE_FDIR_TUNNEL_TYPE_NONE = 0,
  39        ICE_FDIR_TUNNEL_TYPE_GTPU,
  40        ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
  41};
  42
  43struct virtchnl_fdir_fltr_conf {
  44        struct ice_fdir_fltr input;
  45        enum ice_fdir_tunnel_type ttype;
  46        u64 inset_flag;
  47        u32 flow_id;
  48};
  49
  50static enum virtchnl_proto_hdr_type vc_pattern_ether[] = {
  51        VIRTCHNL_PROTO_HDR_ETH,
  52        VIRTCHNL_PROTO_HDR_NONE,
  53};
  54
  55static enum virtchnl_proto_hdr_type vc_pattern_ipv4[] = {
  56        VIRTCHNL_PROTO_HDR_ETH,
  57        VIRTCHNL_PROTO_HDR_IPV4,
  58        VIRTCHNL_PROTO_HDR_NONE,
  59};
  60
  61static enum virtchnl_proto_hdr_type vc_pattern_ipv4_tcp[] = {
  62        VIRTCHNL_PROTO_HDR_ETH,
  63        VIRTCHNL_PROTO_HDR_IPV4,
  64        VIRTCHNL_PROTO_HDR_TCP,
  65        VIRTCHNL_PROTO_HDR_NONE,
  66};
  67
  68static enum virtchnl_proto_hdr_type vc_pattern_ipv4_udp[] = {
  69        VIRTCHNL_PROTO_HDR_ETH,
  70        VIRTCHNL_PROTO_HDR_IPV4,
  71        VIRTCHNL_PROTO_HDR_UDP,
  72        VIRTCHNL_PROTO_HDR_NONE,
  73};
  74
  75static enum virtchnl_proto_hdr_type vc_pattern_ipv4_sctp[] = {
  76        VIRTCHNL_PROTO_HDR_ETH,
  77        VIRTCHNL_PROTO_HDR_IPV4,
  78        VIRTCHNL_PROTO_HDR_SCTP,
  79        VIRTCHNL_PROTO_HDR_NONE,
  80};
  81
  82static enum virtchnl_proto_hdr_type vc_pattern_ipv6[] = {
  83        VIRTCHNL_PROTO_HDR_ETH,
  84        VIRTCHNL_PROTO_HDR_IPV6,
  85        VIRTCHNL_PROTO_HDR_NONE,
  86};
  87
  88static enum virtchnl_proto_hdr_type vc_pattern_ipv6_tcp[] = {
  89        VIRTCHNL_PROTO_HDR_ETH,
  90        VIRTCHNL_PROTO_HDR_IPV6,
  91        VIRTCHNL_PROTO_HDR_TCP,
  92        VIRTCHNL_PROTO_HDR_NONE,
  93};
  94
  95static enum virtchnl_proto_hdr_type vc_pattern_ipv6_udp[] = {
  96        VIRTCHNL_PROTO_HDR_ETH,
  97        VIRTCHNL_PROTO_HDR_IPV6,
  98        VIRTCHNL_PROTO_HDR_UDP,
  99        VIRTCHNL_PROTO_HDR_NONE,
 100};
 101
 102static enum virtchnl_proto_hdr_type vc_pattern_ipv6_sctp[] = {
 103        VIRTCHNL_PROTO_HDR_ETH,
 104        VIRTCHNL_PROTO_HDR_IPV6,
 105        VIRTCHNL_PROTO_HDR_SCTP,
 106        VIRTCHNL_PROTO_HDR_NONE,
 107};
 108
 109static enum virtchnl_proto_hdr_type vc_pattern_ipv4_gtpu[] = {
 110        VIRTCHNL_PROTO_HDR_ETH,
 111        VIRTCHNL_PROTO_HDR_IPV4,
 112        VIRTCHNL_PROTO_HDR_UDP,
 113        VIRTCHNL_PROTO_HDR_GTPU_IP,
 114        VIRTCHNL_PROTO_HDR_NONE,
 115};
 116
 117static enum virtchnl_proto_hdr_type vc_pattern_ipv4_gtpu_eh[] = {
 118        VIRTCHNL_PROTO_HDR_ETH,
 119        VIRTCHNL_PROTO_HDR_IPV4,
 120        VIRTCHNL_PROTO_HDR_UDP,
 121        VIRTCHNL_PROTO_HDR_GTPU_IP,
 122        VIRTCHNL_PROTO_HDR_GTPU_EH,
 123        VIRTCHNL_PROTO_HDR_NONE,
 124};
 125
 126static enum virtchnl_proto_hdr_type vc_pattern_ipv4_l2tpv3[] = {
 127        VIRTCHNL_PROTO_HDR_ETH,
 128        VIRTCHNL_PROTO_HDR_IPV4,
 129        VIRTCHNL_PROTO_HDR_L2TPV3,
 130        VIRTCHNL_PROTO_HDR_NONE,
 131};
 132
 133static enum virtchnl_proto_hdr_type vc_pattern_ipv6_l2tpv3[] = {
 134        VIRTCHNL_PROTO_HDR_ETH,
 135        VIRTCHNL_PROTO_HDR_IPV6,
 136        VIRTCHNL_PROTO_HDR_L2TPV3,
 137        VIRTCHNL_PROTO_HDR_NONE,
 138};
 139
 140static enum virtchnl_proto_hdr_type vc_pattern_ipv4_esp[] = {
 141        VIRTCHNL_PROTO_HDR_ETH,
 142        VIRTCHNL_PROTO_HDR_IPV4,
 143        VIRTCHNL_PROTO_HDR_ESP,
 144        VIRTCHNL_PROTO_HDR_NONE,
 145};
 146
 147static enum virtchnl_proto_hdr_type vc_pattern_ipv6_esp[] = {
 148        VIRTCHNL_PROTO_HDR_ETH,
 149        VIRTCHNL_PROTO_HDR_IPV6,
 150        VIRTCHNL_PROTO_HDR_ESP,
 151        VIRTCHNL_PROTO_HDR_NONE,
 152};
 153
 154static enum virtchnl_proto_hdr_type vc_pattern_ipv4_ah[] = {
 155        VIRTCHNL_PROTO_HDR_ETH,
 156        VIRTCHNL_PROTO_HDR_IPV4,
 157        VIRTCHNL_PROTO_HDR_AH,
 158        VIRTCHNL_PROTO_HDR_NONE,
 159};
 160
 161static enum virtchnl_proto_hdr_type vc_pattern_ipv6_ah[] = {
 162        VIRTCHNL_PROTO_HDR_ETH,
 163        VIRTCHNL_PROTO_HDR_IPV6,
 164        VIRTCHNL_PROTO_HDR_AH,
 165        VIRTCHNL_PROTO_HDR_NONE,
 166};
 167
 168static enum virtchnl_proto_hdr_type vc_pattern_ipv4_nat_t_esp[] = {
 169        VIRTCHNL_PROTO_HDR_ETH,
 170        VIRTCHNL_PROTO_HDR_IPV4,
 171        VIRTCHNL_PROTO_HDR_UDP,
 172        VIRTCHNL_PROTO_HDR_ESP,
 173        VIRTCHNL_PROTO_HDR_NONE,
 174};
 175
 176static enum virtchnl_proto_hdr_type vc_pattern_ipv6_nat_t_esp[] = {
 177        VIRTCHNL_PROTO_HDR_ETH,
 178        VIRTCHNL_PROTO_HDR_IPV6,
 179        VIRTCHNL_PROTO_HDR_UDP,
 180        VIRTCHNL_PROTO_HDR_ESP,
 181        VIRTCHNL_PROTO_HDR_NONE,
 182};
 183
 184static enum virtchnl_proto_hdr_type vc_pattern_ipv4_pfcp[] = {
 185        VIRTCHNL_PROTO_HDR_ETH,
 186        VIRTCHNL_PROTO_HDR_IPV4,
 187        VIRTCHNL_PROTO_HDR_UDP,
 188        VIRTCHNL_PROTO_HDR_PFCP,
 189        VIRTCHNL_PROTO_HDR_NONE,
 190};
 191
 192static enum virtchnl_proto_hdr_type vc_pattern_ipv6_pfcp[] = {
 193        VIRTCHNL_PROTO_HDR_ETH,
 194        VIRTCHNL_PROTO_HDR_IPV6,
 195        VIRTCHNL_PROTO_HDR_UDP,
 196        VIRTCHNL_PROTO_HDR_PFCP,
 197        VIRTCHNL_PROTO_HDR_NONE,
 198};
 199
 200struct virtchnl_fdir_pattern_match_item {
 201        enum virtchnl_proto_hdr_type *list;
 202        u64 input_set;
 203        u64 *meta;
 204};
 205
 206static const struct virtchnl_fdir_pattern_match_item vc_fdir_pattern_os[] = {
 207        {vc_pattern_ipv4,                     0,         NULL},
 208        {vc_pattern_ipv4_tcp,                 0,         NULL},
 209        {vc_pattern_ipv4_udp,                 0,         NULL},
 210        {vc_pattern_ipv4_sctp,                0,         NULL},
 211        {vc_pattern_ipv6,                     0,         NULL},
 212        {vc_pattern_ipv6_tcp,                 0,         NULL},
 213        {vc_pattern_ipv6_udp,                 0,         NULL},
 214        {vc_pattern_ipv6_sctp,                0,         NULL},
 215};
 216
 217static const struct virtchnl_fdir_pattern_match_item vc_fdir_pattern_comms[] = {
 218        {vc_pattern_ipv4,                     0,         NULL},
 219        {vc_pattern_ipv4_tcp,                 0,         NULL},
 220        {vc_pattern_ipv4_udp,                 0,         NULL},
 221        {vc_pattern_ipv4_sctp,                0,         NULL},
 222        {vc_pattern_ipv6,                     0,         NULL},
 223        {vc_pattern_ipv6_tcp,                 0,         NULL},
 224        {vc_pattern_ipv6_udp,                 0,         NULL},
 225        {vc_pattern_ipv6_sctp,                0,         NULL},
 226        {vc_pattern_ether,                    0,         NULL},
 227        {vc_pattern_ipv4_gtpu,                0,         NULL},
 228        {vc_pattern_ipv4_gtpu_eh,             0,         NULL},
 229        {vc_pattern_ipv4_l2tpv3,              0,         NULL},
 230        {vc_pattern_ipv6_l2tpv3,              0,         NULL},
 231        {vc_pattern_ipv4_esp,                 0,         NULL},
 232        {vc_pattern_ipv6_esp,                 0,         NULL},
 233        {vc_pattern_ipv4_ah,                  0,         NULL},
 234        {vc_pattern_ipv6_ah,                  0,         NULL},
 235        {vc_pattern_ipv4_nat_t_esp,           0,         NULL},
 236        {vc_pattern_ipv6_nat_t_esp,           0,         NULL},
 237        {vc_pattern_ipv4_pfcp,                0,         NULL},
 238        {vc_pattern_ipv6_pfcp,                0,         NULL},
 239};
 240
 241struct virtchnl_fdir_inset_map {
 242        enum virtchnl_proto_hdr_field field;
 243        enum ice_flow_field fld;
 244        u64 flag;
 245        u64 mask;
 246};
 247
 248static const struct virtchnl_fdir_inset_map fdir_inset_map[] = {
 249        {VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE, ICE_FLOW_FIELD_IDX_ETH_TYPE, 0, 0},
 250        {VIRTCHNL_PROTO_HDR_IPV4_SRC, ICE_FLOW_FIELD_IDX_IPV4_SA, 0, 0},
 251        {VIRTCHNL_PROTO_HDR_IPV4_DST, ICE_FLOW_FIELD_IDX_IPV4_DA, 0, 0},
 252        {VIRTCHNL_PROTO_HDR_IPV4_DSCP, ICE_FLOW_FIELD_IDX_IPV4_DSCP, 0, 0},
 253        {VIRTCHNL_PROTO_HDR_IPV4_TTL, ICE_FLOW_FIELD_IDX_IPV4_TTL, 0, 0},
 254        {VIRTCHNL_PROTO_HDR_IPV4_PROT, ICE_FLOW_FIELD_IDX_IPV4_PROT, 0, 0},
 255        {VIRTCHNL_PROTO_HDR_IPV6_SRC, ICE_FLOW_FIELD_IDX_IPV6_SA, 0, 0},
 256        {VIRTCHNL_PROTO_HDR_IPV6_DST, ICE_FLOW_FIELD_IDX_IPV6_DA, 0, 0},
 257        {VIRTCHNL_PROTO_HDR_IPV6_TC, ICE_FLOW_FIELD_IDX_IPV6_DSCP, 0, 0},
 258        {VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT, ICE_FLOW_FIELD_IDX_IPV6_TTL, 0, 0},
 259        {VIRTCHNL_PROTO_HDR_IPV6_PROT, ICE_FLOW_FIELD_IDX_IPV6_PROT, 0, 0},
 260        {VIRTCHNL_PROTO_HDR_UDP_SRC_PORT, ICE_FLOW_FIELD_IDX_UDP_SRC_PORT, 0, 0},
 261        {VIRTCHNL_PROTO_HDR_UDP_DST_PORT, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0},
 262        {VIRTCHNL_PROTO_HDR_TCP_SRC_PORT, ICE_FLOW_FIELD_IDX_TCP_SRC_PORT, 0, 0},
 263        {VIRTCHNL_PROTO_HDR_TCP_DST_PORT, ICE_FLOW_FIELD_IDX_TCP_DST_PORT, 0, 0},
 264        {VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT, ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT, 0, 0},
 265        {VIRTCHNL_PROTO_HDR_SCTP_DST_PORT, ICE_FLOW_FIELD_IDX_SCTP_DST_PORT, 0, 0},
 266        {VIRTCHNL_PROTO_HDR_GTPU_IP_TEID, ICE_FLOW_FIELD_IDX_GTPU_IP_TEID, 0, 0},
 267        {VIRTCHNL_PROTO_HDR_GTPU_EH_QFI, ICE_FLOW_FIELD_IDX_GTPU_EH_QFI, 0, 0},
 268        {VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI,
 269                FDIR_INSET_FLAG_ESP_IPSEC, FDIR_INSET_FLAG_ESP_M},
 270        {VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI,
 271                FDIR_INSET_FLAG_ESP_UDP, FDIR_INSET_FLAG_ESP_M},
 272        {VIRTCHNL_PROTO_HDR_AH_SPI, ICE_FLOW_FIELD_IDX_AH_SPI, 0, 0},
 273        {VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID, ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID, 0, 0},
 274        {VIRTCHNL_PROTO_HDR_PFCP_S_FIELD, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0},
 275};
 276
 277/**
 278 * ice_vc_fdir_param_check
 279 * @vf: pointer to the VF structure
 280 * @vsi_id: VF relative VSI ID
 281 *
 282 * Check for the valid VSI ID, PF's state and VF's state
 283 *
 284 * Return: 0 on success, and -EINVAL on error.
 285 */
 286static int
 287ice_vc_fdir_param_check(struct ice_vf *vf, u16 vsi_id)
 288{
 289        struct ice_pf *pf = vf->pf;
 290
 291        if (!test_bit(ICE_FLAG_FD_ENA, pf->flags))
 292                return -EINVAL;
 293
 294        if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
 295                return -EINVAL;
 296
 297        if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF))
 298                return -EINVAL;
 299
 300        if (vsi_id != vf->lan_vsi_num)
 301                return -EINVAL;
 302
 303        if (!ice_vc_isvalid_vsi_id(vf, vsi_id))
 304                return -EINVAL;
 305
 306        if (!pf->vsi[vf->lan_vsi_idx])
 307                return -EINVAL;
 308
 309        return 0;
 310}
 311
 312/**
 313 * ice_vf_start_ctrl_vsi
 314 * @vf: pointer to the VF structure
 315 *
 316 * Allocate ctrl_vsi for the first time and open the ctrl_vsi port for VF
 317 *
 318 * Return: 0 on success, and other on error.
 319 */
 320static int ice_vf_start_ctrl_vsi(struct ice_vf *vf)
 321{
 322        struct ice_pf *pf = vf->pf;
 323        struct ice_vsi *ctrl_vsi;
 324        struct device *dev;
 325        int err;
 326
 327        dev = ice_pf_to_dev(pf);
 328        if (vf->ctrl_vsi_idx != ICE_NO_VSI)
 329                return -EEXIST;
 330
 331        ctrl_vsi = ice_vf_ctrl_vsi_setup(vf);
 332        if (!ctrl_vsi) {
 333                dev_dbg(dev, "Could not setup control VSI for VF %d\n",
 334                        vf->vf_id);
 335                return -ENOMEM;
 336        }
 337
 338        err = ice_vsi_open_ctrl(ctrl_vsi);
 339        if (err) {
 340                dev_dbg(dev, "Could not open control VSI for VF %d\n",
 341                        vf->vf_id);
 342                goto err_vsi_open;
 343        }
 344
 345        return 0;
 346
 347err_vsi_open:
 348        ice_vsi_release(ctrl_vsi);
 349        if (vf->ctrl_vsi_idx != ICE_NO_VSI) {
 350                pf->vsi[vf->ctrl_vsi_idx] = NULL;
 351                vf->ctrl_vsi_idx = ICE_NO_VSI;
 352        }
 353        return err;
 354}
 355
 356/**
 357 * ice_vc_fdir_alloc_prof - allocate profile for this filter flow type
 358 * @vf: pointer to the VF structure
 359 * @flow: filter flow type
 360 *
 361 * Return: 0 on success, and other on error.
 362 */
 363static int
 364ice_vc_fdir_alloc_prof(struct ice_vf *vf, enum ice_fltr_ptype flow)
 365{
 366        struct ice_vf_fdir *fdir = &vf->fdir;
 367
 368        if (!fdir->fdir_prof) {
 369                fdir->fdir_prof = devm_kcalloc(ice_pf_to_dev(vf->pf),
 370                                               ICE_FLTR_PTYPE_MAX,
 371                                               sizeof(*fdir->fdir_prof),
 372                                               GFP_KERNEL);
 373                if (!fdir->fdir_prof)
 374                        return -ENOMEM;
 375        }
 376
 377        if (!fdir->fdir_prof[flow]) {
 378                fdir->fdir_prof[flow] = devm_kzalloc(ice_pf_to_dev(vf->pf),
 379                                                     sizeof(**fdir->fdir_prof),
 380                                                     GFP_KERNEL);
 381                if (!fdir->fdir_prof[flow])
 382                        return -ENOMEM;
 383        }
 384
 385        return 0;
 386}
 387
 388/**
 389 * ice_vc_fdir_free_prof - free profile for this filter flow type
 390 * @vf: pointer to the VF structure
 391 * @flow: filter flow type
 392 */
 393static void
 394ice_vc_fdir_free_prof(struct ice_vf *vf, enum ice_fltr_ptype flow)
 395{
 396        struct ice_vf_fdir *fdir = &vf->fdir;
 397
 398        if (!fdir->fdir_prof)
 399                return;
 400
 401        if (!fdir->fdir_prof[flow])
 402                return;
 403
 404        devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof[flow]);
 405        fdir->fdir_prof[flow] = NULL;
 406}
 407
 408/**
 409 * ice_vc_fdir_free_prof_all - free all the profile for this VF
 410 * @vf: pointer to the VF structure
 411 */
 412static void ice_vc_fdir_free_prof_all(struct ice_vf *vf)
 413{
 414        struct ice_vf_fdir *fdir = &vf->fdir;
 415        enum ice_fltr_ptype flow;
 416
 417        if (!fdir->fdir_prof)
 418                return;
 419
 420        for (flow = ICE_FLTR_PTYPE_NONF_NONE; flow < ICE_FLTR_PTYPE_MAX; flow++)
 421                ice_vc_fdir_free_prof(vf, flow);
 422
 423        devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof);
 424        fdir->fdir_prof = NULL;
 425}
 426
 427/**
 428 * ice_vc_fdir_parse_flow_fld
 429 * @proto_hdr: virtual channel protocol filter header
 430 * @conf: FDIR configuration for each filter
 431 * @fld: field type array
 432 * @fld_cnt: field counter
 433 *
 434 * Parse the virtual channel filter header and store them into field type array
 435 *
 436 * Return: 0 on success, and other on error.
 437 */
 438static int
 439ice_vc_fdir_parse_flow_fld(struct virtchnl_proto_hdr *proto_hdr,
 440                           struct virtchnl_fdir_fltr_conf *conf,
 441                           enum ice_flow_field *fld, int *fld_cnt)
 442{
 443        struct virtchnl_proto_hdr hdr;
 444        u32 i;
 445
 446        memcpy(&hdr, proto_hdr, sizeof(hdr));
 447
 448        for (i = 0; (i < ARRAY_SIZE(fdir_inset_map)) &&
 449             VIRTCHNL_GET_PROTO_HDR_FIELD(&hdr); i++)
 450                if (VIRTCHNL_TEST_PROTO_HDR(&hdr, fdir_inset_map[i].field)) {
 451                        if (fdir_inset_map[i].mask &&
 452                            ((fdir_inset_map[i].mask & conf->inset_flag) !=
 453                             fdir_inset_map[i].flag))
 454                                continue;
 455
 456                        fld[*fld_cnt] = fdir_inset_map[i].fld;
 457                        *fld_cnt += 1;
 458                        if (*fld_cnt >= ICE_FLOW_FIELD_IDX_MAX)
 459                                return -EINVAL;
 460                        VIRTCHNL_DEL_PROTO_HDR_FIELD(&hdr,
 461                                                     fdir_inset_map[i].field);
 462                }
 463
 464        return 0;
 465}
 466
 467/**
 468 * ice_vc_fdir_set_flow_fld
 469 * @vf: pointer to the VF structure
 470 * @fltr: virtual channel add cmd buffer
 471 * @conf: FDIR configuration for each filter
 472 * @seg: array of one or more packet segments that describe the flow
 473 *
 474 * Parse the virtual channel add msg buffer's field vector and store them into
 475 * flow's packet segment field
 476 *
 477 * Return: 0 on success, and other on error.
 478 */
 479static int
 480ice_vc_fdir_set_flow_fld(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
 481                         struct virtchnl_fdir_fltr_conf *conf,
 482                         struct ice_flow_seg_info *seg)
 483{
 484        struct virtchnl_fdir_rule *rule = &fltr->rule_cfg;
 485        enum ice_flow_field fld[ICE_FLOW_FIELD_IDX_MAX];
 486        struct device *dev = ice_pf_to_dev(vf->pf);
 487        struct virtchnl_proto_hdrs *proto;
 488        int fld_cnt = 0;
 489        int i;
 490
 491        proto = &rule->proto_hdrs;
 492        for (i = 0; i < proto->count; i++) {
 493                struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i];
 494                int ret;
 495
 496                ret = ice_vc_fdir_parse_flow_fld(hdr, conf, fld, &fld_cnt);
 497                if (ret)
 498                        return ret;
 499        }
 500
 501        if (fld_cnt == 0) {
 502                dev_dbg(dev, "Empty input set for VF %d\n", vf->vf_id);
 503                return -EINVAL;
 504        }
 505
 506        for (i = 0; i < fld_cnt; i++)
 507                ice_flow_set_fld(seg, fld[i],
 508                                 ICE_FLOW_FLD_OFF_INVAL,
 509                                 ICE_FLOW_FLD_OFF_INVAL,
 510                                 ICE_FLOW_FLD_OFF_INVAL, false);
 511
 512        return 0;
 513}
 514
 515/**
 516 * ice_vc_fdir_set_flow_hdr - config the flow's packet segment header
 517 * @vf: pointer to the VF structure
 518 * @conf: FDIR configuration for each filter
 519 * @seg: array of one or more packet segments that describe the flow
 520 *
 521 * Return: 0 on success, and other on error.
 522 */
 523static int
 524ice_vc_fdir_set_flow_hdr(struct ice_vf *vf,
 525                         struct virtchnl_fdir_fltr_conf *conf,
 526                         struct ice_flow_seg_info *seg)
 527{
 528        enum ice_fltr_ptype flow = conf->input.flow_type;
 529        enum ice_fdir_tunnel_type ttype = conf->ttype;
 530        struct device *dev = ice_pf_to_dev(vf->pf);
 531
 532        switch (flow) {
 533        case ICE_FLTR_PTYPE_NON_IP_L2:
 534                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH_NON_IP);
 535                break;
 536        case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3:
 537                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 |
 538                                  ICE_FLOW_SEG_HDR_IPV4 |
 539                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 540                break;
 541        case ICE_FLTR_PTYPE_NONF_IPV4_ESP:
 542                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP |
 543                                  ICE_FLOW_SEG_HDR_IPV4 |
 544                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 545                break;
 546        case ICE_FLTR_PTYPE_NONF_IPV4_AH:
 547                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH |
 548                                  ICE_FLOW_SEG_HDR_IPV4 |
 549                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 550                break;
 551        case ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP:
 552                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP |
 553                                  ICE_FLOW_SEG_HDR_IPV4 |
 554                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 555                break;
 556        case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE:
 557                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE |
 558                                  ICE_FLOW_SEG_HDR_IPV4 |
 559                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 560                break;
 561        case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION:
 562                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION |
 563                                  ICE_FLOW_SEG_HDR_IPV4 |
 564                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 565                break;
 566        case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
 567                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV4 |
 568                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 569                break;
 570        case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
 571                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
 572                                  ICE_FLOW_SEG_HDR_IPV4 |
 573                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 574                break;
 575        case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
 576                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
 577                                  ICE_FLOW_SEG_HDR_IPV4 |
 578                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 579                break;
 580        case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_UDP:
 581        case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:
 582        case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:
 583        case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:
 584                if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU) {
 585                        ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_IP |
 586                                          ICE_FLOW_SEG_HDR_IPV4 |
 587                                          ICE_FLOW_SEG_HDR_IPV_OTHER);
 588                } else if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH) {
 589                        ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_EH |
 590                                          ICE_FLOW_SEG_HDR_GTPU_IP |
 591                                          ICE_FLOW_SEG_HDR_IPV4 |
 592                                          ICE_FLOW_SEG_HDR_IPV_OTHER);
 593                } else {
 594                        dev_dbg(dev, "Invalid tunnel type 0x%x for VF %d\n",
 595                                flow, vf->vf_id);
 596                        return -EINVAL;
 597                }
 598                break;
 599        case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
 600                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP |
 601                                  ICE_FLOW_SEG_HDR_IPV4 |
 602                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 603                break;
 604        case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3:
 605                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 |
 606                                  ICE_FLOW_SEG_HDR_IPV6 |
 607                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 608                break;
 609        case ICE_FLTR_PTYPE_NONF_IPV6_ESP:
 610                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP |
 611                                  ICE_FLOW_SEG_HDR_IPV6 |
 612                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 613                break;
 614        case ICE_FLTR_PTYPE_NONF_IPV6_AH:
 615                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH |
 616                                  ICE_FLOW_SEG_HDR_IPV6 |
 617                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 618                break;
 619        case ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP:
 620                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP |
 621                                  ICE_FLOW_SEG_HDR_IPV6 |
 622                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 623                break;
 624        case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE:
 625                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE |
 626                                  ICE_FLOW_SEG_HDR_IPV6 |
 627                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 628                break;
 629        case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION:
 630                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION |
 631                                  ICE_FLOW_SEG_HDR_IPV6 |
 632                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 633                break;
 634        case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
 635                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV6 |
 636                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 637                break;
 638        case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
 639                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |
 640                                  ICE_FLOW_SEG_HDR_IPV6 |
 641                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 642                break;
 643        case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
 644                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |
 645                                  ICE_FLOW_SEG_HDR_IPV6 |
 646                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 647                break;
 648        case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
 649                ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP |
 650                                  ICE_FLOW_SEG_HDR_IPV6 |
 651                                  ICE_FLOW_SEG_HDR_IPV_OTHER);
 652                break;
 653        default:
 654                dev_dbg(dev, "Invalid flow type 0x%x for VF %d failed\n",
 655                        flow, vf->vf_id);
 656                return -EINVAL;
 657        }
 658
 659        return 0;
 660}
 661
 662/**
 663 * ice_vc_fdir_rem_prof - remove profile for this filter flow type
 664 * @vf: pointer to the VF structure
 665 * @flow: filter flow type
 666 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter
 667 */
 668static void
 669ice_vc_fdir_rem_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, int tun)
 670{
 671        struct ice_vf_fdir *fdir = &vf->fdir;
 672        struct ice_fd_hw_prof *vf_prof;
 673        struct ice_pf *pf = vf->pf;
 674        struct ice_vsi *vf_vsi;
 675        struct device *dev;
 676        struct ice_hw *hw;
 677        u64 prof_id;
 678        int i;
 679
 680        dev = ice_pf_to_dev(pf);
 681        hw = &pf->hw;
 682        if (!fdir->fdir_prof || !fdir->fdir_prof[flow])
 683                return;
 684
 685        vf_prof = fdir->fdir_prof[flow];
 686
 687        vf_vsi = pf->vsi[vf->lan_vsi_idx];
 688        if (!vf_vsi) {
 689                dev_dbg(dev, "NULL vf %d vsi pointer\n", vf->vf_id);
 690                return;
 691        }
 692
 693        if (!fdir->prof_entry_cnt[flow][tun])
 694                return;
 695
 696        prof_id = ICE_FLOW_PROF_FD(vf_vsi->vsi_num,
 697                                   flow, tun ? ICE_FLTR_PTYPE_MAX : 0);
 698
 699        for (i = 0; i < fdir->prof_entry_cnt[flow][tun]; i++)
 700                if (vf_prof->entry_h[i][tun]) {
 701                        u16 vsi_num = ice_get_hw_vsi_num(hw, vf_prof->vsi_h[i]);
 702
 703                        ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id);
 704                        ice_flow_rem_entry(hw, ICE_BLK_FD,
 705                                           vf_prof->entry_h[i][tun]);
 706                        vf_prof->entry_h[i][tun] = 0;
 707                }
 708
 709        ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id);
 710        devm_kfree(dev, vf_prof->fdir_seg[tun]);
 711        vf_prof->fdir_seg[tun] = NULL;
 712
 713        for (i = 0; i < vf_prof->cnt; i++)
 714                vf_prof->vsi_h[i] = 0;
 715
 716        fdir->prof_entry_cnt[flow][tun] = 0;
 717}
 718
 719/**
 720 * ice_vc_fdir_rem_prof_all - remove profile for this VF
 721 * @vf: pointer to the VF structure
 722 */
 723static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)
 724{
 725        enum ice_fltr_ptype flow;
 726
 727        for (flow = ICE_FLTR_PTYPE_NONF_NONE;
 728             flow < ICE_FLTR_PTYPE_MAX; flow++) {
 729                ice_vc_fdir_rem_prof(vf, flow, 0);
 730                ice_vc_fdir_rem_prof(vf, flow, 1);
 731        }
 732}
 733
 734/**
 735 * ice_vc_fdir_write_flow_prof
 736 * @vf: pointer to the VF structure
 737 * @flow: filter flow type
 738 * @seg: array of one or more packet segments that describe the flow
 739 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter
 740 *
 741 * Write the flow's profile config and packet segment into the hardware
 742 *
 743 * Return: 0 on success, and other on error.
 744 */
 745static int
 746ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow,
 747                            struct ice_flow_seg_info *seg, int tun)
 748{
 749        struct ice_vf_fdir *fdir = &vf->fdir;
 750        struct ice_vsi *vf_vsi, *ctrl_vsi;
 751        struct ice_flow_seg_info *old_seg;
 752        struct ice_flow_prof *prof = NULL;
 753        struct ice_fd_hw_prof *vf_prof;
 754        enum ice_status status;
 755        struct device *dev;
 756        struct ice_pf *pf;
 757        struct ice_hw *hw;
 758        u64 entry1_h = 0;
 759        u64 entry2_h = 0;
 760        u64 prof_id;
 761        int ret;
 762
 763        pf = vf->pf;
 764        dev = ice_pf_to_dev(pf);
 765        hw = &pf->hw;
 766        vf_vsi = pf->vsi[vf->lan_vsi_idx];
 767        if (!vf_vsi)
 768                return -EINVAL;
 769
 770        ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];
 771        if (!ctrl_vsi)
 772                return -EINVAL;
 773
 774        vf_prof = fdir->fdir_prof[flow];
 775        old_seg = vf_prof->fdir_seg[tun];
 776        if (old_seg) {
 777                if (!memcmp(old_seg, seg, sizeof(*seg))) {
 778                        dev_dbg(dev, "Duplicated profile for VF %d!\n",
 779                                vf->vf_id);
 780                        return -EEXIST;
 781                }
 782
 783                if (fdir->fdir_fltr_cnt[flow][tun]) {
 784                        ret = -EINVAL;
 785                        dev_dbg(dev, "Input set conflicts for VF %d\n",
 786                                vf->vf_id);
 787                        goto err_exit;
 788                }
 789
 790                /* remove previously allocated profile */
 791                ice_vc_fdir_rem_prof(vf, flow, tun);
 792        }
 793
 794        prof_id = ICE_FLOW_PROF_FD(vf_vsi->vsi_num, flow,
 795                                   tun ? ICE_FLTR_PTYPE_MAX : 0);
 796
 797        status = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id, seg,
 798                                   tun + 1, &prof);
 799        ret = ice_status_to_errno(status);
 800        if (ret) {
 801                dev_dbg(dev, "Could not add VSI flow 0x%x for VF %d\n",
 802                        flow, vf->vf_id);
 803                goto err_exit;
 804        }
 805
 806        status = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, vf_vsi->idx,
 807                                    vf_vsi->idx, ICE_FLOW_PRIO_NORMAL,
 808                                    seg, &entry1_h);
 809        ret = ice_status_to_errno(status);
 810        if (ret) {
 811                dev_dbg(dev, "Could not add flow 0x%x VSI entry for VF %d\n",
 812                        flow, vf->vf_id);
 813                goto err_prof;
 814        }
 815
 816        status = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, vf_vsi->idx,
 817                                    ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL,
 818                                    seg, &entry2_h);
 819        ret = ice_status_to_errno(status);
 820        if (ret) {
 821                dev_dbg(dev,
 822                        "Could not add flow 0x%x Ctrl VSI entry for VF %d\n",
 823                        flow, vf->vf_id);
 824                goto err_entry_1;
 825        }
 826
 827        vf_prof->fdir_seg[tun] = seg;
 828        vf_prof->cnt = 0;
 829        fdir->prof_entry_cnt[flow][tun] = 0;
 830
 831        vf_prof->entry_h[vf_prof->cnt][tun] = entry1_h;
 832        vf_prof->vsi_h[vf_prof->cnt] = vf_vsi->idx;
 833        vf_prof->cnt++;
 834        fdir->prof_entry_cnt[flow][tun]++;
 835
 836        vf_prof->entry_h[vf_prof->cnt][tun] = entry2_h;
 837        vf_prof->vsi_h[vf_prof->cnt] = ctrl_vsi->idx;
 838        vf_prof->cnt++;
 839        fdir->prof_entry_cnt[flow][tun]++;
 840
 841        return 0;
 842
 843err_entry_1:
 844        ice_rem_prof_id_flow(hw, ICE_BLK_FD,
 845                             ice_get_hw_vsi_num(hw, vf_vsi->idx), prof_id);
 846        ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h);
 847err_prof:
 848        ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id);
 849err_exit:
 850        return ret;
 851}
 852
 853/**
 854 * ice_vc_fdir_config_input_set
 855 * @vf: pointer to the VF structure
 856 * @fltr: virtual channel add cmd buffer
 857 * @conf: FDIR configuration for each filter
 858 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter
 859 *
 860 * Config the input set type and value for virtual channel add msg buffer
 861 *
 862 * Return: 0 on success, and other on error.
 863 */
 864static int
 865ice_vc_fdir_config_input_set(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
 866                             struct virtchnl_fdir_fltr_conf *conf, int tun)
 867{
 868        struct ice_fdir_fltr *input = &conf->input;
 869        struct device *dev = ice_pf_to_dev(vf->pf);
 870        struct ice_flow_seg_info *seg;
 871        enum ice_fltr_ptype flow;
 872        int ret;
 873
 874        flow = input->flow_type;
 875        ret = ice_vc_fdir_alloc_prof(vf, flow);
 876        if (ret) {
 877                dev_dbg(dev, "Alloc flow prof for VF %d failed\n", vf->vf_id);
 878                return ret;
 879        }
 880
 881        seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL);
 882        if (!seg)
 883                return -ENOMEM;
 884
 885        ret = ice_vc_fdir_set_flow_fld(vf, fltr, conf, seg);
 886        if (ret) {
 887                dev_dbg(dev, "Set flow field for VF %d failed\n", vf->vf_id);
 888                goto err_exit;
 889        }
 890
 891        ret = ice_vc_fdir_set_flow_hdr(vf, conf, seg);
 892        if (ret) {
 893                dev_dbg(dev, "Set flow hdr for VF %d failed\n", vf->vf_id);
 894                goto err_exit;
 895        }
 896
 897        ret = ice_vc_fdir_write_flow_prof(vf, flow, seg, tun);
 898        if (ret == -EEXIST) {
 899                devm_kfree(dev, seg);
 900        } else if (ret) {
 901                dev_dbg(dev, "Write flow profile for VF %d failed\n",
 902                        vf->vf_id);
 903                goto err_exit;
 904        }
 905
 906        return 0;
 907
 908err_exit:
 909        devm_kfree(dev, seg);
 910        return ret;
 911}
 912
 913/**
 914 * ice_vc_fdir_match_pattern
 915 * @fltr: virtual channel add cmd buffer
 916 * @type: virtual channel protocol filter header type
 917 *
 918 * Matching the header type by comparing fltr and type's value.
 919 *
 920 * Return: true on success, and false on error.
 921 */
 922static bool
 923ice_vc_fdir_match_pattern(struct virtchnl_fdir_add *fltr,
 924                          enum virtchnl_proto_hdr_type *type)
 925{
 926        struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs;
 927        int i = 0;
 928
 929        while ((i < proto->count) &&
 930               (*type == proto->proto_hdr[i].type) &&
 931               (*type != VIRTCHNL_PROTO_HDR_NONE)) {
 932                type++;
 933                i++;
 934        }
 935
 936        return ((i == proto->count) && (*type == VIRTCHNL_PROTO_HDR_NONE));
 937}
 938
 939/**
 940 * ice_vc_fdir_get_pattern - get while list pattern
 941 * @vf: pointer to the VF info
 942 * @len: filter list length
 943 *
 944 * Return: pointer to allowed filter list
 945 */
 946static const struct virtchnl_fdir_pattern_match_item *
 947ice_vc_fdir_get_pattern(struct ice_vf *vf, int *len)
 948{
 949        const struct virtchnl_fdir_pattern_match_item *item;
 950        struct ice_pf *pf = vf->pf;
 951        struct ice_hw *hw;
 952
 953        hw = &pf->hw;
 954        if (!strncmp(hw->active_pkg_name, "ICE COMMS Package",
 955                     sizeof(hw->active_pkg_name))) {
 956                item = vc_fdir_pattern_comms;
 957                *len = ARRAY_SIZE(vc_fdir_pattern_comms);
 958        } else {
 959                item = vc_fdir_pattern_os;
 960                *len = ARRAY_SIZE(vc_fdir_pattern_os);
 961        }
 962
 963        return item;
 964}
 965
 966/**
 967 * ice_vc_fdir_search_pattern
 968 * @vf: pointer to the VF info
 969 * @fltr: virtual channel add cmd buffer
 970 *
 971 * Search for matched pattern from supported pattern list
 972 *
 973 * Return: 0 on success, and other on error.
 974 */
 975static int
 976ice_vc_fdir_search_pattern(struct ice_vf *vf, struct virtchnl_fdir_add *fltr)
 977{
 978        const struct virtchnl_fdir_pattern_match_item *pattern;
 979        int len, i;
 980
 981        pattern = ice_vc_fdir_get_pattern(vf, &len);
 982
 983        for (i = 0; i < len; i++)
 984                if (ice_vc_fdir_match_pattern(fltr, pattern[i].list))
 985                        return 0;
 986
 987        return -EINVAL;
 988}
 989
 990/**
 991 * ice_vc_fdir_parse_pattern
 992 * @vf: pointer to the VF info
 993 * @fltr: virtual channel add cmd buffer
 994 * @conf: FDIR configuration for each filter
 995 *
 996 * Parse the virtual channel filter's pattern and store them into conf
 997 *
 998 * Return: 0 on success, and other on error.
 999 */
1000static int
1001ice_vc_fdir_parse_pattern(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
1002                          struct virtchnl_fdir_fltr_conf *conf)
1003{
1004        struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs;
1005        enum virtchnl_proto_hdr_type l3 = VIRTCHNL_PROTO_HDR_NONE;
1006        enum virtchnl_proto_hdr_type l4 = VIRTCHNL_PROTO_HDR_NONE;
1007        struct device *dev = ice_pf_to_dev(vf->pf);
1008        struct ice_fdir_fltr *input = &conf->input;
1009        int i;
1010
1011        if (proto->count > VIRTCHNL_MAX_NUM_PROTO_HDRS) {
1012                dev_dbg(dev, "Invalid protocol count:0x%x for VF %d\n",
1013                        proto->count, vf->vf_id);
1014                return -EINVAL;
1015        }
1016
1017        for (i = 0; i < proto->count; i++) {
1018                struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i];
1019                struct ip_esp_hdr *esph;
1020                struct ip_auth_hdr *ah;
1021                struct sctphdr *sctph;
1022                struct ipv6hdr *ip6h;
1023                struct udphdr *udph;
1024                struct tcphdr *tcph;
1025                struct ethhdr *eth;
1026                struct iphdr *iph;
1027                u8 s_field;
1028                u8 *rawh;
1029
1030                switch (hdr->type) {
1031                case VIRTCHNL_PROTO_HDR_ETH:
1032                        eth = (struct ethhdr *)hdr->buffer;
1033                        input->flow_type = ICE_FLTR_PTYPE_NON_IP_L2;
1034
1035                        if (hdr->field_selector)
1036                                input->ext_data.ether_type = eth->h_proto;
1037                        break;
1038                case VIRTCHNL_PROTO_HDR_IPV4:
1039                        iph = (struct iphdr *)hdr->buffer;
1040                        l3 = VIRTCHNL_PROTO_HDR_IPV4;
1041                        input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
1042
1043                        if (hdr->field_selector) {
1044                                input->ip.v4.src_ip = iph->saddr;
1045                                input->ip.v4.dst_ip = iph->daddr;
1046                                input->ip.v4.tos = iph->tos;
1047                                input->ip.v4.proto = iph->protocol;
1048                        }
1049                        break;
1050                case VIRTCHNL_PROTO_HDR_IPV6:
1051                        ip6h = (struct ipv6hdr *)hdr->buffer;
1052                        l3 = VIRTCHNL_PROTO_HDR_IPV6;
1053                        input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
1054
1055                        if (hdr->field_selector) {
1056                                memcpy(input->ip.v6.src_ip,
1057                                       ip6h->saddr.in6_u.u6_addr8,
1058                                       sizeof(ip6h->saddr));
1059                                memcpy(input->ip.v6.dst_ip,
1060                                       ip6h->daddr.in6_u.u6_addr8,
1061                                       sizeof(ip6h->daddr));
1062                                input->ip.v6.tc = ((u8)(ip6h->priority) << 4) |
1063                                                  (ip6h->flow_lbl[0] >> 4);
1064                                input->ip.v6.proto = ip6h->nexthdr;
1065                        }
1066                        break;
1067                case VIRTCHNL_PROTO_HDR_TCP:
1068                        tcph = (struct tcphdr *)hdr->buffer;
1069                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1070                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
1071                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1072                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
1073
1074                        if (hdr->field_selector) {
1075                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {
1076                                        input->ip.v4.src_port = tcph->source;
1077                                        input->ip.v4.dst_port = tcph->dest;
1078                                } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {
1079                                        input->ip.v6.src_port = tcph->source;
1080                                        input->ip.v6.dst_port = tcph->dest;
1081                                }
1082                        }
1083                        break;
1084                case VIRTCHNL_PROTO_HDR_UDP:
1085                        udph = (struct udphdr *)hdr->buffer;
1086                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1087                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
1088                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1089                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
1090
1091                        if (hdr->field_selector) {
1092                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {
1093                                        input->ip.v4.src_port = udph->source;
1094                                        input->ip.v4.dst_port = udph->dest;
1095                                } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {
1096                                        input->ip.v6.src_port = udph->source;
1097                                        input->ip.v6.dst_port = udph->dest;
1098                                }
1099                        }
1100                        break;
1101                case VIRTCHNL_PROTO_HDR_SCTP:
1102                        sctph = (struct sctphdr *)hdr->buffer;
1103                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1104                                input->flow_type =
1105                                        ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
1106                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1107                                input->flow_type =
1108                                        ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
1109
1110                        if (hdr->field_selector) {
1111                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {
1112                                        input->ip.v4.src_port = sctph->source;
1113                                        input->ip.v4.dst_port = sctph->dest;
1114                                } else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {
1115                                        input->ip.v6.src_port = sctph->source;
1116                                        input->ip.v6.dst_port = sctph->dest;
1117                                }
1118                        }
1119                        break;
1120                case VIRTCHNL_PROTO_HDR_L2TPV3:
1121                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1122                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3;
1123                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1124                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3;
1125
1126                        if (hdr->field_selector)
1127                                input->l2tpv3_data.session_id = *((__be32 *)hdr->buffer);
1128                        break;
1129                case VIRTCHNL_PROTO_HDR_ESP:
1130                        esph = (struct ip_esp_hdr *)hdr->buffer;
1131                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4 &&
1132                            l4 == VIRTCHNL_PROTO_HDR_UDP)
1133                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP;
1134                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 &&
1135                                 l4 == VIRTCHNL_PROTO_HDR_UDP)
1136                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP;
1137                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 &&
1138                                 l4 == VIRTCHNL_PROTO_HDR_NONE)
1139                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_ESP;
1140                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 &&
1141                                 l4 == VIRTCHNL_PROTO_HDR_NONE)
1142                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_ESP;
1143
1144                        if (l4 == VIRTCHNL_PROTO_HDR_UDP)
1145                                conf->inset_flag |= FDIR_INSET_FLAG_ESP_UDP;
1146                        else
1147                                conf->inset_flag |= FDIR_INSET_FLAG_ESP_IPSEC;
1148
1149                        if (hdr->field_selector) {
1150                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1151                                        input->ip.v4.sec_parm_idx = esph->spi;
1152                                else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1153                                        input->ip.v6.sec_parm_idx = esph->spi;
1154                        }
1155                        break;
1156                case VIRTCHNL_PROTO_HDR_AH:
1157                        ah = (struct ip_auth_hdr *)hdr->buffer;
1158                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1159                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_AH;
1160                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1161                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_AH;
1162
1163                        if (hdr->field_selector) {
1164                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1165                                        input->ip.v4.sec_parm_idx = ah->spi;
1166                                else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1167                                        input->ip.v6.sec_parm_idx = ah->spi;
1168                        }
1169                        break;
1170                case VIRTCHNL_PROTO_HDR_PFCP:
1171                        rawh = (u8 *)hdr->buffer;
1172                        s_field = (rawh[0] >> PFCP_S_OFFSET) & PFCP_S_MASK;
1173                        if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 0)
1174                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE;
1175                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 1)
1176                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION;
1177                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 0)
1178                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE;
1179                        else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 1)
1180                                input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION;
1181
1182                        if (hdr->field_selector) {
1183                                if (l3 == VIRTCHNL_PROTO_HDR_IPV4)
1184                                        input->ip.v4.dst_port = cpu_to_be16(PFCP_PORT_NR);
1185                                else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)
1186                                        input->ip.v6.dst_port = cpu_to_be16(PFCP_PORT_NR);
1187                        }
1188                        break;
1189                case VIRTCHNL_PROTO_HDR_GTPU_IP:
1190                        rawh = (u8 *)hdr->buffer;
1191                        input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
1192
1193                        if (hdr->field_selector)
1194                                input->gtpu_data.teid = *(__be32 *)(&rawh[GTPU_TEID_OFFSET]);
1195                        conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU;
1196                        break;
1197                case VIRTCHNL_PROTO_HDR_GTPU_EH:
1198                        rawh = (u8 *)hdr->buffer;
1199
1200                        if (hdr->field_selector)
1201                                input->gtpu_data.qfi = rawh[GTPU_EH_QFI_OFFSET] & GTPU_EH_QFI_MASK;
1202                        conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU_EH;
1203                        break;
1204                default:
1205                        dev_dbg(dev, "Invalid header type 0x:%x for VF %d\n",
1206                                hdr->type, vf->vf_id);
1207                        return -EINVAL;
1208                }
1209        }
1210
1211        return 0;
1212}
1213
1214/**
1215 * ice_vc_fdir_parse_action
1216 * @vf: pointer to the VF info
1217 * @fltr: virtual channel add cmd buffer
1218 * @conf: FDIR configuration for each filter
1219 *
1220 * Parse the virtual channel filter's action and store them into conf
1221 *
1222 * Return: 0 on success, and other on error.
1223 */
1224static int
1225ice_vc_fdir_parse_action(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
1226                         struct virtchnl_fdir_fltr_conf *conf)
1227{
1228        struct virtchnl_filter_action_set *as = &fltr->rule_cfg.action_set;
1229        struct device *dev = ice_pf_to_dev(vf->pf);
1230        struct ice_fdir_fltr *input = &conf->input;
1231        u32 dest_num = 0;
1232        u32 mark_num = 0;
1233        int i;
1234
1235        if (as->count > VIRTCHNL_MAX_NUM_ACTIONS) {
1236                dev_dbg(dev, "Invalid action numbers:0x%x for VF %d\n",
1237                        as->count, vf->vf_id);
1238                return -EINVAL;
1239        }
1240
1241        for (i = 0; i < as->count; i++) {
1242                struct virtchnl_filter_action *action = &as->actions[i];
1243
1244                switch (action->type) {
1245                case VIRTCHNL_ACTION_PASSTHRU:
1246                        dest_num++;
1247                        input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER;
1248                        break;
1249                case VIRTCHNL_ACTION_DROP:
1250                        dest_num++;
1251                        input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DROP_PKT;
1252                        break;
1253                case VIRTCHNL_ACTION_QUEUE:
1254                        dest_num++;
1255                        input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX;
1256                        input->q_index = action->act_conf.queue.index;
1257                        break;
1258                case VIRTCHNL_ACTION_Q_REGION:
1259                        dest_num++;
1260                        input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP;
1261                        input->q_index = action->act_conf.queue.index;
1262                        input->q_region = action->act_conf.queue.region;
1263                        break;
1264                case VIRTCHNL_ACTION_MARK:
1265                        mark_num++;
1266                        input->fltr_id = action->act_conf.mark_id;
1267                        input->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_THREE;
1268                        break;
1269                default:
1270                        dev_dbg(dev, "Invalid action type:0x%x for VF %d\n",
1271                                action->type, vf->vf_id);
1272                        return -EINVAL;
1273                }
1274        }
1275
1276        if (dest_num == 0 || dest_num >= 2) {
1277                dev_dbg(dev, "Invalid destination action for VF %d\n",
1278                        vf->vf_id);
1279                return -EINVAL;
1280        }
1281
1282        if (mark_num >= 2) {
1283                dev_dbg(dev, "Too many mark actions for VF %d\n", vf->vf_id);
1284                return -EINVAL;
1285        }
1286
1287        return 0;
1288}
1289
1290/**
1291 * ice_vc_validate_fdir_fltr - validate the virtual channel filter
1292 * @vf: pointer to the VF info
1293 * @fltr: virtual channel add cmd buffer
1294 * @conf: FDIR configuration for each filter
1295 *
1296 * Return: 0 on success, and other on error.
1297 */
1298static int
1299ice_vc_validate_fdir_fltr(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,
1300                          struct virtchnl_fdir_fltr_conf *conf)
1301{
1302        int ret;
1303
1304        ret = ice_vc_fdir_search_pattern(vf, fltr);
1305        if (ret)
1306                return ret;
1307
1308        ret = ice_vc_fdir_parse_pattern(vf, fltr, conf);
1309        if (ret)
1310                return ret;
1311
1312        return ice_vc_fdir_parse_action(vf, fltr, conf);
1313}
1314
1315/**
1316 * ice_vc_fdir_comp_rules - compare if two filter rules have the same value
1317 * @conf_a: FDIR configuration for filter a
1318 * @conf_b: FDIR configuration for filter b
1319 *
1320 * Return: 0 on success, and other on error.
1321 */
1322static bool
1323ice_vc_fdir_comp_rules(struct virtchnl_fdir_fltr_conf *conf_a,
1324                       struct virtchnl_fdir_fltr_conf *conf_b)
1325{
1326        struct ice_fdir_fltr *a = &conf_a->input;
1327        struct ice_fdir_fltr *b = &conf_b->input;
1328
1329        if (conf_a->ttype != conf_b->ttype)
1330                return false;
1331        if (a->flow_type != b->flow_type)
1332                return false;
1333        if (memcmp(&a->ip, &b->ip, sizeof(a->ip)))
1334                return false;
1335        if (memcmp(&a->mask, &b->mask, sizeof(a->mask)))
1336                return false;
1337        if (memcmp(&a->gtpu_data, &b->gtpu_data, sizeof(a->gtpu_data)))
1338                return false;
1339        if (memcmp(&a->gtpu_mask, &b->gtpu_mask, sizeof(a->gtpu_mask)))
1340                return false;
1341        if (memcmp(&a->l2tpv3_data, &b->l2tpv3_data, sizeof(a->l2tpv3_data)))
1342                return false;
1343        if (memcmp(&a->l2tpv3_mask, &b->l2tpv3_mask, sizeof(a->l2tpv3_mask)))
1344                return false;
1345        if (memcmp(&a->ext_data, &b->ext_data, sizeof(a->ext_data)))
1346                return false;
1347        if (memcmp(&a->ext_mask, &b->ext_mask, sizeof(a->ext_mask)))
1348                return false;
1349
1350        return true;
1351}
1352
1353/**
1354 * ice_vc_fdir_is_dup_fltr
1355 * @vf: pointer to the VF info
1356 * @conf: FDIR configuration for each filter
1357 *
1358 * Check if there is duplicated rule with same conf value
1359 *
1360 * Return: 0 true success, and false on error.
1361 */
1362static bool
1363ice_vc_fdir_is_dup_fltr(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf)
1364{
1365        struct ice_fdir_fltr *desc;
1366        bool ret;
1367
1368        list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) {
1369                struct virtchnl_fdir_fltr_conf *node =
1370                                to_fltr_conf_from_desc(desc);
1371
1372                ret = ice_vc_fdir_comp_rules(node, conf);
1373                if (ret)
1374                        return true;
1375        }
1376
1377        return false;
1378}
1379
1380/**
1381 * ice_vc_fdir_insert_entry
1382 * @vf: pointer to the VF info
1383 * @conf: FDIR configuration for each filter
1384 * @id: pointer to ID value allocated by driver
1385 *
1386 * Insert FDIR conf entry into list and allocate ID for this filter
1387 *
1388 * Return: 0 true success, and other on error.
1389 */
1390static int
1391ice_vc_fdir_insert_entry(struct ice_vf *vf,
1392                         struct virtchnl_fdir_fltr_conf *conf, u32 *id)
1393{
1394        struct ice_fdir_fltr *input = &conf->input;
1395        int i;
1396
1397        /* alloc ID corresponding with conf */
1398        i = idr_alloc(&vf->fdir.fdir_rule_idr, conf, 0,
1399                      ICE_FDIR_MAX_FLTRS, GFP_KERNEL);
1400        if (i < 0)
1401                return -EINVAL;
1402        *id = i;
1403
1404        list_add(&input->fltr_node, &vf->fdir.fdir_rule_list);
1405        return 0;
1406}
1407
1408/**
1409 * ice_vc_fdir_remove_entry - remove FDIR conf entry by ID value
1410 * @vf: pointer to the VF info
1411 * @conf: FDIR configuration for each filter
1412 * @id: filter rule's ID
1413 */
1414static void
1415ice_vc_fdir_remove_entry(struct ice_vf *vf,
1416                         struct virtchnl_fdir_fltr_conf *conf, u32 id)
1417{
1418        struct ice_fdir_fltr *input = &conf->input;
1419
1420        idr_remove(&vf->fdir.fdir_rule_idr, id);
1421        list_del(&input->fltr_node);
1422}
1423
1424/**
1425 * ice_vc_fdir_lookup_entry - lookup FDIR conf entry by ID value
1426 * @vf: pointer to the VF info
1427 * @id: filter rule's ID
1428 *
1429 * Return: NULL on error, and other on success.
1430 */
1431static struct virtchnl_fdir_fltr_conf *
1432ice_vc_fdir_lookup_entry(struct ice_vf *vf, u32 id)
1433{
1434        return idr_find(&vf->fdir.fdir_rule_idr, id);
1435}
1436
1437/**
1438 * ice_vc_fdir_flush_entry - remove all FDIR conf entry
1439 * @vf: pointer to the VF info
1440 */
1441static void ice_vc_fdir_flush_entry(struct ice_vf *vf)
1442{
1443        struct virtchnl_fdir_fltr_conf *conf;
1444        struct ice_fdir_fltr *desc, *temp;
1445
1446        list_for_each_entry_safe(desc, temp,
1447                                 &vf->fdir.fdir_rule_list, fltr_node) {
1448                conf = to_fltr_conf_from_desc(desc);
1449                list_del(&desc->fltr_node);
1450                devm_kfree(ice_pf_to_dev(vf->pf), conf);
1451        }
1452}
1453
1454/**
1455 * ice_vc_fdir_write_fltr - write filter rule into hardware
1456 * @vf: pointer to the VF info
1457 * @conf: FDIR configuration for each filter
1458 * @add: true implies add rule, false implies del rules
1459 * @is_tun: false implies non-tunnel type filter, true implies tunnel filter
1460 *
1461 * Return: 0 on success, and other on error.
1462 */
1463static int ice_vc_fdir_write_fltr(struct ice_vf *vf,
1464                                  struct virtchnl_fdir_fltr_conf *conf,
1465                                  bool add, bool is_tun)
1466{
1467        struct ice_fdir_fltr *input = &conf->input;
1468        struct ice_vsi *vsi, *ctrl_vsi;
1469        struct ice_fltr_desc desc;
1470        enum ice_status status;
1471        struct device *dev;
1472        struct ice_pf *pf;
1473        struct ice_hw *hw;
1474        int ret;
1475        u8 *pkt;
1476
1477        pf = vf->pf;
1478        dev = ice_pf_to_dev(pf);
1479        hw = &pf->hw;
1480        vsi = pf->vsi[vf->lan_vsi_idx];
1481        if (!vsi) {
1482                dev_dbg(dev, "Invalid vsi for VF %d\n", vf->vf_id);
1483                return -EINVAL;
1484        }
1485
1486        input->dest_vsi = vsi->idx;
1487        input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;
1488
1489        ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];
1490        if (!ctrl_vsi) {
1491                dev_dbg(dev, "Invalid ctrl_vsi for VF %d\n", vf->vf_id);
1492                return -EINVAL;
1493        }
1494
1495        pkt = devm_kzalloc(dev, ICE_FDIR_MAX_RAW_PKT_SIZE, GFP_KERNEL);
1496        if (!pkt)
1497                return -ENOMEM;
1498
1499        ice_fdir_get_prgm_desc(hw, input, &desc, add);
1500        status = ice_fdir_get_gen_prgm_pkt(hw, input, pkt, false, is_tun);
1501        ret = ice_status_to_errno(status);
1502        if (ret) {
1503                dev_dbg(dev, "Gen training pkt for VF %d ptype %d failed\n",
1504                        vf->vf_id, input->flow_type);
1505                goto err_free_pkt;
1506        }
1507
1508        ret = ice_prgm_fdir_fltr(ctrl_vsi, &desc, pkt);
1509        if (ret)
1510                goto err_free_pkt;
1511
1512        return 0;
1513
1514err_free_pkt:
1515        devm_kfree(dev, pkt);
1516        return ret;
1517}
1518
1519/**
1520 * ice_vf_fdir_timer - FDIR program waiting timer interrupt handler
1521 * @t: pointer to timer_list
1522 */
1523static void ice_vf_fdir_timer(struct timer_list *t)
1524{
1525        struct ice_vf_fdir_ctx *ctx_irq = from_timer(ctx_irq, t, rx_tmr);
1526        struct ice_vf_fdir_ctx *ctx_done;
1527        struct ice_vf_fdir *fdir;
1528        unsigned long flags;
1529        struct ice_vf *vf;
1530        struct ice_pf *pf;
1531
1532        fdir = container_of(ctx_irq, struct ice_vf_fdir, ctx_irq);
1533        vf = container_of(fdir, struct ice_vf, fdir);
1534        ctx_done = &fdir->ctx_done;
1535        pf = vf->pf;
1536        spin_lock_irqsave(&fdir->ctx_lock, flags);
1537        if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) {
1538                spin_unlock_irqrestore(&fdir->ctx_lock, flags);
1539                WARN_ON_ONCE(1);
1540                return;
1541        }
1542
1543        ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID;
1544
1545        ctx_done->flags |= ICE_VF_FDIR_CTX_VALID;
1546        ctx_done->conf = ctx_irq->conf;
1547        ctx_done->stat = ICE_FDIR_CTX_TIMEOUT;
1548        ctx_done->v_opcode = ctx_irq->v_opcode;
1549        spin_unlock_irqrestore(&fdir->ctx_lock, flags);
1550
1551        set_bit(ICE_FD_VF_FLUSH_CTX, pf->state);
1552        ice_service_task_schedule(pf);
1553}
1554
1555/**
1556 * ice_vc_fdir_irq_handler - ctrl_vsi Rx queue interrupt handler
1557 * @ctrl_vsi: pointer to a VF's CTRL VSI
1558 * @rx_desc: pointer to FDIR Rx queue descriptor
1559 */
1560void
1561ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi,
1562                        union ice_32b_rx_flex_desc *rx_desc)
1563{
1564        struct ice_pf *pf = ctrl_vsi->back;
1565        struct ice_vf_fdir_ctx *ctx_done;
1566        struct ice_vf_fdir_ctx *ctx_irq;
1567        struct ice_vf_fdir *fdir;
1568        unsigned long flags;
1569        struct device *dev;
1570        struct ice_vf *vf;
1571        int ret;
1572
1573        vf = &pf->vf[ctrl_vsi->vf_id];
1574
1575        fdir = &vf->fdir;
1576        ctx_done = &fdir->ctx_done;
1577        ctx_irq = &fdir->ctx_irq;
1578        dev = ice_pf_to_dev(pf);
1579        spin_lock_irqsave(&fdir->ctx_lock, flags);
1580        if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) {
1581                spin_unlock_irqrestore(&fdir->ctx_lock, flags);
1582                WARN_ON_ONCE(1);
1583                return;
1584        }
1585
1586        ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID;
1587
1588        ctx_done->flags |= ICE_VF_FDIR_CTX_VALID;
1589        ctx_done->conf = ctx_irq->conf;
1590        ctx_done->stat = ICE_FDIR_CTX_IRQ;
1591        ctx_done->v_opcode = ctx_irq->v_opcode;
1592        memcpy(&ctx_done->rx_desc, rx_desc, sizeof(*rx_desc));
1593        spin_unlock_irqrestore(&fdir->ctx_lock, flags);
1594
1595        ret = del_timer(&ctx_irq->rx_tmr);
1596        if (!ret)
1597                dev_err(dev, "VF %d: Unexpected inactive timer!\n", vf->vf_id);
1598
1599        set_bit(ICE_FD_VF_FLUSH_CTX, pf->state);
1600        ice_service_task_schedule(pf);
1601}
1602
1603/**
1604 * ice_vf_fdir_dump_info - dump FDIR information for diagnosis
1605 * @vf: pointer to the VF info
1606 */
1607static void ice_vf_fdir_dump_info(struct ice_vf *vf)
1608{
1609        struct ice_vsi *vf_vsi;
1610        u32 fd_size, fd_cnt;
1611        struct device *dev;
1612        struct ice_pf *pf;
1613        struct ice_hw *hw;
1614        u16 vsi_num;
1615
1616        pf = vf->pf;
1617        hw = &pf->hw;
1618        dev = ice_pf_to_dev(pf);
1619        vf_vsi = pf->vsi[vf->lan_vsi_idx];
1620        vsi_num = ice_get_hw_vsi_num(hw, vf_vsi->idx);
1621
1622        fd_size = rd32(hw, VSIQF_FD_SIZE(vsi_num));
1623        fd_cnt = rd32(hw, VSIQF_FD_CNT(vsi_num));
1624        dev_dbg(dev, "VF %d: space allocated: guar:0x%x, be:0x%x, space consumed: guar:0x%x, be:0x%x",
1625                vf->vf_id,
1626                (fd_size & VSIQF_FD_CNT_FD_GCNT_M) >> VSIQF_FD_CNT_FD_GCNT_S,
1627                (fd_size & VSIQF_FD_CNT_FD_BCNT_M) >> VSIQF_FD_CNT_FD_BCNT_S,
1628                (fd_cnt & VSIQF_FD_CNT_FD_GCNT_M) >> VSIQF_FD_CNT_FD_GCNT_S,
1629                (fd_cnt & VSIQF_FD_CNT_FD_BCNT_M) >> VSIQF_FD_CNT_FD_BCNT_S);
1630}
1631
1632/**
1633 * ice_vf_verify_rx_desc - verify received FDIR programming status descriptor
1634 * @vf: pointer to the VF info
1635 * @ctx: FDIR context info for post processing
1636 * @status: virtchnl FDIR program status
1637 *
1638 * Return: 0 on success, and other on error.
1639 */
1640static int
1641ice_vf_verify_rx_desc(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,
1642                      enum virtchnl_fdir_prgm_status *status)
1643{
1644        struct device *dev = ice_pf_to_dev(vf->pf);
1645        u32 stat_err, error, prog_id;
1646        int ret;
1647
1648        stat_err = le16_to_cpu(ctx->rx_desc.wb.status_error0);
1649        if (((stat_err & ICE_FXD_FLTR_WB_QW1_DD_M) >>
1650            ICE_FXD_FLTR_WB_QW1_DD_S) != ICE_FXD_FLTR_WB_QW1_DD_YES) {
1651                *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
1652                dev_err(dev, "VF %d: Desc Done not set\n", vf->vf_id);
1653                ret = -EINVAL;
1654                goto err_exit;
1655        }
1656
1657        prog_id = (stat_err & ICE_FXD_FLTR_WB_QW1_PROG_ID_M) >>
1658                ICE_FXD_FLTR_WB_QW1_PROG_ID_S;
1659        if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD &&
1660            ctx->v_opcode != VIRTCHNL_OP_ADD_FDIR_FILTER) {
1661                dev_err(dev, "VF %d: Desc show add, but ctx not",
1662                        vf->vf_id);
1663                *status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;
1664                ret = -EINVAL;
1665                goto err_exit;
1666        }
1667
1668        if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_DEL &&
1669            ctx->v_opcode != VIRTCHNL_OP_DEL_FDIR_FILTER) {
1670                dev_err(dev, "VF %d: Desc show del, but ctx not",
1671                        vf->vf_id);
1672                *status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;
1673                ret = -EINVAL;
1674                goto err_exit;
1675        }
1676
1677        error = (stat_err & ICE_FXD_FLTR_WB_QW1_FAIL_M) >>
1678                ICE_FXD_FLTR_WB_QW1_FAIL_S;
1679        if (error == ICE_FXD_FLTR_WB_QW1_FAIL_YES) {
1680                if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD) {
1681                        dev_err(dev, "VF %d, Failed to add FDIR rule due to no space in the table",
1682                                vf->vf_id);
1683                        *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
1684                } else {
1685                        dev_err(dev, "VF %d, Failed to remove FDIR rule, attempt to remove non-existent entry",
1686                                vf->vf_id);
1687                        *status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST;
1688                }
1689                ret = -EINVAL;
1690                goto err_exit;
1691        }
1692
1693        error = (stat_err & ICE_FXD_FLTR_WB_QW1_FAIL_PROF_M) >>
1694                ICE_FXD_FLTR_WB_QW1_FAIL_PROF_S;
1695        if (error == ICE_FXD_FLTR_WB_QW1_FAIL_PROF_YES) {
1696                dev_err(dev, "VF %d: Profile matching error", vf->vf_id);
1697                *status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
1698                ret = -EINVAL;
1699                goto err_exit;
1700        }
1701
1702        *status = VIRTCHNL_FDIR_SUCCESS;
1703
1704        return 0;
1705
1706err_exit:
1707        ice_vf_fdir_dump_info(vf);
1708        return ret;
1709}
1710
1711/**
1712 * ice_vc_add_fdir_fltr_post
1713 * @vf: pointer to the VF structure
1714 * @ctx: FDIR context info for post processing
1715 * @status: virtchnl FDIR program status
1716 * @success: true implies success, false implies failure
1717 *
1718 * Post process for flow director add command. If success, then do post process
1719 * and send back success msg by virtchnl. Otherwise, do context reversion and
1720 * send back failure msg by virtchnl.
1721 *
1722 * Return: 0 on success, and other on error.
1723 */
1724static int
1725ice_vc_add_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,
1726                          enum virtchnl_fdir_prgm_status status,
1727                          bool success)
1728{
1729        struct virtchnl_fdir_fltr_conf *conf = ctx->conf;
1730        struct device *dev = ice_pf_to_dev(vf->pf);
1731        enum virtchnl_status_code v_ret;
1732        struct virtchnl_fdir_add *resp;
1733        int ret, len, is_tun;
1734
1735        v_ret = VIRTCHNL_STATUS_SUCCESS;
1736        len = sizeof(*resp);
1737        resp = kzalloc(len, GFP_KERNEL);
1738        if (!resp) {
1739                len = 0;
1740                v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
1741                dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id);
1742                goto err_exit;
1743        }
1744
1745        if (!success)
1746                goto err_exit;
1747
1748        is_tun = 0;
1749        resp->status = status;
1750        resp->flow_id = conf->flow_id;
1751        vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]++;
1752
1753        ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,
1754                                    (u8 *)resp, len);
1755        kfree(resp);
1756
1757        dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n",
1758                vf->vf_id, conf->flow_id,
1759                (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ?
1760                "add" : "del");
1761        return ret;
1762
1763err_exit:
1764        if (resp)
1765                resp->status = status;
1766        ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
1767        devm_kfree(dev, conf);
1768
1769        ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,
1770                                    (u8 *)resp, len);
1771        kfree(resp);
1772        return ret;
1773}
1774
1775/**
1776 * ice_vc_del_fdir_fltr_post
1777 * @vf: pointer to the VF structure
1778 * @ctx: FDIR context info for post processing
1779 * @status: virtchnl FDIR program status
1780 * @success: true implies success, false implies failure
1781 *
1782 * Post process for flow director del command. If success, then do post process
1783 * and send back success msg by virtchnl. Otherwise, do context reversion and
1784 * send back failure msg by virtchnl.
1785 *
1786 * Return: 0 on success, and other on error.
1787 */
1788static int
1789ice_vc_del_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,
1790                          enum virtchnl_fdir_prgm_status status,
1791                          bool success)
1792{
1793        struct virtchnl_fdir_fltr_conf *conf = ctx->conf;
1794        struct device *dev = ice_pf_to_dev(vf->pf);
1795        enum virtchnl_status_code v_ret;
1796        struct virtchnl_fdir_del *resp;
1797        int ret, len, is_tun;
1798
1799        v_ret = VIRTCHNL_STATUS_SUCCESS;
1800        len = sizeof(*resp);
1801        resp = kzalloc(len, GFP_KERNEL);
1802        if (!resp) {
1803                len = 0;
1804                v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
1805                dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id);
1806                goto err_exit;
1807        }
1808
1809        if (!success)
1810                goto err_exit;
1811
1812        is_tun = 0;
1813        resp->status = status;
1814        ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
1815        vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]--;
1816
1817        ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,
1818                                    (u8 *)resp, len);
1819        kfree(resp);
1820
1821        dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n",
1822                vf->vf_id, conf->flow_id,
1823                (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ?
1824                "add" : "del");
1825        devm_kfree(dev, conf);
1826        return ret;
1827
1828err_exit:
1829        if (resp)
1830                resp->status = status;
1831        if (success)
1832                devm_kfree(dev, conf);
1833
1834        ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,
1835                                    (u8 *)resp, len);
1836        kfree(resp);
1837        return ret;
1838}
1839
1840/**
1841 * ice_flush_fdir_ctx
1842 * @pf: pointer to the PF structure
1843 *
1844 * Flush all the pending event on ctx_done list and process them.
1845 */
1846void ice_flush_fdir_ctx(struct ice_pf *pf)
1847{
1848        int i;
1849
1850        if (!test_and_clear_bit(ICE_FD_VF_FLUSH_CTX, pf->state))
1851                return;
1852
1853        ice_for_each_vf(pf, i) {
1854                struct device *dev = ice_pf_to_dev(pf);
1855                enum virtchnl_fdir_prgm_status status;
1856                struct ice_vf *vf = &pf->vf[i];
1857                struct ice_vf_fdir_ctx *ctx;
1858                unsigned long flags;
1859                int ret;
1860
1861                if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
1862                        continue;
1863
1864                if (vf->ctrl_vsi_idx == ICE_NO_VSI)
1865                        continue;
1866
1867                ctx = &vf->fdir.ctx_done;
1868                spin_lock_irqsave(&vf->fdir.ctx_lock, flags);
1869                if (!(ctx->flags & ICE_VF_FDIR_CTX_VALID)) {
1870                        spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1871                        continue;
1872                }
1873                spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1874
1875                WARN_ON(ctx->stat == ICE_FDIR_CTX_READY);
1876                if (ctx->stat == ICE_FDIR_CTX_TIMEOUT) {
1877                        status = VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT;
1878                        dev_err(dev, "VF %d: ctrl_vsi irq timeout\n",
1879                                vf->vf_id);
1880                        goto err_exit;
1881                }
1882
1883                ret = ice_vf_verify_rx_desc(vf, ctx, &status);
1884                if (ret)
1885                        goto err_exit;
1886
1887                if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER)
1888                        ice_vc_add_fdir_fltr_post(vf, ctx, status, true);
1889                else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER)
1890                        ice_vc_del_fdir_fltr_post(vf, ctx, status, true);
1891                else
1892                        dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id);
1893
1894                spin_lock_irqsave(&vf->fdir.ctx_lock, flags);
1895                ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;
1896                spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1897                continue;
1898err_exit:
1899                if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER)
1900                        ice_vc_add_fdir_fltr_post(vf, ctx, status, false);
1901                else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER)
1902                        ice_vc_del_fdir_fltr_post(vf, ctx, status, false);
1903                else
1904                        dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id);
1905
1906                spin_lock_irqsave(&vf->fdir.ctx_lock, flags);
1907                ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;
1908                spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1909        }
1910}
1911
1912/**
1913 * ice_vc_fdir_set_irq_ctx - set FDIR context info for later IRQ handler
1914 * @vf: pointer to the VF structure
1915 * @conf: FDIR configuration for each filter
1916 * @v_opcode: virtual channel operation code
1917 *
1918 * Return: 0 on success, and other on error.
1919 */
1920static int
1921ice_vc_fdir_set_irq_ctx(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf,
1922                        enum virtchnl_ops v_opcode)
1923{
1924        struct device *dev = ice_pf_to_dev(vf->pf);
1925        struct ice_vf_fdir_ctx *ctx;
1926        unsigned long flags;
1927
1928        ctx = &vf->fdir.ctx_irq;
1929        spin_lock_irqsave(&vf->fdir.ctx_lock, flags);
1930        if ((vf->fdir.ctx_irq.flags & ICE_VF_FDIR_CTX_VALID) ||
1931            (vf->fdir.ctx_done.flags & ICE_VF_FDIR_CTX_VALID)) {
1932                spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1933                dev_dbg(dev, "VF %d: Last request is still in progress\n",
1934                        vf->vf_id);
1935                return -EBUSY;
1936        }
1937        ctx->flags |= ICE_VF_FDIR_CTX_VALID;
1938        spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1939
1940        ctx->conf = conf;
1941        ctx->v_opcode = v_opcode;
1942        ctx->stat = ICE_FDIR_CTX_READY;
1943        timer_setup(&ctx->rx_tmr, ice_vf_fdir_timer, 0);
1944
1945        mod_timer(&ctx->rx_tmr, round_jiffies(msecs_to_jiffies(10) + jiffies));
1946
1947        return 0;
1948}
1949
1950/**
1951 * ice_vc_fdir_clear_irq_ctx - clear FDIR context info for IRQ handler
1952 * @vf: pointer to the VF structure
1953 *
1954 * Return: 0 on success, and other on error.
1955 */
1956static void ice_vc_fdir_clear_irq_ctx(struct ice_vf *vf)
1957{
1958        struct ice_vf_fdir_ctx *ctx = &vf->fdir.ctx_irq;
1959        unsigned long flags;
1960
1961        del_timer(&ctx->rx_tmr);
1962        spin_lock_irqsave(&vf->fdir.ctx_lock, flags);
1963        ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;
1964        spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);
1965}
1966
1967/**
1968 * ice_vc_add_fdir_fltr - add a FDIR filter for VF by the msg buffer
1969 * @vf: pointer to the VF info
1970 * @msg: pointer to the msg buffer
1971 *
1972 * Return: 0 on success, and other on error.
1973 */
1974int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)
1975{
1976        struct virtchnl_fdir_add *fltr = (struct virtchnl_fdir_add *)msg;
1977        struct virtchnl_fdir_add *stat = NULL;
1978        struct virtchnl_fdir_fltr_conf *conf;
1979        enum virtchnl_status_code v_ret;
1980        struct device *dev;
1981        struct ice_pf *pf;
1982        int is_tun = 0;
1983        int len = 0;
1984        int ret;
1985
1986        pf = vf->pf;
1987        dev = ice_pf_to_dev(pf);
1988        ret = ice_vc_fdir_param_check(vf, fltr->vsi_id);
1989        if (ret) {
1990                v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1991                dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id);
1992                goto err_exit;
1993        }
1994
1995        ret = ice_vf_start_ctrl_vsi(vf);
1996        if (ret && (ret != -EEXIST)) {
1997                v_ret = VIRTCHNL_STATUS_ERR_PARAM;
1998                dev_err(dev, "Init FDIR for VF %d failed, ret:%d\n",
1999                        vf->vf_id, ret);
2000                goto err_exit;
2001        }
2002
2003        stat = kzalloc(sizeof(*stat), GFP_KERNEL);
2004        if (!stat) {
2005                v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2006                dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id);
2007                goto err_exit;
2008        }
2009
2010        conf = devm_kzalloc(dev, sizeof(*conf), GFP_KERNEL);
2011        if (!conf) {
2012                v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2013                dev_dbg(dev, "Alloc conf for VF %d failed\n", vf->vf_id);
2014                goto err_exit;
2015        }
2016
2017        len = sizeof(*stat);
2018        ret = ice_vc_validate_fdir_fltr(vf, fltr, conf);
2019        if (ret) {
2020                v_ret = VIRTCHNL_STATUS_SUCCESS;
2021                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;
2022                dev_dbg(dev, "Invalid FDIR filter from VF %d\n", vf->vf_id);
2023                goto err_free_conf;
2024        }
2025
2026        if (fltr->validate_only) {
2027                v_ret = VIRTCHNL_STATUS_SUCCESS;
2028                stat->status = VIRTCHNL_FDIR_SUCCESS;
2029                devm_kfree(dev, conf);
2030                ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER,
2031                                            v_ret, (u8 *)stat, len);
2032                goto exit;
2033        }
2034
2035        ret = ice_vc_fdir_config_input_set(vf, fltr, conf, is_tun);
2036        if (ret) {
2037                v_ret = VIRTCHNL_STATUS_SUCCESS;
2038                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT;
2039                dev_err(dev, "VF %d: FDIR input set configure failed, ret:%d\n",
2040                        vf->vf_id, ret);
2041                goto err_free_conf;
2042        }
2043
2044        ret = ice_vc_fdir_is_dup_fltr(vf, conf);
2045        if (ret) {
2046                v_ret = VIRTCHNL_STATUS_SUCCESS;
2047                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_EXIST;
2048                dev_dbg(dev, "VF %d: duplicated FDIR rule detected\n",
2049                        vf->vf_id);
2050                goto err_free_conf;
2051        }
2052
2053        ret = ice_vc_fdir_insert_entry(vf, conf, &conf->flow_id);
2054        if (ret) {
2055                v_ret = VIRTCHNL_STATUS_SUCCESS;
2056                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2057                dev_dbg(dev, "VF %d: insert FDIR list failed\n", vf->vf_id);
2058                goto err_free_conf;
2059        }
2060
2061        ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_ADD_FDIR_FILTER);
2062        if (ret) {
2063                v_ret = VIRTCHNL_STATUS_SUCCESS;
2064                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2065                dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
2066                goto err_free_conf;
2067        }
2068
2069        ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);
2070        if (ret) {
2071                v_ret = VIRTCHNL_STATUS_SUCCESS;
2072                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2073                dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
2074                        vf->vf_id, ret);
2075                goto err_rem_entry;
2076        }
2077
2078exit:
2079        kfree(stat);
2080        return ret;
2081
2082err_rem_entry:
2083        ice_vc_fdir_clear_irq_ctx(vf);
2084        ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);
2085err_free_conf:
2086        devm_kfree(dev, conf);
2087err_exit:
2088        ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER, v_ret,
2089                                    (u8 *)stat, len);
2090        kfree(stat);
2091        return ret;
2092}
2093
2094/**
2095 * ice_vc_del_fdir_fltr - delete a FDIR filter for VF by the msg buffer
2096 * @vf: pointer to the VF info
2097 * @msg: pointer to the msg buffer
2098 *
2099 * Return: 0 on success, and other on error.
2100 */
2101int ice_vc_del_fdir_fltr(struct ice_vf *vf, u8 *msg)
2102{
2103        struct virtchnl_fdir_del *fltr = (struct virtchnl_fdir_del *)msg;
2104        struct virtchnl_fdir_del *stat = NULL;
2105        struct virtchnl_fdir_fltr_conf *conf;
2106        enum virtchnl_status_code v_ret;
2107        struct device *dev;
2108        struct ice_pf *pf;
2109        int is_tun = 0;
2110        int len = 0;
2111        int ret;
2112
2113        pf = vf->pf;
2114        dev = ice_pf_to_dev(pf);
2115        ret = ice_vc_fdir_param_check(vf, fltr->vsi_id);
2116        if (ret) {
2117                v_ret = VIRTCHNL_STATUS_ERR_PARAM;
2118                dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id);
2119                goto err_exit;
2120        }
2121
2122        stat = kzalloc(sizeof(*stat), GFP_KERNEL);
2123        if (!stat) {
2124                v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
2125                dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id);
2126                goto err_exit;
2127        }
2128
2129        len = sizeof(*stat);
2130
2131        conf = ice_vc_fdir_lookup_entry(vf, fltr->flow_id);
2132        if (!conf) {
2133                v_ret = VIRTCHNL_STATUS_SUCCESS;
2134                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST;
2135                dev_dbg(dev, "VF %d: FDIR invalid flow_id:0x%X\n",
2136                        vf->vf_id, fltr->flow_id);
2137                goto err_exit;
2138        }
2139
2140        /* Just return failure when ctrl_vsi idx is invalid */
2141        if (vf->ctrl_vsi_idx == ICE_NO_VSI) {
2142                v_ret = VIRTCHNL_STATUS_SUCCESS;
2143                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2144                dev_err(dev, "Invalid FDIR ctrl_vsi for VF %d\n", vf->vf_id);
2145                goto err_exit;
2146        }
2147
2148        ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_DEL_FDIR_FILTER);
2149        if (ret) {
2150                v_ret = VIRTCHNL_STATUS_SUCCESS;
2151                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2152                dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);
2153                goto err_exit;
2154        }
2155
2156        ret = ice_vc_fdir_write_fltr(vf, conf, false, is_tun);
2157        if (ret) {
2158                v_ret = VIRTCHNL_STATUS_SUCCESS;
2159                stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;
2160                dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",
2161                        vf->vf_id, ret);
2162                goto err_del_tmr;
2163        }
2164
2165        kfree(stat);
2166
2167        return ret;
2168
2169err_del_tmr:
2170        ice_vc_fdir_clear_irq_ctx(vf);
2171err_exit:
2172        ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_FDIR_FILTER, v_ret,
2173                                    (u8 *)stat, len);
2174        kfree(stat);
2175        return ret;
2176}
2177
2178/**
2179 * ice_vf_fdir_init - init FDIR resource for VF
2180 * @vf: pointer to the VF info
2181 */
2182void ice_vf_fdir_init(struct ice_vf *vf)
2183{
2184        struct ice_vf_fdir *fdir = &vf->fdir;
2185
2186        idr_init(&fdir->fdir_rule_idr);
2187        INIT_LIST_HEAD(&fdir->fdir_rule_list);
2188
2189        spin_lock_init(&fdir->ctx_lock);
2190        fdir->ctx_irq.flags = 0;
2191        fdir->ctx_done.flags = 0;
2192}
2193
2194/**
2195 * ice_vf_fdir_exit - destroy FDIR resource for VF
2196 * @vf: pointer to the VF info
2197 */
2198void ice_vf_fdir_exit(struct ice_vf *vf)
2199{
2200        ice_vc_fdir_flush_entry(vf);
2201        idr_destroy(&vf->fdir.fdir_rule_idr);
2202        ice_vc_fdir_rem_prof_all(vf);
2203        ice_vc_fdir_free_prof_all(vf);
2204}
2205