xref: /dpdk/drivers/net/dpaa2/base/dpaa2_hw_dpni.c (revision d38febb08d57fec29fed27a2d12a507fc6fcdfa1)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
4  *   Copyright 2016-2021 NXP
5  *
6  */
7 
8 #include <time.h>
9 #include <net/if.h>
10 
11 #include <rte_mbuf.h>
12 #include <ethdev_driver.h>
13 #include <rte_malloc.h>
14 #include <rte_memcpy.h>
15 #include <rte_string_fns.h>
16 #include <rte_cycles.h>
17 #include <rte_kvargs.h>
18 #include <rte_dev.h>
19 
20 #include <dpaa2_pmd_logs.h>
21 #include <dpaa2_hw_pvt.h>
22 #include <dpaa2_hw_mempool.h>
23 
24 #include "../dpaa2_ethdev.h"
25 
26 int
27 dpaa2_distset_to_dpkg_profile_cfg(
28 		uint64_t req_dist_set,
29 		struct dpkg_profile_cfg *kg_cfg);
30 
31 int
32 rte_pmd_dpaa2_set_custom_hash(uint16_t port_id,
33 			      uint16_t offset,
34 			      uint8_t size)
35 {
36 	struct rte_eth_dev *eth_dev = &rte_eth_devices[port_id];
37 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
38 	struct fsl_mc_io *dpni = priv->hw;
39 	struct dpni_rx_tc_dist_cfg tc_cfg;
40 	struct dpkg_profile_cfg kg_cfg;
41 	void *p_params;
42 	int ret, tc_index = 0;
43 
44 	if (!rte_eth_dev_is_valid_port(port_id)) {
45 		DPAA2_PMD_WARN("Invalid port id %u", port_id);
46 		return -EINVAL;
47 	}
48 
49 	if (strcmp(eth_dev->device->driver->name,
50 			RTE_STR(NET_DPAA2_PMD_DRIVER_NAME))) {
51 		DPAA2_PMD_WARN("Not a valid dpaa2 port");
52 		return -EINVAL;
53 	}
54 
55 	p_params = rte_zmalloc(
56 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
57 	if (!p_params) {
58 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
59 		return -ENOMEM;
60 	}
61 
62 	kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_DATA;
63 	kg_cfg.extracts[0].extract.from_data.offset = offset;
64 	kg_cfg.extracts[0].extract.from_data.size = size;
65 	kg_cfg.extracts[0].num_of_byte_masks = 0;
66 	kg_cfg.num_extracts = 1;
67 
68 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
69 	if (ret) {
70 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
71 		rte_free(p_params);
72 		return ret;
73 	}
74 
75 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
76 	tc_cfg.key_cfg_iova = (size_t)(DPAA2_VADDR_TO_IOVA(p_params));
77 	tc_cfg.dist_size = eth_dev->data->nb_rx_queues;
78 	tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
79 
80 	ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW, priv->token, tc_index,
81 				  &tc_cfg);
82 	rte_free(p_params);
83 	if (ret) {
84 		DPAA2_PMD_ERR(
85 			     "Setting distribution for Rx failed with err: %d",
86 			     ret);
87 		return ret;
88 	}
89 
90 	return 0;
91 }
92 
93 int
94 dpaa2_setup_flow_dist(struct rte_eth_dev *eth_dev,
95 	uint64_t req_dist_set, int tc_index)
96 {
97 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
98 	struct fsl_mc_io *dpni = priv->hw;
99 	struct dpni_rx_dist_cfg tc_cfg;
100 	struct dpkg_profile_cfg kg_cfg;
101 	void *p_params;
102 	int ret, tc_dist_queues;
103 
104 	/*TC distribution size is set with dist_queues or
105 	 * nb_rx_queues % dist_queues in order of TC priority index.
106 	 * Calculating dist size for this tc_index:-
107 	 */
108 	tc_dist_queues = eth_dev->data->nb_rx_queues -
109 		tc_index * priv->dist_queues;
110 	if (tc_dist_queues <= 0) {
111 		DPAA2_PMD_INFO("No distribution on TC%d", tc_index);
112 		return 0;
113 	}
114 
115 	if (tc_dist_queues > priv->dist_queues)
116 		tc_dist_queues = priv->dist_queues;
117 
118 	p_params = rte_malloc(
119 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
120 	if (!p_params) {
121 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
122 		return -ENOMEM;
123 	}
124 
125 	memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
126 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
127 
128 	ret = dpaa2_distset_to_dpkg_profile_cfg(req_dist_set, &kg_cfg);
129 	if (ret) {
130 		DPAA2_PMD_ERR("Given RSS Hash (%" PRIx64 ") not supported",
131 			      req_dist_set);
132 		rte_free(p_params);
133 		return ret;
134 	}
135 
136 	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
137 	tc_cfg.dist_size = tc_dist_queues;
138 	tc_cfg.enable = true;
139 	tc_cfg.tc = tc_index;
140 
141 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
142 	if (ret) {
143 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
144 		rte_free(p_params);
145 		return ret;
146 	}
147 
148 	ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token, &tc_cfg);
149 	rte_free(p_params);
150 	if (ret) {
151 		DPAA2_PMD_ERR(
152 			     "Setting distribution for Rx failed with err: %d",
153 			     ret);
154 		return ret;
155 	}
156 
157 	return 0;
158 }
159 
160 int dpaa2_remove_flow_dist(
161 	struct rte_eth_dev *eth_dev,
162 	uint8_t tc_index)
163 {
164 	struct dpaa2_dev_priv *priv = eth_dev->data->dev_private;
165 	struct fsl_mc_io *dpni = priv->hw;
166 	struct dpni_rx_dist_cfg tc_cfg;
167 	struct dpkg_profile_cfg kg_cfg;
168 	void *p_params;
169 	int ret;
170 
171 	p_params = rte_malloc(
172 		NULL, DIST_PARAM_IOVA_SIZE, RTE_CACHE_LINE_SIZE);
173 	if (!p_params) {
174 		DPAA2_PMD_ERR("Unable to allocate flow-dist parameters");
175 		return -ENOMEM;
176 	}
177 
178 	memset(&tc_cfg, 0, sizeof(struct dpni_rx_dist_cfg));
179 	tc_cfg.dist_size = 0;
180 	tc_cfg.key_cfg_iova = (uint64_t)(DPAA2_VADDR_TO_IOVA(p_params));
181 	tc_cfg.enable = true;
182 	tc_cfg.tc = tc_index;
183 
184 	memset(p_params, 0, DIST_PARAM_IOVA_SIZE);
185 	kg_cfg.num_extracts = 0;
186 	ret = dpkg_prepare_key_cfg(&kg_cfg, p_params);
187 	if (ret) {
188 		DPAA2_PMD_ERR("Unable to prepare extract parameters");
189 		rte_free(p_params);
190 		return ret;
191 	}
192 
193 	ret = dpni_set_rx_hash_dist(dpni, CMD_PRI_LOW, priv->token,
194 			&tc_cfg);
195 	rte_free(p_params);
196 	if (ret)
197 		DPAA2_PMD_ERR(
198 			     "Setting distribution for Rx failed with err: %d",
199 			     ret);
200 	return ret;
201 }
202 
203 int
204 dpaa2_distset_to_dpkg_profile_cfg(
205 		uint64_t req_dist_set,
206 		struct dpkg_profile_cfg *kg_cfg)
207 {
208 	uint32_t loop = 0, i = 0;
209 	uint64_t dist_field = 0;
210 	int l2_configured = 0, l3_configured = 0;
211 	int l4_configured = 0, sctp_configured = 0;
212 	int mpls_configured = 0;
213 
214 	memset(kg_cfg, 0, sizeof(struct dpkg_profile_cfg));
215 	while (req_dist_set) {
216 		if (req_dist_set % 2 != 0) {
217 			dist_field = 1ULL << loop;
218 			switch (dist_field) {
219 			case ETH_RSS_L2_PAYLOAD:
220 
221 				if (l2_configured)
222 					break;
223 				l2_configured = 1;
224 
225 				kg_cfg->extracts[i].extract.from_hdr.prot =
226 					NET_PROT_ETH;
227 				kg_cfg->extracts[i].extract.from_hdr.field =
228 					NH_FLD_ETH_TYPE;
229 				kg_cfg->extracts[i].type =
230 					DPKG_EXTRACT_FROM_HDR;
231 				kg_cfg->extracts[i].extract.from_hdr.type =
232 					DPKG_FULL_FIELD;
233 				i++;
234 			break;
235 
236 			case ETH_RSS_MPLS:
237 
238 				if (mpls_configured)
239 					break;
240 				mpls_configured = 1;
241 
242 				kg_cfg->extracts[i].extract.from_hdr.prot =
243 					NET_PROT_MPLS;
244 				kg_cfg->extracts[i].extract.from_hdr.field =
245 					NH_FLD_MPLS_MPLSL_1;
246 				kg_cfg->extracts[i].type =
247 					DPKG_EXTRACT_FROM_HDR;
248 				kg_cfg->extracts[i].extract.from_hdr.type =
249 					DPKG_FULL_FIELD;
250 				i++;
251 
252 				kg_cfg->extracts[i].extract.from_hdr.prot =
253 					NET_PROT_MPLS;
254 				kg_cfg->extracts[i].extract.from_hdr.field =
255 					NH_FLD_MPLS_MPLSL_2;
256 				kg_cfg->extracts[i].type =
257 					DPKG_EXTRACT_FROM_HDR;
258 				kg_cfg->extracts[i].extract.from_hdr.type =
259 					DPKG_FULL_FIELD;
260 				i++;
261 
262 				kg_cfg->extracts[i].extract.from_hdr.prot =
263 					NET_PROT_MPLS;
264 				kg_cfg->extracts[i].extract.from_hdr.field =
265 					NH_FLD_MPLS_MPLSL_N;
266 				kg_cfg->extracts[i].type =
267 					DPKG_EXTRACT_FROM_HDR;
268 				kg_cfg->extracts[i].extract.from_hdr.type =
269 					DPKG_FULL_FIELD;
270 				i++;
271 				break;
272 
273 			case ETH_RSS_IPV4:
274 			case ETH_RSS_FRAG_IPV4:
275 			case ETH_RSS_NONFRAG_IPV4_OTHER:
276 			case ETH_RSS_IPV6:
277 			case ETH_RSS_FRAG_IPV6:
278 			case ETH_RSS_NONFRAG_IPV6_OTHER:
279 			case ETH_RSS_IPV6_EX:
280 
281 				if (l3_configured)
282 					break;
283 				l3_configured = 1;
284 
285 				kg_cfg->extracts[i].extract.from_hdr.prot =
286 					NET_PROT_IP;
287 				kg_cfg->extracts[i].extract.from_hdr.field =
288 					NH_FLD_IP_SRC;
289 				kg_cfg->extracts[i].type =
290 					DPKG_EXTRACT_FROM_HDR;
291 				kg_cfg->extracts[i].extract.from_hdr.type =
292 					DPKG_FULL_FIELD;
293 				i++;
294 
295 				kg_cfg->extracts[i].extract.from_hdr.prot =
296 					NET_PROT_IP;
297 				kg_cfg->extracts[i].extract.from_hdr.field =
298 					NH_FLD_IP_DST;
299 				kg_cfg->extracts[i].type =
300 					DPKG_EXTRACT_FROM_HDR;
301 				kg_cfg->extracts[i].extract.from_hdr.type =
302 					DPKG_FULL_FIELD;
303 				i++;
304 
305 				kg_cfg->extracts[i].extract.from_hdr.prot =
306 					NET_PROT_IP;
307 				kg_cfg->extracts[i].extract.from_hdr.field =
308 					NH_FLD_IP_PROTO;
309 				kg_cfg->extracts[i].type =
310 					DPKG_EXTRACT_FROM_HDR;
311 				kg_cfg->extracts[i].extract.from_hdr.type =
312 					DPKG_FULL_FIELD;
313 				kg_cfg->num_extracts++;
314 				i++;
315 			break;
316 
317 			case ETH_RSS_NONFRAG_IPV4_TCP:
318 			case ETH_RSS_NONFRAG_IPV6_TCP:
319 			case ETH_RSS_NONFRAG_IPV4_UDP:
320 			case ETH_RSS_NONFRAG_IPV6_UDP:
321 			case ETH_RSS_IPV6_TCP_EX:
322 			case ETH_RSS_IPV6_UDP_EX:
323 
324 				if (l4_configured)
325 					break;
326 				l4_configured = 1;
327 
328 				kg_cfg->extracts[i].extract.from_hdr.prot =
329 					NET_PROT_TCP;
330 				kg_cfg->extracts[i].extract.from_hdr.field =
331 					NH_FLD_TCP_PORT_SRC;
332 				kg_cfg->extracts[i].type =
333 					DPKG_EXTRACT_FROM_HDR;
334 				kg_cfg->extracts[i].extract.from_hdr.type =
335 					DPKG_FULL_FIELD;
336 				i++;
337 
338 				kg_cfg->extracts[i].extract.from_hdr.prot =
339 					NET_PROT_TCP;
340 				kg_cfg->extracts[i].extract.from_hdr.field =
341 					NH_FLD_TCP_PORT_SRC;
342 				kg_cfg->extracts[i].type =
343 					DPKG_EXTRACT_FROM_HDR;
344 				kg_cfg->extracts[i].extract.from_hdr.type =
345 					DPKG_FULL_FIELD;
346 				i++;
347 				break;
348 
349 			case ETH_RSS_NONFRAG_IPV4_SCTP:
350 			case ETH_RSS_NONFRAG_IPV6_SCTP:
351 
352 				if (sctp_configured)
353 					break;
354 				sctp_configured = 1;
355 
356 				kg_cfg->extracts[i].extract.from_hdr.prot =
357 					NET_PROT_SCTP;
358 				kg_cfg->extracts[i].extract.from_hdr.field =
359 					NH_FLD_SCTP_PORT_SRC;
360 				kg_cfg->extracts[i].type =
361 					DPKG_EXTRACT_FROM_HDR;
362 				kg_cfg->extracts[i].extract.from_hdr.type =
363 					DPKG_FULL_FIELD;
364 				i++;
365 
366 				kg_cfg->extracts[i].extract.from_hdr.prot =
367 					NET_PROT_SCTP;
368 				kg_cfg->extracts[i].extract.from_hdr.field =
369 					NH_FLD_SCTP_PORT_DST;
370 				kg_cfg->extracts[i].type =
371 					DPKG_EXTRACT_FROM_HDR;
372 				kg_cfg->extracts[i].extract.from_hdr.type =
373 					DPKG_FULL_FIELD;
374 				i++;
375 				break;
376 
377 			default:
378 				DPAA2_PMD_WARN(
379 				      "unsupported flow dist option 0x%" PRIx64,
380 					     dist_field);
381 				return -EINVAL;
382 			}
383 		}
384 		req_dist_set = req_dist_set >> 1;
385 		loop++;
386 	}
387 	kg_cfg->num_extracts = i;
388 	return 0;
389 }
390 
391 int
392 dpaa2_attach_bp_list(struct dpaa2_dev_priv *priv,
393 		     void *blist)
394 {
395 	/* Function to attach a DPNI with a buffer pool list. Buffer pool list
396 	 * handle is passed in blist.
397 	 */
398 	int32_t retcode;
399 	struct fsl_mc_io *dpni = priv->hw;
400 	struct dpni_pools_cfg bpool_cfg;
401 	struct dpaa2_bp_list *bp_list = (struct dpaa2_bp_list *)blist;
402 	struct dpni_buffer_layout layout;
403 	int tot_size;
404 
405 	/* ... rx buffer layout .
406 	 * Check alignment for buffer layouts first
407 	 */
408 
409 	/* ... rx buffer layout ... */
410 	tot_size = RTE_PKTMBUF_HEADROOM;
411 	tot_size = RTE_ALIGN_CEIL(tot_size, DPAA2_PACKET_LAYOUT_ALIGN);
412 
413 	memset(&layout, 0, sizeof(struct dpni_buffer_layout));
414 	layout.options = DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM |
415 			 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
416 			 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
417 			 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
418 			 DPNI_BUF_LAYOUT_OPT_TIMESTAMP |
419 			 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
420 
421 	layout.pass_timestamp = true;
422 	layout.pass_frame_status = 1;
423 	layout.private_data_size = DPAA2_FD_PTA_SIZE;
424 	layout.pass_parser_result = 1;
425 	layout.data_align = DPAA2_PACKET_LAYOUT_ALIGN;
426 	layout.data_head_room = tot_size - DPAA2_FD_PTA_SIZE -
427 				DPAA2_MBUF_HW_ANNOTATION;
428 	retcode = dpni_set_buffer_layout(dpni, CMD_PRI_LOW, priv->token,
429 					 DPNI_QUEUE_RX, &layout);
430 	if (retcode) {
431 		DPAA2_PMD_ERR("Error configuring buffer pool Rx layout (%d)",
432 			     retcode);
433 		return retcode;
434 	}
435 
436 	/*Attach buffer pool to the network interface as described by the user*/
437 	memset(&bpool_cfg, 0, sizeof(struct dpni_pools_cfg));
438 	bpool_cfg.num_dpbp = 1;
439 	bpool_cfg.pools[0].dpbp_id = bp_list->buf_pool.dpbp_node->dpbp_id;
440 	bpool_cfg.pools[0].backup_pool = 0;
441 	bpool_cfg.pools[0].buffer_size = RTE_ALIGN_CEIL(bp_list->buf_pool.size,
442 						DPAA2_PACKET_LAYOUT_ALIGN);
443 	bpool_cfg.pools[0].priority_mask = 0;
444 
445 	retcode = dpni_set_pools(dpni, CMD_PRI_LOW, priv->token, &bpool_cfg);
446 	if (retcode != 0) {
447 		DPAA2_PMD_ERR("Error configuring buffer pool on interface."
448 			      " bpid = %d error code = %d",
449 			      bpool_cfg.pools[0].dpbp_id, retcode);
450 		return retcode;
451 	}
452 
453 	priv->bp_list = bp_list;
454 	return 0;
455 }
456