brintos

brintos / linux-shallow public Read only

0
0
Text · 65.0 KiB · 14e3f0f Raw
2423 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2021-2023, 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 GTPU_TEID_OFFSET 414#define GTPU_EH_QFI_OFFSET 115#define GTPU_EH_QFI_MASK 0x3F16#define PFCP_S_OFFSET 017#define PFCP_S_MASK 0x118#define PFCP_PORT_NR 880519 20#define FDIR_INSET_FLAG_ESP_S 021#define FDIR_INSET_FLAG_ESP_M BIT_ULL(FDIR_INSET_FLAG_ESP_S)22#define FDIR_INSET_FLAG_ESP_UDP BIT_ULL(FDIR_INSET_FLAG_ESP_S)23#define FDIR_INSET_FLAG_ESP_IPSEC (0ULL << FDIR_INSET_FLAG_ESP_S)24 25enum ice_fdir_tunnel_type {26	ICE_FDIR_TUNNEL_TYPE_NONE = 0,27	ICE_FDIR_TUNNEL_TYPE_GTPU,28	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,29	ICE_FDIR_TUNNEL_TYPE_ECPRI,30	ICE_FDIR_TUNNEL_TYPE_GTPU_INNER,31	ICE_FDIR_TUNNEL_TYPE_GTPU_EH_INNER,32	ICE_FDIR_TUNNEL_TYPE_GRE,33	ICE_FDIR_TUNNEL_TYPE_GTPOGRE,34	ICE_FDIR_TUNNEL_TYPE_GTPOGRE_INNER,35	ICE_FDIR_TUNNEL_TYPE_GRE_INNER,36	ICE_FDIR_TUNNEL_TYPE_L2TPV2,37	ICE_FDIR_TUNNEL_TYPE_L2TPV2_INNER,38};39 40struct virtchnl_fdir_fltr_conf {41	struct ice_fdir_fltr input;42	enum ice_fdir_tunnel_type ttype;43	u64 inset_flag;44	u32 flow_id;45 46	struct ice_parser_profile *prof;47	bool parser_ena;48	u8 *pkt_buf;49	u8 pkt_len;50};51 52struct virtchnl_fdir_inset_map {53	enum virtchnl_proto_hdr_field field;54	enum ice_flow_field fld;55	u64 flag;56	u64 mask;57};58 59static const struct virtchnl_fdir_inset_map fdir_inset_map[] = {60	{VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE, ICE_FLOW_FIELD_IDX_ETH_TYPE, 0, 0},61	{VIRTCHNL_PROTO_HDR_IPV4_SRC, ICE_FLOW_FIELD_IDX_IPV4_SA, 0, 0},62	{VIRTCHNL_PROTO_HDR_IPV4_DST, ICE_FLOW_FIELD_IDX_IPV4_DA, 0, 0},63	{VIRTCHNL_PROTO_HDR_IPV4_DSCP, ICE_FLOW_FIELD_IDX_IPV4_DSCP, 0, 0},64	{VIRTCHNL_PROTO_HDR_IPV4_TTL, ICE_FLOW_FIELD_IDX_IPV4_TTL, 0, 0},65	{VIRTCHNL_PROTO_HDR_IPV4_PROT, ICE_FLOW_FIELD_IDX_IPV4_PROT, 0, 0},66	{VIRTCHNL_PROTO_HDR_IPV6_SRC, ICE_FLOW_FIELD_IDX_IPV6_SA, 0, 0},67	{VIRTCHNL_PROTO_HDR_IPV6_DST, ICE_FLOW_FIELD_IDX_IPV6_DA, 0, 0},68	{VIRTCHNL_PROTO_HDR_IPV6_TC, ICE_FLOW_FIELD_IDX_IPV6_DSCP, 0, 0},69	{VIRTCHNL_PROTO_HDR_IPV6_HOP_LIMIT, ICE_FLOW_FIELD_IDX_IPV6_TTL, 0, 0},70	{VIRTCHNL_PROTO_HDR_IPV6_PROT, ICE_FLOW_FIELD_IDX_IPV6_PROT, 0, 0},71	{VIRTCHNL_PROTO_HDR_UDP_SRC_PORT, ICE_FLOW_FIELD_IDX_UDP_SRC_PORT, 0, 0},72	{VIRTCHNL_PROTO_HDR_UDP_DST_PORT, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0},73	{VIRTCHNL_PROTO_HDR_TCP_SRC_PORT, ICE_FLOW_FIELD_IDX_TCP_SRC_PORT, 0, 0},74	{VIRTCHNL_PROTO_HDR_TCP_DST_PORT, ICE_FLOW_FIELD_IDX_TCP_DST_PORT, 0, 0},75	{VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT, ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT, 0, 0},76	{VIRTCHNL_PROTO_HDR_SCTP_DST_PORT, ICE_FLOW_FIELD_IDX_SCTP_DST_PORT, 0, 0},77	{VIRTCHNL_PROTO_HDR_GTPU_IP_TEID, ICE_FLOW_FIELD_IDX_GTPU_IP_TEID, 0, 0},78	{VIRTCHNL_PROTO_HDR_GTPU_EH_QFI, ICE_FLOW_FIELD_IDX_GTPU_EH_QFI, 0, 0},79	{VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_ESP_SPI,80		FDIR_INSET_FLAG_ESP_IPSEC, FDIR_INSET_FLAG_ESP_M},81	{VIRTCHNL_PROTO_HDR_ESP_SPI, ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI,82		FDIR_INSET_FLAG_ESP_UDP, FDIR_INSET_FLAG_ESP_M},83	{VIRTCHNL_PROTO_HDR_AH_SPI, ICE_FLOW_FIELD_IDX_AH_SPI, 0, 0},84	{VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID, ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID, 0, 0},85	{VIRTCHNL_PROTO_HDR_PFCP_S_FIELD, ICE_FLOW_FIELD_IDX_UDP_DST_PORT, 0, 0},86};87 88/**89 * ice_vc_fdir_param_check90 * @vf: pointer to the VF structure91 * @vsi_id: VF relative VSI ID92 *93 * Check for the valid VSI ID, PF's state and VF's state94 *95 * Return: 0 on success, and -EINVAL on error.96 */97static int98ice_vc_fdir_param_check(struct ice_vf *vf, u16 vsi_id)99{100	struct ice_pf *pf = vf->pf;101 102	if (!test_bit(ICE_FLAG_FD_ENA, pf->flags))103		return -EINVAL;104 105	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))106		return -EINVAL;107 108	if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF))109		return -EINVAL;110 111	if (!ice_vc_isvalid_vsi_id(vf, vsi_id))112		return -EINVAL;113 114	if (!ice_get_vf_vsi(vf))115		return -EINVAL;116 117	return 0;118}119 120/**121 * ice_vf_start_ctrl_vsi122 * @vf: pointer to the VF structure123 *124 * Allocate ctrl_vsi for the first time and open the ctrl_vsi port for VF125 *126 * Return: 0 on success, and other on error.127 */128static int ice_vf_start_ctrl_vsi(struct ice_vf *vf)129{130	struct ice_pf *pf = vf->pf;131	struct ice_vsi *ctrl_vsi;132	struct device *dev;133	int err;134 135	dev = ice_pf_to_dev(pf);136	if (vf->ctrl_vsi_idx != ICE_NO_VSI)137		return -EEXIST;138 139	ctrl_vsi = ice_vf_ctrl_vsi_setup(vf);140	if (!ctrl_vsi) {141		dev_dbg(dev, "Could not setup control VSI for VF %d\n",142			vf->vf_id);143		return -ENOMEM;144	}145 146	err = ice_vsi_open_ctrl(ctrl_vsi);147	if (err) {148		dev_dbg(dev, "Could not open control VSI for VF %d\n",149			vf->vf_id);150		goto err_vsi_open;151	}152 153	return 0;154 155err_vsi_open:156	ice_vsi_release(ctrl_vsi);157	if (vf->ctrl_vsi_idx != ICE_NO_VSI) {158		pf->vsi[vf->ctrl_vsi_idx] = NULL;159		vf->ctrl_vsi_idx = ICE_NO_VSI;160	}161	return err;162}163 164/**165 * ice_vc_fdir_alloc_prof - allocate profile for this filter flow type166 * @vf: pointer to the VF structure167 * @flow: filter flow type168 *169 * Return: 0 on success, and other on error.170 */171static int172ice_vc_fdir_alloc_prof(struct ice_vf *vf, enum ice_fltr_ptype flow)173{174	struct ice_vf_fdir *fdir = &vf->fdir;175 176	if (!fdir->fdir_prof) {177		fdir->fdir_prof = devm_kcalloc(ice_pf_to_dev(vf->pf),178					       ICE_FLTR_PTYPE_MAX,179					       sizeof(*fdir->fdir_prof),180					       GFP_KERNEL);181		if (!fdir->fdir_prof)182			return -ENOMEM;183	}184 185	if (!fdir->fdir_prof[flow]) {186		fdir->fdir_prof[flow] = devm_kzalloc(ice_pf_to_dev(vf->pf),187						     sizeof(**fdir->fdir_prof),188						     GFP_KERNEL);189		if (!fdir->fdir_prof[flow])190			return -ENOMEM;191	}192 193	return 0;194}195 196/**197 * ice_vc_fdir_free_prof - free profile for this filter flow type198 * @vf: pointer to the VF structure199 * @flow: filter flow type200 */201static void202ice_vc_fdir_free_prof(struct ice_vf *vf, enum ice_fltr_ptype flow)203{204	struct ice_vf_fdir *fdir = &vf->fdir;205 206	if (!fdir->fdir_prof)207		return;208 209	if (!fdir->fdir_prof[flow])210		return;211 212	devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof[flow]);213	fdir->fdir_prof[flow] = NULL;214}215 216/**217 * ice_vc_fdir_free_prof_all - free all the profile for this VF218 * @vf: pointer to the VF structure219 */220static void ice_vc_fdir_free_prof_all(struct ice_vf *vf)221{222	struct ice_vf_fdir *fdir = &vf->fdir;223	enum ice_fltr_ptype flow;224 225	if (!fdir->fdir_prof)226		return;227 228	for (flow = ICE_FLTR_PTYPE_NONF_NONE; flow < ICE_FLTR_PTYPE_MAX; flow++)229		ice_vc_fdir_free_prof(vf, flow);230 231	devm_kfree(ice_pf_to_dev(vf->pf), fdir->fdir_prof);232	fdir->fdir_prof = NULL;233}234 235/**236 * ice_vc_fdir_parse_flow_fld237 * @proto_hdr: virtual channel protocol filter header238 * @conf: FDIR configuration for each filter239 * @fld: field type array240 * @fld_cnt: field counter241 *242 * Parse the virtual channel filter header and store them into field type array243 *244 * Return: 0 on success, and other on error.245 */246static int247ice_vc_fdir_parse_flow_fld(struct virtchnl_proto_hdr *proto_hdr,248			   struct virtchnl_fdir_fltr_conf *conf,249			   enum ice_flow_field *fld, int *fld_cnt)250{251	struct virtchnl_proto_hdr hdr;252	u32 i;253 254	memcpy(&hdr, proto_hdr, sizeof(hdr));255 256	for (i = 0; (i < ARRAY_SIZE(fdir_inset_map)) &&257	     VIRTCHNL_GET_PROTO_HDR_FIELD(&hdr); i++)258		if (VIRTCHNL_TEST_PROTO_HDR(&hdr, fdir_inset_map[i].field)) {259			if (fdir_inset_map[i].mask &&260			    ((fdir_inset_map[i].mask & conf->inset_flag) !=261			     fdir_inset_map[i].flag))262				continue;263 264			fld[*fld_cnt] = fdir_inset_map[i].fld;265			*fld_cnt += 1;266			if (*fld_cnt >= ICE_FLOW_FIELD_IDX_MAX)267				return -EINVAL;268			VIRTCHNL_DEL_PROTO_HDR_FIELD(&hdr,269						     fdir_inset_map[i].field);270		}271 272	return 0;273}274 275/**276 * ice_vc_fdir_set_flow_fld277 * @vf: pointer to the VF structure278 * @fltr: virtual channel add cmd buffer279 * @conf: FDIR configuration for each filter280 * @seg: array of one or more packet segments that describe the flow281 *282 * Parse the virtual channel add msg buffer's field vector and store them into283 * flow's packet segment field284 *285 * Return: 0 on success, and other on error.286 */287static int288ice_vc_fdir_set_flow_fld(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,289			 struct virtchnl_fdir_fltr_conf *conf,290			 struct ice_flow_seg_info *seg)291{292	struct virtchnl_fdir_rule *rule = &fltr->rule_cfg;293	enum ice_flow_field fld[ICE_FLOW_FIELD_IDX_MAX];294	struct device *dev = ice_pf_to_dev(vf->pf);295	struct virtchnl_proto_hdrs *proto;296	int fld_cnt = 0;297	int i;298 299	proto = &rule->proto_hdrs;300	for (i = 0; i < proto->count; i++) {301		struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i];302		int ret;303 304		ret = ice_vc_fdir_parse_flow_fld(hdr, conf, fld, &fld_cnt);305		if (ret)306			return ret;307	}308 309	if (fld_cnt == 0) {310		dev_dbg(dev, "Empty input set for VF %d\n", vf->vf_id);311		return -EINVAL;312	}313 314	for (i = 0; i < fld_cnt; i++)315		ice_flow_set_fld(seg, fld[i],316				 ICE_FLOW_FLD_OFF_INVAL,317				 ICE_FLOW_FLD_OFF_INVAL,318				 ICE_FLOW_FLD_OFF_INVAL, false);319 320	return 0;321}322 323/**324 * ice_vc_fdir_set_flow_hdr - config the flow's packet segment header325 * @vf: pointer to the VF structure326 * @conf: FDIR configuration for each filter327 * @seg: array of one or more packet segments that describe the flow328 *329 * Return: 0 on success, and other on error.330 */331static int332ice_vc_fdir_set_flow_hdr(struct ice_vf *vf,333			 struct virtchnl_fdir_fltr_conf *conf,334			 struct ice_flow_seg_info *seg)335{336	enum ice_fltr_ptype flow = conf->input.flow_type;337	enum ice_fdir_tunnel_type ttype = conf->ttype;338	struct device *dev = ice_pf_to_dev(vf->pf);339 340	switch (flow) {341	case ICE_FLTR_PTYPE_NON_IP_L2:342		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ETH_NON_IP);343		break;344	case ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3:345		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 |346				  ICE_FLOW_SEG_HDR_IPV4 |347				  ICE_FLOW_SEG_HDR_IPV_OTHER);348		break;349	case ICE_FLTR_PTYPE_NONF_IPV4_ESP:350		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP |351				  ICE_FLOW_SEG_HDR_IPV4 |352				  ICE_FLOW_SEG_HDR_IPV_OTHER);353		break;354	case ICE_FLTR_PTYPE_NONF_IPV4_AH:355		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH |356				  ICE_FLOW_SEG_HDR_IPV4 |357				  ICE_FLOW_SEG_HDR_IPV_OTHER);358		break;359	case ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP:360		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP |361				  ICE_FLOW_SEG_HDR_IPV4 |362				  ICE_FLOW_SEG_HDR_IPV_OTHER);363		break;364	case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE:365		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE |366				  ICE_FLOW_SEG_HDR_IPV4 |367				  ICE_FLOW_SEG_HDR_IPV_OTHER);368		break;369	case ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION:370		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION |371				  ICE_FLOW_SEG_HDR_IPV4 |372				  ICE_FLOW_SEG_HDR_IPV_OTHER);373		break;374	case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:375		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV4 |376				  ICE_FLOW_SEG_HDR_IPV_OTHER);377		break;378	case ICE_FLTR_PTYPE_NONF_IPV4_TCP:379		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |380				  ICE_FLOW_SEG_HDR_IPV4 |381				  ICE_FLOW_SEG_HDR_IPV_OTHER);382		break;383	case ICE_FLTR_PTYPE_NONF_IPV4_UDP:384		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |385				  ICE_FLOW_SEG_HDR_IPV4 |386				  ICE_FLOW_SEG_HDR_IPV_OTHER);387		break;388	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_UDP:389	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:390	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:391	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:392		if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU) {393			ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_IP |394					  ICE_FLOW_SEG_HDR_IPV4 |395					  ICE_FLOW_SEG_HDR_IPV_OTHER);396		} else if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH) {397			ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_EH |398					  ICE_FLOW_SEG_HDR_GTPU_IP |399					  ICE_FLOW_SEG_HDR_IPV4 |400					  ICE_FLOW_SEG_HDR_IPV_OTHER);401		} else {402			dev_dbg(dev, "Invalid tunnel type 0x%x for VF %d\n",403				flow, vf->vf_id);404			return -EINVAL;405		}406		break;407	case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:408		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP |409				  ICE_FLOW_SEG_HDR_IPV4 |410				  ICE_FLOW_SEG_HDR_IPV_OTHER);411		break;412	case ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3:413		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_L2TPV3 |414				  ICE_FLOW_SEG_HDR_IPV6 |415				  ICE_FLOW_SEG_HDR_IPV_OTHER);416		break;417	case ICE_FLTR_PTYPE_NONF_IPV6_ESP:418		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_ESP |419				  ICE_FLOW_SEG_HDR_IPV6 |420				  ICE_FLOW_SEG_HDR_IPV_OTHER);421		break;422	case ICE_FLTR_PTYPE_NONF_IPV6_AH:423		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_AH |424				  ICE_FLOW_SEG_HDR_IPV6 |425				  ICE_FLOW_SEG_HDR_IPV_OTHER);426		break;427	case ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP:428		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_NAT_T_ESP |429				  ICE_FLOW_SEG_HDR_IPV6 |430				  ICE_FLOW_SEG_HDR_IPV_OTHER);431		break;432	case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE:433		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_NODE |434				  ICE_FLOW_SEG_HDR_IPV6 |435				  ICE_FLOW_SEG_HDR_IPV_OTHER);436		break;437	case ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION:438		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_PFCP_SESSION |439				  ICE_FLOW_SEG_HDR_IPV6 |440				  ICE_FLOW_SEG_HDR_IPV_OTHER);441		break;442	case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:443		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_IPV6 |444				  ICE_FLOW_SEG_HDR_IPV_OTHER);445		break;446	case ICE_FLTR_PTYPE_NONF_IPV6_TCP:447		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_TCP |448				  ICE_FLOW_SEG_HDR_IPV6 |449				  ICE_FLOW_SEG_HDR_IPV_OTHER);450		break;451	case ICE_FLTR_PTYPE_NONF_IPV6_UDP:452		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_UDP |453				  ICE_FLOW_SEG_HDR_IPV6 |454				  ICE_FLOW_SEG_HDR_IPV_OTHER);455		break;456	case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:457		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_SCTP |458				  ICE_FLOW_SEG_HDR_IPV6 |459				  ICE_FLOW_SEG_HDR_IPV_OTHER);460		break;461	default:462		dev_dbg(dev, "Invalid flow type 0x%x for VF %d failed\n",463			flow, vf->vf_id);464		return -EINVAL;465	}466 467	return 0;468}469 470/**471 * ice_vc_fdir_rem_prof - remove profile for this filter flow type472 * @vf: pointer to the VF structure473 * @flow: filter flow type474 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter475 */476static void477ice_vc_fdir_rem_prof(struct ice_vf *vf, enum ice_fltr_ptype flow, int tun)478{479	struct ice_vf_fdir *fdir = &vf->fdir;480	struct ice_fd_hw_prof *vf_prof;481	struct ice_pf *pf = vf->pf;482	struct ice_vsi *vf_vsi;483	struct device *dev;484	struct ice_hw *hw;485	u64 prof_id;486	int i;487 488	dev = ice_pf_to_dev(pf);489	hw = &pf->hw;490	if (!fdir->fdir_prof || !fdir->fdir_prof[flow])491		return;492 493	vf_prof = fdir->fdir_prof[flow];494	prof_id = vf_prof->prof_id[tun];495 496	vf_vsi = ice_get_vf_vsi(vf);497	if (!vf_vsi) {498		dev_dbg(dev, "NULL vf %d vsi pointer\n", vf->vf_id);499		return;500	}501 502	if (!fdir->prof_entry_cnt[flow][tun])503		return;504 505	for (i = 0; i < fdir->prof_entry_cnt[flow][tun]; i++)506		if (vf_prof->entry_h[i][tun]) {507			u16 vsi_num = ice_get_hw_vsi_num(hw, vf_prof->vsi_h[i]);508 509			ice_rem_prof_id_flow(hw, ICE_BLK_FD, vsi_num, prof_id);510			ice_flow_rem_entry(hw, ICE_BLK_FD,511					   vf_prof->entry_h[i][tun]);512			vf_prof->entry_h[i][tun] = 0;513		}514 515	ice_flow_rem_prof(hw, ICE_BLK_FD, prof_id);516	devm_kfree(dev, vf_prof->fdir_seg[tun]);517	vf_prof->fdir_seg[tun] = NULL;518 519	for (i = 0; i < vf_prof->cnt; i++)520		vf_prof->vsi_h[i] = 0;521 522	fdir->prof_entry_cnt[flow][tun] = 0;523}524 525/**526 * ice_vc_fdir_rem_prof_all - remove profile for this VF527 * @vf: pointer to the VF structure528 */529static void ice_vc_fdir_rem_prof_all(struct ice_vf *vf)530{531	enum ice_fltr_ptype flow;532 533	for (flow = ICE_FLTR_PTYPE_NONF_NONE;534	     flow < ICE_FLTR_PTYPE_MAX; flow++) {535		ice_vc_fdir_rem_prof(vf, flow, 0);536		ice_vc_fdir_rem_prof(vf, flow, 1);537	}538}539 540/**541 * ice_vc_fdir_reset_cnt_all - reset all FDIR counters for this VF FDIR542 * @fdir: pointer to the VF FDIR structure543 */544static void ice_vc_fdir_reset_cnt_all(struct ice_vf_fdir *fdir)545{546	enum ice_fltr_ptype flow;547 548	for (flow = ICE_FLTR_PTYPE_NONF_NONE;549	     flow < ICE_FLTR_PTYPE_MAX; flow++) {550		fdir->fdir_fltr_cnt[flow][0] = 0;551		fdir->fdir_fltr_cnt[flow][1] = 0;552	}553 554	fdir->fdir_fltr_cnt_total = 0;555}556 557/**558 * ice_vc_fdir_has_prof_conflict559 * @vf: pointer to the VF structure560 * @conf: FDIR configuration for each filter561 *562 * Check if @conf has conflicting profile with existing profiles563 *564 * Return: true on success, and false on error.565 */566static bool567ice_vc_fdir_has_prof_conflict(struct ice_vf *vf,568			      struct virtchnl_fdir_fltr_conf *conf)569{570	struct ice_fdir_fltr *desc;571 572	list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) {573		struct virtchnl_fdir_fltr_conf *existing_conf;574		enum ice_fltr_ptype flow_type_a, flow_type_b;575		struct ice_fdir_fltr *a, *b;576 577		existing_conf = to_fltr_conf_from_desc(desc);578		a = &existing_conf->input;579		b = &conf->input;580		flow_type_a = a->flow_type;581		flow_type_b = b->flow_type;582 583		/* No need to compare two rules with different tunnel types or584		 * with the same protocol type.585		 */586		if (existing_conf->ttype != conf->ttype ||587		    flow_type_a == flow_type_b)588			continue;589 590		switch (flow_type_a) {591		case ICE_FLTR_PTYPE_NONF_IPV4_UDP:592		case ICE_FLTR_PTYPE_NONF_IPV4_TCP:593		case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:594			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)595				return true;596			break;597		case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:598			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||599			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||600			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV4_SCTP)601				return true;602			break;603		case ICE_FLTR_PTYPE_NONF_IPV6_UDP:604		case ICE_FLTR_PTYPE_NONF_IPV6_TCP:605		case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:606			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_OTHER)607				return true;608			break;609		case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:610			if (flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||611			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||612			    flow_type_b == ICE_FLTR_PTYPE_NONF_IPV6_SCTP)613				return true;614			break;615		default:616			break;617		}618	}619 620	return false;621}622 623/**624 * ice_vc_fdir_write_flow_prof625 * @vf: pointer to the VF structure626 * @flow: filter flow type627 * @seg: array of one or more packet segments that describe the flow628 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter629 *630 * Write the flow's profile config and packet segment into the hardware631 *632 * Return: 0 on success, and other on error.633 */634static int635ice_vc_fdir_write_flow_prof(struct ice_vf *vf, enum ice_fltr_ptype flow,636			    struct ice_flow_seg_info *seg, int tun)637{638	struct ice_vf_fdir *fdir = &vf->fdir;639	struct ice_vsi *vf_vsi, *ctrl_vsi;640	struct ice_flow_seg_info *old_seg;641	struct ice_flow_prof *prof = NULL;642	struct ice_fd_hw_prof *vf_prof;643	struct device *dev;644	struct ice_pf *pf;645	struct ice_hw *hw;646	u64 entry1_h = 0;647	u64 entry2_h = 0;648	int ret;649 650	pf = vf->pf;651	dev = ice_pf_to_dev(pf);652	hw = &pf->hw;653	vf_vsi = ice_get_vf_vsi(vf);654	if (!vf_vsi)655		return -EINVAL;656 657	ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];658	if (!ctrl_vsi)659		return -EINVAL;660 661	vf_prof = fdir->fdir_prof[flow];662	old_seg = vf_prof->fdir_seg[tun];663	if (old_seg) {664		if (!memcmp(old_seg, seg, sizeof(*seg))) {665			dev_dbg(dev, "Duplicated profile for VF %d!\n",666				vf->vf_id);667			return -EEXIST;668		}669 670		if (fdir->fdir_fltr_cnt[flow][tun]) {671			ret = -EINVAL;672			dev_dbg(dev, "Input set conflicts for VF %d\n",673				vf->vf_id);674			goto err_exit;675		}676 677		/* remove previously allocated profile */678		ice_vc_fdir_rem_prof(vf, flow, tun);679	}680 681	ret = ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, seg,682				tun + 1, false, &prof);683	if (ret) {684		dev_dbg(dev, "Could not add VSI flow 0x%x for VF %d\n",685			flow, vf->vf_id);686		goto err_exit;687	}688 689	ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx,690				 vf_vsi->idx, ICE_FLOW_PRIO_NORMAL,691				 seg, &entry1_h);692	if (ret) {693		dev_dbg(dev, "Could not add flow 0x%x VSI entry for VF %d\n",694			flow, vf->vf_id);695		goto err_prof;696	}697 698	ret = ice_flow_add_entry(hw, ICE_BLK_FD, prof->id, vf_vsi->idx,699				 ctrl_vsi->idx, ICE_FLOW_PRIO_NORMAL,700				 seg, &entry2_h);701	if (ret) {702		dev_dbg(dev,703			"Could not add flow 0x%x Ctrl VSI entry for VF %d\n",704			flow, vf->vf_id);705		goto err_entry_1;706	}707 708	vf_prof->fdir_seg[tun] = seg;709	vf_prof->cnt = 0;710	fdir->prof_entry_cnt[flow][tun] = 0;711 712	vf_prof->entry_h[vf_prof->cnt][tun] = entry1_h;713	vf_prof->vsi_h[vf_prof->cnt] = vf_vsi->idx;714	vf_prof->cnt++;715	fdir->prof_entry_cnt[flow][tun]++;716 717	vf_prof->entry_h[vf_prof->cnt][tun] = entry2_h;718	vf_prof->vsi_h[vf_prof->cnt] = ctrl_vsi->idx;719	vf_prof->cnt++;720	fdir->prof_entry_cnt[flow][tun]++;721 722	vf_prof->prof_id[tun] = prof->id;723 724	return 0;725 726err_entry_1:727	ice_rem_prof_id_flow(hw, ICE_BLK_FD,728			     ice_get_hw_vsi_num(hw, vf_vsi->idx), prof->id);729	ice_flow_rem_entry(hw, ICE_BLK_FD, entry1_h);730err_prof:731	ice_flow_rem_prof(hw, ICE_BLK_FD, prof->id);732err_exit:733	return ret;734}735 736/**737 * ice_vc_fdir_config_input_set738 * @vf: pointer to the VF structure739 * @fltr: virtual channel add cmd buffer740 * @conf: FDIR configuration for each filter741 * @tun: 0 implies non-tunnel type filter, 1 implies tunnel type filter742 *743 * Config the input set type and value for virtual channel add msg buffer744 *745 * Return: 0 on success, and other on error.746 */747static int748ice_vc_fdir_config_input_set(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,749			     struct virtchnl_fdir_fltr_conf *conf, int tun)750{751	struct ice_fdir_fltr *input = &conf->input;752	struct device *dev = ice_pf_to_dev(vf->pf);753	struct ice_flow_seg_info *seg;754	enum ice_fltr_ptype flow;755	int ret;756 757	ret = ice_vc_fdir_has_prof_conflict(vf, conf);758	if (ret) {759		dev_dbg(dev, "Found flow profile conflict for VF %d\n",760			vf->vf_id);761		return ret;762	}763 764	flow = input->flow_type;765	ret = ice_vc_fdir_alloc_prof(vf, flow);766	if (ret) {767		dev_dbg(dev, "Alloc flow prof for VF %d failed\n", vf->vf_id);768		return ret;769	}770 771	seg = devm_kzalloc(dev, sizeof(*seg), GFP_KERNEL);772	if (!seg)773		return -ENOMEM;774 775	ret = ice_vc_fdir_set_flow_fld(vf, fltr, conf, seg);776	if (ret) {777		dev_dbg(dev, "Set flow field for VF %d failed\n", vf->vf_id);778		goto err_exit;779	}780 781	ret = ice_vc_fdir_set_flow_hdr(vf, conf, seg);782	if (ret) {783		dev_dbg(dev, "Set flow hdr for VF %d failed\n", vf->vf_id);784		goto err_exit;785	}786 787	ret = ice_vc_fdir_write_flow_prof(vf, flow, seg, tun);788	if (ret == -EEXIST) {789		devm_kfree(dev, seg);790	} else if (ret) {791		dev_dbg(dev, "Write flow profile for VF %d failed\n",792			vf->vf_id);793		goto err_exit;794	}795 796	return 0;797 798err_exit:799	devm_kfree(dev, seg);800	return ret;801}802 803/**804 * ice_vc_fdir_is_raw_flow - check if FDIR flow is raw (binary)805 * @proto: virtchnl protocol headers806 *807 * Check if the FDIR rule is raw flow (protocol agnostic flow) or not. Note808 * that common FDIR rule must have non-zero proto->count. Thus, we choose the809 * tunnel_level and count of proto as the indicators. If both tunnel_level and810 * count of proto are zero, this FDIR rule will be regarded as raw flow.811 *812 * Returns: true if headers describe raw flow, false otherwise.813 */814static bool815ice_vc_fdir_is_raw_flow(struct virtchnl_proto_hdrs *proto)816{817	return (proto->tunnel_level == 0 && proto->count == 0);818}819 820/**821 * ice_vc_fdir_parse_raw - parse a virtchnl raw FDIR rule822 * @vf: pointer to the VF info823 * @proto: virtchnl protocol headers824 * @conf: FDIR configuration for each filter825 *826 * Parse the virtual channel filter's raw flow and store it in @conf827 *828 * Return: 0 on success or negative errno on failure.829 */830static int831ice_vc_fdir_parse_raw(struct ice_vf *vf,832		      struct virtchnl_proto_hdrs *proto,833		      struct virtchnl_fdir_fltr_conf *conf)834{835	u8 *pkt_buf, *msk_buf __free(kfree);836	struct ice_parser_result rslt;837	struct ice_pf *pf = vf->pf;838	struct ice_parser *psr;839	int status = -ENOMEM;840	struct ice_hw *hw;841	u16 udp_port = 0;842 843	pkt_buf = kzalloc(proto->raw.pkt_len, GFP_KERNEL);844	msk_buf = kzalloc(proto->raw.pkt_len, GFP_KERNEL);845	if (!pkt_buf || !msk_buf)846		goto err_mem_alloc;847 848	memcpy(pkt_buf, proto->raw.spec, proto->raw.pkt_len);849	memcpy(msk_buf, proto->raw.mask, proto->raw.pkt_len);850 851	hw = &pf->hw;852 853	/* Get raw profile info via Parser Lib */854	psr = ice_parser_create(hw);855	if (IS_ERR(psr)) {856		status = PTR_ERR(psr);857		goto err_mem_alloc;858	}859 860	ice_parser_dvm_set(psr, ice_is_dvm_ena(hw));861 862	if (ice_get_open_tunnel_port(hw, &udp_port, TNL_VXLAN))863		ice_parser_vxlan_tunnel_set(psr, udp_port, true);864 865	status = ice_parser_run(psr, pkt_buf, proto->raw.pkt_len, &rslt);866	if (status)867		goto err_parser_destroy;868 869	if (hw->debug_mask & ICE_DBG_PARSER)870		ice_parser_result_dump(hw, &rslt);871 872	conf->prof = kzalloc(sizeof(*conf->prof), GFP_KERNEL);873	if (!conf->prof) {874		status = -ENOMEM;875		goto err_parser_destroy;876	}877 878	status = ice_parser_profile_init(&rslt, pkt_buf, msk_buf,879					 proto->raw.pkt_len, ICE_BLK_FD,880					 conf->prof);881	if (status)882		goto err_parser_profile_init;883 884	if (hw->debug_mask & ICE_DBG_PARSER)885		ice_parser_profile_dump(hw, conf->prof);886 887	/* Store raw flow info into @conf */888	conf->pkt_len = proto->raw.pkt_len;889	conf->pkt_buf = pkt_buf;890	conf->parser_ena = true;891 892	ice_parser_destroy(psr);893	return 0;894 895err_parser_profile_init:896	kfree(conf->prof);897err_parser_destroy:898	ice_parser_destroy(psr);899err_mem_alloc:900	kfree(pkt_buf);901	return status;902}903 904/**905 * ice_vc_fdir_parse_pattern906 * @vf: pointer to the VF info907 * @fltr: virtual channel add cmd buffer908 * @conf: FDIR configuration for each filter909 *910 * Parse the virtual channel filter's pattern and store them into conf911 *912 * Return: 0 on success, and other on error.913 */914static int915ice_vc_fdir_parse_pattern(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,916			  struct virtchnl_fdir_fltr_conf *conf)917{918	struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs;919	enum virtchnl_proto_hdr_type l3 = VIRTCHNL_PROTO_HDR_NONE;920	enum virtchnl_proto_hdr_type l4 = VIRTCHNL_PROTO_HDR_NONE;921	struct device *dev = ice_pf_to_dev(vf->pf);922	struct ice_fdir_fltr *input = &conf->input;923	int i;924 925	if (proto->count > VIRTCHNL_MAX_NUM_PROTO_HDRS) {926		dev_dbg(dev, "Invalid protocol count:0x%x for VF %d\n",927			proto->count, vf->vf_id);928		return -EINVAL;929	}930 931	/* For raw FDIR filters created by the parser */932	if (ice_vc_fdir_is_raw_flow(proto))933		return ice_vc_fdir_parse_raw(vf, proto, conf);934 935	for (i = 0; i < proto->count; i++) {936		struct virtchnl_proto_hdr *hdr = &proto->proto_hdr[i];937		struct ip_esp_hdr *esph;938		struct ip_auth_hdr *ah;939		struct sctphdr *sctph;940		struct ipv6hdr *ip6h;941		struct udphdr *udph;942		struct tcphdr *tcph;943		struct ethhdr *eth;944		struct iphdr *iph;945		u8 s_field;946		u8 *rawh;947 948		switch (hdr->type) {949		case VIRTCHNL_PROTO_HDR_ETH:950			eth = (struct ethhdr *)hdr->buffer;951			input->flow_type = ICE_FLTR_PTYPE_NON_IP_L2;952 953			if (hdr->field_selector)954				input->ext_data.ether_type = eth->h_proto;955			break;956		case VIRTCHNL_PROTO_HDR_IPV4:957			iph = (struct iphdr *)hdr->buffer;958			l3 = VIRTCHNL_PROTO_HDR_IPV4;959			input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;960 961			if (hdr->field_selector) {962				input->ip.v4.src_ip = iph->saddr;963				input->ip.v4.dst_ip = iph->daddr;964				input->ip.v4.tos = iph->tos;965				input->ip.v4.proto = iph->protocol;966			}967			break;968		case VIRTCHNL_PROTO_HDR_IPV6:969			ip6h = (struct ipv6hdr *)hdr->buffer;970			l3 = VIRTCHNL_PROTO_HDR_IPV6;971			input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;972 973			if (hdr->field_selector) {974				memcpy(input->ip.v6.src_ip,975				       ip6h->saddr.in6_u.u6_addr8,976				       sizeof(ip6h->saddr));977				memcpy(input->ip.v6.dst_ip,978				       ip6h->daddr.in6_u.u6_addr8,979				       sizeof(ip6h->daddr));980				input->ip.v6.tc = ((u8)(ip6h->priority) << 4) |981						  (ip6h->flow_lbl[0] >> 4);982				input->ip.v6.proto = ip6h->nexthdr;983			}984			break;985		case VIRTCHNL_PROTO_HDR_TCP:986			tcph = (struct tcphdr *)hdr->buffer;987			if (l3 == VIRTCHNL_PROTO_HDR_IPV4)988				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_TCP;989			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)990				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_TCP;991 992			if (hdr->field_selector) {993				if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {994					input->ip.v4.src_port = tcph->source;995					input->ip.v4.dst_port = tcph->dest;996				} else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {997					input->ip.v6.src_port = tcph->source;998					input->ip.v6.dst_port = tcph->dest;999				}1000			}1001			break;1002		case VIRTCHNL_PROTO_HDR_UDP:1003			udph = (struct udphdr *)hdr->buffer;1004			if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1005				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_UDP;1006			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1007				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_UDP;1008 1009			if (hdr->field_selector) {1010				if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {1011					input->ip.v4.src_port = udph->source;1012					input->ip.v4.dst_port = udph->dest;1013				} else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {1014					input->ip.v6.src_port = udph->source;1015					input->ip.v6.dst_port = udph->dest;1016				}1017			}1018			break;1019		case VIRTCHNL_PROTO_HDR_SCTP:1020			sctph = (struct sctphdr *)hdr->buffer;1021			if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1022				input->flow_type =1023					ICE_FLTR_PTYPE_NONF_IPV4_SCTP;1024			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1025				input->flow_type =1026					ICE_FLTR_PTYPE_NONF_IPV6_SCTP;1027 1028			if (hdr->field_selector) {1029				if (l3 == VIRTCHNL_PROTO_HDR_IPV4) {1030					input->ip.v4.src_port = sctph->source;1031					input->ip.v4.dst_port = sctph->dest;1032				} else if (l3 == VIRTCHNL_PROTO_HDR_IPV6) {1033					input->ip.v6.src_port = sctph->source;1034					input->ip.v6.dst_port = sctph->dest;1035				}1036			}1037			break;1038		case VIRTCHNL_PROTO_HDR_L2TPV3:1039			if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1040				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_L2TPV3;1041			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1042				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_L2TPV3;1043 1044			if (hdr->field_selector)1045				input->l2tpv3_data.session_id = *((__be32 *)hdr->buffer);1046			break;1047		case VIRTCHNL_PROTO_HDR_ESP:1048			esph = (struct ip_esp_hdr *)hdr->buffer;1049			if (l3 == VIRTCHNL_PROTO_HDR_IPV4 &&1050			    l4 == VIRTCHNL_PROTO_HDR_UDP)1051				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_NAT_T_ESP;1052			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 &&1053				 l4 == VIRTCHNL_PROTO_HDR_UDP)1054				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_NAT_T_ESP;1055			else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 &&1056				 l4 == VIRTCHNL_PROTO_HDR_NONE)1057				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_ESP;1058			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 &&1059				 l4 == VIRTCHNL_PROTO_HDR_NONE)1060				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_ESP;1061 1062			if (l4 == VIRTCHNL_PROTO_HDR_UDP)1063				conf->inset_flag |= FDIR_INSET_FLAG_ESP_UDP;1064			else1065				conf->inset_flag |= FDIR_INSET_FLAG_ESP_IPSEC;1066 1067			if (hdr->field_selector) {1068				if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1069					input->ip.v4.sec_parm_idx = esph->spi;1070				else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1071					input->ip.v6.sec_parm_idx = esph->spi;1072			}1073			break;1074		case VIRTCHNL_PROTO_HDR_AH:1075			ah = (struct ip_auth_hdr *)hdr->buffer;1076			if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1077				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_AH;1078			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1079				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_AH;1080 1081			if (hdr->field_selector) {1082				if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1083					input->ip.v4.sec_parm_idx = ah->spi;1084				else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1085					input->ip.v6.sec_parm_idx = ah->spi;1086			}1087			break;1088		case VIRTCHNL_PROTO_HDR_PFCP:1089			rawh = (u8 *)hdr->buffer;1090			s_field = (rawh[0] >> PFCP_S_OFFSET) & PFCP_S_MASK;1091			if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 0)1092				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_NODE;1093			else if (l3 == VIRTCHNL_PROTO_HDR_IPV4 && s_field == 1)1094				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_PFCP_SESSION;1095			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 0)1096				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_NODE;1097			else if (l3 == VIRTCHNL_PROTO_HDR_IPV6 && s_field == 1)1098				input->flow_type = ICE_FLTR_PTYPE_NONF_IPV6_PFCP_SESSION;1099 1100			if (hdr->field_selector) {1101				if (l3 == VIRTCHNL_PROTO_HDR_IPV4)1102					input->ip.v4.dst_port = cpu_to_be16(PFCP_PORT_NR);1103				else if (l3 == VIRTCHNL_PROTO_HDR_IPV6)1104					input->ip.v6.dst_port = cpu_to_be16(PFCP_PORT_NR);1105			}1106			break;1107		case VIRTCHNL_PROTO_HDR_GTPU_IP:1108			rawh = (u8 *)hdr->buffer;1109			input->flow_type = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;1110 1111			if (hdr->field_selector)1112				input->gtpu_data.teid = *(__be32 *)(&rawh[GTPU_TEID_OFFSET]);1113			conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU;1114			break;1115		case VIRTCHNL_PROTO_HDR_GTPU_EH:1116			rawh = (u8 *)hdr->buffer;1117 1118			if (hdr->field_selector)1119				input->gtpu_data.qfi = rawh[GTPU_EH_QFI_OFFSET] & GTPU_EH_QFI_MASK;1120			conf->ttype = ICE_FDIR_TUNNEL_TYPE_GTPU_EH;1121			break;1122		default:1123			dev_dbg(dev, "Invalid header type 0x:%x for VF %d\n",1124				hdr->type, vf->vf_id);1125			return -EINVAL;1126		}1127	}1128 1129	return 0;1130}1131 1132/**1133 * ice_vc_fdir_parse_action1134 * @vf: pointer to the VF info1135 * @fltr: virtual channel add cmd buffer1136 * @conf: FDIR configuration for each filter1137 *1138 * Parse the virtual channel filter's action and store them into conf1139 *1140 * Return: 0 on success, and other on error.1141 */1142static int1143ice_vc_fdir_parse_action(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,1144			 struct virtchnl_fdir_fltr_conf *conf)1145{1146	struct virtchnl_filter_action_set *as = &fltr->rule_cfg.action_set;1147	struct device *dev = ice_pf_to_dev(vf->pf);1148	struct ice_fdir_fltr *input = &conf->input;1149	u32 dest_num = 0;1150	u32 mark_num = 0;1151	int i;1152 1153	if (as->count > VIRTCHNL_MAX_NUM_ACTIONS) {1154		dev_dbg(dev, "Invalid action numbers:0x%x for VF %d\n",1155			as->count, vf->vf_id);1156		return -EINVAL;1157	}1158 1159	for (i = 0; i < as->count; i++) {1160		struct virtchnl_filter_action *action = &as->actions[i];1161 1162		switch (action->type) {1163		case VIRTCHNL_ACTION_PASSTHRU:1164			dest_num++;1165			input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER;1166			break;1167		case VIRTCHNL_ACTION_DROP:1168			dest_num++;1169			input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DROP_PKT;1170			break;1171		case VIRTCHNL_ACTION_QUEUE:1172			dest_num++;1173			input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX;1174			input->q_index = action->act_conf.queue.index;1175			break;1176		case VIRTCHNL_ACTION_Q_REGION:1177			dest_num++;1178			input->dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP;1179			input->q_index = action->act_conf.queue.index;1180			input->q_region = action->act_conf.queue.region;1181			break;1182		case VIRTCHNL_ACTION_MARK:1183			mark_num++;1184			input->fltr_id = action->act_conf.mark_id;1185			input->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_THREE;1186			break;1187		default:1188			dev_dbg(dev, "Invalid action type:0x%x for VF %d\n",1189				action->type, vf->vf_id);1190			return -EINVAL;1191		}1192	}1193 1194	if (dest_num == 0 || dest_num >= 2) {1195		dev_dbg(dev, "Invalid destination action for VF %d\n",1196			vf->vf_id);1197		return -EINVAL;1198	}1199 1200	if (mark_num >= 2) {1201		dev_dbg(dev, "Too many mark actions for VF %d\n", vf->vf_id);1202		return -EINVAL;1203	}1204 1205	return 0;1206}1207 1208/**1209 * ice_vc_validate_fdir_fltr - validate the virtual channel filter1210 * @vf: pointer to the VF info1211 * @fltr: virtual channel add cmd buffer1212 * @conf: FDIR configuration for each filter1213 *1214 * Return: 0 on success, and other on error.1215 */1216static int1217ice_vc_validate_fdir_fltr(struct ice_vf *vf, struct virtchnl_fdir_add *fltr,1218			  struct virtchnl_fdir_fltr_conf *conf)1219{1220	struct virtchnl_proto_hdrs *proto = &fltr->rule_cfg.proto_hdrs;1221	int ret;1222 1223	/* For raw FDIR filters created by the parser */1224	if (!ice_vc_fdir_is_raw_flow(proto))1225		if (!ice_vc_validate_pattern(vf, proto))1226			return -EINVAL;1227 1228	ret = ice_vc_fdir_parse_pattern(vf, fltr, conf);1229	if (ret)1230		return ret;1231 1232	return ice_vc_fdir_parse_action(vf, fltr, conf);1233}1234 1235/**1236 * ice_vc_fdir_comp_rules - compare if two filter rules have the same value1237 * @conf_a: FDIR configuration for filter a1238 * @conf_b: FDIR configuration for filter b1239 *1240 * Return: 0 on success, and other on error.1241 */1242static bool1243ice_vc_fdir_comp_rules(struct virtchnl_fdir_fltr_conf *conf_a,1244		       struct virtchnl_fdir_fltr_conf *conf_b)1245{1246	struct ice_fdir_fltr *a = &conf_a->input;1247	struct ice_fdir_fltr *b = &conf_b->input;1248 1249	if (conf_a->ttype != conf_b->ttype)1250		return false;1251	if (a->flow_type != b->flow_type)1252		return false;1253	if (memcmp(&a->ip, &b->ip, sizeof(a->ip)))1254		return false;1255	if (memcmp(&a->mask, &b->mask, sizeof(a->mask)))1256		return false;1257	if (memcmp(&a->gtpu_data, &b->gtpu_data, sizeof(a->gtpu_data)))1258		return false;1259	if (memcmp(&a->gtpu_mask, &b->gtpu_mask, sizeof(a->gtpu_mask)))1260		return false;1261	if (memcmp(&a->l2tpv3_data, &b->l2tpv3_data, sizeof(a->l2tpv3_data)))1262		return false;1263	if (memcmp(&a->l2tpv3_mask, &b->l2tpv3_mask, sizeof(a->l2tpv3_mask)))1264		return false;1265	if (memcmp(&a->ext_data, &b->ext_data, sizeof(a->ext_data)))1266		return false;1267	if (memcmp(&a->ext_mask, &b->ext_mask, sizeof(a->ext_mask)))1268		return false;1269 1270	return true;1271}1272 1273/**1274 * ice_vc_fdir_is_dup_fltr1275 * @vf: pointer to the VF info1276 * @conf: FDIR configuration for each filter1277 *1278 * Check if there is duplicated rule with same conf value1279 *1280 * Return: 0 true success, and false on error.1281 */1282static bool1283ice_vc_fdir_is_dup_fltr(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf)1284{1285	struct ice_fdir_fltr *desc;1286	bool ret;1287 1288	list_for_each_entry(desc, &vf->fdir.fdir_rule_list, fltr_node) {1289		struct virtchnl_fdir_fltr_conf *node =1290				to_fltr_conf_from_desc(desc);1291 1292		ret = ice_vc_fdir_comp_rules(node, conf);1293		if (ret)1294			return true;1295	}1296 1297	return false;1298}1299 1300/**1301 * ice_vc_fdir_insert_entry1302 * @vf: pointer to the VF info1303 * @conf: FDIR configuration for each filter1304 * @id: pointer to ID value allocated by driver1305 *1306 * Insert FDIR conf entry into list and allocate ID for this filter1307 *1308 * Return: 0 true success, and other on error.1309 */1310static int1311ice_vc_fdir_insert_entry(struct ice_vf *vf,1312			 struct virtchnl_fdir_fltr_conf *conf, u32 *id)1313{1314	struct ice_fdir_fltr *input = &conf->input;1315	int i;1316 1317	/* alloc ID corresponding with conf */1318	i = idr_alloc(&vf->fdir.fdir_rule_idr, conf, 0,1319		      ICE_FDIR_MAX_FLTRS, GFP_KERNEL);1320	if (i < 0)1321		return -EINVAL;1322	*id = i;1323 1324	list_add(&input->fltr_node, &vf->fdir.fdir_rule_list);1325	return 0;1326}1327 1328/**1329 * ice_vc_fdir_remove_entry - remove FDIR conf entry by ID value1330 * @vf: pointer to the VF info1331 * @conf: FDIR configuration for each filter1332 * @id: filter rule's ID1333 */1334static void1335ice_vc_fdir_remove_entry(struct ice_vf *vf,1336			 struct virtchnl_fdir_fltr_conf *conf, u32 id)1337{1338	struct ice_fdir_fltr *input = &conf->input;1339 1340	idr_remove(&vf->fdir.fdir_rule_idr, id);1341	list_del(&input->fltr_node);1342}1343 1344/**1345 * ice_vc_fdir_lookup_entry - lookup FDIR conf entry by ID value1346 * @vf: pointer to the VF info1347 * @id: filter rule's ID1348 *1349 * Return: NULL on error, and other on success.1350 */1351static struct virtchnl_fdir_fltr_conf *1352ice_vc_fdir_lookup_entry(struct ice_vf *vf, u32 id)1353{1354	return idr_find(&vf->fdir.fdir_rule_idr, id);1355}1356 1357/**1358 * ice_vc_fdir_flush_entry - remove all FDIR conf entry1359 * @vf: pointer to the VF info1360 */1361static void ice_vc_fdir_flush_entry(struct ice_vf *vf)1362{1363	struct virtchnl_fdir_fltr_conf *conf;1364	struct ice_fdir_fltr *desc, *temp;1365 1366	list_for_each_entry_safe(desc, temp,1367				 &vf->fdir.fdir_rule_list, fltr_node) {1368		conf = to_fltr_conf_from_desc(desc);1369		list_del(&desc->fltr_node);1370		devm_kfree(ice_pf_to_dev(vf->pf), conf);1371	}1372}1373 1374/**1375 * ice_vc_fdir_write_fltr - write filter rule into hardware1376 * @vf: pointer to the VF info1377 * @conf: FDIR configuration for each filter1378 * @add: true implies add rule, false implies del rules1379 * @is_tun: false implies non-tunnel type filter, true implies tunnel filter1380 *1381 * Return: 0 on success, and other on error.1382 */1383static int ice_vc_fdir_write_fltr(struct ice_vf *vf,1384				  struct virtchnl_fdir_fltr_conf *conf,1385				  bool add, bool is_tun)1386{1387	struct ice_fdir_fltr *input = &conf->input;1388	struct ice_vsi *vsi, *ctrl_vsi;1389	struct ice_fltr_desc desc;1390	struct device *dev;1391	struct ice_pf *pf;1392	struct ice_hw *hw;1393	int ret;1394	u8 *pkt;1395 1396	pf = vf->pf;1397	dev = ice_pf_to_dev(pf);1398	hw = &pf->hw;1399	vsi = ice_get_vf_vsi(vf);1400	if (!vsi) {1401		dev_dbg(dev, "Invalid vsi for VF %d\n", vf->vf_id);1402		return -EINVAL;1403	}1404 1405	input->dest_vsi = vsi->idx;1406	input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;1407 1408	ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];1409	if (!ctrl_vsi) {1410		dev_dbg(dev, "Invalid ctrl_vsi for VF %d\n", vf->vf_id);1411		return -EINVAL;1412	}1413 1414	pkt = devm_kzalloc(dev, ICE_FDIR_MAX_RAW_PKT_SIZE, GFP_KERNEL);1415	if (!pkt)1416		return -ENOMEM;1417 1418	ice_fdir_get_prgm_desc(hw, input, &desc, add);1419	if (conf->parser_ena) {1420		memcpy(pkt, conf->pkt_buf, conf->pkt_len);1421	} else {1422		ret = ice_fdir_get_gen_prgm_pkt(hw, input, pkt, false, is_tun);1423		if (ret) {1424			dev_dbg(dev, "Gen training pkt for VF %d ptype %d failed\n",1425				vf->vf_id, input->flow_type);1426			goto err_free_pkt;1427		}1428	}1429 1430	ret = ice_prgm_fdir_fltr(ctrl_vsi, &desc, pkt);1431	if (ret)1432		goto err_free_pkt;1433 1434	return 0;1435 1436err_free_pkt:1437	devm_kfree(dev, pkt);1438	return ret;1439}1440 1441/**1442 * ice_vf_fdir_timer - FDIR program waiting timer interrupt handler1443 * @t: pointer to timer_list1444 */1445static void ice_vf_fdir_timer(struct timer_list *t)1446{1447	struct ice_vf_fdir_ctx *ctx_irq = from_timer(ctx_irq, t, rx_tmr);1448	struct ice_vf_fdir_ctx *ctx_done;1449	struct ice_vf_fdir *fdir;1450	unsigned long flags;1451	struct ice_vf *vf;1452	struct ice_pf *pf;1453 1454	fdir = container_of(ctx_irq, struct ice_vf_fdir, ctx_irq);1455	vf = container_of(fdir, struct ice_vf, fdir);1456	ctx_done = &fdir->ctx_done;1457	pf = vf->pf;1458	spin_lock_irqsave(&fdir->ctx_lock, flags);1459	if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) {1460		spin_unlock_irqrestore(&fdir->ctx_lock, flags);1461		WARN_ON_ONCE(1);1462		return;1463	}1464 1465	ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID;1466 1467	ctx_done->flags |= ICE_VF_FDIR_CTX_VALID;1468	ctx_done->conf = ctx_irq->conf;1469	ctx_done->stat = ICE_FDIR_CTX_TIMEOUT;1470	ctx_done->v_opcode = ctx_irq->v_opcode;1471	spin_unlock_irqrestore(&fdir->ctx_lock, flags);1472 1473	set_bit(ICE_FD_VF_FLUSH_CTX, pf->state);1474	ice_service_task_schedule(pf);1475}1476 1477/**1478 * ice_vc_fdir_irq_handler - ctrl_vsi Rx queue interrupt handler1479 * @ctrl_vsi: pointer to a VF's CTRL VSI1480 * @rx_desc: pointer to FDIR Rx queue descriptor1481 */1482void1483ice_vc_fdir_irq_handler(struct ice_vsi *ctrl_vsi,1484			union ice_32b_rx_flex_desc *rx_desc)1485{1486	struct ice_pf *pf = ctrl_vsi->back;1487	struct ice_vf *vf = ctrl_vsi->vf;1488	struct ice_vf_fdir_ctx *ctx_done;1489	struct ice_vf_fdir_ctx *ctx_irq;1490	struct ice_vf_fdir *fdir;1491	unsigned long flags;1492	struct device *dev;1493	int ret;1494 1495	if (WARN_ON(!vf))1496		return;1497 1498	fdir = &vf->fdir;1499	ctx_done = &fdir->ctx_done;1500	ctx_irq = &fdir->ctx_irq;1501	dev = ice_pf_to_dev(pf);1502	spin_lock_irqsave(&fdir->ctx_lock, flags);1503	if (!(ctx_irq->flags & ICE_VF_FDIR_CTX_VALID)) {1504		spin_unlock_irqrestore(&fdir->ctx_lock, flags);1505		WARN_ON_ONCE(1);1506		return;1507	}1508 1509	ctx_irq->flags &= ~ICE_VF_FDIR_CTX_VALID;1510 1511	ctx_done->flags |= ICE_VF_FDIR_CTX_VALID;1512	ctx_done->conf = ctx_irq->conf;1513	ctx_done->stat = ICE_FDIR_CTX_IRQ;1514	ctx_done->v_opcode = ctx_irq->v_opcode;1515	memcpy(&ctx_done->rx_desc, rx_desc, sizeof(*rx_desc));1516	spin_unlock_irqrestore(&fdir->ctx_lock, flags);1517 1518	ret = del_timer(&ctx_irq->rx_tmr);1519	if (!ret)1520		dev_err(dev, "VF %d: Unexpected inactive timer!\n", vf->vf_id);1521 1522	set_bit(ICE_FD_VF_FLUSH_CTX, pf->state);1523	ice_service_task_schedule(pf);1524}1525 1526/**1527 * ice_vf_fdir_dump_info - dump FDIR information for diagnosis1528 * @vf: pointer to the VF info1529 */1530static void ice_vf_fdir_dump_info(struct ice_vf *vf)1531{1532	u32 fd_size, fd_cnt, fd_size_g, fd_cnt_g, fd_size_b, fd_cnt_b;1533	struct ice_vsi *vf_vsi;1534	struct device *dev;1535	struct ice_pf *pf;1536	struct ice_hw *hw;1537	u16 vsi_num;1538 1539	pf = vf->pf;1540	hw = &pf->hw;1541	dev = ice_pf_to_dev(pf);1542	vf_vsi = ice_get_vf_vsi(vf);1543	if (!vf_vsi) {1544		dev_dbg(dev, "VF %d: invalid VSI pointer\n", vf->vf_id);1545		return;1546	}1547 1548	vsi_num = ice_get_hw_vsi_num(hw, vf_vsi->idx);1549 1550	fd_size = rd32(hw, VSIQF_FD_SIZE(vsi_num));1551	fd_cnt = rd32(hw, VSIQF_FD_CNT(vsi_num));1552	switch (hw->mac_type) {1553	case ICE_MAC_E830:1554		fd_size_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_size);1555		fd_size_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_size);1556		fd_cnt_g = FIELD_GET(E830_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt);1557		fd_cnt_b = FIELD_GET(E830_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt);1558		break;1559	case ICE_MAC_E810:1560	default:1561		fd_size_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_size);1562		fd_size_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_size);1563		fd_cnt_g = FIELD_GET(E800_VSIQF_FD_CNT_FD_GCNT_M, fd_cnt);1564		fd_cnt_b = FIELD_GET(E800_VSIQF_FD_CNT_FD_BCNT_M, fd_cnt);1565	}1566 1567	dev_dbg(dev, "VF %d: Size in the FD table: guaranteed:0x%x, best effort:0x%x\n",1568		vf->vf_id, fd_size_g, fd_size_b);1569	dev_dbg(dev, "VF %d: Filter counter in the FD table: guaranteed:0x%x, best effort:0x%x\n",1570		vf->vf_id, fd_cnt_g, fd_cnt_b);1571}1572 1573/**1574 * ice_vf_verify_rx_desc - verify received FDIR programming status descriptor1575 * @vf: pointer to the VF info1576 * @ctx: FDIR context info for post processing1577 * @status: virtchnl FDIR program status1578 *1579 * Return: 0 on success, and other on error.1580 */1581static int1582ice_vf_verify_rx_desc(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,1583		      enum virtchnl_fdir_prgm_status *status)1584{1585	struct device *dev = ice_pf_to_dev(vf->pf);1586	u32 stat_err, error, prog_id;1587	int ret;1588 1589	stat_err = le16_to_cpu(ctx->rx_desc.wb.status_error0);1590	if (FIELD_GET(ICE_FXD_FLTR_WB_QW1_DD_M, stat_err) !=1591	    ICE_FXD_FLTR_WB_QW1_DD_YES) {1592		*status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;1593		dev_err(dev, "VF %d: Desc Done not set\n", vf->vf_id);1594		ret = -EINVAL;1595		goto err_exit;1596	}1597 1598	prog_id = FIELD_GET(ICE_FXD_FLTR_WB_QW1_PROG_ID_M, stat_err);1599	if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD &&1600	    ctx->v_opcode != VIRTCHNL_OP_ADD_FDIR_FILTER) {1601		dev_err(dev, "VF %d: Desc show add, but ctx not",1602			vf->vf_id);1603		*status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;1604		ret = -EINVAL;1605		goto err_exit;1606	}1607 1608	if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_DEL &&1609	    ctx->v_opcode != VIRTCHNL_OP_DEL_FDIR_FILTER) {1610		dev_err(dev, "VF %d: Desc show del, but ctx not",1611			vf->vf_id);1612		*status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;1613		ret = -EINVAL;1614		goto err_exit;1615	}1616 1617	error = FIELD_GET(ICE_FXD_FLTR_WB_QW1_FAIL_M, stat_err);1618	if (error == ICE_FXD_FLTR_WB_QW1_FAIL_YES) {1619		if (prog_id == ICE_FXD_FLTR_WB_QW1_PROG_ADD) {1620			dev_err(dev, "VF %d, Failed to add FDIR rule due to no space in the table",1621				vf->vf_id);1622			*status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;1623		} else {1624			dev_err(dev, "VF %d, Failed to remove FDIR rule, attempt to remove non-existent entry",1625				vf->vf_id);1626			*status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST;1627		}1628		ret = -EINVAL;1629		goto err_exit;1630	}1631 1632	error = FIELD_GET(ICE_FXD_FLTR_WB_QW1_FAIL_PROF_M, stat_err);1633	if (error == ICE_FXD_FLTR_WB_QW1_FAIL_PROF_YES) {1634		dev_err(dev, "VF %d: Profile matching error", vf->vf_id);1635		*status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;1636		ret = -EINVAL;1637		goto err_exit;1638	}1639 1640	*status = VIRTCHNL_FDIR_SUCCESS;1641 1642	return 0;1643 1644err_exit:1645	ice_vf_fdir_dump_info(vf);1646	return ret;1647}1648 1649static int ice_fdir_is_tunnel(enum ice_fdir_tunnel_type ttype)1650{1651	return (ttype == ICE_FDIR_TUNNEL_TYPE_GRE_INNER ||1652		ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_INNER ||1653		ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH_INNER ||1654		ttype == ICE_FDIR_TUNNEL_TYPE_GTPOGRE_INNER ||1655		ttype == ICE_FDIR_TUNNEL_TYPE_ECPRI ||1656		ttype == ICE_FDIR_TUNNEL_TYPE_L2TPV2_INNER);1657}1658 1659/**1660 * ice_vc_add_fdir_fltr_post1661 * @vf: pointer to the VF structure1662 * @ctx: FDIR context info for post processing1663 * @status: virtchnl FDIR program status1664 * @success: true implies success, false implies failure1665 *1666 * Post process for flow director add command. If success, then do post process1667 * and send back success msg by virtchnl. Otherwise, do context reversion and1668 * send back failure msg by virtchnl.1669 *1670 * Return: 0 on success, and other on error.1671 */1672static int1673ice_vc_add_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,1674			  enum virtchnl_fdir_prgm_status status,1675			  bool success)1676{1677	struct virtchnl_fdir_fltr_conf *conf = ctx->conf;1678	struct device *dev = ice_pf_to_dev(vf->pf);1679	enum virtchnl_status_code v_ret;1680	struct virtchnl_fdir_add *resp;1681	int ret, len, is_tun;1682 1683	v_ret = VIRTCHNL_STATUS_SUCCESS;1684	len = sizeof(*resp);1685	resp = kzalloc(len, GFP_KERNEL);1686	if (!resp) {1687		len = 0;1688		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;1689		dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id);1690		goto err_exit;1691	}1692 1693	if (!success)1694		goto err_exit;1695 1696	is_tun = 0;1697	resp->status = status;1698	resp->flow_id = conf->flow_id;1699	vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]++;1700	vf->fdir.fdir_fltr_cnt_total++;1701 1702	ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,1703				    (u8 *)resp, len);1704	kfree(resp);1705 1706	dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n",1707		vf->vf_id, conf->flow_id,1708		(ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ?1709		"add" : "del");1710	return ret;1711 1712err_exit:1713	if (resp)1714		resp->status = status;1715	ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);1716	devm_kfree(dev, conf);1717 1718	ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,1719				    (u8 *)resp, len);1720	kfree(resp);1721	return ret;1722}1723 1724/**1725 * ice_vc_del_fdir_fltr_post1726 * @vf: pointer to the VF structure1727 * @ctx: FDIR context info for post processing1728 * @status: virtchnl FDIR program status1729 * @success: true implies success, false implies failure1730 *1731 * Post process for flow director del command. If success, then do post process1732 * and send back success msg by virtchnl. Otherwise, do context reversion and1733 * send back failure msg by virtchnl.1734 *1735 * Return: 0 on success, and other on error.1736 */1737static int1738ice_vc_del_fdir_fltr_post(struct ice_vf *vf, struct ice_vf_fdir_ctx *ctx,1739			  enum virtchnl_fdir_prgm_status status,1740			  bool success)1741{1742	struct virtchnl_fdir_fltr_conf *conf = ctx->conf;1743	struct device *dev = ice_pf_to_dev(vf->pf);1744	enum virtchnl_status_code v_ret;1745	struct virtchnl_fdir_del *resp;1746	int ret, len, is_tun;1747 1748	v_ret = VIRTCHNL_STATUS_SUCCESS;1749	len = sizeof(*resp);1750	resp = kzalloc(len, GFP_KERNEL);1751	if (!resp) {1752		len = 0;1753		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;1754		dev_dbg(dev, "VF %d: Alloc resp buf fail", vf->vf_id);1755		goto err_exit;1756	}1757 1758	if (!success)1759		goto err_exit;1760 1761	is_tun = 0;1762	resp->status = status;1763	ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);1764	vf->fdir.fdir_fltr_cnt[conf->input.flow_type][is_tun]--;1765	vf->fdir.fdir_fltr_cnt_total--;1766 1767	ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,1768				    (u8 *)resp, len);1769	kfree(resp);1770 1771	dev_dbg(dev, "VF %d: flow_id:0x%X, FDIR %s success!\n",1772		vf->vf_id, conf->flow_id,1773		(ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER) ?1774		"add" : "del");1775	devm_kfree(dev, conf);1776	return ret;1777 1778err_exit:1779	if (resp)1780		resp->status = status;1781	if (success)1782		devm_kfree(dev, conf);1783 1784	ret = ice_vc_send_msg_to_vf(vf, ctx->v_opcode, v_ret,1785				    (u8 *)resp, len);1786	kfree(resp);1787	return ret;1788}1789 1790/**1791 * ice_flush_fdir_ctx1792 * @pf: pointer to the PF structure1793 *1794 * Flush all the pending event on ctx_done list and process them.1795 */1796void ice_flush_fdir_ctx(struct ice_pf *pf)1797{1798	struct ice_vf *vf;1799	unsigned int bkt;1800 1801	if (!test_and_clear_bit(ICE_FD_VF_FLUSH_CTX, pf->state))1802		return;1803 1804	mutex_lock(&pf->vfs.table_lock);1805	ice_for_each_vf(pf, bkt, vf) {1806		struct device *dev = ice_pf_to_dev(pf);1807		enum virtchnl_fdir_prgm_status status;1808		struct ice_vf_fdir_ctx *ctx;1809		unsigned long flags;1810		int ret;1811 1812		if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))1813			continue;1814 1815		if (vf->ctrl_vsi_idx == ICE_NO_VSI)1816			continue;1817 1818		ctx = &vf->fdir.ctx_done;1819		spin_lock_irqsave(&vf->fdir.ctx_lock, flags);1820		if (!(ctx->flags & ICE_VF_FDIR_CTX_VALID)) {1821			spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1822			continue;1823		}1824		spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1825 1826		WARN_ON(ctx->stat == ICE_FDIR_CTX_READY);1827		if (ctx->stat == ICE_FDIR_CTX_TIMEOUT) {1828			status = VIRTCHNL_FDIR_FAILURE_RULE_TIMEOUT;1829			dev_err(dev, "VF %d: ctrl_vsi irq timeout\n",1830				vf->vf_id);1831			goto err_exit;1832		}1833 1834		ret = ice_vf_verify_rx_desc(vf, ctx, &status);1835		if (ret)1836			goto err_exit;1837 1838		if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER)1839			ice_vc_add_fdir_fltr_post(vf, ctx, status, true);1840		else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER)1841			ice_vc_del_fdir_fltr_post(vf, ctx, status, true);1842		else1843			dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id);1844 1845		spin_lock_irqsave(&vf->fdir.ctx_lock, flags);1846		ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;1847		spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1848		continue;1849err_exit:1850		if (ctx->v_opcode == VIRTCHNL_OP_ADD_FDIR_FILTER)1851			ice_vc_add_fdir_fltr_post(vf, ctx, status, false);1852		else if (ctx->v_opcode == VIRTCHNL_OP_DEL_FDIR_FILTER)1853			ice_vc_del_fdir_fltr_post(vf, ctx, status, false);1854		else1855			dev_err(dev, "VF %d: Unsupported opcode\n", vf->vf_id);1856 1857		spin_lock_irqsave(&vf->fdir.ctx_lock, flags);1858		ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;1859		spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1860	}1861	mutex_unlock(&pf->vfs.table_lock);1862}1863 1864/**1865 * ice_vc_fdir_set_irq_ctx - set FDIR context info for later IRQ handler1866 * @vf: pointer to the VF structure1867 * @conf: FDIR configuration for each filter1868 * @v_opcode: virtual channel operation code1869 *1870 * Return: 0 on success, and other on error.1871 */1872static int1873ice_vc_fdir_set_irq_ctx(struct ice_vf *vf, struct virtchnl_fdir_fltr_conf *conf,1874			enum virtchnl_ops v_opcode)1875{1876	struct device *dev = ice_pf_to_dev(vf->pf);1877	struct ice_vf_fdir_ctx *ctx;1878	unsigned long flags;1879 1880	ctx = &vf->fdir.ctx_irq;1881	spin_lock_irqsave(&vf->fdir.ctx_lock, flags);1882	if ((vf->fdir.ctx_irq.flags & ICE_VF_FDIR_CTX_VALID) ||1883	    (vf->fdir.ctx_done.flags & ICE_VF_FDIR_CTX_VALID)) {1884		spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1885		dev_dbg(dev, "VF %d: Last request is still in progress\n",1886			vf->vf_id);1887		return -EBUSY;1888	}1889	ctx->flags |= ICE_VF_FDIR_CTX_VALID;1890	spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1891 1892	ctx->conf = conf;1893	ctx->v_opcode = v_opcode;1894	ctx->stat = ICE_FDIR_CTX_READY;1895	timer_setup(&ctx->rx_tmr, ice_vf_fdir_timer, 0);1896 1897	mod_timer(&ctx->rx_tmr, round_jiffies(msecs_to_jiffies(10) + jiffies));1898 1899	return 0;1900}1901 1902/**1903 * ice_vc_fdir_clear_irq_ctx - clear FDIR context info for IRQ handler1904 * @vf: pointer to the VF structure1905 *1906 * Return: 0 on success, and other on error.1907 */1908static void ice_vc_fdir_clear_irq_ctx(struct ice_vf *vf)1909{1910	struct ice_vf_fdir_ctx *ctx = &vf->fdir.ctx_irq;1911	unsigned long flags;1912 1913	del_timer(&ctx->rx_tmr);1914	spin_lock_irqsave(&vf->fdir.ctx_lock, flags);1915	ctx->flags &= ~ICE_VF_FDIR_CTX_VALID;1916	spin_unlock_irqrestore(&vf->fdir.ctx_lock, flags);1917}1918 1919/**1920 * ice_vc_parser_fv_check_diff - check two parsed FDIR profile fv context1921 * @fv_a: struct of parsed FDIR profile field vector1922 * @fv_b: struct of parsed FDIR profile field vector1923 *1924 * Check if the two parsed FDIR profile field vector context are different,1925 * including proto_id, offset and mask.1926 *1927 * Return: true on different, false on otherwise.1928 */1929static bool ice_vc_parser_fv_check_diff(struct ice_parser_fv *fv_a,1930					struct ice_parser_fv *fv_b)1931{1932	return (fv_a->proto_id	!= fv_b->proto_id ||1933		fv_a->offset	!= fv_b->offset ||1934		fv_a->msk	!= fv_b->msk);1935}1936 1937/**1938 * ice_vc_parser_fv_save - save parsed FDIR profile fv context1939 * @fv: struct of parsed FDIR profile field vector1940 * @fv_src: parsed FDIR profile field vector context to save1941 *1942 * Save the parsed FDIR profile field vector context, including proto_id,1943 * offset and mask.1944 *1945 * Return: Void.1946 */1947static void ice_vc_parser_fv_save(struct ice_parser_fv *fv,1948				  struct ice_parser_fv *fv_src)1949{1950	fv->proto_id	= fv_src->proto_id;1951	fv->offset	= fv_src->offset;1952	fv->msk		= fv_src->msk;1953	fv->spec	= 0;1954}1955 1956/**1957 * ice_vc_add_fdir_raw - add a raw FDIR filter for VF1958 * @vf: pointer to the VF info1959 * @conf: FDIR configuration for each filter1960 * @v_ret: the final VIRTCHNL code1961 * @stat: pointer to the VIRTCHNL_OP_ADD_FDIR_FILTER1962 * @len: length of the stat1963 *1964 * Return: 0 on success or negative errno on failure.1965 */1966static int1967ice_vc_add_fdir_raw(struct ice_vf *vf,1968		    struct virtchnl_fdir_fltr_conf *conf,1969		    enum virtchnl_status_code *v_ret,1970		    struct virtchnl_fdir_add *stat, int len)1971{1972	struct ice_vsi *vf_vsi, *ctrl_vsi;1973	struct ice_fdir_prof_info *pi;1974	struct ice_pf *pf = vf->pf;1975	int ret, ptg, id, i;1976	struct device *dev;1977	struct ice_hw *hw;1978	bool fv_found;1979 1980	dev = ice_pf_to_dev(pf);1981	hw = &pf->hw;1982	*v_ret = VIRTCHNL_STATUS_ERR_PARAM;1983	stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;1984 1985	id = find_first_bit(conf->prof->ptypes, ICE_FLOW_PTYPE_MAX);1986	ptg = hw->blk[ICE_BLK_FD].xlt1.t[id];1987 1988	vf_vsi = ice_get_vf_vsi(vf);1989	if (!vf_vsi) {1990		dev_err(dev, "Can not get FDIR vf_vsi for VF %d\n", vf->vf_id);1991		return -ENODEV;1992	}1993 1994	ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];1995	if (!ctrl_vsi) {1996		dev_err(dev, "Can not get FDIR ctrl_vsi for VF %d\n",1997			vf->vf_id);1998		return -ENODEV;1999	}2000 2001	fv_found = false;2002 2003	/* Check if profile info already exists, then update the counter */2004	pi = &vf->fdir_prof_info[ptg];2005	if (pi->fdir_active_cnt != 0) {2006		for (i = 0; i < ICE_MAX_FV_WORDS; i++)2007			if (ice_vc_parser_fv_check_diff(&pi->prof.fv[i],2008							&conf->prof->fv[i]))2009				break;2010		if (i == ICE_MAX_FV_WORDS) {2011			fv_found = true;2012			pi->fdir_active_cnt++;2013		}2014	}2015 2016	/* HW profile setting is only required for the first time */2017	if (!fv_found) {2018		ret = ice_flow_set_parser_prof(hw, vf_vsi->idx,2019					       ctrl_vsi->idx, conf->prof,2020					       ICE_BLK_FD);2021 2022		if (ret) {2023			*v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;2024			dev_dbg(dev, "VF %d: insert hw prof failed\n",2025				vf->vf_id);2026			return ret;2027		}2028	}2029 2030	ret = ice_vc_fdir_insert_entry(vf, conf, &conf->flow_id);2031	if (ret) {2032		*v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;2033		dev_dbg(dev, "VF %d: insert FDIR list failed\n",2034			vf->vf_id);2035		return ret;2036	}2037 2038	ret = ice_vc_fdir_set_irq_ctx(vf, conf,2039				      VIRTCHNL_OP_ADD_FDIR_FILTER);2040	if (ret) {2041		dev_dbg(dev, "VF %d: set FDIR context failed\n",2042			vf->vf_id);2043		goto err_rem_entry;2044	}2045 2046	ret = ice_vc_fdir_write_fltr(vf, conf, true, false);2047	if (ret) {2048		dev_err(dev, "VF %d: adding FDIR raw flow rule failed, ret:%d\n",2049			vf->vf_id, ret);2050		goto err_clr_irq;2051	}2052 2053	/* Save parsed profile fv info of the FDIR rule for the first time */2054	if (!fv_found) {2055		for (i = 0; i < conf->prof->fv_num; i++)2056			ice_vc_parser_fv_save(&pi->prof.fv[i],2057					      &conf->prof->fv[i]);2058		pi->prof.fv_num = conf->prof->fv_num;2059		pi->fdir_active_cnt = 1;2060	}2061 2062	return 0;2063 2064err_clr_irq:2065	ice_vc_fdir_clear_irq_ctx(vf);2066err_rem_entry:2067	ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);2068	return ret;2069}2070 2071/**2072 * ice_vc_add_fdir_fltr - add a FDIR filter for VF by the msg buffer2073 * @vf: pointer to the VF info2074 * @msg: pointer to the msg buffer2075 *2076 * Return: 0 on success, and other on error.2077 */2078int ice_vc_add_fdir_fltr(struct ice_vf *vf, u8 *msg)2079{2080	struct virtchnl_fdir_add *fltr = (struct virtchnl_fdir_add *)msg;2081	struct virtchnl_fdir_add *stat = NULL;2082	struct virtchnl_fdir_fltr_conf *conf;2083	enum virtchnl_status_code v_ret;2084	struct ice_vsi *vf_vsi;2085	struct device *dev;2086	struct ice_pf *pf;2087	int is_tun = 0;2088	int len = 0;2089	int ret;2090 2091	pf = vf->pf;2092	dev = ice_pf_to_dev(pf);2093	vf_vsi = ice_get_vf_vsi(vf);2094 2095#define ICE_VF_MAX_FDIR_FILTERS	1282096	if (!ice_fdir_num_avail_fltr(&pf->hw, vf_vsi) ||2097	    vf->fdir.fdir_fltr_cnt_total >= ICE_VF_MAX_FDIR_FILTERS) {2098		v_ret = VIRTCHNL_STATUS_ERR_PARAM;2099		dev_err(dev, "Max number of FDIR filters for VF %d is reached\n",2100			vf->vf_id);2101		goto err_exit;2102	}2103 2104	ret = ice_vc_fdir_param_check(vf, fltr->vsi_id);2105	if (ret) {2106		v_ret = VIRTCHNL_STATUS_ERR_PARAM;2107		dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id);2108		goto err_exit;2109	}2110 2111	ret = ice_vf_start_ctrl_vsi(vf);2112	if (ret && (ret != -EEXIST)) {2113		v_ret = VIRTCHNL_STATUS_ERR_PARAM;2114		dev_err(dev, "Init FDIR for VF %d failed, ret:%d\n",2115			vf->vf_id, ret);2116		goto err_exit;2117	}2118 2119	stat = kzalloc(sizeof(*stat), GFP_KERNEL);2120	if (!stat) {2121		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;2122		dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id);2123		goto err_exit;2124	}2125 2126	conf = devm_kzalloc(dev, sizeof(*conf), GFP_KERNEL);2127	if (!conf) {2128		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;2129		dev_dbg(dev, "Alloc conf for VF %d failed\n", vf->vf_id);2130		goto err_exit;2131	}2132 2133	len = sizeof(*stat);2134	ret = ice_vc_validate_fdir_fltr(vf, fltr, conf);2135	if (ret) {2136		v_ret = VIRTCHNL_STATUS_ERR_PARAM;2137		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_INVALID;2138		dev_dbg(dev, "Invalid FDIR filter from VF %d\n", vf->vf_id);2139		goto err_free_conf;2140	}2141 2142	if (fltr->validate_only) {2143		v_ret = VIRTCHNL_STATUS_SUCCESS;2144		stat->status = VIRTCHNL_FDIR_SUCCESS;2145		devm_kfree(dev, conf);2146		ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER,2147					    v_ret, (u8 *)stat, len);2148		goto exit;2149	}2150 2151	/* For raw FDIR filters created by the parser */2152	if (conf->parser_ena) {2153		ret = ice_vc_add_fdir_raw(vf, conf, &v_ret, stat, len);2154		if (ret)2155			goto err_free_conf;2156		goto exit;2157	}2158 2159	is_tun = ice_fdir_is_tunnel(conf->ttype);2160	ret = ice_vc_fdir_config_input_set(vf, fltr, conf, is_tun);2161	if (ret) {2162		v_ret = VIRTCHNL_STATUS_SUCCESS;2163		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_CONFLICT;2164		dev_err(dev, "VF %d: FDIR input set configure failed, ret:%d\n",2165			vf->vf_id, ret);2166		goto err_free_conf;2167	}2168 2169	ret = ice_vc_fdir_is_dup_fltr(vf, conf);2170	if (ret) {2171		v_ret = VIRTCHNL_STATUS_SUCCESS;2172		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_EXIST;2173		dev_dbg(dev, "VF %d: duplicated FDIR rule detected\n",2174			vf->vf_id);2175		goto err_free_conf;2176	}2177 2178	ret = ice_vc_fdir_insert_entry(vf, conf, &conf->flow_id);2179	if (ret) {2180		v_ret = VIRTCHNL_STATUS_SUCCESS;2181		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2182		dev_dbg(dev, "VF %d: insert FDIR list failed\n", vf->vf_id);2183		goto err_free_conf;2184	}2185 2186	ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_ADD_FDIR_FILTER);2187	if (ret) {2188		v_ret = VIRTCHNL_STATUS_SUCCESS;2189		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2190		dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);2191		goto err_rem_entry;2192	}2193 2194	ret = ice_vc_fdir_write_fltr(vf, conf, true, is_tun);2195	if (ret) {2196		v_ret = VIRTCHNL_STATUS_SUCCESS;2197		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2198		dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",2199			vf->vf_id, ret);2200		goto err_clr_irq;2201	}2202 2203exit:2204	kfree(stat);2205	return ret;2206 2207err_clr_irq:2208	ice_vc_fdir_clear_irq_ctx(vf);2209err_rem_entry:2210	ice_vc_fdir_remove_entry(vf, conf, conf->flow_id);2211err_free_conf:2212	devm_kfree(dev, conf);2213err_exit:2214	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_FDIR_FILTER, v_ret,2215				    (u8 *)stat, len);2216	kfree(stat);2217	return ret;2218}2219 2220/**2221 * ice_vc_del_fdir_raw - delete a raw FDIR filter for VF2222 * @vf: pointer to the VF info2223 * @conf: FDIR configuration for each filter2224 * @v_ret: the final VIRTCHNL code2225 * @stat: pointer to the VIRTCHNL_OP_DEL_FDIR_FILTER2226 * @len: length of the stat2227 *2228 * Return: 0 on success or negative errno on failure.2229 */2230static int2231ice_vc_del_fdir_raw(struct ice_vf *vf,2232		    struct virtchnl_fdir_fltr_conf *conf,2233		    enum virtchnl_status_code *v_ret,2234		    struct virtchnl_fdir_del *stat, int len)2235{2236	struct ice_vsi *vf_vsi, *ctrl_vsi;2237	enum ice_block blk = ICE_BLK_FD;2238	struct ice_fdir_prof_info *pi;2239	struct ice_pf *pf = vf->pf;2240	struct device *dev;2241	struct ice_hw *hw;2242	unsigned long id;2243	u16 vsi_num;2244	int ptg;2245	int ret;2246 2247	dev = ice_pf_to_dev(pf);2248	hw = &pf->hw;2249	*v_ret = VIRTCHNL_STATUS_ERR_PARAM;2250	stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2251 2252	id = find_first_bit(conf->prof->ptypes, ICE_FLOW_PTYPE_MAX);2253	ptg = hw->blk[ICE_BLK_FD].xlt1.t[id];2254 2255	ret = ice_vc_fdir_write_fltr(vf, conf, false, false);2256	if (ret) {2257		dev_err(dev, "VF %u: deleting FDIR raw flow rule failed: %d\n",2258			vf->vf_id, ret);2259		return ret;2260	}2261 2262	vf_vsi = ice_get_vf_vsi(vf);2263	if (!vf_vsi) {2264		dev_err(dev, "Can not get FDIR vf_vsi for VF %u\n", vf->vf_id);2265		return -ENODEV;2266	}2267 2268	ctrl_vsi = pf->vsi[vf->ctrl_vsi_idx];2269	if (!ctrl_vsi) {2270		dev_err(dev, "Can not get FDIR ctrl_vsi for VF %u\n",2271			vf->vf_id);2272		return -ENODEV;2273	}2274 2275	pi = &vf->fdir_prof_info[ptg];2276	if (pi->fdir_active_cnt != 0) {2277		pi->fdir_active_cnt--;2278		/* Remove the profile id flow if no active FDIR rule left */2279		if (!pi->fdir_active_cnt) {2280			vsi_num = ice_get_hw_vsi_num(hw, ctrl_vsi->idx);2281			ice_rem_prof_id_flow(hw, blk, vsi_num, id);2282 2283			vsi_num = ice_get_hw_vsi_num(hw, vf_vsi->idx);2284			ice_rem_prof_id_flow(hw, blk, vsi_num, id);2285		}2286	}2287 2288	conf->parser_ena = false;2289	return 0;2290}2291 2292/**2293 * ice_vc_del_fdir_fltr - delete a FDIR filter for VF by the msg buffer2294 * @vf: pointer to the VF info2295 * @msg: pointer to the msg buffer2296 *2297 * Return: 0 on success, and other on error.2298 */2299int ice_vc_del_fdir_fltr(struct ice_vf *vf, u8 *msg)2300{2301	struct virtchnl_fdir_del *fltr = (struct virtchnl_fdir_del *)msg;2302	struct virtchnl_fdir_del *stat = NULL;2303	struct virtchnl_fdir_fltr_conf *conf;2304	struct ice_vf_fdir *fdir = &vf->fdir;2305	enum virtchnl_status_code v_ret;2306	struct ice_fdir_fltr *input;2307	enum ice_fltr_ptype flow;2308	struct device *dev;2309	struct ice_pf *pf;2310	int is_tun = 0;2311	int len = 0;2312	int ret;2313 2314	pf = vf->pf;2315	dev = ice_pf_to_dev(pf);2316	ret = ice_vc_fdir_param_check(vf, fltr->vsi_id);2317	if (ret) {2318		v_ret = VIRTCHNL_STATUS_ERR_PARAM;2319		dev_dbg(dev, "Parameter check for VF %d failed\n", vf->vf_id);2320		goto err_exit;2321	}2322 2323	stat = kzalloc(sizeof(*stat), GFP_KERNEL);2324	if (!stat) {2325		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;2326		dev_dbg(dev, "Alloc stat for VF %d failed\n", vf->vf_id);2327		goto err_exit;2328	}2329 2330	len = sizeof(*stat);2331 2332	conf = ice_vc_fdir_lookup_entry(vf, fltr->flow_id);2333	if (!conf) {2334		v_ret = VIRTCHNL_STATUS_SUCCESS;2335		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NONEXIST;2336		dev_dbg(dev, "VF %d: FDIR invalid flow_id:0x%X\n",2337			vf->vf_id, fltr->flow_id);2338		goto err_exit;2339	}2340 2341	/* Just return failure when ctrl_vsi idx is invalid */2342	if (vf->ctrl_vsi_idx == ICE_NO_VSI) {2343		v_ret = VIRTCHNL_STATUS_SUCCESS;2344		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2345		dev_err(dev, "Invalid FDIR ctrl_vsi for VF %d\n", vf->vf_id);2346		goto err_exit;2347	}2348 2349	ret = ice_vc_fdir_set_irq_ctx(vf, conf, VIRTCHNL_OP_DEL_FDIR_FILTER);2350	if (ret) {2351		v_ret = VIRTCHNL_STATUS_SUCCESS;2352		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2353		dev_dbg(dev, "VF %d: set FDIR context failed\n", vf->vf_id);2354		goto err_exit;2355	}2356 2357	/* For raw FDIR filters created by the parser */2358	if (conf->parser_ena) {2359		ret = ice_vc_del_fdir_raw(vf, conf, &v_ret, stat, len);2360		if (ret)2361			goto err_del_tmr;2362		goto exit;2363	}2364 2365	is_tun = ice_fdir_is_tunnel(conf->ttype);2366	ret = ice_vc_fdir_write_fltr(vf, conf, false, is_tun);2367	if (ret) {2368		v_ret = VIRTCHNL_STATUS_SUCCESS;2369		stat->status = VIRTCHNL_FDIR_FAILURE_RULE_NORESOURCE;2370		dev_err(dev, "VF %d: writing FDIR rule failed, ret:%d\n",2371			vf->vf_id, ret);2372		goto err_del_tmr;2373	}2374 2375	/* Remove unused profiles to avoid unexpected behaviors */2376	input = &conf->input;2377	flow = input->flow_type;2378	if (fdir->fdir_fltr_cnt[flow][is_tun] == 1)2379		ice_vc_fdir_rem_prof(vf, flow, is_tun);2380 2381exit:2382	kfree(stat);2383 2384	return ret;2385 2386err_del_tmr:2387	ice_vc_fdir_clear_irq_ctx(vf);2388err_exit:2389	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_FDIR_FILTER, v_ret,2390				    (u8 *)stat, len);2391	kfree(stat);2392	return ret;2393}2394 2395/**2396 * ice_vf_fdir_init - init FDIR resource for VF2397 * @vf: pointer to the VF info2398 */2399void ice_vf_fdir_init(struct ice_vf *vf)2400{2401	struct ice_vf_fdir *fdir = &vf->fdir;2402 2403	idr_init(&fdir->fdir_rule_idr);2404	INIT_LIST_HEAD(&fdir->fdir_rule_list);2405 2406	spin_lock_init(&fdir->ctx_lock);2407	fdir->ctx_irq.flags = 0;2408	fdir->ctx_done.flags = 0;2409	ice_vc_fdir_reset_cnt_all(fdir);2410}2411 2412/**2413 * ice_vf_fdir_exit - destroy FDIR resource for VF2414 * @vf: pointer to the VF info2415 */2416void ice_vf_fdir_exit(struct ice_vf *vf)2417{2418	ice_vc_fdir_flush_entry(vf);2419	idr_destroy(&vf->fdir.fdir_rule_idr);2420	ice_vc_fdir_rem_prof_all(vf);2421	ice_vc_fdir_free_prof_all(vf);2422}2423