1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
14 ******************************************************************************/
15 #define _RTL8192CU_RECV_C_
16 #include <osdep_service.h>
17 #include <drv_types.h>
18 #include <recv_osdep.h>
19 #include <mlme_osdep.h>
21 #include <linux/if_ether.h>
24 #include <rtl8723a_hal.h>
26 int rtl8723au_init_recv_priv(struct rtw_adapter *padapter)
28 struct recv_priv *precvpriv = &padapter->recvpriv;
29 int i, size, res = _SUCCESS;
30 struct recv_buf *precvbuf;
31 unsigned long tmpaddr;
32 unsigned long alignment;
35 tasklet_init(&precvpriv->recv_tasklet,
36 (void(*)(unsigned long))rtl8723au_recv_tasklet,
37 (unsigned long)padapter);
39 precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
40 if (!precvpriv->int_in_urb)
41 DBG_8723A("alloc_urb for interrupt in endpoint fail !!!!\n");
42 precvpriv->int_in_buf = kzalloc(USB_INTR_CONTENT_LENGTH, GFP_KERNEL);
43 if (!precvpriv->int_in_buf)
44 DBG_8723A("alloc_mem for interrupt in endpoint fail !!!!\n");
46 size = NR_RECVBUFF * sizeof(struct recv_buf);
47 precvpriv->precv_buf = kzalloc(size, GFP_KERNEL);
48 if (!precvpriv->precv_buf) {
50 RT_TRACE(_module_rtl871x_recv_c_, _drv_err_,
51 "alloc recv_buf fail!\n");
55 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
57 for (i = 0; i < NR_RECVBUFF; i++) {
58 INIT_LIST_HEAD(&precvbuf->list);
60 precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
64 precvbuf->adapter = padapter;
69 skb_queue_head_init(&precvpriv->rx_skb_queue);
70 skb_queue_head_init(&precvpriv->free_recv_skb_queue);
72 for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
73 size = MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ;
74 pskb = __netdev_alloc_skb(padapter->pnetdev, size, GFP_KERNEL);
77 pskb->dev = padapter->pnetdev;
79 tmpaddr = (unsigned long)pskb->data;
80 alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
81 skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
83 skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
93 void rtl8723au_free_recv_priv(struct rtw_adapter *padapter)
96 struct recv_buf *precvbuf;
97 struct recv_priv *precvpriv = &padapter->recvpriv;
99 precvbuf = (struct recv_buf *)precvpriv->precv_buf;
101 for (i = 0; i < NR_RECVBUFF; i++) {
102 usb_free_urb(precvbuf->purb);
105 dev_kfree_skb_any(precvbuf->pskb);
110 kfree(precvpriv->precv_buf);
112 usb_free_urb(precvpriv->int_in_urb);
113 kfree(precvpriv->int_in_buf);
115 if (skb_queue_len(&precvpriv->rx_skb_queue))
116 DBG_8723A(KERN_WARNING "rx_skb_queue not empty\n");
118 skb_queue_purge(&precvpriv->rx_skb_queue);
120 if (skb_queue_len(&precvpriv->free_recv_skb_queue)) {
121 DBG_8723A(KERN_WARNING "free_recv_skb_queue not empty, %d\n",
122 skb_queue_len(&precvpriv->free_recv_skb_queue));
125 skb_queue_purge(&precvpriv->free_recv_skb_queue);
128 struct recv_stat_cpu {
137 void update_recvframe_attrib(struct recv_frame *precvframe,
138 struct recv_stat *prxstat)
140 struct rx_pkt_attrib *pattrib;
141 struct recv_stat_cpu report;
142 struct rxreport_8723a *prxreport;
144 report.rxdw0 = le32_to_cpu(prxstat->rxdw0);
145 report.rxdw1 = le32_to_cpu(prxstat->rxdw1);
146 report.rxdw2 = le32_to_cpu(prxstat->rxdw2);
147 report.rxdw3 = le32_to_cpu(prxstat->rxdw3);
148 report.rxdw4 = le32_to_cpu(prxstat->rxdw4);
149 report.rxdw5 = le32_to_cpu(prxstat->rxdw5);
151 prxreport = (struct rxreport_8723a *)&report;
153 pattrib = &precvframe->attrib;
154 memset(pattrib, 0, sizeof(struct rx_pkt_attrib));
156 /* update rx report to recv_frame attribute */
157 pattrib->pkt_len = (u16)prxreport->pktlen;
158 pattrib->drvinfo_sz = (u8)(prxreport->drvinfosize << 3);
159 pattrib->physt = (u8)prxreport->physt;
161 pattrib->crc_err = (u8)prxreport->crc32;
162 pattrib->icv_err = (u8)prxreport->icverr;
164 pattrib->bdecrypted = (u8)(prxreport->swdec ? 0 : 1);
165 pattrib->encrypt = (u8)prxreport->security;
167 pattrib->qos = (u8)prxreport->qos;
168 pattrib->priority = (u8)prxreport->tid;
170 pattrib->amsdu = (u8)prxreport->amsdu;
172 pattrib->seq_num = (u16)prxreport->seq;
173 pattrib->frag_num = (u8)prxreport->frag;
174 pattrib->mfrag = (u8)prxreport->mf;
175 pattrib->mdata = (u8)prxreport->md;
177 pattrib->mcs_rate = (u8)prxreport->rxmcs;
178 pattrib->rxht = (u8)prxreport->rxht;
181 void update_recvframe_phyinfo(struct recv_frame *precvframe,
182 struct phy_stat *pphy_status)
184 struct rtw_adapter *padapter = precvframe->adapter;
185 struct rx_pkt_attrib *pattrib = &precvframe->attrib;
186 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
187 struct phy_info *pPHYInfo = &pattrib->phy_info;
188 struct odm_packet_info pkt_info;
190 struct sta_priv *pstapriv;
191 struct sta_info *psta;
192 struct sk_buff *skb = precvframe->pkt;
193 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
194 bool matchbssid = false;
197 matchbssid = !ieee80211_is_ctl(hdr->frame_control) &&
198 !pattrib->icv_err && !pattrib->crc_err;
201 switch (hdr->frame_control &
202 cpu_to_le16(IEEE80211_FCTL_TODS |
203 IEEE80211_FCTL_FROMDS)) {
204 case cpu_to_le16(IEEE80211_FCTL_TODS):
207 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
219 matchbssid = ether_addr_equal(
220 get_bssid(&padapter->mlmepriv), bssid);
223 pkt_info.bPacketMatchBSSID = matchbssid;
225 da = ieee80211_get_DA(hdr);
226 pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID &&
227 (!memcmp(da, myid(&padapter->eeprompriv), ETH_ALEN));
229 pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID &&
230 ieee80211_is_beacon(hdr->frame_control);
232 pkt_info.StationID = 0xFF;
233 if (pkt_info.bPacketBeacon) {
234 if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == true)
235 sa = padapter->mlmepriv.cur_network.network.MacAddress;
238 sa = ieee80211_get_SA(hdr);
241 pstapriv = &padapter->stapriv;
242 psta = rtw_get_stainfo23a(pstapriv, sa);
244 pkt_info.StationID = psta->mac_id;
245 /* printk("%s ==> StationID(%d)\n", __func__, pkt_info.StationID); */
247 pkt_info.Rate = pattrib->mcs_rate;
249 ODM_PhyStatusQuery23a(&pHalData->odmpriv, pPHYInfo,
250 (u8 *)pphy_status, &pkt_info);
251 precvframe->psta = NULL;
252 if (pkt_info.bPacketMatchBSSID &&
253 (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)) {
255 precvframe->psta = psta;
256 rtl8723a_process_phy_info(padapter, precvframe);
258 } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
259 if (check_fwstate(&padapter->mlmepriv,
260 WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) ==
263 precvframe->psta = psta;
265 rtl8723a_process_phy_info(padapter, precvframe);