382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
#include <linux/module.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <linux/init.h>
 | 
						|
#include <linux/platform_device.h>
 | 
						|
#include <linux/delay.h>
 | 
						|
#include <linux/err.h>
 | 
						|
#include <linux/skbuff.h>
 | 
						|
 | 
						|
enum dhd_prealloc_index {
 | 
						|
	DHD_PREALLOC_PROT = 0,
 | 
						|
	DHD_PREALLOC_RXBUF,
 | 
						|
	DHD_PREALLOC_DATABUF,
 | 
						|
	DHD_PREALLOC_OSL_BUF,
 | 
						|
	DHD_PREALLOC_SKB_BUF,
 | 
						|
	DHD_PREALLOC_WIPHY_ESCAN0 = 5,
 | 
						|
	DHD_PREALLOC_WIPHY_ESCAN1 = 6,
 | 
						|
	DHD_PREALLOC_DHD_INFO = 7,
 | 
						|
	DHD_PREALLOC_DHD_WLFC_INFO = 8,
 | 
						|
	DHD_PREALLOC_IF_FLOW_LKUP = 9,
 | 
						|
	DHD_PREALLOC_MEMDUMP_BUF = 10,
 | 
						|
	DHD_PREALLOC_MEMDUMP_RAM = 11,
 | 
						|
	DHD_PREALLOC_DHD_WLFC_HANGER = 12,
 | 
						|
	DHD_PREALLOC_MAX
 | 
						|
};
 | 
						|
 | 
						|
#define STATIC_BUF_MAX_NUM	20
 | 
						|
#define STATIC_BUF_SIZE	(PAGE_SIZE*2)
 | 
						|
 | 
						|
#define DHD_PREALLOC_PROT_SIZE   	(16 * 1024)
 | 
						|
#define DHD_PREALLOC_RXBUF_SIZE   	(24 * 1024)
 | 
						|
#define DHD_PREALLOC_DATABUF_SIZE   	(64 * 1024)
 | 
						|
#define DHD_PREALLOC_OSL_BUF_SIZE      (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
 | 
						|
#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE	(64 * 1024)
 | 
						|
#define DHD_PREALLOC_DHD_INFO_SIZE		(24 * 1024)
 | 
						|
#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE	(64 * 1024)
 | 
						|
#ifdef CONFIG_64BIT
 | 
						|
#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE	(20 * 1024 * 2)
 | 
						|
#else
 | 
						|
#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE	(20 * 1024)
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(CONFIG_64BIT)
 | 
						|
#define WLAN_DHD_INFO_BUF_SIZE		(24 * 1024)
 | 
						|
#define WLAN_DHD_WLFC_BUF_SIZE		(64 * 1024)
 | 
						|
#define WLAN_DHD_IF_FLOW_LKUP_SIZE	(64 * 1024)
 | 
						|
#else
 | 
						|
#define WLAN_DHD_INFO_BUF_SIZE		(16 * 1024)
 | 
						|
#define WLAN_DHD_WLFC_BUF_SIZE		(24 * 1024)
 | 
						|
#define WLAN_DHD_IF_FLOW_LKUP_SIZE	(20 * 1024)
 | 
						|
#endif /* CONFIG_64BIT */
 | 
						|
#define WLAN_DHD_MEMDUMP_SIZE		(800 * 1024)
 | 
						|
 | 
						|
#ifdef CONFIG_BCMDHD_PCIE
 | 
						|
#define DHD_SKB_1PAGE_BUFSIZE	(PAGE_SIZE*1)
 | 
						|
#define DHD_SKB_2PAGE_BUFSIZE	(PAGE_SIZE*2)
 | 
						|
#define DHD_SKB_4PAGE_BUFSIZE	(PAGE_SIZE*4)
 | 
						|
 | 
						|
#define DHD_SKB_1PAGE_BUF_NUM	0
 | 
						|
#define DHD_SKB_2PAGE_BUF_NUM	64
 | 
						|
#define DHD_SKB_4PAGE_BUF_NUM	0
 | 
						|
#else
 | 
						|
#define DHD_SKB_HDRSIZE		336
 | 
						|
#define DHD_SKB_1PAGE_BUFSIZE	((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)
 | 
						|
#define DHD_SKB_2PAGE_BUFSIZE	((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)
 | 
						|
#define DHD_SKB_4PAGE_BUFSIZE	((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)
 | 
						|
 | 
						|
#define DHD_SKB_1PAGE_BUF_NUM	8
 | 
						|
#define DHD_SKB_2PAGE_BUF_NUM	8
 | 
						|
#define DHD_SKB_4PAGE_BUF_NUM	1
 | 
						|
#endif /* CONFIG_BCMDHD_PCIE */
 | 
						|
 | 
						|
/* The number is defined in linux_osl.c
 | 
						|
 * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM
 | 
						|
 * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM
 | 
						|
 */
 | 
						|
#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \
 | 
						|
		(DHD_SKB_2PAGE_BUF_NUM))
 | 
						|
#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))
 | 
						|
 | 
						|
void *wlan_static_prot = NULL;
 | 
						|
void *wlan_static_rxbuf = NULL;
 | 
						|
void *wlan_static_databuf = NULL;
 | 
						|
void *wlan_static_osl_buf = NULL;
 | 
						|
void *wlan_static_scan_buf0 = NULL;
 | 
						|
void *wlan_static_scan_buf1 = NULL;
 | 
						|
void *wlan_static_dhd_info_buf = NULL;
 | 
						|
void *wlan_static_dhd_wlfc_info_buf = NULL;
 | 
						|
void *wlan_static_if_flow_lkup = NULL;
 | 
						|
void *wlan_static_dhd_wlfc_hanger_buf = NULL;
 | 
						|
 | 
						|
static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
 | 
						|
 | 
						|
void *dhd_wlan_mem_prealloc(int section, unsigned long size)
 | 
						|
{
 | 
						|
	printk("%s: sectoin %d, %ld\n", __FUNCTION__, section, size);
 | 
						|
	if (section == DHD_PREALLOC_PROT)
 | 
						|
		return wlan_static_prot;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_RXBUF)
 | 
						|
		return wlan_static_rxbuf;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_DATABUF)
 | 
						|
		return wlan_static_databuf;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_SKB_BUF)
 | 
						|
		return wlan_static_skb;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_WIPHY_ESCAN0)
 | 
						|
		return wlan_static_scan_buf0;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_WIPHY_ESCAN1)
 | 
						|
		return wlan_static_scan_buf1;
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_OSL_BUF) {
 | 
						|
		if (size > DHD_PREALLOC_OSL_BUF_SIZE) {
 | 
						|
			pr_err("request OSL_BUF(%lu) is bigger than static size(%ld).\n",
 | 
						|
				size, DHD_PREALLOC_OSL_BUF_SIZE);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		return wlan_static_osl_buf;
 | 
						|
	}
 | 
						|
 | 
						|
	if (section == DHD_PREALLOC_DHD_INFO) {
 | 
						|
		if (size > DHD_PREALLOC_DHD_INFO_SIZE) {
 | 
						|
			pr_err("request DHD_INFO size(%lu) is bigger than static size(%d).\n",
 | 
						|
				size, DHD_PREALLOC_DHD_INFO_SIZE);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		return wlan_static_dhd_info_buf;
 | 
						|
	}
 | 
						|
	if (section == DHD_PREALLOC_DHD_WLFC_INFO) {
 | 
						|
		if (size > WLAN_DHD_WLFC_BUF_SIZE) {
 | 
						|
			pr_err("request DHD_WLFC_INFO size(%lu) is bigger than static size(%d).\n",
 | 
						|
				size, WLAN_DHD_WLFC_BUF_SIZE);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		return wlan_static_dhd_wlfc_info_buf;
 | 
						|
	}
 | 
						|
	if (section == DHD_PREALLOC_IF_FLOW_LKUP)  {
 | 
						|
		if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {
 | 
						|
			pr_err("request DHD_IF_FLOW_LKUP size(%lu) is bigger than static size(%d).\n",
 | 
						|
				size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
 | 
						|
		return wlan_static_if_flow_lkup;
 | 
						|
	}
 | 
						|
	if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
 | 
						|
		if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
 | 
						|
			pr_err("request DHD_WLFC_HANGER size(%lu) is bigger than static size(%d).\n",
 | 
						|
				size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
 | 
						|
			return NULL;
 | 
						|
		}
 | 
						|
		return wlan_static_dhd_wlfc_hanger_buf;
 | 
						|
	}
 | 
						|
	if ((section < 0) || (section > DHD_PREALLOC_MAX))
 | 
						|
		pr_err("request section id(%d) is out of max index %d\n",
 | 
						|
				section, DHD_PREALLOC_MAX);
 | 
						|
 | 
						|
	pr_err("%s: failed to alloc section %d, size=%ld\n", __FUNCTION__, section, size);
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(dhd_wlan_mem_prealloc);
 | 
						|
 | 
						|
static int dhd_init_wlan_mem(void)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	int j;
 | 
						|
 | 
						|
	for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {
 | 
						|
		wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);
 | 
						|
		if (!wlan_static_skb[i]) {
 | 
						|
			goto err_skb_alloc;
 | 
						|
		}
 | 
						|
		printk("%s: sectoin %d skb[%d], size=%ld\n", __FUNCTION__, DHD_PREALLOC_SKB_BUF, i, DHD_SKB_1PAGE_BUFSIZE);
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {
 | 
						|
		wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);
 | 
						|
		if (!wlan_static_skb[i]) {
 | 
						|
			goto err_skb_alloc;
 | 
						|
		}
 | 
						|
		printk("%s: sectoin %d skb[%d], size=%ld\n", __FUNCTION__, DHD_PREALLOC_SKB_BUF, i, DHD_SKB_2PAGE_BUFSIZE);
 | 
						|
	}
 | 
						|
 | 
						|
#if !defined(CONFIG_BCMDHD_PCIE)
 | 
						|
	wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);
 | 
						|
	if (!wlan_static_skb[i]) {
 | 
						|
		goto err_skb_alloc;
 | 
						|
	}
 | 
						|
#endif /* !CONFIG_BCMDHD_PCIE */
 | 
						|
 | 
						|
	wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_prot) {
 | 
						|
		pr_err("Failed to alloc wlan_static_prot\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_PROT, DHD_PREALLOC_PROT_SIZE);
 | 
						|
 | 
						|
#if defined(CONFIG_BCMDHD_SDIO)
 | 
						|
	wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_rxbuf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_rxbuf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_RXBUF, DHD_PREALLOC_RXBUF_SIZE);
 | 
						|
 | 
						|
	wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_databuf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_databuf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DATABUF, DHD_PREALLOC_DATABUF_SIZE);
 | 
						|
#endif
 | 
						|
 | 
						|
	wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_osl_buf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_osl_buf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%ld\n", __FUNCTION__, DHD_PREALLOC_OSL_BUF, DHD_PREALLOC_OSL_BUF_SIZE);
 | 
						|
 | 
						|
	wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_scan_buf0) {
 | 
						|
		pr_err("Failed to alloc wlan_static_scan_buf0\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_WIPHY_ESCAN0, DHD_PREALLOC_WIPHY_ESCAN0_SIZE);
 | 
						|
 | 
						|
	wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_dhd_info_buf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_dhd_info_buf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_INFO, DHD_PREALLOC_DHD_INFO_SIZE);
 | 
						|
 | 
						|
	wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_dhd_wlfc_info_buf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_dhd_wlfc_info_buf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE);
 | 
						|
 | 
						|
	wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_dhd_wlfc_hanger_buf) {
 | 
						|
		pr_err("Failed to alloc wlan_static_dhd_wlfc_hanger_buf\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
 | 
						|
 | 
						|
#ifdef CONFIG_BCMDHD_PCIE
 | 
						|
	wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);
 | 
						|
	if (!wlan_static_if_flow_lkup) {
 | 
						|
		pr_err("Failed to alloc wlan_static_if_flow_lkup\n");
 | 
						|
		goto err_mem_alloc;
 | 
						|
	}
 | 
						|
	printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_IF_FLOW_LKUP, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);
 | 
						|
#endif /* CONFIG_BCMDHD_PCIE */
 | 
						|
 | 
						|
	return 0;
 | 
						|
 | 
						|
err_mem_alloc:
 | 
						|
 | 
						|
	if (wlan_static_prot)
 | 
						|
		kfree(wlan_static_prot);
 | 
						|
 | 
						|
#if defined(CONFIG_BCMDHD_SDIO)
 | 
						|
	if (wlan_static_rxbuf)
 | 
						|
		kfree(wlan_static_rxbuf);
 | 
						|
 | 
						|
	if (wlan_static_databuf)
 | 
						|
		kfree(wlan_static_databuf);
 | 
						|
#endif
 | 
						|
 | 
						|
	if (wlan_static_dhd_info_buf)
 | 
						|
		kfree(wlan_static_dhd_info_buf);
 | 
						|
 | 
						|
	if (wlan_static_dhd_wlfc_info_buf)
 | 
						|
		kfree(wlan_static_dhd_wlfc_info_buf);
 | 
						|
 | 
						|
	if (wlan_static_dhd_wlfc_hanger_buf)
 | 
						|
		kfree(wlan_static_dhd_wlfc_hanger_buf);
 | 
						|
 | 
						|
	if (wlan_static_scan_buf1)
 | 
						|
		kfree(wlan_static_scan_buf1);
 | 
						|
 | 
						|
	if (wlan_static_scan_buf0)
 | 
						|
		kfree(wlan_static_scan_buf0);
 | 
						|
 | 
						|
	if (wlan_static_osl_buf)
 | 
						|
		kfree(wlan_static_osl_buf);
 | 
						|
 | 
						|
#ifdef CONFIG_BCMDHD_PCIE
 | 
						|
	if (wlan_static_if_flow_lkup)
 | 
						|
		kfree(wlan_static_if_flow_lkup);
 | 
						|
#endif
 | 
						|
	pr_err("Failed to mem_alloc for WLAN\n");
 | 
						|
 | 
						|
	i = WLAN_SKB_BUF_NUM;
 | 
						|
 | 
						|
err_skb_alloc:
 | 
						|
	pr_err("Failed to skb_alloc for WLAN\n");
 | 
						|
	for (j = 0; j < i; j++) {
 | 
						|
		dev_kfree_skb(wlan_static_skb[j]);
 | 
						|
	}
 | 
						|
 | 
						|
	return -ENOMEM;
 | 
						|
}
 | 
						|
 | 
						|
static int __init
 | 
						|
dhd_static_buf_init(void)
 | 
						|
{
 | 
						|
	printk(KERN_ERR "%s()\n", __FUNCTION__);
 | 
						|
 | 
						|
	dhd_init_wlan_mem();
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void __exit
 | 
						|
dhd_static_buf_exit(void)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	printk(KERN_ERR "%s()\n", __FUNCTION__);
 | 
						|
 | 
						|
	for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {
 | 
						|
		if (wlan_static_skb[i])
 | 
						|
			dev_kfree_skb(wlan_static_skb[i]);
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {
 | 
						|
		if (wlan_static_skb[i])
 | 
						|
			dev_kfree_skb(wlan_static_skb[i]);
 | 
						|
	}
 | 
						|
 | 
						|
#if !defined(CONFIG_BCMDHD_PCIE)
 | 
						|
	if (wlan_static_skb[i])
 | 
						|
		dev_kfree_skb(wlan_static_skb[i]);
 | 
						|
#endif /* !CONFIG_BCMDHD_PCIE */
 | 
						|
 | 
						|
	if (wlan_static_prot)
 | 
						|
		kfree(wlan_static_prot);
 | 
						|
 | 
						|
#if defined(CONFIG_BCMDHD_SDIO)
 | 
						|
	if (wlan_static_rxbuf)
 | 
						|
		kfree(wlan_static_rxbuf);
 | 
						|
 | 
						|
	if (wlan_static_databuf)
 | 
						|
		kfree(wlan_static_databuf);
 | 
						|
#endif
 | 
						|
 | 
						|
	if (wlan_static_osl_buf)
 | 
						|
		kfree(wlan_static_osl_buf);
 | 
						|
 | 
						|
	if (wlan_static_scan_buf0)
 | 
						|
		kfree(wlan_static_scan_buf0);
 | 
						|
 | 
						|
	if (wlan_static_dhd_info_buf)
 | 
						|
		kfree(wlan_static_dhd_info_buf);
 | 
						|
 | 
						|
	if (wlan_static_dhd_wlfc_info_buf)
 | 
						|
		kfree(wlan_static_dhd_wlfc_info_buf);
 | 
						|
 | 
						|
	if (wlan_static_dhd_wlfc_hanger_buf)
 | 
						|
		kfree(wlan_static_dhd_wlfc_hanger_buf);
 | 
						|
 | 
						|
	if (wlan_static_scan_buf1)
 | 
						|
		kfree(wlan_static_scan_buf1);
 | 
						|
 | 
						|
#ifdef CONFIG_BCMDHD_PCIE
 | 
						|
	if (wlan_static_if_flow_lkup)
 | 
						|
		kfree(wlan_static_if_flow_lkup);
 | 
						|
#endif
 | 
						|
	return;
 | 
						|
}
 | 
						|
 | 
						|
module_init(dhd_static_buf_init);
 | 
						|
 | 
						|
module_exit(dhd_static_buf_exit);
 |