1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_internal/mock.h" 37 38 #include "spdk/env.h" 39 #include "spdk/queue.h" 40 41 /* 42 * NOTE: 43 * Functions in this file are mocks for SPDK based functions 44 * and work conceptually in the same way that mocks work in 45 * /lib/ut_mock. However, the globals that control the behavior 46 * of the mock are defined here, with each function, as 47 * opposed to being defined as part of the macro that defines 48 * the stub or wrapper for other types of functions. Be sure 49 * to use the correct global variable naming convention when 50 * working with these functions. See /lib/ut_mock for details. 51 */ 52 53 /* 54 * these stubs have a return value set with one of the MOCK_SET macros 55 */ 56 DEFINE_STUB(spdk_process_is_primary, bool, (void), true) 57 58 DEFINE_STUB_VP(spdk_memzone_lookup, (const char *name), NULL) 59 60 /* 61 * these mocks don't fit well with the library macro model because 62 * they do 'something' other than just return a pre-set value 63 */ 64 65 /* setup the mock control to pass thru by default */ 66 void *ut_p_spdk_memzone_reserve = MOCK_PASS_THRU_P; 67 void * 68 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) 69 { 70 if (ut_p_spdk_memzone_reserve && 71 ut_p_spdk_memzone_reserve == MOCK_PASS_THRU_P) { 72 return malloc(len); 73 } else { 74 return ut_p_spdk_memzone_reserve; 75 } 76 } 77 78 /* setup the mock control to pass thru by default */ 79 void *ut_p_spdk_memzone_reserve_aligned = MOCK_PASS_THRU_P; 80 void * 81 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id, 82 unsigned flags, unsigned align) 83 { 84 if (ut_p_spdk_memzone_reserve_aligned && 85 ut_p_spdk_memzone_reserve_aligned == MOCK_PASS_THRU_P) { 86 return malloc(len); 87 } else { 88 return ut_p_spdk_memzone_reserve_aligned; 89 } 90 } 91 92 void * 93 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) 94 { 95 void *buf = NULL; 96 if (posix_memalign(&buf, align, size)) { 97 return NULL; 98 } 99 if (phys_addr) { 100 *phys_addr = (uint64_t)buf; 101 } 102 return buf; 103 } 104 105 int ut_spdk_dma_zmalloc = (int)MOCK_PASS_THRU; 106 void *ut_p_spdk_dma_zmalloc = &ut_spdk_dma_zmalloc; 107 void * 108 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr) 109 { 110 if (ut_p_spdk_dma_zmalloc && 111 ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) { 112 void *buf = spdk_dma_malloc(size, align, phys_addr); 113 114 if (buf != NULL) { 115 memset(buf, 0, size); 116 } 117 return buf; 118 } else { 119 return ut_p_spdk_dma_zmalloc; 120 } 121 } 122 123 void * 124 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 125 { 126 return spdk_dma_malloc(size, align, phys_addr); 127 } 128 129 void * 130 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 131 { 132 return spdk_dma_zmalloc(size, align, phys_addr); 133 } 134 135 void * 136 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr) 137 { 138 return realloc(buf, size); 139 } 140 141 void spdk_dma_free(void *buf) 142 { 143 if (ut_p_spdk_dma_zmalloc && 144 ut_spdk_dma_zmalloc == (int)MOCK_PASS_THRU) { 145 free(buf); 146 } 147 } 148 149 bool ut_fail_vtophys = false; 150 uint64_t spdk_vtophys(void *buf) 151 { 152 if (ut_fail_vtophys) { 153 return (uint64_t) - 1; 154 } else { 155 return (uintptr_t)buf; 156 } 157 } 158 159 void 160 spdk_memzone_dump(FILE *f) 161 { 162 return; 163 } 164 165 int 166 spdk_memzone_free(const char *name) 167 { 168 return 0; 169 } 170 171 struct test_mempool { 172 size_t count; 173 }; 174 175 struct spdk_mempool * 176 spdk_mempool_create(const char *name, size_t count, 177 size_t ele_size, size_t cache_size, int socket_id) 178 { 179 struct test_mempool *mp; 180 181 mp = calloc(1, sizeof(*mp)); 182 if (mp == NULL) { 183 return NULL; 184 } 185 186 mp->count = count; 187 188 return (struct spdk_mempool *)mp; 189 } 190 191 void 192 spdk_mempool_free(struct spdk_mempool *_mp) 193 { 194 struct test_mempool *mp = (struct test_mempool *)_mp; 195 196 free(mp); 197 } 198 199 void * 200 spdk_mempool_get(struct spdk_mempool *_mp) 201 { 202 struct test_mempool *mp = (struct test_mempool *)_mp; 203 void *buf; 204 205 if (mp && mp->count == 0) { 206 return NULL; 207 } 208 209 if (posix_memalign(&buf, 64, 0x1000)) { 210 return NULL; 211 } else { 212 if (mp) { 213 mp->count--; 214 } 215 return buf; 216 } 217 } 218 219 void 220 spdk_mempool_put(struct spdk_mempool *_mp, void *ele) 221 { 222 struct test_mempool *mp = (struct test_mempool *)_mp; 223 224 if (mp) { 225 mp->count++; 226 } 227 free(ele); 228 } 229 230 void 231 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count) 232 { 233 for (size_t i = 0; i < count; i++) { 234 spdk_mempool_put(mp, ele_arr[i]); 235 } 236 } 237 238 size_t 239 spdk_mempool_count(const struct spdk_mempool *_mp) 240 { 241 struct test_mempool *mp = (struct test_mempool *)_mp; 242 243 if (mp) { 244 return mp->count; 245 } else { 246 return 1024; 247 } 248 } 249 250 struct spdk_ring_ele { 251 void *ele; 252 TAILQ_ENTRY(spdk_ring_ele) link; 253 }; 254 255 struct spdk_ring { 256 TAILQ_HEAD(, spdk_ring_ele) elements; 257 }; 258 259 struct spdk_ring * 260 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id) 261 { 262 struct spdk_ring *ring; 263 264 ring = calloc(1, sizeof(*ring)); 265 if (ring) { 266 TAILQ_INIT(&ring->elements); 267 } 268 269 return ring; 270 } 271 272 273 void 274 spdk_ring_free(struct spdk_ring *ring) 275 { 276 free(ring); 277 } 278 279 size_t 280 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count) 281 { 282 struct spdk_ring_ele *ele; 283 size_t i; 284 285 for (i = 0; i < count; i++) { 286 ele = calloc(1, sizeof(*ele)); 287 if (!ele) { 288 break; 289 } 290 291 ele->ele = objs[i]; 292 TAILQ_INSERT_TAIL(&ring->elements, ele, link); 293 } 294 295 return i; 296 } 297 298 size_t 299 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count) 300 { 301 struct spdk_ring_ele *ele, *tmp; 302 size_t i = 0; 303 304 if (count == 0) { 305 return 0; 306 } 307 308 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) { 309 TAILQ_REMOVE(&ring->elements, ele, link); 310 objs[i] = ele->ele; 311 free(ele); 312 i++; 313 if (i >= count) { 314 break; 315 } 316 } 317 318 return i; 319 320 } 321 322 uint64_t ut_tsc = 0; 323 uint64_t spdk_get_ticks(void) 324 { 325 return ut_tsc; 326 } 327 328 uint64_t spdk_get_ticks_hz(void) 329 { 330 return 1000000; 331 } 332 333 void spdk_delay_us(unsigned int us) 334 { 335 ut_tsc += us; 336 } 337 338 int 339 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf) 340 { 341 unsigned domain, bus, dev, func; 342 343 if (addr == NULL || bdf == NULL) { 344 return -EINVAL; 345 } 346 347 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) || 348 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) { 349 /* Matched a full address - all variables are initialized */ 350 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) { 351 func = 0; 352 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) || 353 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) { 354 domain = 0; 355 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) || 356 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) { 357 domain = 0; 358 func = 0; 359 } else { 360 return -EINVAL; 361 } 362 363 if (bus > 0xFF || dev > 0x1F || func > 7) { 364 return -EINVAL; 365 } 366 367 addr->domain = domain; 368 addr->bus = bus; 369 addr->dev = dev; 370 addr->func = func; 371 372 return 0; 373 } 374 375 int 376 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr) 377 { 378 int rc; 379 380 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x", 381 addr->domain, addr->bus, 382 addr->dev, addr->func); 383 384 if (rc > 0 && (size_t)rc < sz) { 385 return 0; 386 } 387 388 return -1; 389 } 390 391 int 392 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2) 393 { 394 if (a1->domain > a2->domain) { 395 return 1; 396 } else if (a1->domain < a2->domain) { 397 return -1; 398 } else if (a1->bus > a2->bus) { 399 return 1; 400 } else if (a1->bus < a2->bus) { 401 return -1; 402 } else if (a1->dev > a2->dev) { 403 return 1; 404 } else if (a1->dev < a2->dev) { 405 return -1; 406 } else if (a1->func > a2->func) { 407 return 1; 408 } else if (a1->func < a2->func) { 409 return -1; 410 } 411 412 return 0; 413 } 414