xref: /linux/drivers/staging/rtl8723bs/os_dep/recv_linux.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #include <drv_types.h>
8 #include <linux/jiffies.h>
9 #include <net/cfg80211.h>
10 #include <linux/unaligned.h>
11 
rtw_os_free_recvframe(union recv_frame * precvframe)12 void rtw_os_free_recvframe(union recv_frame *precvframe)
13 {
14 	if (precvframe->u.hdr.pkt) {
15 		dev_kfree_skb_any(precvframe->u.hdr.pkt);/* free skb by driver */
16 
17 		precvframe->u.hdr.pkt = NULL;
18 	}
19 }
20 
21 /* alloc os related resource in union recv_frame */
rtw_os_recv_resource_alloc(struct adapter * padapter,union recv_frame * precvframe)22 void rtw_os_recv_resource_alloc(struct adapter *padapter, union recv_frame *precvframe)
23 {
24 	precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
25 }
26 
27 /* free os related resource in union recv_frame */
rtw_os_recv_resource_free(struct recv_priv * precvpriv)28 void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
29 {
30 	signed int i;
31 	union recv_frame *precvframe;
32 
33 	precvframe = (union recv_frame *) precvpriv->precv_frame_buf;
34 
35 	for (i = 0; i < NR_RECVFRAME; i++) {
36 		if (precvframe->u.hdr.pkt) {
37 			/* free skb by driver */
38 			dev_kfree_skb_any(precvframe->u.hdr.pkt);
39 			precvframe->u.hdr.pkt = NULL;
40 		}
41 		precvframe++;
42 	}
43 }
44 
45 /* free os related resource in struct recv_buf */
rtw_os_recvbuf_resource_free(struct adapter * padapter,struct recv_buf * precvbuf)46 void rtw_os_recvbuf_resource_free(struct adapter *padapter, struct recv_buf *precvbuf)
47 {
48 	if (precvbuf->pskb)
49 		dev_kfree_skb_any(precvbuf->pskb);
50 }
51 
rtw_os_alloc_msdu_pkt(union recv_frame * prframe,u16 nSubframe_Length,u8 * pdata)52 struct sk_buff *rtw_os_alloc_msdu_pkt(union recv_frame *prframe, u16 nSubframe_Length, u8 *pdata)
53 {
54 	u16 eth_type;
55 	struct sk_buff *sub_skb;
56 	struct rx_pkt_attrib *pattrib;
57 
58 	pattrib = &prframe->u.hdr.attrib;
59 
60 	sub_skb = rtw_skb_alloc(nSubframe_Length + 12);
61 	if (!sub_skb)
62 		return NULL;
63 
64 	skb_reserve(sub_skb, 12);
65 	skb_put_data(sub_skb, (pdata + ETH_HLEN), nSubframe_Length);
66 
67 	eth_type = get_unaligned_be16(&sub_skb->data[6]);
68 
69 	if (sub_skb->len >= 8 &&
70 		((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
71 		  eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
72 		 !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
73 		/*
74 		 * remove RFC1042 or Bridge-Tunnel encapsulation and replace
75 		 * EtherType
76 		 */
77 		skb_pull(sub_skb, SNAP_SIZE);
78 		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
79 		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
80 	} else {
81 		__be16 len;
82 		/* Leave Ethernet header part of hdr and full payload */
83 		len = htons(sub_skb->len);
84 		memcpy(skb_push(sub_skb, 2), &len, 2);
85 		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN);
86 		memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN);
87 	}
88 
89 	return sub_skb;
90 }
91 
rtw_os_recv_indicate_pkt(struct adapter * padapter,struct sk_buff * pkt,struct rx_pkt_attrib * pattrib)92 void rtw_os_recv_indicate_pkt(struct adapter *padapter, struct sk_buff *pkt, struct rx_pkt_attrib *pattrib)
93 {
94 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
95 
96 	/* Indicate the packets to upper layer */
97 	if (pkt) {
98 		if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
99 			struct sk_buff *pskb2 = NULL;
100 			struct sta_info *psta = NULL;
101 			struct sta_priv *pstapriv = &padapter->stapriv;
102 			int bmcast = is_multicast_ether_addr(pattrib->dst);
103 
104 			if (memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)) {
105 				if (bmcast) {
106 					psta = rtw_get_bcmc_stainfo(padapter);
107 					pskb2 = skb_clone(pkt, GFP_ATOMIC);
108 				} else {
109 					psta = rtw_get_stainfo(pstapriv, pattrib->dst);
110 				}
111 
112 				if (psta) {
113 					struct net_device *pnetdev = (struct net_device *)padapter->pnetdev;
114 					/* skb->ip_summed = CHECKSUM_NONE; */
115 					pkt->dev = pnetdev;
116 					skb_set_queue_mapping(pkt, rtw_recv_select_queue(pkt));
117 
118 					_rtw_xmit_entry(pkt, pnetdev);
119 
120 					if (bmcast && pskb2)
121 						pkt = pskb2;
122 					else
123 						return;
124 				}
125 			} else {
126 				/*  to APself */
127 			}
128 		}
129 
130 		pkt->protocol = eth_type_trans(pkt, padapter->pnetdev);
131 		pkt->dev = padapter->pnetdev;
132 
133 		pkt->ip_summed = CHECKSUM_NONE;
134 
135 		rtw_netif_rx(padapter->pnetdev, pkt);
136 	}
137 }
138 
rtw_handle_tkip_mic_err(struct adapter * padapter,u8 bgroup)139 void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
140 {
141 	enum nl80211_key_type key_type = 0;
142 	union iwreq_data wrqu;
143 	struct iw_michaelmicfailure    ev;
144 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
145 	struct security_priv *psecuritypriv = &padapter->securitypriv;
146 	unsigned long cur_time = 0;
147 
148 	if (psecuritypriv->last_mic_err_time == 0) {
149 		psecuritypriv->last_mic_err_time = jiffies;
150 	} else {
151 		cur_time = jiffies;
152 
153 		if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) {
154 			psecuritypriv->btkip_countermeasure = true;
155 			psecuritypriv->last_mic_err_time = 0;
156 			psecuritypriv->btkip_countermeasure_time = cur_time;
157 		} else {
158 			psecuritypriv->last_mic_err_time = jiffies;
159 		}
160 	}
161 
162 	if (bgroup)
163 		key_type |= NL80211_KEYTYPE_GROUP;
164 	else
165 		key_type |= NL80211_KEYTYPE_PAIRWISE;
166 
167 	cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[0], key_type, -1,
168 		NULL, GFP_ATOMIC);
169 
170 	memset(&ev, 0x00, sizeof(ev));
171 	if (bgroup)
172 		ev.flags |= IW_MICFAILURE_GROUP;
173 	else
174 		ev.flags |= IW_MICFAILURE_PAIRWISE;
175 
176 	ev.src_addr.sa_family = ARPHRD_ETHER;
177 	memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN);
178 
179 	memset(&wrqu, 0x00, sizeof(wrqu));
180 	wrqu.data.length = sizeof(ev);
181 }
182 
rtw_recv_indicatepkt(struct adapter * padapter,union recv_frame * precv_frame)183 int rtw_recv_indicatepkt(struct adapter *padapter, union recv_frame *precv_frame)
184 {
185 	struct recv_priv *precvpriv;
186 	struct __queue	*pfree_recv_queue;
187 	struct sk_buff *skb;
188 	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
189 
190 	precvpriv = &(padapter->recvpriv);
191 	pfree_recv_queue = &(precvpriv->free_recv_queue);
192 
193 	skb = precv_frame->u.hdr.pkt;
194 	if (!skb)
195 		goto _recv_indicatepkt_drop;
196 
197 	skb->data = precv_frame->u.hdr.rx_data;
198 
199 	skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
200 
201 	skb->len = precv_frame->u.hdr.len;
202 
203 	rtw_os_recv_indicate_pkt(padapter, skb, pattrib);
204 
205 	/* pointers to NULL before rtw_free_recvframe() */
206 	precv_frame->u.hdr.pkt = NULL;
207 
208 	rtw_free_recvframe(precv_frame, pfree_recv_queue);
209 
210 	return _SUCCESS;
211 
212 _recv_indicatepkt_drop:
213 
214 	/* enqueue back to free_recv_queue */
215 	rtw_free_recvframe(precv_frame, pfree_recv_queue);
216 
217 	return _FAIL;
218 }
219 
rtw_init_recv_timer(struct recv_reorder_ctrl * preorder_ctrl)220 void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
221 {
222 	timer_setup(&preorder_ctrl->reordering_ctrl_timer,
223 		    rtw_reordering_ctrl_timeout_handler, 0);
224 
225 }
226