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