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 #endif /* __QDF_MEMORY_H */ 394