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