net/hns3: support SVE Rx
[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_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, uint16_t *indir, uint16_t size)
270 {
271         struct hns3_rss_indirection_table_cmd *req;
272         struct hns3_cmd_desc desc;
273         uint8_t qid_msb_off;
274         uint8_t qid_msb_val;
275         uint16_t q_id;
276         uint16_t i, j;
277         int ret;
278
279         req = (struct hns3_rss_indirection_table_cmd *)desc.data;
280
281         for (i = 0; i < size / HNS3_RSS_CFG_TBL_SIZE; i++) {
282                 hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INDIR_TABLE,
283                                           false);
284                 req->start_table_index =
285                                 rte_cpu_to_le_16(i * HNS3_RSS_CFG_TBL_SIZE);
286                 req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK);
287                 for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) {
288                         q_id = indir[i * HNS3_RSS_CFG_TBL_SIZE + j];
289                         req->rss_result_l[j] = q_id & 0xff;
290
291                         qid_msb_off =
292                                 j * HNS3_RSS_CFG_TBL_BW_H / HNS3_BITS_PER_BYTE;
293                         qid_msb_val = (q_id >> HNS3_RSS_CFG_TBL_BW_L & 0x1)
294                                         << (j * HNS3_RSS_CFG_TBL_BW_H %
295                                         HNS3_BITS_PER_BYTE);
296                         req->rss_result_h[qid_msb_off] |= qid_msb_val;
297                 }
298
299                 ret = hns3_cmd_send(hw, &desc, 1);
300                 if (ret) {
301                         hns3_err(hw,
302                                  "Sets RSS indirection table failed %d size %u",
303                                  ret, size);
304                         return ret;
305                 }
306         }
307
308         /* Update redirection table of hw */
309         memcpy(hw->rss_info.rss_indirection_tbl, indir,
310                sizeof(hw->rss_info.rss_indirection_tbl));
311
312         return 0;
313 }
314
315 int
316 hns3_rss_reset_indir_table(struct hns3_hw *hw)
317 {
318         uint16_t *lut;
319         int ret;
320
321         lut = rte_zmalloc("hns3_rss_lut",
322                           HNS3_RSS_IND_TBL_SIZE * sizeof(uint16_t), 0);
323         if (lut == NULL) {
324                 hns3_err(hw, "No hns3_rss_lut memory can be allocated");
325                 return -ENOMEM;
326         }
327
328         ret = hns3_set_rss_indir_table(hw, lut, HNS3_RSS_IND_TBL_SIZE);
329         if (ret)
330                 hns3_err(hw, "RSS uninit indir table failed: %d", ret);
331         rte_free(lut);
332
333         return ret;
334 }
335
336 int
337 hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw,
338                              struct hns3_rss_tuple_cfg *tuple, uint64_t rss_hf)
339 {
340         struct hns3_rss_input_tuple_cmd *req;
341         struct hns3_cmd_desc desc;
342         uint32_t fields_count = 0; /* count times for setting tuple fields */
343         uint32_t i;
344         int ret;
345
346         hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false);
347
348         req = (struct hns3_rss_input_tuple_cmd *)desc.data;
349
350         for (i = 0; i < RTE_DIM(hns3_set_tuple_table); i++) {
351                 if ((rss_hf & hns3_set_tuple_table[i].rss_types) ==
352                      hns3_set_tuple_table[i].rss_types) {
353                         req->tuple_field |=
354                             rte_cpu_to_le_64(hns3_set_tuple_table[i].rss_field);
355                         fields_count++;
356                 }
357         }
358
359         /*
360          * When user does not specify the following types or a combination of
361          * the following types, it enables all fields for the supported RSS
362          * types. the following types as:
363          * - ETH_RSS_L3_SRC_ONLY
364          * - ETH_RSS_L3_DST_ONLY
365          * - ETH_RSS_L4_SRC_ONLY
366          * - ETH_RSS_L4_DST_ONLY
367          */
368         if (fields_count == 0) {
369                 for (i = 0; i < RTE_DIM(hns3_set_rss_types); i++) {
370                         if ((rss_hf & hns3_set_rss_types[i].rss_types) ==
371                              hns3_set_rss_types[i].rss_types)
372                                 req->tuple_field |= rte_cpu_to_le_64(
373                                         hns3_set_rss_types[i].rss_field);
374                 }
375         }
376
377         ret = hns3_cmd_send(hw, &desc, 1);
378         if (ret) {
379                 hns3_err(hw, "Update RSS flow types tuples failed %d", ret);
380                 return ret;
381         }
382
383         tuple->rss_tuple_fields = rte_le_to_cpu_64(req->tuple_field);
384
385         return 0;
386 }
387
388 /*
389  * Configure RSS hash protocols and hash key.
390  * @param dev
391  *   Pointer to Ethernet device.
392  * @praram rss_conf
393  *   The configuration select of  rss key size and tuple flow_types.
394  * @return
395  *   0 on success, a negative errno value otherwise is set.
396  */
397 int
398 hns3_dev_rss_hash_update(struct rte_eth_dev *dev,
399                          struct rte_eth_rss_conf *rss_conf)
400 {
401         struct hns3_adapter *hns = dev->data->dev_private;
402         struct hns3_hw *hw = &hns->hw;
403         struct hns3_rss_tuple_cfg *tuple = &hw->rss_info.rss_tuple_sets;
404         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
405         uint8_t key_len = rss_conf->rss_key_len;
406         uint64_t rss_hf = rss_conf->rss_hf;
407         uint8_t *key = rss_conf->rss_key;
408         int ret;
409
410         if (hw->rss_dis_flag)
411                 return -EINVAL;
412
413         rte_spinlock_lock(&hw->lock);
414         ret = hns3_set_rss_tuple_by_rss_hf(hw, tuple, rss_hf);
415         if (ret)
416                 goto conf_err;
417
418         if (rss_cfg->conf.types && rss_hf == 0) {
419                 /* Disable RSS, reset indirection table by local variable */
420                 ret = hns3_rss_reset_indir_table(hw);
421                 if (ret)
422                         goto conf_err;
423         } else if (rss_hf && rss_cfg->conf.types == 0) {
424                 /* Enable RSS, restore indirection table by hw's config */
425                 ret = hns3_set_rss_indir_table(hw, rss_cfg->rss_indirection_tbl,
426                                                HNS3_RSS_IND_TBL_SIZE);
427                 if (ret)
428                         goto conf_err;
429         }
430
431         /* Update supported flow types when set tuple success */
432         rss_cfg->conf.types = rss_hf;
433
434         if (key) {
435                 if (key_len != HNS3_RSS_KEY_SIZE) {
436                         hns3_err(hw, "The hash key len(%u) is invalid",
437                                  key_len);
438                         ret = -EINVAL;
439                         goto conf_err;
440                 }
441                 ret = hns3_set_rss_algo_key(hw, key);
442                 if (ret)
443                         goto conf_err;
444         }
445         rte_spinlock_unlock(&hw->lock);
446
447         return 0;
448
449 conf_err:
450         rte_spinlock_unlock(&hw->lock);
451         return ret;
452 }
453
454 /*
455  * Get rss key and rss_hf types set of RSS hash configuration.
456  * @param dev
457  *   Pointer to Ethernet device.
458  * @praram rss_conf
459  *   The buffer to get rss key size and tuple types.
460  * @return
461  *   0 on success.
462  */
463 int
464 hns3_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
465                            struct rte_eth_rss_conf *rss_conf)
466 {
467         struct hns3_adapter *hns = dev->data->dev_private;
468         struct hns3_hw *hw = &hns->hw;
469         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
470
471         rte_spinlock_lock(&hw->lock);
472         rss_conf->rss_hf = rss_cfg->conf.types;
473
474         /* Get the RSS Key required by the user */
475         if (rss_conf->rss_key && rss_conf->rss_key_len >= HNS3_RSS_KEY_SIZE) {
476                 memcpy(rss_conf->rss_key, rss_cfg->key, HNS3_RSS_KEY_SIZE);
477                 rss_conf->rss_key_len = HNS3_RSS_KEY_SIZE;
478         }
479         rte_spinlock_unlock(&hw->lock);
480
481         return 0;
482 }
483
484 /*
485  * Update rss redirection table of RSS.
486  * @param dev
487  *   Pointer to Ethernet device.
488  * @praram reta_conf
489  *   Pointer to the configuration select of mask and redirection tables.
490  * @param reta_size
491  *   Redirection table size.
492  * @return
493  *   0 on success, a negative errno value otherwise is set.
494  */
495 int
496 hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
497                          struct rte_eth_rss_reta_entry64 *reta_conf,
498                          uint16_t reta_size)
499 {
500         struct hns3_adapter *hns = dev->data->dev_private;
501         struct hns3_hw *hw = &hns->hw;
502         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
503         uint16_t i, indir_size = HNS3_RSS_IND_TBL_SIZE; /* Table size is 512 */
504         uint16_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
505         uint16_t idx, shift, allow_rss_queues;
506         int ret;
507
508         if (reta_size != indir_size || reta_size > ETH_RSS_RETA_SIZE_512) {
509                 hns3_err(hw, "The size of hash lookup table configured (%u)"
510                          "doesn't match the number hardware can supported"
511                          "(%u)", reta_size, indir_size);
512                 return -EINVAL;
513         }
514         rte_spinlock_lock(&hw->lock);
515         memcpy(indirection_tbl, rss_cfg->rss_indirection_tbl,
516                sizeof(rss_cfg->rss_indirection_tbl));
517         allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
518         for (i = 0; i < reta_size; i++) {
519                 idx = i / RTE_RETA_GROUP_SIZE;
520                 shift = i % RTE_RETA_GROUP_SIZE;
521                 if (reta_conf[idx].reta[shift] >= allow_rss_queues) {
522                         rte_spinlock_unlock(&hw->lock);
523                         hns3_err(hw, "Invalid queue id(%u) to be set in "
524                                  "redirection table, max number of rss "
525                                  "queues: %u", reta_conf[idx].reta[shift],
526                                  allow_rss_queues);
527                         return -EINVAL;
528                 }
529
530                 if (reta_conf[idx].mask & (1ULL << shift))
531                         indirection_tbl[i] = reta_conf[idx].reta[shift];
532         }
533
534         ret = hns3_set_rss_indir_table(hw, indirection_tbl,
535                                        HNS3_RSS_IND_TBL_SIZE);
536
537         rte_spinlock_unlock(&hw->lock);
538         return ret;
539 }
540
541 /*
542  * Get rss redirection table of RSS hash configuration.
543  * @param dev
544  *   Pointer to Ethernet device.
545  * @praram reta_conf
546  *   Pointer to the configuration select of mask and redirection tables.
547  * @param reta_size
548  *   Redirection table size.
549  * @return
550  *   0 on success, a negative errno value otherwise is set.
551  */
552 int
553 hns3_dev_rss_reta_query(struct rte_eth_dev *dev,
554                         struct rte_eth_rss_reta_entry64 *reta_conf,
555                         uint16_t reta_size)
556 {
557         struct hns3_adapter *hns = dev->data->dev_private;
558         struct hns3_hw *hw = &hns->hw;
559         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
560         uint16_t i, indir_size = HNS3_RSS_IND_TBL_SIZE; /* Table size is 512 */
561         uint16_t idx, shift;
562
563         if (reta_size != indir_size || reta_size > ETH_RSS_RETA_SIZE_512) {
564                 hns3_err(hw, "The size of hash lookup table configured (%u)"
565                          " doesn't match the number hardware can supported"
566                          "(%u)", reta_size, indir_size);
567                 return -EINVAL;
568         }
569         rte_spinlock_lock(&hw->lock);
570         for (i = 0; i < reta_size; i++) {
571                 idx = i / RTE_RETA_GROUP_SIZE;
572                 shift = i % RTE_RETA_GROUP_SIZE;
573                 if (reta_conf[idx].mask & (1ULL << shift))
574                         reta_conf[idx].reta[shift] =
575                                                 rss_cfg->rss_indirection_tbl[i];
576         }
577         rte_spinlock_unlock(&hw->lock);
578         return 0;
579 }
580
581 /*
582  * Used to configure the tc_size and tc_offset.
583  */
584 static int
585 hns3_set_rss_tc_mode(struct hns3_hw *hw)
586 {
587         uint16_t rss_size = hw->alloc_rss_size;
588         struct hns3_rss_tc_mode_cmd *req;
589         uint16_t tc_offset[HNS3_MAX_TC_NUM];
590         uint8_t tc_valid[HNS3_MAX_TC_NUM];
591         uint16_t tc_size[HNS3_MAX_TC_NUM];
592         struct hns3_cmd_desc desc;
593         uint16_t roundup_size;
594         uint16_t i;
595         int ret;
596
597         req = (struct hns3_rss_tc_mode_cmd *)desc.data;
598
599         roundup_size = roundup_pow_of_two(rss_size);
600         roundup_size = ilog2(roundup_size);
601
602         for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
603                 tc_valid[i] = !!(hw->hw_tc_map & BIT(i));
604                 tc_size[i] = roundup_size;
605                 tc_offset[i] = rss_size * i;
606         }
607
608         hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_TC_MODE, false);
609         for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
610                 uint16_t mode = 0;
611
612                 hns3_set_bit(mode, HNS3_RSS_TC_VALID_B, (tc_valid[i] & 0x1));
613                 hns3_set_field(mode, HNS3_RSS_TC_SIZE_M, HNS3_RSS_TC_SIZE_S,
614                                tc_size[i]);
615                 if (tc_size[i] >> HNS3_RSS_TC_SIZE_MSB_OFFSET > 0)
616                         hns3_set_bit(mode, HNS3_RSS_TC_SIZE_MSB_S, 1);
617                 hns3_set_field(mode, HNS3_RSS_TC_OFFSET_M, HNS3_RSS_TC_OFFSET_S,
618                                tc_offset[i]);
619
620                 req->rss_tc_mode[i] = rte_cpu_to_le_16(mode);
621         }
622         ret = hns3_cmd_send(hw, &desc, 1);
623         if (ret)
624                 hns3_err(hw, "Sets rss tc mode failed %d", ret);
625
626         return ret;
627 }
628
629 static void
630 hns3_rss_tuple_uninit(struct hns3_hw *hw)
631 {
632         struct hns3_rss_input_tuple_cmd *req;
633         struct hns3_cmd_desc desc;
634         int ret;
635
636         hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_RSS_INPUT_TUPLE, false);
637
638         req = (struct hns3_rss_input_tuple_cmd *)desc.data;
639
640         memset(req, 0, sizeof(struct hns3_rss_tuple_cfg));
641
642         ret = hns3_cmd_send(hw, &desc, 1);
643         if (ret) {
644                 hns3_err(hw, "RSS uninit tuple failed %d", ret);
645                 return;
646         }
647 }
648
649 /*
650  * Set the default rss configuration in the init of driver.
651  */
652 void
653 hns3_set_default_rss_args(struct hns3_hw *hw)
654 {
655         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
656         uint16_t queue_num = hw->alloc_rss_size;
657         int i;
658
659         /* Default hash algorithm */
660         rss_cfg->conf.func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
661
662         /* Default RSS key */
663         memcpy(rss_cfg->key, hns3_hash_key, HNS3_RSS_KEY_SIZE);
664
665         /* Initialize RSS indirection table */
666         for (i = 0; i < HNS3_RSS_IND_TBL_SIZE; i++)
667                 rss_cfg->rss_indirection_tbl[i] = i % queue_num;
668 }
669
670 /*
671  * RSS initialization for hns3 pmd driver.
672  */
673 int
674 hns3_config_rss(struct hns3_adapter *hns)
675 {
676         struct hns3_hw *hw = &hns->hw;
677         struct hns3_rss_conf *rss_cfg = &hw->rss_info;
678         uint8_t *hash_key = rss_cfg->key;
679         int ret, ret1;
680
681         enum rte_eth_rx_mq_mode mq_mode = hw->data->dev_conf.rxmode.mq_mode;
682
683         switch (hw->rss_info.conf.func) {
684         case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
685                 hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SIMPLE;
686                 break;
687         case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
688                 hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_SYMMETRIC_TOEP;
689                 break;
690         default:
691                 hw->rss_info.hash_algo = HNS3_RSS_HASH_ALGO_TOEPLITZ;
692                 break;
693         }
694
695         /* When RSS is off, redirect the packet queue 0 */
696         if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG) == 0)
697                 hns3_rss_uninit(hns);
698
699         /* Configure RSS hash algorithm and hash key offset */
700         ret = hns3_set_rss_algo_key(hw, hash_key);
701         if (ret)
702                 return ret;
703
704         /* Configure the tuple selection for RSS hash input */
705         ret = hns3_set_rss_input_tuple(hw);
706         if (ret)
707                 return ret;
708
709         /*
710          * When RSS is off, it doesn't need to configure rss redirection table
711          * to hardware.
712          */
713         if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG)) {
714                 ret = hns3_set_rss_indir_table(hw, rss_cfg->rss_indirection_tbl,
715                                                HNS3_RSS_IND_TBL_SIZE);
716                 if (ret)
717                         goto rss_tuple_uninit;
718         }
719
720         ret = hns3_set_rss_tc_mode(hw);
721         if (ret)
722                 goto rss_indir_table_uninit;
723
724         return ret;
725
726 rss_indir_table_uninit:
727         if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG)) {
728                 ret1 = hns3_rss_reset_indir_table(hw);
729                 if (ret1 != 0)
730                         return ret;
731         }
732
733 rss_tuple_uninit:
734         hns3_rss_tuple_uninit(hw);
735
736         /* Disable RSS */
737         hw->rss_info.conf.types = 0;
738
739         return ret;
740 }
741
742 /*
743  * RSS uninitialization for hns3 pmd driver.
744  */
745 void
746 hns3_rss_uninit(struct hns3_adapter *hns)
747 {
748         struct hns3_hw *hw = &hns->hw;
749         int ret;
750
751         hns3_rss_tuple_uninit(hw);
752         ret = hns3_rss_reset_indir_table(hw);
753         if (ret != 0)
754                 return;
755
756         /* Disable RSS */
757         hw->rss_info.conf.types = 0;
758 }