rtl8188eu: Flatten os_dep

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
This commit is contained in:
Larry Finger 2014-12-16 19:03:30 -06:00
parent b0c8a54865
commit 52f8d17ffc
18 changed files with 14750 additions and 26420 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,620 +0,0 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _MLME_OSDEP_C_
#include <drv_conf.h>
#include <osdep_service.h>
#include <drv_types.h>
#include <mlme_osdep.h>
#ifdef RTK_DMP_PLATFORM
void Linkup_workitem_callback(struct work_struct *work)
{
struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkup_workitem);
_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
_func_enter_;
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkup_workitem_callback\n"));
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKUP);
#else
kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKUP);
#endif
_func_exit_;
}
void Linkdown_workitem_callback(struct work_struct *work)
{
struct mlme_priv *pmlmepriv = container_of(work, struct mlme_priv, Linkdown_workitem);
_adapter *padapter = container_of(pmlmepriv, _adapter, mlmepriv);
_func_enter_;
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+ Linkdown_workitem_callback\n"));
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,12))
kobject_uevent(&padapter->pnetdev->dev.kobj, KOBJ_LINKDOWN);
#else
kobject_hotplug(&padapter->pnetdev->class_dev.kobj, KOBJ_LINKDOWN);
#endif
_func_exit_;
}
#endif
/*
void sitesurvey_ctrl_handler(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
_sitesurvey_ctrl_handler(adapter);
_set_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer, 3000);
}
*/
void rtw_join_timeout_handler (void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
_rtw_join_timeout_handler(adapter);
}
void _rtw_scan_timeout_handler (void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
rtw_scan_timeout_handler(adapter);
}
void _dynamic_check_timer_handlder (void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
/* remove for MP power tracking DM.
#if (MP_DRIVER == 1)
if (adapter->registrypriv.mp_mode == 1)
return;
#endif
*/
rtw_dynamic_check_timer_handlder(adapter);
_set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
}
#ifdef CONFIG_SET_SCAN_DENY_TIMER
void _rtw_set_scan_deny_timer_hdl(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
rtw_set_scan_deny_timer_hdl(adapter);
}
#endif
#ifdef CONFIG_DETECT_C2H_BY_POLLING
void _rtw_event_polling_timer_hdl(void *FunctionContext)
{
_adapter *adapter = (_adapter *)FunctionContext;
rtw_event_polling_timer_hdl(adapter);
_set_timer(&adapter->mlmepriv.event_polling_timer, 200);
}
#endif
void rtw_init_mlme_timer(_adapter *padapter)
{
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
_init_timer(&(pmlmepriv->assoc_timer), padapter->pnetdev, rtw_join_timeout_handler, padapter);
//_init_timer(&(pmlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer), padapter->pnetdev, sitesurvey_ctrl_handler, padapter);
_init_timer(&(pmlmepriv->scan_to_timer), padapter->pnetdev, _rtw_scan_timeout_handler, padapter);
_init_timer(&(pmlmepriv->dynamic_chk_timer), padapter->pnetdev, _dynamic_check_timer_handlder, padapter);
#ifdef CONFIG_SET_SCAN_DENY_TIMER
_init_timer(&(pmlmepriv->set_scan_deny_timer), padapter->pnetdev, _rtw_set_scan_deny_timer_hdl, padapter);
#endif
#ifdef CONFIG_DETECT_C2H_BY_POLLING
_init_timer(&(pmlmepriv->event_polling_timer), padapter->pnetdev, _rtw_event_polling_timer_hdl, padapter);
#endif
#ifdef RTK_DMP_PLATFORM
_init_workitem(&(pmlmepriv->Linkup_workitem), Linkup_workitem_callback, padapter);
_init_workitem(&(pmlmepriv->Linkdown_workitem), Linkdown_workitem_callback, padapter);
#endif
#if defined(CONFIG_CHECK_BT_HANG) && defined(CONFIG_BT_COEXIST)
if (padapter->HalFunc.hal_init_checkbthang_workqueue)
padapter->HalFunc.hal_init_checkbthang_workqueue(padapter);
#endif
}
extern void rtw_indicate_wx_assoc_event(_adapter *padapter);
extern void rtw_indicate_wx_disassoc_event(_adapter *padapter);
void rtw_os_indicate_connect(_adapter *adapter)
{
struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
_func_enter_;
#ifdef CONFIG_IOCTL_CFG80211
if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==_TRUE ) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE ) )
{
rtw_cfg80211_ibss_indicate_connect(adapter);
}
else
rtw_cfg80211_indicate_connect(adapter);
#endif //CONFIG_IOCTL_CFG80211
rtw_indicate_wx_assoc_event(adapter);
netif_carrier_on(adapter->pnetdev);
if(adapter->pid[2] !=0)
rtw_signal_process(adapter->pid[2], SIGALRM);
#ifdef RTK_DMP_PLATFORM
_set_workitem(&adapter->mlmepriv.Linkup_workitem);
#endif
_func_exit_;
}
extern void indicate_wx_scan_complete_event(_adapter *padapter);
void rtw_os_indicate_scan_done( _adapter *padapter, bool aborted)
{
#ifdef CONFIG_IOCTL_CFG80211
rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev), aborted);
#endif
indicate_wx_scan_complete_event(padapter);
}
static RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
void rtw_reset_securitypriv( _adapter *adapter )
{
u8 backupPMKIDIndex = 0;
u8 backupTKIPCountermeasure = 0x00;
u32 backupTKIPcountermeasure_time = 0;
// add for CONFIG_IEEE80211W, none 11w also can use
_irqL irqL;
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
_enter_critical_bh(&adapter->security_key_mutex, &irqL);
if(adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)//802.1x
{
// Added by Albert 2009/02/18
// We have to backup the PMK information for WiFi PMK Caching test item.
//
// Backup the btkip_countermeasure information.
// When the countermeasure is trigger, the driver have to disconnect with AP for 60 seconds.
_rtw_memset( &backupPMKIDList[ 0 ], 0x00, sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
_rtw_memcpy( &backupPMKIDList[ 0 ], &adapter->securitypriv.PMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
#ifdef CONFIG_IEEE80211W
//reset RX BIP packet number
pmlmeext->mgnt_80211w_IPN_rx = 0;
#endif //CONFIG_IEEE80211W
_rtw_memset((unsigned char *)&adapter->securitypriv, 0, sizeof (struct security_priv));
//_init_timer(&(adapter->securitypriv.tkip_timer),adapter->pnetdev, rtw_use_tkipkey_handler, adapter);
// Added by Albert 2009/02/18
// Restore the PMK information to securitypriv structure for the following connection.
_rtw_memcpy( &adapter->securitypriv.PMKIDList[ 0 ], &backupPMKIDList[ 0 ], sizeof( RT_PMKID_LIST ) * NUM_PMKID_CACHE );
adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
}
else //reset values in securitypriv
{
//if(adapter->mlmepriv.fw_state & WIFI_STATION_STATE)
//{
struct security_priv *psec_priv=&adapter->securitypriv;
psec_priv->dot11AuthAlgrthm =dot11AuthAlgrthm_Open; //open system
psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
psec_priv->dot11PrivacyKeyIndex = 0;
psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
psec_priv->dot118021XGrpKeyid = 1;
psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
//}
}
// add for CONFIG_IEEE80211W, none 11w also can use
_exit_critical_bh(&adapter->security_key_mutex, &irqL);
}
void rtw_os_indicate_disconnect( _adapter *adapter )
{
//RT_PMKID_LIST backupPMKIDList[ NUM_PMKID_CACHE ];
_func_enter_;
netif_carrier_off(adapter->pnetdev); // Do it first for tx broadcast pkt after disconnection issue!
#ifdef CONFIG_IOCTL_CFG80211
rtw_cfg80211_indicate_disconnect(adapter);
#endif //CONFIG_IOCTL_CFG80211
rtw_indicate_wx_disassoc_event(adapter);
#ifdef RTK_DMP_PLATFORM
_set_workitem(&adapter->mlmepriv.Linkdown_workitem);
#endif
//modify for CONFIG_IEEE80211W, none 11w also can use the same command
rtw_reset_securitypriv_cmd(adapter);
_func_exit_;
}
void rtw_report_sec_ie(_adapter *adapter,u8 authmode,u8 *sec_ie)
{
uint len;
u8 *buff,*p,i;
union iwreq_data wrqu;
_func_enter_;
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("+rtw_report_sec_ie, authmode=%d\n", authmode));
buff = NULL;
if(authmode==_WPA_IE_ID_)
{
RT_TRACE(_module_mlme_osdep_c_,_drv_info_,("rtw_report_sec_ie, authmode=%d\n", authmode));
buff = rtw_malloc(IW_CUSTOM_MAX);
_rtw_memset(buff,0,IW_CUSTOM_MAX);
p=buff;
p+=sprintf(p,"ASSOCINFO(ReqIEs=");
len = sec_ie[1]+2;
len = (len < IW_CUSTOM_MAX) ? len:IW_CUSTOM_MAX;
for(i=0;i<len;i++){
p+=sprintf(p,"%02x",sec_ie[i]);
}
p+=sprintf(p,")");
_rtw_memset(&wrqu,0,sizeof(wrqu));
wrqu.data.length=p-buff;
wrqu.data.length = (wrqu.data.length<IW_CUSTOM_MAX) ? wrqu.data.length:IW_CUSTOM_MAX;
#ifndef CONFIG_IOCTL_CFG80211
wireless_send_event(adapter->pnetdev,IWEVCUSTOM,&wrqu,buff);
#endif
if(buff)
rtw_mfree(buff, IW_CUSTOM_MAX);
}
_func_exit_;
}
void _survey_timer_hdl (void *FunctionContext)
{
_adapter *padapter = (_adapter *)FunctionContext;
survey_timer_hdl(padapter);
}
void _link_timer_hdl (void *FunctionContext)
{
_adapter *padapter = (_adapter *)FunctionContext;
link_timer_hdl(padapter);
}
void _addba_timer_hdl(void *FunctionContext)
{
struct sta_info *psta = (struct sta_info *)FunctionContext;
addba_timer_hdl(psta);
}
#ifdef CONFIG_IEEE80211W
void _sa_query_timer_hdl (void *FunctionContext)
{
_adapter *padapter = (_adapter *)FunctionContext;
sa_query_timer_hdl(padapter);
}
#endif //CONFIG_IEEE80211W
void init_addba_retry_timer(_adapter *padapter, struct sta_info *psta)
{
_init_timer(&psta->addba_retry_timer, padapter->pnetdev, _addba_timer_hdl, psta);
}
/*
void _reauth_timer_hdl(void *FunctionContext)
{
_adapter *padapter = (_adapter *)FunctionContext;
reauth_timer_hdl(padapter);
}
void _reassoc_timer_hdl(void *FunctionContext)
{
_adapter *padapter = (_adapter *)FunctionContext;
reassoc_timer_hdl(padapter);
}
*/
void init_mlme_ext_timer(_adapter *padapter)
{
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
_init_timer(&pmlmeext->survey_timer, padapter->pnetdev, _survey_timer_hdl, padapter);
_init_timer(&pmlmeext->link_timer, padapter->pnetdev, _link_timer_hdl, padapter);
#ifdef CONFIG_IEEE80211W
_init_timer(&pmlmeext->sa_query_timer, padapter->pnetdev, _sa_query_timer_hdl, padapter);
#endif //CONFIG_IEEE80211W
//_init_timer(&pmlmeext->ADDBA_timer, padapter->pnetdev, _addba_timer_hdl, padapter);
//_init_timer(&pmlmeext->reauth_timer, padapter->pnetdev, _reauth_timer_hdl, padapter);
//_init_timer(&pmlmeext->reassoc_timer, padapter->pnetdev, _reassoc_timer_hdl, padapter);
}
#ifdef CONFIG_AP_MODE
void rtw_indicate_sta_assoc_event(_adapter *padapter, struct sta_info *psta)
{
union iwreq_data wrqu;
struct sta_priv *pstapriv = &padapter->stapriv;
if(psta==NULL)
return;
if(psta->aid > NUM_STA)
return;
if(pstapriv->sta_aid[psta->aid - 1] != psta)
return;
wrqu.addr.sa_family = ARPHRD_ETHER;
_rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
DBG_871X("+rtw_indicate_sta_assoc_event\n");
#ifndef CONFIG_IOCTL_CFG80211
wireless_send_event(padapter->pnetdev, IWEVREGISTERED, &wrqu, NULL);
#endif
}
void rtw_indicate_sta_disassoc_event(_adapter *padapter, struct sta_info *psta)
{
union iwreq_data wrqu;
struct sta_priv *pstapriv = &padapter->stapriv;
if(psta==NULL)
return;
if(psta->aid > NUM_STA)
return;
if(pstapriv->sta_aid[psta->aid - 1] != psta)
return;
wrqu.addr.sa_family = ARPHRD_ETHER;
_rtw_memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
DBG_871X("+rtw_indicate_sta_disassoc_event\n");
#ifndef CONFIG_IOCTL_CFG80211
wireless_send_event(padapter->pnetdev, IWEVEXPIRED, &wrqu, NULL);
#endif
}
#ifdef CONFIG_HOSTAPD_MLME
static int mgnt_xmit_entry(struct sk_buff *skb, struct net_device *pnetdev)
{
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
_adapter *padapter = (_adapter *)phostapdpriv->padapter;
//DBG_871X("%s\n", __FUNCTION__);
return rtw_hal_hostap_mgnt_xmit_entry(padapter, skb);
}
static int mgnt_netdev_open(struct net_device *pnetdev)
{
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
DBG_871X("mgnt_netdev_open: MAC Address:" MAC_FMT "\n", MAC_ARG(pnetdev->dev_addr));
init_usb_anchor(&phostapdpriv->anchored);
if(!rtw_netif_queue_stopped(pnetdev))
rtw_netif_start_queue(pnetdev);
else
rtw_netif_wake_queue(pnetdev);
netif_carrier_on(pnetdev);
//rtw_write16(phostapdpriv->padapter, 0x0116, 0x0100);//only excluding beacon
return 0;
}
static int mgnt_netdev_close(struct net_device *pnetdev)
{
struct hostapd_priv *phostapdpriv = rtw_netdev_priv(pnetdev);
DBG_871X("%s\n", __FUNCTION__);
usb_kill_anchored_urbs(&phostapdpriv->anchored);
netif_carrier_off(pnetdev);
if (!rtw_netif_queue_stopped(pnetdev))
rtw_netif_stop_queue(pnetdev);
//rtw_write16(phostapdpriv->padapter, 0x0116, 0x3f3f);
return 0;
}
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
static const struct net_device_ops rtl871x_mgnt_netdev_ops = {
.ndo_open = mgnt_netdev_open,
.ndo_stop = mgnt_netdev_close,
.ndo_start_xmit = mgnt_xmit_entry,
//.ndo_set_mac_address = r871x_net_set_mac_address,
//.ndo_get_stats = r871x_net_get_stats,
//.ndo_do_ioctl = r871x_mp_ioctl,
};
#endif
int hostapd_mode_init(_adapter *padapter)
{
unsigned char mac[ETH_ALEN];
struct hostapd_priv *phostapdpriv;
struct net_device *pnetdev;
pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv));
if (!pnetdev)
return -ENOMEM;
//SET_MODULE_OWNER(pnetdev);
ether_setup(pnetdev);
//pnetdev->type = ARPHRD_IEEE80211;
phostapdpriv = rtw_netdev_priv(pnetdev);
phostapdpriv->pmgnt_netdev = pnetdev;
phostapdpriv->padapter= padapter;
padapter->phostapdpriv = phostapdpriv;
//pnetdev->init = NULL;
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))
DBG_871X("register rtl871x_mgnt_netdev_ops to netdev_ops\n");
pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops;
#else
pnetdev->open = mgnt_netdev_open;
pnetdev->stop = mgnt_netdev_close;
pnetdev->hard_start_xmit = mgnt_xmit_entry;
//pnetdev->set_mac_address = r871x_net_set_mac_address;
//pnetdev->get_stats = r871x_net_get_stats;
//pnetdev->do_ioctl = r871x_mp_ioctl;
#endif
pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
//pnetdev->wireless_handlers = NULL;
#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
pnetdev->features |= NETIF_F_IP_CSUM;
#endif
if(dev_alloc_name(pnetdev,"mgnt.wlan%d") < 0)
{
DBG_871X("hostapd_mode_init(): dev_alloc_name, fail! \n");
}
//SET_NETDEV_DEV(pnetdev, pintfpriv->udev);
mac[0]=0x00;
mac[1]=0xe0;
mac[2]=0x4c;
mac[3]=0x87;
mac[4]=0x11;
mac[5]=0x12;
_rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
netif_carrier_off(pnetdev);
/* Tell the network stack we exist */
if (register_netdev(pnetdev) != 0)
{
DBG_871X("hostapd_mode_init(): register_netdev fail!\n");
if(pnetdev)
{
rtw_free_netdev(pnetdev);
}
}
return 0;
}
void hostapd_mode_unload(_adapter *padapter)
{
struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
struct net_device *pnetdev = phostapdpriv->pmgnt_netdev;
unregister_netdev(pnetdev);
rtw_free_netdev(pnetdev);
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,512 +0,0 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _RECV_OSDEP_C_
#include <drv_conf.h>
#include <osdep_service.h>
#include <drv_types.h>
#include <wifi.h>
#include <recv_osdep.h>
#include <osdep_intf.h>
#include <ethernet.h>
#ifdef CONFIG_USB_HCI
#include <usb_ops.h>
#endif
//init os related resource in struct recv_priv
int rtw_os_recv_resource_init(struct recv_priv *precvpriv, _adapter *padapter)
{
int res=_SUCCESS;
return res;
}
//alloc os related resource in union recv_frame
int rtw_os_recv_resource_alloc(_adapter *padapter, union recv_frame *precvframe)
{
int res=_SUCCESS;
precvframe->u.hdr.pkt_newalloc = precvframe->u.hdr.pkt = NULL;
return res;
}
//free os related resource in union recv_frame
void rtw_os_recv_resource_free(struct recv_priv *precvpriv)
{
sint i;
union recv_frame *precvframe;
precvframe = (union recv_frame*) precvpriv->precv_frame_buf;
for(i=0; i < NR_RECVFRAME; i++)
{
if(precvframe->u.hdr.pkt)
{
rtw_skb_free(precvframe->u.hdr.pkt);//free skb by driver
precvframe->u.hdr.pkt = NULL;
}
precvframe++;
}
}
//alloc os related resource in struct recv_buf
int rtw_os_recvbuf_resource_alloc(_adapter *padapter, struct recv_buf *precvbuf)
{
int res=_SUCCESS;
#ifdef CONFIG_USB_HCI
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *pusbd = pdvobjpriv->pusbdev;
precvbuf->irp_pending = _FALSE;
precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
if(precvbuf->purb == NULL){
res = _FAIL;
}
precvbuf->pskb = NULL;
precvbuf->reuse = _FALSE;
precvbuf->pallocated_buf = precvbuf->pbuf = NULL;
precvbuf->pdata = precvbuf->phead = precvbuf->ptail = precvbuf->pend = NULL;
precvbuf->transfer_len = 0;
precvbuf->len = 0;
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
precvbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)precvbuf->alloc_sz, &precvbuf->dma_transfer_addr);
precvbuf->pbuf = precvbuf->pallocated_buf;
if(precvbuf->pallocated_buf == NULL)
return _FAIL;
#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
#endif //CONFIG_USB_HCI
return res;
}
//free os related resource in struct recv_buf
int rtw_os_recvbuf_resource_free(_adapter *padapter, struct recv_buf *precvbuf)
{
int ret = _SUCCESS;
#ifdef CONFIG_USB_HCI
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *pusbd = pdvobjpriv->pusbdev;
rtw_usb_buffer_free(pusbd, (size_t)precvbuf->alloc_sz, precvbuf->pallocated_buf, precvbuf->dma_transfer_addr);
precvbuf->pallocated_buf = NULL;
precvbuf->dma_transfer_addr = 0;
#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
if(precvbuf->purb)
{
//usb_kill_urb(precvbuf->purb);
usb_free_urb(precvbuf->purb);
}
#endif //CONFIG_USB_HCI
if(precvbuf->pskb)
rtw_skb_free(precvbuf->pskb);
return ret;
}
void rtw_handle_tkip_mic_err(_adapter *padapter,u8 bgroup)
{
#ifdef CONFIG_IOCTL_CFG80211
enum nl80211_key_type key_type;
#endif
union iwreq_data wrqu;
struct iw_michaelmicfailure ev;
struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
struct security_priv *psecuritypriv = &padapter->securitypriv;
u32 cur_time = 0;
if( psecuritypriv->last_mic_err_time == 0 )
{
psecuritypriv->last_mic_err_time = rtw_get_current_time();
}
else
{
cur_time = rtw_get_current_time();
if( cur_time - psecuritypriv->last_mic_err_time < 60*HZ )
{
psecuritypriv->btkip_countermeasure = _TRUE;
psecuritypriv->last_mic_err_time = 0;
psecuritypriv->btkip_countermeasure_time = cur_time;
}
else
{
psecuritypriv->last_mic_err_time = rtw_get_current_time();
}
}
#ifdef CONFIG_IOCTL_CFG80211
if ( bgroup )
{
key_type |= NL80211_KEYTYPE_GROUP;
}
else
{
key_type |= NL80211_KEYTYPE_PAIRWISE;
}
cfg80211_michael_mic_failure(padapter->pnetdev, (u8 *)&pmlmepriv->assoc_bssid[ 0 ], key_type, -1,
NULL, GFP_ATOMIC);
#endif
_rtw_memset( &ev, 0x00, sizeof( ev ) );
if ( bgroup )
{
ev.flags |= IW_MICFAILURE_GROUP;
}
else
{
ev.flags |= IW_MICFAILURE_PAIRWISE;
}
ev.src_addr.sa_family = ARPHRD_ETHER;
_rtw_memcpy( ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
_rtw_memset( &wrqu, 0x00, sizeof( wrqu ) );
wrqu.data.length = sizeof( ev );
#ifndef CONFIG_IOCTL_CFG80211
wireless_send_event( padapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu, (char*) &ev );
#endif
}
void rtw_hostapd_mlme_rx(_adapter *padapter, union recv_frame *precv_frame)
{
#ifdef CONFIG_HOSTAPD_MLME
_pkt *skb;
struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
struct net_device *pmgnt_netdev = phostapdpriv->pmgnt_netdev;
RT_TRACE(_module_recv_osdep_c_, _drv_info_, ("+rtw_hostapd_mlme_rx\n"));
skb = precv_frame->u.hdr.pkt;
if (skb == NULL)
return;
skb->data = precv_frame->u.hdr.rx_data;
skb->tail = precv_frame->u.hdr.rx_tail;
skb->len = precv_frame->u.hdr.len;
//pskb_copy = rtw_skb_copy(skb);
// if(skb == NULL) goto _exit;
skb->dev = pmgnt_netdev;
skb->ip_summed = CHECKSUM_NONE;
skb->pkt_type = PACKET_OTHERHOST;
//skb->protocol = __constant_htons(0x0019); /*ETH_P_80211_RAW*/
skb->protocol = __constant_htons(0x0003); /*ETH_P_80211_RAW*/
//DBG_871X("(1)data=0x%x, head=0x%x, tail=0x%x, mac_header=0x%x, len=%d\n", skb->data, skb->head, skb->tail, skb->mac_header, skb->len);
//skb->mac.raw = skb->data;
skb_reset_mac_header(skb);
//skb_pull(skb, 24);
_rtw_memset(skb->cb, 0, sizeof(skb->cb));
rtw_netif_rx(pmgnt_netdev, skb);
precv_frame->u.hdr.pkt = NULL; // set pointer to NULL before rtw_free_recvframe() if call rtw_netif_rx()
#endif
}
int rtw_recv_indicatepkt(_adapter *padapter, union recv_frame *precv_frame)
{
struct recv_priv *precvpriv;
_queue *pfree_recv_queue;
_pkt *skb;
struct mlme_priv*pmlmepriv = &padapter->mlmepriv;
#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
#endif
#ifdef CONFIG_BR_EXT
void *br_port = NULL;
#endif
_func_enter_;
precvpriv = &(padapter->recvpriv);
pfree_recv_queue = &(precvpriv->free_recv_queue);
#ifdef CONFIG_DRVEXT_MODULE
if (drvext_rx_handler(padapter, precv_frame->u.hdr.rx_data, precv_frame->u.hdr.len) == _SUCCESS)
{
goto _recv_indicatepkt_drop;
}
#endif
#ifdef CONFIG_WAPI_SUPPORT
if (rtw_wapi_check_for_drop(padapter,precv_frame))
{
WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__);
goto _recv_indicatepkt_drop;
}
#endif
skb = precv_frame->u.hdr.pkt;
if(skb == NULL)
{
RT_TRACE(_module_recv_osdep_c_,_drv_err_,("rtw_recv_indicatepkt():skb==NULL something wrong!!!!\n"));
goto _recv_indicatepkt_drop;
}
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("rtw_recv_indicatepkt():skb != NULL !!!\n"));
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));
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));
skb->data = precv_frame->u.hdr.rx_data;
skb_set_tail_pointer(skb, precv_frame->u.hdr.len);
skb->len = precv_frame->u.hdr.len;
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, skb->end, skb->len));
if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
{
_pkt *pskb2=NULL;
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
int bmcast = IS_MCAST(pattrib->dst);
//DBG_871X("bmcast=%d\n", bmcast);
if(_rtw_memcmp(pattrib->dst, myid(&padapter->eeprompriv), ETH_ALEN)==_FALSE)
{
//DBG_871X("not ap psta=%p, addr=%pM\n", psta, pattrib->dst);
if(bmcast)
{
psta = rtw_get_bcmc_stainfo(padapter);
pskb2 = rtw_skb_clone(skb);
} else {
psta = rtw_get_stainfo(pstapriv, pattrib->dst);
}
if(psta)
{
struct net_device *pnetdev= (struct net_device*)padapter->pnetdev;
//DBG_871X("directly forwarding to the rtw_xmit_entry\n");
//skb->ip_summed = CHECKSUM_NONE;
skb->dev = pnetdev;
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
skb_set_queue_mapping(skb, rtw_recv_select_queue(skb));
#endif //LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35)
_rtw_xmit_entry(skb, pnetdev);
if(bmcast)
skb = pskb2;
else
goto _recv_indicatepkt_end;
}
}
else// to APself
{
//DBG_871X("to APSelf\n");
}
}
#ifdef CONFIG_BR_EXT
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
br_port = padapter->pnetdev->br_port;
#else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
rcu_read_lock();
br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
rcu_read_unlock();
#endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
if( br_port && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) )
{
int nat25_handle_frame(_adapter *priv, struct sk_buff *skb);
if (nat25_handle_frame(padapter, skb) == -1) {
//priv->ext_stats.rx_data_drops++;
//DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n");
//return FAIL;
#if 1
// bypass this frame to upper layer!!
#else
goto _recv_indicatepkt_drop;
#endif
}
}
#endif // CONFIG_BR_EXT
#ifdef CONFIG_TCP_CSUM_OFFLOAD_RX
if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
//DBG_871X("CHECKSUM_UNNECESSARY \n");
} else {
skb->ip_summed = CHECKSUM_NONE;
//DBG_871X("CHECKSUM_NONE(%d, %d) \n", pattrib->tcpchk_valid, pattrib->tcp_chkrpt);
}
#else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */
skb->ip_summed = CHECKSUM_NONE;
#endif
skb->dev = padapter->pnetdev;
skb->protocol = eth_type_trans(skb, padapter->pnetdev);
#ifdef DBG_TRX_STA_PKTS
{
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
int bmcast = IS_MCAST(pattrib->dst);
if(bmcast)
{
psta = rtw_get_bcmc_stainfo(padapter);
} else {
psta = rtw_get_stainfo(pstapriv, pattrib->src);
}
if(psta)
{
switch(pattrib->priority)
{
case 1:
case 2:
psta->rx_bk_cnt++;
break;
case 4:
case 5:
psta->rx_vi_cnt++;
break;
case 6:
case 7:
psta->rx_vo_cnt++;
break;
case 0:
case 3:
default:
psta->rx_be_cnt++;
break;
}
}
}
#endif
rtw_netif_rx(padapter->pnetdev, skb);
_recv_indicatepkt_end:
precv_frame->u.hdr.pkt = NULL; // pointers to NULL before rtw_free_recvframe()
rtw_free_recvframe(precv_frame, pfree_recv_queue);
RT_TRACE(_module_recv_osdep_c_,_drv_info_,("\n rtw_recv_indicatepkt :after rtw_netif_rx!!!!\n"));
_func_exit_;
return _SUCCESS;
_recv_indicatepkt_drop:
//enqueue back to free_recv_queue
if(precv_frame)
rtw_free_recvframe(precv_frame, pfree_recv_queue);
return _FAIL;
_func_exit_;
}
void rtw_os_read_port(_adapter *padapter, struct recv_buf *precvbuf)
{
struct recv_priv *precvpriv = &padapter->recvpriv;
#ifdef CONFIG_USB_HCI
precvbuf->ref_cnt--;
//free skb in recv_buf
rtw_skb_free(precvbuf->pskb);
precvbuf->pskb = NULL;
precvbuf->reuse = _FALSE;
if(precvbuf->irp_pending == _FALSE)
{
rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, (unsigned char *)precvbuf);
}
#endif
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
precvbuf->pskb = NULL;
#endif
}
void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext);
void _rtw_reordering_ctrl_timeout_handler (void *FunctionContext)
{
struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)FunctionContext;
rtw_reordering_ctrl_timeout_handler(preorder_ctrl);
}
void rtw_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
{
_adapter *padapter = preorder_ctrl->padapter;
_init_timer(&(preorder_ctrl->reordering_ctrl_timer), padapter->pnetdev, _rtw_reordering_ctrl_timeout_handler, preorder_ctrl);
}

View file

@ -1,828 +0,0 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#include <linux/module.h>
#include <linux/netdevice.h>
#include <rtw_android.h>
#include <osdep_service.h>
#include <rtw_debug.h>
#include <ioctl_cfg80211.h>
#include <rtw_ioctl_set.h>
#ifdef CONFIG_GPIO_WAKEUP
#include <linux/gpio.h>
#endif
#include <drv_types.h>
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
#include <linux/platform_device.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
#include <linux/wlan_plat.h>
#else
#include <linux/wifi_tiwlan.h>
#endif
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */
#ifdef CONFIG_GPIO_WAKEUP
#include <linux/interrupt.h>
#include <linux/irq.h>
#endif
static const char *android_wifi_cmd_str[ANDROID_WIFI_CMD_MAX] = {
"START",
"STOP",
"SCAN-ACTIVE",
"SCAN-PASSIVE",
"RSSI",
"LINKSPEED",
"RXFILTER-START",
"RXFILTER-STOP",
"RXFILTER-ADD",
"RXFILTER-REMOVE",
"BTCOEXSCAN-START",
"BTCOEXSCAN-STOP",
"BTCOEXMODE",
"SETSUSPENDOPT",
"P2P_DEV_ADDR",
"SETFWPATH",
"SETBAND",
"GETBAND",
"COUNTRY",
"P2P_SET_NOA",
"P2P_GET_NOA",
"P2P_SET_PS",
"SET_AP_WPS_P2P_IE",
#ifdef PNO_SUPPORT
"PNOSSIDCLR",
"PNOSETUP ",
"PNOFORCE",
"PNODEBUG",
#endif
"MACADDR",
"BLOCK",
"WFD-ENABLE",
"WFD-DISABLE",
"WFD-SET-TCPPORT",
"WFD-SET-MAXTPUT",
"WFD-SET-DEVTYPE",
};
#ifdef PNO_SUPPORT
#define PNO_TLV_PREFIX 'S'
#define PNO_TLV_VERSION '1'
#define PNO_TLV_SUBVERSION '2'
#define PNO_TLV_RESERVED '0'
#define PNO_TLV_TYPE_SSID_IE 'S'
#define PNO_TLV_TYPE_TIME 'T'
#define PNO_TLV_FREQ_REPEAT 'R'
#define PNO_TLV_FREQ_EXPO_MAX 'M'
typedef struct cmd_tlv {
char prefix;
char version;
char subver;
char reserved;
} cmd_tlv_t;
#endif /* PNO_SUPPORT */
typedef struct android_wifi_priv_cmd {
char *buf;
int used_len;
int total_len;
} android_wifi_priv_cmd;
/**
* Local (static) functions and variables
*/
/* Initialize g_wifi_on to 1 so dhd_bus_start will be called for the first
* time (only) in dhd_open, subsequential wifi on will be handled by
* wl_android_wifi_on
*/
static int g_wifi_on = _TRUE;
static unsigned int oob_irq;
#ifdef PNO_SUPPORT
static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len)
{
wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
int res = -1;
int nssid = 0;
cmd_tlv_t *cmd_tlv_temp;
char *str_ptr;
int tlv_size_left;
int pno_time = 0;
int pno_repeat = 0;
int pno_freq_expo_max = 0;
#ifdef PNO_SET_DEBUG
int i;
char pno_in_example[] = {
'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ',
'S', '1', '2', '0',
'S',
0x05,
'd', 'l', 'i', 'n', 'k',
'S',
0x04,
'G', 'O', 'O', 'G',
'T',
'0', 'B',
'R',
'2',
'M',
'2',
0x00
};
#endif /* PNO_SET_DEBUG */
DHD_INFO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
if (total_len < (strlen(CMD_PNOSETUP_SET) + sizeof(cmd_tlv_t))) {
DBG_871X("%s argument=%d less min size\n", __FUNCTION__, total_len);
goto exit_proc;
}
#ifdef PNO_SET_DEBUG
memcpy(command, pno_in_example, sizeof(pno_in_example));
for (i = 0; i < sizeof(pno_in_example); i++)
printf("%02X ", command[i]);
printf("\n");
total_len = sizeof(pno_in_example);
#endif
str_ptr = command + strlen(CMD_PNOSETUP_SET);
tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET);
cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
memset(ssids_local, 0, sizeof(ssids_local));
if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) &&
(cmd_tlv_temp->version == PNO_TLV_VERSION) &&
(cmd_tlv_temp->subver == PNO_TLV_SUBVERSION)) {
str_ptr += sizeof(cmd_tlv_t);
tlv_size_left -= sizeof(cmd_tlv_t);
if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local,
MAX_PFN_LIST_COUNT, &tlv_size_left)) <= 0) {
DBG_871X("SSID is not presented or corrupted ret=%d\n", nssid);
goto exit_proc;
} else {
if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) {
DBG_871X("%s scan duration corrupted field size %d\n",
__FUNCTION__, tlv_size_left);
goto exit_proc;
}
str_ptr++;
pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
DHD_INFO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
if (str_ptr[0] != 0) {
if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
DBG_871X("%s pno repeat : corrupted field\n",
__FUNCTION__);
goto exit_proc;
}
str_ptr++;
pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
DHD_INFO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
DBG_871X("%s FREQ_EXPO_MAX corrupted field size\n",
__FUNCTION__);
goto exit_proc;
}
str_ptr++;
pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
DHD_INFO(("%s: pno_freq_expo_max=%d\n",
__FUNCTION__, pno_freq_expo_max));
}
}
} else {
DBG_871X("%s get wrong TLV command\n", __FUNCTION__);
goto exit_proc;
}
res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
exit_proc:
return res;
}
#endif /* PNO_SUPPORT */
int rtw_android_cmdstr_to_num(char *cmdstr)
{
int cmd_num;
for(cmd_num=0 ; cmd_num<ANDROID_WIFI_CMD_MAX; cmd_num++)
if(0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], strlen(android_wifi_cmd_str[cmd_num])) )
break;
return cmd_num;
}
static int rtw_android_get_rssi(struct net_device *net, char *command, int total_len)
{
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
int bytes_written = 0;
if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
bytes_written += snprintf(&command[bytes_written], total_len, "%s rssi %d",
pcur_network->network.Ssid.Ssid, padapter->recvpriv.rssi);
}
return bytes_written;
}
static int rtw_android_get_link_speed(struct net_device *net, char *command, int total_len)
{
_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
struct wlan_network *pcur_network = &pmlmepriv->cur_network;
int bytes_written = 0;
u16 link_speed = 0;
link_speed = rtw_get_cur_max_rate(padapter)/10;
bytes_written = snprintf(command, total_len, "LinkSpeed %d", link_speed);
return bytes_written;
}
static int rtw_android_get_macaddr(struct net_device *net, char *command, int total_len)
{
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
int bytes_written = 0;
bytes_written = snprintf(command, total_len, "Macaddr = "MAC_FMT, MAC_ARG(net->dev_addr));
return bytes_written;
}
static int rtw_android_set_country(struct net_device *net, char *command, int total_len)
{
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
char *country_code = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_COUNTRY]) + 1;
int ret = _FAIL;
ret = rtw_set_country(adapter, country_code);
return (ret==_SUCCESS)?0:-1;
}
static int rtw_android_get_p2p_dev_addr(struct net_device *net, char *command, int total_len)
{
int bytes_written = 0;
//We use the same address as our HW MAC address
_rtw_memcpy(command, net->dev_addr, ETH_ALEN);
bytes_written = ETH_ALEN;
return bytes_written;
}
static int rtw_android_set_block(struct net_device *net, char *command, int total_len)
{
_adapter *adapter = (_adapter *)rtw_netdev_priv(net);
char *block_value = command + strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_BLOCK]) + 1;
#ifdef CONFIG_IOCTL_CFG80211
wdev_to_priv(adapter->rtw_wdev)->block = (*block_value=='0')?_FALSE:_TRUE;
#endif
return 0;
}
static int get_int_from_command(char *pcmd)
{
int i = 0;
for( i = 0; i < strlen( pcmd ); i++ )
{
if ( pcmd[ i ] == '=' )
{
// Skip the '=' and space characters.
i += 2;
break;
}
}
return ( rtw_atoi( pcmd + i ) );
}
int rtw_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
{
int ret = 0;
char *command = NULL;
int cmd_num;
int bytes_written = 0;
android_wifi_priv_cmd priv_cmd;
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
#ifdef CONFIG_WFD
struct wifi_display_info *pwfd_info;
#endif
rtw_lock_suspend();
if (!ifr->ifr_data) {
ret = -EINVAL;
goto exit;
}
if (copy_from_user(&priv_cmd, ifr->ifr_data, sizeof(android_wifi_priv_cmd))) {
ret = -EFAULT;
goto exit;
}
//DBG_871X("%s priv_cmd.buf=%p priv_cmd.total_len=%d priv_cmd.used_len=%d\n",__func__,priv_cmd.buf,priv_cmd.total_len,priv_cmd.used_len);
command = rtw_zmalloc(priv_cmd.total_len);
if (!command)
{
DBG_871X("%s: failed to allocate memory\n", __FUNCTION__);
ret = -ENOMEM;
goto exit;
}
if (!access_ok(VERIFY_READ, priv_cmd.buf, priv_cmd.total_len)){
DBG_871X("%s: failed to access memory\n", __FUNCTION__);
ret = -EFAULT;
goto exit;
}
if (copy_from_user(command, (void *)priv_cmd.buf, priv_cmd.total_len)) {
ret = -EFAULT;
goto exit;
}
DBG_871X("%s: Android private cmd \"%s\" on %s\n"
, __FUNCTION__, command, ifr->ifr_name);
cmd_num = rtw_android_cmdstr_to_num(command);
switch(cmd_num) {
case ANDROID_WIFI_CMD_START:
//bytes_written = wl_android_wifi_on(net);
goto response;
case ANDROID_WIFI_CMD_SETFWPATH:
goto response;
}
if (!g_wifi_on) {
DBG_871X("%s: Ignore private cmd \"%s\" - iface %s is down\n"
,__FUNCTION__, command, ifr->ifr_name);
ret = 0;
goto exit;
}
switch(cmd_num) {
case ANDROID_WIFI_CMD_STOP:
//bytes_written = wl_android_wifi_off(net);
break;
case ANDROID_WIFI_CMD_SCAN_ACTIVE:
//rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_ACTIVE);
#ifdef CONFIG_PLATFORM_MSTAR
#ifdef CONFIG_IOCTL_CFG80211
(wdev_to_priv(net->ieee80211_ptr))->bandroid_scan = _TRUE;
#endif //CONFIG_IOCTL_CFG80211
#endif //CONFIG_PLATFORM_MSTAR
break;
case ANDROID_WIFI_CMD_SCAN_PASSIVE:
//rtw_set_scan_mode((_adapter *)rtw_netdev_priv(net), SCAN_PASSIVE);
break;
case ANDROID_WIFI_CMD_RSSI:
bytes_written = rtw_android_get_rssi(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_LINKSPEED:
bytes_written = rtw_android_get_link_speed(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_MACADDR:
bytes_written = rtw_android_get_macaddr(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_BLOCK:
bytes_written = rtw_android_set_block(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_RXFILTER_START:
//bytes_written = net_os_set_packet_filter(net, 1);
break;
case ANDROID_WIFI_CMD_RXFILTER_STOP:
//bytes_written = net_os_set_packet_filter(net, 0);
break;
case ANDROID_WIFI_CMD_RXFILTER_ADD:
//int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0';
//bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num);
break;
case ANDROID_WIFI_CMD_RXFILTER_REMOVE:
//int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0';
//bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num);
break;
case ANDROID_WIFI_CMD_BTCOEXSCAN_START:
/* TBD: BTCOEXSCAN-START */
break;
case ANDROID_WIFI_CMD_BTCOEXSCAN_STOP:
/* TBD: BTCOEXSCAN-STOP */
break;
case ANDROID_WIFI_CMD_BTCOEXMODE:
#if 0
uint mode = *(command + strlen(CMD_BTCOEXMODE) + 1) - '0';
if (mode == 1)
net_os_set_packet_filter(net, 0); /* DHCP starts */
else
net_os_set_packet_filter(net, 1); /* DHCP ends */
#ifdef WL_CFG80211
bytes_written = wl_cfg80211_set_btcoex_dhcp(net, command);
#endif
#endif
break;
case ANDROID_WIFI_CMD_SETSUSPENDOPT:
//bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_SETBAND:
{
uint band = *(command + strlen("SETBAND") + 1) - '0';
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
if (padapter->chip_type == RTL8192D)
padapter->setband = band;
break;
}
case ANDROID_WIFI_CMD_GETBAND:
//bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_COUNTRY:
bytes_written = rtw_android_set_country(net, command, priv_cmd.total_len);
break;
#ifdef PNO_SUPPORT
case ANDROID_WIFI_CMD_PNOSSIDCLR_SET:
//bytes_written = dhd_dev_pno_reset(net);
break;
case ANDROID_WIFI_CMD_PNOSETUP_SET:
//bytes_written = wl_android_set_pno_setup(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_PNOENABLE_SET:
//uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
//bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
break;
#endif
case ANDROID_WIFI_CMD_P2P_DEV_ADDR:
bytes_written = rtw_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_P2P_SET_NOA:
//int skip = strlen(CMD_P2P_SET_NOA) + 1;
//bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip);
break;
case ANDROID_WIFI_CMD_P2P_GET_NOA:
//bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
break;
case ANDROID_WIFI_CMD_P2P_SET_PS:
//int skip = strlen(CMD_P2P_SET_PS) + 1;
//bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, priv_cmd.total_len - skip);
break;
#ifdef CONFIG_IOCTL_CFG80211
case ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE:
{
int skip = strlen(android_wifi_cmd_str[ANDROID_WIFI_CMD_SET_AP_WPS_P2P_IE]) + 3;
bytes_written = rtw_cfg80211_set_mgnt_wpsp2pie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0');
break;
}
#endif //CONFIG_IOCTL_CFG80211
#ifdef CONFIG_WFD
case ANDROID_WIFI_CMD_WFD_ENABLE:
// Commented by Albert 2012/07/24
// We can enable the WFD function by using the following command:
// wpa_cli driver wfd-enable
pwfd_info = &padapter->wfd_info;
if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
pwfd_info->wfd_enable = _TRUE;
break;
case ANDROID_WIFI_CMD_WFD_DISABLE:
// Commented by Albert 2012/07/24
// We can disable the WFD function by using the following command:
// wpa_cli driver wfd-disable
pwfd_info = &padapter->wfd_info;
if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
pwfd_info->wfd_enable = _FALSE;
break;
case ANDROID_WIFI_CMD_WFD_SET_TCPPORT:
// Commented by Albert 2012/07/24
// We can set the tcp port number by using the following command:
// wpa_cli driver wfd-set-tcpport = 554
pwfd_info = &padapter->wfd_info;
if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
pwfd_info->rtsp_ctrlport = (u16)get_int_from_command(priv_cmd.buf);
break;
case ANDROID_WIFI_CMD_WFD_SET_MAX_TPUT:
break;
case ANDROID_WIFI_CMD_WFD_SET_DEVTYPE:
{
// Commented by Albert 2012/08/28
// Specify the WFD device type ( WFD source/primary sink )
struct wifi_display_info *pwfd_info;
_adapter* padapter = ( _adapter * ) rtw_netdev_priv(net);
pwfd_info = &padapter->wfd_info;
if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
pwfd_info->wfd_device_type = (u8)get_int_from_command(priv_cmd.buf);
pwfd_info->wfd_device_type &= WFD_DEVINFO_DUAL;
}
break;
}
#endif
default:
DBG_871X("Unknown PRIVATE command %s - ignored\n", command);
snprintf(command, 3, "OK");
bytes_written = strlen("OK");
}
response:
if (bytes_written >= 0) {
if ((bytes_written == 0) && (priv_cmd.total_len > 0))
command[0] = '\0';
if (bytes_written >= priv_cmd.total_len) {
DBG_871X("%s: bytes_written = %d\n", __FUNCTION__, bytes_written);
bytes_written = priv_cmd.total_len;
} else {
bytes_written++;
}
priv_cmd.used_len = bytes_written;
if (copy_to_user((void *)priv_cmd.buf, command, bytes_written)) {
DBG_871X("%s: failed to copy data to user buffer\n", __FUNCTION__);
ret = -EFAULT;
}
}
else {
ret = bytes_written;
}
exit:
rtw_unlock_suspend();
if (command) {
rtw_mfree(command, priv_cmd.total_len);
}
return ret;
}
/**
* Functions for Android WiFi card detection
*/
#if defined(RTW_ENABLE_WIFI_CONTROL_FUNC)
static int g_wifidev_registered = 0;
static struct semaphore wifi_control_sem;
static struct wifi_platform_data *wifi_control_data = NULL;
static struct resource *wifi_irqres = NULL;
static int wifi_add_dev(void);
static void wifi_del_dev(void);
int rtw_android_wifictrl_func_add(void)
{
int ret = 0;
sema_init(&wifi_control_sem, 0);
ret = wifi_add_dev();
if (ret) {
DBG_871X("%s: platform_driver_register failed\n", __FUNCTION__);
return ret;
}
g_wifidev_registered = 1;
/* Waiting callback after platform_driver_register is done or exit with error */
if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) {
ret = -EINVAL;
DBG_871X("%s: platform_driver_register timeout\n", __FUNCTION__);
}
return ret;
}
void rtw_android_wifictrl_func_del(void)
{
if (g_wifidev_registered)
{
wifi_del_dev();
g_wifidev_registered = 0;
}
}
void *wl_android_prealloc(int section, unsigned long size)
{
void *alloc_ptr = NULL;
if (wifi_control_data && wifi_control_data->mem_prealloc) {
alloc_ptr = wifi_control_data->mem_prealloc(section, size);
if (alloc_ptr) {
DBG_871X("success alloc section %d\n", section);
if (size != 0L)
memset(alloc_ptr, 0, size);
return alloc_ptr;
}
}
DBG_871X("can't alloc section %d\n", section);
return NULL;
}
int wifi_get_irq_number(unsigned long *irq_flags_ptr)
{
if (wifi_irqres) {
*irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK;
return (int)wifi_irqres->start;
}
#ifdef CUSTOM_OOB_GPIO_NUM
return CUSTOM_OOB_GPIO_NUM;
#else
return -1;
#endif
}
int wifi_set_power(int on, unsigned long msec)
{
DBG_871X("%s = %d\n", __FUNCTION__, on);
if (wifi_control_data && wifi_control_data->set_power) {
wifi_control_data->set_power(on);
}
if (msec)
msleep(msec);
return 0;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
int wifi_get_mac_addr(unsigned char *buf)
{
DBG_871X("%s\n", __FUNCTION__);
if (!buf)
return -EINVAL;
if (wifi_control_data && wifi_control_data->get_mac_addr) {
return wifi_control_data->get_mac_addr(buf);
}
return -EOPNOTSUPP;
}
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) || defined(COMPAT_KERNEL_RELEASE)
void *wifi_get_country_code(char *ccode)
{
DBG_871X("%s\n", __FUNCTION__);
if (!ccode)
return NULL;
if (wifi_control_data && wifi_control_data->get_country_code) {
return wifi_control_data->get_country_code(ccode);
}
return NULL;
}
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
static int wifi_set_carddetect(int on)
{
DBG_871X("%s = %d\n", __FUNCTION__, on);
if (wifi_control_data && wifi_control_data->set_carddetect) {
wifi_control_data->set_carddetect(on);
}
return 0;
}
static int wifi_probe(struct platform_device *pdev)
{
struct wifi_platform_data *wifi_ctrl =
(struct wifi_platform_data *)(pdev->dev.platform_data);
int wifi_wake_gpio = 0;
DBG_871X("## %s\n", __FUNCTION__);
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
if (wifi_irqres == NULL)
wifi_irqres = platform_get_resource_byname(pdev,
IORESOURCE_IRQ, "bcm4329_wlan_irq");
else
wifi_wake_gpio = wifi_irqres->start;
#ifdef CONFIG_GPIO_WAKEUP
printk("%s: gpio:%d wifi_wake_gpio:%d\n", __func__,
wifi_irqres->start, wifi_wake_gpio);
if (wifi_wake_gpio > 0) {
gpio_request(wifi_wake_gpio, "oob_irq");
gpio_direction_input(wifi_wake_gpio);
oob_irq = gpio_to_irq(wifi_wake_gpio);
printk("%s oob_irq:%d\n", __func__, oob_irq);
}
#endif
wifi_control_data = wifi_ctrl;
wifi_set_power(1, 0); /* Power On */
wifi_set_carddetect(1); /* CardDetect (0->1) */
up(&wifi_control_sem);
return 0;
}
static int wifi_remove(struct platform_device *pdev)
{
struct wifi_platform_data *wifi_ctrl =
(struct wifi_platform_data *)(pdev->dev.platform_data);
DBG_871X("## %s\n", __FUNCTION__);
wifi_control_data = wifi_ctrl;
wifi_set_power(0, 0); /* Power Off */
wifi_set_carddetect(0); /* CardDetect (1->0) */
up(&wifi_control_sem);
return 0;
}
static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
{
DBG_871X("##> %s\n", __FUNCTION__);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
bcmsdh_oob_intr_set(0);
#endif
return 0;
}
static int wifi_resume(struct platform_device *pdev)
{
DBG_871X("##> %s\n", __FUNCTION__);
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY)
if (dhd_os_check_if_up(bcmsdh_get_drvdata()))
bcmsdh_oob_intr_set(1);
#endif
return 0;
}
/* temporarily use these two */
static struct platform_driver wifi_device = {
.probe = wifi_probe,
.remove = wifi_remove,
.suspend = wifi_suspend,
.resume = wifi_resume,
.driver = {
.name = "bcmdhd_wlan",
}
};
static struct platform_driver wifi_device_legacy = {
.probe = wifi_probe,
.remove = wifi_remove,
.suspend = wifi_suspend,
.resume = wifi_resume,
.driver = {
.name = "bcm4329_wlan",
}
};
static int wifi_add_dev(void)
{
DBG_871X("## Calling platform_driver_register\n");
platform_driver_register(&wifi_device);
platform_driver_register(&wifi_device_legacy);
return 0;
}
static void wifi_del_dev(void)
{
DBG_871X("## Unregister platform_driver_register\n");
platform_driver_unregister(&wifi_device);
platform_driver_unregister(&wifi_device_legacy);
}
#endif /* defined(RTW_ENABLE_WIFI_CONTROL_FUNC) */

File diff suppressed because it is too large Load diff

View file

@ -1,698 +0,0 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*******************************************************************************/
#define _USB_OPS_LINUX_C_
#include <drv_types.h>
#include <usb_ops_linux.h>
#include <rtw_sreset.h>
#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
static void _usbctrl_vendorreq_async_callback(struct urb *urb, struct pt_regs *regs)
{
if (urb) {
if (urb->context) {
rtw_mfree(urb->context);
}
usb_free_urb(urb);
}
}
static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
u16 value, u16 index, void *pdata, u16 len, u8 requesttype)
{
int rc;
unsigned int pipe;
u8 reqtype;
struct usb_ctrlrequest *dr;
struct urb *urb;
struct rtl819x_async_write_data {
u8 data[VENDOR_CMD_MAX_DATA_LEN];
struct usb_ctrlrequest dr;
} *buf;
if (requesttype == VENDOR_READ) {
pipe = usb_rcvctrlpipe(udev, 0);//read_in
reqtype = REALTEK_USB_VENQT_READ;
}
else {
pipe = usb_sndctrlpipe(udev, 0);//write_out
reqtype = REALTEK_USB_VENQT_WRITE;
}
buf = (struct rtl819x_async_write_data *)rtw_zmalloc(sizeof(*buf));
if (!buf) {
rc = -ENOMEM;
goto exit;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
rtw_mfree((u8*)buf, sizeof(*buf));
rc = -ENOMEM;
goto exit;
}
dr = &buf->dr;
dr->bRequestType = reqtype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(len);
_rtw_memcpy(buf, pdata, len);
usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, buf, len,
_usbctrl_vendorreq_async_callback, buf);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
rtw_mfree((u8*)buf, sizeof(*buf));
usb_free_urb(urb);
}
exit:
return rc;
}
int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
{
u8 request;
u8 requesttype;
u16 wvalue;
u16 index;
int ret;
requesttype = VENDOR_WRITE;//write_out
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX;//n/a
wvalue = (u16)(addr&0x0000ffff);
ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
return ret;
}
int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
{
u8 data;
int ret;
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
struct usb_device *udev=pdvobjpriv->pusbdev;
_func_enter_;
data = val;
ret = usb_write_async(udev, addr, &data, 1);
_func_exit_;
return ret;
}
int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
{
u16 data;
int ret;
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
struct usb_device *udev=pdvobjpriv->pusbdev;
_func_enter_;
data = val;
ret = usb_write_async(udev, addr, &data, 2);
_func_exit_;
return ret;
}
int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
{
u32 data;
int ret;
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
struct usb_device *udev=pdvobjpriv->pusbdev;
_func_enter_;
data = val;
ret = usb_write_async(udev, addr, &data, 4);
_func_exit_;
return ret;
}
#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
{
unsigned int pipe=0, ep_num=0;
struct usb_device *pusbd = pdvobj->pusbdev;
if (addr == RECV_BULK_IN_ADDR) {
pipe=usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
} else if (addr == RECV_INT_IN_ADDR) {
pipe=usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
} else if (addr < HW_QUEUE_ENTRY) {
ep_num = pdvobj->Queue2Pipe[addr];
pipe = usb_sndbulkpipe(pusbd, ep_num);
}
return pipe;
}
struct zero_bulkout_context{
void *pbuf;
void *purb;
void *pirp;
void *padapter;
};
static void usb_bulkout_zero_complete(struct urb *purb, struct pt_regs *regs)
{
struct zero_bulkout_context *pcontext = (struct zero_bulkout_context *)purb->context;
//DBG_8192C("+usb_bulkout_zero_complete\n");
if(pcontext)
{
if(pcontext->pbuf)
{
rtw_mfree(pcontext->pbuf, sizeof(int));
}
if(pcontext->purb && (pcontext->purb==purb))
{
usb_free_urb(pcontext->purb);
}
rtw_mfree((u8*)pcontext, sizeof(struct zero_bulkout_context));
}
}
static u32 usb_bulkout_zero(struct intf_hdl *pintfhdl, u32 addr)
{
int pipe, status, len;
u32 ret;
unsigned char *pbuf;
struct zero_bulkout_context *pcontext;
PURB purb = NULL;
_adapter *padapter = (_adapter *)pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
struct usb_device *pusbd = pdvobj->pusbdev;
//DBG_871X("%s\n", __func__);
if((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(dvobj_to_pwrctl(pdvobj)->pnp_bstop_trx))
{
return _FAIL;
}
pcontext = (struct zero_bulkout_context *)rtw_zmalloc(sizeof(struct zero_bulkout_context));
pbuf = (unsigned char *)rtw_zmalloc(sizeof(int));
purb = usb_alloc_urb(0, GFP_ATOMIC);
len = 0;
pcontext->pbuf = pbuf;
pcontext->purb = purb;
pcontext->pirp = NULL;
pcontext->padapter = padapter;
//translate DMA FIFO addr to pipehandle
//pipe = ffaddr2pipehdl(pdvobj, addr);
usb_fill_bulk_urb(purb, pusbd, pipe,
pbuf,
len,
usb_bulkout_zero_complete,
pcontext);//context is pcontext
status = usb_submit_urb(purb, GFP_ATOMIC);
if (!status)
{
ret= _SUCCESS;
}
else
{
ret= _FAIL;
}
return _SUCCESS;
}
void usb_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
{
}
void usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
{
}
void usb_read_port_cancel(struct intf_hdl *pintfhdl)
{
int i;
struct recv_buf *precvbuf;
_adapter *padapter = pintfhdl->padapter;
precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
DBG_871X("%s\n", __func__);
padapter->bReadPortCancel = _TRUE;
for (i=0; i < NR_RECVBUFF ; i++) {
precvbuf->reuse = _TRUE;
if (precvbuf->purb) {
//DBG_8192C("usb_read_port_cancel : usb_kill_urb \n");
usb_kill_urb(precvbuf->purb);
}
precvbuf++;
}
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
usb_kill_urb(padapter->recvpriv.int_in_urb);
#endif
}
static void usb_write_port_complete(struct urb *purb, struct pt_regs *regs)
{
_irqL irqL;
int i;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
//struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
//_adapter *padapter = pxmitframe->padapter;
_adapter *padapter = pxmitbuf->padapter;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
//struct pkt_attrib *pattrib = &pxmitframe->attrib;
_func_enter_;
switch(pxmitbuf->flags)
{
case VO_QUEUE_INX:
pxmitpriv->voq_cnt--;
break;
case VI_QUEUE_INX:
pxmitpriv->viq_cnt--;
break;
case BE_QUEUE_INX:
pxmitpriv->beq_cnt--;
break;
case BK_QUEUE_INX:
pxmitpriv->bkq_cnt--;
break;
case HIGH_QUEUE_INX:
#ifdef CONFIG_AP_MODE
rtw_chk_hi_queue_cmd(padapter);
#endif
break;
default:
break;
}
/*
_enter_critical(&pxmitpriv->lock, &irqL);
pxmitpriv->txirp_cnt--;
switch(pattrib->priority)
{
case 1:
case 2:
pxmitpriv->bkq_cnt--;
//DBG_8192C("pxmitpriv->bkq_cnt=%d\n", pxmitpriv->bkq_cnt);
break;
case 4:
case 5:
pxmitpriv->viq_cnt--;
//DBG_8192C("pxmitpriv->viq_cnt=%d\n", pxmitpriv->viq_cnt);
break;
case 6:
case 7:
pxmitpriv->voq_cnt--;
//DBG_8192C("pxmitpriv->voq_cnt=%d\n", pxmitpriv->voq_cnt);
break;
case 0:
case 3:
default:
pxmitpriv->beq_cnt--;
//DBG_8192C("pxmitpriv->beq_cnt=%d\n", pxmitpriv->beq_cnt);
break;
}
_exit_critical(&pxmitpriv->lock, &irqL);
if(pxmitpriv->txirp_cnt==0)
{
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: txirp_cnt== 0, set allrxreturnevt!\n"));
_rtw_up_sema(&(pxmitpriv->tx_retevt));
}
*/
//rtw_free_xmitframe(pxmitpriv, pxmitframe);
if(padapter->bSurpriseRemoved || padapter->bDriverStopped ||padapter->bWritePortCancel)
{
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
DBG_8192C("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x) \n",
__FUNCTION__,padapter->bDriverStopped, padapter->bSurpriseRemoved,padapter->bReadPortCancel,pxmitbuf->ext_tag);
goto check_completion;
}
if (purb->status==0) {
} else {
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete : purb->status(%d) != 0 \n", purb->status));
DBG_871X("###=> urb_write_port_complete status(%d)\n",purb->status);
if((purb->status==-EPIPE)||(purb->status==-EPROTO))
{
//usb_clear_halt(pusbdev, purb->pipe);
//msleep(10);
sreset_set_wifi_error_status(padapter, USB_WRITE_PORT_FAIL);
} else if (purb->status == -EINPROGRESS) {
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: EINPROGESS\n"));
goto check_completion;
} else if (purb->status == -ENOENT) {
DBG_871X("%s: -ENOENT\n", __func__);
goto check_completion;
} else if (purb->status == -ECONNRESET) {
DBG_871X("%s: -ECONNRESET\n", __func__);
goto check_completion;
} else if (purb->status == -ESHUTDOWN) {
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete: ESHUTDOWN\n"));
padapter->bDriverStopped=_TRUE;
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bDriverStopped=TRUE\n"));
goto check_completion;
}
else
{
padapter->bSurpriseRemoved=_TRUE;
DBG_8192C("bSurpriseRemoved=TRUE\n");
//rtl8192cu_trigger_gpio_0(padapter);
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port_complete:bSurpriseRemoved=TRUE\n"));
goto check_completion;
}
}
#ifdef DBG_CONFIG_ERROR_DETECT
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.last_tx_complete_time = rtw_get_current_time();
}
#endif
check_completion:
_enter_critical(&pxmitpriv->lock_sctx, &irqL);
rtw_sctx_done_err(&pxmitbuf->sctx,
purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR : RTW_SCTX_DONE_SUCCESS);
_exit_critical(&pxmitpriv->lock_sctx, &irqL);
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
//if(rtw_txframes_pending(padapter))
{
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
_func_exit_;
}
u32 usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
{
_irqL irqL;
unsigned int pipe;
int status;
u32 ret = _FAIL, bwritezero = _FALSE;
PURB purb = NULL;
_adapter *padapter = (_adapter *)pintfhdl->padapter;
struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)wmem;
struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
struct usb_device *pusbd = pdvobj->pusbdev;
struct pkt_attrib *pattrib = &pxmitframe->attrib;
_func_enter_;
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("+usb_write_port\n"));
if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||(dvobj_to_pwrctl(pdvobj)->pnp_bstop_trx)) {
#ifdef DBG_TX
DBG_871X(" DBG_TX %s:%d bDriverStopped%d, bSurpriseRemoved:%d, pnp_bstop_trx:%d\n",__FUNCTION__, __LINE__
,padapter->bDriverStopped, padapter->bSurpriseRemoved, dvobj_to_pwrctl(pdvobj)->pnp_bstop_trx );
#endif
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||pwrctl->pnp_bstop_trx)!!!\n"));
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
goto exit;
}
_enter_critical(&pxmitpriv->lock, &irqL);
switch(addr)
{
case VO_QUEUE_INX:
pxmitpriv->voq_cnt++;
pxmitbuf->flags = VO_QUEUE_INX;
break;
case VI_QUEUE_INX:
pxmitpriv->viq_cnt++;
pxmitbuf->flags = VI_QUEUE_INX;
break;
case BE_QUEUE_INX:
pxmitpriv->beq_cnt++;
pxmitbuf->flags = BE_QUEUE_INX;
break;
case BK_QUEUE_INX:
pxmitpriv->bkq_cnt++;
pxmitbuf->flags = BK_QUEUE_INX;
break;
case HIGH_QUEUE_INX:
pxmitbuf->flags = HIGH_QUEUE_INX;
break;
default:
pxmitbuf->flags = MGT_QUEUE_INX;
break;
}
_exit_critical(&pxmitpriv->lock, &irqL);
#ifdef DBG_TRX_STA_PKTS
{
struct sta_info *psta = NULL;
struct sta_priv *pstapriv = &padapter->stapriv;
int bmcast = IS_MCAST(pattrib->dst);
u8 agg_num = 1;
#ifdef CONFIG_USB_HCI
#ifdef CONFIG_USB_TX_AGGREGATION
if(pxmitframe->agg_num>1)
agg_num = pxmitframe->agg_num;
#endif
#endif
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
if(pxmitframe->agg_num>1)
agg_num = pxmitframe->agg_num;
#endif
if(bmcast)
{
psta = rtw_get_bcmc_stainfo(padapter);
} else {
psta = rtw_get_stainfo(pstapriv, pattrib->dst);
}
if(psta)
{
switch(pattrib->priority)
{
case 1:
case 2:
psta->tx_bk_cnt += agg_num;
break;
case 4:
case 5:
psta->tx_vi_cnt += agg_num;
break;
case 6:
case 7:
psta->tx_vo_cnt += agg_num;
break;
case 0:
case 3:
default:
psta->tx_be_cnt += agg_num;
break;
}
}
}
#endif
purb = pxmitbuf->pxmit_urb[0];
#if 0
if(pdvobj->ishighspeed)
{
if(cnt> 0 && cnt%512 == 0)
{
//DBG_8192C("ishighspeed, cnt=%d\n", cnt);
bwritezero = _TRUE;
}
}
else
{
if(cnt > 0 && cnt%64 == 0)
{
//DBG_8192C("cnt=%d\n", cnt);
bwritezero = _TRUE;
}
}
#endif
//translate DMA FIFO addr to pipehandle
pipe = ffaddr2pipehdl(pdvobj, addr);
#ifdef CONFIG_REDUCE_USB_TX_INT
if ( (pxmitpriv->free_xmitbuf_cnt%NR_XMITBUFF == 0)
|| (pxmitbuf->ext_tag == _TRUE) )
{
purb->transfer_flags &= (~URB_NO_INTERRUPT);
} else {
purb->transfer_flags |= URB_NO_INTERRUPT;
//DBG_8192C("URB_NO_INTERRUPT ");
}
#endif
usb_fill_bulk_urb(purb, pusbd, pipe,
pxmitframe->buf_addr, //= pxmitbuf->pbuf
cnt,
usb_write_port_complete,
pxmitbuf);//context is pxmitbuf
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
purb->transfer_dma = pxmitbuf->dma_transfer_addr;
purb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
purb->transfer_flags |= URB_ZERO_PACKET;
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
#if 0
if (bwritezero)
{
purb->transfer_flags |= URB_ZERO_PACKET;
}
#endif
status = usb_submit_urb(purb, GFP_ATOMIC);
if (!status) {
#ifdef DBG_CONFIG_ERROR_DETECT
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
pHalData->srestpriv.last_tx_time = rtw_get_current_time();
}
#endif
} else {
rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
DBG_871X("usb_write_port, status=%d\n", status);
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("usb_write_port(): usb_submit_urb, status=%x\n", status));
switch (status) {
case -ENODEV:
padapter->bDriverStopped=_TRUE;
break;
default:
break;
}
goto exit;
}
ret= _SUCCESS;
// Commented by Albert 2009/10/13
// We add the URB_ZERO_PACKET flag to urb so that the host will send the zero packet automatically.
/*
if(bwritezero == _TRUE)
{
usb_bulkout_zero(pintfhdl, addr);
}
*/
RT_TRACE(_module_hci_ops_os_c_,_drv_err_,("-usb_write_port\n"));
exit:
if (ret != _SUCCESS)
rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
_func_exit_;
return ret;
}
void usb_write_port_cancel(struct intf_hdl *pintfhdl)
{
int i, j;
_adapter *padapter = pintfhdl->padapter;
struct xmit_buf *pxmitbuf = (struct xmit_buf *)padapter->xmitpriv.pxmitbuf;
DBG_871X("%s \n", __func__);
padapter->bWritePortCancel = _TRUE;
for (i=0; i<NR_XMITBUFF; i++) {
for (j=0; j<8; j++) {
if (pxmitbuf->pxmit_urb[j]) {
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
}
}
pxmitbuf++;
}
pxmitbuf = (struct xmit_buf*)padapter->xmitpriv.pxmit_extbuf;
for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
for (j=0; j<8; j++) {
if(pxmitbuf->pxmit_urb[j]) {
usb_kill_urb(pxmitbuf->pxmit_urb[j]);
}
}
pxmitbuf++;
}
}

View file

@ -1,456 +0,0 @@
/******************************************************************************
*
* Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
******************************************************************************/
#define _XMIT_OSDEP_C_
#include <drv_conf.h>
#include <osdep_service.h>
#include <drv_types.h>
#include <if_ether.h>
#include <ip.h>
#include <rtw_byteorder.h>
#include <wifi.h>
#include <mlme_osdep.h>
#include <xmit_osdep.h>
#include <osdep_intf.h>
#include <circ_buf.h>
uint rtw_remainder_len(struct pkt_file *pfile)
{
return (pfile->buf_len - ((SIZE_PTR)(pfile->cur_addr) - (SIZE_PTR)(pfile->buf_start)));
}
void _rtw_open_pktfile (_pkt *pktptr, struct pkt_file *pfile)
{
_func_enter_;
pfile->pkt = pktptr;
pfile->cur_addr = pfile->buf_start = pktptr->data;
pfile->pkt_len = pfile->buf_len = pktptr->len;
pfile->cur_buffer = pfile->buf_start ;
_func_exit_;
}
uint _rtw_pktfile_read (struct pkt_file *pfile, u8 *rmem, uint rlen)
{
uint len = 0;
_func_enter_;
len = rtw_remainder_len(pfile);
len = (rlen > len)? len: rlen;
if(rmem)
skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len, rmem, len);
pfile->cur_addr += len;
pfile->pkt_len -= len;
_func_exit_;
return len;
}
sint rtw_endofpktfile(struct pkt_file *pfile)
{
_func_enter_;
if (pfile->pkt_len == 0) {
_func_exit_;
return _TRUE;
}
_func_exit_;
return _FALSE;
}
void rtw_set_tx_chksum_offload(_pkt *pkt, struct pkt_attrib *pattrib)
{
#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
struct sk_buff *skb = (struct sk_buff *)pkt;
pattrib->hw_tcp_csum = 0;
if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (skb_shinfo(skb)->nr_frags == 0)
{
const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP) {
// TCP checksum offload by HW
DBG_871X("CHECKSUM_PARTIAL TCP\n");
pattrib->hw_tcp_csum = 1;
//skb_checksum_help(skb);
} else if (ip->protocol == IPPROTO_UDP) {
//DBG_871X("CHECKSUM_PARTIAL UDP\n");
#if 1
skb_checksum_help(skb);
#else
// Set UDP checksum = 0 to skip checksum check
struct udphdr *udp = skb_transport_header(skb);
udp->check = 0;
#endif
} else {
DBG_871X("%s-%d TCP CSUM offload Error!!\n", __FUNCTION__, __LINE__);
WARN_ON(1); /* we need a WARN() */
}
}
else { // IP fragmentation case
DBG_871X("%s-%d nr_frags != 0, using skb_checksum_help(skb);!!\n", __FUNCTION__, __LINE__);
skb_checksum_help(skb);
}
}
#endif
}
int rtw_os_xmit_resource_alloc(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 alloc_sz)
{
#ifdef CONFIG_USB_HCI
int i;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *pusbd = pdvobjpriv->pusbdev;
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
pxmitbuf->pallocated_buf = rtw_usb_buffer_alloc(pusbd, (size_t)alloc_sz, &pxmitbuf->dma_transfer_addr);
pxmitbuf->pbuf = pxmitbuf->pallocated_buf;
if(pxmitbuf->pallocated_buf == NULL)
return _FAIL;
#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
if (pxmitbuf->pallocated_buf == NULL)
{
return _FAIL;
}
pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
pxmitbuf->dma_transfer_addr = 0;
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
for(i=0; i<8; i++)
{
pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
if(pxmitbuf->pxmit_urb[i] == NULL)
{
DBG_871X("pxmitbuf->pxmit_urb[i]==NULL");
return _FAIL;
}
}
#endif
#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
pxmitbuf->pallocated_buf = rtw_zmalloc(alloc_sz);
if (pxmitbuf->pallocated_buf == NULL)
{
return _FAIL;
}
pxmitbuf->pbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ);
#endif
return _SUCCESS;
}
void rtw_os_xmit_resource_free(_adapter *padapter, struct xmit_buf *pxmitbuf,u32 free_sz)
{
#ifdef CONFIG_USB_HCI
int i;
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
struct usb_device *pusbd = pdvobjpriv->pusbdev;
for(i=0; i<8; i++)
{
if(pxmitbuf->pxmit_urb[i])
{
//usb_kill_urb(pxmitbuf->pxmit_urb[i]);
usb_free_urb(pxmitbuf->pxmit_urb[i]);
}
}
#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
rtw_usb_buffer_free(pusbd, (size_t)free_sz, pxmitbuf->pallocated_buf, pxmitbuf->dma_transfer_addr);
pxmitbuf->pallocated_buf = NULL;
pxmitbuf->dma_transfer_addr = 0;
#else // CONFIG_USE_USB_BUFFER_ALLOC_TX
if(pxmitbuf->pallocated_buf)
rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
#endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
#endif
#if defined(CONFIG_PCI_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
if(pxmitbuf->pallocated_buf)
rtw_mfree(pxmitbuf->pallocated_buf, free_sz);
#endif
}
#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5)
void rtw_os_pkt_complete(_adapter *padapter, _pkt *pkt)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35))
u16 queue;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
queue = skb_get_queue_mapping(pkt);
if (padapter->registrypriv.wifi_spec) {
if(__netif_subqueue_stopped(padapter->pnetdev, queue) &&
(pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
{
netif_wake_subqueue(padapter->pnetdev, queue);
}
} else {
if(__netif_subqueue_stopped(padapter->pnetdev, queue))
netif_wake_subqueue(padapter->pnetdev, queue);
}
#else
if (netif_queue_stopped(padapter->pnetdev))
netif_wake_queue(padapter->pnetdev);
#endif
rtw_skb_free(pkt);
}
void rtw_os_xmit_complete(_adapter *padapter, struct xmit_frame *pxframe)
{
if(pxframe->pkt)
rtw_os_pkt_complete(padapter, pxframe->pkt);
pxframe->pkt = NULL;
}
void rtw_os_xmit_schedule(_adapter *padapter)
{
_adapter *pri_adapter = padapter;
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
if(!padapter)
return;
#ifdef CONFIG_CONCURRENT_MODE
if(padapter->adapter_type > PRIMARY_ADAPTER)
pri_adapter = padapter->pbuddy_adapter;
#endif
if (_rtw_queue_empty(&pri_adapter->xmitpriv.pending_xmitbuf_queue) == _FALSE)
_rtw_up_sema(&pri_adapter->xmitpriv.xmit_sema);
#else
_irqL irqL;
struct xmit_priv *pxmitpriv;
if(!padapter)
return;
pxmitpriv = &padapter->xmitpriv;
_enter_critical_bh(&pxmitpriv->lock, &irqL);
if(rtw_txframes_pending(padapter))
{
tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
}
_exit_critical_bh(&pxmitpriv->lock, &irqL);
#endif
}
static void rtw_check_xmit_resource(_adapter *padapter, _pkt *pkt)
{
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
u16 queue;
queue = skb_get_queue_mapping(pkt);
if (padapter->registrypriv.wifi_spec) {
/* No free space for Tx, tx_worker is too slow */
if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) {
//DBG_871X("%s(): stop netif_subqueue[%d]\n", __FUNCTION__, queue);
netif_stop_subqueue(padapter->pnetdev, queue);
}
} else {
if(pxmitpriv->free_xmitframe_cnt<=4) {
if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
netif_stop_subqueue(padapter->pnetdev, queue);
}
}
#else
if(pxmitpriv->free_xmitframe_cnt<=4)
{
if (!rtw_netif_queue_stopped(padapter->pnetdev))
rtw_netif_stop_queue(padapter->pnetdev);
}
#endif
}
#ifdef CONFIG_TX_MCAST2UNI
static int rtw_mlcst2unicst(_adapter *padapter, struct sk_buff *skb)
{
struct sta_priv *pstapriv = &padapter->stapriv;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
_irqL irqL;
_list *phead, *plist;
struct sk_buff *newskb;
struct sta_info *psta = NULL;
u8 chk_alive_num = 0;
char chk_alive_list[NUM_STA];
u8 bc_addr[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 null_addr[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int i;
s32 res;
_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
phead = &pstapriv->asoc_list;
plist = get_next(phead);
//free sta asoc_queue
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
int stainfo_offset;
psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
plist = get_next(plist);
stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
if (stainfo_offset_valid(stainfo_offset)) {
chk_alive_list[chk_alive_num++] = stainfo_offset;
}
}
_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
for (i = 0; i < chk_alive_num; i++) {
psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
if(!(psta->state &_FW_LINKED))
continue;
/* avoid come from STA1 and send back STA1 */
if (_rtw_memcmp(psta->hwaddr, &skb->data[6], 6) == _TRUE
|| _rtw_memcmp(psta->hwaddr, null_addr, 6) == _TRUE
|| _rtw_memcmp(psta->hwaddr, bc_addr, 6) == _TRUE
)
continue;
newskb = rtw_skb_copy(skb);
if (newskb) {
_rtw_memcpy(newskb->data, psta->hwaddr, 6);
res = rtw_xmit(padapter, &newskb);
if (res < 0) {
DBG_871X("%s()-%d: rtw_xmit() return error!\n", __FUNCTION__, __LINE__);
pxmitpriv->tx_drop++;
rtw_skb_free(newskb);
} else
pxmitpriv->tx_pkts++;
} else {
DBG_871X("%s-%d: rtw_skb_copy() failed!\n", __FUNCTION__, __LINE__);
pxmitpriv->tx_drop++;
//rtw_skb_free(skb);
return _FALSE; // Caller shall tx this multicast frame via normal way.
}
}
rtw_skb_free(skb);
return _TRUE;
}
#endif // CONFIG_TX_MCAST2UNI
int _rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
{
_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
#ifdef CONFIG_TX_MCAST2UNI
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
extern int rtw_mc2u_disable;
#endif // CONFIG_TX_MCAST2UNI
s32 res = 0;
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
u16 queue;
#endif
_func_enter_;
RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
if (rtw_if_up(padapter) == _FALSE) {
RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit_entry: rtw_if_up fail\n"));
#ifdef DBG_TX_DROP_FRAME
DBG_871X("DBG_TX_DROP_FRAME %s if_up fail\n", __FUNCTION__);
#endif
goto drop_packet;
}
rtw_check_xmit_resource(padapter, pkt);
#ifdef CONFIG_TX_MCAST2UNI
if ( !rtw_mc2u_disable
&& check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE
&& ( IP_MCAST_MAC(pkt->data)
|| ICMPV6_MCAST_MAC(pkt->data) )
&& (padapter->registrypriv.wifi_spec == 0)
)
{
if ( pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME/4) ) {
res = rtw_mlcst2unicst(padapter, pkt);
if (res == _TRUE) {
goto exit;
}
} else {
//DBG_871X("Stop M2U(%d, %d)! ", pxmitpriv->free_xmitframe_cnt, pxmitpriv->free_xmitbuf_cnt);
//DBG_871X("!m2u );
}
}
#endif // CONFIG_TX_MCAST2UNI
res = rtw_xmit(padapter, &pkt);
if (res < 0) {
#ifdef DBG_TX_DROP_FRAME
DBG_871X("DBG_TX_DROP_FRAME %s rtw_xmit fail\n", __FUNCTION__);
#endif
goto drop_packet;
}
pxmitpriv->tx_pkts++;
RT_TRACE(_module_xmit_osdep_c_, _drv_info_, ("rtw_xmit_entry: tx_pkts=%d\n", (u32)pxmitpriv->tx_pkts));
goto exit;
drop_packet:
pxmitpriv->tx_drop++;
rtw_skb_free(pkt);
RT_TRACE(_module_xmit_osdep_c_, _drv_notice_, ("rtw_xmit_entry: drop, tx_drop=%d\n", (u32)pxmitpriv->tx_drop));
exit:
_func_exit_;
return 0;
}
int rtw_xmit_entry(_pkt *pkt, _nic_hdl pnetdev)
{
if (pkt)
rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, pkt->truesize);
return _rtw_xmit_entry(pkt, pnetdev);
}