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