Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aba1d784 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "net: cnss_prealloc: add pre alloc support for socket buffer"

parents dae56378 ecb72345
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -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---
+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
@@ -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);

@@ -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},
@@ -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;
@@ -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
@@ -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)
{
+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
@@ -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_ */