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