xref: /f-stack/dpdk/drivers/net/octeontx2/otx2_rss.c (revision 2d9fd380)
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