Commit | Line | Data |
---|---|---|
5adef66a LF |
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 _RECV_OSDEP_C_ | |
21 | ||
22 | #include <osdep_service.h> | |
23 | #include <drv_types.h> | |
24 | ||
25 | #include <wifi.h> | |
26 | #include <recv_osdep.h> | |
27 | ||
28 | #include <osdep_intf.h> | |
17452ee9 | 29 | #include <usb_ops_linux.h> |
5adef66a | 30 | |
f31cca8e | 31 | /* alloc os related resource in struct recv_frame */ |
5adef66a | 32 | int rtw_os_recv_resource_alloc(struct adapter *padapter, |
f31cca8e | 33 | struct recv_frame *precvframe) |
5adef66a | 34 | { |
f31cca8e LF |
35 | precvframe->pkt_newalloc = NULL; |
36 | precvframe->pkt = NULL; | |
5adef66a LF |
37 | return _SUCCESS; |
38 | } | |
39 | ||
5adef66a LF |
40 | /* alloc os related resource in struct recv_buf */ |
41 | int rtw_os_recvbuf_resource_alloc(struct adapter *padapter, | |
42 | struct recv_buf *precvbuf) | |
43 | { | |
44 | int res = _SUCCESS; | |
45 | ||
5adef66a LF |
46 | precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); |
47 | if (precvbuf->purb == NULL) | |
48 | res = _FAIL; | |
49 | precvbuf->pskb = NULL; | |
50 | precvbuf->reuse = false; | |
5adef66a LF |
51 | return res; |
52 | } | |
53 | ||
5adef66a LF |
54 | void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup) |
55 | { | |
56 | union iwreq_data wrqu; | |
57 | struct iw_michaelmicfailure ev; | |
58 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
59 | struct security_priv *psecuritypriv = &padapter->securitypriv; | |
60 | u32 cur_time = 0; | |
61 | ||
62 | if (psecuritypriv->last_mic_err_time == 0) { | |
c01fb496 | 63 | psecuritypriv->last_mic_err_time = jiffies; |
5adef66a | 64 | } else { |
c01fb496 | 65 | cur_time = jiffies; |
5adef66a LF |
66 | |
67 | if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) { | |
68 | psecuritypriv->btkip_countermeasure = true; | |
69 | psecuritypriv->last_mic_err_time = 0; | |
70 | psecuritypriv->btkip_countermeasure_time = cur_time; | |
71 | } else { | |
c01fb496 | 72 | psecuritypriv->last_mic_err_time = jiffies; |
5adef66a LF |
73 | } |
74 | } | |
75 | ||
1ce39848 | 76 | memset(&ev, 0x00, sizeof(ev)); |
5adef66a LF |
77 | if (bgroup) |
78 | ev.flags |= IW_MICFAILURE_GROUP; | |
79 | else | |
80 | ev.flags |= IW_MICFAILURE_PAIRWISE; | |
81 | ||
82 | ev.src_addr.sa_family = ARPHRD_ETHER; | |
83 | memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN); | |
1ce39848 | 84 | memset(&wrqu, 0x00, sizeof(wrqu)); |
5adef66a LF |
85 | wrqu.data.length = sizeof(ev); |
86 | wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE, | |
87 | &wrqu, (char *)&ev); | |
88 | } | |
89 | ||
5adef66a | 90 | int rtw_recv_indicatepkt(struct adapter *padapter, |
f31cca8e | 91 | struct recv_frame *precv_frame) |
5adef66a LF |
92 | { |
93 | struct recv_priv *precvpriv; | |
94 | struct __queue *pfree_recv_queue; | |
95 | struct sk_buff *skb; | |
96 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
97 | ||
5adef66a LF |
98 | |
99 | precvpriv = &(padapter->recvpriv); | |
100 | pfree_recv_queue = &(precvpriv->free_recv_queue); | |
101 | ||
f31cca8e | 102 | skb = precv_frame->pkt; |
5adef66a LF |
103 | if (skb == NULL) { |
104 | RT_TRACE(_module_recv_osdep_c_, _drv_err_, | |
105 | ("rtw_recv_indicatepkt():skb == NULL something wrong!!!!\n")); | |
106 | goto _recv_indicatepkt_drop; | |
107 | } | |
108 | ||
109 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, | |
110 | ("rtw_recv_indicatepkt():skb != NULL !!!\n")); | |
111 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, | |
f31cca8e LF |
112 | ("rtw_recv_indicatepkt():precv_frame->rx_head =%p precv_frame->hdr.rx_data =%p\n", |
113 | precv_frame->rx_head, precv_frame->rx_data)); | |
5adef66a | 114 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, |
f31cca8e LF |
115 | ("precv_frame->hdr.rx_tail =%p precv_frame->rx_end =%p precv_frame->hdr.len =%d\n", |
116 | precv_frame->rx_tail, precv_frame->rx_end, | |
117 | precv_frame->len)); | |
5adef66a | 118 | |
f31cca8e | 119 | skb->data = precv_frame->rx_data; |
5adef66a | 120 | |
f31cca8e | 121 | skb_set_tail_pointer(skb, precv_frame->len); |
5adef66a | 122 | |
f31cca8e | 123 | skb->len = precv_frame->len; |
5adef66a LF |
124 | |
125 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, | |
126 | ("skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", | |
127 | skb->head, skb->data, skb_tail_pointer(skb), | |
128 | skb_end_pointer(skb), skb->len)); | |
129 | ||
130 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { | |
131 | struct sk_buff *pskb2 = NULL; | |
132 | struct sta_info *psta = NULL; | |
133 | struct sta_priv *pstapriv = &padapter->stapriv; | |
f31cca8e | 134 | struct rx_pkt_attrib *pattrib = &precv_frame->attrib; |
5adef66a LF |
135 | int bmcast = IS_MCAST(pattrib->dst); |
136 | ||
f42f52aa LF |
137 | if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), |
138 | ETH_ALEN)) { | |
5adef66a LF |
139 | if (bmcast) { |
140 | psta = rtw_get_bcmc_stainfo(padapter); | |
141 | pskb2 = skb_clone(skb, GFP_ATOMIC); | |
142 | } else { | |
143 | psta = rtw_get_stainfo(pstapriv, pattrib->dst); | |
144 | } | |
145 | ||
146 | if (psta) { | |
147 | struct net_device *pnetdev; | |
148 | ||
149 | pnetdev = (struct net_device *)padapter->pnetdev; | |
150 | skb->dev = pnetdev; | |
151 | skb_set_queue_mapping(skb, rtw_recv_select_queue(skb)); | |
152 | ||
153 | rtw_xmit_entry(skb, pnetdev); | |
154 | ||
155 | if (bmcast) | |
156 | skb = pskb2; | |
157 | else | |
158 | goto _recv_indicatepkt_end; | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
163 | rcu_read_lock(); | |
164 | rcu_dereference(padapter->pnetdev->rx_handler_data); | |
165 | rcu_read_unlock(); | |
166 | ||
167 | skb->ip_summed = CHECKSUM_NONE; | |
168 | skb->dev = padapter->pnetdev; | |
169 | skb->protocol = eth_type_trans(skb, padapter->pnetdev); | |
170 | ||
171 | netif_rx(skb); | |
172 | ||
173 | _recv_indicatepkt_end: | |
174 | ||
175 | /* pointers to NULL before rtw_free_recvframe() */ | |
f31cca8e | 176 | precv_frame->pkt = NULL; |
5adef66a LF |
177 | |
178 | rtw_free_recvframe(precv_frame, pfree_recv_queue); | |
179 | ||
180 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, | |
181 | ("\n rtw_recv_indicatepkt :after netif_rx!!!!\n")); | |
182 | ||
5adef66a LF |
183 | |
184 | return _SUCCESS; | |
185 | ||
186 | _recv_indicatepkt_drop: | |
187 | ||
188 | /* enqueue back to free_recv_queue */ | |
9b276d2b | 189 | rtw_free_recvframe(precv_frame, pfree_recv_queue); |
5adef66a | 190 | |
5adef66a LF |
191 | return _FAIL; |
192 | } | |
193 | ||
5adef66a LF |
194 | void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl) |
195 | { | |
196 | struct adapter *padapter = preorder_ctrl->padapter; | |
197 | ||
7ebd4cba | 198 | _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, rtw_reordering_ctrl_timeout_handler, preorder_ctrl); |
5adef66a | 199 | } |