1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
3 */
4
5 #include "otx2_ethdev.h"
6
7 int
otx2_nix_rss_tbl_init(struct otx2_eth_dev * dev,uint8_t group,uint16_t * ind_tbl)8 otx2_nix_rss_tbl_init(struct otx2_eth_dev *dev,
9 uint8_t group, uint16_t *ind_tbl)
10 {
11 struct otx2_rss_info *rss = &dev->rss_info;
12 struct otx2_mbox *mbox = dev->mbox;
13 struct nix_aq_enq_req *req;
14 int rc, idx;
15
16 for (idx = 0; idx < rss->rss_size; idx++) {
17 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
18 if (!req) {
19 /* The shared memory buffer can be full.
20 * Flush it and retry
21 */
22 otx2_mbox_msg_send(mbox, 0);
23 rc = otx2_mbox_wait_for_rsp(mbox, 0);
24 if (rc < 0)
25 return rc;
26
27 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
28 if (!req)
29 return -ENOMEM;
30 }
31 req->rss.rq = ind_tbl[idx];
32 /* Fill AQ info */
33 req->qidx = (group * rss->rss_size) + idx;
34 req->ctype = NIX_AQ_CTYPE_RSS;
35 req->op = NIX_AQ_INSTOP_INIT;
36
37 if (!dev->lock_rx_ctx)
38 continue;
39
40 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
41 if (!req) {
42 /* The shared memory buffer can be full.
43 * Flush it and retry
44 */
45 otx2_mbox_msg_send(mbox, 0);
46 rc = otx2_mbox_wait_for_rsp(mbox, 0);
47 if (rc < 0)
48 return rc;
49
50 req = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
51 if (!req)
52 return -ENOMEM;
53 }
54 req->rss.rq = ind_tbl[idx];
55 /* Fill AQ info */
56 req->qidx = (group * rss->rss_size) + idx;
57 req->ctype = NIX_AQ_CTYPE_RSS;
58 req->op = NIX_AQ_INSTOP_LOCK;
59 }
60
61 otx2_mbox_msg_send(mbox, 0);
62 rc = otx2_mbox_wait_for_rsp(mbox, 0);
63 if (rc < 0)
64 return rc;
65
66 return 0;
67 }
68
69 int
otx2_nix_dev_reta_update(struct rte_eth_dev * eth_dev,struct rte_eth_rss_reta_entry64 * reta_conf,uint16_t reta_size)70 otx2_nix_dev_reta_update(struct rte_eth_dev *eth_dev,
71 struct rte_eth_rss_reta_entry64 *reta_conf,
72 uint16_t reta_size)
73 {
74 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
75 struct otx2_rss_info *rss = &dev->rss_info;
76 int rc, i, j;
77 int idx = 0;
78
79 rc = -EINVAL;
80 if (reta_size != dev->rss_info.rss_size) {
81 otx2_err("Size of hash lookup table configured "
82 "(%d) doesn't match the number hardware can supported "
83 "(%d)", reta_size, dev->rss_info.rss_size);
84 goto fail;
85 }
86
87 /* Copy RETA table */
88 for (i = 0; i < (dev->rss_info.rss_size / RTE_RETA_GROUP_SIZE); i++) {
89 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++) {
90 if ((reta_conf[i].mask >> j) & 0x01)
91 rss->ind_tbl[idx] = reta_conf[i].reta[j];
92 idx++;
93 }
94 }
95
96 return otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl);
97
98 fail:
99 return rc;
100 }
101
102 int
otx2_nix_dev_reta_query(struct rte_eth_dev * eth_dev,struct rte_eth_rss_reta_entry64 * reta_conf,uint16_t reta_size)103 otx2_nix_dev_reta_query(struct rte_eth_dev *eth_dev,
104 struct rte_eth_rss_reta_entry64 *reta_conf,
105 uint16_t reta_size)
106 {
107 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
108 struct otx2_rss_info *rss = &dev->rss_info;
109 int rc, i, j;
110
111 rc = -EINVAL;
112
113 if (reta_size != dev->rss_info.rss_size) {
114 otx2_err("Size of hash lookup table configured "
115 "(%d) doesn't match the number hardware can supported "
116 "(%d)", reta_size, dev->rss_info.rss_size);
117 goto fail;
118 }
119
120 /* Copy RETA table */
121 for (i = 0; i < (dev->rss_info.rss_size / RTE_RETA_GROUP_SIZE); i++) {
122 for (j = 0; j < RTE_RETA_GROUP_SIZE; j++)
123 if ((reta_conf[i].mask >> j) & 0x01)
124 reta_conf[i].reta[j] = rss->ind_tbl[j];
125 }
126
127 return 0;
128
129 fail:
130 return rc;
131 }
132
133 void
otx2_nix_rss_set_key(struct otx2_eth_dev * dev,uint8_t * key,uint32_t key_len)134 otx2_nix_rss_set_key(struct otx2_eth_dev *dev, uint8_t *key,
135 uint32_t key_len)
136 {
137 const uint8_t default_key[NIX_HASH_KEY_SIZE] = {
138 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
139 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
140 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
141 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
142 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD,
143 0xFE, 0xED, 0x0B, 0xAD, 0xFE, 0xED, 0x0B, 0xAD
144 };
145 struct otx2_rss_info *rss = &dev->rss_info;
146 uint64_t *keyptr;
147 uint64_t val;
148 uint32_t idx;
149
150 if (key == NULL || key == 0) {
151 keyptr = (uint64_t *)(uintptr_t)default_key;
152 key_len = NIX_HASH_KEY_SIZE;
153 memset(rss->key, 0, key_len);
154 } else {
155 memcpy(rss->key, key, key_len);
156 keyptr = (uint64_t *)rss->key;
157 }
158
159 for (idx = 0; idx < (key_len >> 3); idx++) {
160 val = rte_cpu_to_be_64(*keyptr);
161 otx2_write64(val, dev->base + NIX_LF_RX_SECRETX(idx));
162 keyptr++;
163 }
164 }
165
166 static void
rss_get_key(struct otx2_eth_dev * dev,uint8_t * key)167 rss_get_key(struct otx2_eth_dev *dev, uint8_t *key)
168 {
169 uint64_t *keyptr = (uint64_t *)key;
170 uint64_t val;
171 int idx;
172
173 for (idx = 0; idx < (NIX_HASH_KEY_SIZE >> 3); idx++) {
174 val = otx2_read64(dev->base + NIX_LF_RX_SECRETX(idx));
175 *keyptr = rte_be_to_cpu_64(val);
176 keyptr++;
177 }
178 }
179
180 #define RSS_IPV4_ENABLE ( \
181 ETH_RSS_IPV4 | \
182 ETH_RSS_FRAG_IPV4 | \
183 ETH_RSS_NONFRAG_IPV4_UDP | \
184 ETH_RSS_NONFRAG_IPV4_TCP | \
185 ETH_RSS_NONFRAG_IPV4_SCTP)
186
187 #define RSS_IPV6_ENABLE ( \
188 ETH_RSS_IPV6 | \
189 ETH_RSS_FRAG_IPV6 | \
190 ETH_RSS_NONFRAG_IPV6_UDP | \
191 ETH_RSS_NONFRAG_IPV6_TCP | \
192 ETH_RSS_NONFRAG_IPV6_SCTP)
193
194 #define RSS_IPV6_EX_ENABLE ( \
195 ETH_RSS_IPV6_EX | \
196 ETH_RSS_IPV6_TCP_EX | \
197 ETH_RSS_IPV6_UDP_EX)
198
199 #define RSS_MAX_LEVELS 3
200
201 #define RSS_IPV4_INDEX 0
202 #define RSS_IPV6_INDEX 1
203 #define RSS_TCP_INDEX 2
204 #define RSS_UDP_INDEX 3
205 #define RSS_SCTP_INDEX 4
206 #define RSS_DMAC_INDEX 5
207
208 uint32_t
otx2_rss_ethdev_to_nix(struct otx2_eth_dev * dev,uint64_t ethdev_rss,uint8_t rss_level)209 otx2_rss_ethdev_to_nix(struct otx2_eth_dev *dev, uint64_t ethdev_rss,
210 uint8_t rss_level)
211 {
212 uint32_t flow_key_type[RSS_MAX_LEVELS][6] = {
213 {
214 FLOW_KEY_TYPE_IPV4, FLOW_KEY_TYPE_IPV6,
215 FLOW_KEY_TYPE_TCP, FLOW_KEY_TYPE_UDP,
216 FLOW_KEY_TYPE_SCTP, FLOW_KEY_TYPE_ETH_DMAC
217 },
218 {
219 FLOW_KEY_TYPE_INNR_IPV4, FLOW_KEY_TYPE_INNR_IPV6,
220 FLOW_KEY_TYPE_INNR_TCP, FLOW_KEY_TYPE_INNR_UDP,
221 FLOW_KEY_TYPE_INNR_SCTP, FLOW_KEY_TYPE_INNR_ETH_DMAC
222 },
223 {
224 FLOW_KEY_TYPE_IPV4 | FLOW_KEY_TYPE_INNR_IPV4,
225 FLOW_KEY_TYPE_IPV6 | FLOW_KEY_TYPE_INNR_IPV6,
226 FLOW_KEY_TYPE_TCP | FLOW_KEY_TYPE_INNR_TCP,
227 FLOW_KEY_TYPE_UDP | FLOW_KEY_TYPE_INNR_UDP,
228 FLOW_KEY_TYPE_SCTP | FLOW_KEY_TYPE_INNR_SCTP,
229 FLOW_KEY_TYPE_ETH_DMAC | FLOW_KEY_TYPE_INNR_ETH_DMAC
230 }
231 };
232 uint32_t flowkey_cfg = 0;
233
234 dev->rss_info.nix_rss = ethdev_rss;
235
236 if (ethdev_rss & ETH_RSS_L2_PAYLOAD &&
237 dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_LEN_90B) {
238 flowkey_cfg |= FLOW_KEY_TYPE_CH_LEN_90B;
239 }
240
241 if (ethdev_rss & ETH_RSS_C_VLAN)
242 flowkey_cfg |= FLOW_KEY_TYPE_VLAN;
243
244 if (ethdev_rss & ETH_RSS_L3_SRC_ONLY)
245 flowkey_cfg |= FLOW_KEY_TYPE_L3_SRC;
246
247 if (ethdev_rss & ETH_RSS_L3_DST_ONLY)
248 flowkey_cfg |= FLOW_KEY_TYPE_L3_DST;
249
250 if (ethdev_rss & ETH_RSS_L4_SRC_ONLY)
251 flowkey_cfg |= FLOW_KEY_TYPE_L4_SRC;
252
253 if (ethdev_rss & ETH_RSS_L4_DST_ONLY)
254 flowkey_cfg |= FLOW_KEY_TYPE_L4_DST;
255
256 if (ethdev_rss & RSS_IPV4_ENABLE)
257 flowkey_cfg |= flow_key_type[rss_level][RSS_IPV4_INDEX];
258
259 if (ethdev_rss & RSS_IPV6_ENABLE)
260 flowkey_cfg |= flow_key_type[rss_level][RSS_IPV6_INDEX];
261
262 if (ethdev_rss & ETH_RSS_TCP)
263 flowkey_cfg |= flow_key_type[rss_level][RSS_TCP_INDEX];
264
265 if (ethdev_rss & ETH_RSS_UDP)
266 flowkey_cfg |= flow_key_type[rss_level][RSS_UDP_INDEX];
267
268 if (ethdev_rss & ETH_RSS_SCTP)
269 flowkey_cfg |= flow_key_type[rss_level][RSS_SCTP_INDEX];
270
271 if (ethdev_rss & ETH_RSS_L2_PAYLOAD)
272 flowkey_cfg |= flow_key_type[rss_level][RSS_DMAC_INDEX];
273
274 if (ethdev_rss & RSS_IPV6_EX_ENABLE)
275 flowkey_cfg |= FLOW_KEY_TYPE_IPV6_EXT;
276
277 if (ethdev_rss & ETH_RSS_PORT)
278 flowkey_cfg |= FLOW_KEY_TYPE_PORT;
279
280 if (ethdev_rss & ETH_RSS_NVGRE)
281 flowkey_cfg |= FLOW_KEY_TYPE_NVGRE;
282
283 if (ethdev_rss & ETH_RSS_VXLAN)
284 flowkey_cfg |= FLOW_KEY_TYPE_VXLAN;
285
286 if (ethdev_rss & ETH_RSS_GENEVE)
287 flowkey_cfg |= FLOW_KEY_TYPE_GENEVE;
288
289 if (ethdev_rss & ETH_RSS_GTPU)
290 flowkey_cfg |= FLOW_KEY_TYPE_GTPU;
291
292 return flowkey_cfg;
293 }
294
295 int
otx2_rss_set_hf(struct otx2_eth_dev * dev,uint32_t flowkey_cfg,uint8_t * alg_idx,uint8_t group,int mcam_index)296 otx2_rss_set_hf(struct otx2_eth_dev *dev, uint32_t flowkey_cfg,
297 uint8_t *alg_idx, uint8_t group, int mcam_index)
298 {
299 struct nix_rss_flowkey_cfg_rsp *rss_rsp;
300 struct otx2_mbox *mbox = dev->mbox;
301 struct nix_rss_flowkey_cfg *cfg;
302 int rc;
303
304 rc = -EINVAL;
305
306 dev->rss_info.flowkey_cfg = flowkey_cfg;
307
308 cfg = otx2_mbox_alloc_msg_nix_rss_flowkey_cfg(mbox);
309
310 cfg->flowkey_cfg = flowkey_cfg;
311 cfg->mcam_index = mcam_index; /* -1 indicates default group */
312 cfg->group = group; /* 0 is default group */
313
314 rc = otx2_mbox_process_msg(mbox, (void *)&rss_rsp);
315 if (rc)
316 return rc;
317
318 if (alg_idx)
319 *alg_idx = rss_rsp->alg_idx;
320
321 return rc;
322 }
323
324 int
otx2_nix_rss_hash_update(struct rte_eth_dev * eth_dev,struct rte_eth_rss_conf * rss_conf)325 otx2_nix_rss_hash_update(struct rte_eth_dev *eth_dev,
326 struct rte_eth_rss_conf *rss_conf)
327 {
328 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
329 uint8_t rss_hash_level;
330 uint32_t flowkey_cfg;
331 uint8_t alg_idx;
332 int rc;
333
334 rc = -EINVAL;
335
336 if (rss_conf->rss_key && rss_conf->rss_key_len != NIX_HASH_KEY_SIZE) {
337 otx2_err("Hash key size mismatch %d vs %d",
338 rss_conf->rss_key_len, NIX_HASH_KEY_SIZE);
339 goto fail;
340 }
341
342 if (rss_conf->rss_key)
343 otx2_nix_rss_set_key(dev, rss_conf->rss_key,
344 (uint32_t)rss_conf->rss_key_len);
345
346 rss_hash_level = ETH_RSS_LEVEL(rss_conf->rss_hf);
347 if (rss_hash_level)
348 rss_hash_level -= 1;
349 flowkey_cfg =
350 otx2_rss_ethdev_to_nix(dev, rss_conf->rss_hf, rss_hash_level);
351
352 rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx,
353 NIX_DEFAULT_RSS_CTX_GROUP,
354 NIX_DEFAULT_RSS_MCAM_IDX);
355 if (rc) {
356 otx2_err("Failed to set RSS hash function rc=%d", rc);
357 return rc;
358 }
359
360 dev->rss_info.alg_idx = alg_idx;
361
362 fail:
363 return rc;
364 }
365
366 int
otx2_nix_rss_hash_conf_get(struct rte_eth_dev * eth_dev,struct rte_eth_rss_conf * rss_conf)367 otx2_nix_rss_hash_conf_get(struct rte_eth_dev *eth_dev,
368 struct rte_eth_rss_conf *rss_conf)
369 {
370 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
371
372 if (rss_conf->rss_key)
373 rss_get_key(dev, rss_conf->rss_key);
374
375 rss_conf->rss_key_len = NIX_HASH_KEY_SIZE;
376 rss_conf->rss_hf = dev->rss_info.nix_rss;
377
378 return 0;
379 }
380
381 int
otx2_nix_rss_config(struct rte_eth_dev * eth_dev)382 otx2_nix_rss_config(struct rte_eth_dev *eth_dev)
383 {
384 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
385 uint32_t idx, qcnt = eth_dev->data->nb_rx_queues;
386 uint8_t rss_hash_level;
387 uint32_t flowkey_cfg;
388 uint64_t rss_hf;
389 uint8_t alg_idx;
390 int rc;
391
392 /* Skip further configuration if selected mode is not RSS */
393 if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS || !qcnt)
394 return 0;
395
396 /* Update default RSS key and cfg */
397 otx2_nix_rss_set_key(dev, NULL, 0);
398
399 /* Update default RSS RETA */
400 for (idx = 0; idx < dev->rss_info.rss_size; idx++)
401 dev->rss_info.ind_tbl[idx] = idx % qcnt;
402
403 /* Init RSS table context */
404 rc = otx2_nix_rss_tbl_init(dev, 0, dev->rss_info.ind_tbl);
405 if (rc) {
406 otx2_err("Failed to init RSS table rc=%d", rc);
407 return rc;
408 }
409
410 rss_hf = eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf;
411 rss_hash_level = ETH_RSS_LEVEL(rss_hf);
412 if (rss_hash_level)
413 rss_hash_level -= 1;
414 flowkey_cfg = otx2_rss_ethdev_to_nix(dev, rss_hf, rss_hash_level);
415
416 rc = otx2_rss_set_hf(dev, flowkey_cfg, &alg_idx,
417 NIX_DEFAULT_RSS_CTX_GROUP,
418 NIX_DEFAULT_RSS_MCAM_IDX);
419 if (rc) {
420 otx2_err("Failed to set RSS hash function rc=%d", rc);
421 return rc;
422 }
423
424 dev->rss_info.alg_idx = alg_idx;
425
426 return 0;
427 }
428