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