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