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