/****************************************************************************** * * Copyright(c) 2007 - 2015 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 _RTW_MI_C_ #include #include void rtw_mi_update_union_chan_inf(_adapter *adapter, u8 ch, u8 offset , u8 bw) { struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); struct mi_state *iface_state = &dvobj->iface_state; iface_state->union_ch = ch; iface_state->union_bw = bw; iface_state->union_offset = offset; } /* Find union about ch, bw, ch_offset of all linked/linking interfaces */ int _rtw_mi_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset, bool include_self) { struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); _adapter *iface; struct mlme_ext_priv *mlmeext; int i; u8 ch_ret = 0; u8 bw_ret = CHANNEL_WIDTH_20; u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE; int num = 0; if (ch) *ch = 0; if (bw) *bw = CHANNEL_WIDTH_20; if (offset) *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; mlmeext = &iface->mlmeextpriv; if (!check_fwstate(&iface->mlmepriv, _FW_LINKED | _FW_UNDER_LINKING)) continue; if (check_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING)) continue; if (include_self == _FALSE && adapter == iface) continue; if (num == 0) { ch_ret = mlmeext->cur_channel; bw_ret = mlmeext->cur_bwmode; offset_ret = mlmeext->cur_ch_offset; num++; continue; } if (ch_ret != mlmeext->cur_channel) { num = 0; break; } if (bw_ret < mlmeext->cur_bwmode) { bw_ret = mlmeext->cur_bwmode; offset_ret = mlmeext->cur_ch_offset; } else if (bw_ret == mlmeext->cur_bwmode && offset_ret != mlmeext->cur_ch_offset) { num = 0; break; } num++; } if (num) { if (ch) *ch = ch_ret; if (bw) *bw = bw_ret; if (offset) *offset = offset_ret; } return num; } inline int rtw_mi_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset) { return _rtw_mi_get_ch_setting_union(adapter, ch, bw, offset, 1); } inline int rtw_mi_get_ch_setting_union_no_self(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset) { return _rtw_mi_get_ch_setting_union(adapter, ch, bw, offset, 0); } void _rtw_mi_status(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num , u8 *ap_num, u8 *ld_ap_num, u8 *uw_num, bool include_self) { struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); _adapter *iface; struct mlme_ext_priv *mlmeext; int i; u8 sta_num_ret = 0; u8 ld_sta_num_ret = 0; u8 lg_sta_num_ret = 0; u8 ap_num_ret = 0; u8 ld_ap_num_ret = 0; u8 uw_num_ret = 0; if (sta_num) *sta_num = 0; if (ld_sta_num) *ld_sta_num = 0; if (lg_sta_num) *lg_sta_num = 0; if (ap_num) *ap_num = 0; if (ld_ap_num) *ld_ap_num = 0; if (uw_num) *uw_num = 0; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if (include_self == _FALSE && iface == adapter) continue; /*mlmeext = &iface->mlmeextpriv; if (mlmeext_msr(mlmeext) == WIFI_FW_STATION_STATE) {*/ if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE)) { sta_num_ret++; if (check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE) ld_sta_num_ret++; if (check_fwstate(&iface->mlmepriv, _FW_UNDER_LINKING) == _TRUE) lg_sta_num_ret++; } /*if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE*/ if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) && check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE ) { ap_num_ret++; if (iface->stapriv.asoc_sta_count > 2) ld_ap_num_ret++; } if (check_fwstate(&iface->mlmepriv, WIFI_UNDER_WPS) == _TRUE) uw_num_ret++; } if (sta_num) *sta_num = sta_num_ret; if (ld_sta_num) *ld_sta_num = ld_sta_num_ret; if (lg_sta_num) *lg_sta_num = lg_sta_num_ret; if (ap_num) *ap_num = ap_num_ret; if (ld_ap_num) *ld_ap_num = ld_ap_num_ret; if (uw_num) *uw_num = uw_num_ret; } inline void rtw_mi_status(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num , u8 *ap_num, u8 *ld_ap_num, u8 *uw_num) { return _rtw_mi_status(adapter, sta_num, ld_sta_num, lg_sta_num, ap_num, ld_ap_num, uw_num, 1); } inline void rtw_mi_status_no_self(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num , u8 *ap_num, u8 *ld_ap_num, u8 *uw_num) { return _rtw_mi_status(adapter, sta_num, ld_sta_num, lg_sta_num, ap_num, ld_ap_num, uw_num, 0); } void dump_mi_status(void *sel, struct dvobj_priv *dvobj) { RTW_PRINT_SEL(sel, "== dvobj-iface_state ==\n"); RTW_PRINT_SEL(sel, "sta_num:%d\n", dvobj->iface_state.sta_num); RTW_PRINT_SEL(sel, "linking_sta_num:%d\n", dvobj->iface_state.lg_sta_num); RTW_PRINT_SEL(sel, "linked_sta_num:%d\n", dvobj->iface_state.ld_sta_num); RTW_PRINT_SEL(sel, "ap_num:%d\n", dvobj->iface_state.ap_num); RTW_PRINT_SEL(sel, "linked_ap_num:%d\n", dvobj->iface_state.ld_ap_num); RTW_PRINT_SEL(sel, "adhoc_num:%d\n", dvobj->iface_state.adhoc_num); RTW_PRINT_SEL(sel, "linked_adhoc_num:%d\n", dvobj->iface_state.ld_adhoc_num); #ifdef CONFIG_P2P RTW_PRINT_SEL(sel, "p2p_device_num:%d\n", rtw_mi_stay_in_p2p_mode(dvobj->padapters[IFACE_ID0])); #endif RTW_PRINT_SEL(sel, "under_wps_num:%d\n", dvobj->iface_state.uwps_num); RTW_PRINT_SEL(sel, "union_ch:%d\n", dvobj->iface_state.union_ch); RTW_PRINT_SEL(sel, "union_bw:%d\n", dvobj->iface_state.union_bw); RTW_PRINT_SEL(sel, "union_offset:%d\n", dvobj->iface_state.union_offset); RTW_PRINT_SEL(sel, "================\n\n"); } void dump_dvobj_mi_status(void *sel, const char *fun_name, _adapter *adapter) { RTW_INFO("\n[ %s ] call %s\n", fun_name, __func__); dump_mi_status(sel, adapter_to_dvobj(adapter)); } inline void rtw_mi_update_iface_status(struct mlme_priv *pmlmepriv, sint state) { _adapter *adapter = container_of(pmlmepriv, _adapter, mlmepriv); struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); struct mi_state *iface_state = &dvobj->iface_state; u8 i; u8 u_ch, u_offset, u_bw; _adapter *iface; struct mlme_ext_priv *mlmeext; if ((state == WIFI_MONITOR_STATE) || /* (state == WIFI_OP_CH_SWITCHING) || */ (state == WIFI_ADHOC_MASTER_STATE) || (state == WIFI_ADHOC_STATE) || (state == WIFI_SITE_MONITOR) || (state == 0xFFFFFFFF) || (state == WIFI_UNDER_WPS) ) return; if (0) RTW_INFO("%s => will change or clean state to 0x%08x\n", __func__, state); _rtw_memset(iface_state, 0, sizeof(struct mi_state)); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; mlmeext = &iface->mlmeextpriv; if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE) == _TRUE) { iface_state->sta_num++; if (check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE) iface_state->ld_sta_num++; if (check_fwstate(&iface->mlmepriv, _FW_UNDER_LINKING) == _TRUE) iface_state->lg_sta_num++; } else if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == _TRUE && check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE ) { iface_state->ap_num++; if (iface->stapriv.asoc_sta_count > 2) iface_state->ld_ap_num++; } else if (check_fwstate(&iface->mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE && check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE ) { iface_state->adhoc_num++; if (iface->stapriv.asoc_sta_count > 2) iface_state->ld_adhoc_num++; } if (check_fwstate(&iface->mlmepriv, WIFI_UNDER_WPS) == _TRUE) iface_state->uwps_num++; } if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset)) rtw_mi_update_union_chan_inf(adapter , u_ch, u_offset , u_bw); else { if (0) { dump_adapters_status(RTW_DBGDUMP , dvobj); RTW_INFO("%s-[ERROR] cannot get union channel\n", __func__); rtw_warn_on(1); } } #ifdef DBG_IFACE_STATUS DBG_IFACE_STATUS_DUMP(adapter); #endif } u8 rtw_mi_check_status(_adapter *adapter, u8 type) { struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); struct mi_state *iface_state = &dvobj->iface_state; u8 ret = _FALSE; #ifdef DBG_IFACE_STATUS DBG_IFACE_STATUS_DUMP(adapter); RTW_INFO("%s-"ADPT_FMT" check type:%d\n", __func__, ADPT_ARG(adapter), type); #endif switch (type) { case MI_LINKED: if (iface_state->ld_sta_num || iface_state->ap_num || iface_state->adhoc_num) /*check_fwstate(&iface->mlmepriv, _FW_LINKED)*/ ret = _TRUE; break; case MI_ASSOC: if (iface_state->ld_sta_num || iface_state->ld_ap_num || iface_state->ld_adhoc_num) ret = _TRUE; break; case MI_UNDER_WPS: if (iface_state->uwps_num) ret = _TRUE; break; case MI_AP_MODE: if (iface_state->ap_num) ret = _TRUE; break; case MI_AP_ASSOC: if (iface_state->ld_ap_num) ret = _TRUE; break; case MI_ADHOC: if (iface_state->adhoc_num) ret = _TRUE; break; case MI_ADHOC_ASSOC: if (iface_state->ld_adhoc_num) ret = _TRUE; break; case MI_STA_NOLINK: /* this is misleading, but not used now */ if (iface_state->sta_num && (!(iface_state->ld_sta_num || iface_state->lg_sta_num))) ret = _TRUE; break; case MI_STA_LINKED: if (iface_state->ld_sta_num) ret = _TRUE; break; case MI_STA_LINKING: if (iface_state->lg_sta_num) ret = _TRUE; break; default: break; } return ret; } #if 0 inline void rtw_mi_update_fwstate(struct mlme_priv *pmlmepriv, sint state, u8 bset) { _adapter *adapter = container_of(pmlmepriv, _adapter, mlmepriv); struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); struct mi_state *iface_state = &dvobj->iface_state; struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv; if (!(state & (_FW_LINKED | _FW_UNDER_LINKING | WIFI_UNDER_WPS))) return; if (mlmeext_msr(mlmeext) == WIFI_FW_STATION_STATE) { /*ATOMIC_INC(&(iface_state->sta_num_ret));*/ if (state & _FW_LINKED) (bset) ? ATOMIC_INC(&(iface_state->ld_sta_num_ret)) : ATOMIC_DEC(&(iface_state->ld_sta_num_ret)); if (state & _FW_UNDER_LINKING) (bset) ? ATOMIC_INC(&(iface_state->lg_sta_num_ret)) : ATOMIC_DEC(&(iface_state->lg_sta_num_ret)); } if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE && check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _TRUE ) { /*ATOMIC_INC(&(iface_state->ap_num_ret));*/ if (adapter->stapriv.asoc_sta_count > 2) ld_ap_num_ret++; } if (state & WIFI_UNDER_WPS) (bset) ? ATOMIC_INC(&(iface_state->uw_num_ret)) : ATOMIC_DEC(&(iface_state->uw_num_ret)); _rtw_mi_status(adapter, &iface_state->sta_num, &iface_state->ld_sta_num, &iface_state->lg_sta_num , &iface_state->ap_num, &iface_state->ld_ap_num, &iface_state->uwps_num, 1); } #endif #ifdef CONFIG_MP_INCLUDED u8 rtw_mi_mp_mode_check(_adapter *padapter) { #ifdef CONFIG_CONCURRENT_MODE int i; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); _adapter *iface = NULL; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && (iface->registrypriv.mp_mode == 1)) { RTW_INFO(ADPT_FMT "-MP mode enable\n", ADPT_ARG(iface)); return _TRUE; } } #else if (padapter->registrypriv.mp_mode == 1) return _TRUE; #endif return _FALSE; } #endif #ifdef CONFIG_CONCURRENT_MODE u8 rtw_mi_buddy_under_survey(_adapter *padapter) { int i; u8 ret = 0; _adapter *iface = NULL; _irqL irqL; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); #ifdef CONFIG_IOCTL_CFG80211 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter); #endif struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_priv *buddy_mlmepriv; struct rtw_wdev_priv *buddy_wdev_priv; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if (iface == padapter) continue; buddy_mlmepriv = &iface->mlmepriv; if (check_fwstate(buddy_mlmepriv, _FW_UNDER_SURVEY)) { ret = UNDER_SURVEY_T1; #ifdef CONFIG_IOCTL_CFG80211 buddy_wdev_priv = adapter_wdev_data(iface); _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL); _enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL); if (buddy_wdev_priv->scan_request) { pmlmepriv->scanning_via_buddy_intf = _TRUE; _enter_critical_bh(&pmlmepriv->lock, &irqL); set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); _exit_critical_bh(&pmlmepriv->lock, &irqL); ret = UNDER_SURVEY_T2; } _exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL); _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL); #endif RTW_INFO(ADPT_FMT"_FW_UNDER_SURVEY\n", ADPT_ARG(iface)); return ret; } } } return ret; } void rtw_mi_buddy_indicate_scan_done(_adapter *padapter, bool bscan_aborted) { #if defined(CONFIG_IOCTL_CFG80211) int i; u8 ret = 0; _adapter *iface = NULL; _irqL irqL; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct mlme_priv *mlmepriv; struct rtw_wdev_priv *wdev_priv; bool indicate_buddy_scan = _FALSE; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if (iface == padapter) continue; mlmepriv = &(iface->mlmepriv); wdev_priv = adapter_wdev_data(iface); _enter_critical_bh(&wdev_priv->scan_req_lock, &irqL); if (wdev_priv->scan_request && mlmepriv->scanning_via_buddy_intf == _TRUE) { mlmepriv->scanning_via_buddy_intf = _FALSE; clr_fwstate(mlmepriv, _FW_UNDER_SURVEY); indicate_buddy_scan = _TRUE; } _exit_critical_bh(&wdev_priv->scan_req_lock, &irqL); if (indicate_buddy_scan == _TRUE) { rtw_cfg80211_surveydone_event_callback(iface); rtw_indicate_scan_done(iface, bscan_aborted); } } } #endif } #endif /* * return value : 0 is failed or have not interface meet condition * return value : !0 is success or interface numbers which meet condition * return value of ops_func must be _TRUE or _FALSE */ static u8 _rtw_mi_process(_adapter *padapter, bool exclude_self, void *data, u8(*ops_func)(_adapter *padapter, void *data)) { int i; _adapter *iface; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); u8 ret = 0; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if ((exclude_self) && (iface == padapter)) continue; if (ops_func) if (_TRUE == ops_func(iface, data)) ret++; } } return ret; } static u8 _rtw_mi_netif_stop_queue(_adapter *padapter, void *data) { bool carrier_off = *(bool *)data; struct net_device *pnetdev = padapter->pnetdev; if (carrier_off) netif_carrier_off(pnetdev); rtw_netif_stop_queue(pnetdev); return _TRUE; } u8 rtw_mi_netif_stop_queue(_adapter *padapter, bool carrier_off) { bool in_data = carrier_off; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_netif_stop_queue); } u8 rtw_mi_buddy_netif_stop_queue(_adapter *padapter, bool carrier_off) { bool in_data = carrier_off; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_netif_stop_queue); } static u8 _rtw_mi_netif_wake_queue(_adapter *padapter, void *data) { struct net_device *pnetdev = padapter->pnetdev; if (pnetdev) rtw_netif_wake_queue(pnetdev); return _TRUE; } u8 rtw_mi_netif_wake_queue(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_netif_wake_queue); } u8 rtw_mi_buddy_netif_wake_queue(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_netif_wake_queue); } static u8 _rtw_mi_netif_carrier_on(_adapter *padapter, void *data) { struct net_device *pnetdev = padapter->pnetdev; if (pnetdev) rtw_netif_carrier_on(pnetdev); return _TRUE; } u8 rtw_mi_netif_carrier_on(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_netif_carrier_on); } u8 rtw_mi_buddy_netif_carrier_on(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_netif_carrier_on); } static u8 _rtw_mi_scan_abort(_adapter *adapter, void *data) { bool bwait = *(bool *)data; if (bwait) rtw_scan_abort(adapter); else rtw_scan_abort_no_wait(adapter); return _TRUE; } void rtw_mi_scan_abort(_adapter *adapter, bool bwait) { bool in_data = bwait; _rtw_mi_process(adapter, _FALSE, &in_data, _rtw_mi_scan_abort); } void rtw_mi_buddy_scan_abort(_adapter *adapter, bool bwait) { bool in_data = bwait; _rtw_mi_process(adapter, _TRUE, &in_data, _rtw_mi_scan_abort); } static u8 _rtw_mi_start_drv_threads(_adapter *adapter, void *data) { rtw_start_drv_threads(adapter); return _TRUE; } void rtw_mi_start_drv_threads(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_start_drv_threads); } void rtw_mi_buddy_start_drv_threads(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_start_drv_threads); } static u8 _rtw_mi_stop_drv_threads(_adapter *adapter, void *data) { rtw_stop_drv_threads(adapter); return _TRUE; } void rtw_mi_stop_drv_threads(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_stop_drv_threads); } void rtw_mi_buddy_stop_drv_threads(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_stop_drv_threads); } static u8 _rtw_mi_cancel_all_timer(_adapter *adapter, void *data) { rtw_cancel_all_timer(adapter); return _TRUE; } void rtw_mi_cancel_all_timer(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_cancel_all_timer); } void rtw_mi_buddy_cancel_all_timer(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_cancel_all_timer); } static u8 _rtw_mi_reset_drv_sw(_adapter *adapter, void *data) { rtw_reset_drv_sw(adapter); return _TRUE; } void rtw_mi_reset_drv_sw(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_reset_drv_sw); } void rtw_mi_buddy_reset_drv_sw(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_reset_drv_sw); } static u8 _rtw_mi_intf_start(_adapter *adapter, void *data) { rtw_intf_start(adapter); return _TRUE; } void rtw_mi_intf_start(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_intf_start); } void rtw_mi_buddy_intf_start(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_intf_start); } static u8 _rtw_mi_intf_stop(_adapter *adapter, void *data) { rtw_intf_stop(adapter); return _TRUE; } void rtw_mi_intf_stop(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_intf_stop); } void rtw_mi_buddy_intf_stop(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_intf_stop); } static u8 _rtw_mi_suspend_free_assoc_resource(_adapter *padapter, void *data) { return rtw_suspend_free_assoc_resource(padapter); } void rtw_mi_suspend_free_assoc_resource(_adapter *adapter) { _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_suspend_free_assoc_resource); } void rtw_mi_buddy_suspend_free_assoc_resource(_adapter *adapter) { _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_suspend_free_assoc_resource); } static u8 _rtw_mi_is_scan_deny(_adapter *adapter, void *data) { return rtw_is_scan_deny(adapter); } u8 rtw_mi_is_scan_deny(_adapter *adapter) { return _rtw_mi_process(adapter, _FALSE, NULL, _rtw_mi_is_scan_deny); } u8 rtw_mi_buddy_is_scan_deny(_adapter *adapter) { return _rtw_mi_process(adapter, _TRUE, NULL, _rtw_mi_is_scan_deny); } #ifdef CONFIG_SET_SCAN_DENY_TIMER static u8 _rtw_mi_set_scan_deny(_adapter *adapter, void *data) { u32 ms = *(u32 *)data; rtw_set_scan_deny(adapter, ms); return _TRUE; } void rtw_mi_set_scan_deny(_adapter *adapter, u32 ms) { u32 in_data = ms; _rtw_mi_process(adapter, _FALSE, &in_data, _rtw_mi_set_scan_deny); } void rtw_mi_buddy_set_scan_deny(_adapter *adapter, u32 ms) { u32 in_data = ms; _rtw_mi_process(adapter, _TRUE, &in_data, _rtw_mi_set_scan_deny); } #endif struct nulldata_param { unsigned char *da; unsigned int power_mode; int try_cnt; int wait_ms; }; static u8 _rtw_mi_issue_nulldata(_adapter *padapter, void *data) { struct nulldata_param *pnulldata_param = (struct nulldata_param *)data; if (is_client_associated_to_ap(padapter) == _TRUE) { /* TODO: TDLS peers */ issue_nulldata(padapter, pnulldata_param->da, pnulldata_param->power_mode, pnulldata_param->try_cnt, pnulldata_param->wait_ms); return _TRUE; } return _FALSE; } u8 rtw_mi_issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) { struct nulldata_param nparam; nparam.da = da; nparam.power_mode = power_mode;/*0 or 1*/ nparam.try_cnt = try_cnt; nparam.wait_ms = wait_ms; return _rtw_mi_process(padapter, _FALSE, &nparam, _rtw_mi_issue_nulldata); } u8 rtw_mi_buddy_issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) { struct nulldata_param nparam; nparam.da = da; nparam.power_mode = power_mode; nparam.try_cnt = try_cnt; nparam.wait_ms = wait_ms; return _rtw_mi_process(padapter, _TRUE, &nparam, _rtw_mi_issue_nulldata); } static u8 _rtw_mi_beacon_update(_adapter *padapter, void *data) { struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv; if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE && check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE) { RTW_INFO(ADPT_FMT"-WIFI_FW_AP_STATE - update_beacon\n", ADPT_ARG(padapter)); update_beacon(padapter, 0, NULL, _TRUE); } return _TRUE; } void rtw_mi_beacon_update(_adapter *padapter) { _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_beacon_update); } void rtw_mi_buddy_beacon_update(_adapter *padapter) { _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_beacon_update); } static u8 _rtw_mi_hal_dump_macaddr(_adapter *padapter, void *data) { u8 mac_addr[ETH_ALEN] = {0}; rtw_hal_get_macaddr_port(padapter, mac_addr); RTW_INFO(ADPT_FMT"MAC Address ="MAC_FMT"\n", ADPT_ARG(padapter), MAC_ARG(mac_addr)); return _TRUE; } void rtw_mi_hal_dump_macaddr(_adapter *padapter) { _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_hal_dump_macaddr); } void rtw_mi_buddy_hal_dump_macaddr(_adapter *padapter) { _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_hal_dump_macaddr); } #ifdef CONFIG_PCI_HCI static u8 _rtw_mi_xmit_tasklet_schedule(_adapter *padapter, void *data) { if (rtw_txframes_pending(padapter)) { /* try to deal with the pending packets */ tasklet_hi_schedule(&(padapter->xmitpriv.xmit_tasklet)); } return _TRUE; } void rtw_mi_xmit_tasklet_schedule(_adapter *padapter) { _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_xmit_tasklet_schedule); } void rtw_mi_buddy_xmit_tasklet_schedule(_adapter *padapter) { _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_xmit_tasklet_schedule); } #endif u8 _rtw_mi_busy_traffic_check(_adapter *padapter, void *data) { u32 passtime; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; bool check_sc_interval = *(bool *)data; if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE) { if (check_sc_interval) { /* Miracast can't do AP scan*/ passtime = rtw_get_passing_time_ms(pmlmepriv->lastscantime); pmlmepriv->lastscantime = rtw_get_current_time(); if (passtime > BUSY_TRAFFIC_SCAN_DENY_PERIOD) { RTW_INFO(ADPT_FMT" bBusyTraffic == _TRUE\n", ADPT_ARG(padapter)); return _TRUE; } } else return _TRUE; } return _FALSE; } u8 rtw_mi_busy_traffic_check(_adapter *padapter, bool check_sc_interval) { bool in_data = check_sc_interval; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_busy_traffic_check); } u8 rtw_mi_buddy_busy_traffic_check(_adapter *padapter, bool check_sc_interval) { bool in_data = check_sc_interval; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_busy_traffic_check); } static u8 _rtw_mi_check_mlmeinfo_state(_adapter *padapter, void *data) { u32 state = *(u32 *)data; struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv; /*if (mlmeext_msr(mlmeext) == state)*/ if (check_mlmeinfo_state(mlmeext, state)) return _TRUE; else return _FALSE; } u8 rtw_mi_check_mlmeinfo_state(_adapter *padapter, u32 state) { u32 in_data = state; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_check_mlmeinfo_state); } u8 rtw_mi_buddy_check_mlmeinfo_state(_adapter *padapter, u32 state) { u32 in_data = state; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_check_mlmeinfo_state); } /*#define DBG_DUMP_FW_STATE*/ #ifdef DBG_DUMP_FW_STATE static void rtw_dbg_dump_fwstate(_adapter *padapter, sint state) { u8 buf[32] = {0}; if (state & WIFI_FW_NULL_STATE) { _rtw_memset(buf, 0, 32); sprintf(buf, "WIFI_FW_NULL_STATE"); RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf); } if (state & _FW_LINKED) { _rtw_memset(buf, 0, 32); sprintf(buf, "_FW_LINKED"); RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf); } if (state & _FW_UNDER_LINKING) { _rtw_memset(buf, 0, 32); sprintf(buf, "_FW_UNDER_LINKING"); RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf); } if (state & _FW_UNDER_SURVEY) { _rtw_memset(buf, 0, 32); sprintf(buf, "_FW_UNDER_SURVEY"); RTW_INFO(FUNC_ADPT_FMT"fwstate-%s\n", FUNC_ADPT_ARG(padapter), buf); } } #endif static u8 _rtw_mi_check_fwstate(_adapter *padapter, void *data) { u8 ret = _FALSE; sint state = *(sint *)data; if ((state == WIFI_FW_NULL_STATE) && (padapter->mlmepriv.fw_state == WIFI_FW_NULL_STATE)) ret = _TRUE; else if (_TRUE == check_fwstate(&padapter->mlmepriv, state)) ret = _TRUE; #ifdef DBG_DUMP_FW_STATE if (ret) rtw_dbg_dump_fwstate(padapter, state); #endif return ret; } u8 rtw_mi_check_fwstate(_adapter *padapter, sint state) { sint in_data = state; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_check_fwstate); } u8 rtw_mi_buddy_check_fwstate(_adapter *padapter, sint state) { sint in_data = state; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_check_fwstate); } static u8 _rtw_mi_traffic_statistics(_adapter *padapter , void *data) { struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); /* Tx */ pdvobjpriv->traffic_stat.tx_bytes += padapter->xmitpriv.tx_bytes; pdvobjpriv->traffic_stat.tx_pkts += padapter->xmitpriv.tx_pkts; pdvobjpriv->traffic_stat.tx_drop += padapter->xmitpriv.tx_drop; /* Rx */ pdvobjpriv->traffic_stat.rx_bytes += padapter->recvpriv.rx_bytes; pdvobjpriv->traffic_stat.rx_pkts += padapter->recvpriv.rx_pkts; pdvobjpriv->traffic_stat.rx_drop += padapter->recvpriv.rx_drop; return _TRUE; } u8 rtw_mi_traffic_statistics(_adapter *padapter) { struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter); /*_rtw_memset(&pdvobjpriv->traffic_stat, 0, sizeof(struct rtw_traffic_statistics));*/ /* Tx bytes reset*/ pdvobjpriv->traffic_stat.tx_bytes = 0; pdvobjpriv->traffic_stat.tx_pkts = 0; pdvobjpriv->traffic_stat.tx_drop = 0; /* Rx bytes reset*/ pdvobjpriv->traffic_stat.rx_bytes = 0; pdvobjpriv->traffic_stat.rx_pkts = 0; pdvobjpriv->traffic_stat.rx_drop = 0; return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_traffic_statistics); } static u8 _rtw_mi_check_miracast_enabled(_adapter *padapter , void *data) { return is_miracast_enabled(padapter); } u8 rtw_mi_check_miracast_enabled(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_check_miracast_enabled); } #ifdef CONFIG_XMIT_THREAD_MODE static u8 _rtw_mi_check_pending_xmitbuf(_adapter *padapter , void *data) { struct xmit_priv *pxmitpriv = &padapter->xmitpriv; return check_pending_xmitbuf(pxmitpriv); } u8 rtw_mi_check_pending_xmitbuf(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_check_pending_xmitbuf); } u8 rtw_mi_buddy_check_pending_xmitbuf(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_check_pending_xmitbuf); } #endif #if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) static u8 _rtw_mi_dequeue_writeport(_adapter *padapter , bool exclude_self) { int i; u8 queue_empty = _TRUE; _adapter *iface; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if ((exclude_self) && (iface == padapter)) continue; queue_empty &= _dequeue_writeport(iface); } } return queue_empty; } u8 rtw_mi_dequeue_writeport(_adapter *padapter) { return _rtw_mi_dequeue_writeport(padapter, _FALSE); } u8 rtw_mi_buddy_dequeue_writeport(_adapter *padapter) { return _rtw_mi_dequeue_writeport(padapter, _TRUE); } #endif static void _rtw_mi_adapter_reset(_adapter *padapter , u8 exclude_self) { int i; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { if (dvobj->padapters[i]) { if ((exclude_self) && (dvobj->padapters[i] == padapter)) continue; dvobj->padapters[i] = NULL; } } } void rtw_mi_adapter_reset(_adapter *padapter) { _rtw_mi_adapter_reset(padapter, _FALSE); } void rtw_mi_buddy_adapter_reset(_adapter *padapter) { _rtw_mi_adapter_reset(padapter, _TRUE); } static u8 _rtw_mi_dynamic_check_timer_handlder(_adapter *adapter, void *data) { rtw_dynamic_check_timer_handlder(adapter); return _TRUE; } u8 rtw_mi_dynamic_check_timer_handlder(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_dynamic_check_timer_handlder); } u8 rtw_mi_buddy_dynamic_check_timer_handlder(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_dynamic_check_timer_handlder); } static u8 _rtw_mi_dev_unload(_adapter *adapter, void *data) { rtw_dev_unload(adapter); return _TRUE; } u8 rtw_mi_dev_unload(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_dev_unload); } u8 rtw_mi_buddy_dev_unload(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_dev_unload); } static u8 _rtw_mi_dynamic_chk_wk_hdl(_adapter *adapter, void *data) { dynamic_chk_wk_hdl(adapter); return _TRUE; } u8 rtw_mi_dynamic_chk_wk_hdl(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_dynamic_chk_wk_hdl); } u8 rtw_mi_buddy_dynamic_chk_wk_hdl(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_dynamic_chk_wk_hdl); } static u8 _rtw_mi_os_xmit_schedule(_adapter *adapter, void *data) { rtw_os_xmit_schedule(adapter); return _TRUE; } u8 rtw_mi_os_xmit_schedule(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_os_xmit_schedule); } u8 rtw_mi_buddy_os_xmit_schedule(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_os_xmit_schedule); } static u8 _rtw_mi_report_survey_event(_adapter *adapter, void *data) { union recv_frame *precv_frame = (union recv_frame *)data; report_survey_event(adapter, precv_frame); return _TRUE; } u8 rtw_mi_report_survey_event(_adapter *padapter, union recv_frame *precv_frame) { return _rtw_mi_process(padapter, _FALSE, precv_frame, _rtw_mi_report_survey_event); } u8 rtw_mi_buddy_report_survey_event(_adapter *padapter, union recv_frame *precv_frame) { return _rtw_mi_process(padapter, _TRUE, precv_frame, _rtw_mi_report_survey_event); } static u8 _rtw_mi_sreset_adapter_hdl(_adapter *adapter, void *data) { u8 bstart = *(u8 *)data; if (bstart) sreset_start_adapter(adapter); else sreset_stop_adapter(adapter); return _TRUE; } u8 rtw_mi_sreset_adapter_hdl(_adapter *padapter, u8 bstart) { u8 in_data = bstart; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_sreset_adapter_hdl); } u8 rtw_mi_buddy_sreset_adapter_hdl(_adapter *padapter, u8 bstart) { u8 in_data = bstart; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_sreset_adapter_hdl); } static u8 _rtw_mi_tx_beacon_hdl(_adapter *adapter, void *data) { if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _TRUE && check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE) == _TRUE ) { adapter->mlmepriv.update_bcn = _TRUE; #ifndef CONFIG_INTERRUPT_BASED_TXBCN #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI) tx_beacon_hdl(adapter, NULL); #endif #endif } return _TRUE; } u8 rtw_mi_tx_beacon_hdl(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_tx_beacon_hdl); } u8 rtw_mi_buddy_tx_beacon_hdl(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_sreset_adapter_hdl); } static u8 _rtw_mi_set_tx_beacon_cmd(_adapter *adapter, void *data) { struct mlme_priv *pmlmepriv = &adapter->mlmepriv; if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { if (pmlmepriv->update_bcn == _TRUE) set_tx_beacon_cmd(adapter); } return _TRUE; } u8 rtw_mi_set_tx_beacon_cmd(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_set_tx_beacon_cmd); } u8 rtw_mi_buddy_set_tx_beacon_cmd(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_set_tx_beacon_cmd); } #ifdef CONFIG_P2P static u8 _rtw_mi_p2p_chk_state(_adapter *adapter, void *data) { struct wifidirect_info *pwdinfo = &(adapter->wdinfo); enum P2P_STATE state = *(enum P2P_STATE *)data; return rtw_p2p_chk_state(pwdinfo, state); } u8 rtw_mi_p2p_chk_state(_adapter *padapter, enum P2P_STATE p2p_state) { u8 in_data = p2p_state; return _rtw_mi_process(padapter, _FALSE, &in_data, _rtw_mi_p2p_chk_state); } u8 rtw_mi_buddy_p2p_chk_state(_adapter *padapter, enum P2P_STATE p2p_state) { u8 in_data = p2p_state; return _rtw_mi_process(padapter, _TRUE, &in_data, _rtw_mi_p2p_chk_state); } static u8 _rtw_mi_stay_in_p2p_mode(_adapter *adapter, void *data) { struct wifidirect_info *pwdinfo = &(adapter->wdinfo); if (rtw_p2p_role(pwdinfo) != P2P_ROLE_DISABLE) return _TRUE; return _FALSE; } u8 rtw_mi_stay_in_p2p_mode(_adapter *padapter) { return _rtw_mi_process(padapter, _FALSE, NULL, _rtw_mi_stay_in_p2p_mode); } u8 rtw_mi_buddy_stay_in_p2p_mode(_adapter *padapter) { return _rtw_mi_process(padapter, _TRUE, NULL, _rtw_mi_stay_in_p2p_mode); } #endif /*CONFIG_P2P*/ _adapter *rtw_get_iface_by_id(_adapter *padapter, u8 iface_id) { _adapter *iface = NULL; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); if ((padapter == NULL) || (iface_id >= CONFIG_IFACE_NUMBER)) { rtw_warn_on(1); return iface; } return dvobj->padapters[iface_id]; } _adapter *rtw_get_iface_by_macddr(_adapter *padapter, u8 *mac_addr) { int i; _adapter *iface = NULL; u8 bmatch = _FALSE; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && (_rtw_memcmp(mac_addr, adapter_mac_addr(iface), ETH_ALEN))) { bmatch = _TRUE; break; } } if (bmatch) return iface; else return NULL; } _adapter *rtw_get_iface_by_hwport(_adapter *padapter, u8 hw_port) { int i; _adapter *iface = NULL; u8 bmatch = _FALSE; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && (hw_port == iface->hw_port)) { bmatch = _TRUE; break; } } if (bmatch) return iface; else return NULL; } /*#define CONFIG_SKB_ALLOCATED*/ #define DBG_SKB_PROCESS #ifdef DBG_SKB_PROCESS void rtw_dbg_skb_process(_adapter *padapter, union recv_frame *precvframe, union recv_frame *pcloneframe) { _pkt *pkt_copy, *pkt_org; pkt_org = precvframe->u.hdr.pkt; pkt_copy = pcloneframe->u.hdr.pkt; /* RTW_INFO("%s ===== ORG SKB =====\n", __func__); RTW_INFO(" SKB head(%p)\n", pkt_org->head); RTW_INFO(" SKB data(%p)\n", pkt_org->data); RTW_INFO(" SKB tail(%p)\n", pkt_org->tail); RTW_INFO(" SKB end(%p)\n", pkt_org->end); RTW_INFO(" recv frame head(%p)\n", precvframe->u.hdr.rx_head); RTW_INFO(" recv frame data(%p)\n", precvframe->u.hdr.rx_data); RTW_INFO(" recv frame tail(%p)\n", precvframe->u.hdr.rx_tail); RTW_INFO(" recv frame end(%p)\n", precvframe->u.hdr.rx_end); RTW_INFO("%s ===== COPY SKB =====\n", __func__); RTW_INFO(" SKB head(%p)\n", pkt_copy->head); RTW_INFO(" SKB data(%p)\n", pkt_copy->data); RTW_INFO(" SKB tail(%p)\n", pkt_copy->tail); RTW_INFO(" SKB end(%p)\n", pkt_copy->end); RTW_INFO(" recv frame head(%p)\n", pcloneframe->u.hdr.rx_head); RTW_INFO(" recv frame data(%p)\n", pcloneframe->u.hdr.rx_data); RTW_INFO(" recv frame tail(%p)\n", pcloneframe->u.hdr.rx_tail); RTW_INFO(" recv frame end(%p)\n", pcloneframe->u.hdr.rx_end); */ /* RTW_INFO("%s => recv_frame adapter(%p,%p)\n", __func__, precvframe->u.hdr.adapter, pcloneframe->u.hdr.adapter); RTW_INFO("%s => recv_frame dev(%p,%p)\n", __func__, pkt_org->dev , pkt_copy->dev); RTW_INFO("%s => recv_frame len(%d,%d)\n", __func__, precvframe->u.hdr.len, pcloneframe->u.hdr.len); */ if (precvframe->u.hdr.len != pcloneframe->u.hdr.len) RTW_INFO("%s [WARN] recv_frame length(%d:%d) compare failed\n", __func__, precvframe->u.hdr.len, pcloneframe->u.hdr.len); if (_rtw_memcmp(&precvframe->u.hdr.attrib, &pcloneframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)) == _FALSE) RTW_INFO("%s [WARN] recv_frame attrib compare failed\n", __func__); if (_rtw_memcmp(precvframe->u.hdr.rx_data, pcloneframe->u.hdr.rx_data, precvframe->u.hdr.len) == _FALSE) RTW_INFO("%s [WARN] recv_frame rx_data compare failed\n", __func__); } #endif static s32 _rtw_mi_buddy_clone_bcmc_packet(_adapter *adapter, union recv_frame *precvframe, u8 *pphy_status, union recv_frame *pcloneframe) { s32 ret = _SUCCESS; u8 *pbuf = precvframe->u.hdr.rx_data; struct rx_pkt_attrib *pattrib = NULL; HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter); if (pcloneframe) { pcloneframe->u.hdr.adapter = adapter; _rtw_init_listhead(&pcloneframe->u.hdr.list); pcloneframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf for new arch.*/ pcloneframe->u.hdr.len = 0; _rtw_memcpy(&pcloneframe->u.hdr.attrib, &precvframe->u.hdr.attrib, sizeof(struct rx_pkt_attrib)); pattrib = &pcloneframe->u.hdr.attrib; #ifdef CONFIG_SKB_ALLOCATED if (rtw_os_alloc_recvframe(adapter, pcloneframe, pbuf, NULL) == _SUCCESS) #else if (rtw_os_recvframe_duplicate_skb(adapter, pcloneframe, precvframe->u.hdr.pkt) == _SUCCESS) #endif { #ifdef CONFIG_SKB_ALLOCATED recvframe_put(pcloneframe, pattrib->pkt_len); #endif #ifdef DBG_SKB_PROCESS rtw_dbg_skb_process(adapter, precvframe, pcloneframe); #endif if (pattrib->physt && pphy_status) rx_query_phy_status(pcloneframe, pphy_status); ret = rtw_recv_entry(pcloneframe); } else { ret = -1; RTW_INFO("%s()-%d: rtw_os_alloc_recvframe() failed!\n", __func__, __LINE__); } } return ret; } void rtw_mi_buddy_clone_bcmc_packet(_adapter *padapter, union recv_frame *precvframe, u8 *pphy_status) { int i; s32 ret = _SUCCESS; _adapter *iface = NULL; union recv_frame *pcloneframe = NULL; struct recv_priv *precvpriv = &padapter->recvpriv;/*primary_padapter*/ _queue *pfree_recv_queue = &precvpriv->free_recv_queue; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if ((iface) && rtw_is_adapter_up(iface)) { if (iface == padapter) continue; pcloneframe = rtw_alloc_recvframe(pfree_recv_queue); if (pcloneframe) { ret = _rtw_mi_buddy_clone_bcmc_packet(iface, precvframe, pphy_status, pcloneframe); if (_SUCCESS != ret) { if (ret == -1) rtw_free_recvframe(pcloneframe, pfree_recv_queue); /*RTW_INFO(ADPT_FMT"-clone BC/MC frame failed\n", ADPT_ARG(iface));*/ } } } } } #ifdef CONFIG_PCI_HCI /*API be created temporary for MI, caller is interrupt-handler, PCIE's interrupt handler cannot apply to multi-AP*/ _adapter *rtw_mi_get_ap_adapter(_adapter *padapter) { struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); int i; _adapter *iface = NULL; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if (!iface) continue; if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == _TRUE && check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) break; } return iface; } #endif void rtw_mi_update_ap_bmc_camid(_adapter *padapter, u8 camid_a, u8 camid_b) { #ifdef CONFIG_CONCURRENT_MODE struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj); int i; _adapter *iface = NULL; for (i = 0; i < dvobj->iface_nums; i++) { iface = dvobj->padapters[i]; if (!iface) continue; if (macid_ctl->iface_bmc[iface->iface_id] != INVALID_SEC_MAC_CAM_ID) { if (macid_ctl->iface_bmc[iface->iface_id] == camid_a) macid_ctl->iface_bmc[iface->iface_id] = camid_b; else if (macid_ctl->iface_bmc[iface->iface_id] == camid_b) macid_ctl->iface_bmc[iface->iface_id] = camid_a; iface->securitypriv.dot118021x_bmc_cam_id = macid_ctl->iface_bmc[iface->iface_id]; } } #endif }