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 DEFINE_STUB(spdk_process_is_primary, bool, (void), true) 42 DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL) 43 DEFINE_STUB(spdk_pci_nvme_get_driver, struct spdk_pci_driver *, (void), NULL) 44 DEFINE_STUB(spdk_pci_ioat_get_driver, struct spdk_pci_driver *, (void), NULL) 45 DEFINE_STUB(spdk_pci_virtio_get_driver, struct spdk_pci_driver *, (void), NULL) 46 47 /* 48 * These mocks don't use the DEFINE_STUB macros because 49 * their default implementation is more complex. 50 */ 51 52 DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *); 53 void * 54 spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags) 55 { 56 HANDLE_RETURN_MOCK(spdk_memzone_reserve); 57 58 return malloc(len); 59 } 60 61 DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *); 62 void * 63 spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id, 64 unsigned flags, unsigned align) 65 { 66 HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned); 67 68 return malloc(len); 69 } 70 71 DEFINE_RETURN_MOCK(spdk_malloc, void *); 72 void * 73 spdk_malloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags) 74 { 75 HANDLE_RETURN_MOCK(spdk_malloc); 76 77 void *buf = NULL; 78 79 if (align == 0) { 80 align = 8; 81 } 82 83 if (posix_memalign(&buf, align, size)) { 84 return NULL; 85 } 86 if (phys_addr) { 87 *phys_addr = (uint64_t)buf; 88 } 89 90 return buf; 91 } 92 93 DEFINE_RETURN_MOCK(spdk_zmalloc, void *); 94 void * 95 spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags) 96 { 97 HANDLE_RETURN_MOCK(spdk_zmalloc); 98 99 void *buf = spdk_malloc(size, align, phys_addr, -1, 1); 100 101 if (buf != NULL) { 102 memset(buf, 0, size); 103 } 104 return buf; 105 } 106 107 DEFINE_RETURN_MOCK(spdk_dma_malloc, void *); 108 void * 109 spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr) 110 { 111 HANDLE_RETURN_MOCK(spdk_dma_malloc); 112 113 return spdk_malloc(size, align, phys_addr, -1, 1); 114 } 115 116 DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *); 117 void * 118 spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr) 119 { 120 HANDLE_RETURN_MOCK(spdk_dma_zmalloc); 121 122 return spdk_zmalloc(size, align, phys_addr, -1, 1); 123 } 124 125 DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *); 126 void * 127 spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 128 { 129 HANDLE_RETURN_MOCK(spdk_dma_malloc_socket); 130 131 return spdk_dma_malloc(size, align, phys_addr); 132 } 133 134 DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *); 135 void * 136 spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id) 137 { 138 HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket); 139 140 return spdk_dma_zmalloc(size, align, phys_addr); 141 } 142 143 DEFINE_RETURN_MOCK(spdk_dma_realloc, void *); 144 void * 145 spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr) 146 { 147 HANDLE_RETURN_MOCK(spdk_dma_realloc); 148 149 return realloc(buf, size); 150 } 151 152 void 153 spdk_free(void *buf) 154 { 155 free(buf); 156 } 157 158 void 159 spdk_dma_free(void *buf) 160 { 161 return spdk_free(buf); 162 } 163 164 DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t); 165 uint64_t 166 spdk_vtophys(void *buf, uint64_t *size) 167 { 168 HANDLE_RETURN_MOCK(spdk_vtophys); 169 170 return (uintptr_t)buf; 171 } 172 173 void 174 spdk_memzone_dump(FILE *f) 175 { 176 return; 177 } 178 179 DEFINE_RETURN_MOCK(spdk_memzone_free, int); 180 int 181 spdk_memzone_free(const char *name) 182 { 183 HANDLE_RETURN_MOCK(spdk_memzone_free); 184 185 return 0; 186 } 187 188 struct test_mempool { 189 size_t count; 190 }; 191 192 DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *); 193 struct spdk_mempool * 194 spdk_mempool_create(const char *name, size_t count, 195 size_t ele_size, size_t cache_size, int socket_id) 196 { 197 struct test_mempool *mp; 198 199 HANDLE_RETURN_MOCK(spdk_mempool_create); 200 201 mp = calloc(1, sizeof(*mp)); 202 if (mp == NULL) { 203 return NULL; 204 } 205 206 mp->count = count; 207 208 return (struct spdk_mempool *)mp; 209 } 210 211 void 212 spdk_mempool_free(struct spdk_mempool *_mp) 213 { 214 struct test_mempool *mp = (struct test_mempool *)_mp; 215 216 free(mp); 217 } 218 219 DEFINE_RETURN_MOCK(spdk_mempool_get, void *); 220 void * 221 spdk_mempool_get(struct spdk_mempool *_mp) 222 { 223 struct test_mempool *mp = (struct test_mempool *)_mp; 224 void *buf; 225 226 HANDLE_RETURN_MOCK(spdk_mempool_get); 227 228 if (mp && mp->count == 0) { 229 return NULL; 230 } 231 232 if (posix_memalign(&buf, 64, 0x10000)) { 233 return NULL; 234 } else { 235 if (mp) { 236 mp->count--; 237 } 238 return buf; 239 } 240 } 241 242 int 243 spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count) 244 { 245 for (size_t i = 0; i < count; i++) { 246 ele_arr[i] = spdk_mempool_get(mp); 247 if (ele_arr[i] == NULL) { 248 return -1; 249 } 250 } 251 return 0; 252 } 253 254 void 255 spdk_mempool_put(struct spdk_mempool *_mp, void *ele) 256 { 257 struct test_mempool *mp = (struct test_mempool *)_mp; 258 259 if (mp) { 260 mp->count++; 261 } 262 free(ele); 263 } 264 265 void 266 spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count) 267 { 268 for (size_t i = 0; i < count; i++) { 269 spdk_mempool_put(mp, ele_arr[i]); 270 } 271 } 272 273 DEFINE_RETURN_MOCK(spdk_mempool_count, size_t); 274 size_t 275 spdk_mempool_count(const struct spdk_mempool *_mp) 276 { 277 struct test_mempool *mp = (struct test_mempool *)_mp; 278 279 HANDLE_RETURN_MOCK(spdk_mempool_count); 280 281 if (mp) { 282 return mp->count; 283 } else { 284 return 1024; 285 } 286 } 287 288 struct spdk_ring_ele { 289 void *ele; 290 TAILQ_ENTRY(spdk_ring_ele) link; 291 }; 292 293 struct spdk_ring { 294 TAILQ_HEAD(, spdk_ring_ele) elements; 295 pthread_mutex_t lock; 296 }; 297 298 DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *); 299 struct spdk_ring * 300 spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id) 301 { 302 struct spdk_ring *ring; 303 304 HANDLE_RETURN_MOCK(spdk_ring_create); 305 306 ring = calloc(1, sizeof(*ring)); 307 if (!ring) { 308 return NULL; 309 } 310 311 if (pthread_mutex_init(&ring->lock, NULL)) { 312 free(ring); 313 return NULL; 314 } 315 316 TAILQ_INIT(&ring->elements); 317 return ring; 318 } 319 320 void 321 spdk_ring_free(struct spdk_ring *ring) 322 { 323 struct spdk_ring_ele *ele, *tmp; 324 325 if (!ring) { 326 return; 327 } 328 329 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) { 330 free(ele); 331 } 332 333 pthread_mutex_destroy(&ring->lock); 334 free(ring); 335 } 336 337 DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t); 338 size_t 339 spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count) 340 { 341 struct spdk_ring_ele *ele; 342 size_t i; 343 344 HANDLE_RETURN_MOCK(spdk_ring_enqueue); 345 346 pthread_mutex_lock(&ring->lock); 347 348 for (i = 0; i < count; i++) { 349 ele = calloc(1, sizeof(*ele)); 350 if (!ele) { 351 break; 352 } 353 354 ele->ele = objs[i]; 355 TAILQ_INSERT_TAIL(&ring->elements, ele, link); 356 } 357 358 pthread_mutex_unlock(&ring->lock); 359 return i; 360 } 361 362 DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t); 363 size_t 364 spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count) 365 { 366 struct spdk_ring_ele *ele, *tmp; 367 size_t i = 0; 368 369 HANDLE_RETURN_MOCK(spdk_ring_dequeue); 370 371 if (count == 0) { 372 return 0; 373 } 374 375 pthread_mutex_lock(&ring->lock); 376 377 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) { 378 TAILQ_REMOVE(&ring->elements, ele, link); 379 objs[i] = ele->ele; 380 free(ele); 381 i++; 382 if (i >= count) { 383 break; 384 } 385 } 386 387 pthread_mutex_unlock(&ring->lock); 388 return i; 389 390 } 391 392 DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t); 393 uint64_t 394 spdk_get_ticks(void) 395 { 396 HANDLE_RETURN_MOCK(spdk_get_ticks); 397 398 return ut_spdk_get_ticks; 399 } 400 401 DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t); 402 uint64_t 403 spdk_get_ticks_hz(void) 404 { 405 HANDLE_RETURN_MOCK(spdk_get_ticks_hz); 406 407 return 1000000; 408 } 409 410 void 411 spdk_delay_us(unsigned int us) 412 { 413 /* spdk_get_ticks_hz is 1000000, meaning 1 tick per us. */ 414 ut_spdk_get_ticks += us; 415 } 416 417 DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int); 418 int 419 spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf) 420 { 421 unsigned domain, bus, dev, func; 422 423 HANDLE_RETURN_MOCK(spdk_pci_addr_parse); 424 425 if (addr == NULL || bdf == NULL) { 426 return -EINVAL; 427 } 428 429 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) || 430 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) { 431 /* Matched a full address - all variables are initialized */ 432 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) { 433 func = 0; 434 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) || 435 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) { 436 domain = 0; 437 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) || 438 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) { 439 domain = 0; 440 func = 0; 441 } else { 442 return -EINVAL; 443 } 444 445 if (bus > 0xFF || dev > 0x1F || func > 7) { 446 return -EINVAL; 447 } 448 449 addr->domain = domain; 450 addr->bus = bus; 451 addr->dev = dev; 452 addr->func = func; 453 454 return 0; 455 } 456 457 DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int); 458 int 459 spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr) 460 { 461 int rc; 462 463 HANDLE_RETURN_MOCK(spdk_pci_addr_fmt); 464 465 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x", 466 addr->domain, addr->bus, 467 addr->dev, addr->func); 468 469 if (rc > 0 && (size_t)rc < sz) { 470 return 0; 471 } 472 473 return -1; 474 } 475 476 DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int); 477 int 478 spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2) 479 { 480 HANDLE_RETURN_MOCK(spdk_pci_addr_compare); 481 482 if (a1->domain > a2->domain) { 483 return 1; 484 } else if (a1->domain < a2->domain) { 485 return -1; 486 } else if (a1->bus > a2->bus) { 487 return 1; 488 } else if (a1->bus < a2->bus) { 489 return -1; 490 } else if (a1->dev > a2->dev) { 491 return 1; 492 } else if (a1->dev < a2->dev) { 493 return -1; 494 } else if (a1->func > a2->func) { 495 return 1; 496 } else if (a1->func < a2->func) { 497 return -1; 498 } 499 500 return 0; 501 } 502