/****************************************************************************** * * Copyright(c) 2016 - 2017 Realtek Corporation. * * 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 the GNU General Public License for * more details. * *****************************************************************************/ #include <drv_types.h> #include <rtw_mem.h> MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Realtek Wireless Lan Driver"); MODULE_AUTHOR("Realtek Semiconductor Corp."); MODULE_VERSION("DRIVERVERSION"); struct sk_buff_head rtk_skb_mem_q; struct u8 *rtk_buf_mem[NR_RECVBUFF]; struct u8 *rtw_get_buf_premem(int index) { printk("%s, rtk_buf_mem index : %d\n", __func__, index); return rtk_buf_mem[index]; } u16 rtw_rtkm_get_buff_size(void) { return MAX_RTKM_RECVBUF_SZ; } EXPORT_SYMBOL(rtw_rtkm_get_buff_size); u8 rtw_rtkm_get_nr_recv_skb(void) { return MAX_RTKM_NR_PREALLOC_RECV_SKB; } EXPORT_SYMBOL(rtw_rtkm_get_nr_recv_skb); struct sk_buff *rtw_alloc_skb_premem(u16 in_size) { struct sk_buff *skb = NULL; if (in_size > MAX_RTKM_RECVBUF_SZ) { pr_info("warning %s: driver buffer size(%d) > rtkm buffer size(%d)\n", __func__, in_size, MAX_RTKM_RECVBUF_SZ); WARN_ON(1); return skb; } skb = skb_dequeue(&rtk_skb_mem_q); printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q)); return skb; } EXPORT_SYMBOL(rtw_alloc_skb_premem); int rtw_free_skb_premem(struct sk_buff *pskb) { if (!pskb) return -1; if (skb_queue_len(&rtk_skb_mem_q) >= MAX_RTKM_NR_PREALLOC_RECV_SKB) return -1; skb_queue_tail(&rtk_skb_mem_q, pskb); printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q)); return 0; } EXPORT_SYMBOL(rtw_free_skb_premem); static int __init rtw_mem_init(void) { int i; SIZE_PTR tmpaddr = 0; SIZE_PTR alignment = 0; struct sk_buff *pskb = NULL; printk("%s\n", __func__); pr_info("MAX_RTKM_NR_PREALLOC_RECV_SKB: %d\n", MAX_RTKM_NR_PREALLOC_RECV_SKB); pr_info("MAX_RTKM_RECVBUF_SZ: %d\n", MAX_RTKM_RECVBUF_SZ); #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX for (i = 0; i < NR_RECVBUFF; i++) rtk_buf_mem[i] = usb_buffer_alloc(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma); #endif /* CONFIG_USE_USB_BUFFER_ALLOC_RX */ skb_queue_head_init(&rtk_skb_mem_q); for (i = 0; i < MAX_RTKM_NR_PREALLOC_RECV_SKB; i++) { pskb = __dev_alloc_skb(MAX_RTKM_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); if (pskb) { tmpaddr = (SIZE_PTR)pskb->data; alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1); skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment)); skb_queue_tail(&rtk_skb_mem_q, pskb); } else printk("%s, alloc skb memory fail!\n", __func__); pskb = NULL; } printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q)); return 0; } static void __exit rtw_mem_exit(void) { if (skb_queue_len(&rtk_skb_mem_q)) printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q)); skb_queue_purge(&rtk_skb_mem_q); printk("%s\n", __func__); } module_init(rtw_mem_init); module_exit(rtw_mem_exit);