12865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/****************************************************************************** 22865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * recv_linux.c 32865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 42865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. 52865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Linux device driver for RTL8192SU 62865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 72865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is free software; you can redistribute it and/or modify it 82865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * under the terms of version 2 of the GNU General Public License as 92865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * published by the Free Software Foundation. 102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT 122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * more details. 152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * You should have received a copy of the GNU General Public License along with 172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * this program; if not, write to the Free Software Foundation, Inc., 182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Modifications for inclusion into the Linux staging tree are 212865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Copyright(c) 2010 Larry Finger. All rights reserved. 222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Contact information: 242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * WLAN FAE <wlanfae@realtek.com>. 252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * Larry Finger <Larry.Finger@lwfinger.net> 262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * 272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ******************************************************************************/ 282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#define _RECV_OSDEP_C_ 302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 31359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/usb.h> 32359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar 332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_service.h" 342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "drv_types.h" 352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "wifi.h" 362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "recv_osdep.h" 372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "osdep_intf.h" 38359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include "ethernet.h" 39359140aaea5bc3123356d46d0daa9dac8cfb12bcAli Bahar#include <linux/if_arp.h> 402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger#include "usb_ops.h" 412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*init os related resource in struct recv_priv*/ 432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*alloc os related resource in union recv_frame*/ 442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_os_recv_resource_alloc(struct _adapter *padapter, 452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger union recv_frame *precvframe) 462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL; 482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _SUCCESS; 492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*alloc os related resource in struct recv_buf*/ 522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_os_recvbuf_resource_alloc(struct _adapter *padapter, 532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_buf *precvbuf) 542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger int res = _SUCCESS; 562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->irp_pending = false; 5868e9b249565ef2786eee2b4676c8f04c8154215dAli Bahar precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL); 592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->purb == NULL) 602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger res = _FAIL; 612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pskb = NULL; 622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = false; 632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pallocated_buf = NULL; 642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pbuf = NULL; 652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pdata = NULL; 662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->phead = NULL; 672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->ptail = NULL; 682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pend = NULL; 692865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->transfer_len = 0; 702865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->len = 0; 712865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return res; 722865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 732865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 742865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger/*free os related resource in struct recv_buf*/ 752865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerint r8712_os_recvbuf_resource_free(struct _adapter *padapter, 762865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_buf *precvbuf) 772865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 782865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->pskb) 792865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger dev_kfree_skb_any(precvbuf->pskb); 802865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->purb) { 812865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_kill_urb(precvbuf->purb); 822865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger usb_free_urb(precvbuf->purb); 832865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger } 842865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return _SUCCESS; 852865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 862865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 872865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup) 882865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 892865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger union iwreq_data wrqu; 902865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct iw_michaelmicfailure ev; 912865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 922865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 932865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memset(&ev, 0x00, sizeof(ev)); 942865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (bgroup) 952865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ev.flags |= IW_MICFAILURE_GROUP; 962865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 972865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ev.flags |= IW_MICFAILURE_PAIRWISE; 982865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger ev.src_addr.sa_family = ARPHRD_ETHER; 992865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memcpy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0], ETH_ALEN); 1002865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger memset(&wrqu, 0x00, sizeof(wrqu)); 1012865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger wrqu.data.length = sizeof(ev); 1022865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger wireless_send_event(padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, 1032865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (char *)&ev); 1042865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1052865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1062865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_recv_indicatepkt(struct _adapter *padapter, 1072865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger union recv_frame *precv_frame) 1082865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1092865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_priv *precvpriv; 1102865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct __queue *pfree_recv_queue; 1112865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _pkt *skb; 1122865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; 1132865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1142865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvpriv = &(padapter->recvpriv); 1152865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger pfree_recv_queue = &(precvpriv->free_recv_queue); 1162865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb = precv_frame->u.hdr.pkt; 1172865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (skb == NULL) 1182865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger goto _recv_indicatepkt_drop; 1192865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->data = precv_frame->u.hdr.rx_data; 1202865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->len = precv_frame->u.hdr.len; 121abf02cfc179bb4bd30d05f582d61b3b8f429b813Eric Dumazet skb_set_tail_pointer(skb, skb->len); 1222865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) 1232865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->ip_summed = CHECKSUM_UNNECESSARY; 1242865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger else 1252865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->ip_summed = CHECKSUM_NONE; 1262865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->dev = padapter->pnetdev; 1272865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger skb->protocol = eth_type_trans(skb, padapter->pnetdev); 1282865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger netif_rx(skb); 1292865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precv_frame->u.hdr.pkt = NULL; /* pointers to NULL before 1302865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger * r8712_free_recvframe() */ 1312865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_recvframe(precv_frame, pfree_recv_queue); 1322865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger return; 1332865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger_recv_indicatepkt_drop: 1342865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*enqueue back to free_recv_queue*/ 1352865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precv_frame) 1362865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_free_recvframe(precv_frame, pfree_recv_queue); 1372865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvpriv->rx_drop++; 1382865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1392865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1402865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_os_read_port(struct _adapter *padapter, struct recv_buf *precvbuf) 1412865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1422865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_priv *precvpriv = &padapter->recvpriv; 1432865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1442865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->ref_cnt--; 1452865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger /*free skb in recv_buf*/ 1462865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger dev_kfree_skb_any(precvbuf->pskb); 1472865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->pskb = NULL; 1482865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger precvbuf->reuse = false; 1492865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger if (precvbuf->irp_pending == false) 1502865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_read_port(padapter, precvpriv->ff_hwaddr, 0, 1512865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (unsigned char *)precvbuf); 1522865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1532865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1542865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingerstatic void _r8712_reordering_ctrl_timeout_handler (void *FunctionContext) 1552865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1562865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct recv_reorder_ctrl *preorder_ctrl = 1572865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger (struct recv_reorder_ctrl *)FunctionContext; 1582865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1592865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger r8712_reordering_ctrl_timeout_handler(preorder_ctrl); 1602865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 1612865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1622865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Fingervoid r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl) 1632865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger{ 1642865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger struct _adapter *padapter = preorder_ctrl->padapter; 1652865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger 1662865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, 1672865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger _r8712_reordering_ctrl_timeout_handler, preorder_ctrl); 1682865d42c78a9121caad52cb02d1fbb7f5cdbc4efLarry Finger} 169