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