xref: /linux/drivers/net/ethernet/intel/ice/virt/rss.c (revision 270251b946a956cee53dacc8866b4795cc5c8925)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2022, Intel Corporation. */
3 
4 #include "ice_vf_lib_private.h"
5 #include "ice.h"
6 
7 #define FIELD_SELECTOR(proto_hdr_field) \
8 		BIT((proto_hdr_field) & PROTO_HDR_FIELD_MASK)
9 
10 struct ice_vc_hdr_match_type {
11 	u32 vc_hdr;	/* virtchnl headers (VIRTCHNL_PROTO_HDR_XXX) */
12 	u32 ice_hdr;	/* ice headers (ICE_FLOW_SEG_HDR_XXX) */
13 };
14 
15 static const struct ice_vc_hdr_match_type ice_vc_hdr_list[] = {
16 	{VIRTCHNL_PROTO_HDR_NONE,	ICE_FLOW_SEG_HDR_NONE},
17 	{VIRTCHNL_PROTO_HDR_ETH,	ICE_FLOW_SEG_HDR_ETH},
18 	{VIRTCHNL_PROTO_HDR_S_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
19 	{VIRTCHNL_PROTO_HDR_C_VLAN,	ICE_FLOW_SEG_HDR_VLAN},
20 	{VIRTCHNL_PROTO_HDR_IPV4,	ICE_FLOW_SEG_HDR_IPV4 |
21 					ICE_FLOW_SEG_HDR_IPV_OTHER},
22 	{VIRTCHNL_PROTO_HDR_IPV6,	ICE_FLOW_SEG_HDR_IPV6 |
23 					ICE_FLOW_SEG_HDR_IPV_OTHER},
24 	{VIRTCHNL_PROTO_HDR_TCP,	ICE_FLOW_SEG_HDR_TCP},
25 	{VIRTCHNL_PROTO_HDR_UDP,	ICE_FLOW_SEG_HDR_UDP},
26 	{VIRTCHNL_PROTO_HDR_SCTP,	ICE_FLOW_SEG_HDR_SCTP},
27 	{VIRTCHNL_PROTO_HDR_PPPOE,	ICE_FLOW_SEG_HDR_PPPOE},
28 	{VIRTCHNL_PROTO_HDR_GTPU_IP,	ICE_FLOW_SEG_HDR_GTPU_IP},
29 	{VIRTCHNL_PROTO_HDR_GTPU_EH,	ICE_FLOW_SEG_HDR_GTPU_EH},
30 	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_DWN,
31 					ICE_FLOW_SEG_HDR_GTPU_DWN},
32 	{VIRTCHNL_PROTO_HDR_GTPU_EH_PDU_UP,
33 					ICE_FLOW_SEG_HDR_GTPU_UP},
34 	{VIRTCHNL_PROTO_HDR_L2TPV3,	ICE_FLOW_SEG_HDR_L2TPV3},
35 	{VIRTCHNL_PROTO_HDR_ESP,	ICE_FLOW_SEG_HDR_ESP},
36 	{VIRTCHNL_PROTO_HDR_AH,		ICE_FLOW_SEG_HDR_AH},
37 	{VIRTCHNL_PROTO_HDR_PFCP,	ICE_FLOW_SEG_HDR_PFCP_SESSION},
38 };
39 
40 struct ice_vc_hash_field_match_type {
41 	u32 vc_hdr;		/* virtchnl headers
42 				 * (VIRTCHNL_PROTO_HDR_XXX)
43 				 */
44 	u32 vc_hash_field;	/* virtchnl hash fields selector
45 				 * FIELD_SELECTOR((VIRTCHNL_PROTO_HDR_ETH_XXX))
46 				 */
47 	u64 ice_hash_field;	/* ice hash fields
48 				 * (BIT_ULL(ICE_FLOW_FIELD_IDX_XXX))
49 				 */
50 };
51 
52 static const struct
53 ice_vc_hash_field_match_type ice_vc_hash_field_list[] = {
54 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC),
55 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_SA)},
56 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
57 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_DA)},
58 	{VIRTCHNL_PROTO_HDR_ETH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC) |
59 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST),
60 		ICE_FLOW_HASH_ETH},
61 	{VIRTCHNL_PROTO_HDR_ETH,
62 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_ETHERTYPE),
63 		BIT_ULL(ICE_FLOW_FIELD_IDX_ETH_TYPE)},
64 	{VIRTCHNL_PROTO_HDR_S_VLAN,
65 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_S_VLAN_ID),
66 		BIT_ULL(ICE_FLOW_FIELD_IDX_S_VLAN)},
67 	{VIRTCHNL_PROTO_HDR_C_VLAN,
68 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_C_VLAN_ID),
69 		BIT_ULL(ICE_FLOW_FIELD_IDX_C_VLAN)},
70 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC),
71 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA)},
72 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
73 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA)},
74 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
75 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST),
76 		ICE_FLOW_HASH_IPV4},
77 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
78 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
79 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_SA) |
80 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
81 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
82 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
83 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_DA) |
84 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
85 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) |
86 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) |
87 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
88 		ICE_FLOW_HASH_IPV4 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
89 	{VIRTCHNL_PROTO_HDR_IPV4, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT),
90 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV4_PROT)},
91 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC),
92 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA)},
93 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
94 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA)},
95 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
96 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST),
97 		ICE_FLOW_HASH_IPV6},
98 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
99 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
100 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_SA) |
101 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
102 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
103 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
104 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_DA) |
105 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
106 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) |
107 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) |
108 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
109 		ICE_FLOW_HASH_IPV6 | BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
110 	{VIRTCHNL_PROTO_HDR_IPV6, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT),
111 		BIT_ULL(ICE_FLOW_FIELD_IDX_IPV6_PROT)},
112 	{VIRTCHNL_PROTO_HDR_TCP,
113 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT),
114 		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_SRC_PORT)},
115 	{VIRTCHNL_PROTO_HDR_TCP,
116 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
117 		BIT_ULL(ICE_FLOW_FIELD_IDX_TCP_DST_PORT)},
118 	{VIRTCHNL_PROTO_HDR_TCP,
119 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) |
120 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT),
121 		ICE_FLOW_HASH_TCP_PORT},
122 	{VIRTCHNL_PROTO_HDR_UDP,
123 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT),
124 		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_SRC_PORT)},
125 	{VIRTCHNL_PROTO_HDR_UDP,
126 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
127 		BIT_ULL(ICE_FLOW_FIELD_IDX_UDP_DST_PORT)},
128 	{VIRTCHNL_PROTO_HDR_UDP,
129 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) |
130 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT),
131 		ICE_FLOW_HASH_UDP_PORT},
132 	{VIRTCHNL_PROTO_HDR_SCTP,
133 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT),
134 		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT)},
135 	{VIRTCHNL_PROTO_HDR_SCTP,
136 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
137 		BIT_ULL(ICE_FLOW_FIELD_IDX_SCTP_DST_PORT)},
138 	{VIRTCHNL_PROTO_HDR_SCTP,
139 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) |
140 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT),
141 		ICE_FLOW_HASH_SCTP_PORT},
142 	{VIRTCHNL_PROTO_HDR_PPPOE,
143 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PPPOE_SESS_ID),
144 		BIT_ULL(ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID)},
145 	{VIRTCHNL_PROTO_HDR_GTPU_IP,
146 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_GTPU_IP_TEID),
147 		BIT_ULL(ICE_FLOW_FIELD_IDX_GTPU_IP_TEID)},
148 	{VIRTCHNL_PROTO_HDR_L2TPV3,
149 		FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID),
150 		BIT_ULL(ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID)},
151 	{VIRTCHNL_PROTO_HDR_ESP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ESP_SPI),
152 		BIT_ULL(ICE_FLOW_FIELD_IDX_ESP_SPI)},
153 	{VIRTCHNL_PROTO_HDR_AH, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_AH_SPI),
154 		BIT_ULL(ICE_FLOW_FIELD_IDX_AH_SPI)},
155 	{VIRTCHNL_PROTO_HDR_PFCP, FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID),
156 		BIT_ULL(ICE_FLOW_FIELD_IDX_PFCP_SEID)},
157 };
158 
159 /**
160  * ice_vc_validate_pattern
161  * @vf: pointer to the VF info
162  * @proto: virtchnl protocol headers
163  *
164  * validate the pattern is supported or not.
165  *
166  * Return: true on success, false on error.
167  */
168 bool
169 ice_vc_validate_pattern(struct ice_vf *vf, struct virtchnl_proto_hdrs *proto)
170 {
171 	bool is_ipv4 = false;
172 	bool is_ipv6 = false;
173 	bool is_udp = false;
174 	u16 ptype = -1;
175 	int i = 0;
176 
177 	while (i < proto->count &&
178 	       proto->proto_hdr[i].type != VIRTCHNL_PROTO_HDR_NONE) {
179 		switch (proto->proto_hdr[i].type) {
180 		case VIRTCHNL_PROTO_HDR_ETH:
181 			ptype = ICE_PTYPE_MAC_PAY;
182 			break;
183 		case VIRTCHNL_PROTO_HDR_IPV4:
184 			ptype = ICE_PTYPE_IPV4_PAY;
185 			is_ipv4 = true;
186 			break;
187 		case VIRTCHNL_PROTO_HDR_IPV6:
188 			ptype = ICE_PTYPE_IPV6_PAY;
189 			is_ipv6 = true;
190 			break;
191 		case VIRTCHNL_PROTO_HDR_UDP:
192 			if (is_ipv4)
193 				ptype = ICE_PTYPE_IPV4_UDP_PAY;
194 			else if (is_ipv6)
195 				ptype = ICE_PTYPE_IPV6_UDP_PAY;
196 			is_udp = true;
197 			break;
198 		case VIRTCHNL_PROTO_HDR_TCP:
199 			if (is_ipv4)
200 				ptype = ICE_PTYPE_IPV4_TCP_PAY;
201 			else if (is_ipv6)
202 				ptype = ICE_PTYPE_IPV6_TCP_PAY;
203 			break;
204 		case VIRTCHNL_PROTO_HDR_SCTP:
205 			if (is_ipv4)
206 				ptype = ICE_PTYPE_IPV4_SCTP_PAY;
207 			else if (is_ipv6)
208 				ptype = ICE_PTYPE_IPV6_SCTP_PAY;
209 			break;
210 		case VIRTCHNL_PROTO_HDR_GTPU_IP:
211 		case VIRTCHNL_PROTO_HDR_GTPU_EH:
212 			if (is_ipv4)
213 				ptype = ICE_MAC_IPV4_GTPU;
214 			else if (is_ipv6)
215 				ptype = ICE_MAC_IPV6_GTPU;
216 			goto out;
217 		case VIRTCHNL_PROTO_HDR_L2TPV3:
218 			if (is_ipv4)
219 				ptype = ICE_MAC_IPV4_L2TPV3;
220 			else if (is_ipv6)
221 				ptype = ICE_MAC_IPV6_L2TPV3;
222 			goto out;
223 		case VIRTCHNL_PROTO_HDR_ESP:
224 			if (is_ipv4)
225 				ptype = is_udp ? ICE_MAC_IPV4_NAT_T_ESP :
226 						ICE_MAC_IPV4_ESP;
227 			else if (is_ipv6)
228 				ptype = is_udp ? ICE_MAC_IPV6_NAT_T_ESP :
229 						ICE_MAC_IPV6_ESP;
230 			goto out;
231 		case VIRTCHNL_PROTO_HDR_AH:
232 			if (is_ipv4)
233 				ptype = ICE_MAC_IPV4_AH;
234 			else if (is_ipv6)
235 				ptype = ICE_MAC_IPV6_AH;
236 			goto out;
237 		case VIRTCHNL_PROTO_HDR_PFCP:
238 			if (is_ipv4)
239 				ptype = ICE_MAC_IPV4_PFCP_SESSION;
240 			else if (is_ipv6)
241 				ptype = ICE_MAC_IPV6_PFCP_SESSION;
242 			goto out;
243 		default:
244 			break;
245 		}
246 		i++;
247 	}
248 
249 out:
250 	return ice_hw_ptype_ena(&vf->pf->hw, ptype);
251 }
252 
253 /**
254  * ice_vc_parse_rss_cfg - parses hash fields and headers from
255  * a specific virtchnl RSS cfg
256  * @hw: pointer to the hardware
257  * @rss_cfg: pointer to the virtchnl RSS cfg
258  * @hash_cfg: pointer to the HW hash configuration
259  *
260  * Return true if all the protocol header and hash fields in the RSS cfg could
261  * be parsed, else return false
262  *
263  * This function parses the virtchnl RSS cfg to be the intended
264  * hash fields and the intended header for RSS configuration
265  */
266 static bool ice_vc_parse_rss_cfg(struct ice_hw *hw,
267 				 struct virtchnl_rss_cfg *rss_cfg,
268 				 struct ice_rss_hash_cfg *hash_cfg)
269 {
270 	const struct ice_vc_hash_field_match_type *hf_list;
271 	const struct ice_vc_hdr_match_type *hdr_list;
272 	int i, hf_list_len, hdr_list_len;
273 	u32 *addl_hdrs = &hash_cfg->addl_hdrs;
274 	u64 *hash_flds = &hash_cfg->hash_flds;
275 
276 	/* set outer layer RSS as default */
277 	hash_cfg->hdr_type = ICE_RSS_OUTER_HEADERS;
278 
279 	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
280 		hash_cfg->symm = true;
281 	else
282 		hash_cfg->symm = false;
283 
284 	hf_list = ice_vc_hash_field_list;
285 	hf_list_len = ARRAY_SIZE(ice_vc_hash_field_list);
286 	hdr_list = ice_vc_hdr_list;
287 	hdr_list_len = ARRAY_SIZE(ice_vc_hdr_list);
288 
289 	for (i = 0; i < rss_cfg->proto_hdrs.count; i++) {
290 		struct virtchnl_proto_hdr *proto_hdr =
291 					&rss_cfg->proto_hdrs.proto_hdr[i];
292 		bool hdr_found = false;
293 		int j;
294 
295 		/* Find matched ice headers according to virtchnl headers. */
296 		for (j = 0; j < hdr_list_len; j++) {
297 			struct ice_vc_hdr_match_type hdr_map = hdr_list[j];
298 
299 			if (proto_hdr->type == hdr_map.vc_hdr) {
300 				*addl_hdrs |= hdr_map.ice_hdr;
301 				hdr_found = true;
302 			}
303 		}
304 
305 		if (!hdr_found)
306 			return false;
307 
308 		/* Find matched ice hash fields according to
309 		 * virtchnl hash fields.
310 		 */
311 		for (j = 0; j < hf_list_len; j++) {
312 			struct ice_vc_hash_field_match_type hf_map = hf_list[j];
313 
314 			if (proto_hdr->type == hf_map.vc_hdr &&
315 			    proto_hdr->field_selector == hf_map.vc_hash_field) {
316 				*hash_flds |= hf_map.ice_hash_field;
317 				break;
318 			}
319 		}
320 	}
321 
322 	return true;
323 }
324 
325 /**
326  * ice_vf_adv_rss_offload_ena - determine if capabilities support advanced
327  * RSS offloads
328  * @caps: VF driver negotiated capabilities
329  *
330  * Return true if VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF capability is set,
331  * else return false
332  */
333 static bool ice_vf_adv_rss_offload_ena(u32 caps)
334 {
335 	return !!(caps & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF);
336 }
337 
338 /**
339  * ice_vc_handle_rss_cfg
340  * @vf: pointer to the VF info
341  * @msg: pointer to the message buffer
342  * @add: add a RSS config if true, otherwise delete a RSS config
343  *
344  * This function adds/deletes a RSS config
345  */
346 static int ice_vc_handle_rss_cfg(struct ice_vf *vf, u8 *msg, bool add)
347 {
348 	u32 v_opcode = add ? VIRTCHNL_OP_ADD_RSS_CFG : VIRTCHNL_OP_DEL_RSS_CFG;
349 	struct virtchnl_rss_cfg *rss_cfg = (struct virtchnl_rss_cfg *)msg;
350 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
351 	struct device *dev = ice_pf_to_dev(vf->pf);
352 	struct ice_hw *hw = &vf->pf->hw;
353 	struct ice_vsi *vsi;
354 
355 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
356 		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS is not supported by the PF\n",
357 			vf->vf_id);
358 		v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
359 		goto error_param;
360 	}
361 
362 	if (!ice_vf_adv_rss_offload_ena(vf->driver_caps)) {
363 		dev_dbg(dev, "VF %d attempting to configure RSS, but Advanced RSS offload is not supported\n",
364 			vf->vf_id);
365 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
366 		goto error_param;
367 	}
368 
369 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
370 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
371 		goto error_param;
372 	}
373 
374 	if (rss_cfg->proto_hdrs.count > VIRTCHNL_MAX_NUM_PROTO_HDRS ||
375 	    rss_cfg->rss_algorithm < VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC ||
376 	    rss_cfg->rss_algorithm > VIRTCHNL_RSS_ALG_XOR_SYMMETRIC) {
377 		dev_dbg(dev, "VF %d attempting to configure RSS, but RSS configuration is not valid\n",
378 			vf->vf_id);
379 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
380 		goto error_param;
381 	}
382 
383 	vsi = ice_get_vf_vsi(vf);
384 	if (!vsi) {
385 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
386 		goto error_param;
387 	}
388 
389 	if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) {
390 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
391 		goto error_param;
392 	}
393 
394 	if (rss_cfg->rss_algorithm == VIRTCHNL_RSS_ALG_R_ASYMMETRIC) {
395 		struct ice_vsi_ctx *ctx;
396 		u8 lut_type, hash_type;
397 		int status;
398 
399 		lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_VSI;
400 		hash_type = add ? ICE_AQ_VSI_Q_OPT_RSS_HASH_XOR :
401 				ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
402 
403 		ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
404 		if (!ctx) {
405 			v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
406 			goto error_param;
407 		}
408 
409 		ctx->info.q_opt_rss =
410 			FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_LUT_M, lut_type) |
411 			FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hash_type);
412 
413 		/* Preserve existing queueing option setting */
414 		ctx->info.q_opt_rss |= (vsi->info.q_opt_rss &
415 					  ICE_AQ_VSI_Q_OPT_RSS_GBL_LUT_M);
416 		ctx->info.q_opt_tc = vsi->info.q_opt_tc;
417 		ctx->info.q_opt_flags = vsi->info.q_opt_rss;
418 
419 		ctx->info.valid_sections =
420 				cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID);
421 
422 		status = ice_update_vsi(hw, vsi->idx, ctx, NULL);
423 		if (status) {
424 			dev_err(dev, "update VSI for RSS failed, err %d aq_err %s\n",
425 				status, libie_aq_str(hw->adminq.sq_last_status));
426 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
427 		} else {
428 			vsi->info.q_opt_rss = ctx->info.q_opt_rss;
429 		}
430 
431 		kfree(ctx);
432 	} else {
433 		struct ice_rss_hash_cfg cfg;
434 
435 		/* Only check for none raw pattern case */
436 		if (!ice_vc_validate_pattern(vf, &rss_cfg->proto_hdrs)) {
437 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
438 			goto error_param;
439 		}
440 		cfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE;
441 		cfg.hash_flds = ICE_HASH_INVALID;
442 		cfg.hdr_type = ICE_RSS_ANY_HEADERS;
443 
444 		if (!ice_vc_parse_rss_cfg(hw, rss_cfg, &cfg)) {
445 			v_ret = VIRTCHNL_STATUS_ERR_PARAM;
446 			goto error_param;
447 		}
448 
449 		if (add) {
450 			if (ice_add_rss_cfg(hw, vsi, &cfg)) {
451 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
452 				dev_err(dev, "ice_add_rss_cfg failed for vsi = %d, v_ret = %d\n",
453 					vsi->vsi_num, v_ret);
454 			}
455 		} else {
456 			int status;
457 
458 			status = ice_rem_rss_cfg(hw, vsi->idx, &cfg);
459 			/* We just ignore -ENOENT, because if two configurations
460 			 * share the same profile remove one of them actually
461 			 * removes both, since the profile is deleted.
462 			 */
463 			if (status && status != -ENOENT) {
464 				v_ret = VIRTCHNL_STATUS_ERR_PARAM;
465 				dev_err(dev, "ice_rem_rss_cfg failed for VF ID:%d, error:%d\n",
466 					vf->vf_id, status);
467 			}
468 		}
469 	}
470 
471 error_param:
472 	return ice_vc_send_msg_to_vf(vf, v_opcode, v_ret, NULL, 0);
473 }
474 
475 /**
476  * ice_vc_config_rss_key
477  * @vf: pointer to the VF info
478  * @msg: pointer to the msg buffer
479  *
480  * Configure the VF's RSS key
481  */
482 static int ice_vc_config_rss_key(struct ice_vf *vf, u8 *msg)
483 {
484 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
485 	struct virtchnl_rss_key *vrk =
486 		(struct virtchnl_rss_key *)msg;
487 	struct ice_vsi *vsi;
488 
489 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
490 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
491 		goto error_param;
492 	}
493 
494 	if (!ice_vc_isvalid_vsi_id(vf, vrk->vsi_id)) {
495 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
496 		goto error_param;
497 	}
498 
499 	if (vrk->key_len != ICE_VSIQF_HKEY_ARRAY_SIZE) {
500 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
501 		goto error_param;
502 	}
503 
504 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
505 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
506 		goto error_param;
507 	}
508 
509 	vsi = ice_get_vf_vsi(vf);
510 	if (!vsi) {
511 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
512 		goto error_param;
513 	}
514 
515 	if (ice_set_rss_key(vsi, vrk->key))
516 		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
517 error_param:
518 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_KEY, v_ret,
519 				     NULL, 0);
520 }
521 
522 /**
523  * ice_vc_config_rss_lut
524  * @vf: pointer to the VF info
525  * @msg: pointer to the msg buffer
526  *
527  * Configure the VF's RSS LUT
528  */
529 static int ice_vc_config_rss_lut(struct ice_vf *vf, u8 *msg)
530 {
531 	struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg;
532 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
533 	struct ice_vsi *vsi;
534 
535 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
536 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
537 		goto error_param;
538 	}
539 
540 	if (!ice_vc_isvalid_vsi_id(vf, vrl->vsi_id)) {
541 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
542 		goto error_param;
543 	}
544 
545 	if (vrl->lut_entries != ICE_LUT_VSI_SIZE) {
546 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
547 		goto error_param;
548 	}
549 
550 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
551 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
552 		goto error_param;
553 	}
554 
555 	vsi = ice_get_vf_vsi(vf);
556 	if (!vsi) {
557 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
558 		goto error_param;
559 	}
560 
561 	if (ice_set_rss_lut(vsi, vrl->lut, ICE_LUT_VSI_SIZE))
562 		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
563 error_param:
564 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_LUT, v_ret,
565 				     NULL, 0);
566 }
567 
568 /**
569  * ice_vc_config_rss_hfunc
570  * @vf: pointer to the VF info
571  * @msg: pointer to the msg buffer
572  *
573  * Configure the VF's RSS Hash function
574  */
575 static int ice_vc_config_rss_hfunc(struct ice_vf *vf, u8 *msg)
576 {
577 	struct virtchnl_rss_hfunc *vrh = (struct virtchnl_rss_hfunc *)msg;
578 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
579 	u8 hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ;
580 	struct ice_vsi *vsi;
581 
582 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
583 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
584 		goto error_param;
585 	}
586 
587 	if (!ice_vc_isvalid_vsi_id(vf, vrh->vsi_id)) {
588 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
589 		goto error_param;
590 	}
591 
592 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
593 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
594 		goto error_param;
595 	}
596 
597 	vsi = ice_get_vf_vsi(vf);
598 	if (!vsi) {
599 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
600 		goto error_param;
601 	}
602 
603 	if (vrh->rss_algorithm == VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC)
604 		hfunc = ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ;
605 
606 	if (ice_set_rss_hfunc(vsi, hfunc))
607 		v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR;
608 error_param:
609 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_RSS_HFUNC, v_ret,
610 				     NULL, 0);
611 }
612 
613 /**
614  * ice_vc_get_rss_hashcfg - return the RSS Hash configuration
615  * @vf: pointer to the VF info
616  */
617 static int ice_vc_get_rss_hashcfg(struct ice_vf *vf)
618 {
619 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
620 	struct virtchnl_rss_hashcfg *vrh = NULL;
621 	int len = 0, ret;
622 
623 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
624 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
625 		goto err;
626 	}
627 
628 	if (!test_bit(ICE_FLAG_RSS_ENA, vf->pf->flags)) {
629 		dev_err(ice_pf_to_dev(vf->pf), "RSS not supported by PF\n");
630 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
631 		goto err;
632 	}
633 
634 	len = sizeof(struct virtchnl_rss_hashcfg);
635 	vrh = kzalloc(len, GFP_KERNEL);
636 	if (!vrh) {
637 		v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY;
638 		len = 0;
639 		goto err;
640 	}
641 
642 	vrh->hashcfg = ICE_DEFAULT_RSS_HASHCFG;
643 err:
644 	/* send the response back to the VF */
645 	ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_RSS_HASHCFG_CAPS, v_ret,
646 				    (u8 *)vrh, len);
647 	kfree(vrh);
648 	return ret;
649 }
650 
651 /**
652  * ice_vc_set_rss_hashcfg - set RSS Hash configuration bits for the VF
653  * @vf: pointer to the VF info
654  * @msg: pointer to the msg buffer
655  */
656 static int ice_vc_set_rss_hashcfg(struct ice_vf *vf, u8 *msg)
657 {
658 	struct virtchnl_rss_hashcfg *vrh = (struct virtchnl_rss_hashcfg *)msg;
659 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
660 	struct ice_pf *pf = vf->pf;
661 	struct ice_vsi *vsi;
662 	struct device *dev;
663 	int status;
664 
665 	dev = ice_pf_to_dev(pf);
666 
667 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
668 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
669 		goto err;
670 	}
671 
672 	if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
673 		dev_err(dev, "RSS not supported by PF\n");
674 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
675 		goto err;
676 	}
677 
678 	vsi = ice_get_vf_vsi(vf);
679 	if (!vsi) {
680 		v_ret = VIRTCHNL_STATUS_ERR_PARAM;
681 		goto err;
682 	}
683 
684 	/* clear all previously programmed RSS configuration to allow VF drivers
685 	 * the ability to customize the RSS configuration and/or completely
686 	 * disable RSS
687 	 */
688 	status = ice_rem_vsi_rss_cfg(&pf->hw, vsi->idx);
689 	if (status && !vrh->hashcfg) {
690 		/* only report failure to clear the current RSS configuration if
691 		 * that was clearly the VF's intention (i.e. vrh->hashcfg = 0)
692 		 */
693 		v_ret = ice_err_to_virt_err(status);
694 		goto err;
695 	} else if (status) {
696 		/* allow the VF to update the RSS configuration even on failure
697 		 * to clear the current RSS confguration in an attempt to keep
698 		 * RSS in a working state
699 		 */
700 		dev_warn(dev, "Failed to clear the RSS configuration for VF %u\n",
701 			 vf->vf_id);
702 	}
703 
704 	if (vrh->hashcfg) {
705 		status = ice_add_avf_rss_cfg(&pf->hw, vsi, vrh->hashcfg);
706 		v_ret = ice_err_to_virt_err(status);
707 	}
708 
709 	/* save the requested VF configuration */
710 	if (!v_ret)
711 		vf->rss_hashcfg = vrh->hashcfg;
712 
713 	/* send the response to the VF */
714 err:
715 	return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_SET_RSS_HASHCFG, v_ret,
716 				     NULL, 0);
717 }
718 
719