net/mlx5: fix build with clang 14
[dpdk.git] / drivers / net / hns3 / hns3_rss.c
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 }