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