cachepc-linux

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

ice_virtchnl_fdir.c (53675B)


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