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