1/****************************************************************************** 2 * 3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 17 * 18 * 19 ******************************************************************************/ 20#define _RTL8188EU_RECV_C_ 21#include <osdep_service.h> 22#include <drv_types.h> 23#include <recv_osdep.h> 24#include <mlme_osdep.h> 25 26#include <usb_ops_linux.h> 27#include <wifi.h> 28 29#include <rtl8188e_hal.h> 30 31int rtl8188eu_init_recv_priv(struct adapter *padapter) 32{ 33 struct recv_priv *precvpriv = &padapter->recvpriv; 34 int i, res = _SUCCESS; 35 struct recv_buf *precvbuf; 36 37 tasklet_init(&precvpriv->recv_tasklet, 38 (void(*)(unsigned long))rtl8188eu_recv_tasklet, 39 (unsigned long)padapter); 40 41 /* init recv_buf */ 42 _rtw_init_queue(&precvpriv->free_recv_buf_queue); 43 44 precvpriv->pallocated_recv_buf = 45 kzalloc(NR_RECVBUFF * sizeof(struct recv_buf), GFP_KERNEL); 46 if (precvpriv->pallocated_recv_buf == NULL) { 47 res = _FAIL; 48 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, 49 ("alloc recv_buf fail!\n")); 50 goto exit; 51 } 52 53 precvpriv->precv_buf = precvpriv->pallocated_recv_buf; 54 55 56 precvbuf = (struct recv_buf *)precvpriv->precv_buf; 57 58 for (i = 0; i < NR_RECVBUFF; i++) { 59 res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf); 60 if (res == _FAIL) 61 break; 62 precvbuf->adapter = padapter; 63 precvbuf++; 64 } 65 precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF; 66 skb_queue_head_init(&precvpriv->rx_skb_queue); 67 { 68 int i; 69 size_t tmpaddr = 0; 70 size_t alignm = 0; 71 struct sk_buff *pskb = NULL; 72 73 skb_queue_head_init(&precvpriv->free_recv_skb_queue); 74 75 for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) { 76 pskb = __netdev_alloc_skb(padapter->pnetdev, 77 MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, 78 GFP_KERNEL); 79 if (pskb) { 80 pskb->dev = padapter->pnetdev; 81 tmpaddr = (size_t)pskb->data; 82 alignm = tmpaddr & (RECVBUFF_ALIGN_SZ-1); 83 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignm)); 84 85 skb_queue_tail(&precvpriv->free_recv_skb_queue, 86 pskb); 87 } 88 pskb = NULL; 89 } 90 } 91exit: 92 return res; 93} 94 95void rtl8188eu_free_recv_priv(struct adapter *padapter) 96{ 97 int i; 98 struct recv_buf *precvbuf; 99 struct recv_priv *precvpriv = &padapter->recvpriv; 100 101 precvbuf = (struct recv_buf *)precvpriv->precv_buf; 102 103 for (i = 0; i < NR_RECVBUFF; i++) { 104 usb_free_urb(precvbuf->purb); 105 precvbuf++; 106 } 107 108 kfree(precvpriv->pallocated_recv_buf); 109 110 if (skb_queue_len(&precvpriv->rx_skb_queue)) 111 DBG_88E(KERN_WARNING "rx_skb_queue not empty\n"); 112 skb_queue_purge(&precvpriv->rx_skb_queue); 113 114 115 if (skb_queue_len(&precvpriv->free_recv_skb_queue)) 116 DBG_88E(KERN_WARNING "free_recv_skb_queue not empty, %d\n", 117 skb_queue_len(&precvpriv->free_recv_skb_queue)); 118 119 skb_queue_purge(&precvpriv->free_recv_skb_queue); 120} 121