Commit | Line | Data |
---|---|---|
58391efd | 1 | // SPDX-License-Identifier: GPL-2.0 |
554c0a3a HG |
2 | /****************************************************************************** |
3 | * | |
4 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
5 | * | |
554c0a3a HG |
6 | ******************************************************************************/ |
7 | #define _RECV_OSDEP_C_ | |
8 | ||
9 | #include <drv_types.h> | |
10 | #include <rtw_debug.h> | |
11 | #include <linux/jiffies.h> | |
12 | ||
13 | void rtw_os_free_recvframe(union recv_frame *precvframe) | |
14 | { | |
6a9b5dd1 | 15 | if (precvframe->u.hdr.pkt) { |
554c0a3a HG |
16 | dev_kfree_skb_any(precvframe->u.hdr.pkt);/* free skb by driver */ |
17 | ||
18 | precvframe->u.hdr.pkt = NULL; | |
19 | } | |
20 | } | |
21 | ||
22 | /* alloc os related resource in union recv_frame */ | |
d05b5320 | 23 | void rtw_os_recv_resource_alloc(struct adapter *padapter, union recv_frame *precvframe) |
554c0a3a | 24 | { |
554c0a3a | 25 | precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL; |
554c0a3a HG |
26 | } |
27 | ||
28 | /* free os related resource in union recv_frame */ | |
29 | void rtw_os_recv_resource_free(struct recv_priv *precvpriv) | |
30 | { | |
31 | sint i; | |
32 | union recv_frame *precvframe; | |
f066ac11 | 33 | |
554c0a3a HG |
34 | precvframe = (union recv_frame*) precvpriv->precv_frame_buf; |
35 | ||
6a9b5dd1 SK |
36 | for (i = 0; i < NR_RECVFRAME; i++) { |
37 | if (precvframe->u.hdr.pkt) { | |
b6b2a53c VK |
38 | /* free skb by driver */ |
39 | dev_kfree_skb_any(precvframe->u.hdr.pkt); | |
554c0a3a HG |
40 | precvframe->u.hdr.pkt = NULL; |
41 | } | |
42 | precvframe++; | |
43 | } | |
44 | } | |
45 | ||
46 | /* free os related resource in struct recv_buf */ | |
85d237bd | 47 | void rtw_os_recvbuf_resource_free(struct adapter *padapter, struct recv_buf *precvbuf) |
554c0a3a | 48 | { |
6a9b5dd1 | 49 | if (precvbuf->pskb) { |
554c0a3a HG |
50 | dev_kfree_skb_any(precvbuf->pskb); |
51 | } | |
554c0a3a HG |
52 | } |
53 | ||
54 | _pkt *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 *pdata) | |
55 | { | |
56 | u16 eth_type; | |
554c0a3a HG |
57 | _pkt *sub_skb; |
58 | struct rx_pkt_attrib *pattrib; | |
59 | ||
60 | pattrib = &prframe->u.hdr.attrib; | |
61 | ||
62 | sub_skb = rtw_skb_alloc(nSubframe_Length + 12); | |
6a9b5dd1 | 63 | if (sub_skb) { |
554c0a3a | 64 | skb_reserve(sub_skb, 12); |
b952f4df | 65 | skb_put_data(sub_skb, (pdata + ETH_HLEN), nSubframe_Length); |
fabf2986 | 66 | } else { |
554c0a3a | 67 | sub_skb = rtw_skb_clone(prframe->u.hdr.pkt); |
6a9b5dd1 | 68 | if (sub_skb) { |
554c0a3a HG |
69 | sub_skb->data = pdata + ETH_HLEN; |
70 | sub_skb->len = nSubframe_Length; | |
71 | skb_set_tail_pointer(sub_skb, nSubframe_Length); | |
fabf2986 | 72 | } else { |
554c0a3a HG |
73 | DBG_871X("%s(): rtw_skb_clone() Fail!!!\n", __func__); |
74 | return NULL; | |
75 | } | |
76 | } | |
77 | ||
78 | eth_type = RTW_GET_BE16(&sub_skb->data[6]); | |
79 | ||
80 | if (sub_skb->len >= 8 && | |
81 | ((!memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) && | |
82 | eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || | |
83 | !memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE))) { | |
b6b2a53c VK |
84 | /* |
85 | * remove RFC1042 or Bridge-Tunnel encapsulation and replace | |
86 | * EtherType | |
87 | */ | |
554c0a3a HG |
88 | skb_pull(sub_skb, SNAP_SIZE); |
89 | memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); | |
90 | memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); | |
91 | } else { | |
92 | __be16 len; | |
93 | /* Leave Ethernet header part of hdr and full payload */ | |
94 | len = htons(sub_skb->len); | |
95 | memcpy(skb_push(sub_skb, 2), &len, 2); | |
96 | memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); | |
97 | memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); | |
98 | } | |
99 | ||
100 | return sub_skb; | |
101 | } | |
102 | ||
103 | void rtw_os_recv_indicate_pkt(struct adapter *padapter, _pkt *pkt, struct rx_pkt_attrib *pattrib) | |
104 | { | |
105 | struct mlme_priv*pmlmepriv = &padapter->mlmepriv; | |
106 | int ret; | |
107 | ||
3fce0276 | 108 | /* Indicate the packets to upper layer */ |
554c0a3a | 109 | if (pkt) { |
6a9b5dd1 | 110 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) { |
554c0a3a HG |
111 | _pkt *pskb2 = NULL; |
112 | struct sta_info *psta = NULL; | |
113 | struct sta_priv *pstapriv = &padapter->stapriv; | |
114 | int bmcast = IS_MCAST(pattrib->dst); | |
115 | ||
6a9b5dd1 | 116 | if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) { |
6a9b5dd1 | 117 | if (bmcast) { |
554c0a3a HG |
118 | psta = rtw_get_bcmc_stainfo(padapter); |
119 | pskb2 = rtw_skb_clone(pkt); | |
120 | } else { | |
121 | psta = rtw_get_stainfo(pstapriv, pattrib->dst); | |
122 | } | |
123 | ||
6a9b5dd1 | 124 | if (psta) { |
554c0a3a | 125 | struct net_device *pnetdev = (struct net_device*)padapter->pnetdev; |
554c0a3a HG |
126 | /* skb->ip_summed = CHECKSUM_NONE; */ |
127 | pkt->dev = pnetdev; | |
128 | skb_set_queue_mapping(pkt, rtw_recv_select_queue(pkt)); | |
129 | ||
130 | _rtw_xmit_entry(pkt, pnetdev); | |
131 | ||
132 | if (bmcast && (pskb2 != NULL)) { | |
133 | pkt = pskb2; | |
134 | DBG_COUNTER(padapter->rx_logs.os_indicate_ap_mcast); | |
135 | } else { | |
136 | DBG_COUNTER(padapter->rx_logs.os_indicate_ap_forward); | |
137 | return; | |
138 | } | |
139 | } | |
fabf2986 | 140 | } else { |
6a9b5dd1 | 141 | /* to APself */ |
554c0a3a HG |
142 | /* DBG_871X("to APSelf\n"); */ |
143 | DBG_COUNTER(padapter->rx_logs.os_indicate_ap_self); | |
144 | } | |
145 | } | |
146 | ||
147 | pkt->protocol = eth_type_trans(pkt, padapter->pnetdev); | |
148 | pkt->dev = padapter->pnetdev; | |
149 | ||
150 | #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX | |
af1bef4a | 151 | if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) |
554c0a3a | 152 | pkt->ip_summed = CHECKSUM_UNNECESSARY; |
af1bef4a | 153 | else |
554c0a3a | 154 | pkt->ip_summed = CHECKSUM_NONE; |
af1bef4a | 155 | |
554c0a3a HG |
156 | #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ |
157 | pkt->ip_summed = CHECKSUM_NONE; | |
158 | #endif /* CONFIG_TCP_CSUM_OFFLOAD_RX */ | |
159 | ||
160 | ret = rtw_netif_rx(padapter->pnetdev, pkt); | |
161 | if (ret == NET_RX_SUCCESS) | |
162 | DBG_COUNTER(padapter->rx_logs.os_netif_ok); | |
163 | else | |
164 | DBG_COUNTER(padapter->rx_logs.os_netif_err); | |
165 | } | |
166 | } | |
167 | ||
168 | void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup) | |
169 | { | |
170 | enum nl80211_key_type key_type = 0; | |
171 | union iwreq_data wrqu; | |
172 | struct iw_michaelmicfailure ev; | |
173 | struct mlme_priv* pmlmepriv = &padapter->mlmepriv; | |
174 | struct security_priv *psecuritypriv = &padapter->securitypriv; | |
175 | unsigned long cur_time = 0; | |
176 | ||
6a9b5dd1 | 177 | if (psecuritypriv->last_mic_err_time == 0) { |
554c0a3a | 178 | psecuritypriv->last_mic_err_time = jiffies; |
fabf2986 | 179 | } else { |
554c0a3a HG |
180 | cur_time = jiffies; |
181 | ||
6a9b5dd1 | 182 | if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) { |
554c0a3a HG |
183 | psecuritypriv->btkip_countermeasure = true; |
184 | psecuritypriv->last_mic_err_time = 0; | |
185 | psecuritypriv->btkip_countermeasure_time = cur_time; | |
fabf2986 | 186 | } else { |
554c0a3a HG |
187 | psecuritypriv->last_mic_err_time = jiffies; |
188 | } | |
189 | } | |
190 | ||
6a9b5dd1 | 191 | if (bgroup) { |
554c0a3a | 192 | key_type |= NL80211_KEYTYPE_GROUP; |
fabf2986 | 193 | } else { |
554c0a3a HG |
194 | key_type |= NL80211_KEYTYPE_PAIRWISE; |
195 | } | |
196 | ||
c77761d6 | 197 | cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[0], key_type, -1, |
554c0a3a HG |
198 | NULL, GFP_ATOMIC); |
199 | ||
200 | memset(&ev, 0x00, sizeof(ev)); | |
6a9b5dd1 | 201 | if (bgroup) { |
65ae78c2 | 202 | ev.flags |= IW_MICFAILURE_GROUP; |
fabf2986 | 203 | } else { |
65ae78c2 | 204 | ev.flags |= IW_MICFAILURE_PAIRWISE; |
554c0a3a HG |
205 | } |
206 | ||
207 | ev.src_addr.sa_family = ARPHRD_ETHER; | |
c77761d6 | 208 | memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN); |
554c0a3a HG |
209 | |
210 | memset(&wrqu, 0x00, sizeof(wrqu)); | |
211 | wrqu.data.length = sizeof(ev); | |
212 | } | |
213 | ||
214 | #ifdef CONFIG_AUTO_AP_MODE | |
215 | static void rtw_os_ksocket_send(struct adapter *padapter, union recv_frame *precv_frame) | |
216 | { | |
217 | _pkt *skb = precv_frame->u.hdr.pkt; | |
218 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; | |
219 | struct sta_info *psta = precv_frame->u.hdr.psta; | |
220 | ||
221 | DBG_871X("eth rx: got eth_type = 0x%x\n", pattrib->eth_type); | |
222 | ||
c77761d6 | 223 | if (psta && psta->isrc && psta->pid > 0) { |
554c0a3a HG |
224 | u16 rx_pid; |
225 | ||
226 | rx_pid = *(u16*)(skb->data+ETH_HLEN); | |
227 | ||
228 | DBG_871X("eth rx(pid = 0x%x): sta("MAC_FMT") pid = 0x%x\n", | |
229 | rx_pid, MAC_ARG(psta->hwaddr), psta->pid); | |
230 | ||
6a9b5dd1 | 231 | if (rx_pid == psta->pid) { |
554c0a3a HG |
232 | int i; |
233 | u16 len = *(u16*)(skb->data+ETH_HLEN+2); | |
554c0a3a HG |
234 | DBG_871X("eth, RC: len = 0x%x\n", len); |
235 | ||
c77761d6 | 236 | for (i = 0; i < len; i++) |
554c0a3a | 237 | DBG_871X("0x%x\n", *(skb->data+ETH_HLEN+4+i)); |
554c0a3a HG |
238 | |
239 | DBG_871X("eth, RC-end\n"); | |
240 | } | |
241 | ||
242 | } | |
243 | ||
244 | } | |
245 | #endif /* CONFIG_AUTO_AP_MODE */ | |
246 | ||
247 | int rtw_recv_indicatepkt(struct adapter *padapter, union recv_frame *precv_frame) | |
248 | { | |
249 | struct recv_priv *precvpriv; | |
250 | struct __queue *pfree_recv_queue; | |
251 | _pkt *skb; | |
252 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; | |
253 | ||
254 | DBG_COUNTER(padapter->rx_logs.os_indicate); | |
255 | ||
256 | precvpriv = &(padapter->recvpriv); | |
257 | pfree_recv_queue = &(precvpriv->free_recv_queue); | |
258 | ||
259 | skb = precv_frame->u.hdr.pkt; | |
6a9b5dd1 | 260 | if (skb == NULL) { |
554c0a3a HG |
261 | RT_TRACE(_module_recv_osdep_c_, _drv_err_, ("rtw_recv_indicatepkt():skb == NULL something wrong!!!!\n")); |
262 | goto _recv_indicatepkt_drop; | |
263 | } | |
264 | ||
265 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():skb != NULL !!!\n")); | |
266 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("rtw_recv_indicatepkt():precv_frame->u.hdr.rx_head =%p precv_frame->hdr.rx_data =%p\n", precv_frame->u.hdr.rx_head, precv_frame->u.hdr.rx_data)); | |
267 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("precv_frame->hdr.rx_tail =%p precv_frame->u.hdr.rx_end =%p precv_frame->hdr.len =%d\n", precv_frame->u.hdr.rx_tail, precv_frame->u.hdr.rx_end, precv_frame->u.hdr.len)); | |
268 | ||
269 | skb->data = precv_frame->u.hdr.rx_data; | |
270 | ||
271 | skb_set_tail_pointer(skb, precv_frame->u.hdr.len); | |
272 | ||
273 | skb->len = precv_frame->u.hdr.len; | |
274 | ||
275 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n", skb->head, skb->data, skb_tail_pointer(skb), skb_end_pointer(skb), skb->len)); | |
276 | ||
277 | #ifdef CONFIG_AUTO_AP_MODE | |
6a9b5dd1 | 278 | if (0x8899 == pattrib->eth_type) { |
554c0a3a HG |
279 | rtw_os_ksocket_send(padapter, precv_frame); |
280 | ||
281 | /* goto _recv_indicatepkt_drop; */ | |
282 | } | |
283 | #endif /* CONFIG_AUTO_AP_MODE */ | |
284 | ||
285 | rtw_os_recv_indicate_pkt(padapter, skb, pattrib); | |
286 | ||
b6b2a53c VK |
287 | /* pointers to NULL before rtw_free_recvframe() */ |
288 | precv_frame->u.hdr.pkt = NULL; | |
554c0a3a HG |
289 | |
290 | rtw_free_recvframe(precv_frame, pfree_recv_queue); | |
291 | ||
292 | RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("\n rtw_recv_indicatepkt :after rtw_os_recv_indicate_pkt!!!!\n")); | |
293 | ||
65ae78c2 | 294 | return _SUCCESS; |
554c0a3a HG |
295 | |
296 | _recv_indicatepkt_drop: | |
297 | ||
067be572 VK |
298 | /* enqueue back to free_recv_queue */ |
299 | rtw_free_recvframe(precv_frame, pfree_recv_queue); | |
554c0a3a | 300 | |
067be572 VK |
301 | DBG_COUNTER(padapter->rx_logs.os_indicate_err); |
302 | return _FAIL; | |
554c0a3a HG |
303 | } |
304 | ||
305 | void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl) | |
306 | { | |
e8b1844a KC |
307 | timer_setup(&preorder_ctrl->reordering_ctrl_timer, |
308 | rtw_reordering_ctrl_timeout_handler, 0); | |
554c0a3a HG |
309 | |
310 | } |