xref: /dpdk/drivers/net/ntnic/ntutil/nt_util.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * Copyright(c) 2023 Napatech A/S
4  */
5 
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <inttypes.h>
10 #include <assert.h>
11 
12 #include <rte_ethdev.h>
13 #include <rte_malloc.h>
14 
15 #include "ntlog.h"
16 #include "nt_util.h"
17 
18 static struct nt_util_vfio_impl vfio_cb;
19 
20 /* uses usleep which schedules out the calling thread */
21 void nt_os_wait_usec(int val)
22 {
23 	rte_delay_us_sleep(val);
24 }
25 
26 /* spins in a waiting loop calling pause asm instruction uses RDTSC - precise wait */
27 void nt_os_wait_usec_poll(int val)
28 {
29 	rte_delay_us(val);
30 }
31 
32 uint64_t nt_os_get_time_monotonic_counter(void)
33 {
34 	return rte_get_timer_cycles();
35 }
36 
37 /* Allocation size matching minimum alignment of specified size */
38 uint64_t nt_util_align_size(uint64_t size)
39 {
40 	uint64_t alignment_size = 1ULL << rte_log2_u64(size);
41 	return alignment_size;
42 }
43 
44 void nt_util_vfio_init(struct nt_util_vfio_impl *impl)
45 {
46 	vfio_cb = *impl;
47 }
48 
49 struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa)
50 {
51 	int res;
52 	struct nt_dma_s *vfio_addr;
53 
54 	vfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0);
55 
56 	if (!vfio_addr) {
57 		NT_LOG(ERR, GENERAL, "VFIO rte_malloc failed");
58 		return NULL;
59 	}
60 
61 	void *addr = rte_malloc_socket(NULL, size, align, numa);
62 
63 	if (!addr) {
64 		rte_free(vfio_addr);
65 		NT_LOG(ERR, GENERAL, "VFIO rte_malloc_socket failed");
66 		return NULL;
67 	}
68 
69 	res = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova, nt_util_align_size(size));
70 
71 	if (res != 0) {
72 		rte_free(addr);
73 		rte_free(vfio_addr);
74 		NT_LOG(ERR, GENERAL, "VFIO nt_dma_map failed");
75 		return NULL;
76 	}
77 
78 	vfio_addr->addr = (uint64_t)addr;
79 	vfio_addr->size = nt_util_align_size(size);
80 
81 	NT_LOG(DBG, GENERAL,
82 		"VFIO DMA alloc addr=%" PRIX64 ", iova=%" PRIX64
83 		", size=%" PRIX64 "align=0x%" PRIX64,
84 		vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align);
85 
86 	return vfio_addr;
87 }
88 
89 void nt_dma_free(struct nt_dma_s *vfio_addr)
90 {
91 	NT_LOG(DBG, GENERAL, "VFIO DMA free addr=%" PRIX64 ", iova=%" PRIX64 ", size=%" PRIX64,
92 		vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
93 
94 	int res = vfio_cb.vfio_dma_unmap(0, (void *)vfio_addr->addr, vfio_addr->iova,
95 			vfio_addr->size);
96 
97 	if (res != 0) {
98 		NT_LOG(WRN, GENERAL,
99 			"VFIO DMA free FAILED addr=%" PRIX64 ", iova=%" PRIX64 ", size=%" PRIX64,
100 			vfio_addr->addr, vfio_addr->iova, vfio_addr->size);
101 	}
102 
103 	rte_free((void *)(vfio_addr->addr));
104 	rte_free(vfio_addr);
105 }
106 
107 /* NOTE: please note the difference between RTE_ETH_SPEED_NUM_xxx and RTE_ETH_LINK_SPEED_xxx */
108 int nt_link_speed_to_eth_speed_num(enum nt_link_speed_e nt_link_speed)
109 {
110 	int eth_speed_num = RTE_ETH_SPEED_NUM_NONE;
111 
112 	switch (nt_link_speed) {
113 	case NT_LINK_SPEED_10M:
114 		eth_speed_num = RTE_ETH_SPEED_NUM_10M;
115 		break;
116 
117 	case NT_LINK_SPEED_100M:
118 		eth_speed_num = RTE_ETH_SPEED_NUM_100M;
119 		break;
120 
121 	case NT_LINK_SPEED_1G:
122 		eth_speed_num = RTE_ETH_SPEED_NUM_1G;
123 		break;
124 
125 	case NT_LINK_SPEED_10G:
126 		eth_speed_num = RTE_ETH_SPEED_NUM_10G;
127 		break;
128 
129 	case NT_LINK_SPEED_25G:
130 		eth_speed_num = RTE_ETH_SPEED_NUM_25G;
131 		break;
132 
133 	case NT_LINK_SPEED_40G:
134 		eth_speed_num = RTE_ETH_SPEED_NUM_40G;
135 		break;
136 
137 	case NT_LINK_SPEED_50G:
138 		eth_speed_num = RTE_ETH_SPEED_NUM_50G;
139 		break;
140 
141 	case NT_LINK_SPEED_100G:
142 		eth_speed_num = RTE_ETH_SPEED_NUM_100G;
143 		break;
144 
145 	default:
146 		eth_speed_num = RTE_ETH_SPEED_NUM_NONE;
147 		break;
148 	}
149 
150 	return eth_speed_num;
151 }
152 
153 uint32_t nt_link_speed_capa_to_eth_speed_capa(int nt_link_speed_capa)
154 {
155 	uint32_t eth_speed_capa = 0;
156 
157 	if (nt_link_speed_capa & NT_LINK_SPEED_10M)
158 		eth_speed_capa |= RTE_ETH_LINK_SPEED_10M;
159 
160 	if (nt_link_speed_capa & NT_LINK_SPEED_100M)
161 		eth_speed_capa |= RTE_ETH_LINK_SPEED_100M;
162 
163 	if (nt_link_speed_capa & NT_LINK_SPEED_1G)
164 		eth_speed_capa |= RTE_ETH_LINK_SPEED_1G;
165 
166 	if (nt_link_speed_capa & NT_LINK_SPEED_10G)
167 		eth_speed_capa |= RTE_ETH_LINK_SPEED_10G;
168 
169 	if (nt_link_speed_capa & NT_LINK_SPEED_25G)
170 		eth_speed_capa |= RTE_ETH_LINK_SPEED_25G;
171 
172 	if (nt_link_speed_capa & NT_LINK_SPEED_40G)
173 		eth_speed_capa |= RTE_ETH_LINK_SPEED_40G;
174 
175 	if (nt_link_speed_capa & NT_LINK_SPEED_50G)
176 		eth_speed_capa |= RTE_ETH_LINK_SPEED_50G;
177 
178 	if (nt_link_speed_capa & NT_LINK_SPEED_100G)
179 		eth_speed_capa |= RTE_ETH_LINK_SPEED_100G;
180 
181 	return eth_speed_capa;
182 }
183 
184 /* Converts link speed provided in Mbps to NT specific definitions.*/
185 nt_link_speed_t convert_link_speed(int link_speed_mbps)
186 {
187 	switch (link_speed_mbps) {
188 	case 10:
189 		return NT_LINK_SPEED_10M;
190 
191 	case 100:
192 		return NT_LINK_SPEED_100M;
193 
194 	case 1000:
195 		return NT_LINK_SPEED_1G;
196 
197 	case 10000:
198 		return NT_LINK_SPEED_10G;
199 
200 	case 40000:
201 		return NT_LINK_SPEED_40G;
202 
203 	case 100000:
204 		return NT_LINK_SPEED_100G;
205 
206 	case 50000:
207 		return NT_LINK_SPEED_50G;
208 
209 	case 25000:
210 		return NT_LINK_SPEED_25G;
211 
212 	default:
213 		return NT_LINK_SPEED_UNKNOWN;
214 	}
215 }
216 
217 int nt_link_duplex_to_eth_duplex(enum nt_link_duplex_e nt_link_duplex)
218 {
219 	int eth_link_duplex = 0;
220 
221 	switch (nt_link_duplex) {
222 	case NT_LINK_DUPLEX_FULL:
223 		eth_link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
224 		break;
225 
226 	case NT_LINK_DUPLEX_HALF:
227 		eth_link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
228 		break;
229 
230 	case NT_LINK_DUPLEX_UNKNOWN:	/* fall-through */
231 	default:
232 		break;
233 	}
234 
235 	return eth_link_duplex;
236 }
237