29 #define _RTL8712_RECV_C_
31 #include <linux/if_ether.h>
43 static u8 bridge_tunnel_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
46 static u8 rfc1042_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
48 static void recv_tasklet(
void *
priv);
71 _init_listhead(&precvbuf->
list);
78 list_insert_tail(&precvbuf->
list,
84 (
void(*)(
unsigned long))recv_tasklet,
85 (
unsigned long)padapter);
93 pskb->
dev = padapter->pnetdev;
132 if (precvbuf->
pbuf) {
142 struct __queue *pfree_recv_queue)
148 if (precvframe->
u.
hdr.pkt) {
153 list_delete(&(precvframe->
u.
hdr.list));
154 list_insert_tail(&(precvframe->
u.
hdr.list),
155 get_list_head(pfree_recv_queue));
156 if (padapter !=
NULL) {
160 spin_unlock_irqrestore(&pfree_recv_queue->
lock, irqL);
164 static void update_recvframe_attrib_from_recvstat(
struct rx_pkt_attrib *pattrib,
172 drvinfo_sz = drvinfo_sz<<3;
199 pphy_stat = (
struct phy_stat *)(prxstat+1);
200 pphy_info = (
u32 *)prxstat+1;
213 struct __queue *pfree_recv_queue;
215 pfree_recv_queue = &adapter->
recvpriv.free_recv_queue;
216 phead = get_list_head(defrag_q);
219 list_delete(&prframe->
u.
list);
220 pfhdr = &prframe->
u.
hdr;
222 if (curfragnum != pfhdr->
attrib.frag_num) {
230 plist = get_list_head(defrag_q);
232 data = get_recvframe_data(prframe);
233 while (end_of_queue_search(phead, plist) ==
false) {
235 pnfhdr = &pnextrframe->
u.
hdr;
237 if (curfragnum != pnfhdr->
attrib.frag_num) {
247 wlanhdr_offset = pnfhdr->
attrib.hdrlen + pnfhdr->
attrib.iv_len;
248 recvframe_pull(pnextrframe, wlanhdr_offset);
251 recvframe_pull_tail(prframe, pfhdr->
attrib.icv_len);
253 recvframe_put(prframe, pnfhdr->
len);
274 struct __queue *pfree_recv_queue, *pdefrag_q;
277 pfhdr = &precv_frame->
u.
hdr;
278 pfree_recv_queue = &padapter->
recvpriv.free_recv_queue;
280 ismfrag = pfhdr->
attrib.mfrag;
281 fragnum = pfhdr->
attrib.frag_num;
282 psta_addr = pfhdr->
attrib.ta;
289 if ((ismfrag == 0) && (fragnum == 0))
290 prtnframe = precv_frame;
294 if (pdefrag_q !=
NULL) {
297 if (_queue_empty(pdefrag_q) ==
false) {
304 phead = get_list_head(pdefrag_q);
305 list_insert_tail(&pfhdr->
list, phead);
315 if ((ismfrag == 0) && (fragnum != 0)) {
318 if (pdefrag_q !=
NULL) {
319 phead = get_list_head(pdefrag_q);
320 list_insert_tail(&pfhdr->
list, phead);
322 precv_frame = recvframe_defrag(padapter, pdefrag_q);
323 prtnframe = precv_frame;
331 if ((prtnframe !=
NULL) && (prtnframe->
u.
hdr.attrib.privacy)) {
343 int a_len, padding_len;
344 u16 eth_type, nSubframe_Length;
346 unsigned char *data_ptr, *
pdata;
354 pattrib = &prframe->
u.
hdr.attrib;
355 recvframe_pull(prframe, prframe->
u.
hdr.attrib.hdrlen);
356 if (prframe->
u.
hdr.attrib.iv_len > 0)
357 recvframe_pull(prframe, prframe->
u.
hdr.attrib.iv_len);
358 a_len = prframe->
u.
hdr.len;
359 pdata = prframe->
u.
hdr.rx_data;
362 nSubframe_Length = *((
u16 *)(pdata + 12));
364 nSubframe_Length = (nSubframe_Length >> 8) +
365 (nSubframe_Length << 8);
368 " nSubframe_Length is: %d\n",
369 a_len, nSubframe_Length);
376 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
379 skb_reserve(sub_skb, 12);
380 data_ptr = (
u8 *)
skb_put(sub_skb, nSubframe_Length);
381 memcpy(data_ptr, pdata, nSubframe_Length);
382 subframes[nr_subframes++] = sub_skb;
385 " many Subframes! Packets dropped!\n");
388 pdata += nSubframe_Length;
389 a_len -= nSubframe_Length;
391 padding_len = 4 - ((nSubframe_Length +
ETH_HLEN) & 3);
392 if (padding_len == 4)
394 if (a_len < padding_len)
396 pdata += padding_len;
397 a_len -= padding_len;
401 sub_skb = subframes[
i];
403 eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
404 if (sub_skb->len >= 8 &&
418 len =
htons(sub_skb->len);
429 sub_skb->dev = padapter->
pnetdev;
439 prframe->
u.
hdr.len = 0;
452 poffset = (
u8 *)prxcmdbuf;
453 voffset = *(
uint *)poffset;
457 drvinfo_sz = drvinfo_sz << 3;
460 voffset = *(
uint *)poffset;
465 poffset += (cmd_len + 8);
490 else if (
SN_LESS(wend, seq_num)) {
491 if (seq_num >= (wsize - 1))
506 struct __queue *ppending_recvframe_queue =
510 phead = get_list_head(ppending_recvframe_queue);
512 while (end_of_queue_search(phead, plist) ==
false) {
514 pnextattrib = &pnextrframe->
u.
hdr.attrib;
522 list_delete(&(prframe->
u.
hdr.list));
523 list_insert_tail(&(prframe->
u.
hdr.list), plist);
534 int bPktInBuf =
false;
536 struct __queue *ppending_recvframe_queue =
539 phead = get_list_head(ppending_recvframe_queue);
542 if (bforced ==
true) {
543 if (is_list_empty(phead))
547 pattrib = &prframe->
u.
hdr.attrib;
553 while (!is_list_empty(phead)) {
555 pattrib = &prframe->
u.
hdr.attrib;
558 list_delete(&(prframe->
u.
hdr.list));
564 if (!pattrib->
amsdu) {
571 }
else if (pattrib->
amsdu == 1) {
572 if (amsdu_to_msdu(padapter, prframe) !=
587 static int recv_indicatepkt_reorder(
struct _adapter *padapter,
593 struct __queue *ppending_recvframe_queue =
596 if (!pattrib->
amsdu) {
599 if (pattrib->
qos != 1) {
610 if (!check_indicate_seq(preorder_ctrl, pattrib->
seq_num))
613 if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
630 spin_unlock_irqrestore(&ppending_recvframe_queue->
lock, irql);
632 spin_unlock_irqrestore(&ppending_recvframe_queue->
lock, irql);
637 spin_unlock_irqrestore(&ppending_recvframe_queue->
lock, irql);
647 struct __queue *ppending_recvframe_queue =
654 spin_unlock_irqrestore(&ppending_recvframe_queue->
lock, irql);
657 static int r8712_process_recv_indicatepkts(
struct _adapter *padapter,
665 if (recv_indicatepkt_reorder(padapter, prframe) !=
_SUCCESS) {
685 static u8 query_rx_pwr_percentage(
s8 antpower)
687 if ((antpower <= -100) || (antpower >= 20))
689 else if (antpower >= 0)
692 return 100 + antpower;
718 if (cur_sig >= 51 && cur_sig <= 100)
720 else if (cur_sig >= 41 && cur_sig <= 50)
721 ret_sig = 80 + ((cur_sig - 40) * 2);
722 else if (cur_sig >= 31 && cur_sig <= 40)
723 ret_sig = 66 + (cur_sig - 30);
724 else if (cur_sig >= 21 && cur_sig <= 30)
725 ret_sig = 54 + (cur_sig - 20);
726 else if (cur_sig >= 10 && cur_sig <= 20)
727 ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
728 else if (cur_sig >= 5 && cur_sig <= 9)
729 ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
730 else if (cur_sig >= 1 && cur_sig <= 4)
731 ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
737 static s32 translate2dbm(
struct _adapter *padapter,
u8 signal_strength_idx)
741 signal_power = (
s32)((signal_strength_idx + 1) >> 1);
746 static void query_rx_phy_status(
struct _adapter *padapter,
749 u8 i, max_spatial_stream, evm;
752 u8 *pphy_head = (
u8 *)(prxstat + 1);
753 s8 rx_pwr[4], rx_pwr_all;
755 u32 rssi, total_rssi = 0;
756 u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0;
761 bcck_rate = (prframe->
u.
hdr.attrib.mcs_rate <= 3 ? 1 : 0);
773 report = report >> 6;
799 report = report >> 5;
819 pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
826 if (pwdb_all > 34 && pwdb_all <= 42)
828 else if (pwdb_all > 26 && pwdb_all <= 34)
830 else if (pwdb_all > 14 && pwdb_all <= 26)
832 else if (pwdb_all > 4 && pwdb_all <= 14)
841 if (pcck_buf->
sq_rpt > 64)
843 else if (pcck_buf->
sq_rpt < 20)
846 sq = ((64-sq) * 100) / 44;
848 prframe->
u.
hdr.attrib.signal_qual = sq;
849 prframe->
u.
hdr.attrib.rx_mimo_signal_qual[0] = sq;
850 prframe->
u.
hdr.attrib.rx_mimo_signal_qual[1] = -1;
859 rssi = query_rx_pwr_percentage(rx_pwr[i]);
866 pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
870 if (prframe->
u.
hdr.attrib.htc &&
871 prframe->
u.
hdr.attrib.mcs_rate >= 20 &&
872 prframe->
u.
hdr.attrib.mcs_rate <= 27) {
874 max_spatial_stream = 2;
877 max_spatial_stream = 1;
879 for (i = 0; i < max_spatial_stream; i++) {
880 evm = evm_db2percentage((pphy_head
882 prframe->
u.
hdr.attrib.signal_qual =
884 prframe->
u.
hdr.attrib.rx_mimo_signal_qual[
i] =
893 prframe->
u.
hdr.attrib.signal_strength =
897 prframe->
u.
hdr.attrib.signal_strength =
903 static void process_link_qual(
struct _adapter *padapter,
906 u32 last_evm = 0, tmpVal;
909 if (prframe ==
NULL || padapter ==
NULL)
911 pattrib = &prframe->
u.
hdr.attrib;
916 if (padapter->
recvpriv.signal_qual_data.total_num++ >=
918 padapter->
recvpriv.signal_qual_data.total_num =
920 last_evm = padapter->
recvpriv.signal_qual_data.elements
921 [padapter->
recvpriv.signal_qual_data.index];
922 padapter->
recvpriv.signal_qual_data.total_val -=
925 padapter->
recvpriv.signal_qual_data.total_val +=
927 padapter->
recvpriv.signal_qual_data.elements[padapter->
928 recvpriv.signal_qual_data.index++] =
930 if (padapter->
recvpriv.signal_qual_data.index >=
932 padapter->
recvpriv.signal_qual_data.index = 0;
935 tmpVal = padapter->
recvpriv.signal_qual_data.total_val /
936 padapter->
recvpriv.signal_qual_data.total_num;
943 u32 last_rssi, tmp_val;
946 if (padapter->
recvpriv.signal_strength_data.total_num++ >=
948 padapter->
recvpriv.signal_strength_data.total_num =
950 last_rssi = padapter->
recvpriv.signal_strength_data.elements
951 [padapter->
recvpriv.signal_strength_data.index];
952 padapter->
recvpriv.signal_strength_data.total_val -= last_rssi;
954 padapter->
recvpriv.signal_strength_data.total_val +=
957 signal_strength_data.index++] =
959 if (padapter->
recvpriv.signal_strength_data.index >=
961 padapter->
recvpriv.signal_strength_data.index = 0;
962 tmp_val = padapter->
recvpriv.signal_strength_data.total_val /
963 padapter->
recvpriv.signal_strength_data.total_num;
964 padapter->
recvpriv.rssi = (
s8)translate2dbm(padapter, (
u8)tmp_val);
967 static void process_phy_info(
struct _adapter *padapter,
970 query_rx_phy_status(padapter, prframe);
971 process_rssi(padapter, prframe);
972 process_link_qual(padapter, prframe);
980 struct __queue *pfree_recv_queue = &padapter->
recvpriv.free_recv_queue;
984 orig_prframe = prframe;
985 pattrib = &prframe->
u.
hdr.attrib;
988 padapter->
mppriv.rx_crcerrpktcount++;
990 padapter->
mppriv.rx_pktcount++;
994 goto _exit_recv_func;
1002 goto _exit_recv_func;
1004 process_phy_info(padapter, prframe);
1006 if (prframe ==
NULL) {
1008 goto _exit_recv_func;
1011 if (prframe ==
NULL)
1012 goto _exit_recv_func;
1014 if (prframe ==
NULL) {
1016 goto _exit_recv_func;
1018 retval = r8712_process_recv_indicatepkts(padapter, prframe);
1021 goto _exit_recv_func;
1027 static int recvbuf2recvframe(
struct _adapter *padapter,
struct sk_buff *pskb)
1029 u8 *pbuf, shift_sz = 0;
1034 u16 pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz;
1035 struct __queue *pfree_recv_queue;
1045 transfer_len = pskb->
len;
1049 if (transfer_len < pkt_len) {
1063 drvinfo_sz = drvinfo_sz<<3;
1065 goto _exit_recvbuf2recvframe;
1070 if (precvframe ==
NULL)
1071 goto _exit_recvbuf2recvframe;
1072 _init_listhead(&precvframe->
u.
hdr.list);
1074 precvframe->
u.
hdr.len = 0;
1076 pkt_offset = (
u16)_RND128(tmp_len);
1079 if ((mf == 1) && (frag == 0))
1086 pkt_copy = netdev_alloc_skb(padapter->
pnetdev, alloc_sz);
1088 pkt_copy->dev = padapter->
pnetdev;
1089 precvframe->
u.
hdr.pkt = pkt_copy;
1090 skb_reserve(pkt_copy, 4 - ((
addr_t)(pkt_copy->data)
1092 skb_reserve(pkt_copy, shift_sz);
1093 memcpy(pkt_copy->data, pbuf, tmp_len);
1094 precvframe->
u.
hdr.rx_head = precvframe->
u.
hdr.rx_data =
1095 precvframe->
u.
hdr.rx_tail = pkt_copy->data;
1096 precvframe->
u.
hdr.rx_end = pkt_copy->data + alloc_sz;
1099 if (!precvframe->
u.
hdr.pkt)
1101 precvframe->
u.
hdr.rx_head = pbuf;
1102 precvframe->
u.
hdr.rx_data = pbuf;
1103 precvframe->
u.
hdr.rx_tail = pbuf;
1104 precvframe->
u.
hdr.rx_end = pbuf + alloc_sz;
1106 recvframe_put(precvframe, tmp_len);
1107 recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
1111 update_recvframe_attrib_from_recvstat(&precvframe->
u.
hdr.attrib,
1114 transfer_len -= pkt_offset;
1119 }
while ((transfer_len > 0) && pkt_cnt > 0);
1120 _exit_recvbuf2recvframe:
1124 static void recv_tasklet(
void *
priv)
1131 recvbuf2recvframe(padapter, pskb);
1132 skb_reset_tail_pointer(pskb);
1134 if (!skb_cloned(pskb))