Loading drivers/net/wireless/Kconfig +14 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,20 @@ config WCNSS_MEM_PRE_ALLOC for it's internal usage and release it to back to pre allocated pool. This memory is allocated at the cold boot time. config WCNSS_SKB_PRE_ALLOC tristate "CNSS pre-alloc memory support for skb" depends on WCNSS_MEM_PRE_ALLOC ---help--- The cnss wlan module which has interfaced with high latency bus(e.g. SDIO) needs physical contiguous memory more than one page for its socket buffer initialization. If the system memory has high fragmented it’s not possible to get this much huge physically contiguous memory through dynamic memory allocation. This feature enable socket buffer to use pre allocated memory for socket buffer initialization and release it to back to pre-allocated pool. config CNSS_CRYPTO tristate "Enable CNSS crypto support" ---help--- Loading drivers/net/wireless/cnss_prealloc/cnss_prealloc.c +104 −3 Original line number Diff line number Diff line /* Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2012,2014-2016 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -15,6 +15,10 @@ #include <linux/stacktrace.h> #include <linux/wcnss_wlan.h> #include <linux/spinlock.h> #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC #include <linux/skbuff.h> #endif static DEFINE_SPINLOCK(alloc_lock); Loading @@ -32,6 +36,16 @@ struct wcnss_prealloc { #endif }; #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC /* pre-alloced memory for skb */ static struct wcnss_prealloc wcnss_skb_allocs[] = { {0, 64 * 1024, NULL}, {0, 64 * 1024, NULL}, {0, 128 * 1024, NULL}, {0, 128 * 1024, NULL}, }; #endif /* pre-alloced mem for WLAN driver */ static struct wcnss_prealloc wcnss_allocs[] = { {0, 8 * 1024, NULL}, Loading Loading @@ -102,20 +116,57 @@ static struct wcnss_prealloc wcnss_allocs[] = { {0, 128 * 1024, NULL}, }; int wcnss_prealloc_init(void) #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC int cnss_skb_prealloc_init(void) { int i; for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { wcnss_skb_allocs[i].occupied = 0; wcnss_skb_allocs[i].ptr = dev_alloc_skb(wcnss_skb_allocs[i].size); if (wcnss_skb_allocs[i].ptr == NULL) return -ENOMEM; } return 0; } #else int cnss_skb_prealloc_init(void) { return 0; } #endif int wcnss_prealloc_init(void) { int i, ret; for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) { wcnss_allocs[i].occupied = 0; wcnss_allocs[i].ptr = kmalloc(wcnss_allocs[i].size, GFP_KERNEL); if (wcnss_allocs[i].ptr == NULL) return -ENOMEM; } ret = cnss_skb_prealloc_init(); return 0; return ret; } #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC void cnss_skb_prealloc_deinit(void) { int i; for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { dev_kfree_skb(wcnss_skb_allocs[i].ptr); wcnss_skb_allocs[i].ptr = NULL; } } #else void cnss_skb_prealloc_deinit(void) {} #endif void wcnss_prealloc_deinit(void) { int i = 0; Loading @@ -124,6 +175,8 @@ void wcnss_prealloc_deinit(void) kfree(wcnss_allocs[i].ptr); wcnss_allocs[i].ptr = NULL; } cnss_skb_prealloc_deinit(); } #ifdef CONFIG_SLUB_DEBUG Loading Loading @@ -195,6 +248,54 @@ int wcnss_prealloc_put(void *ptr) } EXPORT_SYMBOL(wcnss_prealloc_put); #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC struct sk_buff *wcnss_skb_prealloc_get(unsigned int size) { int i = 0; unsigned long flags; spin_lock_irqsave(&alloc_lock, flags); for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { if (wcnss_skb_allocs[i].occupied) continue; if (wcnss_skb_allocs[i].size > size) { /* we found the slot */ wcnss_skb_allocs[i].occupied = 1; spin_unlock_irqrestore(&alloc_lock, flags); wcnss_prealloc_save_stack_trace(&wcnss_allocs[i]); return wcnss_skb_allocs[i].ptr; } } spin_unlock_irqrestore(&alloc_lock, flags); pr_err("wcnss: %s: prealloc not available for size: %d\n", __func__, size); return NULL; } EXPORT_SYMBOL(wcnss_skb_prealloc_get); int wcnss_skb_prealloc_put(struct sk_buff *skb) { int i = 0; unsigned long flags; spin_lock_irqsave(&alloc_lock, flags); for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { if (wcnss_skb_allocs[i].ptr == skb) { wcnss_skb_allocs[i].occupied = 0; spin_unlock_irqrestore(&alloc_lock, flags); return 1; } } spin_unlock_irqrestore(&alloc_lock, flags); return 0; } EXPORT_SYMBOL(wcnss_skb_prealloc_put); #endif #ifdef CONFIG_SLUB_DEBUG void wcnss_prealloc_check_memory_leak(void) { Loading include/net/cnss_prealloc.h +9 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -14,10 +14,18 @@ #define _NET_CNSS_PREALLOC_H_ #define WCNSS_PRE_ALLOC_GET_THRESHOLD (4*1024) #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC #define WCNSS_PRE_SKB_ALLOC_GET_THRESHOLD (50*1024) #endif extern void *wcnss_prealloc_get(unsigned int size); extern int wcnss_prealloc_put(void *ptr); extern int wcnss_pre_alloc_reset(void); void wcnss_prealloc_check_memory_leak(void); #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC extern struct sk_buff *wcnss_skb_prealloc_get(unsigned int size); extern int wcnss_skb_prealloc_put(struct sk_buff *skb); #endif #endif /* _NET_CNSS__PREALLOC_H_ */ Loading
drivers/net/wireless/Kconfig +14 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,20 @@ config WCNSS_MEM_PRE_ALLOC for it's internal usage and release it to back to pre allocated pool. This memory is allocated at the cold boot time. config WCNSS_SKB_PRE_ALLOC tristate "CNSS pre-alloc memory support for skb" depends on WCNSS_MEM_PRE_ALLOC ---help--- The cnss wlan module which has interfaced with high latency bus(e.g. SDIO) needs physical contiguous memory more than one page for its socket buffer initialization. If the system memory has high fragmented it’s not possible to get this much huge physically contiguous memory through dynamic memory allocation. This feature enable socket buffer to use pre allocated memory for socket buffer initialization and release it to back to pre-allocated pool. config CNSS_CRYPTO tristate "Enable CNSS crypto support" ---help--- Loading
drivers/net/wireless/cnss_prealloc/cnss_prealloc.c +104 −3 Original line number Diff line number Diff line /* Copyright (c) 2012,2014-2015 The Linux Foundation. All rights reserved. /* Copyright (c) 2012,2014-2016 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -15,6 +15,10 @@ #include <linux/stacktrace.h> #include <linux/wcnss_wlan.h> #include <linux/spinlock.h> #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC #include <linux/skbuff.h> #endif static DEFINE_SPINLOCK(alloc_lock); Loading @@ -32,6 +36,16 @@ struct wcnss_prealloc { #endif }; #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC /* pre-alloced memory for skb */ static struct wcnss_prealloc wcnss_skb_allocs[] = { {0, 64 * 1024, NULL}, {0, 64 * 1024, NULL}, {0, 128 * 1024, NULL}, {0, 128 * 1024, NULL}, }; #endif /* pre-alloced mem for WLAN driver */ static struct wcnss_prealloc wcnss_allocs[] = { {0, 8 * 1024, NULL}, Loading Loading @@ -102,20 +116,57 @@ static struct wcnss_prealloc wcnss_allocs[] = { {0, 128 * 1024, NULL}, }; int wcnss_prealloc_init(void) #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC int cnss_skb_prealloc_init(void) { int i; for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { wcnss_skb_allocs[i].occupied = 0; wcnss_skb_allocs[i].ptr = dev_alloc_skb(wcnss_skb_allocs[i].size); if (wcnss_skb_allocs[i].ptr == NULL) return -ENOMEM; } return 0; } #else int cnss_skb_prealloc_init(void) { return 0; } #endif int wcnss_prealloc_init(void) { int i, ret; for (i = 0; i < ARRAY_SIZE(wcnss_allocs); i++) { wcnss_allocs[i].occupied = 0; wcnss_allocs[i].ptr = kmalloc(wcnss_allocs[i].size, GFP_KERNEL); if (wcnss_allocs[i].ptr == NULL) return -ENOMEM; } ret = cnss_skb_prealloc_init(); return 0; return ret; } #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC void cnss_skb_prealloc_deinit(void) { int i; for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { dev_kfree_skb(wcnss_skb_allocs[i].ptr); wcnss_skb_allocs[i].ptr = NULL; } } #else void cnss_skb_prealloc_deinit(void) {} #endif void wcnss_prealloc_deinit(void) { int i = 0; Loading @@ -124,6 +175,8 @@ void wcnss_prealloc_deinit(void) kfree(wcnss_allocs[i].ptr); wcnss_allocs[i].ptr = NULL; } cnss_skb_prealloc_deinit(); } #ifdef CONFIG_SLUB_DEBUG Loading Loading @@ -195,6 +248,54 @@ int wcnss_prealloc_put(void *ptr) } EXPORT_SYMBOL(wcnss_prealloc_put); #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC struct sk_buff *wcnss_skb_prealloc_get(unsigned int size) { int i = 0; unsigned long flags; spin_lock_irqsave(&alloc_lock, flags); for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { if (wcnss_skb_allocs[i].occupied) continue; if (wcnss_skb_allocs[i].size > size) { /* we found the slot */ wcnss_skb_allocs[i].occupied = 1; spin_unlock_irqrestore(&alloc_lock, flags); wcnss_prealloc_save_stack_trace(&wcnss_allocs[i]); return wcnss_skb_allocs[i].ptr; } } spin_unlock_irqrestore(&alloc_lock, flags); pr_err("wcnss: %s: prealloc not available for size: %d\n", __func__, size); return NULL; } EXPORT_SYMBOL(wcnss_skb_prealloc_get); int wcnss_skb_prealloc_put(struct sk_buff *skb) { int i = 0; unsigned long flags; spin_lock_irqsave(&alloc_lock, flags); for (i = 0; i < ARRAY_SIZE(wcnss_skb_allocs); i++) { if (wcnss_skb_allocs[i].ptr == skb) { wcnss_skb_allocs[i].occupied = 0; spin_unlock_irqrestore(&alloc_lock, flags); return 1; } } spin_unlock_irqrestore(&alloc_lock, flags); return 0; } EXPORT_SYMBOL(wcnss_skb_prealloc_put); #endif #ifdef CONFIG_SLUB_DEBUG void wcnss_prealloc_check_memory_leak(void) { Loading
include/net/cnss_prealloc.h +9 −1 Original line number Diff line number Diff line /* Copyright (c) 2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -14,10 +14,18 @@ #define _NET_CNSS_PREALLOC_H_ #define WCNSS_PRE_ALLOC_GET_THRESHOLD (4*1024) #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC #define WCNSS_PRE_SKB_ALLOC_GET_THRESHOLD (50*1024) #endif extern void *wcnss_prealloc_get(unsigned int size); extern int wcnss_prealloc_put(void *ptr); extern int wcnss_pre_alloc_reset(void); void wcnss_prealloc_check_memory_leak(void); #ifdef CONFIG_WCNSS_SKB_PRE_ALLOC extern struct sk_buff *wcnss_skb_prealloc_get(unsigned int size); extern int wcnss_skb_prealloc_put(struct sk_buff *skb); #endif #endif /* _NET_CNSS__PREALLOC_H_ */