[WCNCR00166654] misc: add memory preallocation module

[Description]
memory preallocation is for avoiding memory fragmentation

Usage:
1. in Makefile.x86 or Makefile.ce
   export CONFIG_MTK_PREALLOC_MEMORY=y
2. after build, there is preallocate module
   ex. wlan_mt6632_usb_prealloc.ko
3. insmod prealloc module before insmod wifi module

Note:
for all HIFs, now just USB is implemented

Test:
in Linux PC is ok
1. insmod prealloc module
2. loop insmod wifi module -> connect AP -> rmmod wifi module

Change-Id: I3531381a328ee47f25e2cd2764b67e1dbfe04578
Signed-off-by: Neil Chen <yn.chen@mediatek.com>
CR-Id: WCNCR00166654
Feature: misc
diff --git a/Makefile b/Makefile
index eb58c30..2c253ad 100644
--- a/Makefile
+++ b/Makefile
@@ -254,4 +254,14 @@
 $(MODULE_NAME)-objs  += $(MGMT_OBJS)
 $(MODULE_NAME)-objs  += $(CHIPS_OBJS)
 
-
+#
+# mtprealloc
+#
+ifeq ($(CONFIG_MTK_PREALLOC_MEMORY), y)
+ccflags-y += -DCFG_PREALLOC_MEMORY
+ccflags-y += -I$(src)/prealloc/include
+MODULE_NAME_PREALLOC = $(MODULE_NAME)_prealloc
+PREALLOC_OBJS := prealloc/prealloc.o
+$(MODULE_NAME_PREALLOC)-objs += $(PREALLOC_OBJS)
+obj-m += $(MODULE_NAME_PREALLOC).o
+endif
diff --git a/Makefile.ce b/Makefile.ce
index fa830eb..5738d2e 100644
--- a/Makefile.ce
+++ b/Makefile.ce
@@ -24,6 +24,7 @@
 export CONFIG_MTK_COMBO_WIFI_HIF=$(HIF)
 MODULE_NAME := wlan_$(WLAN_CHIP_ID)_$(HIF)
 
+export CONFIG_MTK_PREALLOC_MEMORY=n
 
 ##############################################################
 # Platform specific
diff --git a/Makefile.x86 b/Makefile.x86
index 3a91303..ad95c45 100644
--- a/Makefile.x86
+++ b/Makefile.x86
@@ -36,6 +36,8 @@
 
 export CONFIG_MTK_COMBO_PLAT_PATH=x86
 
+export CONFIG_MTK_PREALLOC_MEMORY=n
+
 ##############################################################
 # Compile options
 ##############################################################
diff --git a/include/precomp.h b/include/precomp.h
index 33beba8..8dd937f 100644
--- a/include/precomp.h
+++ b/include/precomp.h
@@ -247,6 +247,14 @@
 #include "gl_qa_agent.h"
 #endif
 
+/*------------------------------------------------------------------------------
+ * Memory Prealloc
+ *------------------------------------------------------------------------------
+ */
+#ifdef CFG_PREALLOC_MEMORY
+#include "prealloc.h"
+#endif
+
 /*******************************************************************************
 *                              C O N S T A N T S
 ********************************************************************************
diff --git a/nic/nic.c b/nic/nic.c
index 8754a79..4fe165c 100644
--- a/nic/nic.c
+++ b/nic/nic.c
@@ -191,8 +191,12 @@
 		/* Allocate memory for the CMD_INFO_T and its MGMT memory pool. */
 		prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE;
 
+#ifdef CFG_PREALLOC_MEMORY
+		prAdapter->pucMgtBufCached = preallocGetMem(MEM_ID_NIC_ADAPTER);
+#else
 		LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached,
 					  prAdapter->u4MgtBufCachedSize, PHY_MEM_TYPE, "COMMON MGMT MEMORY POOL");
+#endif
 
 		/* 4 <2> Memory for RX Descriptor */
 		/* Initialize the number of rx buffers we will have in our queue. */
@@ -279,7 +283,9 @@
 	}
 	/* 4 <1> Memory for Management Memory Pool */
 	if (prAdapter->pucMgtBufCached) {
+#ifndef CFG_PREALLOC_MEMORY
 		kalMemFree((PVOID) prAdapter->pucMgtBufCached, PHY_MEM_TYPE, prAdapter->u4MgtBufCachedSize);
+#endif
 		prAdapter->pucMgtBufCached = (PUINT_8) NULL;
 	}
 
diff --git a/os/linux/hif/usb/usb.c b/os/linux/hif/usb/usb.c
index d360448..2dcf6d4 100644
--- a/os/linux/hif/usb/usb.c
+++ b/os/linux/hif/usb/usb.c
@@ -793,8 +793,12 @@
 		prUsbReq->prBufCtrl->pucBuf = usb_alloc_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE, GFP_ATOMIC,
 								 &prUsbReq->prUrb->transfer_dma);
 #else
+#ifdef CFG_PREALLOC_MEMORY
+		prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_CMD);
+#else
 		prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_CMD_BUF_SIZE, GFP_ATOMIC);
 #endif
+#endif
 		if (prUsbReq->prBufCtrl->pucBuf == NULL) {
 			DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
 			goto error;
@@ -848,8 +852,12 @@
 			    usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC,
 					       &prUsbReq->prUrb->transfer_dma);
 #else
+#ifdef CFG_PREALLOC_MEMORY
+			prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA);
+#else
 			prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUFF_SIZE, GFP_ATOMIC);
 #endif
+#endif
 			if (prUsbReq->prBufCtrl->pucBuf == NULL) {
 				DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
 				goto error;
@@ -874,8 +882,12 @@
 		    usb_alloc_coherent(prHifInfo->udev, USB_TX_DATA_BUF_SIZE, GFP_ATOMIC,
 				       &prUsbReq->prUrb->transfer_dma);
 #else
+#ifdef CFG_PREALLOC_MEMORY
+		prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_TX_DATA);
+#else
 		prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_TX_DATA_BUF_SIZE, GFP_ATOMIC);
 #endif
+#endif
 		if (prUsbReq->prBufCtrl->pucBuf == NULL) {
 			DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
 			goto error;
@@ -893,7 +905,11 @@
 	i = 0;
 	list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) {
 		prUsbReq->prBufCtrl = &prHifInfo->rRxEventBufCtrl[i];
+#ifdef CFG_PREALLOC_MEMORY
+		prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_EVENT);
+#else
 		prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_EVENT_BUF_SIZE, GFP_ATOMIC);
+#endif
 		if (prUsbReq->prBufCtrl->pucBuf == NULL) {
 			DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
 			goto error;
@@ -908,7 +924,11 @@
 	i = 0;
 	list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) {
 		prUsbReq->prBufCtrl = &prHifInfo->rRxDataBufCtrl[i];
+#ifdef CFG_PREALLOC_MEMORY
+		prUsbReq->prBufCtrl->pucBuf = preallocGetMem(MEM_ID_RX_DATA);
+#else
 		prUsbReq->prBufCtrl->pucBuf = kmalloc(USB_RX_DATA_BUF_SIZE, GFP_ATOMIC);
+#endif
 		if (prUsbReq->prBufCtrl->pucBuf == NULL) {
 			DBGLOG(HAL, ERROR, "kmalloc() reports error\n");
 			goto error;
@@ -959,8 +979,10 @@
 			usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE,
 				prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma);
 #else
+#ifndef CFG_PREALLOC_MEMORY
 			kfree(prUsbReq->prBufCtrl->pucBuf);
 #endif
+#endif
 			usb_free_urb(prUsbReq->prUrb);
 		}
 	}
@@ -970,8 +992,10 @@
 		usb_free_coherent(prHifInfo->udev, USB_TX_DATA_BUFF_SIZE,
 			prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma);
 #else
+#ifndef CFG_PREALLOC_MEMORY
 		kfree(prUsbReq->prBufCtrl->pucBuf);
 #endif
+#endif
 		usb_free_urb(prUsbReq->prUrb);
 	}
 #endif
@@ -991,8 +1015,10 @@
 		usb_free_coherent(prHifInfo->udev, USB_TX_CMD_BUF_SIZE,
 			prUsbReq->prBufCtrl->pucBuf, prUsbReq->prUrb->transfer_dma);
 #else
+#ifndef CFG_PREALLOC_MEMORY
 		kfree(prUsbReq->prBufCtrl->pucBuf);
 #endif
+#endif
 		usb_free_urb(prUsbReq->prUrb);
 	}
 
@@ -1017,12 +1043,16 @@
 	}
 
 	list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxDataFreeQ, list) {
+#ifndef CFG_PREALLOC_MEMORY
 		kfree(prUsbReq->prBufCtrl->pucBuf);
+#endif
 		usb_free_urb(prUsbReq->prUrb);
 	}
 
 	list_for_each_entry_safe(prUsbReq, prUsbReqNext, &prHifInfo->rRxEventFreeQ, list) {
+#ifndef CFG_PREALLOC_MEMORY
 		kfree(prUsbReq->prBufCtrl->pucBuf);
+#endif
 		usb_free_urb(prUsbReq->prUrb);
 	}
 
diff --git a/prealloc/include/prealloc.h b/prealloc/include/prealloc.h
new file mode 100644
index 0000000..80d4ee5
--- /dev/null
+++ b/prealloc/include/prealloc.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual license.  When you use or
+ * distribute this software, you may choose to be licensed under
+ * version 2 of the GNU General Public License ("GPLv2 License")
+ * or BSD License.
+ *
+ * GPLv2 License
+ *
+ * Copyright(C) 2017 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(C) 2017 MediaTek Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*! \file   "prealloc.h"
+*   \brief  This file contains the declairation of memory preallocation module
+*/
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#ifndef _PREALLOC_H
+#define _PREALLOC_H
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+enum ENUM_MEM_ID {
+	MEM_ID_NIC_ADAPTER,
+#if defined(_HIF_USB)
+	MEM_ID_TX_CMD,
+	MEM_ID_TX_DATA,
+	MEM_ID_RX_EVENT,
+	MEM_ID_RX_DATA,
+#endif
+
+	MEM_ID_NUM, /* END, Do not modify */
+};
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+#define PreLog(level, ...) printk(level "[wlan][MemPrealloc] " __VA_ARGS__)
+#define MP_Info(...) PreLog(KERN_INFO, __VA_ARGS__)
+#define MP_Err(...) PreLog(KERN_ERR, __VA_ARGS__)
+
+/*******************************************************************************
+*                   F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+PVOID preallocGetMem(enum ENUM_MEM_ID memId);
+
+#endif /* _PREALLOC_H */
diff --git a/prealloc/prealloc.c b/prealloc/prealloc.c
new file mode 100644
index 0000000..3da0309
--- /dev/null
+++ b/prealloc/prealloc.c
@@ -0,0 +1,284 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual license.  When you use or
+ * distribute this software, you may choose to be licensed under
+ * version 2 of the GNU General Public License ("GPLv2 License")
+ * or BSD License.
+ *
+ * GPLv2 License
+ *
+ * Copyright(C) 2017 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(C) 2017 MediaTek Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*! \file   prealloc.c
+*   \brief  memory preallocation module
+*
+*    This file contains all implementations of memory preallocation module
+*/
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include "precomp.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+/*
+ * -----------------             ----------------           ----------
+ * | PRE_MEM_BLOCK |-pItemArray->| PRE_MEM_ITEM |-pvBuffer->| Memory |
+ * |---------------|             |--------------|           ----------
+ * | PRE_MEM_BLOCK |->...        | PRE_MEM_ITEM |-pvBuffer->----------
+ * |---------------|             |--------------|           | Memory |
+ *       .                              .                   ----------
+ *       .                              .
+ *       .                              .
+ */
+struct PRE_MEM_ITEM {
+	PVOID pvBuffer;
+};
+
+struct PRE_MEM_BLOCK {
+	PUCHAR pucName;
+	struct PRE_MEM_ITEM *pItemArray;
+	UINT_32 u4Count;
+	UINT_32 u4Size;
+	UINT_32 u4KmallocFlags;
+	UINT_32 u4Curr;
+};
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+static INT_32 blockCount;
+static struct PRE_MEM_BLOCK arMemBlocks[MEM_ID_NUM];
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+/*----------------------------------------------------------------------------*/
+/*!
+* \brief export function for memory preallocation
+*
+* \param[in] memId memory id.
+*
+* \retval void pointer to the memory address
+*/
+/*----------------------------------------------------------------------------*/
+PVOID preallocGetMem(enum ENUM_MEM_ID memId)
+{
+	struct PRE_MEM_BLOCK *block = NULL;
+	UINT_32 curr = 0, count = 0;
+	PUCHAR name = NULL;
+
+	/* check memId exist */
+	if (memId < 0 || memId >= MEM_ID_NUM) {
+		MP_Err("request wrong memId %d", memId);
+		return NULL;
+	}
+
+	block = &arMemBlocks[memId];
+	curr = block->u4Curr;
+	count = block->u4Count;
+	name = block->pucName;
+	block->u4Curr = (curr + 1) % count; /* point to next */
+
+	/* return request memory address */
+	MP_Info("request [%s], return [%d]\n", name, curr);
+	return block->pItemArray[curr].pvBuffer;
+}
+EXPORT_SYMBOL(preallocGetMem);
+
+static void preallocFree(void)
+{
+	INT_32 i = 0, j = 0;
+	struct PRE_MEM_BLOCK *block = NULL;
+	struct PRE_MEM_ITEM *items = NULL;
+	PVOID memory = NULL;
+
+	for (i = 0; i < MEM_ID_NUM; i++) {
+		block = &arMemBlocks[i];
+		MP_Info("free [%d], block name=\"%s\" count=%d size=%d\n",
+				i, block->pucName, block->u4Count, block->u4Size);
+		items = block->pItemArray;
+		if (items == NULL)
+			continue;
+		/* free memory */
+		for (j = 0; j < block->u4Count; j++) {
+			memory = items[j].pvBuffer;
+			MP_Info(" - [%d] memory 0x%p\n", j, memory);
+			kfree(memory);
+		}
+		/* free items */
+		MP_Info(" - items 0x%p\n", items);
+		kfree(items);
+		memset(block, 0, sizeof(*block));
+	}
+}
+
+static int preallocAlloc(void)
+{
+	INT_32 i = 0, j = 0;
+	struct PRE_MEM_BLOCK *block = NULL;
+	struct PRE_MEM_ITEM *items = NULL;
+	PVOID memory = NULL;
+
+	for (i = 0; i < MEM_ID_NUM; i++) {
+		block = &arMemBlocks[i];
+		MP_Info("allocate [%d] block name=\"%s\" count=%d size=%d\n",
+				i, block->pucName, block->u4Count, block->u4Size);
+		/* allocate u4Count items */
+		items = kcalloc(block->u4Count, sizeof(*items), GFP_KERNEL);
+		if (items == NULL) {
+			MP_Err("allocate [%d] items failed\n", i);
+			goto fail;
+		}
+		MP_Info(" + items 0x%p\n", items);
+		block->pItemArray = items;
+		for (j = 0; j < block->u4Count; j++) {
+			/* allocate u4Size memory */
+			memory = kmalloc(block->u4Size, block->u4KmallocFlags);
+			if (memory == NULL) {
+				MP_Err("allocate [%d][%d] memory failed\n", i, j);
+				goto fail;
+			}
+			MP_Info(" + [%d] memory 0x%p\n", j, memory);
+			items[j].pvBuffer = memory;
+		}
+	}
+
+	return 0;
+
+fail:
+	preallocFree();
+	return -ENOMEM;
+}
+
+static void preallocAddBlock(enum ENUM_MEM_ID memId,
+		PUCHAR name, UINT_32 count, UINT_32 size, UINT_32 kmallocFlags)
+{
+	if (memId != blockCount) {
+		MP_Err("memId %d != index %d\n", memId, blockCount);
+		return;
+	}
+	arMemBlocks[blockCount].pucName = name;
+	arMemBlocks[blockCount].pItemArray = NULL;
+	arMemBlocks[blockCount].u4Count = count;
+	arMemBlocks[blockCount].u4Size = size;
+	arMemBlocks[blockCount].u4KmallocFlags = kmallocFlags;
+	arMemBlocks[blockCount].u4Curr = 0;
+	blockCount++;
+}
+
+static int __init preallocInit(void)
+{
+	blockCount = 0;
+
+	/* ADD BLOCK START, follow the sequence of ENUM_MEM_ID */
+	preallocAddBlock(MEM_ID_NIC_ADAPTER, "NIC ADAPTER MEMORY",
+			1, MGT_BUFFER_SIZE,
+			GFP_KERNEL);
+#if defined(_HIF_USB)
+	preallocAddBlock(MEM_ID_TX_CMD, "TX CMD",
+			USB_REQ_TX_CMD_CNT, USB_TX_CMD_BUF_SIZE,
+			GFP_KERNEL);
+#if CFG_USB_TX_AGG
+	preallocAddBlock(MEM_ID_TX_DATA, "TX AGG DATA",
+			(USB_TC_NUM * USB_REQ_TX_DATA_CNT), USB_TX_DATA_BUFF_SIZE,
+			GFP_KERNEL);
+#else
+	preallocAddBlock(MEM_ID_TX_DATA, "TX DATA",
+			USB_REQ_TX_DATA_CNT, USB_TX_DATA_BUFF_SIZE,
+			GFP_KERNEL);
+#endif
+	preallocAddBlock(MEM_ID_RX_EVENT, "RX EVENT",
+			USB_REQ_RX_EVENT_CNT, USB_RX_EVENT_BUF_SIZE,
+			GFP_KERNEL);
+	preallocAddBlock(MEM_ID_RX_DATA, "RX DATA",
+			USB_REQ_RX_DATA_CNT, USB_RX_DATA_BUF_SIZE,
+			GFP_KERNEL);
+#endif
+	/* ADD BLOCK END */
+
+	return preallocAlloc();
+}
+
+static void __exit preallocExit(void)
+{
+	preallocFree();
+}
+
+module_init(preallocInit);
+module_exit(preallocExit);