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 uint64_t nt_os_get_time_monotonic_counter(void) 27 { 28 return rte_get_timer_cycles(); 29 } 30 31 /* Allocation size matching minimum alignment of specified size */ 32 uint64_t nt_util_align_size(uint64_t size) 33 { 34 return 1 << rte_log2_u64(size); 35 } 36 37 void nt_util_vfio_init(struct nt_util_vfio_impl *impl) 38 { 39 vfio_cb = *impl; 40 } 41 42 struct nt_dma_s *nt_dma_alloc(uint64_t size, uint64_t align, int numa) 43 { 44 int res; 45 struct nt_dma_s *vfio_addr; 46 47 vfio_addr = rte_malloc(NULL, sizeof(struct nt_dma_s), 0); 48 49 if (!vfio_addr) { 50 NT_LOG(ERR, GENERAL, "VFIO rte_malloc failed\n"); 51 return NULL; 52 } 53 54 void *addr = rte_malloc_socket(NULL, size, align, numa); 55 56 if (!addr) { 57 rte_free(vfio_addr); 58 NT_LOG(ERR, GENERAL, "VFIO rte_malloc_socket failed\n"); 59 return NULL; 60 } 61 62 res = vfio_cb.vfio_dma_map(0, addr, &vfio_addr->iova, nt_util_align_size(size)); 63 64 if (res != 0) { 65 rte_free(addr); 66 rte_free(vfio_addr); 67 NT_LOG(ERR, GENERAL, "VFIO nt_dma_map failed\n"); 68 return NULL; 69 } 70 71 vfio_addr->addr = (uint64_t)addr; 72 vfio_addr->size = nt_util_align_size(size); 73 74 NT_LOG(DBG, GENERAL, 75 "VFIO DMA alloc addr=%" PRIX64 ", iova=%" PRIX64 76 ", size=%" PRIX64 "align=0x%" PRIX64 "\n", 77 vfio_addr->addr, vfio_addr->iova, vfio_addr->size, align); 78 79 return vfio_addr; 80 } 81 82 void nt_dma_free(struct nt_dma_s *vfio_addr) 83 { 84 NT_LOG(DBG, GENERAL, "VFIO DMA free addr=%" PRIX64 ", iova=%" PRIX64 ", size=%" PRIX64 "\n", 85 vfio_addr->addr, vfio_addr->iova, vfio_addr->size); 86 87 int res = vfio_cb.vfio_dma_unmap(0, (void *)vfio_addr->addr, vfio_addr->iova, 88 vfio_addr->size); 89 90 if (res != 0) { 91 NT_LOG(WRN, GENERAL, 92 "VFIO DMA free FAILED addr=%" PRIX64 ", iova=%" PRIX64 ", size=%" PRIX64 "\n", 93 vfio_addr->addr, vfio_addr->iova, vfio_addr->size); 94 } 95 96 rte_free((void *)(vfio_addr->addr)); 97 rte_free(vfio_addr); 98 } 99 100 /* NOTE: please note the difference between RTE_ETH_SPEED_NUM_xxx and RTE_ETH_LINK_SPEED_xxx */ 101 int nt_link_speed_to_eth_speed_num(enum nt_link_speed_e nt_link_speed) 102 { 103 int eth_speed_num = RTE_ETH_SPEED_NUM_NONE; 104 105 switch (nt_link_speed) { 106 case NT_LINK_SPEED_10M: 107 eth_speed_num = RTE_ETH_SPEED_NUM_10M; 108 break; 109 110 case NT_LINK_SPEED_100M: 111 eth_speed_num = RTE_ETH_SPEED_NUM_100M; 112 break; 113 114 case NT_LINK_SPEED_1G: 115 eth_speed_num = RTE_ETH_SPEED_NUM_1G; 116 break; 117 118 case NT_LINK_SPEED_10G: 119 eth_speed_num = RTE_ETH_SPEED_NUM_10G; 120 break; 121 122 case NT_LINK_SPEED_25G: 123 eth_speed_num = RTE_ETH_SPEED_NUM_25G; 124 break; 125 126 case NT_LINK_SPEED_40G: 127 eth_speed_num = RTE_ETH_SPEED_NUM_40G; 128 break; 129 130 case NT_LINK_SPEED_50G: 131 eth_speed_num = RTE_ETH_SPEED_NUM_50G; 132 break; 133 134 case NT_LINK_SPEED_100G: 135 eth_speed_num = RTE_ETH_SPEED_NUM_100G; 136 break; 137 138 default: 139 eth_speed_num = RTE_ETH_SPEED_NUM_NONE; 140 break; 141 } 142 143 return eth_speed_num; 144 } 145 146 uint32_t nt_link_speed_capa_to_eth_speed_capa(int nt_link_speed_capa) 147 { 148 uint32_t eth_speed_capa = 0; 149 150 if (nt_link_speed_capa & NT_LINK_SPEED_10M) 151 eth_speed_capa |= RTE_ETH_LINK_SPEED_10M; 152 153 if (nt_link_speed_capa & NT_LINK_SPEED_100M) 154 eth_speed_capa |= RTE_ETH_LINK_SPEED_100M; 155 156 if (nt_link_speed_capa & NT_LINK_SPEED_1G) 157 eth_speed_capa |= RTE_ETH_LINK_SPEED_1G; 158 159 if (nt_link_speed_capa & NT_LINK_SPEED_10G) 160 eth_speed_capa |= RTE_ETH_LINK_SPEED_10G; 161 162 if (nt_link_speed_capa & NT_LINK_SPEED_25G) 163 eth_speed_capa |= RTE_ETH_LINK_SPEED_25G; 164 165 if (nt_link_speed_capa & NT_LINK_SPEED_40G) 166 eth_speed_capa |= RTE_ETH_LINK_SPEED_40G; 167 168 if (nt_link_speed_capa & NT_LINK_SPEED_50G) 169 eth_speed_capa |= RTE_ETH_LINK_SPEED_50G; 170 171 if (nt_link_speed_capa & NT_LINK_SPEED_100G) 172 eth_speed_capa |= RTE_ETH_LINK_SPEED_100G; 173 174 return eth_speed_capa; 175 } 176 177 /* Converts link speed provided in Mbps to NT specific definitions.*/ 178 nt_link_speed_t convert_link_speed(int link_speed_mbps) 179 { 180 switch (link_speed_mbps) { 181 case 10: 182 return NT_LINK_SPEED_10M; 183 184 case 100: 185 return NT_LINK_SPEED_100M; 186 187 case 1000: 188 return NT_LINK_SPEED_1G; 189 190 case 10000: 191 return NT_LINK_SPEED_10G; 192 193 case 40000: 194 return NT_LINK_SPEED_40G; 195 196 case 100000: 197 return NT_LINK_SPEED_100G; 198 199 case 50000: 200 return NT_LINK_SPEED_50G; 201 202 case 25000: 203 return NT_LINK_SPEED_25G; 204 205 default: 206 return NT_LINK_SPEED_UNKNOWN; 207 } 208 } 209 210 int nt_link_duplex_to_eth_duplex(enum nt_link_duplex_e nt_link_duplex) 211 { 212 int eth_link_duplex = 0; 213 214 switch (nt_link_duplex) { 215 case NT_LINK_DUPLEX_FULL: 216 eth_link_duplex = RTE_ETH_LINK_FULL_DUPLEX; 217 break; 218 219 case NT_LINK_DUPLEX_HALF: 220 eth_link_duplex = RTE_ETH_LINK_HALF_DUPLEX; 221 break; 222 223 case NT_LINK_DUPLEX_UNKNOWN: /* fall-through */ 224 default: 225 break; 226 } 227 228 return eth_link_duplex; 229 } 230