1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (c) 2021-2021 Hisilicon Limited.
3#include <linux/skbuff.h>
4
5#include "hnae3.h"
6#include "hclge_comm_cmd.h"
7#include "hclge_comm_rss.h"
8
9static const u8 hclge_comm_hash_key[] = {
10 0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
11 0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
12 0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
13 0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
14 0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA
15};
16
17static void
18hclge_comm_init_rss_tuple(struct hnae3_ae_dev *ae_dev,
19 struct hclge_comm_rss_tuple_cfg *rss_tuple_cfg)
20{
21 rss_tuple_cfg->ipv4_tcp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
22 rss_tuple_cfg->ipv4_udp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
23 rss_tuple_cfg->ipv4_sctp_en = HCLGE_COMM_RSS_INPUT_TUPLE_SCTP;
24 rss_tuple_cfg->ipv4_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
25 rss_tuple_cfg->ipv6_tcp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
26 rss_tuple_cfg->ipv6_udp_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
27 rss_tuple_cfg->ipv6_sctp_en =
28 ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ?
29 HCLGE_COMM_RSS_INPUT_TUPLE_SCTP_NO_PORT :
30 HCLGE_COMM_RSS_INPUT_TUPLE_SCTP;
31 rss_tuple_cfg->ipv6_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
32}
33
34int hclge_comm_rss_init_cfg(struct hnae3_handle *nic,
35 struct hnae3_ae_dev *ae_dev,
36 struct hclge_comm_rss_cfg *rss_cfg)
37{
38 u16 rss_ind_tbl_size = ae_dev->dev_specs.rss_ind_tbl_size;
39 int rss_algo = HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ;
40 u16 *rss_ind_tbl;
41
42 if (nic->flags & HNAE3_SUPPORT_VF)
43 rss_cfg->rss_size = nic->kinfo.rss_size;
44
45 if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
46 rss_algo = HCLGE_COMM_RSS_HASH_ALGO_SIMPLE;
47
48 hclge_comm_init_rss_tuple(ae_dev, rss_tuple_cfg: &rss_cfg->rss_tuple_sets);
49
50 rss_cfg->rss_algo = rss_algo;
51
52 rss_ind_tbl = devm_kcalloc(dev: &ae_dev->pdev->dev, n: rss_ind_tbl_size,
53 size: sizeof(*rss_ind_tbl), GFP_KERNEL);
54 if (!rss_ind_tbl)
55 return -ENOMEM;
56
57 rss_cfg->rss_indirection_tbl = rss_ind_tbl;
58 memcpy(rss_cfg->rss_hash_key, hclge_comm_hash_key,
59 HCLGE_COMM_RSS_KEY_SIZE);
60
61 hclge_comm_rss_indir_init_cfg(ae_dev, rss_cfg);
62
63 return 0;
64}
65
66void hclge_comm_get_rss_tc_info(u16 rss_size, u8 hw_tc_map, u16 *tc_offset,
67 u16 *tc_valid, u16 *tc_size)
68{
69 u16 roundup_size;
70 u32 i;
71
72 roundup_size = roundup_pow_of_two(rss_size);
73 roundup_size = ilog2(roundup_size);
74
75 for (i = 0; i < HCLGE_COMM_MAX_TC_NUM; i++) {
76 tc_valid[i] = 1;
77 tc_size[i] = roundup_size;
78 tc_offset[i] = (hw_tc_map & BIT(i)) ? rss_size * i : 0;
79 }
80}
81
82int hclge_comm_set_rss_tc_mode(struct hclge_comm_hw *hw, u16 *tc_offset,
83 u16 *tc_valid, u16 *tc_size)
84{
85 struct hclge_comm_rss_tc_mode_cmd *req;
86 struct hclge_desc desc;
87 unsigned int i;
88 int ret;
89
90 req = (struct hclge_comm_rss_tc_mode_cmd *)desc.data;
91
92 hclge_comm_cmd_setup_basic_desc(desc: &desc, opcode: HCLGE_OPC_RSS_TC_MODE, is_read: false);
93 for (i = 0; i < HCLGE_COMM_MAX_TC_NUM; i++) {
94 u16 mode = 0;
95
96 hnae3_set_bit(mode, HCLGE_COMM_RSS_TC_VALID_B,
97 (tc_valid[i] & 0x1));
98 hnae3_set_field(mode, HCLGE_COMM_RSS_TC_SIZE_M,
99 HCLGE_COMM_RSS_TC_SIZE_S, tc_size[i]);
100 hnae3_set_bit(mode, HCLGE_COMM_RSS_TC_SIZE_MSB_B,
101 tc_size[i] >> HCLGE_COMM_RSS_TC_SIZE_MSB_OFFSET &
102 0x1);
103 hnae3_set_field(mode, HCLGE_COMM_RSS_TC_OFFSET_M,
104 HCLGE_COMM_RSS_TC_OFFSET_S, tc_offset[i]);
105
106 req->rss_tc_mode[i] = cpu_to_le16(mode);
107 }
108
109 ret = hclge_comm_cmd_send(hw, desc: &desc, num: 1);
110 if (ret)
111 dev_err(&hw->cmq.csq.pdev->dev,
112 "failed to set rss tc mode, ret = %d.\n", ret);
113
114 return ret;
115}
116
117int hclge_comm_set_rss_hash_key(struct hclge_comm_rss_cfg *rss_cfg,
118 struct hclge_comm_hw *hw, const u8 *key,
119 const u8 hfunc)
120{
121 u8 hash_algo;
122 int ret;
123
124 ret = hclge_comm_parse_rss_hfunc(rss_cfg, hfunc, hash_algo: &hash_algo);
125 if (ret)
126 return ret;
127
128 /* Set the RSS Hash Key if specififed by the user */
129 if (key) {
130 ret = hclge_comm_set_rss_algo_key(hw, hfunc: hash_algo, key);
131 if (ret)
132 return ret;
133
134 /* Update the shadow RSS key with user specified qids */
135 memcpy(rss_cfg->rss_hash_key, key, HCLGE_COMM_RSS_KEY_SIZE);
136 } else {
137 ret = hclge_comm_set_rss_algo_key(hw, hfunc: hash_algo,
138 key: rss_cfg->rss_hash_key);
139 if (ret)
140 return ret;
141 }
142 rss_cfg->rss_algo = hash_algo;
143
144 return 0;
145}
146
147int hclge_comm_set_rss_tuple(struct hnae3_ae_dev *ae_dev,
148 struct hclge_comm_hw *hw,
149 struct hclge_comm_rss_cfg *rss_cfg,
150 struct ethtool_rxnfc *nfc)
151{
152 struct hclge_comm_rss_input_tuple_cmd *req;
153 struct hclge_desc desc;
154 int ret;
155
156 if (nfc->data &
157 ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
158 return -EINVAL;
159
160 req = (struct hclge_comm_rss_input_tuple_cmd *)desc.data;
161 hclge_comm_cmd_setup_basic_desc(desc: &desc, opcode: HCLGE_OPC_RSS_INPUT_TUPLE,
162 is_read: false);
163
164 ret = hclge_comm_init_rss_tuple_cmd(rss_cfg, nfc, ae_dev, req);
165 if (ret) {
166 dev_err(&hw->cmq.csq.pdev->dev,
167 "failed to init rss tuple cmd, ret = %d.\n", ret);
168 return ret;
169 }
170
171 ret = hclge_comm_cmd_send(hw, desc: &desc, num: 1);
172 if (ret) {
173 dev_err(&hw->cmq.csq.pdev->dev,
174 "failed to set rss tuple, ret = %d.\n", ret);
175 return ret;
176 }
177
178 rss_cfg->rss_tuple_sets.ipv4_tcp_en = req->ipv4_tcp_en;
179 rss_cfg->rss_tuple_sets.ipv4_udp_en = req->ipv4_udp_en;
180 rss_cfg->rss_tuple_sets.ipv4_sctp_en = req->ipv4_sctp_en;
181 rss_cfg->rss_tuple_sets.ipv4_fragment_en = req->ipv4_fragment_en;
182 rss_cfg->rss_tuple_sets.ipv6_tcp_en = req->ipv6_tcp_en;
183 rss_cfg->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en;
184 rss_cfg->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en;
185 rss_cfg->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en;
186 return 0;
187}
188
189u32 hclge_comm_get_rss_key_size(struct hnae3_handle *handle)
190{
191 return HCLGE_COMM_RSS_KEY_SIZE;
192}
193
194int hclge_comm_parse_rss_hfunc(struct hclge_comm_rss_cfg *rss_cfg,
195 const u8 hfunc, u8 *hash_algo)
196{
197 switch (hfunc) {
198 case ETH_RSS_HASH_TOP:
199 *hash_algo = HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ;
200 return 0;
201 case ETH_RSS_HASH_XOR:
202 *hash_algo = HCLGE_COMM_RSS_HASH_ALGO_SIMPLE;
203 return 0;
204 case ETH_RSS_HASH_NO_CHANGE:
205 *hash_algo = rss_cfg->rss_algo;
206 return 0;
207 default:
208 return -EINVAL;
209 }
210}
211
212void hclge_comm_rss_indir_init_cfg(struct hnae3_ae_dev *ae_dev,
213 struct hclge_comm_rss_cfg *rss_cfg)
214{
215 u16 i;
216 /* Initialize RSS indirect table */
217 for (i = 0; i < ae_dev->dev_specs.rss_ind_tbl_size; i++)
218 rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size;
219}
220
221int hclge_comm_get_rss_tuple(struct hclge_comm_rss_cfg *rss_cfg, int flow_type,
222 u8 *tuple_sets)
223{
224 switch (flow_type) {
225 case TCP_V4_FLOW:
226 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
227 break;
228 case UDP_V4_FLOW:
229 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_udp_en;
230 break;
231 case TCP_V6_FLOW:
232 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
233 break;
234 case UDP_V6_FLOW:
235 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_udp_en;
236 break;
237 case SCTP_V4_FLOW:
238 *tuple_sets = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
239 break;
240 case SCTP_V6_FLOW:
241 *tuple_sets = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
242 break;
243 case IPV4_FLOW:
244 case IPV6_FLOW:
245 *tuple_sets = HCLGE_COMM_S_IP_BIT | HCLGE_COMM_D_IP_BIT;
246 break;
247 default:
248 return -EINVAL;
249 }
250
251 return 0;
252}
253
254static void
255hclge_comm_append_rss_msb_info(struct hclge_comm_rss_ind_tbl_cmd *req,
256 u16 qid, u32 j)
257{
258 u8 rss_msb_oft;
259 u8 rss_msb_val;
260
261 rss_msb_oft =
262 j * HCLGE_COMM_RSS_CFG_TBL_BW_H / BITS_PER_BYTE;
263 rss_msb_val = (qid >> HCLGE_COMM_RSS_CFG_TBL_BW_L & 0x1) <<
264 (j * HCLGE_COMM_RSS_CFG_TBL_BW_H % BITS_PER_BYTE);
265 req->rss_qid_h[rss_msb_oft] |= rss_msb_val;
266}
267
268int hclge_comm_set_rss_indir_table(struct hnae3_ae_dev *ae_dev,
269 struct hclge_comm_hw *hw, const u16 *indir)
270{
271 struct hclge_comm_rss_ind_tbl_cmd *req;
272 struct hclge_desc desc;
273 u16 rss_cfg_tbl_num;
274 int ret;
275 u16 qid;
276 u16 i;
277 u32 j;
278
279 req = (struct hclge_comm_rss_ind_tbl_cmd *)desc.data;
280 rss_cfg_tbl_num = ae_dev->dev_specs.rss_ind_tbl_size /
281 HCLGE_COMM_RSS_CFG_TBL_SIZE;
282
283 for (i = 0; i < rss_cfg_tbl_num; i++) {
284 hclge_comm_cmd_setup_basic_desc(desc: &desc,
285 opcode: HCLGE_OPC_RSS_INDIR_TABLE,
286 is_read: false);
287
288 req->start_table_index =
289 cpu_to_le16(i * HCLGE_COMM_RSS_CFG_TBL_SIZE);
290 req->rss_set_bitmap =
291 cpu_to_le16(HCLGE_COMM_RSS_SET_BITMAP_MSK);
292 for (j = 0; j < HCLGE_COMM_RSS_CFG_TBL_SIZE; j++) {
293 qid = indir[i * HCLGE_COMM_RSS_CFG_TBL_SIZE + j];
294 req->rss_qid_l[j] = qid & 0xff;
295 hclge_comm_append_rss_msb_info(req, qid, j);
296 }
297 ret = hclge_comm_cmd_send(hw, desc: &desc, num: 1);
298 if (ret) {
299 dev_err(&hw->cmq.csq.pdev->dev,
300 "failed to configure rss table, ret = %d.\n",
301 ret);
302 return ret;
303 }
304 }
305 return 0;
306}
307
308int hclge_comm_set_rss_input_tuple(struct hclge_comm_hw *hw,
309 struct hclge_comm_rss_cfg *rss_cfg)
310{
311 struct hclge_comm_rss_input_tuple_cmd *req;
312 struct hclge_desc desc;
313 int ret;
314
315 hclge_comm_cmd_setup_basic_desc(desc: &desc, opcode: HCLGE_OPC_RSS_INPUT_TUPLE,
316 is_read: false);
317
318 req = (struct hclge_comm_rss_input_tuple_cmd *)desc.data;
319
320 req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
321 req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
322 req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
323 req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
324 req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
325 req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
326 req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
327 req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
328
329 ret = hclge_comm_cmd_send(hw, desc: &desc, num: 1);
330 if (ret)
331 dev_err(&hw->cmq.csq.pdev->dev,
332 "failed to configure rss input, ret = %d.\n", ret);
333 return ret;
334}
335
336void hclge_comm_get_rss_hash_info(struct hclge_comm_rss_cfg *rss_cfg, u8 *key,
337 u8 *hfunc)
338{
339 /* Get hash algorithm */
340 if (hfunc) {
341 switch (rss_cfg->rss_algo) {
342 case HCLGE_COMM_RSS_HASH_ALGO_TOEPLITZ:
343 *hfunc = ETH_RSS_HASH_TOP;
344 break;
345 case HCLGE_COMM_RSS_HASH_ALGO_SIMPLE:
346 *hfunc = ETH_RSS_HASH_XOR;
347 break;
348 default:
349 *hfunc = ETH_RSS_HASH_UNKNOWN;
350 break;
351 }
352 }
353
354 /* Get the RSS Key required by the user */
355 if (key)
356 memcpy(key, rss_cfg->rss_hash_key, HCLGE_COMM_RSS_KEY_SIZE);
357}
358
359void hclge_comm_get_rss_indir_tbl(struct hclge_comm_rss_cfg *rss_cfg,
360 u32 *indir, u16 rss_ind_tbl_size)
361{
362 u16 i;
363
364 if (!indir)
365 return;
366
367 for (i = 0; i < rss_ind_tbl_size; i++)
368 indir[i] = rss_cfg->rss_indirection_tbl[i];
369}
370
371int hclge_comm_set_rss_algo_key(struct hclge_comm_hw *hw, const u8 hfunc,
372 const u8 *key)
373{
374 struct hclge_comm_rss_config_cmd *req;
375 unsigned int key_offset = 0;
376 struct hclge_desc desc;
377 int key_counts;
378 int key_size;
379 int ret;
380
381 key_counts = HCLGE_COMM_RSS_KEY_SIZE;
382 req = (struct hclge_comm_rss_config_cmd *)desc.data;
383
384 while (key_counts) {
385 hclge_comm_cmd_setup_basic_desc(desc: &desc,
386 opcode: HCLGE_OPC_RSS_GENERIC_CONFIG,
387 is_read: false);
388
389 req->hash_config |= (hfunc & HCLGE_COMM_RSS_HASH_ALGO_MASK);
390 req->hash_config |=
391 (key_offset << HCLGE_COMM_RSS_HASH_KEY_OFFSET_B);
392
393 key_size = min(HCLGE_COMM_RSS_HASH_KEY_NUM, key_counts);
394 memcpy(req->hash_key,
395 key + key_offset * HCLGE_COMM_RSS_HASH_KEY_NUM,
396 key_size);
397
398 key_counts -= key_size;
399 key_offset++;
400 ret = hclge_comm_cmd_send(hw, desc: &desc, num: 1);
401 if (ret) {
402 dev_err(&hw->cmq.csq.pdev->dev,
403 "failed to configure RSS key, ret = %d.\n",
404 ret);
405 return ret;
406 }
407 }
408
409 return 0;
410}
411
412static u8 hclge_comm_get_rss_hash_bits(struct ethtool_rxnfc *nfc)
413{
414 u8 hash_sets = nfc->data & RXH_L4_B_0_1 ? HCLGE_COMM_S_PORT_BIT : 0;
415
416 if (nfc->data & RXH_L4_B_2_3)
417 hash_sets |= HCLGE_COMM_D_PORT_BIT;
418 else
419 hash_sets &= ~HCLGE_COMM_D_PORT_BIT;
420
421 if (nfc->data & RXH_IP_SRC)
422 hash_sets |= HCLGE_COMM_S_IP_BIT;
423 else
424 hash_sets &= ~HCLGE_COMM_S_IP_BIT;
425
426 if (nfc->data & RXH_IP_DST)
427 hash_sets |= HCLGE_COMM_D_IP_BIT;
428 else
429 hash_sets &= ~HCLGE_COMM_D_IP_BIT;
430
431 if (nfc->flow_type == SCTP_V4_FLOW || nfc->flow_type == SCTP_V6_FLOW)
432 hash_sets |= HCLGE_COMM_V_TAG_BIT;
433
434 return hash_sets;
435}
436
437int hclge_comm_init_rss_tuple_cmd(struct hclge_comm_rss_cfg *rss_cfg,
438 struct ethtool_rxnfc *nfc,
439 struct hnae3_ae_dev *ae_dev,
440 struct hclge_comm_rss_input_tuple_cmd *req)
441{
442 u8 tuple_sets;
443
444 req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
445 req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
446 req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
447 req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
448 req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
449 req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
450 req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
451 req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
452
453 tuple_sets = hclge_comm_get_rss_hash_bits(nfc);
454 switch (nfc->flow_type) {
455 case TCP_V4_FLOW:
456 req->ipv4_tcp_en = tuple_sets;
457 break;
458 case TCP_V6_FLOW:
459 req->ipv6_tcp_en = tuple_sets;
460 break;
461 case UDP_V4_FLOW:
462 req->ipv4_udp_en = tuple_sets;
463 break;
464 case UDP_V6_FLOW:
465 req->ipv6_udp_en = tuple_sets;
466 break;
467 case SCTP_V4_FLOW:
468 req->ipv4_sctp_en = tuple_sets;
469 break;
470 case SCTP_V6_FLOW:
471 if (ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 &&
472 (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)))
473 return -EINVAL;
474
475 req->ipv6_sctp_en = tuple_sets;
476 break;
477 case IPV4_FLOW:
478 req->ipv4_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
479 break;
480 case IPV6_FLOW:
481 req->ipv6_fragment_en = HCLGE_COMM_RSS_INPUT_TUPLE_OTHER;
482 break;
483 default:
484 return -EINVAL;
485 }
486
487 return 0;
488}
489
490u64 hclge_comm_convert_rss_tuple(u8 tuple_sets)
491{
492 u64 tuple_data = 0;
493
494 if (tuple_sets & HCLGE_COMM_D_PORT_BIT)
495 tuple_data |= RXH_L4_B_2_3;
496 if (tuple_sets & HCLGE_COMM_S_PORT_BIT)
497 tuple_data |= RXH_L4_B_0_1;
498 if (tuple_sets & HCLGE_COMM_D_IP_BIT)
499 tuple_data |= RXH_IP_DST;
500 if (tuple_sets & HCLGE_COMM_S_IP_BIT)
501 tuple_data |= RXH_IP_SRC;
502
503 return tuple_data;
504}
505

source code of linux/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_rss.c