1 /* 2 * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /** 20 * DOC: qdf_mem 21 * QCA driver framework (QDF) memory management APIs 22 */ 23 24 #if !defined(__QDF_MEMORY_H) 25 #define __QDF_MEMORY_H 26 27 /* Include Files */ 28 #include <qdf_types.h> 29 #include <i_qdf_mem.h> 30 31 #define QDF_CACHE_LINE_SZ __qdf_cache_line_sz 32 33 /** 34 * qdf_align() - align to the given size. 35 * @a: input that needs to be aligned. 36 * @align_size: boundary on which 'a' has to be alinged. 37 * 38 * Return: aligned value. 39 */ 40 #define qdf_align(a, align_size) __qdf_align(a, align_size) 41 42 /** 43 * struct qdf_mem_dma_page_t - Allocated dmaable page 44 * @page_v_addr_start: Page start virtual address 45 * @page_v_addr_end: Page end virtual address 46 * @page_p_addr: Page start physical address 47 */ 48 struct qdf_mem_dma_page_t { 49 char *page_v_addr_start; 50 char *page_v_addr_end; 51 qdf_dma_addr_t page_p_addr; 52 }; 53 54 /** 55 * struct qdf_mem_multi_page_t - multiple page allocation information storage 56 * @num_element_per_page: Number of element in single page 57 * @num_pages: Number of allocation needed pages 58 * @dma_pages: page information storage in case of coherent memory 59 * @cacheable_pages: page information storage in case of cacheable memory 60 */ 61 struct qdf_mem_multi_page_t { 62 uint16_t num_element_per_page; 63 uint16_t num_pages; 64 struct qdf_mem_dma_page_t *dma_pages; 65 void **cacheable_pages; 66 }; 67 68 69 /* Preprocessor definitions and constants */ 70 71 typedef __qdf_mempool_t qdf_mempool_t; 72 73 /** 74 * qdf_mem_init() - Initialize QDF memory module 75 * 76 * Return: None 77 * 78 */ 79 void qdf_mem_init(void); 80 81 /** 82 * qdf_mem_exit() - Exit QDF memory module 83 * 84 * Return: None 85 * 86 */ 87 void qdf_mem_exit(void); 88 89 #define QDF_MEM_FILE_NAME_SIZE 48 90 91 #ifdef MEMORY_DEBUG 92 /** 93 * qdf_mem_malloc_debug() - debug version of QDF memory allocation API 94 * @size: Number of bytes of memory to allocate. 95 * @file: File name of the call site 96 * @line: Line number of the call site 97 * @caller: Address of the caller function 98 * @flag: GFP flag 99 * 100 * This function will dynamicallly allocate the specified number of bytes of 101 * memory and add it to the qdf tracking list to check for memory leaks and 102 * corruptions 103 * 104 * Return: A valid memory location on success, or NULL on failure 105 */ 106 void *qdf_mem_malloc_debug(size_t size, const char *file, uint32_t line, 107 void *caller, uint32_t flag); 108 109 #define qdf_mem_malloc(size) \ 110 qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, 0) 111 112 #define qdf_mem_malloc_atomic(size) \ 113 qdf_mem_malloc_debug(size, __FILE__, __LINE__, QDF_RET_IP, GFP_ATOMIC) 114 /** 115 * qdf_mem_free_debug() - debug version of qdf_mem_free 116 * @ptr: Pointer to the starting address of the memory to be freed. 117 * 118 * This function will free the memory pointed to by 'ptr'. It also checks for 119 * memory corruption, underrun, overrun, double free, domain mismatch, etc. 120 * 121 * Return: none 122 */ 123 void qdf_mem_free_debug(void *ptr, const char *file, uint32_t line); 124 125 #define qdf_mem_free(ptr) \ 126 qdf_mem_free_debug(ptr, __FILE__, __LINE__) 127 128 /** 129 * qdf_mem_check_for_leaks() - Assert that the current memory domain is empty 130 * 131 * Call this to ensure there are no active memory allocations being tracked 132 * against the current debug domain. For example, one should call this function 133 * immediately before a call to qdf_debug_domain_set() as a memory leak 134 * detection mechanism. 135 * 136 * e.g. 137 * qdf_debug_domain_set(QDF_DEBUG_DOMAIN_ACTIVE); 138 * 139 * ... 140 * 141 * // memory is allocated and freed 142 * 143 * ... 144 * 145 * // before transitioning back to inactive state, 146 * // make sure all active memory has been freed 147 * qdf_mem_check_for_leaks(); 148 * qdf_debug_domain_set(QDF_DEBUG_DOMAIN_INIT); 149 * 150 * ... 151 * 152 * // also, before program exit, make sure init time memory is freed 153 * qdf_mem_check_for_leaks(); 154 * exit(); 155 * 156 * Return: None 157 */ 158 void qdf_mem_check_for_leaks(void); 159 160 /** 161 * qdf_mem_alloc_consistent_debug() - allocates consistent qdf memory 162 * @osdev: OS device handle 163 * @dev: Pointer to device handle 164 * @size: Size to be allocated 165 * @paddr: Physical address 166 * @file: file name of the call site 167 * @line: line numbe rof the call site 168 * @caller: Address of the caller function 169 * 170 * Return: pointer of allocated memory or null if memory alloc fails 171 */ 172 void *qdf_mem_alloc_consistent_debug(qdf_device_t osdev, void *dev, 173 qdf_size_t size, qdf_dma_addr_t *paddr, 174 const char *file, uint32_t line, 175 void *caller); 176 177 #define qdf_mem_alloc_consistent(osdev, dev, size, paddr) \ 178 qdf_mem_alloc_consistent_debug(osdev, dev, size, paddr, \ 179 __FILE__, __LINE__, QDF_RET_IP) 180 181 /** 182 * qdf_mem_free_consistent_debug() - free consistent qdf memory 183 * @osdev: OS device handle 184 * @size: Size to be allocated 185 * @vaddr: virtual address 186 * @paddr: Physical address 187 * @memctx: Pointer to DMA context 188 * @file: file name of the call site 189 * @line: line numbe rof the call site 190 * 191 * Return: none 192 */ 193 void qdf_mem_free_consistent_debug(qdf_device_t osdev, void *dev, 194 qdf_size_t size, void *vaddr, 195 qdf_dma_addr_t paddr, 196 qdf_dma_context_t memctx, 197 const char *file, uint32_t line); 198 199 #define qdf_mem_free_consistent(osdev, dev, size, vaddr, paddr, memctx) \ 200 qdf_mem_free_consistent_debug(osdev, dev, size, vaddr, paddr, memctx, \ 201 __FILE__, __LINE__) 202 #else 203 void *qdf_mem_malloc(qdf_size_t size); 204 void *qdf_mem_malloc_atomic(qdf_size_t size); 205 206 /** 207 * qdf_mem_free() - free QDF memory 208 * @ptr: Pointer to the starting address of the memory to be freed. 209 * 210 * Return: None 211 */ 212 void qdf_mem_free(void *ptr); 213 214 static inline void qdf_mem_check_for_leaks(void) { } 215 216 void *qdf_mem_alloc_consistent(qdf_device_t osdev, void *dev, 217 qdf_size_t size, qdf_dma_addr_t *paddr); 218 219 void qdf_mem_free_consistent(qdf_device_t osdev, void *dev, 220 qdf_size_t size, void *vaddr, 221 qdf_dma_addr_t paddr, qdf_dma_context_t memctx); 222 223 #endif /* MEMORY_DEBUG */ 224 225 void *qdf_mem_alloc_outline(qdf_device_t osdev, qdf_size_t size); 226 227 void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value); 228 229 void qdf_mem_zero(void *ptr, uint32_t num_bytes); 230 231 void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes); 232 233 void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes); 234 235 void qdf_mem_free_outline(void *buf); 236 237 void qdf_mem_zero_outline(void *buf, qdf_size_t size); 238 239 void qdf_ether_addr_copy(void *dst_addr, const void *src_addr); 240 241 /** 242 * qdf_mem_cmp() - memory compare 243 * @memory1: pointer to one location in memory to compare. 244 * @memory2: pointer to second location in memory to compare. 245 * @num_bytes: the number of bytes to compare. 246 * 247 * Function to compare two pieces of memory, similar to memcmp function 248 * in standard C. 249 * Return: 250 * int32_t - returns an int value that tells if the memory 251 * locations are equal or not equal. 252 * 0 -- equal 253 * < 0 -- *memory1 is less than *memory2 254 * > 0 -- *memory1 is bigger than *memory2 255 */ 256 static inline int32_t qdf_mem_cmp(const void *memory1, const void *memory2, 257 uint32_t num_bytes) 258 { 259 return __qdf_mem_cmp(memory1, memory2, num_bytes); 260 } 261 262 /** 263 * qdf_mem_map_nbytes_single - Map memory for DMA 264 * @osdev: pomter OS device context 265 * @buf: pointer to memory to be dma mapped 266 * @dir: DMA map direction 267 * @nbytes: number of bytes to be mapped. 268 * @phy_addr: ponter to recive physical address. 269 * 270 * Return: success/failure 271 */ 272 static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf, 273 qdf_dma_dir_t dir, int nbytes, 274 qdf_dma_addr_t *phy_addr) 275 { 276 #if defined(HIF_PCI) 277 return __qdf_mem_map_nbytes_single(osdev, buf, dir, nbytes, phy_addr); 278 #else 279 return 0; 280 #endif 281 } 282 283 /** 284 * qdf_mem_unmap_nbytes_single() - un_map memory for DMA 285 * @osdev: pomter OS device context 286 * @phy_addr: physical address of memory to be dma unmapped 287 * @dir: DMA unmap direction 288 * @nbytes: number of bytes to be unmapped. 289 * 290 * Return: none 291 */ 292 static inline void qdf_mem_unmap_nbytes_single(qdf_device_t osdev, 293 qdf_dma_addr_t phy_addr, 294 qdf_dma_dir_t dir, 295 int nbytes) 296 { 297 #if defined(HIF_PCI) 298 __qdf_mem_unmap_nbytes_single(osdev, phy_addr, dir, nbytes); 299 #endif 300 } 301 302 /** 303 * qdf_mempool_init - Create and initialize memory pool 304 * @osdev: platform device object 305 * @pool_addr: address of the pool created 306 * @elem_cnt: no. of elements in pool 307 * @elem_size: size of each pool element in bytes 308 * @flags: flags 309 * Return: Handle to memory pool or NULL if allocation failed 310 */ 311 static inline int qdf_mempool_init(qdf_device_t osdev, 312 qdf_mempool_t *pool_addr, int elem_cnt, 313 size_t elem_size, uint32_t flags) 314 { 315 return __qdf_mempool_init(osdev, pool_addr, elem_cnt, elem_size, 316 flags); 317 } 318 319 /** 320 * qdf_mempool_destroy - Destroy memory pool 321 * @osdev: platform device object 322 * @Handle: to memory pool 323 * Return: none 324 */ 325 static inline void qdf_mempool_destroy(qdf_device_t osdev, qdf_mempool_t pool) 326 { 327 __qdf_mempool_destroy(osdev, pool); 328 } 329 330 /** 331 * qdf_mempool_alloc - Allocate an element memory pool 332 * @osdev: platform device object 333 * @Handle: to memory pool 334 * Return: Pointer to the allocated element or NULL if the pool is empty 335 */ 336 static inline void *qdf_mempool_alloc(qdf_device_t osdev, qdf_mempool_t pool) 337 { 338 return (void *)__qdf_mempool_alloc(osdev, pool); 339 } 340 341 /** 342 * qdf_mempool_free - Free a memory pool element 343 * @osdev: Platform device object 344 * @pool: Handle to memory pool 345 * @buf: Element to be freed 346 * Return: none 347 */ 348 static inline void qdf_mempool_free(qdf_device_t osdev, qdf_mempool_t pool, 349 void *buf) 350 { 351 __qdf_mempool_free(osdev, pool, buf); 352 } 353 354 void qdf_mem_dma_sync_single_for_device(qdf_device_t osdev, 355 qdf_dma_addr_t bus_addr, 356 qdf_size_t size, 357 __dma_data_direction direction); 358 359 void qdf_mem_dma_sync_single_for_cpu(qdf_device_t osdev, 360 qdf_dma_addr_t bus_addr, 361 qdf_size_t size, 362 __dma_data_direction direction); 363 364 void qdf_mem_multi_pages_alloc(qdf_device_t osdev, 365 struct qdf_mem_multi_page_t *pages, 366 size_t element_size, uint16_t element_num, 367 qdf_dma_context_t memctxt, bool cacheable); 368 void qdf_mem_multi_pages_free(qdf_device_t osdev, 369 struct qdf_mem_multi_page_t *pages, 370 qdf_dma_context_t memctxt, bool cacheable); 371 int qdf_mem_multi_page_link(qdf_device_t osdev, 372 struct qdf_mem_multi_page_t *pages, 373 uint32_t elem_size, uint32_t elem_count, uint8_t cacheable); 374 /** 375 * qdf_mem_skb_inc() - increment total skb allocation size 376 * @size: size to be added 377 * 378 * Return: none 379 */ 380 void qdf_mem_skb_inc(qdf_size_t size); 381 382 /** 383 * qdf_mem_skb_dec() - decrement total skb allocation size 384 * @size: size to be decremented 385 * 386 * Return: none 387 */ 388 void qdf_mem_skb_dec(qdf_size_t size); 389 390 /** 391 * qdf_mem_map_table_alloc() - Allocate shared memory info structure 392 * @num: number of required storage 393 * 394 * Allocate mapping table for DMA memory allocation. This is needed for 395 * IPA-WLAN buffer sharing when SMMU Stage1 Translation is enabled. 396 * 397 * Return: shared memory info storage table pointer 398 */ 399 static inline qdf_mem_info_t *qdf_mem_map_table_alloc(uint32_t num) 400 { 401 qdf_mem_info_t *mem_info_arr; 402 403 mem_info_arr = qdf_mem_malloc(num * sizeof(mem_info_arr[0])); 404 return mem_info_arr; 405 } 406 407 /** 408 * qdf_update_mem_map_table() - Update DMA memory map info 409 * @osdev: Parent device instance 410 * @mem_info: Pointer to shared memory information 411 * @dma_addr: dma address 412 * @mem_size: memory size allocated 413 * 414 * Store DMA shared memory information 415 * 416 * Return: none 417 */ 418 static inline void qdf_update_mem_map_table(qdf_device_t osdev, 419 qdf_mem_info_t *mem_info, 420 qdf_dma_addr_t dma_addr, 421 uint32_t mem_size) 422 { 423 if (!mem_info) { 424 __qdf_print("%s: NULL mem_info\n", __func__); 425 return; 426 } 427 428 __qdf_update_mem_map_table(osdev, mem_info, dma_addr, mem_size); 429 } 430 431 /** 432 * qdf_mem_smmu_s1_enabled() - Return SMMU stage 1 translation enable status 433 * @osdev parent device instance 434 * 435 * Return: true if smmu s1 enabled, false if smmu s1 is bypassed 436 */ 437 static inline bool qdf_mem_smmu_s1_enabled(qdf_device_t osdev) 438 { 439 return __qdf_mem_smmu_s1_enabled(osdev); 440 } 441 442 /** 443 * qdf_mem_paddr_from_dmaaddr() - get actual physical address from dma address 444 * @osdev: Parent device instance 445 * @dma_addr: DMA/IOVA address 446 * 447 * Get actual physical address from dma_addr based on SMMU enablement status. 448 * IF SMMU Stage 1 tranlation is enabled, DMA APIs return IO virtual address 449 * (IOVA) otherwise returns physical address. So get SMMU physical address 450 * mapping from IOVA. 451 * 452 * Return: dmaable physical address 453 */ 454 static inline qdf_dma_addr_t qdf_mem_paddr_from_dmaaddr(qdf_device_t osdev, 455 qdf_dma_addr_t dma_addr) 456 { 457 return __qdf_mem_paddr_from_dmaaddr(osdev, dma_addr); 458 } 459 460 /** 461 * qdf_os_mem_dma_get_sgtable() - Returns DMA memory scatter gather table 462 * @dev: device instace 463 * @sgt: scatter gather table pointer 464 * @cpu_addr: HLOS virtual address 465 * @dma_addr: dma address 466 * @size: allocated memory size 467 * 468 * Return: physical address 469 */ 470 static inline int 471 qdf_mem_dma_get_sgtable(struct device *dev, void *sgt, void *cpu_addr, 472 qdf_dma_addr_t dma_addr, size_t size) 473 { 474 return __qdf_os_mem_dma_get_sgtable(dev, sgt, cpu_addr, dma_addr, size); 475 } 476 477 /** 478 * qdf_mem_get_dma_addr() - Return dma address based on SMMU translation status. 479 * @osdev: Parent device instance 480 * @mem_info: Pointer to allocated memory information 481 * 482 * Get dma address based on SMMU enablement status. If SMMU Stage 1 483 * tranlation is enabled, DMA APIs return IO virtual address otherwise 484 * returns physical address. 485 * 486 * Return: dma address 487 */ 488 static inline qdf_dma_addr_t qdf_mem_get_dma_addr(qdf_device_t osdev, 489 qdf_mem_info_t *mem_info) 490 { 491 return __qdf_mem_get_dma_addr(osdev, mem_info); 492 } 493 494 /** 495 * qdf_mem_get_dma_addr_ptr() - Return DMA address pointer from mem info struct 496 * @osdev: Parent device instance 497 * @mem_info: Pointer to allocated memory information 498 * 499 * Based on smmu stage 1 translation enablement, return corresponding dma 500 * address storage pointer. 501 * 502 * Return: dma address storage pointer 503 */ 504 static inline qdf_dma_addr_t *qdf_mem_get_dma_addr_ptr(qdf_device_t osdev, 505 qdf_mem_info_t *mem_info) 506 { 507 return __qdf_mem_get_dma_addr_ptr(osdev, mem_info); 508 } 509 510 511 /** 512 * qdf_mem_get_dma_size() - Return DMA memory size 513 * @osdev: parent device instance 514 * @mem_info: Pointer to allocated memory information 515 * 516 * Return: DMA memory size 517 */ 518 static inline uint32_t 519 qdf_mem_get_dma_size(qdf_device_t osdev, 520 qdf_mem_info_t *mem_info) 521 { 522 return __qdf_mem_get_dma_size(osdev, mem_info); 523 } 524 525 /** 526 * qdf_mem_set_dma_size() - Set DMA memory size 527 * @osdev: parent device instance 528 * @mem_info: Pointer to allocated memory information 529 * @mem_size: memory size allocated 530 * 531 * Return: none 532 */ 533 static inline void 534 qdf_mem_set_dma_size(qdf_device_t osdev, 535 qdf_mem_info_t *mem_info, 536 uint32_t mem_size) 537 { 538 __qdf_mem_set_dma_size(osdev, mem_info, mem_size); 539 } 540 541 /** 542 * qdf_mem_get_dma_size() - Return DMA physical address 543 * @osdev: parent device instance 544 * @mem_info: Pointer to allocated memory information 545 * 546 * Return: DMA physical address 547 */ 548 static inline qdf_dma_addr_t 549 qdf_mem_get_dma_pa(qdf_device_t osdev, 550 qdf_mem_info_t *mem_info) 551 { 552 return __qdf_mem_get_dma_pa(osdev, mem_info); 553 } 554 555 /** 556 * qdf_mem_set_dma_size() - Set DMA physical address 557 * @osdev: parent device instance 558 * @mem_info: Pointer to allocated memory information 559 * @dma_pa: DMA phsical address 560 * 561 * Return: none 562 */ 563 static inline void 564 qdf_mem_set_dma_pa(qdf_device_t osdev, 565 qdf_mem_info_t *mem_info, 566 qdf_dma_addr_t dma_pa) 567 { 568 __qdf_mem_set_dma_pa(osdev, mem_info, dma_pa); 569 } 570 571 /** 572 * qdf_mem_shared_mem_alloc() - Allocate DMA memory for shared resource 573 * @osdev: parent device instance 574 * @mem_info: Pointer to allocated memory information 575 * @size: size to be allocated 576 * 577 * Allocate DMA memory which will be shared with external kernel module. This 578 * information is needed for SMMU mapping. 579 * 580 * Return: 0 suceess 581 */ 582 static inline qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev, 583 uint32_t size) 584 { 585 qdf_shared_mem_t *shared_mem; 586 587 shared_mem = qdf_mem_malloc(sizeof(*shared_mem)); 588 if (!shared_mem) { 589 __qdf_print("%s: Unable to allocate memory for shared resource struct\n", 590 __func__); 591 return NULL; 592 } 593 594 shared_mem->vaddr = qdf_mem_alloc_consistent(osdev, osdev->dev, 595 size, qdf_mem_get_dma_addr_ptr(osdev, 596 &shared_mem->mem_info)); 597 if (!shared_mem->vaddr) { 598 __qdf_print("%s; Unable to allocate DMA memory for shared resource\n", 599 __func__); 600 qdf_mem_free(shared_mem); 601 return NULL; 602 } 603 604 qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size); 605 qdf_mem_zero(shared_mem->vaddr, 606 qdf_mem_get_dma_size(osdev, &shared_mem->mem_info)); 607 qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info, 608 qdf_mem_paddr_from_dmaaddr(osdev, 609 qdf_mem_get_dma_addr(osdev, 610 &shared_mem->mem_info))); 611 qdf_mem_dma_get_sgtable(osdev->dev, 612 (void *)&shared_mem->sgtable, 613 shared_mem->vaddr, 614 qdf_mem_get_dma_addr(osdev, 615 &shared_mem->mem_info), 616 qdf_mem_get_dma_size(osdev, 617 &shared_mem->mem_info)); 618 619 shared_mem->sgtable.sgl->dma_address = 620 qdf_mem_get_dma_pa(osdev, &shared_mem->mem_info); 621 622 return shared_mem; 623 } 624 625 /** 626 * qdf_mem_shared_mem_free() - Free shared memory 627 * @osdev: parent device instance 628 * @shared_mem: shared memory information storage 629 * 630 * Free DMA shared memory resource 631 * 632 * Return: None 633 */ 634 static inline void qdf_mem_shared_mem_free(qdf_device_t osdev, 635 qdf_shared_mem_t *shared_mem) 636 { 637 if (!shared_mem) { 638 __qdf_print("%s: NULL shared mem struct passed\n", 639 __func__); 640 return; 641 } 642 643 if (shared_mem->vaddr) { 644 qdf_mem_free_consistent(osdev, osdev->dev, 645 qdf_mem_get_dma_size(osdev, 646 &shared_mem->mem_info), 647 shared_mem->vaddr, 648 qdf_mem_get_dma_addr(osdev, 649 &shared_mem->mem_info), 650 qdf_get_dma_mem_context(shared_mem, 651 memctx)); 652 } 653 qdf_mem_free(shared_mem); 654 } 655 656 #endif /* __QDF_MEMORY_H */ 657