xref: /dpdk/drivers/net/hns3/hns3_rss.c (revision 72206323a5dd3182b13f61b25a64abdddfee595c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 HiSilicon Limited.
3  */
4 
5 #include <rte_ethdev.h>
6 #include <rte_io.h>
7 #include <rte_malloc.h>
8 
9 #include "hns3_ethdev.h"
10 #include "hns3_logs.h"
11 
12 /* Default hash keys */
13 const uint8_t hns3_hash_key[] = {
14 	0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
15 	0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
16 	0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
17 	0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
18 	0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA
19 };
20 
21 enum hns3_tuple_field {
22 	/* IPV4_TCP ENABLE FIELD */
23 	HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D = 0,
24 	HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S,
25 	HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D,
26 	HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S,
27 
28 	/* IPV4_UDP ENABLE FIELD */
29 	HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D = 8,
30 	HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S,
31 	HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D,
32 	HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S,
33 
34 	/* IPV4_SCTP ENABLE FIELD */
35 	HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D = 16,
36 	HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S,
37 	HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D,
38 	HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S,
39 	HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER,
40 
41 	/* IPV4 ENABLE FIELD */
42 	HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D = 24,
43 	HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S,
44 	HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D,
45 	HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S,
46 
47 	/* IPV6_TCP ENABLE FIELD */
48 	HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D = 32,
49 	HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S,
50 	HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D,
51 	HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S,
52 
53 	/* IPV6_UDP ENABLE FIELD */
54 	HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D = 40,
55 	HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S,
56 	HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D,
57 	HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S,
58 
59 	/* IPV6_SCTP ENABLE FIELD */
60 	HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_D = 48,
61 	HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_S,
62 	HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D,
63 	HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S,
64 	HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER,
65 
66 	/* IPV6 ENABLE FIELD */
67 	HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D = 56,
68 	HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S,
69 	HNS3_RSS_FIELD_IPV6_FRAG_IP_D,
70 	HNS3_RSS_FIELD_IPV6_FRAG_IP_S
71 };
72 
73 static const struct {
74 	uint64_t rss_types;
75 	uint64_t rss_field;
76 } hns3_set_tuple_table[] = {
77 	{ RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_L3_SRC_ONLY,
78 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S) },
79 	{ RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_L3_DST_ONLY,
80 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D) },
81 	{ RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L3_SRC_ONLY,
82 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S) },
83 	{ RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L3_DST_ONLY,
84 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D) },
85 	{ RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L4_SRC_ONLY,
86 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S) },
87 	{ RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_L4_DST_ONLY,
88 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D) },
89 	{ RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L3_SRC_ONLY,
90 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S) },
91 	{ RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L3_DST_ONLY,
92 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D) },
93 	{ RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L4_SRC_ONLY,
94 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S) },
95 	{ RTE_ETH_RSS_NONFRAG_IPV4_UDP | RTE_ETH_RSS_L4_DST_ONLY,
96 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D) },
97 	{ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L3_SRC_ONLY,
98 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S) },
99 	{ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L3_DST_ONLY,
100 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D) },
101 	{ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L4_SRC_ONLY,
102 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S) },
103 	{ RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_L4_DST_ONLY,
104 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D) },
105 	{ RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_L3_SRC_ONLY,
106 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) },
107 	{ RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_L3_DST_ONLY,
108 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) },
109 	{ RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_L3_SRC_ONLY,
110 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_S) },
111 	{ RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_L3_DST_ONLY,
112 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D) },
113 	{ RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L3_SRC_ONLY,
114 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S) },
115 	{ RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L3_DST_ONLY,
116 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D) },
117 	{ RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L4_SRC_ONLY,
118 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S) },
119 	{ RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_L4_DST_ONLY,
120 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D) },
121 	{ RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L3_SRC_ONLY,
122 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S) },
123 	{ RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L3_DST_ONLY,
124 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D) },
125 	{ RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L4_SRC_ONLY,
126 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S) },
127 	{ RTE_ETH_RSS_NONFRAG_IPV6_UDP | RTE_ETH_RSS_L4_DST_ONLY,
128 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D) },
129 	{ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L3_SRC_ONLY,
130 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S) },
131 	{ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L3_DST_ONLY,
132 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D) },
133 	{ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L4_SRC_ONLY,
134 	  BIT_ULL(HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_S) },
135 	{ RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_L4_DST_ONLY,
136 	  BIT_ULL(HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_D) },
137 	{ RTE_ETH_RSS_NONFRAG_IPV6_OTHER | RTE_ETH_RSS_L3_SRC_ONLY,
138 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) },
139 	{ RTE_ETH_RSS_NONFRAG_IPV6_OTHER | RTE_ETH_RSS_L3_DST_ONLY,
140 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) },
141 };
142 
143 static const struct {
144 	uint64_t rss_types;
145 	uint64_t rss_field;
146 } hns3_set_rss_types[] = {
147 	{ RTE_ETH_RSS_FRAG_IPV4, BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_D) |
148 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_FRAG_IP_S) },
149 	{ RTE_ETH_RSS_NONFRAG_IPV4_TCP, BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_S) |
150 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_IP_D) |
151 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_S) |
152 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_TCP_EN_TCP_D) },
153 	{ RTE_ETH_RSS_NONFRAG_IPV4_UDP, BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_S) |
154 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_IP_D) |
155 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_S) |
156 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_UDP_EN_UDP_D) },
157 	{ RTE_ETH_RSS_NONFRAG_IPV4_SCTP, BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_S) |
158 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_IP_D) |
159 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_S) |
160 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_D) |
161 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_SCTP_EN_SCTP_VER) },
162 	{ RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
163 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_S) |
164 	  BIT_ULL(HNS3_RSS_FIELD_IPV4_EN_NONFRAG_IP_D) },
165 	{ RTE_ETH_RSS_FRAG_IPV6, BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_S) |
166 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_FRAG_IP_D) },
167 	{ RTE_ETH_RSS_NONFRAG_IPV6_TCP, BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_S) |
168 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_IP_D) |
169 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_S) |
170 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_TCP_EN_TCP_D) },
171 	{ RTE_ETH_RSS_NONFRAG_IPV6_UDP, BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_S) |
172 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_IP_D) |
173 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_S) |
174 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_UDP_EN_UDP_D) },
175 	{ RTE_ETH_RSS_NONFRAG_IPV6_SCTP, BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_S) |
176 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_IP_D) |
177 	  BIT_ULL(HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_D) |
178 	  BIT_ULL(HNS3_RSS_FILED_IPV6_SCTP_EN_SCTP_S) |
179 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_SCTP_EN_SCTP_VER) },
180 	{ RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
181 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_S) |
182 	  BIT_ULL(HNS3_RSS_FIELD_IPV6_NONFRAG_IP_D) }
183 };
184 
185 /*
186  * rss_generic_config command function, opcode:0x0D01.
187  * Used to set algorithm, key_offset and hash key of rss.
188  */
189 int
190 hns3_rss_set_algo_key(struct hns3_hw *hw, const uint8_t *key)
191 {
192 #define HNS3_KEY_OFFSET_MAX	3
193 #define HNS3_SET_HASH_KEY_BYTE_FOUR	2
194 
195 	struct hns3_rss_generic_config_cmd *req;
196 	struct hns3_cmd_desc desc;
197 	uint32_t key_offset, key_size;
198 	const uint8_t *key_cur;
199 	uint8_t cur_offset;
200 	int ret;
201 
202 	req = (struct hns3_rss_generic_config_cmd *)desc.data;
203 
204 	/*
205 	 * key_offset=0, hash key byte0~15 is set to hardware.
206 	 * key_offset=1, hash key byte16~31 is set to hardware.
207 	 * key_offset=2, hash key byte32~39 is set to hardware.
208 	 */
209 	for (key_offset = 0; key_offset < HNS3_KEY_OFFSET_MAX; key_offset++) {
210 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_GENERIC_CONFIG,
211 					  false);
212 
213 		req->hash_config |=
214 			(hw->rss_info.hash_algo & HNS3_RSS_HASH_ALGO_MASK);
215 		req->hash_config |= (key_offset << HNS3_RSS_HASH_KEY_OFFSET_B);
216 
217 		if (key_offset == HNS3_SET_HASH_KEY_BYTE_FOUR)
218 			key_size = HNS3_RSS_KEY_SIZE - HNS3_RSS_HASH_KEY_NUM *
219 			HNS3_SET_HASH_KEY_BYTE_FOUR;
220 		else
221 			key_size = HNS3_RSS_HASH_KEY_NUM;
222 
223 		cur_offset = key_offset * HNS3_RSS_HASH_KEY_NUM;
224 		key_cur = key + cur_offset;
225 		memcpy(req->hash_key, key_cur, key_size);
226 
227 		ret = hns3_cmd_send(hw, &desc, 1);
228 		if (ret) {
229 			hns3_err(hw, "Configure RSS algo key failed %d", ret);
230 			return ret;
231 		}
232 	}
233 	/* Update the shadow RSS key with user specified */
234 	memcpy(hw->rss_info.key, key, HNS3_RSS_KEY_SIZE);
235 	return 0;
236 }
237 
238 /*
239  * rss_indirection_table command function, opcode:0x0D07.
240  * Used to configure the indirection table of rss.
241  */
242 int
243 hns3_set_rss_indir_table(struct hns3_hw *hw, uint16_t *indir, uint16_t size)
244 {
245 	struct hns3_rss_indirection_table_cmd *req;
246 	struct hns3_cmd_desc desc;
247 	uint8_t qid_msb_off;
248 	uint8_t qid_msb_val;
249 	uint16_t q_id;
250 	uint16_t i, j;
251 	int ret;
252 
253 	req = (struct hns3_rss_indirection_table_cmd *)desc.data;
254 
255 	for (i = 0; i < size / HNS3_RSS_CFG_TBL_SIZE; i++) {
256 		hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INDIR_TABLE,
257 					  false);
258 		req->start_table_index =
259 				rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE);
260 		req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK);
261 		for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) {
262 			q_id = indir[i * HNS3_RSS_CFG_TBL_SIZE + j];
263 			req->rss_result_l[j] = q_id & 0xff;
264 
265 			qid_msb_off =
266 				j * HNS3_RSS_CFG_TBL_BW_H / HNS3_BITS_PER_BYTE;
267 			qid_msb_val = (q_id >> HNS3_RSS_CFG_TBL_BW_L & 0x1)
268 					<< (j * HNS3_RSS_CFG_TBL_BW_H %
269 					HNS3_BITS_PER_BYTE);
270 			req->rss_result_h[qid_msb_off] |= qid_msb_val;
271 		}
272 
273 		ret = hns3_cmd_send(hw, &desc, 1);
274 		if (ret) {
275 			hns3_err(hw,
276 				 "Sets RSS indirection table failed %d size %u",
277 				 ret, size);
278 			return ret;
279 		}
280 	}
281 
282 	/* Update redirection table of hw */
283 	memcpy(hw->rss_info.rss_indirection_tbl, indir,
284 	       sizeof(uint16_t) * size);
285 
286 	return 0;
287 }
288 
289 int
290 hns3_rss_reset_indir_table(struct hns3_hw *hw)
291 {
292 	uint16_t *lut;
293 	int ret;
294 
295 	lut = rte_zmalloc("hns3_rss_lut",
296 			  hw->rss_ind_tbl_size * sizeof(uint16_t), 0);
297 	if (lut == NULL) {
298 		hns3_err(hw, "No hns3_rss_lut memory can be allocated");
299 		return -ENOMEM;
300 	}
301 
302 	ret = hns3_set_rss_indir_table(hw, lut, hw->rss_ind_tbl_size);
303 	if (ret)
304 		hns3_err(hw, "RSS uninit indir table failed: %d", ret);
305 	rte_free(lut);
306 
307 	return ret;
308 }
309 
310 int
311 hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw, uint64_t rss_hf)
312 {
313 	struct hns3_rss_input_tuple_cmd *req;
314 	struct hns3_cmd_desc desc;
315 	uint32_t fields_count = 0; /* count times for setting tuple fields */
316 	uint32_t i;
317 	int ret;
318 
319 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false);
320 
321 	req = (struct hns3_rss_input_tuple_cmd *)desc.data;
322 
323 	for (i = 0; i < RTE_DIM(hns3_set_tuple_table); i++) {
324 		if ((rss_hf & hns3_set_tuple_table[i].rss_types) ==
325 		     hns3_set_tuple_table[i].rss_types) {
326 			req->tuple_field |=
327 			    rte_cpu_to_le_64(hns3_set_tuple_table[i].rss_field);
328 			fields_count++;
329 		}
330 	}
331 
332 	/*
333 	 * When user does not specify the following types or a combination of
334 	 * the following types, it enables all fields for the supported RSS
335 	 * types. the following types as:
336 	 * - RTE_ETH_RSS_L3_SRC_ONLY
337 	 * - RTE_ETH_RSS_L3_DST_ONLY
338 	 * - RTE_ETH_RSS_L4_SRC_ONLY
339 	 * - RTE_ETH_RSS_L4_DST_ONLY
340 	 */
341 	if (fields_count == 0) {
342 		for (i = 0; i < RTE_DIM(hns3_set_rss_types); i++) {
343 			if ((rss_hf & hns3_set_rss_types[i].rss_types) ==
344 			     hns3_set_rss_types[i].rss_types)
345 				req->tuple_field |= rte_cpu_to_le_64(
346 					hns3_set_rss_types[i].rss_field);
347 		}
348 	}
349 
350 	ret = hns3_cmd_send(hw, &desc, 1);
351 	if (ret) {
352 		hns3_err(hw, "Update RSS flow types tuples failed %d", ret);
353 		return ret;
354 	}
355 
356 	/* Update supported flow types when set tuple success */
357 	hw->rss_info.conf.types = rss_hf;
358 
359 	return 0;
360 }
361 
362 /*
363  * Configure RSS hash protocols and hash key.
364  * @param dev
365  *   Pointer to Ethernet device.
366  * @praram rss_conf
367  *   The configuration select of  rss key size and tuple flow_types.
368  * @return
369  *   0 on success, a negative errno value otherwise is set.
370  */
371 int
372 hns3_dev_rss_hash_update(struct rte_eth_dev *dev,
373 			 struct rte_eth_rss_conf *rss_conf)
374 {
375 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
376 	uint64_t rss_hf_bk = hw->rss_info.conf.types;
377 	uint8_t key_len = rss_conf->rss_key_len;
378 	uint64_t rss_hf = rss_conf->rss_hf;
379 	uint8_t *key = rss_conf->rss_key;
380 	int ret;
381 
382 	if (key && key_len != HNS3_RSS_KEY_SIZE) {
383 		hns3_err(hw, "the hash key len(%u) is invalid, must be %u",
384 			 key_len, HNS3_RSS_KEY_SIZE);
385 		return -EINVAL;
386 	}
387 
388 	rte_spinlock_lock(&hw->lock);
389 	ret = hns3_set_rss_tuple_by_rss_hf(hw, rss_hf);
390 	if (ret)
391 		goto set_tuple_fail;
392 
393 	if (key) {
394 		ret = hns3_rss_set_algo_key(hw, key);
395 		if (ret)
396 			goto set_algo_key_fail;
397 	}
398 	rte_spinlock_unlock(&hw->lock);
399 
400 	return 0;
401 
402 set_algo_key_fail:
403 	(void)hns3_set_rss_tuple_by_rss_hf(hw, rss_hf_bk);
404 set_tuple_fail:
405 	rte_spinlock_unlock(&hw->lock);
406 	return ret;
407 }
408 
409 /*
410  * Get rss key and rss_hf types set of RSS hash configuration.
411  * @param dev
412  *   Pointer to Ethernet device.
413  * @praram rss_conf
414  *   The buffer to get rss key size and tuple types.
415  * @return
416  *   0 on success.
417  */
418 int
419 hns3_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
420 			   struct rte_eth_rss_conf *rss_conf)
421 {
422 	struct hns3_adapter *hns = dev->data->dev_private;
423 	struct hns3_hw *hw = &hns->hw;
424 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
425 
426 	rte_spinlock_lock(&hw->lock);
427 	rss_conf->rss_hf = rss_cfg->conf.types;
428 
429 	/* Get the RSS Key required by the user */
430 	if (rss_conf->rss_key && rss_conf->rss_key_len >= HNS3_RSS_KEY_SIZE) {
431 		memcpy(rss_conf->rss_key, rss_cfg->key, HNS3_RSS_KEY_SIZE);
432 		rss_conf->rss_key_len = HNS3_RSS_KEY_SIZE;
433 	}
434 	rte_spinlock_unlock(&hw->lock);
435 
436 	return 0;
437 }
438 
439 /*
440  * Update rss redirection table of RSS.
441  * @param dev
442  *   Pointer to Ethernet device.
443  * @praram reta_conf
444  *   Pointer to the configuration select of mask and redirection tables.
445  * @param reta_size
446  *   Redirection table size.
447  * @return
448  *   0 on success, a negative errno value otherwise is set.
449  */
450 int
451 hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
452 			 struct rte_eth_rss_reta_entry64 *reta_conf,
453 			 uint16_t reta_size)
454 {
455 	struct hns3_adapter *hns = dev->data->dev_private;
456 	struct hns3_hw *hw = &hns->hw;
457 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
458 	uint16_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE_MAX];
459 	uint16_t idx, shift;
460 	uint16_t i;
461 	int ret;
462 
463 	if (reta_size != hw->rss_ind_tbl_size) {
464 		hns3_err(hw, "The size of hash lookup table configured (%u)"
465 			 "doesn't match the number hardware can supported"
466 			 "(%u)", reta_size, hw->rss_ind_tbl_size);
467 		return -EINVAL;
468 	}
469 	rte_spinlock_lock(&hw->lock);
470 	memcpy(indirection_tbl, rss_cfg->rss_indirection_tbl,
471 	       sizeof(rss_cfg->rss_indirection_tbl));
472 	for (i = 0; i < reta_size; i++) {
473 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
474 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
475 		if (reta_conf[idx].reta[shift] >= hw->alloc_rss_size) {
476 			rte_spinlock_unlock(&hw->lock);
477 			hns3_err(hw, "queue id(%u) set to redirection table "
478 				 "exceeds queue number(%u) allocated to a TC",
479 				 reta_conf[idx].reta[shift],
480 				 hw->alloc_rss_size);
481 			return -EINVAL;
482 		}
483 
484 		if (reta_conf[idx].mask & (1ULL << shift))
485 			indirection_tbl[i] = reta_conf[idx].reta[shift];
486 	}
487 
488 	ret = hns3_set_rss_indir_table(hw, indirection_tbl,
489 				       hw->rss_ind_tbl_size);
490 
491 	rte_spinlock_unlock(&hw->lock);
492 	return ret;
493 }
494 
495 /*
496  * Get rss redirection table of RSS hash configuration.
497  * @param dev
498  *   Pointer to Ethernet device.
499  * @praram reta_conf
500  *   Pointer to the configuration select of mask and redirection tables.
501  * @param reta_size
502  *   Redirection table size.
503  * @return
504  *   0 on success, a negative errno value otherwise is set.
505  */
506 int
507 hns3_dev_rss_reta_query(struct rte_eth_dev *dev,
508 			struct rte_eth_rss_reta_entry64 *reta_conf,
509 			uint16_t reta_size)
510 {
511 	struct hns3_adapter *hns = dev->data->dev_private;
512 	struct hns3_hw *hw = &hns->hw;
513 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
514 	uint16_t idx, shift;
515 	uint16_t i;
516 
517 	if (reta_size != hw->rss_ind_tbl_size) {
518 		hns3_err(hw, "The size of hash lookup table configured (%u)"
519 			 " doesn't match the number hardware can supported"
520 			 "(%u)", reta_size, hw->rss_ind_tbl_size);
521 		return -EINVAL;
522 	}
523 	rte_spinlock_lock(&hw->lock);
524 	for (i = 0; i < reta_size; i++) {
525 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
526 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
527 		if (reta_conf[idx].mask & (1ULL << shift))
528 			reta_conf[idx].reta[shift] =
529 						rss_cfg->rss_indirection_tbl[i];
530 	}
531 	rte_spinlock_unlock(&hw->lock);
532 	return 0;
533 }
534 
535 static void
536 hns3_set_rss_tc_mode_entry(struct hns3_hw *hw, uint8_t *tc_valid,
537 			   uint16_t *tc_size, uint16_t *tc_offset,
538 			   uint8_t tc_num)
539 {
540 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
541 	uint16_t rss_size = hw->alloc_rss_size;
542 	uint16_t roundup_size;
543 	uint16_t i;
544 
545 	roundup_size = roundup_pow_of_two(rss_size);
546 	roundup_size = ilog2(roundup_size);
547 
548 	for (i = 0; i < tc_num; i++) {
549 		if (hns->is_vf) {
550 			/*
551 			 * For packets with VLAN priorities destined for the VF,
552 			 * hardware still assign Rx queue based on the Up-to-TC
553 			 * mapping PF configured. But VF has only one TC. If
554 			 * other TC don't enable, it causes that the priority
555 			 * packets that aren't destined for TC0 aren't received
556 			 * by RSS hash but is destined for queue 0. So driver
557 			 * has to enable the unused TC by using TC0 queue
558 			 * mapping configuration.
559 			 */
560 			tc_valid[i] = (hw->hw_tc_map & BIT(i)) ?
561 					!!(hw->hw_tc_map & BIT(i)) : 1;
562 			tc_size[i] = roundup_size;
563 			tc_offset[i] = (hw->hw_tc_map & BIT(i)) ?
564 					rss_size * i : 0;
565 		} else {
566 			tc_valid[i] = !!(hw->hw_tc_map & BIT(i));
567 			tc_size[i] = tc_valid[i] ? roundup_size : 0;
568 			tc_offset[i] = tc_valid[i] ? rss_size * i : 0;
569 		}
570 	}
571 }
572 
573 static int
574 hns3_set_rss_tc_mode(struct hns3_hw *hw)
575 {
576 	struct hns3_rss_tc_mode_cmd *req;
577 	uint16_t tc_offset[HNS3_MAX_TC_NUM];
578 	uint8_t tc_valid[HNS3_MAX_TC_NUM];
579 	uint16_t tc_size[HNS3_MAX_TC_NUM];
580 	struct hns3_cmd_desc desc;
581 	uint16_t i;
582 	int ret;
583 
584 	hns3_set_rss_tc_mode_entry(hw, tc_valid, tc_size,
585 				   tc_offset, HNS3_MAX_TC_NUM);
586 
587 	req = (struct hns3_rss_tc_mode_cmd *)desc.data;
588 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_TC_MODE, false);
589 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
590 		uint16_t mode = 0;
591 
592 		hns3_set_bit(mode, HNS3_RSS_TC_VALID_B, (tc_valid[i] & 0x1));
593 		hns3_set_field(mode, HNS3_RSS_TC_SIZE_M, HNS3_RSS_TC_SIZE_S,
594 			       tc_size[i]);
595 		if (tc_size[i] >> HNS3_RSS_TC_SIZE_MSB_OFFSET > 0)
596 			hns3_set_bit(mode, HNS3_RSS_TC_SIZE_MSB_S, 1);
597 		hns3_set_field(mode, HNS3_RSS_TC_OFFSET_M, HNS3_RSS_TC_OFFSET_S,
598 			       tc_offset[i]);
599 
600 		req->rss_tc_mode[i] = rte_cpu_to_le_16(mode);
601 	}
602 	ret = hns3_cmd_send(hw, &desc, 1);
603 	if (ret)
604 		hns3_err(hw, "Sets rss tc mode failed %d", ret);
605 
606 	return ret;
607 }
608 
609 static void
610 hns3_rss_tuple_uninit(struct hns3_hw *hw)
611 {
612 	struct hns3_cmd_desc desc;
613 	int ret;
614 
615 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false);
616 
617 	ret = hns3_cmd_send(hw, &desc, 1);
618 	if (ret) {
619 		hns3_err(hw, "RSS uninit tuple failed %d", ret);
620 		return;
621 	}
622 }
623 
624 /*
625  * Set the default rss configuration in the init of driver.
626  */
627 void
628 hns3_rss_set_default_args(struct hns3_hw *hw)
629 {
630 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
631 	uint16_t queue_num = hw->alloc_rss_size;
632 	uint16_t i;
633 
634 	/* Default hash algorithm */
635 	rss_cfg->conf.func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
636 
637 	/* Default RSS key */
638 	memcpy(rss_cfg->key, hns3_hash_key, HNS3_RSS_KEY_SIZE);
639 
640 	/* Initialize RSS indirection table */
641 	for (i = 0; i < hw->rss_ind_tbl_size; i++)
642 		rss_cfg->rss_indirection_tbl[i] = i % queue_num;
643 }
644 
645 /*
646  * RSS initialization for hns3 PMD.
647  */
648 int
649 hns3_config_rss(struct hns3_adapter *hns)
650 {
651 	struct hns3_hw *hw = &hns->hw;
652 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
653 	uint8_t *hash_key = rss_cfg->key;
654 	uint64_t rss_hf;
655 	int ret;
656 
657 	enum rte_eth_rx_mq_mode mq_mode = hw->data->dev_conf.rxmode.mq_mode;
658 
659 	switch (hw->rss_info.conf.func) {
660 	case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
661 		hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SIMPLE;
662 		break;
663 	case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
664 		hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP;
665 		break;
666 	default:
667 		hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ;
668 		break;
669 	}
670 
671 	/* Configure RSS hash algorithm and hash key offset */
672 	ret = hns3_rss_set_algo_key(hw, hash_key);
673 	if (ret)
674 		return ret;
675 
676 	ret = hns3_set_rss_indir_table(hw, rss_cfg->rss_indirection_tbl,
677 				       hw->rss_ind_tbl_size);
678 	if (ret)
679 		return ret;
680 
681 	ret = hns3_set_rss_tc_mode(hw);
682 	if (ret)
683 		return ret;
684 
685 	/*
686 	 * When muli-queue RSS mode flag is not set or unsupported tuples are
687 	 * set, disable all tuples.
688 	 */
689 	rss_hf = hw->rss_info.conf.types;
690 	if (!((uint32_t)mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) ||
691 	    !(rss_hf & HNS3_ETH_RSS_SUPPORT))
692 		rss_hf = 0;
693 
694 	return hns3_set_rss_tuple_by_rss_hf(hw, rss_hf);
695 }
696 
697 /*
698  * RSS uninitialization for hns3 PMD.
699  */
700 void
701 hns3_rss_uninit(struct hns3_adapter *hns)
702 {
703 	struct hns3_hw *hw = &hns->hw;
704 	int ret;
705 
706 	hns3_rss_tuple_uninit(hw);
707 	ret = hns3_rss_reset_indir_table(hw);
708 	if (ret != 0)
709 		return;
710 
711 	/* Disable RSS */
712 	hw->rss_info.conf.types = 0;
713 }
714