xref: /wlan-dirver/qca-wifi-host-cmn/qdf/inc/qdf_mem.h (revision 1b9674e21e24478fba4530f5ae7396b9555e9c6a)
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_io(void *ptr, uint32_t num_bytes, uint32_t value);
228 
229 void qdf_mem_copy_toio(void *dst_addr, const void *src_addr,
230 					   uint32_t num_bytes);
231 
232 void qdf_mem_set(void *ptr, uint32_t num_bytes, uint32_t value);
233 
234 void qdf_mem_zero(void *ptr, uint32_t num_bytes);
235 
236 void qdf_mem_copy(void *dst_addr, const void *src_addr, uint32_t num_bytes);
237 
238 void qdf_mem_move(void *dst_addr, const void *src_addr, uint32_t num_bytes);
239 
240 void qdf_mem_free_outline(void *buf);
241 
242 void qdf_mem_zero_outline(void *buf, qdf_size_t size);
243 
244 void qdf_ether_addr_copy(void *dst_addr, const void *src_addr);
245 
246 /**
247  * qdf_mem_cmp() - memory compare
248  * @memory1: pointer to one location in memory to compare.
249  * @memory2: pointer to second location in memory to compare.
250  * @num_bytes: the number of bytes to compare.
251  *
252  * Function to compare two pieces of memory, similar to memcmp function
253  * in standard C.
254  * Return:
255  * int32_t - returns an int value that tells if the memory
256  * locations are equal or not equal.
257  * 0 -- equal
258  * < 0 -- *memory1 is less than *memory2
259  * > 0 -- *memory1 is bigger than *memory2
260  */
261 static inline int32_t qdf_mem_cmp(const void *memory1, const void *memory2,
262 				  uint32_t num_bytes)
263 {
264 	return __qdf_mem_cmp(memory1, memory2, num_bytes);
265 }
266 
267 /**
268  * qdf_mem_map_nbytes_single - Map memory for DMA
269  * @osdev: pomter OS device context
270  * @buf: pointer to memory to be dma mapped
271  * @dir: DMA map direction
272  * @nbytes: number of bytes to be mapped.
273  * @phy_addr: ponter to recive physical address.
274  *
275  * Return: success/failure
276  */
277 static inline uint32_t qdf_mem_map_nbytes_single(qdf_device_t osdev, void *buf,
278 						 qdf_dma_dir_t dir, int nbytes,
279 						 qdf_dma_addr_t *phy_addr)
280 {
281 #if defined(HIF_PCI)
282 	return __qdf_mem_map_nbytes_single(osdev, buf, dir, nbytes, phy_addr);
283 #else
284 	return 0;
285 #endif
286 }
287 
288 /**
289  * qdf_mem_unmap_nbytes_single() - un_map memory for DMA
290  * @osdev: pomter OS device context
291  * @phy_addr: physical address of memory to be dma unmapped
292  * @dir: DMA unmap direction
293  * @nbytes: number of bytes to be unmapped.
294  *
295  * Return: none
296  */
297 static inline void qdf_mem_unmap_nbytes_single(qdf_device_t osdev,
298 					       qdf_dma_addr_t phy_addr,
299 					       qdf_dma_dir_t dir,
300 					       int nbytes)
301 {
302 #if defined(HIF_PCI)
303 	__qdf_mem_unmap_nbytes_single(osdev, phy_addr, dir, nbytes);
304 #endif
305 }
306 
307 /**
308  * qdf_mempool_init - Create and initialize memory pool
309  * @osdev: platform device object
310  * @pool_addr: address of the pool created
311  * @elem_cnt: no. of elements in pool
312  * @elem_size: size of each pool element in bytes
313  * @flags: flags
314  * Return: Handle to memory pool or NULL if allocation failed
315  */
316 static inline int qdf_mempool_init(qdf_device_t osdev,
317 				   qdf_mempool_t *pool_addr, int elem_cnt,
318 				   size_t elem_size, uint32_t flags)
319 {
320 	return __qdf_mempool_init(osdev, pool_addr, elem_cnt, elem_size,
321 				  flags);
322 }
323 
324 /**
325  * qdf_mempool_destroy - Destroy memory pool
326  * @osdev: platform device object
327  * @Handle: to memory pool
328  * Return: none
329  */
330 static inline void qdf_mempool_destroy(qdf_device_t osdev, qdf_mempool_t pool)
331 {
332 	__qdf_mempool_destroy(osdev, pool);
333 }
334 
335 /**
336  * qdf_mempool_alloc - Allocate an element memory pool
337  * @osdev: platform device object
338  * @Handle: to memory pool
339  * Return: Pointer to the allocated element or NULL if the pool is empty
340  */
341 static inline void *qdf_mempool_alloc(qdf_device_t osdev, qdf_mempool_t pool)
342 {
343 	return (void *)__qdf_mempool_alloc(osdev, pool);
344 }
345 
346 /**
347  * qdf_mempool_free - Free a memory pool element
348  * @osdev: Platform device object
349  * @pool: Handle to memory pool
350  * @buf: Element to be freed
351  * Return: none
352  */
353 static inline void qdf_mempool_free(qdf_device_t osdev, qdf_mempool_t pool,
354 				    void *buf)
355 {
356 	__qdf_mempool_free(osdev, pool, buf);
357 }
358 
359 void qdf_mem_dma_sync_single_for_device(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_dma_sync_single_for_cpu(qdf_device_t osdev,
365 					qdf_dma_addr_t bus_addr,
366 					qdf_size_t size,
367 					__dma_data_direction direction);
368 
369 void qdf_mem_multi_pages_alloc(qdf_device_t osdev,
370 			       struct qdf_mem_multi_page_t *pages,
371 			       size_t element_size, uint16_t element_num,
372 			       qdf_dma_context_t memctxt, bool cacheable);
373 void qdf_mem_multi_pages_free(qdf_device_t osdev,
374 			      struct qdf_mem_multi_page_t *pages,
375 			      qdf_dma_context_t memctxt, bool cacheable);
376 int qdf_mem_multi_page_link(qdf_device_t osdev,
377 		struct qdf_mem_multi_page_t *pages,
378 		uint32_t elem_size, uint32_t elem_count, uint8_t cacheable);
379 /**
380  * qdf_mem_skb_inc() - increment total skb allocation size
381  * @size: size to be added
382  *
383  * Return: none
384  */
385 void qdf_mem_skb_inc(qdf_size_t size);
386 
387 /**
388  * qdf_mem_skb_dec() - decrement total skb allocation size
389  * @size: size to be decremented
390  *
391  * Return: none
392  */
393 void qdf_mem_skb_dec(qdf_size_t size);
394 
395 /**
396  * qdf_mem_map_table_alloc() - Allocate shared memory info structure
397  * @num: number of required storage
398  *
399  * Allocate mapping table for DMA memory allocation. This is needed for
400  * IPA-WLAN buffer sharing when SMMU Stage1 Translation is enabled.
401  *
402  * Return: shared memory info storage table pointer
403  */
404 static inline qdf_mem_info_t *qdf_mem_map_table_alloc(uint32_t num)
405 {
406 	qdf_mem_info_t *mem_info_arr;
407 
408 	mem_info_arr = qdf_mem_malloc(num * sizeof(mem_info_arr[0]));
409 	return mem_info_arr;
410 }
411 
412 /**
413  * qdf_update_mem_map_table() - Update DMA memory map info
414  * @osdev: Parent device instance
415  * @mem_info: Pointer to shared memory information
416  * @dma_addr: dma address
417  * @mem_size: memory size allocated
418  *
419  * Store DMA shared memory information
420  *
421  * Return: none
422  */
423 static inline void qdf_update_mem_map_table(qdf_device_t osdev,
424 					    qdf_mem_info_t *mem_info,
425 					    qdf_dma_addr_t dma_addr,
426 					    uint32_t mem_size)
427 {
428 	if (!mem_info) {
429 		__qdf_print("%s: NULL mem_info\n", __func__);
430 		return;
431 	}
432 
433 	__qdf_update_mem_map_table(osdev, mem_info, dma_addr, mem_size);
434 }
435 
436 /**
437  * qdf_mem_smmu_s1_enabled() - Return SMMU stage 1 translation enable status
438  * @osdev parent device instance
439  *
440  * Return: true if smmu s1 enabled, false if smmu s1 is bypassed
441  */
442 static inline bool qdf_mem_smmu_s1_enabled(qdf_device_t osdev)
443 {
444 	return __qdf_mem_smmu_s1_enabled(osdev);
445 }
446 
447 /**
448  * qdf_mem_paddr_from_dmaaddr() - get actual physical address from dma address
449  * @osdev: Parent device instance
450  * @dma_addr: DMA/IOVA address
451  *
452  * Get actual physical address from dma_addr based on SMMU enablement status.
453  * IF SMMU Stage 1 tranlation is enabled, DMA APIs return IO virtual address
454  * (IOVA) otherwise returns physical address. So get SMMU physical address
455  * mapping from IOVA.
456  *
457  * Return: dmaable physical address
458  */
459 static inline qdf_dma_addr_t qdf_mem_paddr_from_dmaaddr(qdf_device_t osdev,
460 							qdf_dma_addr_t dma_addr)
461 {
462 	return __qdf_mem_paddr_from_dmaaddr(osdev, dma_addr);
463 }
464 
465 /**
466  * qdf_mem_dma_get_sgtable() - Returns DMA memory scatter gather table
467  * @dev: device instace
468  * @sgt: scatter gather table pointer
469  * @cpu_addr: HLOS virtual address
470  * @dma_addr: dma address
471  * @size: allocated memory size
472  *
473  * Return: physical address
474  */
475 static inline int
476 qdf_mem_dma_get_sgtable(struct device *dev, void *sgt, void *cpu_addr,
477 			qdf_dma_addr_t dma_addr, size_t size)
478 {
479 	return __qdf_os_mem_dma_get_sgtable(dev, sgt, cpu_addr, dma_addr, size);
480 }
481 
482 /**
483  * qdf_dma_get_sgtable_dma_addr() - Assigns DMA address to scatterlist elements
484  * @sgt: scatter gather table pointer
485  *
486  * @Return: None
487  */
488 static inline void
489 qdf_dma_get_sgtable_dma_addr(struct sg_table *sgt)
490 {
491 	__qdf_dma_get_sgtable_dma_addr(sgt);
492 }
493 
494 /**
495  * qdf_mem_get_dma_addr() - Return dma address based on SMMU translation status.
496  * @osdev: Parent device instance
497  * @mem_info: Pointer to allocated memory information
498  *
499  * Get dma address based on SMMU enablement status. If SMMU Stage 1
500  * tranlation is enabled, DMA APIs return IO virtual address otherwise
501  * returns physical address.
502  *
503  * Return: dma address
504  */
505 static inline qdf_dma_addr_t qdf_mem_get_dma_addr(qdf_device_t osdev,
506 						  qdf_mem_info_t *mem_info)
507 {
508 	return __qdf_mem_get_dma_addr(osdev, mem_info);
509 }
510 
511 /**
512  * qdf_mem_get_dma_addr_ptr() - Return DMA address pointer from mem info struct
513  * @osdev: Parent device instance
514  * @mem_info: Pointer to allocated memory information
515  *
516  * Based on smmu stage 1 translation enablement, return corresponding dma
517  * address storage pointer.
518  *
519  * Return: dma address storage pointer
520  */
521 static inline qdf_dma_addr_t *qdf_mem_get_dma_addr_ptr(qdf_device_t osdev,
522 						       qdf_mem_info_t *mem_info)
523 {
524 	return __qdf_mem_get_dma_addr_ptr(osdev, mem_info);
525 }
526 
527 
528 /**
529  * qdf_mem_get_dma_size() - Return DMA memory size
530  * @osdev: parent device instance
531  * @mem_info: Pointer to allocated memory information
532  *
533  * Return: DMA memory size
534  */
535 static inline uint32_t
536 qdf_mem_get_dma_size(qdf_device_t osdev,
537 		       qdf_mem_info_t *mem_info)
538 {
539 	return __qdf_mem_get_dma_size(osdev, mem_info);
540 }
541 
542 /**
543  * qdf_mem_set_dma_size() - Set DMA memory size
544  * @osdev: parent device instance
545  * @mem_info: Pointer to allocated memory information
546  * @mem_size: memory size allocated
547  *
548  * Return: none
549  */
550 static inline void
551 qdf_mem_set_dma_size(qdf_device_t osdev,
552 		       qdf_mem_info_t *mem_info,
553 		       uint32_t mem_size)
554 {
555 	__qdf_mem_set_dma_size(osdev, mem_info, mem_size);
556 }
557 
558 /**
559  * qdf_mem_get_dma_size() - Return DMA physical address
560  * @osdev: parent device instance
561  * @mem_info: Pointer to allocated memory information
562  *
563  * Return: DMA physical address
564  */
565 static inline qdf_dma_addr_t
566 qdf_mem_get_dma_pa(qdf_device_t osdev,
567 		     qdf_mem_info_t *mem_info)
568 {
569 	return __qdf_mem_get_dma_pa(osdev, mem_info);
570 }
571 
572 /**
573  * qdf_mem_set_dma_size() - Set DMA physical address
574  * @osdev: parent device instance
575  * @mem_info: Pointer to allocated memory information
576  * @dma_pa: DMA phsical address
577  *
578  * Return: none
579  */
580 static inline void
581 qdf_mem_set_dma_pa(qdf_device_t osdev,
582 		     qdf_mem_info_t *mem_info,
583 		     qdf_dma_addr_t dma_pa)
584 {
585 	__qdf_mem_set_dma_pa(osdev, mem_info, dma_pa);
586 }
587 
588 /**
589  * qdf_mem_shared_mem_alloc() - Allocate DMA memory for shared resource
590  * @osdev: parent device instance
591  * @mem_info: Pointer to allocated memory information
592  * @size: size to be allocated
593  *
594  * Allocate DMA memory which will be shared with external kernel module. This
595  * information is needed for SMMU mapping.
596  *
597  * Return: 0 suceess
598  */
599 static inline qdf_shared_mem_t *qdf_mem_shared_mem_alloc(qdf_device_t osdev,
600 							 uint32_t size)
601 {
602 	qdf_shared_mem_t *shared_mem;
603 
604 	shared_mem = qdf_mem_malloc(sizeof(*shared_mem));
605 	if (!shared_mem) {
606 		__qdf_print("%s: Unable to allocate memory for shared resource struct\n",
607 			    __func__);
608 		return NULL;
609 	}
610 
611 	shared_mem->vaddr = qdf_mem_alloc_consistent(osdev, osdev->dev,
612 				size, qdf_mem_get_dma_addr_ptr(osdev,
613 						&shared_mem->mem_info));
614 	if (!shared_mem->vaddr) {
615 		__qdf_print("%s; Unable to allocate DMA memory for shared resource\n",
616 			    __func__);
617 		qdf_mem_free(shared_mem);
618 		return NULL;
619 	}
620 
621 	qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size);
622 	qdf_mem_zero(shared_mem->vaddr,
623 		     qdf_mem_get_dma_size(osdev, &shared_mem->mem_info));
624 	qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info,
625 			   qdf_mem_paddr_from_dmaaddr(osdev,
626 				qdf_mem_get_dma_addr(osdev,
627 						     &shared_mem->mem_info)));
628 	qdf_mem_dma_get_sgtable(osdev->dev,
629 				(void *)&shared_mem->sgtable,
630 				shared_mem->vaddr,
631 				qdf_mem_get_dma_addr(osdev,
632 						     &shared_mem->mem_info),
633 				qdf_mem_get_dma_size(osdev,
634 						     &shared_mem->mem_info));
635 
636 	qdf_dma_get_sgtable_dma_addr(&shared_mem->sgtable);
637 
638 	return shared_mem;
639 }
640 
641 /**
642  * qdf_mem_shared_mem_free() - Free shared memory
643  * @osdev: parent device instance
644  * @shared_mem: shared memory information storage
645  *
646  * Free DMA shared memory resource
647  *
648  * Return: None
649  */
650 static inline void qdf_mem_shared_mem_free(qdf_device_t osdev,
651 					   qdf_shared_mem_t *shared_mem)
652 {
653 	if (!shared_mem) {
654 		__qdf_print("%s: NULL shared mem struct passed\n",
655 			    __func__);
656 		return;
657 	}
658 
659 	if (shared_mem->vaddr) {
660 		qdf_mem_free_consistent(osdev, osdev->dev,
661 					qdf_mem_get_dma_size(osdev,
662 						&shared_mem->mem_info),
663 					shared_mem->vaddr,
664 					qdf_mem_get_dma_addr(osdev,
665 						&shared_mem->mem_info),
666 					qdf_get_dma_mem_context(shared_mem,
667 								memctx));
668 	}
669 	qdf_mem_free(shared_mem);
670 }
671 
672 #endif /* __QDF_MEMORY_H */
673