mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 17:55:05 +03:00
1. Add custom roam parameters 2. Add path for power file 3. Add source tree path for Makefile 4. Add section in Makefile for TEGRA platform 5. Update permissions from 0755 to 0644 for files 6. Move roaming debug prints to RTW_INFO 7. Remove pr_debug redefinition 8. Move LOG_LEVEL to 0 Bug 4556940 Change-Id: Ic6de0172e6e866c6e81fa84685a929b60051ffce Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3140409 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3202806 GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com> Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
16963 lines
491 KiB
C
16963 lines
491 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2007 - 2017 Realtek Corporation.
|
|
*
|
|
* 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.
|
|
*
|
|
*****************************************************************************/
|
|
#define _HAL_COM_C_
|
|
|
|
#include <drv_types.h>
|
|
#include "hal_com_h2c.h"
|
|
|
|
#include "hal_data.h"
|
|
|
|
#ifdef RTW_HALMAC
|
|
#include "../../hal/hal_halmac.h"
|
|
#endif
|
|
|
|
void rtw_dump_fw_info(void *sel, _adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = NULL;
|
|
|
|
if (!adapter)
|
|
return;
|
|
|
|
hal_data = GET_HAL_DATA(adapter);
|
|
if (hal_data->bFWReady)
|
|
RTW_PRINT_SEL(sel, "FW VER -%d.%d\n", hal_data->firmware_version, hal_data->firmware_sub_version);
|
|
else
|
|
RTW_PRINT_SEL(sel, "FW not ready\n");
|
|
}
|
|
|
|
bool rsvd_page_cache_update_all(struct rsvd_page_cache_t *cache, u8 loc
|
|
, u8 txdesc_len, u32 page_size, u8 *info, u32 info_len)
|
|
{
|
|
u8 page_num;
|
|
bool modified = 0;
|
|
bool loc_mod = 0, size_mod = 0, page_num_mod = 0;
|
|
|
|
page_num = info_len ? (u8)PageNum(txdesc_len + info_len, page_size) : 0;
|
|
if (!info_len)
|
|
loc = 0;
|
|
|
|
if (cache->loc != loc) {
|
|
RTW_INFO("%s %s loc change (%u -> %u)\n"
|
|
, __func__, cache->name, cache->loc, loc);
|
|
loc_mod = 1;
|
|
}
|
|
if (cache->size != info_len) {
|
|
RTW_INFO("%s %s size change (%u -> %u)\n"
|
|
, __func__, cache->name, cache->size, info_len);
|
|
size_mod = 1;
|
|
}
|
|
if (cache->page_num != page_num) {
|
|
RTW_INFO("%s %s page_num change (%u -> %u)\n"
|
|
, __func__, cache->name, cache->page_num, page_num);
|
|
page_num_mod = 1;
|
|
}
|
|
|
|
if (info && info_len) {
|
|
if (cache->data) {
|
|
if (cache->size == info_len) {
|
|
if (_rtw_memcmp(cache->data, info, info_len) != _TRUE) {
|
|
RTW_INFO("%s %s data change\n", __func__, cache->name);
|
|
modified = 1;
|
|
}
|
|
} else
|
|
rsvd_page_cache_free_data(cache);
|
|
}
|
|
|
|
if (!cache->data) {
|
|
cache->data = rtw_malloc(info_len);
|
|
if (!cache->data) {
|
|
RTW_ERR("%s %s alloc data with size(%u) fail\n"
|
|
, __func__, cache->name, info_len);
|
|
rtw_warn_on(1);
|
|
} else {
|
|
RTW_INFO("%s %s alloc data with size(%u)\n"
|
|
, __func__, cache->name, info_len);
|
|
}
|
|
modified = 1;
|
|
}
|
|
|
|
if (cache->data && modified)
|
|
_rtw_memcpy(cache->data, info, info_len);
|
|
} else {
|
|
if (cache->data && size_mod)
|
|
rsvd_page_cache_free_data(cache);
|
|
}
|
|
|
|
cache->loc = loc;
|
|
cache->page_num = page_num;
|
|
cache->size = info_len;
|
|
|
|
return modified | loc_mod | size_mod | page_num_mod;
|
|
}
|
|
|
|
bool rsvd_page_cache_update_data(struct rsvd_page_cache_t *cache, u8 *info, u32 info_len)
|
|
{
|
|
bool modified = 0;
|
|
|
|
if (!info || !info_len) {
|
|
RTW_WARN("%s %s invalid input(info:%p, info_len:%u)\n"
|
|
, __func__, cache->name, info, info_len);
|
|
goto exit;
|
|
}
|
|
|
|
if (!cache->loc || !cache->page_num || !cache->size) {
|
|
RTW_ERR("%s %s layout not ready(loc:%u, page_num:%u, size:%u)\n"
|
|
, __func__, cache->name, cache->loc, cache->page_num, cache->size);
|
|
rtw_warn_on(1);
|
|
goto exit;
|
|
}
|
|
|
|
if (cache->size != info_len) {
|
|
RTW_ERR("%s %s size(%u) differ with info_len(%u)\n"
|
|
, __func__, cache->name, cache->size, info_len);
|
|
rtw_warn_on(1);
|
|
goto exit;
|
|
}
|
|
|
|
if (!cache->data) {
|
|
cache->data = rtw_zmalloc(cache->size);
|
|
if (!cache->data) {
|
|
RTW_ERR("%s %s alloc data with size(%u) fail\n"
|
|
, __func__, cache->name, cache->size);
|
|
rtw_warn_on(1);
|
|
goto exit;
|
|
} else {
|
|
RTW_INFO("%s %s alloc data with size(%u)\n"
|
|
, __func__, cache->name, info_len);
|
|
}
|
|
modified = 1;
|
|
}
|
|
|
|
if (_rtw_memcmp(cache->data, info, cache->size) == _FALSE) {
|
|
RTW_INFO("%s %s data change\n", __func__, cache->name);
|
|
_rtw_memcpy(cache->data, info, cache->size);
|
|
modified = 1;
|
|
}
|
|
|
|
exit:
|
|
return modified;
|
|
}
|
|
|
|
void rsvd_page_cache_free_data(struct rsvd_page_cache_t *cache)
|
|
{
|
|
if (cache->data) {
|
|
rtw_mfree(cache->data, cache->size);
|
|
cache->data = NULL;
|
|
}
|
|
}
|
|
|
|
void rsvd_page_cache_free(struct rsvd_page_cache_t *cache)
|
|
{
|
|
cache->loc = 0;
|
|
cache->page_num = 0;
|
|
rsvd_page_cache_free_data(cache);
|
|
cache->size = 0;
|
|
}
|
|
|
|
/* #define CONFIG_GTK_OL_DBG */
|
|
|
|
/*#define DBG_SEC_CAM_MOVE*/
|
|
#ifdef DBG_SEC_CAM_MOVE
|
|
void rtw_hal_move_sta_gk_to_dk(_adapter *adapter)
|
|
{
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
int cam_id, index = 0;
|
|
u8 *addr = NULL;
|
|
|
|
if (!MLME_IS_STA(adapter))
|
|
return;
|
|
|
|
addr = get_bssid(pmlmepriv);
|
|
|
|
if (addr == NULL) {
|
|
RTW_INFO("%s: get bssid MAC addr fail!!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
rtw_clean_dk_section(adapter);
|
|
|
|
do {
|
|
cam_id = rtw_camid_search(adapter, addr, index, 1);
|
|
|
|
if (cam_id == -1)
|
|
RTW_INFO("%s: cam_id: %d, key_id:%d\n", __func__, cam_id, index);
|
|
else
|
|
rtw_sec_cam_swap(adapter, cam_id, index);
|
|
|
|
index++;
|
|
} while (index < 4);
|
|
|
|
}
|
|
|
|
void rtw_hal_read_sta_dk_key(_adapter *adapter, u8 key_id)
|
|
{
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
|
|
_irqL irqL;
|
|
u8 get_key[16];
|
|
|
|
_rtw_memset(get_key, 0, sizeof(get_key));
|
|
|
|
if (key_id > 4) {
|
|
RTW_INFO("%s [ERROR] gtk_keyindex:%d invalid\n", __func__, key_id);
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
rtw_sec_read_cam_ent(adapter, key_id, NULL, NULL, get_key);
|
|
|
|
/*update key into related sw variable*/
|
|
_enter_critical_bh(&cam_ctl->lock, &irqL);
|
|
if (_rtw_camid_is_gk(adapter, key_id)) {
|
|
RTW_INFO("[HW KEY] -Key-id:%d "KEY_FMT"\n", key_id, KEY_ARG(get_key));
|
|
RTW_INFO("[cam_cache KEY] - Key-id:%d "KEY_FMT"\n", key_id, KEY_ARG(&dvobj->cam_cache[key_id].key));
|
|
}
|
|
_exit_critical_bh(&cam_ctl->lock, &irqL);
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
|
|
char rtw_phy_para_file_path[PATH_LENGTH_MAX];
|
|
#endif
|
|
|
|
void dump_chip_info(HAL_VERSION ChipVersion)
|
|
{
|
|
int cnt = 0;
|
|
u8 buf[128] = {0};
|
|
|
|
if (IS_8188E(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188E_");
|
|
else if (IS_8188F(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188F_");
|
|
else if (IS_8188GTV(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188GTV_");
|
|
else if (IS_8812_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8812_");
|
|
else if (IS_8192E(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8192E_");
|
|
else if (IS_8821_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8821_");
|
|
else if (IS_8723B_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723B_");
|
|
else if (IS_8703B_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8703B_");
|
|
else if (IS_8723D_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723D_");
|
|
else if (IS_8814A_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8814A_");
|
|
else if (IS_8822B_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8822B_");
|
|
else if (IS_8821C_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8821C_");
|
|
else if (IS_8710B_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8710B_");
|
|
else if (IS_8192F_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8192F_");
|
|
else if (IS_8822C_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8822C_");
|
|
else if (IS_8814B_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8814B_");
|
|
else if (IS_8723F_SERIES(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723F_");
|
|
else
|
|
cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_UNKNOWN_");
|
|
|
|
cnt += sprintf((buf + cnt), "%s", IS_NORMAL_CHIP(ChipVersion) ? "" : "T_");
|
|
|
|
if (IS_CHIP_VENDOR_TSMC(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "%s", "T");
|
|
else if (IS_CHIP_VENDOR_UMC(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "%s", "U");
|
|
else if (IS_CHIP_VENDOR_SMIC(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "%s", "S");
|
|
|
|
if (IS_A_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "1_");
|
|
else if (IS_B_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "2_");
|
|
else if (IS_C_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "3_");
|
|
else if (IS_D_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "4_");
|
|
else if (IS_E_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "5_");
|
|
else if (IS_F_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "6_");
|
|
else if (IS_I_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "9_");
|
|
else if (IS_J_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "10_");
|
|
else if (IS_K_CUT(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "11_");
|
|
else
|
|
cnt += sprintf((buf + cnt), "UNKNOWN_Cv(%d)_", ChipVersion.CUTVersion);
|
|
|
|
if (IS_1T1R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "1T1R_");
|
|
else if (IS_1T2R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "1T2R_");
|
|
else if (IS_2T2R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "2T2R_");
|
|
else if (IS_3T3R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "3T3R_");
|
|
else if (IS_3T4R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "3T4R_");
|
|
else if (IS_4T4R(ChipVersion))
|
|
cnt += sprintf((buf + cnt), "4T4R_");
|
|
else
|
|
cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_", ChipVersion.RFType);
|
|
|
|
cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
|
|
|
|
RTW_INFO("%s", buf);
|
|
}
|
|
|
|
u8 rtw_hal_get_port(_adapter *adapter)
|
|
{
|
|
u8 hw_port = get_hw_port(adapter);
|
|
#ifdef CONFIG_CLIENT_PORT_CFG
|
|
u8 clt_port = get_clt_port(adapter);
|
|
|
|
if (clt_port)
|
|
hw_port = clt_port;
|
|
|
|
#ifdef DBG_HW_PORT
|
|
if (MLME_IS_STA(adapter) && (adapter->client_id != MAX_CLIENT_PORT_NUM)) {
|
|
if(hw_port == CLT_PORT_INVALID) {
|
|
RTW_ERR(ADPT_FMT" @@@@@ Client port == 0 @@@@@\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
}
|
|
#ifdef CONFIG_AP_MODE
|
|
else if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {
|
|
if (hw_port != HW_PORT0) {
|
|
RTW_ERR(ADPT_FMT" @@@@@ AP / MESH port != 0 @@@@@\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
}
|
|
#endif
|
|
if (0)
|
|
RTW_INFO(ADPT_FMT" - HP:%d,CP:%d\n", ADPT_ARG(adapter), get_hw_port(adapter), get_clt_port(adapter));
|
|
#endif /*DBG_HW_PORT*/
|
|
|
|
#endif/*CONFIG_CLIENT_PORT_CFG*/
|
|
|
|
return hw_port;
|
|
}
|
|
|
|
#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
|
|
|
|
/*
|
|
* Description:
|
|
* Use hardware(efuse), driver parameter(registry) and default channel plan
|
|
* to decide which one should be used.
|
|
*
|
|
* Parameters:
|
|
* padapter pointer of adapter
|
|
* hw_alpha2 country code from HW (efuse/eeprom/mapfile)
|
|
* hw_chplan channel plan from HW (efuse/eeprom/mapfile)
|
|
* BIT[7] software configure mode; 0:Enable, 1:disable
|
|
* BIT[6:0] Channel Plan
|
|
* sw_alpha2 country code from HW (registry/module param)
|
|
* sw_chplan channel plan from SW (registry/module param)
|
|
* AutoLoadFail efuse autoload fail or not
|
|
*
|
|
*/
|
|
void hal_com_config_channel_plan(
|
|
PADAPTER padapter,
|
|
const char *hw_alpha2,
|
|
u8 hw_chplan,
|
|
u8 hw_chplan_6g,
|
|
BOOLEAN AutoLoadFail
|
|
)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
u8 force_hw_chplan = _FALSE;
|
|
|
|
#ifdef CONFIG_HEXFILE_CHANNEL_PLAN
|
|
if (rtw_get_channel_plan_from_file(RTW_HEXFILE_NAME)) {
|
|
RTW_WARN("get channel plan hexfile fail\n");
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* autoload fail, by pass all hw settings
|
|
*/
|
|
if (AutoLoadFail == _TRUE) {
|
|
hw_alpha2 = NULL;
|
|
hw_chplan = RTW_CHPLAN_UNSPECIFIED;
|
|
goto init;
|
|
}
|
|
|
|
/*
|
|
* treat {0xFF, 0xFF} as unspecified
|
|
*/
|
|
if (hw_alpha2 && strncmp(hw_alpha2, "\xFF\xFF", 2) == 0)
|
|
hw_alpha2 = NULL;
|
|
|
|
/*
|
|
* treat 0xFF as invalid value, bypass hw_chplan & force_hw_chplan parsing
|
|
* and check hw setting with only country code
|
|
*/
|
|
if (hw_chplan == 0xFF) {
|
|
hw_chplan = RTW_CHPLAN_UNSPECIFIED;
|
|
goto init;
|
|
}
|
|
|
|
#ifndef CONFIG_FORCE_SW_CHANNEL_PLAN
|
|
if (hw_chplan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
|
|
force_hw_chplan = _TRUE;
|
|
#endif
|
|
hw_chplan &= (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
|
|
|
|
init:
|
|
rtw_rfctl_decide_init_chplan(adapter_to_rfctl(padapter), hw_alpha2, hw_chplan, hw_chplan_6g, force_hw_chplan);
|
|
}
|
|
|
|
BOOLEAN
|
|
HAL_IsLegalChannel(
|
|
PADAPTER Adapter,
|
|
u32 Channel
|
|
)
|
|
{
|
|
BOOLEAN bLegalChannel = _TRUE;
|
|
|
|
if (Channel > 14) {
|
|
if (is_supported_5g(Adapter->registrypriv.wireless_mode) == _FALSE) {
|
|
bLegalChannel = _FALSE;
|
|
RTW_INFO("Channel > 14 but wireless_mode do not support 5G\n");
|
|
}
|
|
} else if ((Channel <= 14) && (Channel >= 1)) {
|
|
if (IsSupported24G(Adapter->registrypriv.wireless_mode) == _FALSE) {
|
|
bLegalChannel = _FALSE;
|
|
RTW_INFO("(Channel <= 14) && (Channel >=1) but wireless_mode do not support 2.4G\n");
|
|
}
|
|
} else {
|
|
bLegalChannel = _FALSE;
|
|
RTW_INFO("Channel is Invalid !!!\n");
|
|
}
|
|
|
|
return bLegalChannel;
|
|
}
|
|
|
|
static const u8 _MRateToHwRate[MGN_UNKNOWN] = {
|
|
[MGN_1M] = DESC_RATE1M,
|
|
[MGN_2M] = DESC_RATE2M,
|
|
[MGN_5_5M] = DESC_RATE5_5M,
|
|
[MGN_11M] = DESC_RATE11M,
|
|
[MGN_6M] = DESC_RATE6M,
|
|
[MGN_9M] = DESC_RATE9M,
|
|
[MGN_12M] = DESC_RATE12M,
|
|
[MGN_18M] = DESC_RATE18M,
|
|
[MGN_24M] = DESC_RATE24M,
|
|
[MGN_36M] = DESC_RATE36M,
|
|
[MGN_48M] = DESC_RATE48M,
|
|
[MGN_54M] = DESC_RATE54M,
|
|
[MGN_MCS0] = DESC_RATEMCS0,
|
|
[MGN_MCS1] = DESC_RATEMCS1,
|
|
[MGN_MCS2] = DESC_RATEMCS2,
|
|
[MGN_MCS3] = DESC_RATEMCS3,
|
|
[MGN_MCS4] = DESC_RATEMCS4,
|
|
[MGN_MCS5] = DESC_RATEMCS5,
|
|
[MGN_MCS6] = DESC_RATEMCS6,
|
|
[MGN_MCS7] = DESC_RATEMCS7,
|
|
[MGN_MCS8] = DESC_RATEMCS8,
|
|
[MGN_MCS9] = DESC_RATEMCS9,
|
|
[MGN_MCS10] = DESC_RATEMCS10,
|
|
[MGN_MCS11] = DESC_RATEMCS11,
|
|
[MGN_MCS12] = DESC_RATEMCS12,
|
|
[MGN_MCS13] = DESC_RATEMCS13,
|
|
[MGN_MCS14] = DESC_RATEMCS14,
|
|
[MGN_MCS15] = DESC_RATEMCS15,
|
|
[MGN_MCS16] = DESC_RATEMCS16,
|
|
[MGN_MCS17] = DESC_RATEMCS17,
|
|
[MGN_MCS18] = DESC_RATEMCS18,
|
|
[MGN_MCS19] = DESC_RATEMCS19,
|
|
[MGN_MCS20] = DESC_RATEMCS20,
|
|
[MGN_MCS21] = DESC_RATEMCS21,
|
|
[MGN_MCS22] = DESC_RATEMCS22,
|
|
[MGN_MCS23] = DESC_RATEMCS23,
|
|
[MGN_MCS24] = DESC_RATEMCS24,
|
|
[MGN_MCS25] = DESC_RATEMCS25,
|
|
[MGN_MCS26] = DESC_RATEMCS26,
|
|
[MGN_MCS27] = DESC_RATEMCS27,
|
|
[MGN_MCS28] = DESC_RATEMCS28,
|
|
[MGN_MCS29] = DESC_RATEMCS29,
|
|
[MGN_MCS30] = DESC_RATEMCS30,
|
|
[MGN_MCS31] = DESC_RATEMCS31,
|
|
[MGN_VHT1SS_MCS0] = DESC_RATEVHTSS1MCS0,
|
|
[MGN_VHT1SS_MCS1] = DESC_RATEVHTSS1MCS1,
|
|
[MGN_VHT1SS_MCS2] = DESC_RATEVHTSS1MCS2,
|
|
[MGN_VHT1SS_MCS3] = DESC_RATEVHTSS1MCS3,
|
|
[MGN_VHT1SS_MCS4] = DESC_RATEVHTSS1MCS4,
|
|
[MGN_VHT1SS_MCS5] = DESC_RATEVHTSS1MCS5,
|
|
[MGN_VHT1SS_MCS6] = DESC_RATEVHTSS1MCS6,
|
|
[MGN_VHT1SS_MCS7] = DESC_RATEVHTSS1MCS7,
|
|
[MGN_VHT1SS_MCS8] = DESC_RATEVHTSS1MCS8,
|
|
[MGN_VHT1SS_MCS9] = DESC_RATEVHTSS1MCS9,
|
|
[MGN_VHT2SS_MCS0] = DESC_RATEVHTSS2MCS0,
|
|
[MGN_VHT2SS_MCS1] = DESC_RATEVHTSS2MCS1,
|
|
[MGN_VHT2SS_MCS2] = DESC_RATEVHTSS2MCS2,
|
|
[MGN_VHT2SS_MCS3] = DESC_RATEVHTSS2MCS3,
|
|
[MGN_VHT2SS_MCS4] = DESC_RATEVHTSS2MCS4,
|
|
[MGN_VHT2SS_MCS5] = DESC_RATEVHTSS2MCS5,
|
|
[MGN_VHT2SS_MCS6] = DESC_RATEVHTSS2MCS6,
|
|
[MGN_VHT2SS_MCS7] = DESC_RATEVHTSS2MCS7,
|
|
[MGN_VHT2SS_MCS8] = DESC_RATEVHTSS2MCS8,
|
|
[MGN_VHT2SS_MCS9] = DESC_RATEVHTSS2MCS9,
|
|
[MGN_VHT3SS_MCS0] = DESC_RATEVHTSS3MCS0,
|
|
[MGN_VHT3SS_MCS1] = DESC_RATEVHTSS3MCS1,
|
|
[MGN_VHT3SS_MCS2] = DESC_RATEVHTSS3MCS2,
|
|
[MGN_VHT3SS_MCS3] = DESC_RATEVHTSS3MCS3,
|
|
[MGN_VHT3SS_MCS4] = DESC_RATEVHTSS3MCS4,
|
|
[MGN_VHT3SS_MCS5] = DESC_RATEVHTSS3MCS5,
|
|
[MGN_VHT3SS_MCS6] = DESC_RATEVHTSS3MCS6,
|
|
[MGN_VHT3SS_MCS7] = DESC_RATEVHTSS3MCS7,
|
|
[MGN_VHT3SS_MCS8] = DESC_RATEVHTSS3MCS8,
|
|
[MGN_VHT3SS_MCS9] = DESC_RATEVHTSS3MCS9,
|
|
[MGN_VHT4SS_MCS0] = DESC_RATEVHTSS4MCS0,
|
|
[MGN_VHT4SS_MCS1] = DESC_RATEVHTSS4MCS1,
|
|
[MGN_VHT4SS_MCS2] = DESC_RATEVHTSS4MCS2,
|
|
[MGN_VHT4SS_MCS3] = DESC_RATEVHTSS4MCS3,
|
|
[MGN_VHT4SS_MCS4] = DESC_RATEVHTSS4MCS4,
|
|
[MGN_VHT4SS_MCS5] = DESC_RATEVHTSS4MCS5,
|
|
[MGN_VHT4SS_MCS6] = DESC_RATEVHTSS4MCS6,
|
|
[MGN_VHT4SS_MCS7] = DESC_RATEVHTSS4MCS7,
|
|
[MGN_VHT4SS_MCS8] = DESC_RATEVHTSS4MCS8,
|
|
[MGN_VHT4SS_MCS9] = DESC_RATEVHTSS4MCS9,
|
|
};
|
|
|
|
u8 MRateToHwRate(enum MGN_RATE rate)
|
|
{
|
|
u8 hw_rate = DESC_RATE1M; /* default value, also is zero */
|
|
|
|
if (rate < MGN_UNKNOWN)
|
|
hw_rate = _MRateToHwRate[rate];
|
|
|
|
if (rate != MGN_1M && hw_rate == DESC_RATE1M)
|
|
RTW_WARN("Invalid rate 0x%x in %s\n", rate, __FUNCTION__);
|
|
|
|
return hw_rate;
|
|
}
|
|
|
|
const char * const _HDATA_RATE[DESC_RATE_NUM + 1] = {
|
|
[DESC_RATE1M] = "CCK_1M",
|
|
[DESC_RATE2M] = "CCK_2M",
|
|
[DESC_RATE5_5M] = "CCK5_5M",
|
|
[DESC_RATE11M] = "CCK_11M",
|
|
[DESC_RATE6M] = "OFDM_6M",
|
|
[DESC_RATE9M] = "OFDM_9M",
|
|
[DESC_RATE12M] = "OFDM_12M",
|
|
[DESC_RATE18M] = "OFDM_18M",
|
|
[DESC_RATE24M] = "OFDM_24M",
|
|
[DESC_RATE36M] = "OFDM_36M",
|
|
[DESC_RATE48M] = "OFDM_48M",
|
|
[DESC_RATE54M] = "OFDM_54M",
|
|
[DESC_RATEMCS0] = "MCS0",
|
|
[DESC_RATEMCS1] = "MCS1",
|
|
[DESC_RATEMCS2] = "MCS2",
|
|
[DESC_RATEMCS3] = "MCS3",
|
|
[DESC_RATEMCS4] = "MCS4",
|
|
[DESC_RATEMCS5] = "MCS5",
|
|
[DESC_RATEMCS6] = "MCS6",
|
|
[DESC_RATEMCS7] = "MCS7",
|
|
[DESC_RATEMCS8] = "MCS8",
|
|
[DESC_RATEMCS9] = "MCS9",
|
|
[DESC_RATEMCS10] = "MCS10",
|
|
[DESC_RATEMCS11] = "MCS11",
|
|
[DESC_RATEMCS12] = "MCS12",
|
|
[DESC_RATEMCS13] = "MCS13",
|
|
[DESC_RATEMCS14] = "MCS14",
|
|
[DESC_RATEMCS15] = "MCS15",
|
|
[DESC_RATEMCS16] = "MCS16",
|
|
[DESC_RATEMCS17] = "MCS17",
|
|
[DESC_RATEMCS18] = "MCS18",
|
|
[DESC_RATEMCS19] = "MCS19",
|
|
[DESC_RATEMCS20] = "MCS20",
|
|
[DESC_RATEMCS21] = "MCS21",
|
|
[DESC_RATEMCS22] = "MCS22",
|
|
[DESC_RATEMCS23] = "MCS23",
|
|
[DESC_RATEMCS24] = "MCS24",
|
|
[DESC_RATEMCS25] = "MCS25",
|
|
[DESC_RATEMCS26] = "MCS26",
|
|
[DESC_RATEMCS27] = "MCS27",
|
|
[DESC_RATEMCS28] = "MCS28",
|
|
[DESC_RATEMCS29] = "MCS29",
|
|
[DESC_RATEMCS30] = "MCS30",
|
|
[DESC_RATEMCS31] = "MCS31",
|
|
[DESC_RATEVHTSS1MCS0] = "VHT1SMCS0",
|
|
[DESC_RATEVHTSS1MCS1] = "VHT1SMCS1",
|
|
[DESC_RATEVHTSS1MCS2] = "VHT1SMCS2",
|
|
[DESC_RATEVHTSS1MCS3] = "VHT1SMCS3",
|
|
[DESC_RATEVHTSS1MCS4] = "VHT1SMCS4",
|
|
[DESC_RATEVHTSS1MCS5] = "VHT1SMCS5",
|
|
[DESC_RATEVHTSS1MCS6] = "VHT1SMCS6",
|
|
[DESC_RATEVHTSS1MCS7] = "VHT1SMCS7",
|
|
[DESC_RATEVHTSS1MCS8] = "VHT1SMCS8",
|
|
[DESC_RATEVHTSS1MCS9] = "VHT1SMCS9",
|
|
[DESC_RATEVHTSS2MCS0] = "VHT2SMCS0",
|
|
[DESC_RATEVHTSS2MCS1] = "VHT2SMCS1",
|
|
[DESC_RATEVHTSS2MCS2] = "VHT2SMCS2",
|
|
[DESC_RATEVHTSS2MCS3] = "VHT2SMCS3",
|
|
[DESC_RATEVHTSS2MCS4] = "VHT2SMCS4",
|
|
[DESC_RATEVHTSS2MCS5] = "VHT2SMCS5",
|
|
[DESC_RATEVHTSS2MCS6] = "VHT2SMCS6",
|
|
[DESC_RATEVHTSS2MCS7] = "VHT2SMCS7",
|
|
[DESC_RATEVHTSS2MCS8] = "VHT2SMCS8",
|
|
[DESC_RATEVHTSS2MCS9] = "VHT2SMCS9",
|
|
[DESC_RATEVHTSS3MCS0] = "VHT3SMCS0",
|
|
[DESC_RATEVHTSS3MCS1] = "VHT3SMCS1",
|
|
[DESC_RATEVHTSS3MCS2] = "VHT3SMCS2",
|
|
[DESC_RATEVHTSS3MCS3] = "VHT3SMCS3",
|
|
[DESC_RATEVHTSS3MCS4] = "VHT3SMCS4",
|
|
[DESC_RATEVHTSS3MCS5] = "VHT3SMCS5",
|
|
[DESC_RATEVHTSS3MCS6] = "VHT3SMCS6",
|
|
[DESC_RATEVHTSS3MCS7] = "VHT3SMCS7",
|
|
[DESC_RATEVHTSS3MCS8] = "VHT3SMCS8",
|
|
[DESC_RATEVHTSS3MCS9] = "VHT3SMCS9",
|
|
[DESC_RATEVHTSS4MCS0] = "VHT4SMCS0",
|
|
[DESC_RATEVHTSS4MCS1] = "VHT4SMCS1",
|
|
[DESC_RATEVHTSS4MCS2] = "VHT4SMCS2",
|
|
[DESC_RATEVHTSS4MCS3] = "VHT4SMCS3",
|
|
[DESC_RATEVHTSS4MCS4] = "VHT4SMCS4",
|
|
[DESC_RATEVHTSS4MCS5] = "VHT4SMCS5",
|
|
[DESC_RATEVHTSS4MCS6] = "VHT4SMCS6",
|
|
[DESC_RATEVHTSS4MCS7] = "VHT4SMCS7",
|
|
[DESC_RATEVHTSS4MCS8] = "VHT4SMCS8",
|
|
[DESC_RATEVHTSS4MCS9] = "VHT4SMCS9",
|
|
[DESC_RATE_NUM] = "UNKNOWN",
|
|
};
|
|
|
|
static const u8 _hw_rate_to_m_rate[DESC_RATE_NUM] = {
|
|
[DESC_RATE1M] = MGN_1M,
|
|
[DESC_RATE2M] = MGN_2M,
|
|
[DESC_RATE5_5M] = MGN_5_5M,
|
|
[DESC_RATE11M] = MGN_11M,
|
|
[DESC_RATE6M] = MGN_6M,
|
|
[DESC_RATE9M] = MGN_9M,
|
|
[DESC_RATE12M] = MGN_12M,
|
|
[DESC_RATE18M] = MGN_18M,
|
|
[DESC_RATE24M] = MGN_24M,
|
|
[DESC_RATE36M] = MGN_36M,
|
|
[DESC_RATE48M] = MGN_48M,
|
|
[DESC_RATE54M] = MGN_54M,
|
|
[DESC_RATEMCS0] = MGN_MCS0,
|
|
[DESC_RATEMCS1] = MGN_MCS1,
|
|
[DESC_RATEMCS2] = MGN_MCS2,
|
|
[DESC_RATEMCS3] = MGN_MCS3,
|
|
[DESC_RATEMCS4] = MGN_MCS4,
|
|
[DESC_RATEMCS5] = MGN_MCS5,
|
|
[DESC_RATEMCS6] = MGN_MCS6,
|
|
[DESC_RATEMCS7] = MGN_MCS7,
|
|
[DESC_RATEMCS8] = MGN_MCS8,
|
|
[DESC_RATEMCS9] = MGN_MCS9,
|
|
[DESC_RATEMCS10] = MGN_MCS10,
|
|
[DESC_RATEMCS11] = MGN_MCS11,
|
|
[DESC_RATEMCS12] = MGN_MCS12,
|
|
[DESC_RATEMCS13] = MGN_MCS13,
|
|
[DESC_RATEMCS14] = MGN_MCS14,
|
|
[DESC_RATEMCS15] = MGN_MCS15,
|
|
[DESC_RATEMCS16] = MGN_MCS16,
|
|
[DESC_RATEMCS17] = MGN_MCS17,
|
|
[DESC_RATEMCS18] = MGN_MCS18,
|
|
[DESC_RATEMCS19] = MGN_MCS19,
|
|
[DESC_RATEMCS20] = MGN_MCS20,
|
|
[DESC_RATEMCS21] = MGN_MCS21,
|
|
[DESC_RATEMCS22] = MGN_MCS22,
|
|
[DESC_RATEMCS23] = MGN_MCS23,
|
|
[DESC_RATEMCS24] = MGN_MCS24,
|
|
[DESC_RATEMCS25] = MGN_MCS25,
|
|
[DESC_RATEMCS26] = MGN_MCS26,
|
|
[DESC_RATEMCS27] = MGN_MCS27,
|
|
[DESC_RATEMCS28] = MGN_MCS28,
|
|
[DESC_RATEMCS29] = MGN_MCS29,
|
|
[DESC_RATEMCS30] = MGN_MCS30,
|
|
[DESC_RATEMCS31] = MGN_MCS31,
|
|
[DESC_RATEVHTSS1MCS0] = MGN_VHT1SS_MCS0,
|
|
[DESC_RATEVHTSS1MCS1] = MGN_VHT1SS_MCS1,
|
|
[DESC_RATEVHTSS1MCS2] = MGN_VHT1SS_MCS2,
|
|
[DESC_RATEVHTSS1MCS3] = MGN_VHT1SS_MCS3,
|
|
[DESC_RATEVHTSS1MCS4] = MGN_VHT1SS_MCS4,
|
|
[DESC_RATEVHTSS1MCS5] = MGN_VHT1SS_MCS5,
|
|
[DESC_RATEVHTSS1MCS6] = MGN_VHT1SS_MCS6,
|
|
[DESC_RATEVHTSS1MCS7] = MGN_VHT1SS_MCS7,
|
|
[DESC_RATEVHTSS1MCS8] = MGN_VHT1SS_MCS8,
|
|
[DESC_RATEVHTSS1MCS9] = MGN_VHT1SS_MCS9,
|
|
[DESC_RATEVHTSS2MCS0] = MGN_VHT2SS_MCS0,
|
|
[DESC_RATEVHTSS2MCS1] = MGN_VHT2SS_MCS1,
|
|
[DESC_RATEVHTSS2MCS2] = MGN_VHT2SS_MCS2,
|
|
[DESC_RATEVHTSS2MCS3] = MGN_VHT2SS_MCS3,
|
|
[DESC_RATEVHTSS2MCS4] = MGN_VHT2SS_MCS4,
|
|
[DESC_RATEVHTSS2MCS5] = MGN_VHT2SS_MCS5,
|
|
[DESC_RATEVHTSS2MCS6] = MGN_VHT2SS_MCS6,
|
|
[DESC_RATEVHTSS2MCS7] = MGN_VHT2SS_MCS7,
|
|
[DESC_RATEVHTSS2MCS8] = MGN_VHT2SS_MCS8,
|
|
[DESC_RATEVHTSS2MCS9] = MGN_VHT2SS_MCS9,
|
|
[DESC_RATEVHTSS3MCS0] = MGN_VHT3SS_MCS0,
|
|
[DESC_RATEVHTSS3MCS1] = MGN_VHT3SS_MCS1,
|
|
[DESC_RATEVHTSS3MCS2] = MGN_VHT3SS_MCS2,
|
|
[DESC_RATEVHTSS3MCS3] = MGN_VHT3SS_MCS3,
|
|
[DESC_RATEVHTSS3MCS4] = MGN_VHT3SS_MCS4,
|
|
[DESC_RATEVHTSS3MCS5] = MGN_VHT3SS_MCS5,
|
|
[DESC_RATEVHTSS3MCS6] = MGN_VHT3SS_MCS6,
|
|
[DESC_RATEVHTSS3MCS7] = MGN_VHT3SS_MCS7,
|
|
[DESC_RATEVHTSS3MCS8] = MGN_VHT3SS_MCS8,
|
|
[DESC_RATEVHTSS3MCS9] = MGN_VHT3SS_MCS9,
|
|
[DESC_RATEVHTSS4MCS0] = MGN_VHT4SS_MCS0,
|
|
[DESC_RATEVHTSS4MCS1] = MGN_VHT4SS_MCS1,
|
|
[DESC_RATEVHTSS4MCS2] = MGN_VHT4SS_MCS2,
|
|
[DESC_RATEVHTSS4MCS3] = MGN_VHT4SS_MCS3,
|
|
[DESC_RATEVHTSS4MCS4] = MGN_VHT4SS_MCS4,
|
|
[DESC_RATEVHTSS4MCS5] = MGN_VHT4SS_MCS5,
|
|
[DESC_RATEVHTSS4MCS6] = MGN_VHT4SS_MCS6,
|
|
[DESC_RATEVHTSS4MCS7] = MGN_VHT4SS_MCS7,
|
|
[DESC_RATEVHTSS4MCS8] = MGN_VHT4SS_MCS8,
|
|
[DESC_RATEVHTSS4MCS9] = MGN_VHT4SS_MCS9,
|
|
};
|
|
|
|
u8 hw_rate_to_m_rate(u8 hw_rate)
|
|
{
|
|
u8 rate = MGN_1M; /* default value */
|
|
|
|
if (hw_rate < DESC_RATE_NUM)
|
|
rate = _hw_rate_to_m_rate[hw_rate];
|
|
else
|
|
RTW_WARN("Invalid hw_rate 0x%x in %s\n", hw_rate, __FUNCTION__);
|
|
|
|
return rate;
|
|
}
|
|
|
|
#ifdef CONFIG_RTW_DEBUG
|
|
void dump_hw_rate_map_test(void *sel)
|
|
{
|
|
RATE_SECTION rs;
|
|
u8 hw_rate;
|
|
enum MGN_RATE m_rate;
|
|
int i;
|
|
|
|
for (rs = 0; rs < RATE_SECTION_NUM; rs++) {
|
|
for (i = 0; i < rates_by_sections[rs].rate_num; i++) {
|
|
hw_rate = MRateToHwRate(rates_by_sections[rs].rates[i]);
|
|
RTW_PRINT_SEL(sel, "m_rate:%s(%d) to hw_rate:%s(%d)\n"
|
|
, MGN_RATE_STR(rates_by_sections[rs].rates[i]), rates_by_sections[rs].rates[i]
|
|
, HDATA_RATE(hw_rate), hw_rate
|
|
);
|
|
}
|
|
if (rs == HT_4SS) { /* show MCS32 after MCS31 */
|
|
hw_rate = MRateToHwRate(MGN_MCS32);
|
|
RTW_PRINT_SEL(sel, "m_rate:%s(%d) to hw_rate:%s(%d)\n"
|
|
, MGN_RATE_STR(MGN_MCS32), MGN_MCS32
|
|
, HDATA_RATE(hw_rate), hw_rate
|
|
);
|
|
}
|
|
}
|
|
hw_rate = MRateToHwRate(MGN_UNKNOWN);
|
|
RTW_PRINT_SEL(sel, "m_rate:%s(%d) to hw_rate:%s(%d)\n"
|
|
, MGN_RATE_STR(MGN_UNKNOWN), MGN_UNKNOWN
|
|
, HDATA_RATE(hw_rate), hw_rate
|
|
);
|
|
|
|
for (i = DESC_RATE1M; i <= DESC_RATE_NUM; i++) {
|
|
m_rate = hw_rate_to_m_rate(i);
|
|
RTW_PRINT_SEL(sel, "hw_rate:%s(%d) to m_rate:%s(%d)\n"
|
|
, HDATA_RATE(i), i
|
|
, MGN_RATE_STR(m_rate), m_rate
|
|
);
|
|
}
|
|
}
|
|
#endif /* CONFIG_RTW_DEBUG */
|
|
|
|
void HalSetBrateCfg(
|
|
PADAPTER Adapter,
|
|
u8 *mBratesOS,
|
|
u16 *pBrateCfg)
|
|
{
|
|
u8 i, is_brate, brate;
|
|
|
|
for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
|
|
is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
|
|
brate = mBratesOS[i] & 0x7f;
|
|
|
|
if (is_brate) {
|
|
switch (brate) {
|
|
case IEEE80211_CCK_RATE_1MB:
|
|
*pBrateCfg |= RATE_1M;
|
|
break;
|
|
case IEEE80211_CCK_RATE_2MB:
|
|
*pBrateCfg |= RATE_2M;
|
|
break;
|
|
case IEEE80211_CCK_RATE_5MB:
|
|
*pBrateCfg |= RATE_5_5M;
|
|
break;
|
|
case IEEE80211_CCK_RATE_11MB:
|
|
*pBrateCfg |= RATE_11M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_6MB:
|
|
*pBrateCfg |= RATE_6M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_9MB:
|
|
*pBrateCfg |= RATE_9M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_12MB:
|
|
*pBrateCfg |= RATE_12M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_18MB:
|
|
*pBrateCfg |= RATE_18M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_24MB:
|
|
*pBrateCfg |= RATE_24M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_36MB:
|
|
*pBrateCfg |= RATE_36M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_48MB:
|
|
*pBrateCfg |= RATE_48M;
|
|
break;
|
|
case IEEE80211_OFDM_RATE_54MB:
|
|
*pBrateCfg |= RATE_54M;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_OneOutPipeMapping(
|
|
PADAPTER pAdapter
|
|
)
|
|
{
|
|
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
}
|
|
|
|
static void
|
|
_TwoOutPipeMapping(
|
|
PADAPTER pAdapter,
|
|
BOOLEAN bWIFICfg
|
|
)
|
|
{
|
|
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
|
|
|
|
if (bWIFICfg) { /* WMM */
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */
|
|
/* 0:ep_0 num, 1:ep_1 num */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
|
|
} else { /* typical setting */
|
|
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */
|
|
/* 0:ep_0 num, 1:ep_1 num */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void _ThreeOutPipeMapping(
|
|
PADAPTER pAdapter,
|
|
BOOLEAN bWIFICfg
|
|
)
|
|
{
|
|
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
|
|
|
|
if (bWIFICfg) { /* for WMM */
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
|
|
/* 0:H, 1:N, 2:L */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
|
|
} else { /* typical setting */
|
|
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
|
|
/* 0:H, 1:N, 2:L */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
}
|
|
|
|
}
|
|
#if 0
|
|
static void _FourOutPipeMapping(
|
|
PADAPTER pAdapter,
|
|
BOOLEAN bWIFICfg
|
|
)
|
|
{
|
|
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
|
|
|
|
if (bWIFICfg) { /* for WMM */
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
|
|
/* 0:H, 1:N, 2:L ,3:E */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[3];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
|
|
} else { /* typical setting */
|
|
|
|
|
|
/* BK, BE, VI, VO, BCN, CMD,MGT,HIGH,HCCA */
|
|
/* { 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
|
|
/* 0:H, 1:N, 2:L */
|
|
|
|
pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
|
|
pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
|
|
pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
|
|
pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
|
|
|
|
pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
|
|
pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
|
|
pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[3];/* HIGH */
|
|
pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
|
|
}
|
|
|
|
}
|
|
#endif
|
|
BOOLEAN
|
|
Hal_MappingOutPipe(
|
|
PADAPTER pAdapter,
|
|
u8 NumOutPipe
|
|
)
|
|
{
|
|
struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
|
|
|
|
BOOLEAN bWIFICfg = (pregistrypriv->wifi_spec) ? _TRUE : _FALSE;
|
|
|
|
BOOLEAN result = _TRUE;
|
|
|
|
switch (NumOutPipe) {
|
|
case 2:
|
|
_TwoOutPipeMapping(pAdapter, bWIFICfg);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
_ThreeOutPipeMapping(pAdapter, bWIFICfg);
|
|
break;
|
|
case 1:
|
|
_OneOutPipeMapping(pAdapter);
|
|
break;
|
|
default:
|
|
result = _FALSE;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
void rtw_hal_reqtxrpt(_adapter *padapter, u8 macid)
|
|
{
|
|
if (padapter->hal_func.reqtxrpt)
|
|
padapter->hal_func.reqtxrpt(padapter, macid);
|
|
}
|
|
|
|
int rtw_get_sta_tx_stat(_adapter *adapter, u8 mac_id, u8 *macaddr)
|
|
{
|
|
struct sta_priv *pstapriv_primary = &(GET_PRIMARY_ADAPTER(adapter))->stapriv;
|
|
struct submit_ctx gotc2h;
|
|
u8 cmd_ret;
|
|
int ret = _SUCCESS;
|
|
|
|
if (!adapter->hal_func.reqtxrpt) {
|
|
RTW_INFO("Not support.\n");
|
|
ret = RTW_NOT_SUPPORT;
|
|
goto exit;
|
|
}
|
|
|
|
if (pstapriv_primary->gotc2h != NULL) {
|
|
RTW_INFO("sta tx stat is processing.\n");
|
|
ret = RTW_BUSY;
|
|
goto exit;
|
|
}
|
|
|
|
rtw_sctx_init(&gotc2h, 60);
|
|
pstapriv_primary->gotc2h = &gotc2h;
|
|
_rtw_memcpy(pstapriv_primary->c2h_sta_mac, macaddr, ETH_ALEN);
|
|
pstapriv_primary->c2h_adapter_id = adapter->iface_id;
|
|
|
|
cmd_ret = rtw_reqtxrpt_cmd(adapter, mac_id);
|
|
if (cmd_ret != _SUCCESS) {
|
|
RTW_WARN("rtw_reqtxrpt_cmd fail\n");
|
|
ret = _FAIL;
|
|
} else
|
|
rtw_sctx_wait(&gotc2h, __func__);
|
|
|
|
enter_critical_bh(&pstapriv_primary->tx_rpt_lock);
|
|
pstapriv_primary->gotc2h = NULL;
|
|
exit_critical_bh(&pstapriv_primary->tx_rpt_lock);
|
|
|
|
if (cmd_ret == _SUCCESS && gotc2h.status != RTW_SCTX_DONE_SUCCESS) {
|
|
RTW_WARN("wait for C2H timeout, operation abort!!\n");
|
|
ret = _FAIL;
|
|
}
|
|
|
|
_rtw_memset(pstapriv_primary->c2h_sta_mac, 0, ETH_ALEN);
|
|
pstapriv_primary->c2h_adapter_id = CONFIG_IFACE_NUMBER;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
void rtw_hal_dump_macaddr(void *sel, _adapter *adapter)
|
|
{
|
|
int i;
|
|
_adapter *iface;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
u8 mac_addr[ETH_ALEN];
|
|
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
rtw_mbid_cam_dump(sel, __func__, adapter);
|
|
#else
|
|
rtw_mi_hal_dump_macaddr(sel, adapter);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* rtw_hal_set_hw_macaddr() - Set HW MAC address
|
|
* @adapter: struct PADAPTER
|
|
* @mac_addr: 6-bytes mac address
|
|
*
|
|
* Set Wifi Mac address by writing to the relative HW registers,
|
|
*
|
|
*/
|
|
void rtw_hal_set_hw_macaddr(PADAPTER adapter, u8 *mac_addr)
|
|
{
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
rtw_hal_change_macaddr_mbid(adapter, mac_addr);
|
|
#else
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_MAC_ADDR, mac_addr);
|
|
#endif
|
|
#ifdef CONFIG_RTW_DEBUG
|
|
rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter);
|
|
#endif
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
}
|
|
|
|
#ifdef RTW_HALMAC
|
|
void rtw_hal_hw_port_enable(_adapter *adapter)
|
|
{
|
|
#if 1
|
|
u8 port_enable = _TRUE;
|
|
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_PORT_CFG, &port_enable);
|
|
#else
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct rtw_halmac_bcn_ctrl bcn_ctrl;
|
|
|
|
_rtw_memset(&bcn_ctrl, 0, sizeof(struct rtw_halmac_bcn_ctrl));
|
|
bcn_ctrl.enable_bcn = 1;
|
|
bcn_ctrl.rx_bssid_fit = 1;
|
|
bcn_ctrl.rxbcn_rpt = 1;
|
|
|
|
/*rtw_halmac_get_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
|
|
struct rtw_halmac_bcn_ctrl *bcn_ctrl)*/
|
|
if (rtw_halmac_set_bcn_ctrl(dvobj, get_hw_port(adapter), &bcn_ctrl) == -1) {
|
|
RTW_ERR(ADPT_FMT" - hw port(%d) enable fail!!\n", ADPT_ARG(adapter), get_hw_port(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
#endif
|
|
}
|
|
void rtw_hal_hw_port_disable(_adapter *adapter)
|
|
{
|
|
u8 port_enable = _FALSE;
|
|
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_PORT_CFG, &port_enable);
|
|
}
|
|
|
|
void rtw_restore_hw_port_cfg(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
int i;
|
|
_adapter *iface;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (iface)
|
|
rtw_hal_hw_port_enable(iface);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void rtw_mi_set_mac_addr(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
rtw_mi_set_mbid_cam(adapter);
|
|
#else
|
|
int i;
|
|
_adapter *iface;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (iface)
|
|
rtw_hal_set_hwreg(iface, HW_VAR_MAC_ADDR, adapter_mac_addr(iface));
|
|
}
|
|
#endif
|
|
if (0)
|
|
rtw_hal_dump_macaddr(RTW_DBGDUMP, adapter);
|
|
}
|
|
|
|
void rtw_init_hal_com_default_value(PADAPTER Adapter)
|
|
{
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
|
|
struct registry_priv *regsty = adapter_to_regsty(Adapter);
|
|
|
|
pHalData->AntDetection = 1;
|
|
pHalData->antenna_test = _FALSE;
|
|
pHalData->RegIQKFWOffload = regsty->iqk_fw_offload;
|
|
pHalData->ch_switch_offload = regsty->ch_switch_offload;
|
|
pHalData->multi_ch_switch_mode = 0;
|
|
#ifdef RTW_REDUCE_SCAN_SWITCH_CH_TIME
|
|
if (pHalData->ch_switch_offload == 0)
|
|
pHalData->ch_switch_offload = 1;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_FW_C2H_REG
|
|
void c2h_evt_clear(_adapter *adapter)
|
|
{
|
|
rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
|
|
}
|
|
|
|
s32 c2h_evt_read_88xx(_adapter *adapter, u8 *buf)
|
|
{
|
|
s32 ret = _FAIL;
|
|
int i;
|
|
u8 trigger;
|
|
|
|
if (buf == NULL)
|
|
goto exit;
|
|
|
|
trigger = rtw_read8(adapter, REG_C2HEVT_CLEAR);
|
|
|
|
if (trigger == C2H_EVT_HOST_CLOSE) {
|
|
goto exit; /* Not ready */
|
|
} else if (trigger != C2H_EVT_FW_CLOSE) {
|
|
goto clear_evt; /* Not a valid value */
|
|
}
|
|
|
|
_rtw_memset(buf, 0, C2H_REG_LEN);
|
|
|
|
/* Read ID, LEN, SEQ */
|
|
SET_C2H_ID_88XX(buf, rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL));
|
|
SET_C2H_SEQ_88XX(buf, rtw_read8(adapter, REG_C2HEVT_CMD_SEQ_88XX));
|
|
SET_C2H_PLEN_88XX(buf, rtw_read8(adapter, REG_C2HEVT_CMD_LEN_88XX));
|
|
|
|
if (0) {
|
|
RTW_INFO("%s id=0x%02x, seq=%u, plen=%u, trigger=0x%02x\n", __func__
|
|
, C2H_ID_88XX(buf), C2H_SEQ_88XX(buf), C2H_PLEN_88XX(buf), trigger);
|
|
}
|
|
|
|
/* Read the content */
|
|
for (i = 0; i < C2H_PLEN_88XX(buf); i++)
|
|
*(C2H_PAYLOAD_88XX(buf) + i) = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i);
|
|
|
|
RTW_DBG_DUMP("payload: ", C2H_PAYLOAD_88XX(buf), C2H_PLEN_88XX(buf));
|
|
|
|
ret = _SUCCESS;
|
|
|
|
clear_evt:
|
|
/*
|
|
* Clear event to notify FW we have read the command.
|
|
* If this field isn't clear, the FW won't update the next command message.
|
|
*/
|
|
c2h_evt_clear(adapter);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_FW_C2H_REG */
|
|
|
|
#ifdef CONFIG_FW_C2H_PKT
|
|
#ifndef DBG_C2H_PKT_PRE_HDL
|
|
#define DBG_C2H_PKT_PRE_HDL 0
|
|
#endif
|
|
#ifndef DBG_C2H_PKT_HDL
|
|
#define DBG_C2H_PKT_HDL 0
|
|
#endif
|
|
void rtw_hal_c2h_pkt_pre_hdl(_adapter *adapter, u8 *buf, u16 len)
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
/* TODO: extract hal_mac IC's code here*/
|
|
#else
|
|
u8 parse_fail = 0;
|
|
u8 hdl_here = 0;
|
|
s32 ret = _FAIL;
|
|
u8 id, seq, plen;
|
|
u8 *payload;
|
|
|
|
if (rtw_hal_c2h_pkt_hdr_parse(adapter, buf, len, &id, &seq, &plen, &payload) != _SUCCESS) {
|
|
parse_fail = 1;
|
|
goto exit;
|
|
}
|
|
|
|
hdl_here = rtw_hal_c2h_id_handle_directly(adapter, id, seq, plen, payload) == _TRUE ? 1 : 0;
|
|
if (hdl_here)
|
|
ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
|
|
else
|
|
ret = rtw_c2h_packet_wk_cmd(adapter, buf, len);
|
|
|
|
exit:
|
|
if (parse_fail)
|
|
RTW_ERR("%s parse fail, buf=%p, len=:%u\n", __func__, buf, len);
|
|
else if (ret != _SUCCESS || DBG_C2H_PKT_PRE_HDL > 0) {
|
|
RTW_PRINT("%s: id=0x%02x, seq=%u, plen=%u, %s %s\n", __func__, id, seq, plen
|
|
, hdl_here ? "handle" : "enqueue"
|
|
, ret == _SUCCESS ? "ok" : "fail"
|
|
);
|
|
if (DBG_C2H_PKT_PRE_HDL >= 2)
|
|
RTW_PRINT_DUMP("dump: ", buf, len);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void rtw_hal_c2h_pkt_hdl(_adapter *adapter, u8 *buf, u16 len)
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
adapter->hal_func.hal_mac_c2h_handler(adapter, buf, len);
|
|
#else
|
|
u8 parse_fail = 0;
|
|
u8 bypass = 0;
|
|
s32 ret = _FAIL;
|
|
u8 id, seq, plen;
|
|
u8 *payload;
|
|
|
|
if (rtw_hal_c2h_pkt_hdr_parse(adapter, buf, len, &id, &seq, &plen, &payload) != _SUCCESS) {
|
|
parse_fail = 1;
|
|
goto exit;
|
|
}
|
|
|
|
#ifdef CONFIG_WOWLAN
|
|
if (adapter_to_pwrctl(adapter)->wowlan_mode == _TRUE) {
|
|
bypass = 1;
|
|
ret = _SUCCESS;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
ret = rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
|
|
|
|
exit:
|
|
if (parse_fail)
|
|
RTW_ERR("%s parse fail, buf=%p, len=:%u\n", __func__, buf, len);
|
|
else if (ret != _SUCCESS || bypass || DBG_C2H_PKT_HDL > 0) {
|
|
RTW_PRINT("%s: id=0x%02x, seq=%u, plen=%u, %s %s\n", __func__, id, seq, plen
|
|
, !bypass ? "handle" : "bypass"
|
|
, ret == _SUCCESS ? "ok" : "fail"
|
|
);
|
|
if (DBG_C2H_PKT_HDL >= 2)
|
|
RTW_PRINT_DUMP("dump: ", buf, len);
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* CONFIG_FW_C2H_PKT */
|
|
|
|
void c2h_iqk_offload(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct submit_ctx *iqk_sctx = &hal_data->iqk_sctx;
|
|
|
|
RTW_INFO("IQK offload finish in %dms\n", rtw_get_passing_time_ms(iqk_sctx->submit_time));
|
|
if (0)
|
|
RTW_INFO_DUMP("C2H_IQK_FINISH: ", data, len);
|
|
|
|
rtw_sctx_done(&iqk_sctx);
|
|
}
|
|
|
|
int c2h_iqk_offload_wait(_adapter *adapter, u32 timeout_ms)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct submit_ctx *iqk_sctx = &hal_data->iqk_sctx;
|
|
|
|
iqk_sctx->submit_time = rtw_get_current_time();
|
|
iqk_sctx->timeout_ms = timeout_ms;
|
|
iqk_sctx->status = RTW_SCTX_SUBMITTED;
|
|
|
|
return rtw_sctx_wait(iqk_sctx, __func__);
|
|
}
|
|
|
|
#ifdef CONFIG_FW_OFFLOAD_SET_TXPWR_IDX
|
|
void c2h_txpwr_idx_offload_done(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct submit_ctx *sctx = &hal_data->txpwr_idx_offload_sctx;
|
|
|
|
if (0)
|
|
RTW_INFO("txpwr_idx offload finish in %dms\n", rtw_get_passing_time_ms(sctx->submit_time));
|
|
rtw_sctx_done(&sctx);
|
|
}
|
|
|
|
int c2h_txpwr_idx_offload_wait(_adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct submit_ctx *sctx = &hal_data->txpwr_idx_offload_sctx;
|
|
|
|
return rtw_sctx_wait(sctx, __func__);
|
|
}
|
|
#endif
|
|
|
|
#define GET_C2H_MAC_HIDDEN_RPT_UUID_X(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 0, 0, 8)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_UUID_Y(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 1, 0, 8)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_UUID_Z(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 2, 0, 5)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_UUID_CRC(_data) LE_BITS_TO_2BYTE(((u8 *)(_data)) + 2, 5, 11)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_HCI_TYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 0, 4)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_PACKAGE_TYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 4, 3)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_TR_SWITCH(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 7, 1)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_WL_FUNC(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 5, 0, 4)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_HW_STYPE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 5, 4, 4)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_BW(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 0, 3)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_ANT_NUM(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 5, 3)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_80211_PROTOCOL(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 2, 2)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_NIC_ROUTER(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 6, 2)
|
|
|
|
#ifndef DBG_C2H_MAC_HIDDEN_RPT_HANDLE
|
|
#define DBG_C2H_MAC_HIDDEN_RPT_HANDLE 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTW_MAC_HIDDEN_RPT
|
|
int c2h_mac_hidden_rpt_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
enum rf_type rf_type;
|
|
u8 tx_path_num, rx_path_num;
|
|
int ret = _FAIL;
|
|
|
|
u8 uuid_x;
|
|
u8 uuid_y;
|
|
u8 uuid_z;
|
|
u16 uuid_crc;
|
|
|
|
u8 hci_type;
|
|
u8 package_type;
|
|
u8 tr_switch;
|
|
u8 wl_func;
|
|
u8 hw_stype;
|
|
u8 bw;
|
|
u8 ss_num = 4;
|
|
u8 ant_num;
|
|
u8 protocol;
|
|
u8 nic;
|
|
|
|
int i;
|
|
|
|
if (len < MAC_HIDDEN_RPT_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, MAC_HIDDEN_RPT_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
uuid_x = GET_C2H_MAC_HIDDEN_RPT_UUID_X(data);
|
|
uuid_y = GET_C2H_MAC_HIDDEN_RPT_UUID_Y(data);
|
|
uuid_z = GET_C2H_MAC_HIDDEN_RPT_UUID_Z(data);
|
|
uuid_crc = GET_C2H_MAC_HIDDEN_RPT_UUID_CRC(data);
|
|
|
|
hci_type = GET_C2H_MAC_HIDDEN_RPT_HCI_TYPE(data);
|
|
package_type = GET_C2H_MAC_HIDDEN_RPT_PACKAGE_TYPE(data);
|
|
|
|
tr_switch = GET_C2H_MAC_HIDDEN_RPT_TR_SWITCH(data);
|
|
|
|
wl_func = GET_C2H_MAC_HIDDEN_RPT_WL_FUNC(data);
|
|
hw_stype = GET_C2H_MAC_HIDDEN_RPT_HW_STYPE(data);
|
|
|
|
bw = GET_C2H_MAC_HIDDEN_RPT_BW(data);
|
|
ant_num = GET_C2H_MAC_HIDDEN_RPT_ANT_NUM(data);
|
|
|
|
protocol = GET_C2H_MAC_HIDDEN_RPT_80211_PROTOCOL(data);
|
|
nic = GET_C2H_MAC_HIDDEN_RPT_NIC_ROUTER(data);
|
|
|
|
if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE) {
|
|
for (i = 0; i < len; i++)
|
|
RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i));
|
|
|
|
RTW_PRINT("uuid x:0x%02x y:0x%02x z:0x%x crc:0x%x\n", uuid_x, uuid_y, uuid_z, uuid_crc);
|
|
RTW_PRINT("hci_type:0x%x\n", hci_type);
|
|
RTW_PRINT("package_type:0x%x\n", package_type);
|
|
RTW_PRINT("tr_switch:0x%x\n", tr_switch);
|
|
RTW_PRINT("wl_func:0x%x\n", wl_func);
|
|
RTW_PRINT("hw_stype:0x%x\n", hw_stype);
|
|
RTW_PRINT("bw:0x%x\n", bw);
|
|
RTW_PRINT("ant_num:0x%x\n", ant_num);
|
|
RTW_PRINT("protocol:0x%x\n", protocol);
|
|
RTW_PRINT("nic:0x%x\n", nic);
|
|
}
|
|
|
|
#if defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B)
|
|
if (IS_8822C_SERIES(hal_data->version_id) || IS_8814B_SERIES(hal_data->version_id)) {
|
|
#define GET_C2H_MAC_HIDDEN_RPT_SS_NUM(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 3, 2)
|
|
ss_num = GET_C2H_MAC_HIDDEN_RPT_SS_NUM(data);
|
|
|
|
if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE)
|
|
RTW_PRINT("ss_num:0x%x\n", ss_num);
|
|
|
|
if (ss_num == 0x03)
|
|
ss_num = 4;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_RTL8822C)
|
|
if (IS_8822C_SERIES(hal_data->version_id)) {
|
|
if (ant_num == 1)
|
|
hal_spec->rf_reg_trx_path_bmp = 0x22; /* 1T1R pathB */
|
|
if (hw_stype == 0xE)
|
|
hal_spec->max_tx_cnt = rtw_min(hal_spec->max_tx_cnt, 1); /* limit 1TX only */
|
|
}
|
|
#endif
|
|
hal_data->PackageType = package_type;
|
|
hal_spec->hci_type = hci_type;
|
|
hal_spec->wl_func &= mac_hidden_wl_func_to_hal_wl_func(wl_func);
|
|
hal_spec->bw_cap &= mac_hidden_max_bw_to_hal_bw_cap(bw);
|
|
hal_spec->proto_cap &= mac_hidden_proto_to_hal_proto_cap(protocol);
|
|
|
|
rf_type = rtw_chip_rftype_to_hal_rftype(adapter, 0);
|
|
if (!RF_TYPE_VALID(rf_type)) {
|
|
RTW_ERR("%s rtw_chip_rftype_to_hal_rftype failed\n", __func__);
|
|
goto exit;
|
|
}
|
|
hal_spec->rf_reg_path_avail_num = rtw_min(hal_spec->rf_reg_path_num, ant_num);
|
|
tx_path_num = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->rf_reg_path_avail_num);
|
|
rx_path_num = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rf_reg_path_avail_num);
|
|
hal_spec->rf_reg_trx_path_bmp = rtw_restrict_trx_path_bmp_by_trx_num_lmt(
|
|
hal_spec->rf_reg_trx_path_bmp, tx_path_num, rx_path_num, &tx_path_num, &rx_path_num);
|
|
if (!hal_spec->rf_reg_trx_path_bmp) {
|
|
RTW_ERR("%s rtw_restrict_trx_path_bmp_by_trx_num_lmt(0x%x, %u, %u) failed\n"
|
|
, __func__, hal_spec->rf_reg_trx_path_bmp, tx_path_num, rx_path_num);
|
|
goto exit;
|
|
}
|
|
hal_spec->rf_reg_path_avail_num = rtw_max(tx_path_num, rx_path_num);
|
|
|
|
/*
|
|
* RF TX path num >= max_tx_cnt >= tx_nss_num
|
|
* ex: RF TX path num(4) >= max_tx_cnt(2) >= tx_nss_num(1)
|
|
* Select at most 2 out of 4 TX RF path to do 1SS 2TX
|
|
*/
|
|
hal_spec->max_tx_cnt = rtw_min(hal_spec->max_tx_cnt, tx_path_num);
|
|
hal_spec->tx_nss_num = rtw_min(hal_spec->tx_nss_num, hal_spec->max_tx_cnt);
|
|
hal_spec->tx_nss_num = rtw_min(hal_spec->tx_nss_num, ss_num);
|
|
|
|
hal_spec->rx_nss_num = rtw_min(hal_spec->rx_nss_num, rx_path_num);
|
|
hal_spec->rx_nss_num = rtw_min(hal_spec->rx_nss_num, ss_num);
|
|
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
int c2h_mac_hidden_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
int ret = _FAIL;
|
|
|
|
int i;
|
|
|
|
if (len < MAC_HIDDEN_RPT_2_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, MAC_HIDDEN_RPT_2_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE) {
|
|
for (i = 0; i < len; i++)
|
|
RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i));
|
|
}
|
|
|
|
#if defined(CONFIG_RTL8188F) || defined(CONFIG_RTL8188GTV)
|
|
if (IS_8188F(hal_data->version_id) || IS_8188GTV(hal_data->version_id)) {
|
|
#define GET_C2H_MAC_HIDDEN_RPT_IRV(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 0, 0, 4)
|
|
u8 irv = GET_C2H_MAC_HIDDEN_RPT_IRV(data);
|
|
|
|
if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE)
|
|
RTW_PRINT("irv:0x%x\n", irv);
|
|
|
|
if(irv != 0xf)
|
|
hal_data->version_id.CUTVersion = irv;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_8723F)
|
|
if (IS_8723F_SERIES(hal_data->version_id)) {
|
|
#define GET_C2H_MAC_HIDDEN_RPT_BT_SUPPORT(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 0, 1)
|
|
#define GET_C2H_MAC_HIDDEN_RPT_5G_SUPPORT(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 1, 1)
|
|
|
|
struct hal_spec_t *hal_spec;
|
|
u8 bt_support = GET_C2H_MAC_HIDDEN_RPT_BT_SUPPORT(data);
|
|
u8 band_5g_support = GET_C2H_MAC_HIDDEN_RPT_5G_SUPPORT(data);
|
|
|
|
hal_spec = GET_HAL_SPEC(adapter);
|
|
|
|
if (DBG_C2H_MAC_HIDDEN_RPT_HANDLE) {
|
|
RTW_PRINT("bt support:%u\n", bt_support);
|
|
RTW_PRINT("band 5g support:%u\n", band_5g_support);
|
|
}
|
|
|
|
hal_spec->rfpath_num_5g = (band_5g_support ? hal_spec->rfpath_num_5g : 0);
|
|
if(!band_5g_support)
|
|
hal_spec->band_cap &= ~BAND_CAP_5G;
|
|
|
|
hal_data->EEPROMBluetoothCoexist = bt_support;
|
|
/* 0 : solo module, 1 : combo module */
|
|
hal_data->InterfaceSel = bt_support;
|
|
}
|
|
#endif
|
|
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
int hal_read_mac_hidden_rpt(_adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
|
|
int ret = _FAIL;
|
|
int ret_fwdl;
|
|
u8 mac_hidden_rpt[MAC_HIDDEN_RPT_LEN + MAC_HIDDEN_RPT_2_LEN] = {0};
|
|
systime start = rtw_get_current_time();
|
|
u32 cnt = 0;
|
|
u32 timeout_ms = 800;
|
|
u32 min_cnt = 10;
|
|
u8 id = C2H_DEFEATURE_RSVD;
|
|
int i;
|
|
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
|
|
u8 hci_type = rtw_get_intf_type(adapter);
|
|
|
|
if ((hci_type == RTW_USB || hci_type == RTW_PCIE)
|
|
&& !rtw_is_hw_init_completed(adapter))
|
|
rtw_hal_power_on(adapter);
|
|
#endif
|
|
|
|
/* inform FW mac hidden rpt from reg is needed */
|
|
rtw_write8(adapter, REG_C2HEVT_MSG_NORMAL, C2H_DEFEATURE_RSVD);
|
|
|
|
/* download FW */
|
|
pHalData->not_xmitframe_fw_dl = 1;
|
|
ret_fwdl = rtw_hal_fw_dl(adapter, _FALSE);
|
|
pHalData->not_xmitframe_fw_dl = 0;
|
|
if (ret_fwdl != _SUCCESS)
|
|
goto mac_hidden_rpt_hdl;
|
|
|
|
/* polling for data ready */
|
|
start = rtw_get_current_time();
|
|
do {
|
|
cnt++;
|
|
id = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL);
|
|
if (id == C2H_MAC_HIDDEN_RPT || RTW_CANNOT_IO(adapter))
|
|
break;
|
|
rtw_msleep_os(10);
|
|
} while (rtw_get_passing_time_ms(start) < timeout_ms || cnt < min_cnt);
|
|
|
|
if (id == C2H_MAC_HIDDEN_RPT) {
|
|
/* read data */
|
|
for (i = 0; i < MAC_HIDDEN_RPT_LEN + MAC_HIDDEN_RPT_2_LEN; i++)
|
|
mac_hidden_rpt[i] = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 2 + i);
|
|
}
|
|
|
|
/* inform FW mac hidden rpt has read */
|
|
rtw_write8(adapter, REG_C2HEVT_MSG_NORMAL, C2H_DBG);
|
|
|
|
mac_hidden_rpt_hdl:
|
|
c2h_mac_hidden_rpt_hdl(adapter, mac_hidden_rpt, MAC_HIDDEN_RPT_LEN);
|
|
c2h_mac_hidden_rpt_2_hdl(adapter, mac_hidden_rpt + MAC_HIDDEN_RPT_LEN, MAC_HIDDEN_RPT_2_LEN);
|
|
|
|
if (ret_fwdl == _SUCCESS && id == C2H_MAC_HIDDEN_RPT)
|
|
ret = _SUCCESS;
|
|
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
|
|
if ((hci_type == RTW_USB || hci_type == RTW_PCIE)
|
|
&& !rtw_is_hw_init_completed(adapter))
|
|
rtw_hal_power_off(adapter);
|
|
#endif
|
|
|
|
RTW_INFO("%s %s! (%u, %dms), fwdl:%d, id:0x%02x\n", __func__
|
|
, (ret == _SUCCESS) ? "OK" : "Fail", cnt, rtw_get_passing_time_ms(start), ret_fwdl, id);
|
|
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_RTW_MAC_HIDDEN_RPT */
|
|
|
|
int c2h_defeature_dbg_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
int ret = _FAIL;
|
|
|
|
int i;
|
|
|
|
if (len < DEFEATURE_DBG_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, DEFEATURE_DBG_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
for (i = 0; i < len; i++)
|
|
RTW_PRINT("%s: 0x%02X\n", __func__, *(data + i));
|
|
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
#ifndef DBG_CUSTOMER_STR_RPT_HANDLE
|
|
#define DBG_CUSTOMER_STR_RPT_HANDLE 0
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTW_CUSTOMER_STR
|
|
s32 rtw_hal_h2c_customer_str_req(_adapter *adapter)
|
|
{
|
|
u8 h2c_data[H2C_CUSTOMER_STR_REQ_LEN] = {0};
|
|
|
|
SET_H2CCMD_CUSTOMER_STR_REQ_EN(h2c_data, 1);
|
|
return rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_REQ, H2C_CUSTOMER_STR_REQ_LEN, h2c_data);
|
|
}
|
|
|
|
#define C2H_CUSTOMER_STR_RPT_BYTE0(_data) ((u8 *)(_data))
|
|
#define C2H_CUSTOMER_STR_RPT_2_BYTE8(_data) ((u8 *)(_data))
|
|
|
|
int c2h_customer_str_rpt_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
int ret = _FAIL;
|
|
int i;
|
|
|
|
if (len < CUSTOMER_STR_RPT_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, CUSTOMER_STR_RPT_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
if (DBG_CUSTOMER_STR_RPT_HANDLE)
|
|
RTW_PRINT_DUMP("customer_str_rpt: ", data, CUSTOMER_STR_RPT_LEN);
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
if (dvobj->customer_str_sctx != NULL) {
|
|
if (dvobj->customer_str_sctx->status != RTW_SCTX_SUBMITTED)
|
|
RTW_WARN("%s invalid sctx.status:%d\n", __func__, dvobj->customer_str_sctx->status);
|
|
_rtw_memcpy(dvobj->customer_str, C2H_CUSTOMER_STR_RPT_BYTE0(data), CUSTOMER_STR_RPT_LEN);
|
|
dvobj->customer_str_sctx->status = RTX_SCTX_CSTR_WAIT_RPT2;
|
|
} else
|
|
RTW_WARN("%s sctx not set\n", __func__);
|
|
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
int c2h_customer_str_rpt_2_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
int ret = _FAIL;
|
|
int i;
|
|
|
|
if (len < CUSTOMER_STR_RPT_2_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, CUSTOMER_STR_RPT_2_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
if (DBG_CUSTOMER_STR_RPT_HANDLE)
|
|
RTW_PRINT_DUMP("customer_str_rpt_2: ", data, CUSTOMER_STR_RPT_2_LEN);
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
if (dvobj->customer_str_sctx != NULL) {
|
|
if (dvobj->customer_str_sctx->status != RTX_SCTX_CSTR_WAIT_RPT2)
|
|
RTW_WARN("%s rpt not ready\n", __func__);
|
|
_rtw_memcpy(dvobj->customer_str + CUSTOMER_STR_RPT_LEN, C2H_CUSTOMER_STR_RPT_2_BYTE8(data), CUSTOMER_STR_RPT_2_LEN);
|
|
rtw_sctx_done(&dvobj->customer_str_sctx);
|
|
} else
|
|
RTW_WARN("%s sctx not set\n", __func__);
|
|
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/* read customer str */
|
|
s32 rtw_hal_customer_str_read(_adapter *adapter, u8 *cs)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct submit_ctx sctx;
|
|
s32 ret = _SUCCESS;
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
if (dvobj->customer_str_sctx != NULL)
|
|
ret = _FAIL;
|
|
else {
|
|
rtw_sctx_init(&sctx, 2 * 1000);
|
|
dvobj->customer_str_sctx = &sctx;
|
|
}
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
if (ret == _FAIL) {
|
|
RTW_WARN("%s another handle ongoing\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_customer_str_req_cmd(adapter);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s read cmd fail\n", __func__);
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
dvobj->customer_str_sctx = NULL;
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
goto exit;
|
|
}
|
|
|
|
/* wait till rpt done or timeout */
|
|
rtw_sctx_wait(&sctx, __func__);
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
dvobj->customer_str_sctx = NULL;
|
|
if (sctx.status == RTW_SCTX_DONE_SUCCESS)
|
|
_rtw_memcpy(cs, dvobj->customer_str, RTW_CUSTOMER_STR_LEN);
|
|
else
|
|
ret = _FAIL;
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
s32 rtw_hal_h2c_customer_str_write(_adapter *adapter, const u8 *cs)
|
|
{
|
|
u8 h2c_data_w1[H2C_CUSTOMER_STR_W1_LEN] = {0};
|
|
u8 h2c_data_w2[H2C_CUSTOMER_STR_W2_LEN] = {0};
|
|
u8 h2c_data_w3[H2C_CUSTOMER_STR_W3_LEN] = {0};
|
|
s32 ret;
|
|
|
|
SET_H2CCMD_CUSTOMER_STR_W1_EN(h2c_data_w1, 1);
|
|
_rtw_memcpy(H2CCMD_CUSTOMER_STR_W1_BYTE0(h2c_data_w1), cs, 6);
|
|
|
|
SET_H2CCMD_CUSTOMER_STR_W2_EN(h2c_data_w2, 1);
|
|
_rtw_memcpy(H2CCMD_CUSTOMER_STR_W2_BYTE6(h2c_data_w2), cs + 6, 6);
|
|
|
|
SET_H2CCMD_CUSTOMER_STR_W3_EN(h2c_data_w3, 1);
|
|
_rtw_memcpy(H2CCMD_CUSTOMER_STR_W3_BYTE12(h2c_data_w3), cs + 6 + 6, 4);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W1, H2C_CUSTOMER_STR_W1_LEN, h2c_data_w1);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s w1 fail\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W2, H2C_CUSTOMER_STR_W2_LEN, h2c_data_w2);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s w2 fail\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_CUSTOMER_STR_W3, H2C_CUSTOMER_STR_W3_LEN, h2c_data_w3);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s w3 fail\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
/* write customer str and check if value reported is the same as requested */
|
|
s32 rtw_hal_customer_str_write(_adapter *adapter, const u8 *cs)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct submit_ctx sctx;
|
|
s32 ret = _SUCCESS;
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
if (dvobj->customer_str_sctx != NULL)
|
|
ret = _FAIL;
|
|
else {
|
|
rtw_sctx_init(&sctx, 2 * 1000);
|
|
dvobj->customer_str_sctx = &sctx;
|
|
}
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
if (ret == _FAIL) {
|
|
RTW_WARN("%s another handle ongoing\n", __func__);
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_customer_str_write_cmd(adapter, cs);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s write cmd fail\n", __func__);
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
dvobj->customer_str_sctx = NULL;
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_customer_str_req_cmd(adapter);
|
|
if (ret != _SUCCESS) {
|
|
RTW_WARN("%s read cmd fail\n", __func__);
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
dvobj->customer_str_sctx = NULL;
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
goto exit;
|
|
}
|
|
|
|
/* wait till rpt done or timeout */
|
|
rtw_sctx_wait(&sctx, __func__);
|
|
|
|
_enter_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
dvobj->customer_str_sctx = NULL;
|
|
if (sctx.status == RTW_SCTX_DONE_SUCCESS) {
|
|
if (_rtw_memcmp(cs, dvobj->customer_str, RTW_CUSTOMER_STR_LEN) != _TRUE) {
|
|
RTW_WARN("%s read back check fail\n", __func__);
|
|
RTW_INFO_DUMP("write req: ", cs, RTW_CUSTOMER_STR_LEN);
|
|
RTW_INFO_DUMP("read back: ", dvobj->customer_str, RTW_CUSTOMER_STR_LEN);
|
|
ret = _FAIL;
|
|
}
|
|
} else
|
|
ret = _FAIL;
|
|
_exit_critical_mutex(&dvobj->customer_str_mutex, NULL);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_RTW_CUSTOMER_STR */
|
|
|
|
#ifdef RTW_PER_CMD_SUPPORT_FW
|
|
#define H2C_REQ_PER_RPT_LEN 5
|
|
#define SET_H2CCMD_REQ_PER_RPT_GROUP_MACID(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 4, __Value)
|
|
#define SET_H2CCMD_REQ_PER_RPT_RPT_TYPE(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 4, 4, __Value)
|
|
#define SET_H2CCMD_REQ_PER_RPT_MACID_BMAP(__pH2CCmd, __Value) SET_BITS_TO_LE_4BYTE(__pH2CCmd + 1, 0, 32, __Value)
|
|
|
|
u8 rtw_hal_set_req_per_rpt_cmd(_adapter *adapter, u8 group_macid,
|
|
u8 rpt_type, u32 macid_bitmap)
|
|
{
|
|
u8 ret = _FAIL;
|
|
u8 cmd_buf[H2C_REQ_PER_RPT_LEN] = {0};
|
|
|
|
SET_H2CCMD_REQ_PER_RPT_GROUP_MACID(cmd_buf, group_macid);
|
|
SET_H2CCMD_REQ_PER_RPT_RPT_TYPE(cmd_buf, rpt_type);
|
|
SET_H2CCMD_REQ_PER_RPT_MACID_BMAP(cmd_buf, macid_bitmap);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_REQ_PER_RPT,
|
|
H2C_REQ_PER_RPT_LEN,
|
|
cmd_buf);
|
|
return ret;
|
|
}
|
|
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_MACID0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)), 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_PER0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 1, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_RATE0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 2, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_BW0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 3, 0, 2)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_TOTAL_PKT0(_data) LE_BITS_TO_2BYTE(((u8 *)(_data)) + 4, 0, 16)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_MACID1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_PER1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_RATE1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 8, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_BW1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 9, 0, 2)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE0_TOTAL_PKT1(_data) LE_BITS_TO_2BYTE(((u8 *)(_data)) + 10, 0, 16)
|
|
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_MACID0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)), 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_PER0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 1, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_RATE0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 2, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_BW0(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 3, 0, 2)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_MACID1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 4, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_PER1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 5, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_RATE1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 6, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_BW1(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 7, 0, 2)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_MACID2(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 8, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_PER2(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 9, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_RATE2(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 10, 0, 8)
|
|
#define GET_C2H_PER_RATE_RPT_TYPE1_BW2(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 11, 0, 2)
|
|
|
|
static void per_rate_rpt_update(_adapter *adapter, u8 mac_id,
|
|
u8 per, u8 rate,
|
|
u8 bw, u8 total_pkt)
|
|
{
|
|
#ifdef CONFIG_RTW_MESH
|
|
rtw_ieee80211s_update_metric(adapter, mac_id,
|
|
per, rate,
|
|
bw, total_pkt);
|
|
#endif
|
|
}
|
|
|
|
int c2h_per_rate_rpt_hdl(_adapter *adapter, u8 *data, u8 len)
|
|
{
|
|
/* Now only consider type0, since it covers all params in type1
|
|
* type0: mac_id, per, rate, bw, total_pkt
|
|
* type1: mac_id, per, rate, bw
|
|
*/
|
|
u8 mac_id[2] = {0}, per[2] = {0}, rate[2] = {0}, bw[2] = {0};
|
|
u16 total_pkt[2] = {0};
|
|
int ret = _FAIL, i, macid_cnt = 0;
|
|
|
|
/* type0:
|
|
* 1 macid includes 6 bytes info + 1 byte 0xff
|
|
* 2 macid includes 2*6 bytes info
|
|
*/
|
|
if (!(len == 7 || len == 12)) {
|
|
RTW_WARN("%s len(%u) != 7 or 12\n", __FUNCTION__, len);
|
|
goto exit;
|
|
}
|
|
|
|
macid_cnt++;
|
|
mac_id[0] = GET_C2H_PER_RATE_RPT_TYPE0_MACID0(data);
|
|
per[0] = GET_C2H_PER_RATE_RPT_TYPE0_PER0(data);
|
|
rate[0] = GET_C2H_PER_RATE_RPT_TYPE0_RATE0(data);
|
|
bw[0] = GET_C2H_PER_RATE_RPT_TYPE0_BW0(data);
|
|
total_pkt[0] = GET_C2H_PER_RATE_RPT_TYPE0_TOTAL_PKT0(data);
|
|
|
|
mac_id[1] = GET_C2H_PER_RATE_RPT_TYPE0_MACID1(data);
|
|
/* 0xff means no report anymore */
|
|
if (mac_id[1] == 0xff)
|
|
goto update_per;
|
|
if (len != 12) {
|
|
RTW_WARN("%s incorrect format\n", __FUNCTION__);
|
|
goto exit;
|
|
}
|
|
macid_cnt++;
|
|
per[1] = GET_C2H_PER_RATE_RPT_TYPE0_PER1(data);
|
|
rate[1] = GET_C2H_PER_RATE_RPT_TYPE0_RATE1(data);
|
|
bw[1] = GET_C2H_PER_RATE_RPT_TYPE0_BW1(data);
|
|
total_pkt[1] = GET_C2H_PER_RATE_RPT_TYPE0_TOTAL_PKT1(data);
|
|
|
|
update_per:
|
|
for (i = 0; i < macid_cnt; i++) {
|
|
RTW_DBG("[%s] type0 rpt[%d]: macid = %u, per = %u, "
|
|
"rate = %u, bw = %u, total_pkt = %u\n",
|
|
__FUNCTION__, i, mac_id[i], per[i],
|
|
rate[i], bw[i], total_pkt[i]);
|
|
per_rate_rpt_update(adapter, mac_id[i],
|
|
per[i], rate[i],
|
|
bw[i], total_pkt[i]);
|
|
}
|
|
ret = _SUCCESS;
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* RTW_PER_CMD_SUPPORT_FW */
|
|
|
|
#ifdef CONFIG_LPS_ACK
|
|
#define GET_C2H_LPS_STATUS_RPT_GET_ACTION(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)), 0, 8)
|
|
#define GET_C2H_LPS_STATUS_RPT_GET_STATUS_CODE(_data) LE_BITS_TO_1BYTE(((u8 *)(_data)) + 1, 0, 8)
|
|
#define DBG_LPS_STATUS_RPT 0
|
|
|
|
int c2h_lps_status_rpt(PADAPTER adapter, u8 *data, u8 len)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct submit_ctx *lps_sctx = &pwrpriv->lps_ack_sctx;
|
|
u8 action = 0;
|
|
s8 status_code = 0;
|
|
int ret = _FAIL;
|
|
|
|
if (len < LPS_STATUS_RPT_LEN) {
|
|
RTW_WARN("%s len(%u) < %d\n", __func__, len, LPS_STATUS_RPT_LEN);
|
|
goto exit;
|
|
}
|
|
|
|
action = GET_C2H_LPS_STATUS_RPT_GET_ACTION(data);
|
|
status_code = GET_C2H_LPS_STATUS_RPT_GET_STATUS_CODE(data);
|
|
|
|
/* action=0: report force leave null data status */
|
|
/* action=1: report Rf on status when receiving a SetPwrMode H2C with PwrState = RFON */
|
|
switch (action) {
|
|
case 0:
|
|
/* status code 0: success, 1: no ack, 2: timeout, 3: cancel */
|
|
case 1:
|
|
/* status code 0: FW has already turn to RFON */
|
|
pwrpriv->lps_ack_status = status_code;
|
|
|
|
if (DBG_LPS_STATUS_RPT)
|
|
RTW_INFO("=== [C2H LPS Action(%d)] LPS Status Code:%d ===\n", action, status_code);
|
|
|
|
break;
|
|
default:
|
|
RTW_INFO("UnKnown Action(%d) for C2H LPS RPT\n", action);
|
|
break;
|
|
}
|
|
|
|
rtw_sctx_done(&lps_sctx);
|
|
ret = _SUCCESS;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_LPS_ACK */
|
|
|
|
void rtw_hal_update_sta_wset(_adapter *adapter, struct sta_info *psta)
|
|
{
|
|
u8 w_set = 0;
|
|
|
|
if (psta->wireless_mode & WIRELESS_11B)
|
|
w_set |= WIRELESS_CCK;
|
|
|
|
if ((psta->wireless_mode & WIRELESS_11G) || (psta->wireless_mode & WIRELESS_11A))
|
|
w_set |= WIRELESS_OFDM;
|
|
|
|
if ((psta->wireless_mode & WIRELESS_11_24N) || (psta->wireless_mode & WIRELESS_11_5N))
|
|
w_set |= WIRELESS_HT;
|
|
|
|
if (psta->wireless_mode & WIRELESS_11AC)
|
|
w_set |= WIRELESS_VHT;
|
|
|
|
psta->cmn.support_wireless_set = w_set;
|
|
}
|
|
|
|
void rtw_hal_update_sta_mimo_type(_adapter *adapter, struct sta_info *psta)
|
|
{
|
|
s8 tx_nss, rx_nss;
|
|
|
|
tx_nss = rtw_get_sta_tx_nss(adapter, psta);
|
|
rx_nss = rtw_get_sta_rx_nss(adapter, psta);
|
|
if ((tx_nss == 1) && (rx_nss == 1))
|
|
psta->cmn.mimo_type = RF_1T1R;
|
|
else if ((tx_nss == 1) && (rx_nss == 2))
|
|
psta->cmn.mimo_type = RF_1T2R;
|
|
else if ((tx_nss == 2) && (rx_nss == 2))
|
|
psta->cmn.mimo_type = RF_2T2R;
|
|
else if ((tx_nss == 2) && (rx_nss == 3))
|
|
psta->cmn.mimo_type = RF_2T3R;
|
|
else if ((tx_nss == 2) && (rx_nss == 4))
|
|
psta->cmn.mimo_type = RF_2T4R;
|
|
else if ((tx_nss == 3) && (rx_nss == 3))
|
|
psta->cmn.mimo_type = RF_3T3R;
|
|
else if ((tx_nss == 3) && (rx_nss == 4))
|
|
psta->cmn.mimo_type = RF_3T4R;
|
|
else if ((tx_nss == 4) && (rx_nss == 4))
|
|
psta->cmn.mimo_type = RF_4T4R;
|
|
else
|
|
rtw_warn_on(1);
|
|
|
|
#ifdef CONFIG_CTRL_TXSS_BY_TP
|
|
rtw_ctrl_txss_update_mimo_type(adapter, psta);
|
|
#endif
|
|
|
|
RTW_INFO("STA - MAC_ID:%d, Tx - %d SS, Rx - %d SS\n",
|
|
psta->cmn.mac_id, tx_nss, rx_nss);
|
|
}
|
|
|
|
void rtw_hal_update_sta_smps_cap(_adapter *adapter, struct sta_info *psta)
|
|
{
|
|
/*Spatial Multiplexing Power Save*/
|
|
#if 0
|
|
if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
|
|
#ifdef CONFIG_80211N_HT
|
|
if (psta->htpriv.ht_option) {
|
|
if (psta->htpriv.smps_cap == 0)
|
|
psta->cmn.sm_ps = SM_PS_STATIC;
|
|
else if (psta->htpriv.smps_cap == 1)
|
|
psta->cmn.sm_ps = SM_PS_DYNAMIC;
|
|
else
|
|
psta->cmn.sm_ps = SM_PS_DISABLE;
|
|
}
|
|
#endif /* CONFIG_80211N_HT */
|
|
} else
|
|
#endif
|
|
psta->cmn.sm_ps = SM_PS_DISABLE;
|
|
|
|
RTW_INFO("STA - MAC_ID:%d, SM_PS %d\n",
|
|
psta->cmn.mac_id, psta->cmn.sm_ps);
|
|
}
|
|
|
|
u8 rtw_get_mgntframe_raid(_adapter *adapter, unsigned char network_type)
|
|
{
|
|
|
|
u8 raid;
|
|
if (IS_NEW_GENERATION_IC(adapter)) {
|
|
|
|
raid = (network_type & WIRELESS_11B) ? RATEID_IDX_B
|
|
: RATEID_IDX_G;
|
|
} else {
|
|
raid = (network_type & WIRELESS_11B) ? RATR_INX_WIRELESS_B
|
|
: RATR_INX_WIRELESS_G;
|
|
}
|
|
return raid;
|
|
}
|
|
|
|
void rtw_hal_update_sta_rate_mask(PADAPTER padapter, struct sta_info *psta)
|
|
{
|
|
u8 i, tx_nss;
|
|
u64 tx_ra_bitmap = 0, tmp64=0;
|
|
|
|
if (psta == NULL)
|
|
return;
|
|
|
|
/* b/g mode ra_bitmap */
|
|
for (i = 0; i < sizeof(psta->bssrateset); i++) {
|
|
if (psta->bssrateset[i])
|
|
tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i] & 0x7f);
|
|
}
|
|
|
|
#ifdef CONFIG_80211N_HT
|
|
if (padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode)) {
|
|
tx_nss = GET_HAL_TX_NSS(padapter);
|
|
#ifdef CONFIG_80211AC_VHT
|
|
if (psta->vhtpriv.vht_option) {
|
|
/* AC mode ra_bitmap */
|
|
tx_ra_bitmap |= (rtw_vht_mcs_map_to_bitmap(psta->vhtpriv.vht_mcs_map, tx_nss) << 12);
|
|
} else
|
|
#endif /* CONFIG_80211AC_VHT */
|
|
if (psta->htpriv.ht_option) {
|
|
/* n mode ra_bitmap */
|
|
|
|
/* Handling SMPS mode for AP MODE only*/
|
|
if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
|
|
/*0:static SMPS, 1:dynamic SMPS, 3:SMPS disabled, 2:reserved*/
|
|
if (psta->htpriv.smps_cap == 0 || psta->htpriv.smps_cap == 1) {
|
|
/*operate with only one active receive chain // 11n-MCS rate <= MSC7*/
|
|
tx_nss = rtw_min(tx_nss, 1);
|
|
}
|
|
}
|
|
|
|
tmp64 = rtw_ht_mcs_set_to_bitmap(psta->htpriv.ht_cap.supp_mcs_set, tx_nss);
|
|
tx_ra_bitmap |= (tmp64 << 12);
|
|
}
|
|
}
|
|
#endif /* CONFIG_80211N_HT */
|
|
psta->cmn.ra_info.ramask = tx_ra_bitmap;
|
|
psta->init_rate = get_highest_rate_idx(tx_ra_bitmap) & 0x3f;
|
|
}
|
|
|
|
void rtw_hal_update_sta_ra_info(PADAPTER padapter, struct sta_info *psta)
|
|
{
|
|
rtw_hal_update_sta_mimo_type(padapter, psta);
|
|
rtw_hal_update_sta_smps_cap(padapter, psta);
|
|
rtw_hal_update_sta_rate_mask(padapter, psta);
|
|
}
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_BCN_CTRL_ADDR
|
|
static u32 hw_bcn_ctrl_addr(_adapter *adapter, u8 hw_port)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
|
|
if (hw_port >= hal_spec->port_num) {
|
|
RTW_ERR(FUNC_ADPT_FMT" HW Port(%d) invalid\n", FUNC_ADPT_ARG(adapter), hw_port);
|
|
rtw_warn_on(1);
|
|
return 0;
|
|
}
|
|
|
|
switch (hw_port) {
|
|
case HW_PORT0:
|
|
return REG_BCN_CTRL;
|
|
case HW_PORT1:
|
|
return REG_BCN_CTRL_1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static void rtw_hal_get_msr(_adapter *adapter, u8 *net_type)
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
rtw_halmac_get_network_type(adapter_to_dvobj(adapter),
|
|
adapter->hw_port, net_type);
|
|
#else /* !RTW_HALMAC */
|
|
switch (adapter->hw_port) {
|
|
case HW_PORT0:
|
|
/*REG_CR - BIT[17:16]-Network Type for port 1*/
|
|
*net_type = rtw_read8(adapter, MSR) & 0x03;
|
|
break;
|
|
case HW_PORT1:
|
|
/*REG_CR - BIT[19:18]-Network Type for port 1*/
|
|
*net_type = (rtw_read8(adapter, MSR) & 0x0C) >> 2;
|
|
break;
|
|
#if defined(CONFIG_RTL8814A)
|
|
case HW_PORT2:
|
|
/*REG_CR_EXT- BIT[1:0]-Network Type for port 2*/
|
|
*net_type = rtw_read8(adapter, MSR1) & 0x03;
|
|
break;
|
|
case HW_PORT3:
|
|
/*REG_CR_EXT- BIT[3:2]-Network Type for port 3*/
|
|
*net_type = (rtw_read8(adapter, MSR1) & 0x0C) >> 2;
|
|
break;
|
|
case HW_PORT4:
|
|
/*REG_CR_EXT- BIT[5:4]-Network Type for port 4*/
|
|
*net_type = (rtw_read8(adapter, MSR1) & 0x30) >> 4;
|
|
break;
|
|
#endif /*#if defined(CONFIG_RTL8814A)*/
|
|
default:
|
|
RTW_INFO("[WARN] "ADPT_FMT"- invalid hw port -%d\n",
|
|
ADPT_ARG(adapter), adapter->hw_port);
|
|
rtw_warn_on(1);
|
|
break;
|
|
}
|
|
#endif /* !RTW_HALMAC */
|
|
}
|
|
|
|
#if defined(CONFIG_MI_WITH_MBSSID_CAM) && defined(CONFIG_MBSSID_CAM) /*For 2 hw ports - 88E/92E/8812/8821/8723B*/
|
|
static u8 rtw_hal_net_type_decision(_adapter *adapter, u8 net_type)
|
|
{
|
|
if ((adapter->hw_port == HW_PORT0) && (rtw_get_mbid_cam_entry_num(adapter))) {
|
|
if (net_type != _HW_STATE_NOLINK_)
|
|
return _HW_STATE_AP_;
|
|
}
|
|
return net_type;
|
|
}
|
|
#endif
|
|
static void rtw_hal_set_msr(_adapter *adapter, u8 net_type)
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
#if defined(CONFIG_MI_WITH_MBSSID_CAM) && defined(CONFIG_MBSSID_CAM)
|
|
net_type = rtw_hal_net_type_decision(adapter, net_type);
|
|
#endif
|
|
rtw_halmac_set_network_type(adapter_to_dvobj(adapter),
|
|
adapter->hw_port, net_type);
|
|
#else /* !RTW_HALMAC */
|
|
u8 val8 = 0;
|
|
|
|
switch (adapter->hw_port) {
|
|
case HW_PORT0:
|
|
#if defined(CONFIG_MI_WITH_MBSSID_CAM) && defined(CONFIG_MBSSID_CAM)
|
|
net_type = rtw_hal_net_type_decision(adapter, net_type);
|
|
#endif
|
|
/*REG_CR - BIT[17:16]-Network Type for port 0*/
|
|
val8 = rtw_read8(adapter, MSR) & 0x0C;
|
|
val8 |= net_type;
|
|
rtw_write8(adapter, MSR, val8);
|
|
break;
|
|
case HW_PORT1:
|
|
/*REG_CR - BIT[19:18]-Network Type for port 1*/
|
|
val8 = rtw_read8(adapter, MSR) & 0x03;
|
|
val8 |= net_type << 2;
|
|
rtw_write8(adapter, MSR, val8);
|
|
break;
|
|
#if defined(CONFIG_RTL8814A)
|
|
case HW_PORT2:
|
|
/*REG_CR_EXT- BIT[1:0]-Network Type for port 2*/
|
|
val8 = rtw_read8(adapter, MSR1) & 0xFC;
|
|
val8 |= net_type;
|
|
rtw_write8(adapter, MSR1, val8);
|
|
break;
|
|
case HW_PORT3:
|
|
/*REG_CR_EXT- BIT[3:2]-Network Type for port 3*/
|
|
val8 = rtw_read8(adapter, MSR1) & 0xF3;
|
|
val8 |= net_type << 2;
|
|
rtw_write8(adapter, MSR1, val8);
|
|
break;
|
|
case HW_PORT4:
|
|
/*REG_CR_EXT- BIT[5:4]-Network Type for port 4*/
|
|
val8 = rtw_read8(adapter, MSR1) & 0xCF;
|
|
val8 |= net_type << 4;
|
|
rtw_write8(adapter, MSR1, val8);
|
|
break;
|
|
#endif /* CONFIG_RTL8814A */
|
|
default:
|
|
RTW_INFO("[WARN] "ADPT_FMT"- invalid hw port -%d\n",
|
|
ADPT_ARG(adapter), adapter->hw_port);
|
|
rtw_warn_on(1);
|
|
break;
|
|
}
|
|
#endif /* !RTW_HALMAC */
|
|
}
|
|
|
|
#ifndef SEC_CAM_ACCESS_TIMEOUT_MS
|
|
#define SEC_CAM_ACCESS_TIMEOUT_MS 200
|
|
#endif
|
|
|
|
#ifndef DBG_SEC_CAM_ACCESS
|
|
#define DBG_SEC_CAM_ACCESS 0
|
|
#endif
|
|
|
|
u32 rtw_sec_read_cam(_adapter *adapter, u8 addr)
|
|
{
|
|
_mutex *mutex = &adapter_to_dvobj(adapter)->cam_ctl.sec_cam_access_mutex;
|
|
u32 rdata;
|
|
u32 cnt = 0;
|
|
systime start = 0, end = 0;
|
|
u8 timeout = 0;
|
|
u8 sr = 0;
|
|
|
|
_enter_critical_mutex(mutex, NULL);
|
|
|
|
rtw_write32(adapter, REG_CAMCMD, CAM_POLLINIG | addr);
|
|
|
|
start = rtw_get_current_time();
|
|
while (1) {
|
|
if (rtw_is_surprise_removed(adapter)) {
|
|
sr = 1;
|
|
break;
|
|
}
|
|
|
|
cnt++;
|
|
if (0 == (rtw_read32(adapter, REG_CAMCMD) & CAM_POLLINIG))
|
|
break;
|
|
|
|
if (rtw_get_passing_time_ms(start) > SEC_CAM_ACCESS_TIMEOUT_MS) {
|
|
timeout = 1;
|
|
break;
|
|
}
|
|
}
|
|
end = rtw_get_current_time();
|
|
|
|
rdata = rtw_read32(adapter, REG_CAMREAD);
|
|
|
|
_exit_critical_mutex(mutex, NULL);
|
|
|
|
if (DBG_SEC_CAM_ACCESS || timeout) {
|
|
RTW_INFO(FUNC_ADPT_FMT" addr:0x%02x, rdata:0x%08x, to:%u, polling:%u, %d ms\n"
|
|
, FUNC_ADPT_ARG(adapter), addr, rdata, timeout, cnt, rtw_get_time_interval_ms(start, end));
|
|
}
|
|
|
|
return rdata;
|
|
}
|
|
|
|
void rtw_sec_write_cam(_adapter *adapter, u8 addr, u32 wdata)
|
|
{
|
|
_mutex *mutex = &adapter_to_dvobj(adapter)->cam_ctl.sec_cam_access_mutex;
|
|
u32 cnt = 0;
|
|
systime start = 0, end = 0;
|
|
u8 timeout = 0;
|
|
u8 sr = 0;
|
|
|
|
_enter_critical_mutex(mutex, NULL);
|
|
|
|
rtw_write32(adapter, REG_CAMWRITE, wdata);
|
|
rtw_write32(adapter, REG_CAMCMD, CAM_POLLINIG | CAM_WRITE | addr);
|
|
|
|
start = rtw_get_current_time();
|
|
while (1) {
|
|
if (rtw_is_surprise_removed(adapter)) {
|
|
sr = 1;
|
|
break;
|
|
}
|
|
|
|
cnt++;
|
|
if (0 == (rtw_read32(adapter, REG_CAMCMD) & CAM_POLLINIG))
|
|
break;
|
|
|
|
if (rtw_get_passing_time_ms(start) > SEC_CAM_ACCESS_TIMEOUT_MS) {
|
|
timeout = 1;
|
|
break;
|
|
}
|
|
}
|
|
end = rtw_get_current_time();
|
|
|
|
_exit_critical_mutex(mutex, NULL);
|
|
|
|
if (DBG_SEC_CAM_ACCESS || timeout) {
|
|
RTW_INFO(FUNC_ADPT_FMT" addr:0x%02x, wdata:0x%08x, to:%u, polling:%u, %d ms\n"
|
|
, FUNC_ADPT_ARG(adapter), addr, wdata, timeout, cnt, rtw_get_time_interval_ms(start, end));
|
|
}
|
|
}
|
|
|
|
void rtw_sec_read_cam_ent(_adapter *adapter, u8 id, u8 *ctrl, u8 *mac, u8 *key)
|
|
{
|
|
u8 i;
|
|
u32 rdata;
|
|
u8 begin = 0;
|
|
u8 end = 5; /* TODO: consider other key length accordingly */
|
|
|
|
if (!ctrl && !mac && !key) {
|
|
rtw_warn_on(1);
|
|
goto exit;
|
|
}
|
|
|
|
/* TODO: check id range */
|
|
|
|
if (!ctrl && !mac)
|
|
begin = 2; /* read from key */
|
|
|
|
if (!key && !mac)
|
|
end = 0; /* read to ctrl */
|
|
else if (!key)
|
|
end = 2; /* read to mac */
|
|
|
|
for (i = begin; i <= end; i++) {
|
|
rdata = rtw_sec_read_cam(adapter, (id << 3) | i);
|
|
|
|
switch (i) {
|
|
case 0:
|
|
if (ctrl)
|
|
_rtw_memcpy(ctrl, (u8 *)(&rdata), 2);
|
|
if (mac)
|
|
_rtw_memcpy(mac, ((u8 *)(&rdata)) + 2, 2);
|
|
break;
|
|
case 1:
|
|
if (mac)
|
|
_rtw_memcpy(mac + 2, (u8 *)(&rdata), 4);
|
|
break;
|
|
default:
|
|
if (key)
|
|
_rtw_memcpy(key + (i - 2) * 4, (u8 *)(&rdata), 4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
void rtw_sec_write_cam_ent(_adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
|
|
{
|
|
unsigned int i;
|
|
int j;
|
|
u8 addr, addr1 = 0;
|
|
u32 wdata, wdata1 = 0;
|
|
|
|
/* TODO: consider other key length accordingly */
|
|
#if 0
|
|
switch ((ctrl & 0x1c) >> 2) {
|
|
case _WEP40_:
|
|
case _TKIP_:
|
|
case _AES_:
|
|
case _WEP104_:
|
|
|
|
}
|
|
#else
|
|
j = 7;
|
|
#endif
|
|
|
|
for (; j >= 0; j--) {
|
|
switch (j) {
|
|
case 0:
|
|
wdata = (ctrl | (mac[0] << 16) | (mac[1] << 24));
|
|
break;
|
|
case 1:
|
|
wdata = (mac[2] | (mac[3] << 8) | (mac[4] << 16) | (mac[5] << 24));
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
wdata = 0;
|
|
break;
|
|
default:
|
|
i = (j - 2) << 2;
|
|
wdata = (key[i] | (key[i + 1] << 8) | (key[i + 2] << 16) | (key[i + 3] << 24));
|
|
break;
|
|
}
|
|
|
|
addr = (id << 3) + j;
|
|
|
|
#if defined(CONFIG_RTL8192F)
|
|
if(j == 1) {
|
|
wdata1 = wdata;
|
|
addr1 = addr;
|
|
continue;
|
|
}
|
|
#endif
|
|
|
|
rtw_sec_write_cam(adapter, addr, wdata);
|
|
}
|
|
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_sec_write_cam(adapter, addr1, wdata1);
|
|
#endif
|
|
}
|
|
|
|
void rtw_sec_clr_cam_ent(_adapter *adapter, u8 id)
|
|
{
|
|
u8 addr;
|
|
|
|
addr = (id << 3);
|
|
rtw_sec_write_cam(adapter, addr, 0);
|
|
}
|
|
|
|
bool rtw_sec_read_cam_is_gk(_adapter *adapter, u8 id)
|
|
{
|
|
bool res;
|
|
u16 ctrl;
|
|
|
|
rtw_sec_read_cam_ent(adapter, id, (u8 *)&ctrl, NULL, NULL);
|
|
|
|
res = (ctrl & BIT6) ? _TRUE : _FALSE;
|
|
return res;
|
|
}
|
|
#ifdef CONFIG_MBSSID_CAM
|
|
void rtw_mbid_cam_init(struct dvobj_priv *dvobj)
|
|
{
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_rtw_spinlock_init(&mbid_cam_ctl->lock);
|
|
mbid_cam_ctl->bitmap = 0;
|
|
ATOMIC_SET(&mbid_cam_ctl->mbid_entry_num, 0);
|
|
_rtw_memset(&dvobj->mbid_cam_cache, 0, sizeof(dvobj->mbid_cam_cache));
|
|
}
|
|
|
|
void rtw_mbid_cam_deinit(struct dvobj_priv *dvobj)
|
|
{
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_rtw_spinlock_free(&mbid_cam_ctl->lock);
|
|
}
|
|
|
|
void rtw_mbid_cam_reset(_adapter *adapter)
|
|
{
|
|
_irqL irqL;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
mbid_cam_ctl->bitmap = 0;
|
|
_rtw_memset(&dvobj->mbid_cam_cache, 0, sizeof(dvobj->mbid_cam_cache));
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
ATOMIC_SET(&mbid_cam_ctl->mbid_entry_num, 0);
|
|
}
|
|
static u8 _rtw_mbid_cam_search_by_macaddr(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
u8 i;
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
if (mac_addr && _rtw_memcmp(dvobj->mbid_cam_cache[i].mac_addr, mac_addr, ETH_ALEN) == _TRUE) {
|
|
cam_id = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id);
|
|
return cam_id;
|
|
}
|
|
|
|
u8 rtw_mbid_cam_search_by_macaddr(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
_irqL irqL;
|
|
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
cam_id = _rtw_mbid_cam_search_by_macaddr(adapter, mac_addr);
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
return cam_id;
|
|
}
|
|
static u8 _rtw_mbid_cam_search_by_ifaceid(_adapter *adapter, u8 iface_id)
|
|
{
|
|
u8 i;
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
if (iface_id == dvobj->mbid_cam_cache[i].iface_id) {
|
|
cam_id = i;
|
|
break;
|
|
}
|
|
}
|
|
if (cam_id != INVALID_CAM_ID)
|
|
RTW_INFO("%s iface_id:%d mac:"MAC_FMT" - cam_id:%d\n",
|
|
__func__, iface_id, MAC_ARG(dvobj->mbid_cam_cache[cam_id].mac_addr), cam_id);
|
|
|
|
return cam_id;
|
|
}
|
|
|
|
u8 rtw_mbid_cam_search_by_ifaceid(_adapter *adapter, u8 iface_id)
|
|
{
|
|
_irqL irqL;
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
cam_id = _rtw_mbid_cam_search_by_ifaceid(adapter, iface_id);
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
return cam_id;
|
|
}
|
|
u8 rtw_get_max_mbid_cam_id(_adapter *adapter)
|
|
{
|
|
_irqL irqL;
|
|
s8 i;
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
for (i = (TOTAL_MBID_CAM_NUM - 1); i >= 0; i--) {
|
|
if (mbid_cam_ctl->bitmap & BIT(i)) {
|
|
cam_id = i;
|
|
break;
|
|
}
|
|
}
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
/*RTW_INFO("%s max cam_id:%d\n", __func__, cam_id);*/
|
|
return cam_id;
|
|
}
|
|
|
|
inline u8 rtw_get_mbid_cam_entry_num(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
return ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num);
|
|
}
|
|
|
|
static inline void mbid_cam_cache_init(_adapter *adapter, struct mbid_cam_cache *pmbid_cam, u8 *mac_addr)
|
|
{
|
|
if (adapter && pmbid_cam && mac_addr) {
|
|
_rtw_memcpy(pmbid_cam->mac_addr, mac_addr, ETH_ALEN);
|
|
pmbid_cam->iface_id = adapter->iface_id;
|
|
}
|
|
}
|
|
static inline void mbid_cam_cache_clr(struct mbid_cam_cache *pmbid_cam)
|
|
{
|
|
if (pmbid_cam) {
|
|
_rtw_memset(pmbid_cam->mac_addr, 0, ETH_ALEN);
|
|
pmbid_cam->iface_id = CONFIG_IFACE_NUMBER;
|
|
}
|
|
}
|
|
|
|
u8 rtw_mbid_camid_alloc(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
_irqL irqL;
|
|
u8 cam_id = INVALID_CAM_ID, i;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
u8 entry_num = ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num);
|
|
|
|
if (INVALID_CAM_ID != rtw_mbid_cam_search_by_macaddr(adapter, mac_addr))
|
|
goto exit;
|
|
|
|
if (entry_num >= TOTAL_MBID_CAM_NUM) {
|
|
RTW_INFO(FUNC_ADPT_FMT" failed !! MBSSID number :%d over TOTAL_CAM_ENTRY(8)\n", FUNC_ADPT_ARG(adapter), entry_num);
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
if (!(mbid_cam_ctl->bitmap & BIT(i))) {
|
|
mbid_cam_ctl->bitmap |= BIT(i);
|
|
cam_id = i;
|
|
break;
|
|
}
|
|
}
|
|
if ((cam_id != INVALID_CAM_ID) && (mac_addr))
|
|
mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[cam_id], mac_addr);
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
if (cam_id != INVALID_CAM_ID) {
|
|
ATOMIC_INC(&mbid_cam_ctl->mbid_entry_num);
|
|
RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id);
|
|
#ifdef DBG_MBID_CAM_DUMP
|
|
rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter);
|
|
#endif
|
|
} else
|
|
RTW_INFO("%s [WARN] "MAC_FMT" - invalid cam_id:%d\n", __func__, MAC_ARG(mac_addr), cam_id);
|
|
exit:
|
|
return cam_id;
|
|
}
|
|
|
|
u8 rtw_mbid_cam_info_change(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
_irqL irqL;
|
|
u8 entry_id = INVALID_CAM_ID;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
entry_id = _rtw_mbid_cam_search_by_ifaceid(adapter, adapter->iface_id);
|
|
if (entry_id != INVALID_CAM_ID)
|
|
mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[entry_id], mac_addr);
|
|
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
return entry_id;
|
|
}
|
|
|
|
u8 rtw_mbid_cam_assign(_adapter *adapter, u8 *mac_addr, u8 camid)
|
|
{
|
|
_irqL irqL;
|
|
u8 ret = _FALSE;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
if ((camid >= TOTAL_MBID_CAM_NUM) || (camid == INVALID_CAM_ID)) {
|
|
RTW_INFO(FUNC_ADPT_FMT" failed !! invlaid mbid_canid :%d\n", FUNC_ADPT_ARG(adapter), camid);
|
|
rtw_warn_on(1);
|
|
}
|
|
if (INVALID_CAM_ID != rtw_mbid_cam_search_by_macaddr(adapter, mac_addr))
|
|
goto exit;
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
if (!(mbid_cam_ctl->bitmap & BIT(camid))) {
|
|
if (mac_addr) {
|
|
mbid_cam_ctl->bitmap |= BIT(camid);
|
|
mbid_cam_cache_init(adapter, &dvobj->mbid_cam_cache[camid], mac_addr);
|
|
ret = _TRUE;
|
|
}
|
|
}
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
|
|
if (ret == _TRUE) {
|
|
ATOMIC_INC(&mbid_cam_ctl->mbid_entry_num);
|
|
RTW_INFO("%s mac:"MAC_FMT" - cam_id:%d\n", __func__, MAC_ARG(mac_addr), camid);
|
|
#ifdef DBG_MBID_CAM_DUMP
|
|
rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter);
|
|
#endif
|
|
} else
|
|
RTW_INFO("%s [WARN] mac:"MAC_FMT" - cam_id:%d assigned failed\n", __func__, MAC_ARG(mac_addr), camid);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
void rtw_mbid_camid_clean(_adapter *adapter, u8 mbss_canid)
|
|
{
|
|
_irqL irqL;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
if ((mbss_canid >= TOTAL_MBID_CAM_NUM) || (mbss_canid == INVALID_CAM_ID)) {
|
|
RTW_INFO(FUNC_ADPT_FMT" failed !! invlaid mbid_canid :%d\n", FUNC_ADPT_ARG(adapter), mbss_canid);
|
|
rtw_warn_on(1);
|
|
}
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
mbid_cam_cache_clr(&dvobj->mbid_cam_cache[mbss_canid]);
|
|
mbid_cam_ctl->bitmap &= (~BIT(mbss_canid));
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
ATOMIC_DEC(&mbid_cam_ctl->mbid_entry_num);
|
|
RTW_INFO("%s - cam_id:%d\n", __func__, mbss_canid);
|
|
}
|
|
int rtw_mbid_cam_cache_dump(void *sel, const char *fun_name, _adapter *adapter)
|
|
{
|
|
_irqL irqL;
|
|
u8 i;
|
|
_adapter *iface;
|
|
u8 iface_id;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
u8 entry_num = ATOMIC_READ(&mbid_cam_ctl->mbid_entry_num);
|
|
u8 max_cam_id = rtw_get_max_mbid_cam_id(adapter);
|
|
|
|
RTW_PRINT_SEL(sel, "== MBSSID CAM DUMP (%s)==\n", fun_name);
|
|
|
|
_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
RTW_PRINT_SEL(sel, "Entry numbers:%d, max_camid:%d, bitmap:0x%08x\n", entry_num, max_cam_id, mbid_cam_ctl->bitmap);
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
RTW_PRINT_SEL(sel, "CAM_ID = %d\t", i);
|
|
|
|
if (mbid_cam_ctl->bitmap & BIT(i)) {
|
|
iface_id = dvobj->mbid_cam_cache[i].iface_id;
|
|
_RTW_PRINT_SEL(sel, "IF_ID:%d\t", iface_id);
|
|
_RTW_PRINT_SEL(sel, "MAC Addr:"MAC_FMT"\t", MAC_ARG(dvobj->mbid_cam_cache[i].mac_addr));
|
|
|
|
iface = dvobj->padapters[iface_id];
|
|
if (iface) {
|
|
if (MLME_IS_STA(iface))
|
|
_RTW_PRINT_SEL(sel, "ROLE:%s\n", "STA");
|
|
else if (MLME_IS_AP(iface))
|
|
_RTW_PRINT_SEL(sel, "ROLE:%s\n", "AP");
|
|
else if (MLME_IS_MESH(iface))
|
|
_RTW_PRINT_SEL(sel, "ROLE:%s\n", "MESH");
|
|
else
|
|
_RTW_PRINT_SEL(sel, "ROLE:%s\n", "NONE");
|
|
}
|
|
|
|
} else
|
|
_RTW_PRINT_SEL(sel, "N/A\n");
|
|
}
|
|
_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);
|
|
return 0;
|
|
}
|
|
|
|
static void read_mbssid_cam(_adapter *padapter, u8 cam_addr, u8 *mac)
|
|
{
|
|
u8 poll = 1;
|
|
u8 cam_ready = _FALSE;
|
|
u32 cam_data1 = 0;
|
|
u16 cam_data2 = 0;
|
|
|
|
if (RTW_CANNOT_RUN(padapter))
|
|
return;
|
|
|
|
rtw_write32(padapter, REG_MBIDCAMCFG_2, BIT_MBIDCAM_POLL | ((cam_addr & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT));
|
|
|
|
do {
|
|
if (0 == (rtw_read32(padapter, REG_MBIDCAMCFG_2) & BIT_MBIDCAM_POLL)) {
|
|
cam_ready = _TRUE;
|
|
break;
|
|
}
|
|
poll++;
|
|
} while ((poll % 10) != 0 && !RTW_CANNOT_RUN(padapter));
|
|
|
|
if (cam_ready) {
|
|
cam_data1 = rtw_read32(padapter, REG_MBIDCAMCFG_1);
|
|
mac[0] = cam_data1 & 0xFF;
|
|
mac[1] = (cam_data1 >> 8) & 0xFF;
|
|
mac[2] = (cam_data1 >> 16) & 0xFF;
|
|
mac[3] = (cam_data1 >> 24) & 0xFF;
|
|
|
|
cam_data2 = rtw_read16(padapter, REG_MBIDCAMCFG_2);
|
|
mac[4] = cam_data2 & 0xFF;
|
|
mac[5] = (cam_data2 >> 8) & 0xFF;
|
|
}
|
|
|
|
}
|
|
int rtw_mbid_cam_dump(void *sel, const char *fun_name, _adapter *adapter)
|
|
{
|
|
/*_irqL irqL;*/
|
|
u8 i;
|
|
u8 mac_addr[ETH_ALEN];
|
|
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
RTW_PRINT_SEL(sel, "\n== MBSSID HW-CAM DUMP (%s)==\n", fun_name);
|
|
|
|
/*_enter_critical_bh(&mbid_cam_ctl->lock, &irqL);*/
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
RTW_PRINT_SEL(sel, "CAM_ID = %d\t", i);
|
|
_rtw_memset(mac_addr, 0, ETH_ALEN);
|
|
read_mbssid_cam(adapter, i, mac_addr);
|
|
_RTW_PRINT_SEL(sel, "MAC Addr:"MAC_FMT"\n", MAC_ARG(mac_addr));
|
|
}
|
|
/*_exit_critical_bh(&mbid_cam_ctl->lock, &irqL);*/
|
|
return 0;
|
|
}
|
|
|
|
static void write_mbssid_cam(_adapter *padapter, u8 cam_addr, u8 *mac)
|
|
{
|
|
u32 cam_val[2] = {0};
|
|
|
|
cam_val[0] = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
|
|
cam_val[1] = ((cam_addr & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT) | (mac[5] << 8) | mac[4];
|
|
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_MBSSID_CAM_WRITE, (u8 *)cam_val);
|
|
}
|
|
|
|
/*
|
|
static void clear_mbssid_cam(_adapter *padapter, u8 cam_addr)
|
|
{
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_MBSSID_CAM_CLEAR, &cam_addr);
|
|
}
|
|
*/
|
|
|
|
void rtw_ap_set_mbid_num(_adapter *adapter, u8 ap_num)
|
|
{
|
|
rtw_write8(adapter, REG_MBID_NUM,
|
|
((rtw_read8(adapter, REG_MBID_NUM) & 0xF8) | ((ap_num -1) & 0x07)));
|
|
|
|
}
|
|
void rtw_mbid_cam_enable(_adapter *adapter)
|
|
{
|
|
/*enable MBSSID*/
|
|
rtw_hal_rcr_add(adapter, RCR_ENMBID);
|
|
}
|
|
void rtw_mi_set_mbid_cam(_adapter *adapter)
|
|
{
|
|
u8 i;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mbid_cam_ctl_t *mbid_cam_ctl = &dvobj->mbid_cam_ctl;
|
|
|
|
#ifdef DBG_MBID_CAM_DUMP
|
|
rtw_mbid_cam_cache_dump(RTW_DBGDUMP, __func__, adapter);
|
|
#endif
|
|
|
|
for (i = 0; i < TOTAL_MBID_CAM_NUM; i++) {
|
|
if (mbid_cam_ctl->bitmap & BIT(i)) {
|
|
write_mbssid_cam(adapter, i, dvobj->mbid_cam_cache[i].mac_addr);
|
|
RTW_INFO("%s - cam_id:%d => mac:"MAC_FMT"\n", __func__, i, MAC_ARG(dvobj->mbid_cam_cache[i].mac_addr));
|
|
}
|
|
}
|
|
rtw_mbid_cam_enable(adapter);
|
|
}
|
|
#endif /*CONFIG_MBSSID_CAM*/
|
|
|
|
#ifdef CONFIG_FW_HANDLE_TXBCN
|
|
#define H2C_BCN_OFFLOAD_LEN 1
|
|
|
|
#define SET_H2CCMD_BCN_OFFLOAD_EN(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 1, __Value)
|
|
#define SET_H2CCMD_BCN_ROOT_TBTT_RPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 1, __Value)
|
|
#define SET_H2CCMD_BCN_VAP1_TBTT_RPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 2, 1, __Value)
|
|
#define SET_H2CCMD_BCN_VAP2_TBTT_RPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 3, 1, __Value)
|
|
#define SET_H2CCMD_BCN_VAP3_TBTT_RPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 4, 1, __Value)
|
|
#define SET_H2CCMD_BCN_VAP4_TBTT_RPT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 5, 1, __Value)
|
|
|
|
void rtw_hal_set_fw_ap_bcn_offload_cmd(_adapter *adapter, bool fw_bcn_en, u8 tbtt_rpt_map)
|
|
{
|
|
u8 fw_bcn_offload[1] = {0};
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
if (fw_bcn_en)
|
|
SET_H2CCMD_BCN_OFFLOAD_EN(fw_bcn_offload, 1);
|
|
|
|
if (tbtt_rpt_map & BIT(0))
|
|
SET_H2CCMD_BCN_ROOT_TBTT_RPT(fw_bcn_offload, 1);
|
|
if (tbtt_rpt_map & BIT(1))
|
|
SET_H2CCMD_BCN_VAP1_TBTT_RPT(fw_bcn_offload, 1);
|
|
if (tbtt_rpt_map & BIT(2))
|
|
SET_H2CCMD_BCN_VAP2_TBTT_RPT(fw_bcn_offload, 1);
|
|
if (tbtt_rpt_map & BIT(3))
|
|
SET_H2CCMD_BCN_VAP3_TBTT_RPT(fw_bcn_offload, 1);
|
|
|
|
dvobj->vap_tbtt_rpt_map = tbtt_rpt_map;
|
|
dvobj->fw_bcn_offload = fw_bcn_en;
|
|
RTW_INFO("[FW BCN] Offload : %s\n", (dvobj->fw_bcn_offload) ? "EN" : "DIS");
|
|
RTW_INFO("[FW BCN] TBTT RPT map : 0x%02x\n", dvobj->vap_tbtt_rpt_map);
|
|
|
|
rtw_hal_fill_h2c_cmd(adapter, H2C_FW_BCN_OFFLOAD,
|
|
H2C_BCN_OFFLOAD_LEN, fw_bcn_offload);
|
|
}
|
|
|
|
void rtw_hal_set_bcn_rsvdpage_loc_cmd(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
u8 ret, vap_id;
|
|
u32 page_size = 0;
|
|
u8 bcn_rsvdpage[H2C_BCN_RSVDPAGE_LEN] = {0};
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&page_size);
|
|
#if 1
|
|
for (vap_id = 0; vap_id < CONFIG_LIMITED_AP_NUM; vap_id++) {
|
|
if (dvobj->vap_map & BIT(vap_id))
|
|
bcn_rsvdpage[vap_id] = vap_id * (MAX_BEACON_LEN / page_size);
|
|
}
|
|
#else
|
|
#define SET_H2CCMD_BCN_RSVDPAGE_LOC_ROOT(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 0, 8, __Value)
|
|
#define SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP1(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 1, 8, __Value)
|
|
#define SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP2(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 2, 8, __Value)
|
|
#define SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP3(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 3, 8, __Value)
|
|
#define SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP4(__pH2CCmd, __Value) SET_BITS_TO_LE_1BYTE(__pH2CCmd, 4, 8, __Value)
|
|
|
|
if (dvobj->vap_map & BIT(0))
|
|
SET_H2CCMD_BCN_RSVDPAGE_LOC_ROOT(bcn_rsvdpage, 0);
|
|
if (dvobj->vap_map & BIT(1))
|
|
SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP1(bcn_rsvdpage,
|
|
1 * (MAX_BEACON_LEN / page_size));
|
|
if (dvobj->vap_map & BIT(2))
|
|
SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP2(bcn_rsvdpage,
|
|
2 * (MAX_BEACON_LEN / page_size));
|
|
if (dvobj->vap_map & BIT(3))
|
|
SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP3(bcn_rsvdpage,
|
|
3 * (MAX_BEACON_LEN / page_size));
|
|
if (dvobj->vap_map & BIT(4))
|
|
SET_H2CCMD_BCN_RSVDPAGE_LOC_VAP4(bcn_rsvdpage,
|
|
4 * (MAX_BEACON_LEN / page_size));
|
|
#endif
|
|
if (1) {
|
|
RTW_INFO("[BCN_LOC] vap_map : 0x%02x\n", dvobj->vap_map);
|
|
RTW_INFO("[BCN_LOC] page_size :%d, @bcn_page_num :%d\n"
|
|
, page_size, (MAX_BEACON_LEN / page_size));
|
|
RTW_INFO("[BCN_LOC] root ap : 0x%02x\n", *bcn_rsvdpage);
|
|
RTW_INFO("[BCN_LOC] vap_1 : 0x%02x\n", *(bcn_rsvdpage + 1));
|
|
RTW_INFO("[BCN_LOC] vap_2 : 0x%02x\n", *(bcn_rsvdpage + 2));
|
|
RTW_INFO("[BCN_LOC] vap_3 : 0x%02x\n", *(bcn_rsvdpage + 3));
|
|
RTW_INFO("[BCN_LOC] vap_4 : 0x%02x\n", *(bcn_rsvdpage + 4));
|
|
}
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_BCN_RSVDPAGE,
|
|
H2C_BCN_RSVDPAGE_LEN, bcn_rsvdpage);
|
|
}
|
|
|
|
void rtw_ap_multi_bcn_cfg(_adapter *adapter)
|
|
{
|
|
u8 dft_bcn_space = DEFAULT_BCN_INTERVAL;
|
|
u8 sub_bcn_space = (DEFAULT_BCN_INTERVAL / CONFIG_LIMITED_AP_NUM);
|
|
|
|
/*enable to rx data frame*/
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
|
|
/*Disable Port0's beacon function*/
|
|
rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) & ~BIT_EN_BCN_FUNCTION);
|
|
/*Reset Port0's TSF*/
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT_TSFTR_RST);
|
|
|
|
rtw_ap_set_mbid_num(adapter, CONFIG_LIMITED_AP_NUM);
|
|
|
|
/*BCN space & BCN sub-space 0x554[15:0] = 0x64,0x5BC[23:16] = 0x21*/
|
|
rtw_halmac_set_bcn_interval(adapter_to_dvobj(adapter), HW_PORT0, dft_bcn_space);
|
|
rtw_write8(adapter, REG_MBSSID_BCN_SPACE3 + 2, sub_bcn_space);
|
|
|
|
#if 0 /*setting in hw_var_set_opmode_mbid - ResumeTxBeacon*/
|
|
/*BCN hold time 0x540[19:8] = 0x80*/
|
|
rtw_write8(adapter, REG_TBTT_PROHIBIT + 1, TBTT_PROHIBIT_HOLD_TIME & 0xFF);
|
|
rtw_write8(adapter, REG_TBTT_PROHIBIT + 2,
|
|
(rtw_read8(adapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROHIBIT_HOLD_TIME >> 8));
|
|
#endif
|
|
|
|
/*ATIM window -0x55A = 0x32, reg 0x570 = 0x32, reg 0x5A0 = 0x32 */
|
|
rtw_write8(adapter, REG_ATIMWND, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND1_V1, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND2, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND3, 0x32);
|
|
/*
|
|
rtw_write8(adapter, REG_ATIMWND4, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND5, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND6, 0x32);
|
|
rtw_write8(adapter, REG_ATIMWND7, 0x32);*/
|
|
|
|
/*no limit setting - 0x5A7 = 0xFF - Packet in Hi Queue Tx immediately*/
|
|
rtw_write8(adapter, REG_HIQ_NO_LMT_EN, 0xFF);
|
|
|
|
/*Mask all beacon*/
|
|
rtw_write8(adapter, REG_MBSSID_CTRL, 0);
|
|
|
|
/*BCN invalid bit setting 0x454[6] = 1*/
|
|
/*rtw_write8(adapter, REG_CCK_CHECK, rtw_read8(adapter, REG_CCK_CHECK) | BIT_EN_BCN_PKT_REL);*/
|
|
|
|
/*Enable Port0's beacon function*/
|
|
rtw_write8(adapter, REG_BCN_CTRL,
|
|
rtw_read8(adapter, REG_BCN_CTRL) | BIT_DIS_RX_BSSID_FIT | BIT_P0_EN_TXBCN_RPT | BIT_DIS_TSF_UDT | BIT_EN_BCN_FUNCTION);
|
|
|
|
/* Enable HW seq for BCN
|
|
* 0x4FC[0]: EN_HWSEQ / 0x4FC[1]: EN_HWSEQEXT */
|
|
#ifdef CONFIG_RTL8822B
|
|
if (IS_HARDWARE_TYPE_8822B(adapter))
|
|
rtw_write8(adapter, REG_DUMMY_PAGE4_V1_8822B, 0x01);
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
if (IS_HARDWARE_TYPE_8822C(adapter))
|
|
rtw_write8(adapter, REG_DUMMY_PAGE4_V1_8822C, 0x01);
|
|
#endif
|
|
}
|
|
static void _rtw_mbid_bcn_cfg(_adapter *adapter, bool mbcnq_en, u8 mbcnq_id)
|
|
{
|
|
if (mbcnq_id >= CONFIG_LIMITED_AP_NUM) {
|
|
RTW_ERR(FUNC_ADPT_FMT"- mbid bcnq_id(%d) invalid\n", FUNC_ADPT_ARG(adapter), mbcnq_id);
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
if (mbcnq_en) {
|
|
rtw_write8(adapter, REG_MBSSID_CTRL,
|
|
rtw_read8(adapter, REG_MBSSID_CTRL) | BIT(mbcnq_id));
|
|
RTW_INFO(FUNC_ADPT_FMT"- mbid bcnq_id(%d) enabled\n", FUNC_ADPT_ARG(adapter), mbcnq_id);
|
|
} else {
|
|
rtw_write8(adapter, REG_MBSSID_CTRL,
|
|
rtw_read8(adapter, REG_MBSSID_CTRL) & (~BIT(mbcnq_id)));
|
|
RTW_INFO(FUNC_ADPT_FMT"- mbid bcnq_id(%d) disabled\n", FUNC_ADPT_ARG(adapter), mbcnq_id);
|
|
}
|
|
}
|
|
/*#define CONFIG_FW_TBTT_RPT*/
|
|
void rtw_ap_mbid_bcn_en(_adapter *adapter, u8 ap_id)
|
|
{
|
|
RTW_INFO(FUNC_ADPT_FMT"- ap_id(%d)\n", FUNC_ADPT_ARG(adapter), ap_id);
|
|
|
|
#ifdef CONFIG_FW_TBTT_RPT
|
|
if (rtw_ap_get_nums(adapter) >= 1) {
|
|
u8 tbtt_rpt_map = adapter_to_dvobj(adapter)->vap_tbtt_rpt_map;
|
|
|
|
rtw_hal_set_fw_ap_bcn_offload_cmd(adapter, _TRUE,
|
|
tbtt_rpt_map | BIT(ap_id));/*H2C-0xBA*/
|
|
}
|
|
#else
|
|
if (rtw_ap_get_nums(adapter) == 1)
|
|
rtw_hal_set_fw_ap_bcn_offload_cmd(adapter, _TRUE, 0);/*H2C-0xBA*/
|
|
#endif
|
|
|
|
rtw_hal_set_bcn_rsvdpage_loc_cmd(adapter);/*H2C-0x09*/
|
|
|
|
_rtw_mbid_bcn_cfg(adapter, _TRUE, ap_id);
|
|
}
|
|
void rtw_ap_mbid_bcn_dis(_adapter *adapter, u8 ap_id)
|
|
{
|
|
RTW_INFO(FUNC_ADPT_FMT"- ap_id(%d)\n", FUNC_ADPT_ARG(adapter), ap_id);
|
|
_rtw_mbid_bcn_cfg(adapter, _FALSE, ap_id);
|
|
|
|
if (rtw_ap_get_nums(adapter) == 0)
|
|
rtw_hal_set_fw_ap_bcn_offload_cmd(adapter, _FALSE, 0);
|
|
#ifdef CONFIG_FW_TBTT_RPT
|
|
else if (rtw_ap_get_nums(adapter) >= 1) {
|
|
u8 tbtt_rpt_map = adapter_to_dvobj(adapter)->vap_tbtt_rpt_map;
|
|
|
|
rtw_hal_set_fw_ap_bcn_offload_cmd(adapter, _TRUE,
|
|
tbtt_rpt_map & ~BIT(ap_id));/*H2C-0xBA*/
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_SWTIMER_BASED_TXBCN
|
|
void rtw_ap_multi_bcn_cfg(_adapter *adapter)
|
|
{
|
|
#if defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
|
|
rtw_write8(adapter, REG_BCN_CTRL, DIS_TSF_UDT);
|
|
#else
|
|
rtw_write8(adapter, REG_BCN_CTRL, DIS_TSF_UDT | DIS_BCNQ_SUB);
|
|
#endif
|
|
/*enable to rx data frame*/
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
|
|
/*Beacon Control related register for first time*/
|
|
rtw_write8(adapter, REG_BCNDMATIM, 0x02); /* 2ms */
|
|
|
|
/*rtw_write8(Adapter, REG_BCN_MAX_ERR, 0xFF);*/
|
|
rtw_write8(adapter, REG_ATIMWND, 0x0c); /* 12ms */
|
|
|
|
#ifndef CONFIG_HW_P0_TSF_SYNC
|
|
#ifdef CONFIG_RTL8192F
|
|
rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, 0x640);/*unit:32us*/
|
|
#else/*not CONFIG_RTL8192F*/
|
|
rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, 0x7fff);/* +32767 (~32ms) */
|
|
#endif
|
|
#endif
|
|
|
|
/*reset TSF*/
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(0));
|
|
|
|
/*enable BCN0 Function for if1*/
|
|
/*don't enable update TSF0 for if1 (due to TSF update when beacon,probe rsp are received)*/
|
|
#if defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
|
|
rtw_write8(adapter, REG_BCN_CTRL, BIT_DIS_RX_BSSID_FIT | BIT_P0_EN_TXBCN_RPT | BIT_DIS_TSF_UDT |BIT_EN_BCN_FUNCTION);
|
|
#else
|
|
rtw_write8(adapter, REG_BCN_CTRL, (DIS_TSF_UDT | EN_BCN_FUNCTION | EN_TXBCN_RPT | DIS_BCNQ_SUB));
|
|
#endif
|
|
#ifdef CONFIG_BCN_XMIT_PROTECT
|
|
rtw_write8(adapter, REG_CCK_CHECK, rtw_read8(adapter, REG_CCK_CHECK) | BIT_EN_BCN_PKT_REL);
|
|
#endif
|
|
|
|
if (IS_HARDWARE_TYPE_8821(adapter) || IS_HARDWARE_TYPE_8192E(adapter))/* select BCN on port 0 for DualBeacon*/
|
|
rtw_write8(adapter, REG_CCK_CHECK, rtw_read8(adapter, REG_CCK_CHECK) & (~BIT_BCN_PORT_SEL));
|
|
|
|
/* Enable HW seq for BCN
|
|
* 0x4FC[0]: EN_HWSEQ / 0x4FC[1]: EN_HWSEQEXT */
|
|
#ifdef CONFIG_RTL8822B
|
|
if (IS_HARDWARE_TYPE_8822B(adapter))
|
|
rtw_write8(adapter, REG_DUMMY_PAGE4_V1_8822B, 0x01);
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
if (IS_HARDWARE_TYPE_8822C(adapter))
|
|
rtw_write8(adapter, REG_DUMMY_PAGE4_V1_8822C, 0x01);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
void rtw_hal_set_macaddr_mbid(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
|
|
#if 0 /*TODO - modify for more flexible*/
|
|
u8 idx = 0;
|
|
|
|
if ((check_fwstate(&adapter->mlmepriv, WIFI_STATION_STATE) == _TRUE) &&
|
|
(DEV_STA_NUM(adapter_to_dvobj(adapter)) == 1)) {
|
|
for (idx = 0; idx < 6; idx++)
|
|
rtw_write8(GET_PRIMARY_ADAPTER(adapter), (REG_MACID + idx), val[idx]);
|
|
} else {
|
|
/*MBID entry_id = 0~7 ,0 for root AP, 1~7 for VAP*/
|
|
u8 entry_id;
|
|
|
|
if ((check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _TRUE) &&
|
|
(DEV_AP_NUM(adapter_to_dvobj(adapter)) == 1)) {
|
|
entry_id = 0;
|
|
if (rtw_mbid_cam_assign(adapter, val, entry_id)) {
|
|
RTW_INFO(FUNC_ADPT_FMT" Root AP assigned success\n", FUNC_ADPT_ARG(adapter));
|
|
write_mbssid_cam(adapter, entry_id, val);
|
|
}
|
|
} else {
|
|
entry_id = rtw_mbid_camid_alloc(adapter, val);
|
|
if (entry_id != INVALID_CAM_ID)
|
|
write_mbssid_cam(adapter, entry_id, val);
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
/*
|
|
MBID entry_id = 0~7 ,for IFACE_ID0 ~ IFACE_IDx
|
|
*/
|
|
u8 entry_id = rtw_mbid_camid_alloc(adapter, mac_addr);
|
|
|
|
|
|
if (entry_id != INVALID_CAM_ID) {
|
|
write_mbssid_cam(adapter, entry_id, mac_addr);
|
|
RTW_INFO("%s "ADPT_FMT"- mbid(%d) mac_addr ="MAC_FMT"\n", __func__,
|
|
ADPT_ARG(adapter), entry_id, MAC_ARG(mac_addr));
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void rtw_hal_change_macaddr_mbid(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
u8 idx = 0;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
u8 entry_id;
|
|
|
|
if (!mac_addr) {
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
|
|
|
|
entry_id = rtw_mbid_cam_info_change(adapter, mac_addr);
|
|
|
|
if (entry_id != INVALID_CAM_ID)
|
|
write_mbssid_cam(adapter, entry_id, mac_addr);
|
|
}
|
|
|
|
#ifdef CONFIG_SWTIMER_BASED_TXBCN
|
|
u16 rtw_hal_bcn_interval_adjust(_adapter *adapter, u16 bcn_interval)
|
|
{
|
|
if (adapter_to_dvobj(adapter)->inter_bcn_space != bcn_interval)
|
|
return adapter_to_dvobj(adapter)->inter_bcn_space;
|
|
else
|
|
return bcn_interval;
|
|
}
|
|
#endif/*CONFIG_SWTIMER_BASED_TXBCN*/
|
|
|
|
#else
|
|
|
|
#ifndef RTW_HALMAC
|
|
static u32 _get_macaddr_reg(enum _hw_port hwport)
|
|
{
|
|
u32 reg_macaddr = REG_MACID;
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (hwport == HW_PORT1)
|
|
reg_macaddr = REG_MACID1;
|
|
#if defined(CONFIG_RTL8814A)
|
|
else if (hwport == HW_PORT2)
|
|
reg_macaddr = REG_MACID2;
|
|
else if (hwport == HW_PORT3)
|
|
reg_macaddr = REG_MACID3;
|
|
else if (hwport == HW_PORT4)
|
|
reg_macaddr = REG_MACID4;
|
|
#endif /*CONFIG_RTL8814A*/
|
|
#endif /*CONFIG_CONCURRENT_MODE*/
|
|
|
|
return reg_macaddr;
|
|
}
|
|
#endif /*!RTW_HALMAC*/
|
|
|
|
static void rtw_hal_set_macaddr_port(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
enum _hw_port hwport;
|
|
|
|
if (mac_addr == NULL)
|
|
return;
|
|
hwport = get_hw_port(adapter);
|
|
|
|
RTW_INFO("%s "ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n", __func__,
|
|
ADPT_ARG(adapter), hwport, MAC_ARG(mac_addr));
|
|
|
|
#ifdef RTW_HALMAC /*8822B ~ 8814B*/
|
|
rtw_halmac_set_mac_address(adapter_to_dvobj(adapter), hwport, mac_addr);
|
|
#else /* !RTW_HALMAC */
|
|
{
|
|
u8 idx = 0;
|
|
u32 reg_macaddr = _get_macaddr_reg(hwport);
|
|
|
|
for (idx = 0; idx < ETH_ALEN; idx++)
|
|
rtw_write8(GET_PRIMARY_ADAPTER(adapter), (reg_macaddr + idx), mac_addr[idx]);
|
|
}
|
|
#endif /* !RTW_HALMAC */
|
|
}
|
|
|
|
static void rtw_hal_get_macaddr_port(_adapter *adapter, u8 *mac_addr)
|
|
{
|
|
enum _hw_port hwport;
|
|
|
|
if (mac_addr == NULL)
|
|
return;
|
|
hwport = get_hw_port(adapter);
|
|
|
|
_rtw_memset(mac_addr, 0, ETH_ALEN);
|
|
#ifdef RTW_HALMAC /*8822B ~ 8814B*/
|
|
rtw_halmac_get_mac_address(adapter_to_dvobj(adapter), hwport, mac_addr);
|
|
#else /* !RTW_HALMAC */
|
|
{
|
|
u8 idx = 0;
|
|
u32 reg_macaddr = _get_macaddr_reg(hwport);
|
|
|
|
for (idx = 0; idx < ETH_ALEN; idx++)
|
|
mac_addr[idx] = rtw_read8(GET_PRIMARY_ADAPTER(adapter), (reg_macaddr + idx));
|
|
}
|
|
#endif /* !RTW_HALMAC */
|
|
|
|
RTW_DBG("%s "ADPT_FMT"- hw port(%d) mac_addr ="MAC_FMT"\n", __func__,
|
|
ADPT_ARG(adapter), hwport, MAC_ARG(mac_addr));
|
|
}
|
|
#endif/*#ifdef CONFIG_MI_WITH_MBSSID_CAM*/
|
|
|
|
#ifndef RTW_HALMAC
|
|
static u32 _get_bssid_reg(enum _hw_port hw_port)
|
|
{
|
|
u32 reg_bssid = REG_BSSID;
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (hw_port == HW_PORT1)
|
|
reg_bssid = REG_BSSID1;
|
|
#if defined(CONFIG_RTL8814A)
|
|
else if (hw_port == HW_PORT2)
|
|
reg_bssid = REG_BSSID2;
|
|
else if (hw_port == HW_PORT3)
|
|
reg_bssid = REG_BSSID3;
|
|
else if (hw_port == HW_PORT4)
|
|
reg_bssid = REG_BSSID4;
|
|
#endif /*CONFIG_RTL8814A*/
|
|
#endif /*CONFIG_CONCURRENT_MODE*/
|
|
|
|
return reg_bssid;
|
|
}
|
|
#endif /*!RTW_HALMAC*/
|
|
static void rtw_hal_set_bssid(_adapter *adapter, u8 *val)
|
|
{
|
|
enum _hw_port hw_port = rtw_hal_get_port(adapter);
|
|
#ifdef RTW_HALMAC
|
|
|
|
rtw_halmac_set_bssid(adapter_to_dvobj(adapter), hw_port, val);
|
|
#else /* !RTW_HALMAC */
|
|
u8 idx = 0;
|
|
u32 reg_bssid = _get_bssid_reg(hw_port);
|
|
|
|
for (idx = 0 ; idx < ETH_ALEN; idx++)
|
|
rtw_write8(adapter, (reg_bssid + idx), val[idx]);
|
|
#endif /* !RTW_HALMAC */
|
|
|
|
RTW_INFO("%s "ADPT_FMT"- hw port -%d BSSID: "MAC_FMT"\n",
|
|
__func__, ADPT_ARG(adapter), hw_port, MAC_ARG(val));
|
|
}
|
|
|
|
#ifndef CONFIG_MI_WITH_MBSSID_CAM
|
|
static void rtw_hal_set_tsf_update(_adapter *adapter, u8 en)
|
|
{
|
|
u32 addr = 0;
|
|
u8 val8;
|
|
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_BCN_CTRL_ADDR, (u8 *)&addr);
|
|
if (addr) {
|
|
rtw_enter_protsel_port(adapter, get_hw_port(adapter));
|
|
val8 = rtw_read8(adapter, addr);
|
|
if (en && (val8 & DIS_TSF_UDT)) {
|
|
rtw_write8(adapter, addr, val8 & ~DIS_TSF_UDT);
|
|
#ifdef DBG_TSF_UPDATE
|
|
RTW_INFO("port%u("ADPT_FMT") enable TSF update\n", adapter->hw_port, ADPT_ARG(adapter));
|
|
#endif
|
|
}
|
|
if (!en && !(val8 & DIS_TSF_UDT)) {
|
|
rtw_write8(adapter, addr, val8 | DIS_TSF_UDT);
|
|
#ifdef DBG_TSF_UPDATE
|
|
RTW_INFO("port%u("ADPT_FMT") disable TSF update\n", adapter->hw_port, ADPT_ARG(adapter));
|
|
#endif
|
|
}
|
|
rtw_leave_protsel_port(adapter);
|
|
} else {
|
|
RTW_WARN("unknown port%d("ADPT_FMT") %s TSF update\n"
|
|
, adapter->hw_port, ADPT_ARG(adapter), en ? "enable" : "disable");
|
|
rtw_warn_on(1);
|
|
}
|
|
}
|
|
#endif /*CONFIG_MI_WITH_MBSSID_CAM*/
|
|
static void rtw_hal_set_hw_update_tsf(PADAPTER padapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
|
|
|
|
if (!pmlmeext->en_hw_update_tsf)
|
|
return;
|
|
|
|
/* check RCR */
|
|
if (!rtw_hal_rcr_check(padapter, RCR_CBSSID_BCN))
|
|
return;
|
|
|
|
if (pmlmeext->tsf_update_required) {
|
|
pmlmeext->tsf_update_pause_stime = 0;
|
|
rtw_hal_set_tsf_update(padapter, 1);
|
|
}
|
|
|
|
pmlmeext->en_hw_update_tsf = 0;
|
|
#endif
|
|
}
|
|
|
|
void rtw_iface_enable_tsf_update(_adapter *adapter)
|
|
{
|
|
adapter->mlmeextpriv.tsf_update_pause_stime = 0;
|
|
adapter->mlmeextpriv.tsf_update_required = 1;
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
rtw_hal_set_tsf_update(adapter, 1);
|
|
#endif
|
|
}
|
|
|
|
void rtw_iface_disable_tsf_update(_adapter *adapter)
|
|
{
|
|
adapter->mlmeextpriv.tsf_update_required = 0;
|
|
adapter->mlmeextpriv.tsf_update_pause_stime = 0;
|
|
adapter->mlmeextpriv.en_hw_update_tsf = 0;
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
rtw_hal_set_tsf_update(adapter, 0);
|
|
#endif
|
|
}
|
|
|
|
static void rtw_hal_tsf_update_pause(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface;
|
|
int i;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
|
|
rtw_hal_set_tsf_update(iface, 0);
|
|
if (iface->mlmeextpriv.tsf_update_required) {
|
|
iface->mlmeextpriv.tsf_update_pause_stime = rtw_get_current_time();
|
|
if (!iface->mlmeextpriv.tsf_update_pause_stime)
|
|
iface->mlmeextpriv.tsf_update_pause_stime++;
|
|
}
|
|
iface->mlmeextpriv.en_hw_update_tsf = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void rtw_hal_tsf_update_restore(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface;
|
|
int i;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
|
|
if (iface->mlmeextpriv.tsf_update_required) {
|
|
/* enable HW TSF update when recive beacon*/
|
|
iface->mlmeextpriv.en_hw_update_tsf = 1;
|
|
#ifdef DBG_TSF_UPDATE
|
|
RTW_INFO("port%d("ADPT_FMT") enabling TSF update...\n"
|
|
, iface->hw_port, ADPT_ARG(iface));
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void rtw_hal_periodic_tsf_update_chk(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
|
|
#else
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface;
|
|
struct mlme_ext_priv *mlmeext;
|
|
int i;
|
|
u32 restore_ms = 0;
|
|
|
|
if (dvobj->periodic_tsf_update_etime) {
|
|
if (rtw_time_after(rtw_get_current_time(), dvobj->periodic_tsf_update_etime)) {
|
|
/* end for restore status */
|
|
dvobj->periodic_tsf_update_etime = 0;
|
|
rtw_hal_rcr_set_chk_bssid(adapter, MLME_ACTION_NONE);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (dvobj->rf_ctl.offch_state != OFFCHS_NONE)
|
|
return;
|
|
|
|
/*
|
|
* all required ifaces can switch to restore status together
|
|
* loop all pause iface to get largest restore time required
|
|
*/
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
|
|
mlmeext = &iface->mlmeextpriv;
|
|
|
|
if (mlmeext->tsf_update_required
|
|
&& mlmeext->tsf_update_pause_stime
|
|
&& rtw_get_passing_time_ms(mlmeext->tsf_update_pause_stime)
|
|
> mlmeext->mlmext_info.bcn_interval * mlmeext->tsf_update_pause_factor
|
|
) {
|
|
if (restore_ms < mlmeext->mlmext_info.bcn_interval * mlmeext->tsf_update_restore_factor)
|
|
restore_ms = mlmeext->mlmext_info.bcn_interval * mlmeext->tsf_update_restore_factor;
|
|
}
|
|
}
|
|
|
|
if (!restore_ms)
|
|
return;
|
|
|
|
dvobj->periodic_tsf_update_etime = rtw_get_current_time() + rtw_ms_to_systime(restore_ms);
|
|
if (!dvobj->periodic_tsf_update_etime)
|
|
dvobj->periodic_tsf_update_etime++;
|
|
|
|
rtw_hal_rcr_set_chk_bssid(adapter, MLME_ACTION_NONE);
|
|
|
|
/* set timer to end restore status */
|
|
_set_timer(&dvobj->periodic_tsf_update_end_timer, restore_ms);
|
|
#endif
|
|
}
|
|
|
|
void rtw_hal_periodic_tsf_update_end_timer_hdl(void *ctx)
|
|
{
|
|
struct dvobj_priv *dvobj = (struct dvobj_priv *)ctx;
|
|
|
|
if (dev_is_surprise_removed(dvobj) || dev_is_drv_stopped(dvobj))
|
|
return;
|
|
|
|
rtw_periodic_tsf_update_end_cmd(dvobj_get_primary_adapter(dvobj));
|
|
}
|
|
|
|
static inline u8 hw_var_rcr_config(_adapter *adapter, u32 rcr)
|
|
{
|
|
int err;
|
|
|
|
#ifdef CONFIG_CUSTOMER_ALIBABA_GENERAL
|
|
rcr = RCR_AAP | RCR_APM | RCR_AM | RCR_AB | RCR_APWRMGT | RCR_ADF | RCR_AMF | RCR_APP_PHYST_RXFF | RCR_APP_MIC | RCR_APP_ICV;
|
|
#endif
|
|
err = rtw_write32(adapter, REG_RCR, rcr);
|
|
if (err == _SUCCESS)
|
|
GET_HAL_DATA(adapter)->ReceiveConfig = rcr;
|
|
return err;
|
|
}
|
|
|
|
static inline u8 hw_var_rcr_get(_adapter *adapter, u32 *rcr)
|
|
{
|
|
u32 v32;
|
|
|
|
v32 = rtw_read32(adapter, REG_RCR);
|
|
if (rcr)
|
|
*rcr = v32;
|
|
GET_HAL_DATA(adapter)->ReceiveConfig = v32;
|
|
return _SUCCESS;
|
|
}
|
|
|
|
/* only check SW RCR variable */
|
|
inline u8 rtw_hal_rcr_check(_adapter *adapter, u32 check_bit)
|
|
{
|
|
PHAL_DATA_TYPE hal;
|
|
u32 rcr;
|
|
|
|
hal = GET_HAL_DATA(adapter);
|
|
|
|
rcr = hal->ReceiveConfig;
|
|
if ((rcr & check_bit) == check_bit)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline u8 rtw_hal_rcr_add(_adapter *adapter, u32 add)
|
|
{
|
|
PHAL_DATA_TYPE hal;
|
|
u32 rcr;
|
|
u8 ret = _SUCCESS;
|
|
|
|
hal = GET_HAL_DATA(adapter);
|
|
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
rcr |= add;
|
|
if (rcr != hal->ReceiveConfig)
|
|
ret = rtw_hal_set_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
inline u8 rtw_hal_rcr_clear(_adapter *adapter, u32 clear)
|
|
{
|
|
PHAL_DATA_TYPE hal;
|
|
u32 rcr;
|
|
u8 ret = _SUCCESS;
|
|
|
|
hal = GET_HAL_DATA(adapter);
|
|
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
rcr &= ~clear;
|
|
if (rcr != hal->ReceiveConfig)
|
|
ret = rtw_hal_set_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void rtw_hal_rcr_set_chk_bssid(_adapter *adapter, u8 self_action)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
u32 rcr, rcr_new;
|
|
#if !defined(CONFIG_MI_WITH_MBSSID_CAM) || defined(CONFIG_CLIENT_PORT_CFG) || defined(CONFIG_RTW_MULTI_AP)
|
|
struct mi_state mstate, mstate_s;
|
|
#endif
|
|
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
rcr_new = rcr;
|
|
|
|
#if !defined(CONFIG_MI_WITH_MBSSID_CAM) || defined(CONFIG_CLIENT_PORT_CFG) || defined(CONFIG_RTW_MULTI_AP)
|
|
rtw_mi_status_no_self(adapter, &mstate);
|
|
rtw_mi_status_no_others(adapter, &mstate_s);
|
|
|
|
/* only adjust parameters interested */
|
|
switch (self_action) {
|
|
case MLME_SCAN_ENTER:
|
|
mstate_s.scan_num = 1;
|
|
mstate_s.scan_enter_num = 1;
|
|
break;
|
|
case MLME_SCAN_DONE:
|
|
mstate_s.scan_enter_num = 0;
|
|
break;
|
|
case MLME_STA_CONNECTING:
|
|
mstate_s.lg_sta_num = 1;
|
|
mstate_s.ld_sta_num = 0;
|
|
break;
|
|
case MLME_STA_CONNECTED:
|
|
mstate_s.lg_sta_num = 0;
|
|
mstate_s.ld_sta_num = 1;
|
|
break;
|
|
case MLME_STA_DISCONNECTED:
|
|
mstate_s.lg_sta_num = 0;
|
|
mstate_s.ld_sta_num = 0;
|
|
break;
|
|
#ifdef CONFIG_TDLS
|
|
case MLME_TDLS_LINKED:
|
|
mstate_s.ld_tdls_num = 1;
|
|
break;
|
|
case MLME_TDLS_NOLINK:
|
|
mstate_s.ld_tdls_num = 0;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_AP_MODE
|
|
case MLME_AP_STARTED:
|
|
mstate_s.ap_num = 1;
|
|
break;
|
|
case MLME_AP_STOPPED:
|
|
mstate_s.ap_num = 0;
|
|
mstate_s.ld_ap_num = 0;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTW_MESH
|
|
case MLME_MESH_STARTED:
|
|
mstate_s.mesh_num = 1;
|
|
break;
|
|
case MLME_MESH_STOPPED:
|
|
mstate_s.mesh_num = 0;
|
|
mstate_s.ld_mesh_num = 0;
|
|
break;
|
|
#endif
|
|
case MLME_ACTION_NONE:
|
|
case MLME_ADHOC_STARTED:
|
|
/* caller without effect of decision */
|
|
break;
|
|
default:
|
|
rtw_warn_on(1);
|
|
};
|
|
|
|
rtw_mi_status_merge(&mstate, &mstate_s);
|
|
#endif /* !defined(CONFIG_MI_WITH_MBSSID_CAM) || defined(CONFIG_CLIENT_PORT_CFG) || defined(CONFIG_RTW_MULTI_AP) */
|
|
|
|
#if defined(CONFIG_MI_WITH_MBSSID_CAM) && !defined(CONFIG_CLIENT_PORT_CFG)
|
|
rcr_new &= ~(RCR_CBSSID_BCN | RCR_CBSSID_DATA);
|
|
#else
|
|
if (MSTATE_AP_NUM(&mstate) || MSTATE_MESH_NUM(&mstate) || MSTATE_TDLS_LD_NUM(&mstate)
|
|
#ifdef CONFIG_FIND_BEST_CHANNEL
|
|
|| MSTATE_SCAN_ENTER_NUM(&mstate)
|
|
#endif
|
|
|| hal_data->in_cta_test
|
|
)
|
|
rcr_new &= ~RCR_CBSSID_DATA;
|
|
else
|
|
rcr_new |= RCR_CBSSID_DATA;
|
|
|
|
if (MSTATE_SCAN_ENTER_NUM(&mstate) || hal_data->in_cta_test)
|
|
rcr_new &= ~RCR_CBSSID_BCN;
|
|
else if (MSTATE_STA_LG_NUM(&mstate)
|
|
|| adapter_to_dvobj(adapter)->periodic_tsf_update_etime
|
|
)
|
|
rcr_new |= RCR_CBSSID_BCN;
|
|
else if ((MSTATE_AP_NUM(&mstate) && adapter->registrypriv.wifi_spec) /* for 11n Logo 4.2.31/4.2.32 */
|
|
|| MSTATE_MESH_NUM(&mstate)
|
|
)
|
|
rcr_new &= ~RCR_CBSSID_BCN;
|
|
else
|
|
rcr_new |= RCR_CBSSID_BCN;
|
|
|
|
#ifdef CONFIG_CLIENT_PORT_CFG
|
|
if (get_clt_num(adapter) > MAX_CLIENT_PORT_NUM)
|
|
rcr_new &= ~RCR_CBSSID_BCN;
|
|
#endif
|
|
#endif /* CONFIG_MI_WITH_MBSSID_CAM */
|
|
|
|
#ifdef CONFIG_RTW_MULTI_AP
|
|
if (MSTATE_AP_NUM(&mstate)
|
|
&& rtw_unassoc_sta_src_chk(adapter, UNASOC_STA_SRC_RX_NMY_UC)
|
|
) {
|
|
rcr_new |= RCR_AAP;
|
|
} else
|
|
rcr_new &= ~RCR_AAP;
|
|
#endif
|
|
|
|
if (rcr == rcr_new)
|
|
return;
|
|
|
|
if (!hal_spec->rx_tsf_filter
|
|
&& (rcr & RCR_CBSSID_BCN) && !(rcr_new & RCR_CBSSID_BCN))
|
|
rtw_hal_tsf_update_pause(adapter);
|
|
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr_new);
|
|
|
|
if (!hal_spec->rx_tsf_filter
|
|
&& !(rcr & RCR_CBSSID_BCN) && (rcr_new & RCR_CBSSID_BCN)
|
|
&& self_action != MLME_STA_CONNECTING)
|
|
rtw_hal_tsf_update_restore(adapter);
|
|
}
|
|
|
|
void rtw_hal_rcr_set_chk_bssid_act_non(_adapter *adapter)
|
|
{
|
|
rtw_hal_rcr_set_chk_bssid(adapter, MLME_ACTION_NONE);
|
|
}
|
|
|
|
static void hw_var_set_rcr_am(_adapter *adapter, u8 enable)
|
|
{
|
|
u32 rcr = RCR_AM;
|
|
|
|
if (enable)
|
|
rtw_hal_rcr_add(adapter, rcr);
|
|
else
|
|
rtw_hal_rcr_clear(adapter, rcr);
|
|
}
|
|
|
|
static void hw_var_set_bcn_interval(_adapter *adapter, u16 interval)
|
|
{
|
|
#ifdef CONFIG_SWTIMER_BASED_TXBCN
|
|
interval = rtw_hal_bcn_interval_adjust(adapter, interval);
|
|
#endif
|
|
|
|
#ifdef RTW_HALMAC
|
|
rtw_halmac_set_bcn_interval(adapter_to_dvobj(adapter), adapter->hw_port, interval);
|
|
#else
|
|
rtw_write16(adapter, REG_MBSSID_BCN_SPACE, interval);
|
|
#endif
|
|
|
|
#ifdef CONFIG_INTERRUPT_BASED_TXBCN_EARLY_INT
|
|
{
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
|
|
if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
|
|
RTW_INFO("%s==> bcn_interval:%d, eraly_int:%d\n", __func__, interval, interval >> 1);
|
|
rtw_write8(adapter, REG_DRVERLYINT, interval >> 1);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if CONFIG_TX_AC_LIFETIME
|
|
const char *const _tx_aclt_conf_str[] = {
|
|
"DEFAULT",
|
|
"AP_M2U",
|
|
"MESH",
|
|
"INVALID",
|
|
};
|
|
|
|
void dump_tx_aclt_force_val(void *sel, struct dvobj_priv *dvobj)
|
|
{
|
|
#define TX_ACLT_FORCE_MSG_LEN 64
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(dvobj_get_primary_adapter(dvobj));
|
|
struct tx_aclt_conf_t *conf = &dvobj->tx_aclt_force_val;
|
|
char buf[TX_ACLT_FORCE_MSG_LEN];
|
|
int cnt = 0;
|
|
|
|
RTW_PRINT_SEL(sel, "unit:%uus, maximum:%uus\n"
|
|
, hal_spec->tx_aclt_unit_factor * 32
|
|
, 0xFFFF * hal_spec->tx_aclt_unit_factor * 32);
|
|
|
|
RTW_PRINT_SEL(sel, "%-5s %-12s %-12s\n", "en", "vo_vi(us)", "be_bk(us)");
|
|
RTW_PRINT_SEL(sel, " 0x%02x %12u %12u\n"
|
|
, conf->en
|
|
, conf->vo_vi * hal_spec->tx_aclt_unit_factor * 32
|
|
, conf->be_bk * hal_spec->tx_aclt_unit_factor * 32
|
|
);
|
|
|
|
cnt += snprintf(buf + cnt, TX_ACLT_FORCE_MSG_LEN - cnt - 1, "%5s", conf->en == 0xFF ? "AUTO" : "FORCE");
|
|
if (cnt >= TX_ACLT_FORCE_MSG_LEN - 1)
|
|
goto exit;
|
|
|
|
if (conf->vo_vi)
|
|
cnt += snprintf(buf + cnt, TX_ACLT_FORCE_MSG_LEN - cnt - 1, " FORCE:0x%04x", conf->vo_vi);
|
|
else
|
|
cnt += snprintf(buf + cnt, TX_ACLT_FORCE_MSG_LEN - cnt - 1, " AUTO");
|
|
if (cnt >= TX_ACLT_FORCE_MSG_LEN - 1)
|
|
goto exit;
|
|
|
|
|
|
if (conf->be_bk)
|
|
cnt += snprintf(buf + cnt, TX_ACLT_FORCE_MSG_LEN - cnt - 1, " FORCE:0x%04x", conf->be_bk);
|
|
else
|
|
cnt += snprintf(buf + cnt, TX_ACLT_FORCE_MSG_LEN - cnt - 1, " AUTO");
|
|
if (cnt >= TX_ACLT_FORCE_MSG_LEN - 1)
|
|
goto exit;
|
|
|
|
RTW_PRINT_SEL(sel, "%s\n", buf);
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
void rtw_hal_set_tx_aclt_force_val(_adapter *adapter, struct tx_aclt_conf_t *input, u8 arg_num)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct tx_aclt_conf_t *conf = &dvobj->tx_aclt_force_val;
|
|
|
|
if (arg_num >= 1) {
|
|
if (input->en == 0xFF)
|
|
conf->en = input->en;
|
|
else
|
|
conf->en = input->en & 0xF;
|
|
}
|
|
if (arg_num >= 2) {
|
|
conf->vo_vi = input->vo_vi / (hal_spec->tx_aclt_unit_factor * 32);
|
|
if (conf->vo_vi > 0xFFFF)
|
|
conf->vo_vi = 0xFFFF;
|
|
}
|
|
if (arg_num >= 3) {
|
|
conf->be_bk = input->be_bk / (hal_spec->tx_aclt_unit_factor * 32);
|
|
if (conf->be_bk > 0xFFFF)
|
|
conf->be_bk = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
void dump_tx_aclt_confs(void *sel, struct dvobj_priv *dvobj)
|
|
{
|
|
#define TX_ACLT_CONF_MSG_LEN 32
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(dvobj_get_primary_adapter(dvobj));
|
|
struct tx_aclt_conf_t *conf;
|
|
char buf[TX_ACLT_CONF_MSG_LEN];
|
|
int cnt;
|
|
int i;
|
|
|
|
RTW_PRINT_SEL(sel, "unit:%uus, maximum:%uus\n"
|
|
, hal_spec->tx_aclt_unit_factor * 32
|
|
, 0xFFFF * hal_spec->tx_aclt_unit_factor * 32);
|
|
|
|
RTW_PRINT_SEL(sel, "%-7s %-1s %-3s %-9s %-9s %-10s %-10s\n"
|
|
, "name", "#", "en", "vo_vi(us)", "be_bk(us)", "vo_vi(reg)", "be_bk(reg)");
|
|
|
|
for (i = 0; i < TX_ACLT_CONF_NUM; i++) {
|
|
conf = &dvobj->tx_aclt_confs[i];
|
|
cnt = 0;
|
|
|
|
if (conf->vo_vi)
|
|
cnt += snprintf(buf + cnt, TX_ACLT_CONF_MSG_LEN - cnt - 1, " 0x%04x", conf->vo_vi);
|
|
else
|
|
cnt += snprintf(buf + cnt, TX_ACLT_CONF_MSG_LEN - cnt - 1, " N/A");
|
|
if (cnt >= TX_ACLT_CONF_MSG_LEN - 1)
|
|
continue;
|
|
|
|
if (conf->be_bk)
|
|
cnt += snprintf(buf + cnt, TX_ACLT_CONF_MSG_LEN - cnt - 1, " 0x%04x", conf->be_bk);
|
|
else
|
|
cnt += snprintf(buf + cnt, TX_ACLT_CONF_MSG_LEN - cnt - 1, " N/A");
|
|
if (cnt >= TX_ACLT_CONF_MSG_LEN - 1)
|
|
continue;
|
|
|
|
RTW_PRINT_SEL(sel, "%7s %1u 0x%x %9u %9u%s\n"
|
|
, tx_aclt_conf_str(i), i
|
|
, conf->en
|
|
, conf->vo_vi * hal_spec->tx_aclt_unit_factor * 32
|
|
, conf->be_bk * hal_spec->tx_aclt_unit_factor * 32
|
|
, buf
|
|
);
|
|
}
|
|
}
|
|
|
|
void rtw_hal_set_tx_aclt_conf(_adapter *adapter, u8 conf_idx, struct tx_aclt_conf_t *input, u8 arg_num)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct tx_aclt_conf_t *conf;
|
|
|
|
if (conf_idx >= TX_ACLT_CONF_NUM)
|
|
return;
|
|
|
|
conf = &dvobj->tx_aclt_confs[conf_idx];
|
|
|
|
if (arg_num >= 1) {
|
|
if (input->en != 0xFF)
|
|
conf->en = input->en & 0xF;
|
|
}
|
|
if (arg_num >= 2) {
|
|
conf->vo_vi = input->vo_vi / (hal_spec->tx_aclt_unit_factor * 32);
|
|
if (conf->vo_vi > 0xFFFF)
|
|
conf->vo_vi = 0xFFFF;
|
|
}
|
|
if (arg_num >= 3) {
|
|
conf->be_bk = input->be_bk / (hal_spec->tx_aclt_unit_factor * 32);
|
|
if (conf->be_bk > 0xFFFF)
|
|
conf->be_bk = 0xFFFF;
|
|
}
|
|
}
|
|
|
|
void rtw_hal_update_tx_aclt(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct macid_ctl_t *macid_ctl = adapter_to_macidctl(adapter);
|
|
u8 lt_en = 0, lt_en_ori;
|
|
u16 lt_vo_vi = 0xFFFF, lt_be_bk = 0xFFFF;
|
|
u32 lt, lt_ori;
|
|
struct tx_aclt_conf_t *conf;
|
|
int i;
|
|
#ifdef CONFIG_AP_MODE
|
|
#if CONFIG_RTW_AP_DATA_BMC_TO_UC
|
|
_adapter *iface;
|
|
u8 ap_m2u_num = 0;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
|
|
if (MLME_IS_AP(iface)
|
|
&& ((iface->b2u_flags_ap_src & RTW_AP_B2U_IP_MCAST)
|
|
|| (iface->b2u_flags_ap_fwd & RTW_AP_B2U_IP_MCAST))
|
|
)
|
|
ap_m2u_num++;
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_AP_MODE */
|
|
|
|
lt_en_ori = rtw_read8(adapter, REG_LIFETIME_EN);
|
|
lt_ori = rtw_read32(adapter, REG_PKT_LIFE_TIME);
|
|
|
|
for (i = 0; i < TX_ACLT_CONF_NUM; i++) {
|
|
if (!(dvobj->tx_aclt_flags & BIT(i)))
|
|
continue;
|
|
|
|
conf = &dvobj->tx_aclt_confs[i];
|
|
|
|
if (i == TX_ACLT_CONF_DEFAULT) {
|
|
/* first and default status, assign directly */
|
|
lt_en = conf->en;
|
|
if (conf->vo_vi)
|
|
lt_vo_vi = conf->vo_vi;
|
|
if (conf->be_bk)
|
|
lt_be_bk = conf->be_bk;
|
|
}
|
|
#ifdef CONFIG_AP_MODE
|
|
#if CONFIG_RTW_AP_DATA_BMC_TO_UC || defined(CONFIG_RTW_MESH)
|
|
else if (0
|
|
#if CONFIG_RTW_AP_DATA_BMC_TO_UC
|
|
|| (i == TX_ACLT_CONF_AP_M2U
|
|
&& ap_m2u_num
|
|
&& macid_ctl->op_num[H2C_MSR_ROLE_STA] /* having AP mode with STA connected */)
|
|
#endif
|
|
#ifdef CONFIG_RTW_MESH
|
|
|| (i == TX_ACLT_CONF_MESH
|
|
&& macid_ctl->op_num[H2C_MSR_ROLE_MESH] > 1 /* implies only 1 MESH mode supported */)
|
|
#endif
|
|
) {
|
|
/* long term status, OR en and MIN lifetime */
|
|
lt_en |= conf->en;
|
|
if (conf->vo_vi && lt_vo_vi > conf->vo_vi)
|
|
lt_vo_vi = conf->vo_vi;
|
|
if (conf->be_bk && lt_be_bk > conf->be_bk)
|
|
lt_be_bk = conf->be_bk;
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_AP_MODE */
|
|
}
|
|
|
|
if (dvobj->tx_aclt_force_val.en != 0xFF)
|
|
lt_en = dvobj->tx_aclt_force_val.en;
|
|
if (dvobj->tx_aclt_force_val.vo_vi)
|
|
lt_vo_vi = dvobj->tx_aclt_force_val.vo_vi;
|
|
if (dvobj->tx_aclt_force_val.be_bk)
|
|
lt_be_bk = dvobj->tx_aclt_force_val.be_bk;
|
|
|
|
lt_en = (lt_en_ori & 0xF0) | (lt_en & 0x0F);
|
|
lt = (lt_be_bk << 16) | lt_vo_vi;
|
|
|
|
if (0)
|
|
RTW_INFO("lt_en:0x%x(0x%x), lt:0x%08x(0x%08x)\n", lt_en, lt_en_ori, lt, lt_ori);
|
|
|
|
if (lt_en != lt_en_ori)
|
|
rtw_write8(adapter, REG_LIFETIME_EN, lt_en);
|
|
if (lt != lt_ori)
|
|
rtw_write32(adapter, REG_PKT_LIFE_TIME, lt);
|
|
}
|
|
#endif /* CONFIG_TX_AC_LIFETIME */
|
|
|
|
void hw_var_port_switch(_adapter *adapter)
|
|
{
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
#ifdef CONFIG_RUNTIME_PORT_SWITCH
|
|
/*
|
|
0x102: MSR
|
|
0x550: REG_BCN_CTRL
|
|
0x551: REG_BCN_CTRL_1
|
|
0x55A: REG_ATIMWND
|
|
0x560: REG_TSFTR
|
|
0x568: REG_TSFTR1
|
|
0x570: REG_ATIMWND_1
|
|
0x610: REG_MACID
|
|
0x618: REG_BSSID
|
|
0x700: REG_MACID1
|
|
0x708: REG_BSSID1
|
|
*/
|
|
|
|
int i;
|
|
u8 msr;
|
|
u8 bcn_ctrl;
|
|
u8 bcn_ctrl_1;
|
|
u8 atimwnd[2];
|
|
u8 atimwnd_1[2];
|
|
u8 tsftr[8];
|
|
u8 tsftr_1[8];
|
|
u8 macid[6];
|
|
u8 bssid[6];
|
|
u8 macid_1[6];
|
|
u8 bssid_1[6];
|
|
#if defined(CONFIG_RTL8192F)
|
|
u16 wlan_act_mask_ctrl = 0;
|
|
u16 en_port_mask = EN_PORT_0_FUNCTION | EN_PORT_1_FUNCTION;
|
|
#endif
|
|
|
|
u8 hw_port;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface = NULL;
|
|
|
|
msr = rtw_read8(adapter, MSR);
|
|
bcn_ctrl = rtw_read8(adapter, REG_BCN_CTRL);
|
|
bcn_ctrl_1 = rtw_read8(adapter, REG_BCN_CTRL_1);
|
|
#if defined(CONFIG_RTL8192F)
|
|
wlan_act_mask_ctrl = rtw_read16(adapter, REG_WLAN_ACT_MASK_CTRL_1);
|
|
#endif
|
|
|
|
for (i = 0; i < 2; i++)
|
|
atimwnd[i] = rtw_read8(adapter, REG_ATIMWND + i);
|
|
for (i = 0; i < 2; i++)
|
|
atimwnd_1[i] = rtw_read8(adapter, REG_ATIMWND_1 + i);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
tsftr[i] = rtw_read8(adapter, REG_TSFTR + i);
|
|
for (i = 0; i < 8; i++)
|
|
tsftr_1[i] = rtw_read8(adapter, REG_TSFTR1 + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
macid[i] = rtw_read8(adapter, REG_MACID + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
bssid[i] = rtw_read8(adapter, REG_BSSID + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
macid_1[i] = rtw_read8(adapter, REG_MACID1 + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
bssid_1[i] = rtw_read8(adapter, REG_BSSID1 + i);
|
|
|
|
#ifdef DBG_RUNTIME_PORT_SWITCH
|
|
RTW_INFO(FUNC_ADPT_FMT" before switch\n"
|
|
"msr:0x%02x\n"
|
|
"bcn_ctrl:0x%02x\n"
|
|
"bcn_ctrl_1:0x%02x\n"
|
|
#if defined(CONFIG_RTL8192F)
|
|
"wlan_act_mask_ctrl:0x%02x\n"
|
|
#endif
|
|
"atimwnd:0x%04x\n"
|
|
"atimwnd_1:0x%04x\n"
|
|
"tsftr:%llu\n"
|
|
"tsftr1:%llu\n"
|
|
"macid:"MAC_FMT"\n"
|
|
"bssid:"MAC_FMT"\n"
|
|
"macid_1:"MAC_FMT"\n"
|
|
"bssid_1:"MAC_FMT"\n"
|
|
, FUNC_ADPT_ARG(adapter)
|
|
, msr
|
|
, bcn_ctrl
|
|
, bcn_ctrl_1
|
|
#if defined(CONFIG_RTL8192F)
|
|
, wlan_act_mask_ctrl
|
|
#endif
|
|
, *((u16 *)atimwnd)
|
|
, *((u16 *)atimwnd_1)
|
|
, *((u64 *)tsftr)
|
|
, *((u64 *)tsftr_1)
|
|
, MAC_ARG(macid)
|
|
, MAC_ARG(bssid)
|
|
, MAC_ARG(macid_1)
|
|
, MAC_ARG(bssid_1)
|
|
);
|
|
#endif /* DBG_RUNTIME_PORT_SWITCH */
|
|
|
|
/* disable bcn function, disable update TSF */
|
|
rtw_write8(adapter, REG_BCN_CTRL, (bcn_ctrl & (~EN_BCN_FUNCTION)) | DIS_TSF_UDT);
|
|
rtw_write8(adapter, REG_BCN_CTRL_1, (bcn_ctrl_1 & (~EN_BCN_FUNCTION)) | DIS_TSF_UDT);
|
|
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(adapter, REG_WLAN_ACT_MASK_CTRL_1, wlan_act_mask_ctrl & ~en_port_mask);
|
|
#endif
|
|
|
|
/* switch msr */
|
|
msr = (msr & 0xf0) | ((msr & 0x03) << 2) | ((msr & 0x0c) >> 2);
|
|
rtw_write8(adapter, MSR, msr);
|
|
|
|
/* write port0 */
|
|
rtw_write8(adapter, REG_BCN_CTRL, bcn_ctrl_1 & ~EN_BCN_FUNCTION);
|
|
for (i = 0; i < 2; i++)
|
|
rtw_write8(adapter, REG_ATIMWND + i, atimwnd_1[i]);
|
|
for (i = 0; i < 8; i++)
|
|
rtw_write8(adapter, REG_TSFTR + i, tsftr_1[i]);
|
|
for (i = 0; i < 6; i++)
|
|
rtw_write8(adapter, REG_MACID + i, macid_1[i]);
|
|
for (i = 0; i < 6; i++)
|
|
rtw_write8(adapter, REG_BSSID + i, bssid_1[i]);
|
|
|
|
/* write port1 */
|
|
rtw_write8(adapter, REG_BCN_CTRL_1, bcn_ctrl & ~EN_BCN_FUNCTION);
|
|
for (i = 0; i < 2; i++)
|
|
rtw_write8(adapter, REG_ATIMWND_1 + i, atimwnd[i]);
|
|
for (i = 0; i < 8; i++)
|
|
rtw_write8(adapter, REG_TSFTR1 + i, tsftr[i]);
|
|
for (i = 0; i < 6; i++)
|
|
rtw_write8(adapter, REG_MACID1 + i, macid[i]);
|
|
for (i = 0; i < 6; i++)
|
|
rtw_write8(adapter, REG_BSSID1 + i, bssid[i]);
|
|
|
|
/* write bcn ctl */
|
|
#ifdef CONFIG_BT_COEXIST
|
|
/* always enable port0 beacon function for PSTDMA */
|
|
if (IS_HARDWARE_TYPE_8723B(adapter) || IS_HARDWARE_TYPE_8703B(adapter)
|
|
|| IS_HARDWARE_TYPE_8723D(adapter))
|
|
bcn_ctrl_1 |= EN_BCN_FUNCTION;
|
|
/* always disable port1 beacon function for PSTDMA */
|
|
if (IS_HARDWARE_TYPE_8723B(adapter) || IS_HARDWARE_TYPE_8703B(adapter))
|
|
bcn_ctrl &= ~EN_BCN_FUNCTION;
|
|
#endif
|
|
rtw_write8(adapter, REG_BCN_CTRL, bcn_ctrl_1);
|
|
rtw_write8(adapter, REG_BCN_CTRL_1, bcn_ctrl);
|
|
|
|
#if defined(CONFIG_RTL8192F)
|
|
/* if the setting of port0 and port1 are the same, it does not need to switch port setting*/
|
|
if(((wlan_act_mask_ctrl & en_port_mask) != 0) && ((wlan_act_mask_ctrl & en_port_mask)
|
|
!= (EN_PORT_0_FUNCTION | EN_PORT_1_FUNCTION)))
|
|
wlan_act_mask_ctrl ^= en_port_mask;
|
|
rtw_write16(adapter, REG_WLAN_ACT_MASK_CTRL_1, wlan_act_mask_ctrl);
|
|
#endif
|
|
|
|
if (adapter->iface_id == IFACE_ID0)
|
|
iface = dvobj->padapters[IFACE_ID1];
|
|
else if (adapter->iface_id == IFACE_ID1)
|
|
iface = dvobj->padapters[IFACE_ID0];
|
|
|
|
|
|
if (adapter->hw_port == HW_PORT0) {
|
|
adapter->hw_port = HW_PORT1;
|
|
iface->hw_port = HW_PORT0;
|
|
RTW_PRINT("port switch - port0("ADPT_FMT"), port1("ADPT_FMT")\n",
|
|
ADPT_ARG(iface), ADPT_ARG(adapter));
|
|
} else {
|
|
adapter->hw_port = HW_PORT0;
|
|
iface->hw_port = HW_PORT1;
|
|
RTW_PRINT("port switch - port0("ADPT_FMT"), port1("ADPT_FMT")\n",
|
|
ADPT_ARG(adapter), ADPT_ARG(iface));
|
|
}
|
|
|
|
#ifdef DBG_RUNTIME_PORT_SWITCH
|
|
msr = rtw_read8(adapter, MSR);
|
|
bcn_ctrl = rtw_read8(adapter, REG_BCN_CTRL);
|
|
bcn_ctrl_1 = rtw_read8(adapter, REG_BCN_CTRL_1);
|
|
#if defined(CONFIG_RTL8192F)
|
|
wlan_act_mask_ctrl = rtw_read16(adapter, REG_WLAN_ACT_MASK_CTRL_1);
|
|
#endif
|
|
|
|
for (i = 0; i < 2; i++)
|
|
atimwnd[i] = rtw_read8(adapter, REG_ATIMWND + i);
|
|
for (i = 0; i < 2; i++)
|
|
atimwnd_1[i] = rtw_read8(adapter, REG_ATIMWND_1 + i);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
tsftr[i] = rtw_read8(adapter, REG_TSFTR + i);
|
|
for (i = 0; i < 8; i++)
|
|
tsftr_1[i] = rtw_read8(adapter, REG_TSFTR1 + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
macid[i] = rtw_read8(adapter, REG_MACID + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
bssid[i] = rtw_read8(adapter, REG_BSSID + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
macid_1[i] = rtw_read8(adapter, REG_MACID1 + i);
|
|
|
|
for (i = 0; i < 6; i++)
|
|
bssid_1[i] = rtw_read8(adapter, REG_BSSID1 + i);
|
|
|
|
RTW_INFO(FUNC_ADPT_FMT" after switch\n"
|
|
"msr:0x%02x\n"
|
|
"bcn_ctrl:0x%02x\n"
|
|
"bcn_ctrl_1:0x%02x\n"
|
|
#if defined(CONFIG_RTL8192F)
|
|
"wlan_act_mask_ctrl:0x%02x\n"
|
|
#endif
|
|
"atimwnd:%u\n"
|
|
"atimwnd_1:%u\n"
|
|
"tsftr:%llu\n"
|
|
"tsftr1:%llu\n"
|
|
"macid:"MAC_FMT"\n"
|
|
"bssid:"MAC_FMT"\n"
|
|
"macid_1:"MAC_FMT"\n"
|
|
"bssid_1:"MAC_FMT"\n"
|
|
, FUNC_ADPT_ARG(adapter)
|
|
, msr
|
|
, bcn_ctrl
|
|
, bcn_ctrl_1
|
|
#if defined(CONFIG_RTL8192F)
|
|
, wlan_act_mask_ctrl
|
|
#endif
|
|
, *((u16 *)atimwnd)
|
|
, *((u16 *)atimwnd_1)
|
|
, *((u64 *)tsftr)
|
|
, *((u64 *)tsftr_1)
|
|
, MAC_ARG(macid)
|
|
, MAC_ARG(bssid)
|
|
, MAC_ARG(macid_1)
|
|
, MAC_ARG(bssid_1)
|
|
);
|
|
#endif /* DBG_RUNTIME_PORT_SWITCH */
|
|
|
|
#endif /* CONFIG_RUNTIME_PORT_SWITCH */
|
|
#endif /* CONFIG_CONCURRENT_MODE */
|
|
}
|
|
|
|
const char *const _h2c_msr_role_str[] = {
|
|
"RSVD",
|
|
"STA",
|
|
"AP",
|
|
"GC",
|
|
"GO",
|
|
"TDLS",
|
|
"ADHOC",
|
|
"MESH",
|
|
"INVALID",
|
|
};
|
|
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
s32 rtw_hal_set_default_port_id_cmd(_adapter *adapter, u8 mac_id)
|
|
{
|
|
s32 ret = _SUCCESS;
|
|
u8 parm[H2C_DEFAULT_PORT_ID_LEN] = {0};
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
u8 port_id = rtw_hal_get_port(adapter);
|
|
|
|
if ((dvobj->dft.port_id == port_id) && (dvobj->dft.mac_id == mac_id))
|
|
return ret;
|
|
|
|
SET_H2CCMD_DFTPID_PORT_ID(parm, port_id);
|
|
SET_H2CCMD_DFTPID_MAC_ID(parm, mac_id);
|
|
|
|
RTW_DBG_DUMP("DFT port id parm:", parm, H2C_DEFAULT_PORT_ID_LEN);
|
|
RTW_INFO("%s ("ADPT_FMT") port_id :%d, mad_id:%d\n",
|
|
__func__, ADPT_ARG(adapter), port_id, mac_id);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_DEFAULT_PORT_ID, H2C_DEFAULT_PORT_ID_LEN, parm);
|
|
dvobj->dft.port_id = port_id;
|
|
dvobj->dft.mac_id = mac_id;
|
|
|
|
return ret;
|
|
}
|
|
s32 rtw_set_default_port_id(_adapter *adapter)
|
|
{
|
|
s32 ret = _SUCCESS;
|
|
struct sta_info *psta;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
|
|
if (is_client_associated_to_ap(adapter)) {
|
|
psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
|
|
if (psta)
|
|
ret = rtw_hal_set_default_port_id_cmd(adapter, psta->cmn.mac_id);
|
|
} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {
|
|
|
|
} else {
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
s32 rtw_set_ps_rsvd_page(_adapter *adapter)
|
|
{
|
|
s32 ret = _SUCCESS;
|
|
u16 media_status_rpt = RT_MEDIA_CONNECT;
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
|
|
if (adapter->iface_id == pwrctl->fw_psmode_iface_id)
|
|
return ret;
|
|
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT,
|
|
(u8 *)&media_status_rpt);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if 0
|
|
_adapter * _rtw_search_dp_iface(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface;
|
|
_adapter *target_iface = NULL;
|
|
int i;
|
|
u8 sta_num = 0, tdls_num = 0, ap_num = 0, mesh_num = 0, adhoc_num = 0;
|
|
u8 p2p_go_num = 0, p2p_gc_num = 0;
|
|
_adapter *sta_ifs[8];
|
|
_adapter *ap_ifs[8];
|
|
_adapter *mesh_ifs[8];
|
|
_adapter *gc_ifs[8];
|
|
_adapter *go_ifs[8];
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE) == _TRUE) {
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
|
|
sta_ifs[sta_num++] = iface;
|
|
|
|
#ifdef CONFIG_TDLS
|
|
if (iface->tdlsinfo.link_established == _TRUE)
|
|
tdls_num++;
|
|
#endif
|
|
#ifdef CONFIG_P2P
|
|
if (MLME_IS_GC(iface))
|
|
gc_ifs[p2p_gc_num++] = iface;
|
|
#endif
|
|
}
|
|
#ifdef CONFIG_AP_MODE
|
|
} else if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == _TRUE ) {
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
|
|
ap_ifs[ap_num++] = iface;
|
|
#ifdef CONFIG_P2P
|
|
if (MLME_IS_GO(iface))
|
|
go_ifs[p2p_go_num++] = iface;
|
|
#endif
|
|
}
|
|
#endif
|
|
} else if (check_fwstate(&iface->mlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE) == _TRUE
|
|
&& check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE
|
|
) {
|
|
adhoc_num++;
|
|
|
|
#ifdef CONFIG_RTW_MESH
|
|
} else if (check_fwstate(&iface->mlmepriv, WIFI_MESH_STATE) == _TRUE
|
|
&& check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE
|
|
) {
|
|
mesh_ifs[mesh_num++] = iface;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (p2p_gc_num) {
|
|
target_iface = gc_ifs[0];
|
|
}
|
|
else if (sta_num) {
|
|
if(sta_num == 1) {
|
|
target_iface = sta_ifs[0];
|
|
} else if (sta_num >= 2) {
|
|
/*TODO get target_iface by timestamp*/
|
|
target_iface = sta_ifs[0];
|
|
}
|
|
} else if (ap_num) {
|
|
target_iface = ap_ifs[0];
|
|
}
|
|
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - STA :%d", sta_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - TDLS :%d", tdls_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - AP:%d", ap_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - MESH :%d", mesh_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - ADHOC :%d", adhoc_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - P2P-GC :%d", p2p_gc_num);
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - P2P-GO :%d", p2p_go_num);
|
|
|
|
if (target_iface)
|
|
RTW_INFO("%s => target_iface ("ADPT_FMT")\n",
|
|
__func__, ADPT_ARG(target_iface));
|
|
else
|
|
RTW_INFO("%s => target_iface NULL\n", __func__);
|
|
|
|
return target_iface;
|
|
}
|
|
|
|
void rtw_search_default_port(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *adp_iface = NULL;
|
|
#ifdef CONFIG_WOWLAN
|
|
struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
|
|
|
|
if (pwrpriv->wowlan_mode == _TRUE) {
|
|
adp_iface = adapter;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
adp_iface = _rtw_search_dp_iface(adapter);
|
|
|
|
exit :
|
|
if ((adp_iface != NULL) && (MLME_IS_STA(adp_iface)))
|
|
rtw_set_default_port_id(adp_iface);
|
|
else
|
|
rtw_hal_set_default_port_id_cmd(adapter, 0);
|
|
|
|
if (1) {
|
|
_adapter *tmp_adp;
|
|
|
|
tmp_adp = (adp_iface) ? adp_iface : adapter;
|
|
|
|
RTW_INFO("%s ("ADPT_FMT")=> hw_port :%d, default_port(%d)\n",
|
|
__func__, ADPT_ARG(adapter), get_hw_port(tmp_adp), get_dft_portid(tmp_adp));
|
|
}
|
|
}
|
|
#endif
|
|
#endif /*CONFIG_FW_MULTI_PORT_SUPPORT*/
|
|
|
|
#ifdef CONFIG_P2P_PS
|
|
#ifdef RTW_HALMAC
|
|
void rtw_set_p2p_ps_offload_cmd(_adapter *adapter, u8 p2p_ps_state)
|
|
{
|
|
PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
|
|
struct wifidirect_info *pwdinfo = &adapter->wdinfo;
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
|
struct sta_priv *pstapriv = &adapter->stapriv;
|
|
struct sta_info *psta;
|
|
HAL_P2P_PS_PARA p2p_ps_para;
|
|
int status = -1;
|
|
u8 i;
|
|
u8 hw_port = rtw_hal_get_port(adapter);
|
|
|
|
_rtw_memset(&p2p_ps_para, 0, sizeof(HAL_P2P_PS_PARA));
|
|
_rtw_memcpy((&p2p_ps_para) , &hal->p2p_ps_offload , sizeof(hal->p2p_ps_offload));
|
|
|
|
(&p2p_ps_para)->p2p_port_id = hw_port;
|
|
(&p2p_ps_para)->p2p_group = 0;
|
|
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
|
|
if (psta) {
|
|
(&p2p_ps_para)->p2p_macid = psta->cmn.mac_id;
|
|
} else {
|
|
if (p2p_ps_state != P2P_PS_DISABLE) {
|
|
RTW_ERR("%s , psta was NULL\n", __func__);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
switch (p2p_ps_state) {
|
|
case P2P_PS_DISABLE:
|
|
RTW_INFO("P2P_PS_DISABLE\n");
|
|
_rtw_memset(&p2p_ps_para , 0, sizeof(HAL_P2P_PS_PARA));
|
|
break;
|
|
|
|
case P2P_PS_ENABLE:
|
|
RTW_INFO("P2P_PS_ENABLE\n");
|
|
/* update CTWindow value. */
|
|
if (pwdinfo->ctwindow > 0) {
|
|
(&p2p_ps_para)->ctwindow_en = 1;
|
|
(&p2p_ps_para)->ctwindow_length = pwdinfo->ctwindow;
|
|
/*RTW_INFO("%s , ctwindow_length = %d\n" , __func__ , (&p2p_ps_para)->ctwindow_length);*/
|
|
}
|
|
|
|
|
|
if ((pwdinfo->opp_ps == 1) || (pwdinfo->noa_num > 0)) {
|
|
(&p2p_ps_para)->offload_en = 1;
|
|
if (pwdinfo->role == P2P_ROLE_GO) {
|
|
(&p2p_ps_para)->role = 1;
|
|
(&p2p_ps_para)->all_sta_sleep = 0;
|
|
} else
|
|
(&p2p_ps_para)->role = 0;
|
|
|
|
(&p2p_ps_para)->discovery = 0;
|
|
}
|
|
/* hw only support 2 set of NoA */
|
|
for (i = 0; i < pwdinfo->noa_num; i++) {
|
|
/* To control the register setting for which NOA */
|
|
(&p2p_ps_para)->noa_sel = i;
|
|
(&p2p_ps_para)->noa_en = 1;
|
|
(&p2p_ps_para)->disable_close_rf = 0;
|
|
#ifdef CONFIG_P2P_PS_NOA_USE_MACID_SLEEP
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_buddy_check_fwstate(adapter, WIFI_ASOC_STATE))
|
|
#endif /* CONFIG_CONCURRENT_MODE */
|
|
(&p2p_ps_para)->disable_close_rf = 1;
|
|
#endif /* CONFIG_P2P_PS_NOA_USE_MACID_SLEEP */
|
|
/* config P2P NoA Descriptor Register */
|
|
/* config NOA duration */
|
|
(&p2p_ps_para)->noa_duration_para = pwdinfo->noa_duration[i];
|
|
/* config NOA interval */
|
|
(&p2p_ps_para)->noa_interval_para = pwdinfo->noa_interval[i];
|
|
/* config NOA start time */
|
|
(&p2p_ps_para)->noa_start_time_para = pwdinfo->noa_start_time[i];
|
|
/* config NOA count */
|
|
(&p2p_ps_para)->noa_count_para = pwdinfo->noa_count[i];
|
|
/*RTW_INFO("%s , noa_duration_para = %d , noa_interval_para = %d , noa_start_time_para = %d , noa_count_para = %d\n" , __func__ ,
|
|
(&p2p_ps_para)->noa_duration_para , (&p2p_ps_para)->noa_interval_para ,
|
|
(&p2p_ps_para)->noa_start_time_para , (&p2p_ps_para)->noa_count_para);*/
|
|
status = rtw_halmac_p2pps(adapter_to_dvobj(adapter) , (&p2p_ps_para));
|
|
if (status == -1)
|
|
RTW_ERR("%s , rtw_halmac_p2pps fail\n", __func__);
|
|
}
|
|
|
|
break;
|
|
|
|
case P2P_PS_SCAN:
|
|
/*This feature FW not ready 20161116 YiWei*/
|
|
return;
|
|
/*
|
|
RTW_INFO("P2P_PS_SCAN\n");
|
|
(&p2p_ps_para)->discovery = 1;
|
|
(&p2p_ps_para)->ctwindow_length = pwdinfo->ctwindow;
|
|
(&p2p_ps_para)->noa_duration_para = pwdinfo->noa_duration[0];
|
|
(&p2p_ps_para)->noa_interval_para = pwdinfo->noa_interval[0];
|
|
(&p2p_ps_para)->noa_start_time_para = pwdinfo->noa_start_time[0];
|
|
(&p2p_ps_para)->noa_count_para = pwdinfo->noa_count[0];
|
|
*/
|
|
break;
|
|
|
|
case P2P_PS_SCAN_DONE:
|
|
/*This feature FW not ready 20161116 YiWei*/
|
|
return;
|
|
/*
|
|
RTW_INFO("P2P_PS_SCAN_DONE\n");
|
|
(&p2p_ps_para)->discovery = 0;
|
|
pwdinfo->p2p_ps_state = P2P_PS_ENABLE;
|
|
(&p2p_ps_para)->ctwindow_length = pwdinfo->ctwindow;
|
|
(&p2p_ps_para)->noa_duration_para = pwdinfo->noa_duration[0];
|
|
(&p2p_ps_para)->noa_interval_para = pwdinfo->noa_interval[0];
|
|
(&p2p_ps_para)->noa_start_time_para = pwdinfo->noa_start_time[0];
|
|
(&p2p_ps_para)->noa_count_para = pwdinfo->noa_count[0];
|
|
*/
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (p2p_ps_state != P2P_PS_ENABLE || (&p2p_ps_para)->noa_en == 0) {
|
|
status = rtw_halmac_p2pps(adapter_to_dvobj(adapter) , (&p2p_ps_para));
|
|
if (status == -1)
|
|
RTW_ERR("%s , rtw_halmac_p2pps fail\n", __func__);
|
|
}
|
|
_rtw_memcpy(&hal->p2p_ps_offload , (&p2p_ps_para) , sizeof(hal->p2p_ps_offload));
|
|
|
|
}
|
|
#endif /* RTW_HALMAC */
|
|
#endif /* CONFIG_P2P */
|
|
|
|
#if defined(CONFIG_RTL8822C) && defined(CONFIG_SUPPORT_DYNAMIC_TXPWR)
|
|
static void _rtw_hal_dtp_macid_set(
|
|
_adapter *padapter, u8 opmode, u8 mac_id)
|
|
{
|
|
struct macid_ctl_t *macid_ctl = &(padapter->dvobj->macid_ctl);
|
|
struct sta_info *psta;
|
|
u8 h2c_cmd[H2C_FW_CRC5_SEARCH_LEN] = {0};
|
|
u8 mac_addr[ETH_ALEN] = {0};
|
|
|
|
if (opmode) {
|
|
psta = macid_ctl->sta[mac_id];
|
|
if (psta)
|
|
_rtw_memcpy(mac_addr, psta->cmn.mac_addr, ETH_ALEN);
|
|
|
|
if (rtw_check_invalid_mac_address(mac_addr, _FALSE))
|
|
return;
|
|
}
|
|
/* else DON'T CARE H2C_FW_CRC5_SEARCH mac addr in disconnected case */
|
|
|
|
if (rtw_get_chip_type(padapter) == RTL8822C) {
|
|
SET_H2CCMD_FW_CRC5_SEARCH_EN(h2c_cmd, opmode);
|
|
SET_H2CCMD_FW_CRC5_SEARCH_MACID(h2c_cmd, mac_id);
|
|
SET_H2CCMD_FW_CRC5_SEARCH_MAC(&h2c_cmd[1], mac_addr);
|
|
if (rtw_hal_fill_h2c_cmd(padapter, H2C_FW_CRC5_SEARCH,
|
|
H2C_FW_CRC5_SEARCH_LEN, h2c_cmd) != _SUCCESS)
|
|
RTW_WARN("%s : set h2c - 0x%02x fail!\n", __func__, H2C_FW_CRC5_SEARCH);
|
|
}
|
|
}
|
|
|
|
static void rtw_hal_dtp_macid_set(_adapter *padapter, u8 opmode,
|
|
bool macid_ind, u8 mac_id, u8 macid_end)
|
|
{
|
|
int i;
|
|
|
|
if (macid_ind == 0) {
|
|
_rtw_hal_dtp_macid_set(padapter, opmode, mac_id);
|
|
} else {
|
|
for (i = mac_id; i <= macid_end; i++)
|
|
_rtw_hal_dtp_macid_set(padapter, opmode, i);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* rtw_hal_set_FwMediaStatusRpt_cmd -
|
|
*
|
|
* @adapter:
|
|
* @opmode: 0:disconnect, 1:connect
|
|
* @miracast: 0:it's not in miracast scenario. 1:it's in miracast scenario
|
|
* @miracast_sink: 0:source. 1:sink
|
|
* @role: The role of this macid. 0:rsvd. 1:STA. 2:AP. 3:GC. 4:GO. 5:TDLS
|
|
* @macid:
|
|
* @macid_ind: 0:update Media Status to macid. 1:update Media Status from macid to macid_end
|
|
* @macid_end:
|
|
*/
|
|
s32 rtw_hal_set_FwMediaStatusRpt_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid, bool macid_ind, u8 macid_end)
|
|
{
|
|
struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl;
|
|
u8 parm[H2C_MEDIA_STATUS_RPT_LEN] = {0};
|
|
int i;
|
|
s32 ret;
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
u8 hw_port = rtw_hal_get_port(adapter);
|
|
#endif
|
|
u8 op_num_change_bmp = 0;
|
|
|
|
#if defined(CONFIG_RTL8822C) && defined(CONFIG_SUPPORT_DYNAMIC_TXPWR)
|
|
rtw_hal_dtp_macid_set(adapter, opmode, macid_ind, macid, macid_end);
|
|
#endif
|
|
|
|
SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, opmode);
|
|
SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, macid_ind);
|
|
SET_H2CCMD_MSRRPT_PARM_MIRACAST(parm, miracast);
|
|
SET_H2CCMD_MSRRPT_PARM_MIRACAST_SINK(parm, miracast_sink);
|
|
SET_H2CCMD_MSRRPT_PARM_ROLE(parm, role);
|
|
SET_H2CCMD_MSRRPT_PARM_MACID(parm, macid);
|
|
SET_H2CCMD_MSRRPT_PARM_MACID_END(parm, macid_end);
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
SET_H2CCMD_MSRRPT_PARM_PORT_NUM(parm, hw_port);
|
|
#endif
|
|
RTW_DBG_DUMP("MediaStatusRpt parm:", parm, H2C_MEDIA_STATUS_RPT_LEN);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_MEDIA_STATUS_RPT, H2C_MEDIA_STATUS_RPT_LEN, parm);
|
|
if (ret != _SUCCESS)
|
|
goto exit;
|
|
|
|
#if defined(CONFIG_RTL8188E)
|
|
if (rtw_get_chip_type(adapter) == RTL8188E) {
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
|
|
/* 8188E FW doesn't set macid no link, driver does it by self */
|
|
if (opmode)
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_MACID_LINK, &macid);
|
|
else
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_MACID_NOLINK, &macid);
|
|
|
|
/* for 8188E RA */
|
|
#if (RATE_ADAPTIVE_SUPPORT == 1)
|
|
if (hal_data->fw_ractrl == _FALSE) {
|
|
u8 max_macid;
|
|
|
|
max_macid = rtw_search_max_mac_id(adapter);
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, &max_macid);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
|
|
/* TODO: this should move to IOT issue area */
|
|
if (rtw_get_chip_type(adapter) == RTL8812
|
|
|| rtw_get_chip_type(adapter) == RTL8821
|
|
) {
|
|
if (MLME_IS_STA(adapter))
|
|
Hal_PatchwithJaguar_8812(adapter, opmode);
|
|
}
|
|
#endif
|
|
|
|
SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
|
|
if (macid_ind == 0)
|
|
macid_end = macid;
|
|
|
|
for (i = macid; macid <= macid_end; macid++) {
|
|
op_num_change_bmp |= rtw_macid_ctl_set_h2c_msr(macid_ctl, macid, parm[0]);
|
|
if (!opmode) {
|
|
rtw_macid_ctl_set_bw(macid_ctl, macid, CHANNEL_WIDTH_20);
|
|
rtw_macid_ctl_set_vht_en(macid_ctl, macid, 0);
|
|
rtw_macid_ctl_set_rate_bmp0(macid_ctl, macid, 0);
|
|
rtw_macid_ctl_set_rate_bmp1(macid_ctl, macid, 0);
|
|
}
|
|
}
|
|
|
|
#if CONFIG_TX_AC_LIFETIME
|
|
if (op_num_change_bmp)
|
|
rtw_hal_update_tx_aclt(adapter);
|
|
#endif
|
|
|
|
if (!opmode)
|
|
rtw_update_tx_rate_bmp(adapter_to_dvobj(adapter));
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
inline s32 rtw_hal_set_FwMediaStatusRpt_single_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid)
|
|
{
|
|
return rtw_hal_set_FwMediaStatusRpt_cmd(adapter, opmode, miracast, miracast_sink, role, macid, 0, 0);
|
|
}
|
|
|
|
inline s32 rtw_hal_set_FwMediaStatusRpt_range_cmd(_adapter *adapter, bool opmode, bool miracast, bool miracast_sink, u8 role, u8 macid, u8 macid_end)
|
|
{
|
|
return rtw_hal_set_FwMediaStatusRpt_cmd(adapter, opmode, miracast, miracast_sink, role, macid, 1, macid_end);
|
|
}
|
|
|
|
void rtw_hal_set_FwRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
u8 u1H2CRsvdPageParm[H2C_RSVDPAGE_LOC_LEN] = {0};
|
|
u8 ret = 0;
|
|
|
|
RTW_INFO("RsvdPageLoc: ProbeRsp=%d PsPoll=%d Null=%d QoSNull=%d BTNull=%d\n",
|
|
rsvdpageloc->LocProbeRsp, rsvdpageloc->LocPsPoll,
|
|
rsvdpageloc->LocNullData, rsvdpageloc->LocQosNull,
|
|
rsvdpageloc->LocBTQosNull);
|
|
|
|
SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1H2CRsvdPageParm, rsvdpageloc->LocProbeRsp);
|
|
SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1H2CRsvdPageParm, rsvdpageloc->LocPsPoll);
|
|
SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocNullData);
|
|
SET_H2CCMD_RSVDPAGE_LOC_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocQosNull);
|
|
SET_H2CCMD_RSVDPAGE_LOC_BT_QOS_NULL_DATA(u1H2CRsvdPageParm, rsvdpageloc->LocBTQosNull);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(padapter,
|
|
H2C_RSVD_PAGE,
|
|
H2C_RSVDPAGE_LOC_LEN,
|
|
u1H2CRsvdPageParm);
|
|
|
|
}
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
void rtw_hal_switch_gpio_wl_ctrl(_adapter *padapter, u8 index, u8 enable)
|
|
{
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
|
|
|
|
if (IS_8723D_SERIES(pHalData->version_id) || IS_8192F_SERIES(pHalData->version_id)
|
|
|| IS_8822B_SERIES(pHalData->version_id) || IS_8821C_SERIES(pHalData->version_id)
|
|
|| IS_8822C_SERIES(pHalData->version_id))
|
|
rtw_hal_set_hwreg(padapter, HW_SET_GPIO_WL_CTRL, (u8 *)(&enable));
|
|
/*
|
|
* Switch GPIO_13, GPIO_14 to wlan control, or pull GPIO_13,14 MUST fail.
|
|
* It happended at 8723B/8192E/8821A. New IC will check multi function GPIO,
|
|
* and implement HAL function.
|
|
* TODO: GPIO_8 multi function?
|
|
*/
|
|
|
|
if ((index == 13 || index == 14)
|
|
#if defined(CONFIG_RTL8821A) && defined(CONFIG_SDIO_HCI)
|
|
/* 8821A's LED2 circuit(used by HW_LED strategy) needs enable WL GPIO control of GPIO[14:13], can't disable */
|
|
&& (!IS_HW_LED_STRATEGY(rtw_led_get_strategy(padapter)) || enable)
|
|
#endif
|
|
)
|
|
rtw_hal_set_hwreg(padapter, HW_SET_GPIO_WL_CTRL, (u8 *)(&enable));
|
|
}
|
|
|
|
void rtw_hal_set_output_gpio(_adapter *padapter, u8 index, u8 outputval)
|
|
{
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_WOW_OUTPUT_GPIO, (u8 *)(&outputval));
|
|
#else
|
|
if (index <= 7) {
|
|
/* config GPIO mode */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 3,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(index));
|
|
|
|
/* config GPIO Sel */
|
|
/* 0: input */
|
|
/* 1: output */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 2,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 2) | BIT(index));
|
|
|
|
/* set output value */
|
|
if (outputval) {
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) | BIT(index));
|
|
} else {
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 1,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 1) & ~BIT(index));
|
|
}
|
|
} else if (index <= 15) {
|
|
/* 88C Series: */
|
|
/* index: 11~8 transform to 3~0 */
|
|
/* 8723 Series: */
|
|
/* index: 12~8 transform to 4~0 */
|
|
|
|
index -= 8;
|
|
|
|
/* config GPIO mode */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 3,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 3) & ~BIT(index));
|
|
|
|
/* config GPIO Sel */
|
|
/* 0: input */
|
|
/* 1: output */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 2,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 2) | BIT(index));
|
|
|
|
/* set output value */
|
|
if (outputval) {
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) | BIT(index));
|
|
} else {
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 1,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 1) & ~BIT(index));
|
|
}
|
|
} else {
|
|
RTW_INFO("%s: invalid GPIO%d=%d\n",
|
|
__FUNCTION__, index, outputval);
|
|
}
|
|
#endif
|
|
}
|
|
void rtw_hal_set_input_gpio(_adapter *padapter, u8 index)
|
|
{
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_WOW_INPUT_GPIO, (u8 *)(&index));
|
|
#else
|
|
if (index <= 7) {
|
|
/* config GPIO mode */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 3,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(index));
|
|
|
|
/* config GPIO Sel */
|
|
/* 0: input */
|
|
/* 1: output */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL + 2,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL + 2) & ~BIT(index));
|
|
|
|
} else if (index <= 15) {
|
|
/* 88C Series: */
|
|
/* index: 11~8 transform to 3~0 */
|
|
/* 8723 Series: */
|
|
/* index: 12~8 transform to 4~0 */
|
|
|
|
index -= 8;
|
|
|
|
/* config GPIO mode */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 3,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 3) & ~BIT(index));
|
|
|
|
/* config GPIO Sel */
|
|
/* 0: input */
|
|
/* 1: output */
|
|
rtw_write8(padapter, REG_GPIO_PIN_CTRL_2 + 2,
|
|
rtw_read8(padapter, REG_GPIO_PIN_CTRL_2 + 2) & ~BIT(index));
|
|
} else
|
|
RTW_INFO("%s: invalid GPIO%d\n", __func__, index);
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
void rtw_hal_set_FwAoacRsvdPage_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
u8 ret = 0;
|
|
#ifdef CONFIG_WOWLAN
|
|
u8 u1H2CAoacRsvdPageParm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0};
|
|
|
|
RTW_INFO("%s: RWC: %d ArpRsp: %d NbrAdv: %d LocNDPInfo: %d\n",
|
|
__func__, rsvdpageloc->LocRemoteCtrlInfo,
|
|
rsvdpageloc->LocArpRsp, rsvdpageloc->LocNbrAdv,
|
|
rsvdpageloc->LocNDPInfo);
|
|
RTW_INFO("%s:GtkRsp: %d GtkInfo: %d ProbeReq: %d NetworkList: %d\n",
|
|
__func__, rsvdpageloc->LocGTKRsp, rsvdpageloc->LocGTKInfo,
|
|
rsvdpageloc->LocProbeReq, rsvdpageloc->LocNetList);
|
|
|
|
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) {
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_REMOTE_WAKE_CTRL_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocRemoteCtrlInfo);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_ARP_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocArpRsp);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_NEIGHBOR_ADV(u1H2CAoacRsvdPageParm,
|
|
rsvdpageloc->LocNbrAdv);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_NDP_INFO(u1H2CAoacRsvdPageParm,
|
|
rsvdpageloc->LocNDPInfo);
|
|
#ifdef CONFIG_GTK_OL
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_RSP(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKRsp);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_INFO(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKInfo);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_GTK_EXT_MEM(u1H2CAoacRsvdPageParm, rsvdpageloc->LocGTKEXTMEM);
|
|
#endif /* CONFIG_GTK_OL */
|
|
ret = rtw_hal_fill_h2c_cmd(padapter,
|
|
H2C_AOAC_RSVD_PAGE,
|
|
H2C_AOAC_RSVDPAGE_LOC_LEN,
|
|
u1H2CAoacRsvdPageParm);
|
|
|
|
RTW_INFO("AOAC Report=%d\n", rsvdpageloc->LocAOACReport);
|
|
_rtw_memset(&u1H2CAoacRsvdPageParm, 0, sizeof(u1H2CAoacRsvdPageParm));
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_AOAC_REPORT(u1H2CAoacRsvdPageParm,
|
|
rsvdpageloc->LocAOACReport);
|
|
ret = rtw_hal_fill_h2c_cmd(padapter,
|
|
H2C_AOAC_RSVDPAGE3,
|
|
H2C_AOAC_RSVDPAGE_LOC_LEN,
|
|
u1H2CAoacRsvdPageParm);
|
|
pwrpriv->wowlan_aoac_rpt_loc = rsvdpageloc->LocAOACReport;
|
|
}
|
|
#if defined(CONFIG_PNO_SUPPORT) && !defined(RTW_HALMAC)
|
|
else {
|
|
|
|
if (!pwrpriv->wowlan_in_resume) {
|
|
RTW_INFO("NLO_INFO=%d\n", rsvdpageloc->LocPNOInfo);
|
|
_rtw_memset(&u1H2CAoacRsvdPageParm, 0,
|
|
sizeof(u1H2CAoacRsvdPageParm));
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_NLO_INFO(u1H2CAoacRsvdPageParm,
|
|
rsvdpageloc->LocPNOInfo);
|
|
ret = rtw_hal_fill_h2c_cmd(padapter,
|
|
H2C_AOAC_RSVDPAGE3,
|
|
H2C_AOAC_RSVDPAGE_LOC_LEN,
|
|
u1H2CAoacRsvdPageParm);
|
|
}
|
|
}
|
|
#endif /* defined(CONFIG_PNO_SUPPORT) && !defined(RTW_HALMAC) */
|
|
#endif /* CONFIG_WOWLAN */
|
|
}
|
|
|
|
#ifdef DBG_FW_DEBUG_MSG_PKT
|
|
void rtw_hal_set_fw_dbg_msg_pkt_rsvd_page_cmd(PADAPTER padapter, PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
struct hal_ops *pHalFunc = &padapter->hal_func;
|
|
u8 u1H2C_fw_dbg_msg_pkt_parm[H2C_FW_DBG_MSG_PKT_LEN] = {0};
|
|
u8 ret = 0;
|
|
|
|
|
|
RTW_INFO("RsvdPageLoc: loc_fw_dbg_msg_pkt =%d\n", rsvdpageloc->loc_fw_dbg_msg_pkt);
|
|
|
|
SET_H2CCMD_FW_DBG_MSG_PKT_EN(u1H2C_fw_dbg_msg_pkt_parm, 1);
|
|
SET_H2CCMD_RSVDPAGE_LOC_FW_DBG_MSG_PKT(u1H2C_fw_dbg_msg_pkt_parm, rsvdpageloc->loc_fw_dbg_msg_pkt);
|
|
ret = rtw_hal_fill_h2c_cmd(padapter,
|
|
H2C_FW_DBG_MSG_PKT,
|
|
H2C_FW_DBG_MSG_PKT_LEN,
|
|
u1H2C_fw_dbg_msg_pkt_parm);
|
|
|
|
}
|
|
#endif /*DBG_FW_DEBUG_MSG_PKT*/
|
|
|
|
/*#define DBG_GET_RSVD_PAGE*/
|
|
int rtw_hal_get_rsvd_page(_adapter *adapter, u32 page_offset,
|
|
u32 page_num, u8 *buffer, u32 buffer_size)
|
|
{
|
|
u32 addr = 0, size = 0, count = 0;
|
|
u32 page_size = 0, data_low = 0, data_high = 0;
|
|
u16 txbndy = 0, offset = 0;
|
|
u8 i = 0;
|
|
bool rst = _FALSE;
|
|
|
|
#ifdef DBG_LA_MODE
|
|
struct registry_priv *registry_par = &adapter->registrypriv;
|
|
|
|
if(registry_par->la_mode_en == 1) {
|
|
RTW_INFO("%s LA debug mode can't dump rsvd pg \n", __func__);
|
|
return rst;
|
|
}
|
|
#endif
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
|
|
|
|
addr = page_offset * page_size;
|
|
size = page_num * page_size;
|
|
|
|
if (buffer_size < size) {
|
|
RTW_ERR("%s buffer_size(%d) < get page total size(%d)\n",
|
|
__func__, buffer_size, size);
|
|
return rst;
|
|
}
|
|
#ifdef RTW_HALMAC
|
|
if (rtw_halmac_dump_fifo(adapter_to_dvobj(adapter), 2, addr, size, buffer) < 0)
|
|
rst = _FALSE;
|
|
else
|
|
rst = _TRUE;
|
|
#else
|
|
txbndy = rtw_read8(adapter, REG_TDECTRL + 1);
|
|
|
|
offset = (txbndy + page_offset) * page_size / 8;
|
|
count = (buffer_size / 8) + 1;
|
|
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, 0x69);
|
|
|
|
for (i = 0 ; i < count ; i++) {
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_CTRL, offset + i);
|
|
data_low = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L);
|
|
data_high = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H);
|
|
_rtw_memcpy(buffer + (i * 8),
|
|
&data_low, sizeof(data_low));
|
|
_rtw_memcpy(buffer + ((i * 8) + 4),
|
|
&data_high, sizeof(data_high));
|
|
}
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, 0x0);
|
|
rst = _TRUE;
|
|
#endif /*RTW_HALMAC*/
|
|
|
|
#ifdef DBG_GET_RSVD_PAGE
|
|
RTW_INFO("%s [page_offset:%d , page_num:%d][start_addr:0x%04x , size:%d]\n",
|
|
__func__, page_offset, page_num, addr, size);
|
|
RTW_INFO_DUMP("\n", buffer, size);
|
|
RTW_INFO(" ==================================================\n");
|
|
#endif
|
|
return rst;
|
|
}
|
|
|
|
void rtw_dump_rsvd_page(void *sel, _adapter *adapter, u8 page_offset, u8 page_num)
|
|
{
|
|
#if defined(CONFIG_RTW_DEBUG) || defined(CONFIG_PROC_DEBUG)
|
|
u32 page_size = 0;
|
|
u8 *buffer = NULL;
|
|
u32 buf_size = 0;
|
|
|
|
if (page_num == 0)
|
|
return;
|
|
|
|
RTW_PRINT_SEL(sel, "======= RSVD PAGE DUMP =======\n");
|
|
RTW_PRINT_SEL(sel, "page_offset:%d, page_num:%d\n", page_offset, page_num);
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
|
|
if (page_size) {
|
|
buf_size = page_size * page_num;
|
|
buffer = rtw_zvmalloc(buf_size);
|
|
|
|
if (buffer) {
|
|
rtw_hal_get_rsvd_page(adapter, page_offset, page_num, buffer, buf_size);
|
|
RTW_DUMP_SEL(sel, buffer, buf_size);
|
|
rtw_vmfree(buffer, buf_size);
|
|
} else
|
|
RTW_PRINT_SEL(sel, "ERROR - rsvd_buf mem allocate failed\n");
|
|
} else
|
|
RTW_PRINT_SEL(sel, "ERROR - Tx page size is zero ??\n");
|
|
|
|
RTW_PRINT_SEL(sel, "==========================\n");
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_SUPPORT_FIFO_DUMP
|
|
void rtw_dump_fifo(void *sel, _adapter *adapter, u8 fifo_sel, u32 fifo_addr, u32 fifo_size)
|
|
{
|
|
u8 *buffer = NULL;
|
|
u32 buff_size = 0;
|
|
static const char * const fifo_sel_str[] = {
|
|
"TX", "RX", "RSVD_PAGE", "REPORT", "LLT", "RXBUF_FW"
|
|
};
|
|
|
|
if (fifo_sel > 5) {
|
|
RTW_ERR("fifo_sel:%d invalid\n", fifo_sel);
|
|
return;
|
|
}
|
|
|
|
RTW_PRINT_SEL(sel, "========= FIFO DUMP =========\n");
|
|
RTW_PRINT_SEL(sel, "%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[fifo_sel], fifo_addr, fifo_size);
|
|
|
|
if (fifo_size) {
|
|
buff_size = RND4(fifo_size);
|
|
buffer = rtw_zvmalloc(buff_size);
|
|
if (buffer == NULL)
|
|
buff_size = 0;
|
|
}
|
|
|
|
rtw_halmac_dump_fifo(adapter_to_dvobj(adapter), fifo_sel, fifo_addr, buff_size, buffer);
|
|
|
|
if (buffer) {
|
|
RTW_DUMP_SEL(sel, buffer, fifo_size);
|
|
rtw_vmfree(buffer, buff_size);
|
|
}
|
|
|
|
RTW_PRINT_SEL(sel, "==========================\n");
|
|
}
|
|
#endif
|
|
|
|
u8 rtw_hal_pause_rx_dma(_adapter *adapter)
|
|
{
|
|
PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
|
|
u8 ret = 0;
|
|
s8 trycnt = 100;
|
|
u32 tmp = 0;
|
|
int res = 0;
|
|
/* RX DMA stop */
|
|
RTW_PRINT("Pause DMA\n");
|
|
rtw_write32(adapter, REG_RXPKT_NUM,
|
|
(rtw_read32(adapter, REG_RXPKT_NUM) | RW_RELEASE_EN));
|
|
do {
|
|
if ((rtw_read32(adapter, REG_RXPKT_NUM) & RXDMA_IDLE)) {
|
|
#ifdef CONFIG_USB_HCI
|
|
/* stop interface before leave */
|
|
if (_TRUE == hal->usb_intf_start) {
|
|
rtw_intf_stop(adapter);
|
|
RTW_ENABLE_FUNC(adapter, DF_RX_BIT);
|
|
RTW_ENABLE_FUNC(adapter, DF_TX_BIT);
|
|
}
|
|
#endif /* CONFIG_USB_HCI */
|
|
|
|
RTW_PRINT("RX_DMA_IDLE is true\n");
|
|
ret = _SUCCESS;
|
|
break;
|
|
}
|
|
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
|
else {
|
|
res = RecvOnePkt(adapter);
|
|
RTW_PRINT("RecvOnePkt Result: %d\n", res);
|
|
}
|
|
#endif /* CONFIG_SDIO_HCI || CONFIG_GSPI_HCI */
|
|
|
|
#ifdef CONFIG_USB_HCI
|
|
else {
|
|
/* to avoid interface start repeatedly */
|
|
if (_FALSE == hal->usb_intf_start)
|
|
rtw_intf_start(adapter);
|
|
}
|
|
#endif /* CONFIG_USB_HCI */
|
|
} while (trycnt--);
|
|
|
|
if (trycnt <= 0) {
|
|
tmp = rtw_read16(adapter, REG_RXPKT_NUM + 2);
|
|
|
|
RTW_PRINT("Stop RX DMA failed......\n");
|
|
#if defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B)
|
|
RTW_PRINT("%s, RXPKT_NUM: 0x%04x\n",
|
|
__func__, rtw_read16(adapter, REG_RXPKTNUM));
|
|
#else
|
|
RTW_PRINT("%s, RXPKT_NUM: 0x%02x\n",
|
|
__func__, ((tmp & 0xFF00) >> 8));
|
|
#endif
|
|
if (tmp & BIT(3))
|
|
RTW_PRINT("%s, RX DMA has req\n",
|
|
__func__);
|
|
else
|
|
RTW_PRINT("%s, RX DMA no req\n",
|
|
__func__);
|
|
ret = _FAIL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
|
|
static void rtw_hal_force_enable_rxdma(_adapter *adapter)
|
|
{
|
|
RTW_INFO("%s: Set 0x690=0x00\n", __func__);
|
|
rtw_write8(adapter, REG_WOW_CTRL,
|
|
(rtw_read8(adapter, REG_WOW_CTRL) & 0xf0));
|
|
RTW_PRINT("%s: Release RXDMA\n", __func__);
|
|
rtw_write32(adapter, REG_RXPKT_NUM,
|
|
(rtw_read32(adapter, REG_RXPKT_NUM) & (~RW_RELEASE_EN)));
|
|
}
|
|
#if defined(CONFIG_RTL8188E)
|
|
static void rtw_hal_disable_tx_report(_adapter *adapter)
|
|
{
|
|
rtw_write8(adapter, REG_TX_RPT_CTRL,
|
|
((rtw_read8(adapter, REG_TX_RPT_CTRL) & ~BIT(1))) & ~BIT(5));
|
|
RTW_INFO("disable TXRPT:0x%02x\n", rtw_read8(adapter, REG_TX_RPT_CTRL));
|
|
}
|
|
|
|
static void rtw_hal_enable_tx_report(_adapter *adapter)
|
|
{
|
|
rtw_write8(adapter, REG_TX_RPT_CTRL,
|
|
((rtw_read8(adapter, REG_TX_RPT_CTRL) | BIT(1))) | BIT(5));
|
|
RTW_INFO("enable TX_RPT:0x%02x\n", rtw_read8(adapter, REG_TX_RPT_CTRL));
|
|
}
|
|
#endif
|
|
static void rtw_hal_release_rx_dma(_adapter *adapter)
|
|
{
|
|
u32 val32 = 0;
|
|
|
|
val32 = rtw_read32(adapter, REG_RXPKT_NUM);
|
|
|
|
rtw_write32(adapter, REG_RXPKT_NUM, (val32 & (~RW_RELEASE_EN)));
|
|
|
|
RTW_INFO("%s, [0x%04x]: 0x%08x\n",
|
|
__func__, REG_RXPKT_NUM, (u32)(val32 & (~RW_RELEASE_EN)));
|
|
}
|
|
|
|
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
|
#ifndef RTW_HALMAC
|
|
static u8 rtw_hal_enable_cpwm2(_adapter *adapter)
|
|
{
|
|
u8 ret = 0;
|
|
int res = 0;
|
|
u32 tmp = 0;
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
return _SUCCESS;
|
|
#else
|
|
RTW_PRINT("%s\n", __func__);
|
|
|
|
res = sdio_local_read(adapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
|
|
if (!res)
|
|
RTW_INFO("read SDIO_REG_HIMR: 0x%08x\n", tmp);
|
|
else
|
|
RTW_INFO("sdio_local_read fail\n");
|
|
|
|
tmp = SDIO_HIMR_CPWM2_MSK;
|
|
|
|
res = sdio_local_write(adapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
|
|
|
|
if (!res) {
|
|
res = sdio_local_read(adapter, SDIO_REG_HIMR, 4, (u8 *)&tmp);
|
|
RTW_INFO("read again SDIO_REG_HIMR: 0x%08x\n", tmp);
|
|
ret = _SUCCESS;
|
|
} else {
|
|
RTW_INFO("sdio_local_write fail\n");
|
|
ret = _FAIL;
|
|
}
|
|
return ret;
|
|
#endif /* CONFIG_CPIO_WAKEUP */
|
|
}
|
|
#endif
|
|
#endif /* CONFIG_SDIO_HCI, CONFIG_GSPI_HCI */
|
|
#endif /* CONFIG_WOWLAN || CONFIG_AP_WOWLAN */
|
|
|
|
#ifdef CONFIG_WOWLAN
|
|
/*
|
|
* rtw_hal_check_wow_ctrl
|
|
* chk_type: _TRUE means to check enable, if 0x690 & bit1 (for 8051), WOW enable successful.
|
|
* If 0x1C7 == 0 (for 3081), WOW enable successful.
|
|
* _FALSE means to check disable, if 0x690 & bit1 (for 8051), WOW disable fail.
|
|
* If 0x120 & bit16 || 0x284 & bit18 (for 3081), WOW disable fail.
|
|
*/
|
|
static u8 rtw_hal_check_wow_ctrl(_adapter *adapter, u8 chk_type)
|
|
{
|
|
u32 fe1_imr = 0xFF, rxpkt_num = 0xFF;
|
|
u8 mstatus = 0;
|
|
u8 reason = 0xFF;
|
|
u8 trycnt = 25;
|
|
u8 res = _FALSE;
|
|
|
|
if (IS_HARDWARE_TYPE_JAGUAR2(adapter) || IS_HARDWARE_TYPE_JAGUAR3(adapter)) {
|
|
if (chk_type) {
|
|
reason = rtw_read8(adapter, REG_WOWLAN_WAKE_REASON);
|
|
RTW_INFO("%s reason:0x%02x\n", __func__, reason);
|
|
|
|
while (reason && trycnt > 1) {
|
|
reason = rtw_read8(adapter, REG_WOWLAN_WAKE_REASON);
|
|
RTW_PRINT("Loop index: %d :0x%02x\n",
|
|
trycnt, reason);
|
|
trycnt--;
|
|
rtw_msleep_os(20);
|
|
}
|
|
if (!reason)
|
|
res = _TRUE;
|
|
else
|
|
res = _FALSE;
|
|
} else {
|
|
/* Wait FW to cleare 0x120 bit16, 0x284 bit18 to 0 */
|
|
fe1_imr = rtw_read32(adapter, REG_FE1IMR); /* RxDone IMR for 3081 */
|
|
rxpkt_num = rtw_read32(adapter, REG_RXPKT_NUM); /* Release RXDMA */
|
|
RTW_PRINT("%s REG_FE1IMR (reg120): 0x%x, REG_RXPKT_NUM(reg284): 0x%x\n", __func__, fe1_imr, rxpkt_num);
|
|
|
|
while (((fe1_imr & BIT_FS_RXDONE_INT_EN) || (rxpkt_num & BIT_RW_RELEASE_EN)) && trycnt > 1) {
|
|
rtw_msleep_os(20);
|
|
fe1_imr = rtw_read32(adapter, REG_FE1IMR);
|
|
rxpkt_num = rtw_read32(adapter, REG_RXPKT_NUM);
|
|
RTW_PRINT("Loop index: %d :0x%x, 0x%x\n",
|
|
trycnt, fe1_imr, rxpkt_num);
|
|
trycnt--;
|
|
}
|
|
|
|
if ((fe1_imr & BIT_FS_RXDONE_INT_EN) || (rxpkt_num & BIT_RW_RELEASE_EN))
|
|
res = _FALSE;
|
|
else
|
|
res = _TRUE;
|
|
}
|
|
} else {
|
|
mstatus = rtw_read8(adapter, REG_WOW_CTRL);
|
|
RTW_INFO("%s mstatus:0x%02x\n", __func__, mstatus);
|
|
|
|
|
|
if (chk_type) {
|
|
while (!(mstatus & BIT1) && trycnt > 1) {
|
|
mstatus = rtw_read8(adapter, REG_WOW_CTRL);
|
|
RTW_PRINT("Loop index: %d :0x%02x\n",
|
|
trycnt, mstatus);
|
|
trycnt--;
|
|
rtw_msleep_os(20);
|
|
}
|
|
if (mstatus & BIT1)
|
|
res = _TRUE;
|
|
else
|
|
res = _FALSE;
|
|
} else {
|
|
while (mstatus & BIT1 && trycnt > 1) {
|
|
mstatus = rtw_read8(adapter, REG_WOW_CTRL);
|
|
RTW_PRINT("Loop index: %d :0x%02x\n",
|
|
trycnt, mstatus);
|
|
trycnt--;
|
|
rtw_msleep_os(20);
|
|
}
|
|
|
|
if (mstatus & BIT1)
|
|
res = _FALSE;
|
|
else
|
|
res = _TRUE;
|
|
}
|
|
}
|
|
|
|
RTW_PRINT("%s check_type: %d res: %d trycnt: %d\n",
|
|
__func__, chk_type, res, (25 - trycnt));
|
|
return res;
|
|
}
|
|
|
|
#if defined(CONFIG_PNO_SUPPORT) && !defined(RTW_HALMAC)
|
|
static u8 rtw_hal_check_pno_enabled(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
u8 res = 0, count = 0;
|
|
u8 ret = _FALSE;
|
|
|
|
if (ppwrpriv->wowlan_pno_enable && ppwrpriv->wowlan_in_resume == _FALSE) {
|
|
res = rtw_read8(adapter, REG_PNO_STATUS);
|
|
while (!(res & BIT(7)) && count < 25) {
|
|
RTW_INFO("[%d] cmd: 0x81 REG_PNO_STATUS: 0x%02x\n",
|
|
count, res);
|
|
res = rtw_read8(adapter, REG_PNO_STATUS);
|
|
count++;
|
|
rtw_msleep_os(2);
|
|
}
|
|
if (res & BIT(7))
|
|
ret = _TRUE;
|
|
else
|
|
ret = _FALSE;
|
|
RTW_INFO("cmd: 0x81 REG_PNO_STATUS: ret(%d)\n", ret);
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
static void rtw_hal_backup_rate(_adapter *adapter)
|
|
{
|
|
RTW_INFO("%s\n", __func__);
|
|
/* backup data rate to register 0x8b for wowlan FW */
|
|
rtw_write8(adapter, 0x8d, 1);
|
|
rtw_write8(adapter, 0x8c, 0);
|
|
rtw_write8(adapter, 0x8f, 0x40);
|
|
rtw_write8(adapter, 0x8b, rtw_read8(adapter, 0x2f0));
|
|
}
|
|
|
|
#ifdef CONFIG_GTK_OL
|
|
static void rtw_hal_fw_sync_cam_id(_adapter *adapter)
|
|
{
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
int cam_id, index = 0;
|
|
u8 *addr = NULL;
|
|
|
|
if (!MLME_IS_STA(adapter))
|
|
return;
|
|
|
|
addr = get_bssid(pmlmepriv);
|
|
|
|
if (addr == NULL) {
|
|
RTW_INFO("%s: get bssid MAC addr fail!!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
rtw_clean_dk_section(adapter);
|
|
|
|
do {
|
|
cam_id = rtw_camid_search(adapter, addr, index, 1);
|
|
|
|
if (cam_id == -1)
|
|
RTW_INFO("%s: cam_id: %d, key_id:%d\n", __func__, cam_id, index);
|
|
else
|
|
rtw_sec_cam_swap(adapter, cam_id, index);
|
|
|
|
index++;
|
|
} while (index < 4);
|
|
|
|
rtw_write8(adapter, REG_SECCFG, 0xcc);
|
|
}
|
|
|
|
static void rtw_hal_update_gtk_offload_info(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
|
|
_irqL irqL;
|
|
u8 get_key[16];
|
|
u8 gtk_id = 0, offset = 0, i = 0, sz = 0, aoac_rpt_ver = 0, has_rekey = _FALSE;
|
|
u64 replay_count = 0, tmp_iv_hdr = 0, pkt_pn = 0;
|
|
|
|
if (!MLME_IS_STA(adapter))
|
|
return;
|
|
|
|
_rtw_memset(get_key, 0, sizeof(get_key));
|
|
_rtw_memcpy(&replay_count,
|
|
paoac_rpt->replay_counter_eapol_key, 8);
|
|
|
|
/*read gtk key index*/
|
|
gtk_id = paoac_rpt->key_index;
|
|
aoac_rpt_ver = paoac_rpt->version_info;
|
|
|
|
if (aoac_rpt_ver == 0) {
|
|
/* initial verison */
|
|
if (gtk_id == 5)
|
|
has_rekey = _FALSE;
|
|
else
|
|
has_rekey = _TRUE;
|
|
} else if (aoac_rpt_ver >= 1) {
|
|
/* Add krack patch */
|
|
if (gtk_id == 5)
|
|
RTW_WARN("%s FW check iv fail\n", __func__);
|
|
|
|
if (aoac_rpt_ver == 1)
|
|
RTW_WARN("%s aoac report version should be update to v2\n", __func__);
|
|
|
|
/* Fix key id mismatch */
|
|
if (aoac_rpt_ver == 2)
|
|
has_rekey = paoac_rpt->rekey_ok == 1 ? _TRUE : _FALSE;
|
|
}
|
|
|
|
if (has_rekey == _FALSE) {
|
|
RTW_INFO("%s no rekey event happened.\n", __func__);
|
|
} else if (has_rekey == _TRUE) {
|
|
RTW_INFO("%s update security key.\n", __func__);
|
|
/*read key from sec-cam,for DK ,keyindex is equal to cam-id*/
|
|
rtw_sec_read_cam_ent(adapter, gtk_id,
|
|
NULL, NULL, get_key);
|
|
rtw_clean_hw_dk_cam(adapter);
|
|
|
|
if (_rtw_camid_is_gk(adapter, gtk_id)) {
|
|
_enter_critical_bh(&cam_ctl->lock, &irqL);
|
|
_rtw_memcpy(&dvobj->cam_cache[gtk_id].key,
|
|
get_key, 16);
|
|
_exit_critical_bh(&cam_ctl->lock, &irqL);
|
|
} else {
|
|
struct setkey_parm parm_gtk;
|
|
|
|
parm_gtk.algorithm = paoac_rpt->security_type;
|
|
parm_gtk.keyid = gtk_id;
|
|
_rtw_memcpy(parm_gtk.key, get_key, 16);
|
|
setkey_hdl(adapter, (u8 *)&parm_gtk);
|
|
}
|
|
|
|
/*update key into related sw variable and sec-cam cache*/
|
|
psecuritypriv->dot118021XGrpKeyid = gtk_id;
|
|
_rtw_memcpy(&psecuritypriv->dot118021XGrpKey[gtk_id],
|
|
get_key, 16);
|
|
/* update SW TKIP TX/RX MIC value */
|
|
if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_) {
|
|
offset = RTW_KEK_LEN + RTW_TKIP_MIC_LEN;
|
|
_rtw_memcpy(
|
|
&psecuritypriv->dot118021XGrptxmickey[gtk_id],
|
|
&(paoac_rpt->group_key[offset]),
|
|
RTW_TKIP_MIC_LEN);
|
|
|
|
offset = RTW_KEK_LEN;
|
|
_rtw_memcpy(
|
|
&psecuritypriv->dot118021XGrprxmickey[gtk_id],
|
|
&(paoac_rpt->group_key[offset]),
|
|
RTW_TKIP_MIC_LEN);
|
|
}
|
|
RTW_PRINT("GTK (%d) "KEY_FMT"\n", gtk_id,
|
|
KEY_ARG(psecuritypriv->dot118021XGrpKey[gtk_id].skey));
|
|
}
|
|
|
|
/* Update broadcast RX IV */
|
|
if (psecuritypriv->dot118021XGrpPrivacy == _AES_) {
|
|
sz = sizeof(psecuritypriv->iv_seq[0]);
|
|
for (i = 0 ; i < 4 ; i++) {
|
|
_rtw_memcpy(&tmp_iv_hdr, paoac_rpt->rxgtk_iv[i], sz);
|
|
tmp_iv_hdr = le64_to_cpu(tmp_iv_hdr);
|
|
pkt_pn = CCMPH_2_PN(tmp_iv_hdr);
|
|
_rtw_memcpy(psecuritypriv->iv_seq[i], &pkt_pn, sz);
|
|
}
|
|
}
|
|
|
|
rtw_clean_dk_section(adapter);
|
|
|
|
rtw_write8(adapter, REG_SECCFG, 0x0c);
|
|
|
|
#ifdef CONFIG_GTK_OL_DBG
|
|
/* if (gtk_keyindex != 5) */
|
|
dump_sec_cam(RTW_DBGDUMP, adapter);
|
|
dump_sec_cam_cache(RTW_DBGDUMP, adapter);
|
|
#endif
|
|
}
|
|
#endif /*CONFIG_GTK_OL*/
|
|
|
|
static void rtw_dump_aoac_rpt(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt;
|
|
int i = 0;
|
|
|
|
RTW_INFO_DUMP("[AOAC-RPT] IV -", paoac_rpt->iv, 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] Replay counter of EAPOL key - ",
|
|
paoac_rpt->replay_counter_eapol_key, 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] Group key - ", paoac_rpt->group_key, 32);
|
|
RTW_INFO("[AOAC-RPT] Key Index - %d\n", paoac_rpt->key_index);
|
|
RTW_INFO("[AOAC-RPT] Security Type - %d\n", paoac_rpt->security_type);
|
|
RTW_INFO("[AOAC-RPT] wow_pattern_idx - %d\n",
|
|
paoac_rpt->wow_pattern_idx);
|
|
RTW_INFO("[AOAC-RPT] version_info - %d\n", paoac_rpt->version_info);
|
|
RTW_INFO("[AOAC-RPT] rekey_ok - %d\n", paoac_rpt->rekey_ok);
|
|
RTW_INFO_DUMP("[AOAC-RPT] RX PTK IV-", paoac_rpt->rxptk_iv, 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] RX GTK[0] IV-", paoac_rpt->rxgtk_iv[0], 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] RX GTK[1] IV-", paoac_rpt->rxgtk_iv[1], 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] RX GTK[2] IV-", paoac_rpt->rxgtk_iv[2], 8);
|
|
RTW_INFO_DUMP("[AOAC-RPT] RX GTK[3] IV-", paoac_rpt->rxgtk_iv[3], 8);
|
|
}
|
|
|
|
static void rtw_hal_get_aoac_rpt(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt;
|
|
u32 page_offset = 0, page_number = 0;
|
|
u32 page_size = 0, buf_size = 0;
|
|
u8 *buffer = NULL;
|
|
u8 i = 0, tmp = 0;
|
|
int ret = -1;
|
|
|
|
/* read aoac report from rsvd page */
|
|
page_offset = pwrctl->wowlan_aoac_rpt_loc;
|
|
page_number = 1;
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
|
|
buf_size = page_size * page_number;
|
|
|
|
buffer = rtw_zvmalloc(buf_size);
|
|
|
|
if (buffer == NULL) {
|
|
RTW_ERR("%s buffer allocate failed size(%d)\n",
|
|
__func__, buf_size);
|
|
return;
|
|
}
|
|
|
|
RTW_INFO("Get AOAC Report from rsvd page_offset:%d\n", page_offset);
|
|
|
|
ret = rtw_hal_get_rsvd_page(adapter, page_offset,
|
|
page_number, buffer, buf_size);
|
|
|
|
if (ret == _FALSE) {
|
|
RTW_ERR("%s get aoac report failed\n", __func__);
|
|
rtw_warn_on(1);
|
|
goto _exit;
|
|
}
|
|
|
|
_rtw_memset(paoac_rpt, 0, sizeof(struct aoac_report));
|
|
_rtw_memcpy(paoac_rpt, buffer, sizeof(struct aoac_report));
|
|
|
|
for (i = 0 ; i < 4 ; i++) {
|
|
tmp = paoac_rpt->replay_counter_eapol_key[i];
|
|
paoac_rpt->replay_counter_eapol_key[i] =
|
|
paoac_rpt->replay_counter_eapol_key[7 - i];
|
|
paoac_rpt->replay_counter_eapol_key[7 - i] = tmp;
|
|
}
|
|
|
|
rtw_dump_aoac_rpt(adapter);
|
|
|
|
_exit:
|
|
if (buffer)
|
|
rtw_vmfree(buffer, buf_size);
|
|
}
|
|
|
|
static void rtw_hal_update_tx_iv(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct aoac_report *paoac_rpt = &pwrctl->wowlan_aoac_rpt;
|
|
struct sta_info *psta;
|
|
struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecpriv = &adapter->securitypriv;
|
|
|
|
u16 val16 = 0;
|
|
u32 val32 = 0;
|
|
u64 txiv = 0;
|
|
u8 *pval = NULL;
|
|
|
|
psta = rtw_get_stainfo(&adapter->stapriv,
|
|
get_my_bssid(&pmlmeinfo->network));
|
|
|
|
/* Update TX iv data. */
|
|
pval = (u8 *)&paoac_rpt->iv;
|
|
|
|
if (psecpriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
val16 = ((u16)(paoac_rpt->iv[2]) << 0) +
|
|
((u16)(paoac_rpt->iv[0]) << 8);
|
|
val32 = ((u32)(paoac_rpt->iv[4]) << 0) +
|
|
((u32)(paoac_rpt->iv[5]) << 8) +
|
|
((u32)(paoac_rpt->iv[6]) << 16) +
|
|
((u32)(paoac_rpt->iv[7]) << 24);
|
|
} else if (psecpriv->dot11PrivacyAlgrthm == _AES_) {
|
|
val16 = ((u16)(paoac_rpt->iv[0]) << 0) +
|
|
((u16)(paoac_rpt->iv[1]) << 8);
|
|
val32 = ((u32)(paoac_rpt->iv[4]) << 0) +
|
|
((u32)(paoac_rpt->iv[5]) << 8) +
|
|
((u32)(paoac_rpt->iv[6]) << 16) +
|
|
((u32)(paoac_rpt->iv[7]) << 24);
|
|
}
|
|
|
|
if (psta) {
|
|
txiv = val16 + ((u64)val32 << 16);
|
|
if (txiv != 0)
|
|
psta->dot11txpn.val = txiv;
|
|
}
|
|
}
|
|
|
|
static void rtw_hal_update_sw_security_info(_adapter *adapter)
|
|
{
|
|
struct security_priv *psecpriv = &adapter->securitypriv;
|
|
u8 sz = sizeof (psecpriv->iv_seq);
|
|
|
|
rtw_hal_update_tx_iv(adapter);
|
|
#ifdef CONFIG_GTK_OL
|
|
if (psecpriv->binstallKCK_KEK == _TRUE &&
|
|
(psecpriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK || _rtw_wow_chk_cap(adapter, WOW_CAP_TKIP_OL)))
|
|
rtw_hal_update_gtk_offload_info(adapter);
|
|
#else
|
|
_rtw_memset(psecpriv->iv_seq, 0, sz);
|
|
#endif
|
|
}
|
|
#ifdef CONFIG_CUSTOM_PULSE
|
|
static u8 rtw_hal_set_gpio_custom_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
u8 H2CGpioCustomParm[H2C_GPIO_CUSTOM_LEN] = {0};
|
|
u8 customid = 0x2, special_wakeup_reason = RX_MAGIC_PKT, custom_for_wakeup_reason=0x1;
|
|
u8 ret = _FAIL;
|
|
|
|
RTW_INFO("%s(): enable = %d\n", __func__, enable);
|
|
|
|
if(enable) {
|
|
SET_H2CCMD_CUSTOMERID(H2CGpioCustomParm, customid);
|
|
SET_H2CCMD_SPECIAL_WAKE_REASON(H2CGpioCustomParm, special_wakeup_reason);
|
|
SET_H2CCMD_CUSTOM_WAKE_REASON(H2CGpioCustomParm, custom_for_wakeup_reason);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_GPIO_CUSTOM,
|
|
H2C_GPIO_CUSTOM_LEN,
|
|
H2CGpioCustomParm);
|
|
RTW_DBG("%s(): H2C_cmd=%x, cmd=%02x, %02x, %02x\n", __func__, H2C_GPIO_CUSTOM,
|
|
H2CGpioCustomParm[0], H2CGpioCustomParm[1], H2CGpioCustomParm[2]);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_CUSTOM_PULSE */
|
|
static u8 rtw_hal_set_keep_alive_cmd(_adapter *adapter, u8 enable, u8 pkt_type)
|
|
{
|
|
u8 u1H2CKeepAliveParm[H2C_KEEP_ALIVE_CTRL_LEN] = {0};
|
|
u8 adopt = 1, check_period = 5;
|
|
u8 ret = _FAIL;
|
|
u8 hw_port = rtw_hal_get_port(adapter);
|
|
|
|
SET_H2CCMD_KEEPALIVE_PARM_ENABLE(u1H2CKeepAliveParm, enable);
|
|
SET_H2CCMD_KEEPALIVE_PARM_ADOPT(u1H2CKeepAliveParm, adopt);
|
|
SET_H2CCMD_KEEPALIVE_PARM_PKT_TYPE(u1H2CKeepAliveParm, pkt_type);
|
|
SET_H2CCMD_KEEPALIVE_PARM_CHECK_PERIOD(u1H2CKeepAliveParm, check_period);
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
SET_H2CCMD_KEEPALIVE_PARM_PORT_NUM(u1H2CKeepAliveParm, hw_port);
|
|
RTW_INFO("%s(): enable = %d, port = %d\n", __func__, enable, hw_port);
|
|
#else
|
|
RTW_INFO("%s(): enable = %d\n", __func__, enable);
|
|
#endif
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_KEEP_ALIVE,
|
|
H2C_KEEP_ALIVE_CTRL_LEN,
|
|
u1H2CKeepAliveParm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
static u8 rtw_hal_set_keep_alive_pattern_cmd(PADAPTER adapter, u8 enable)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
u8 u1H2CKeepAliveParm[H2C_KEEP_ALIVE_PATTERN_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
int i;
|
|
|
|
/* If keep alive pattern is set, FW will use pattern for keep alive action */
|
|
if(enable == 0 || (pwrctl->wowlan_keep_alive_mode == wow_keep_alive_pattern_disable)) {
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_EN(u1H2CKeepAliveParm, _FALSE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_EN(u1H2CKeepAliveParm, _FALSE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_WAKE_EN(u1H2CKeepAliveParm, _FALSE);
|
|
return ret;
|
|
}
|
|
/*step1:set keep alive period*/
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_PERIOD_LOW_BIT(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_period & 0x00FF);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_PERIOD_HI_BIT(u1H2CKeepAliveParm, ((pwrctl->wowlan_keep_alive_period & 0xFF00)>> 8));
|
|
|
|
if (pwrctl->wowlan_keep_alive_mode == wow_keep_alive_pattern_tx) {
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_EN(u1H2CKeepAliveParm, _FALSE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_WAKE_EN(u1H2CKeepAliveParm, _FALSE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_PACKET_LOC(u1H2CKeepAliveParm, pwrctl->keep_alive_pattern_loc);
|
|
goto exit;
|
|
}
|
|
if (pwrctl->wowlan_keep_alive_mode == wow_keep_alive_pattern_trx) {
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_WAKE_EN(u1H2CKeepAliveParm, _FALSE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_PACKET_LOC(u1H2CKeepAliveParm, pwrctl->keep_alive_pattern_loc);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_idx(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_ack_index);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_RETRY_INTERVAL(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_retry_interval);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_RETRY_LIMIT(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_retry_counter);
|
|
goto exit;
|
|
}
|
|
if (pwrctl->wowlan_keep_alive_mode == wow_keep_alive_pattern_trx_with_ack) {
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_WAKE_EN(u1H2CKeepAliveParm, _TRUE);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_PACKET_LOC(u1H2CKeepAliveParm, pwrctl->keep_alive_pattern_loc);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_ACK_PATTERN_idx(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_ack_index);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_WAKE_PATTERN_idx(u1H2CKeepAliveParm, pwrctl->wowlan_wake_pattern_index);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_RETRY_INTERVAL(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_retry_interval);
|
|
SET_H2CCMD_UDP_KEEP_ALIVE_RETRY_LIMIT(u1H2CKeepAliveParm, pwrctl->wowlan_keep_alive_retry_counter);
|
|
goto exit;
|
|
}
|
|
exit:
|
|
for(i=0; i<H2C_KEEP_ALIVE_PATTERN_LEN; i++) {
|
|
RTW_INFO("u1H2CKeepAliveParm[%d]= x%0x\n", i, u1H2CKeepAliveParm[i]);
|
|
}
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_UDP_KEEPALIVE,
|
|
H2C_KEEP_ALIVE_PATTERN_LEN,
|
|
u1H2CKeepAliveParm);
|
|
|
|
return ret;
|
|
}
|
|
#endif/*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
|
|
|
|
static u8 rtw_hal_set_disconnect_decision_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
u8 u1H2CDisconDecisionParm[H2C_DISCON_DECISION_LEN] = {0};
|
|
u8 adopt = 1, check_period = 100, trypkt_num = 5;
|
|
u8 ret = _FAIL;
|
|
struct registry_priv *pregistry = &adapter->registrypriv;
|
|
u8 hw_port = rtw_hal_get_port(adapter);
|
|
|
|
SET_H2CCMD_DISCONDECISION_PARM_ENABLE(u1H2CDisconDecisionParm, enable);
|
|
SET_H2CCMD_DISCONDECISION_PARM_ADOPT(u1H2CDisconDecisionParm, adopt);
|
|
if (!(pregistry->wakeup_event & BIT(2)))
|
|
SET_H2CCMD_DISCONDECISION_PARM_DISCONNECT_EN(u1H2CDisconDecisionParm, adopt);
|
|
SET_H2CCMD_DISCONDECISION_PARM_CHECK_PERIOD(u1H2CDisconDecisionParm, check_period);
|
|
SET_H2CCMD_DISCONDECISION_PARM_TRY_PKT_NUM(u1H2CDisconDecisionParm, trypkt_num);
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
SET_H2CCMD_DISCONDECISION_PORT_NUM(u1H2CDisconDecisionParm, hw_port);
|
|
RTW_INFO("%s(): enable = %d, port = %d\n", __func__, enable, hw_port);
|
|
#else
|
|
RTW_INFO("%s(): enable = %d\n", __func__, enable);
|
|
#endif
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_DISCON_DECISION,
|
|
H2C_DISCON_DECISION_LEN,
|
|
u1H2CDisconDecisionParm);
|
|
return ret;
|
|
}
|
|
|
|
static u8 rtw_hal_set_wowlan_ctrl_cmd(_adapter *adapter, u8 enable, u8 change_unit)
|
|
{
|
|
struct registry_priv *registry_par = &adapter->registrypriv;
|
|
struct security_priv *psecpriv = &adapter->securitypriv;
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
|
|
|
|
u8 u1H2CWoWlanCtrlParm[H2C_WOWLAN_LEN] = {0};
|
|
u8 discont_wake = 0, gpionum = 0, gpio_dur = 0, no_wake = 0;
|
|
u8 hw_unicast = 0, gpio_pulse_cnt = 0, gpio_pulse_en = 0;
|
|
u8 sdio_wakeup_enable = 1;
|
|
u8 gpio_high_active = 0;
|
|
u8 magic_pkt = 0;
|
|
u8 gpio_unit = 0; /*0: 64ns, 1: 8ms*/
|
|
u8 ret = _FAIL;
|
|
#ifdef CONFIG_DIS_UPHY
|
|
u8 dis_uphy = 0, dis_uphy_unit = 0, dis_uphy_time = 0;
|
|
#endif /* CONFIG_DIS_UPHY */
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
gpio_high_active = ppwrpriv->is_high_active;
|
|
gpionum = ppwrpriv->wowlan_gpio_index;
|
|
sdio_wakeup_enable = 0;
|
|
#endif /* CONFIG_GPIO_WAKEUP */
|
|
|
|
if(registry_par->suspend_type == FW_IPS_DISABLE_BBRF &&
|
|
!check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
|
|
no_wake = 1;
|
|
|
|
if (!ppwrpriv->wowlan_pno_enable &&
|
|
registry_par->wakeup_event & BIT(0) && !no_wake)
|
|
magic_pkt = enable;
|
|
|
|
if (registry_par->wakeup_event & BIT(2) && !no_wake)
|
|
discont_wake = enable;
|
|
|
|
RTW_INFO("%s(): enable=%d change_unit=%d\n", __func__,
|
|
enable, change_unit);
|
|
|
|
/* time = (gpio_dur/2) * gpio_unit, default:256 ms */
|
|
if (enable && change_unit) {
|
|
gpio_dur = 0x40;
|
|
gpio_unit = 1;
|
|
gpio_pulse_en = 1;
|
|
}
|
|
|
|
#ifdef CONFIG_PLATFORM_ARM_RK3188
|
|
if (enable) {
|
|
gpio_pulse_en = 1;
|
|
gpio_pulse_cnt = 0x04;
|
|
}
|
|
#endif
|
|
|
|
SET_H2CCMD_WOWLAN_FUNC_ENABLE(u1H2CWoWlanCtrlParm, enable);
|
|
if(!no_wake)
|
|
SET_H2CCMD_WOWLAN_PATTERN_MATCH_ENABLE(u1H2CWoWlanCtrlParm, enable);
|
|
SET_H2CCMD_WOWLAN_MAGIC_PKT_ENABLE(u1H2CWoWlanCtrlParm, magic_pkt);
|
|
SET_H2CCMD_WOWLAN_UNICAST_PKT_ENABLE(u1H2CWoWlanCtrlParm, hw_unicast);
|
|
SET_H2CCMD_WOWLAN_ALL_PKT_DROP(u1H2CWoWlanCtrlParm, 0);
|
|
SET_H2CCMD_WOWLAN_GPIO_ACTIVE(u1H2CWoWlanCtrlParm, gpio_high_active);
|
|
|
|
#ifdef CONFIG_GTK_OL
|
|
if (psecpriv->binstallKCK_KEK == _TRUE &&
|
|
(psecpriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK || _rtw_wow_chk_cap(adapter, WOW_CAP_TKIP_OL)))
|
|
SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, 0);
|
|
else
|
|
SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, 1);
|
|
#else
|
|
SET_H2CCMD_WOWLAN_REKEY_WAKE_UP(u1H2CWoWlanCtrlParm, enable);
|
|
#endif
|
|
SET_H2CCMD_WOWLAN_DISCONNECT_WAKE_UP(u1H2CWoWlanCtrlParm, discont_wake);
|
|
SET_H2CCMD_WOWLAN_GPIONUM(u1H2CWoWlanCtrlParm, gpionum);
|
|
SET_H2CCMD_WOWLAN_DATAPIN_WAKE_UP(u1H2CWoWlanCtrlParm, sdio_wakeup_enable);
|
|
|
|
SET_H2CCMD_WOWLAN_GPIO_DURATION(u1H2CWoWlanCtrlParm, gpio_dur);
|
|
SET_H2CCMD_WOWLAN_CHANGE_UNIT(u1H2CWoWlanCtrlParm, gpio_unit);
|
|
|
|
SET_H2CCMD_WOWLAN_GPIO_PULSE_EN(u1H2CWoWlanCtrlParm, gpio_pulse_en);
|
|
SET_H2CCMD_WOWLAN_GPIO_PULSE_COUNT(u1H2CWoWlanCtrlParm, gpio_pulse_cnt);
|
|
|
|
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
|
|
if (enable)
|
|
SET_H2CCMD_WOWLAN_GPIO_INPUT_EN(u1H2CWoWlanCtrlParm, 1);
|
|
#endif
|
|
|
|
#ifdef CONFIG_DIS_UPHY
|
|
if (enable) {
|
|
dis_uphy = 1;
|
|
/* time unit: 0 -> ms, 1 -> 256 ms*/
|
|
dis_uphy_unit = 1;
|
|
dis_uphy_time = 0x4;
|
|
}
|
|
|
|
SET_H2CCMD_WOWLAN_DISABLE_UPHY(u1H2CWoWlanCtrlParm, dis_uphy);
|
|
SET_H2CCMD_WOWLAN_UNIT_FOR_UPHY_DISABLE(u1H2CWoWlanCtrlParm, dis_uphy_unit);
|
|
SET_H2CCMD_WOWLAN_TIME_FOR_UPHY_DISABLE(u1H2CWoWlanCtrlParm, dis_uphy_time);
|
|
if (ppwrpriv->hst2dev_high_active == 1)
|
|
SET_H2CCMD_WOWLAN_RISE_HST2DEV(u1H2CWoWlanCtrlParm, 1);
|
|
#ifdef CONFIG_RTW_ONE_PIN_GPIO
|
|
SET_H2CCMD_WOWLAN_GPIO_INPUT_EN(u1H2CWoWlanCtrlParm, 1);
|
|
SET_H2CCMD_WOWLAN_DEV2HST_EN(u1H2CWoWlanCtrlParm, 1);
|
|
SET_H2CCMD_WOWLAN_HST2DEV_EN(u1H2CWoWlanCtrlParm, 0);
|
|
#else
|
|
SET_H2CCMD_WOWLAN_HST2DEV_EN(u1H2CWoWlanCtrlParm, 1);
|
|
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
|
|
#endif /* CONFIG_DIS_UPHY */
|
|
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_WOWLAN,
|
|
H2C_WOWLAN_LEN,
|
|
u1H2CWoWlanCtrlParm);
|
|
return ret;
|
|
}
|
|
|
|
static u8 rtw_hal_set_remote_wake_ctrl_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
struct security_priv *psecuritypriv = &(adapter->securitypriv);
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
struct registry_priv *pregistrypriv = &adapter->registrypriv;
|
|
u8 u1H2CRemoteWakeCtrlParm[H2C_REMOTE_WAKE_CTRL_LEN] = {0};
|
|
u8 ret = _FAIL, count = 0, no_wake = 0;
|
|
struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
|
|
|
|
RTW_INFO("%s(): enable=%d\n", __func__, enable);
|
|
|
|
if(pregistrypriv->suspend_type == FW_IPS_DISABLE_BBRF &&
|
|
!check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
|
|
no_wake = 1;
|
|
if(no_wake) {
|
|
SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
} else {
|
|
if (!ppwrpriv->wowlan_pno_enable) {
|
|
SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
#ifdef CONFIG_GTK_OL
|
|
if (psecuritypriv->binstallKCK_KEK == _TRUE &&
|
|
(psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK || _rtw_wow_chk_cap(adapter, WOW_CAP_TKIP_OL))) {
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
} else {
|
|
RTW_INFO("no kck kek\n");
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_GTK_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 0);
|
|
}
|
|
#endif /* CONFIG_GTK_OL */
|
|
|
|
#ifdef CONFIG_IPV6
|
|
if (ppwrpriv->wowlan_ns_offload_en == _TRUE) {
|
|
RTW_INFO("enable NS offload\n");
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_NDP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
}
|
|
|
|
/*
|
|
* filter NetBios name service pkt to avoid being waked-up
|
|
* by this kind of unicast pkt this exceptional modification
|
|
* is used for match competitor's behavior
|
|
*/
|
|
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_NBNS_FILTER_EN(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
#endif /*CONFIG_IPV6*/
|
|
#if 0 /* replaced by WOWLAN pattern match */
|
|
#ifdef CONFIG_RTL8192F
|
|
if (IS_HARDWARE_TYPE_8192F(adapter)){
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_FW_UNICAST_EN(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
}
|
|
#endif /* CONFIG_RTL8192F */
|
|
#endif
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
#ifdef CONFIG_GTK_OL
|
|
if(_rtw_wow_chk_cap(adapter, WOW_CAP_TKIP_OL))
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_TKIP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
#endif /* CONFIG_GTK_OL */
|
|
if (IS_HARDWARE_TYPE_8188E(adapter) ||
|
|
IS_HARDWARE_TYPE_8812(adapter)) {
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_TKIP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 0);
|
|
}
|
|
}
|
|
|
|
if (0) {
|
|
/* ARP wake up case */
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_ACTION(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
} else if (pregistrypriv->wakeup_event) {
|
|
/* ARP no wake up case */
|
|
if ((psecuritypriv->dot11PrivacyAlgrthm == _AES_) ||
|
|
(psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_)) {
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
}
|
|
#ifdef CONFIG_GTK_OL
|
|
else if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_ &&
|
|
_rtw_wow_chk_cap(adapter, WOW_CAP_TKIP_OL)) {
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_ARP_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
}
|
|
#endif
|
|
} else {
|
|
/* ARP no wake up and no ARP response case */
|
|
}
|
|
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_FW_PARSING_UNTIL_WAKEUP(
|
|
u1H2CRemoteWakeCtrlParm, 1);
|
|
}
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
else {
|
|
SET_H2CCMD_REMOTE_WAKECTRL_ENABLE(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(
|
|
u1H2CRemoteWakeCtrlParm, enable);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_P2P_WOWLAN
|
|
if (_TRUE == ppwrpriv->wowlan_p2p_mode) {
|
|
RTW_INFO("P2P OFFLOAD ENABLE\n");
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_P2P_OFFLAD_EN(u1H2CRemoteWakeCtrlParm, 1);
|
|
} else {
|
|
RTW_INFO("P2P OFFLOAD DISABLE\n");
|
|
SET_H2CCMD_REMOTE_WAKE_CTRL_P2P_OFFLAD_EN(u1H2CRemoteWakeCtrlParm, 0);
|
|
}
|
|
#endif /* CONFIG_P2P_WOWLAN */
|
|
}
|
|
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_REMOTE_WAKE_CTRL,
|
|
H2C_REMOTE_WAKE_CTRL_LEN,
|
|
u1H2CRemoteWakeCtrlParm);
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
static u8 rtw_hal_set_war_offload_ctrl_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
u8 u1H2CWarOffloadParm[H2C_WAR_OFFLOAD_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
RTW_INFO("%s(): enable=%d\n", __func__, enable);
|
|
|
|
if (_TRUE == ppwrpriv->wowlan_war_offload_mode) {
|
|
SET_H2CCMD_WAR_CFG_EN(u1H2CWarOffloadParm, enable);
|
|
SET_H2CCMD_WAR_CFG_ARP_RSP_EN(u1H2CWarOffloadParm, 1);
|
|
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V4
|
|
if (WAR_MDNS_V4_RSP_EN & ppwrpriv->wowlan_war_offload_ctrl) {
|
|
SET_H2CCMD_WAR_CFG_MDNSV4_RSP_EN(u1H2CWarOffloadParm, 1);
|
|
}
|
|
if (WAR_MDNS_V4_WAKEUP_EN& ppwrpriv->wowlan_war_offload_ctrl) {
|
|
SET_H2CCMD_WAR_CFG_MDNSV4_WAKE_EN(u1H2CWarOffloadParm, 1);
|
|
}
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V4 */
|
|
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V6
|
|
if (WAR_MDNS_V6_RSP_EN & ppwrpriv->wowlan_war_offload_ctrl) {
|
|
SET_H2CCMD_WAR_CFG_MDNSV6_RSP_EN(u1H2CWarOffloadParm, 1);
|
|
}
|
|
if (WAR_MDNS_V6_WAKEUP_EN & ppwrpriv->wowlan_war_offload_ctrl) {
|
|
SET_H2CCMD_WAR_CFG_MDNSV6_WAKE_EN(u1H2CWarOffloadParm, 1);
|
|
}
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V6 */
|
|
|
|
}
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_WAR_OFFLOAD,
|
|
H2C_WAR_OFFLOAD_LEN,
|
|
u1H2CWarOffloadParm);
|
|
return ret;
|
|
}
|
|
|
|
static u8 rtw_hal_set_war_offload_parm(_adapter *adapter, PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
u8 u1H2CWarOfldParm[H2C_WAROFLD_RSVDPAGE1_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
SET_H2CCMD_WAROFLD_RSVDPAGE1_LOC_PARM(u1H2CWarOfldParm, rsvdpageloc->LocIpParm);
|
|
RTW_INFO("%s(): LocIpParm = %d\n", __func__, rsvdpageloc->LocIpParm);
|
|
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_WAROFLD_RSVDPAGE1,
|
|
H2C_WAROFLD_RSVDPAGE1_LEN,
|
|
u1H2CWarOfldParm);
|
|
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_WAR_OFFLOAD */
|
|
|
|
|
|
|
|
static u8 rtw_hal_set_global_info_cmd(_adapter *adapter, u8 group_alg, u8 pairwise_alg)
|
|
{
|
|
u8 ret = _FAIL;
|
|
u8 u1H2CAOACGlobalInfoParm[H2C_AOAC_GLOBAL_INFO_LEN] = {0};
|
|
|
|
RTW_INFO("%s(): group_alg=%d pairwise_alg=%d\n",
|
|
__func__, group_alg, pairwise_alg);
|
|
SET_H2CCMD_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(u1H2CAOACGlobalInfoParm,
|
|
pairwise_alg);
|
|
SET_H2CCMD_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(u1H2CAOACGlobalInfoParm,
|
|
group_alg);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_AOAC_GLOBAL_INFO,
|
|
H2C_AOAC_GLOBAL_INFO_LEN,
|
|
u1H2CAOACGlobalInfoParm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
static u8 rtw_hal_set_scan_offload_info_cmd(_adapter *adapter,
|
|
PRSVDPAGE_LOC rsvdpageloc, u8 enable)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
u8 ret = _FAIL;
|
|
#ifndef RTW_HALMAC
|
|
u8 u1H2CScanOffloadInfoParm[H2C_SCAN_OFFLOAD_CTRL_LEN] = {0};
|
|
|
|
RTW_INFO("%s: loc_probe_packet:%d, loc_scan_info: %d loc_ssid_info:%d\n",
|
|
__func__, rsvdpageloc->LocProbePacket,
|
|
rsvdpageloc->LocScanInfo, rsvdpageloc->LocSSIDInfo);
|
|
|
|
SET_H2CCMD_AOAC_NLO_FUN_EN(u1H2CScanOffloadInfoParm, enable);
|
|
SET_H2CCMD_AOAC_NLO_IPS_EN(u1H2CScanOffloadInfoParm, enable);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_SCAN_INFO(u1H2CScanOffloadInfoParm,
|
|
rsvdpageloc->LocScanInfo);
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_PROBE_PACKET(u1H2CScanOffloadInfoParm,
|
|
rsvdpageloc->LocProbePacket);
|
|
/*
|
|
SET_H2CCMD_AOAC_RSVDPAGE_LOC_SSID_INFO(u1H2CScanOffloadInfoParm,
|
|
rsvdpageloc->LocSSIDInfo);
|
|
*/
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_D0_SCAN_OFFLOAD_INFO,
|
|
H2C_SCAN_OFFLOAD_CTRL_LEN,
|
|
u1H2CScanOffloadInfoParm);
|
|
#else
|
|
u8 u1H2CNLOINFOInfoParm[H2C_NLO_INFO_LEN] = {0};
|
|
|
|
RTW_INFO("%s: loc_nlo_info: %d enable %d\n", __func__,
|
|
rsvdpageloc->LocPNOInfo, enable);
|
|
|
|
SET_H2CCMD_NLO_FUN_EN(u1H2CNLOINFOInfoParm, enable);
|
|
#ifdef CONFIG_LPS_LCLK
|
|
// TODO(Owen): Controlled by wowlan lps level
|
|
/* This H2C bit requires driver leave LCLK in rtw_resume_process_wow() */
|
|
SET_H2CCMD_NLO_PS_32K(u1H2CNLOINFOInfoParm, enable);
|
|
#endif
|
|
SET_H2CCMD_NLO_LOC_NLO_INFO(u1H2CNLOINFOInfoParm, rsvdpageloc->LocPNOInfo);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_NLO_INFO,
|
|
H2C_NLO_INFO_LEN,
|
|
u1H2CNLOINFOInfoParm);
|
|
#endif
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_PNO_SUPPORT */
|
|
|
|
void rtw_hal_set_fw_wow_related_cmd(_adapter *padapter, u8 enable)
|
|
{
|
|
struct security_priv *psecpriv = &padapter->securitypriv;
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(padapter);
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct registry_priv *pregistry = &padapter->registrypriv;
|
|
u8 pkt_type = 0, no_wake = 0;
|
|
|
|
if(pregistry->suspend_type == FW_IPS_DISABLE_BBRF &&
|
|
!check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
|
|
no_wake = 1;
|
|
|
|
RTW_PRINT("+%s()+: enable=%d\n", __func__, enable);
|
|
|
|
rtw_hal_set_wowlan_ctrl_cmd(padapter, enable, _FALSE);
|
|
|
|
if (enable) {
|
|
if(!no_wake)
|
|
rtw_hal_set_global_info_cmd(padapter,
|
|
psecpriv->dot118021XGrpPrivacy,
|
|
psecpriv->dot11PrivacyAlgrthm);
|
|
|
|
if (!(ppwrpriv->wowlan_pno_enable)) {
|
|
if (!no_wake)
|
|
rtw_hal_set_disconnect_decision_cmd(padapter,
|
|
enable);
|
|
#ifdef CONFIG_ARP_KEEP_ALIVE
|
|
if ((psecpriv->dot11PrivacyAlgrthm == _WEP40_) ||
|
|
(psecpriv->dot11PrivacyAlgrthm == _WEP104_))
|
|
pkt_type = 0;
|
|
else
|
|
pkt_type = 1;
|
|
#else
|
|
pkt_type = 0;
|
|
#endif /* CONFIG_ARP_KEEP_ALIVE */
|
|
if(!no_wake) {
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
rtw_hal_set_keep_alive_pattern_cmd(padapter,enable);
|
|
#endif /*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
|
|
rtw_hal_set_keep_alive_cmd(padapter, enable, pkt_type);
|
|
}
|
|
}
|
|
#if defined(CONFIG_PNO_SUPPORT) && !defined(RTW_HALMAC)
|
|
rtw_hal_check_pno_enabled(padapter);
|
|
#endif /* defined(CONFIG_PNO_SUPPORT) && !defined(RTW_HALMAC) */
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
rtw_hal_set_war_offload_ctrl_cmd(padapter, enable);
|
|
#endif /* CONFIG_WAR_OFFLOAD */
|
|
|
|
} else {
|
|
#if 0
|
|
{
|
|
u32 PageSize = 0;
|
|
rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&PageSize);
|
|
dump_TX_FIFO(padapter, 4, PageSize);
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef CONFIG_CUSTOM_PULSE
|
|
rtw_hal_set_gpio_custom_cmd(padapter, enable);
|
|
#endif /* CONFIG_CUSTOM_PULSE */
|
|
rtw_hal_set_remote_wake_ctrl_cmd(padapter, enable);
|
|
RTW_PRINT("-%s()-\n", __func__);
|
|
}
|
|
#endif /* CONFIG_WOWLAN */
|
|
|
|
#ifdef CONFIG_AP_WOWLAN
|
|
static u8 rtw_hal_set_ap_wowlan_ctrl_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
struct pwrctrl_priv *ppwrpriv = adapter_to_pwrctl(adapter);
|
|
|
|
u8 u1H2CAPWoWlanCtrlParm[H2C_AP_WOW_GPIO_CTRL_LEN] = {0};
|
|
u8 gpionum = 0, gpio_dur = 0;
|
|
u8 gpio_pulse = enable;
|
|
u8 sdio_wakeup_enable = 1;
|
|
u8 gpio_high_active = 0;
|
|
u8 ret = _FAIL;
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
gpio_high_active = ppwrpriv->is_high_active;
|
|
gpionum = ppwrpriv->wowlan_gpio_index;
|
|
sdio_wakeup_enable = 0;
|
|
#endif /*CONFIG_GPIO_WAKEUP*/
|
|
|
|
RTW_INFO("%s(): enable=%d\n", __func__, enable);
|
|
|
|
SET_H2CCMD_AP_WOW_GPIO_CTRL_INDEX(u1H2CAPWoWlanCtrlParm,
|
|
gpionum);
|
|
SET_H2CCMD_AP_WOW_GPIO_CTRL_PLUS(u1H2CAPWoWlanCtrlParm,
|
|
gpio_pulse);
|
|
SET_H2CCMD_AP_WOW_GPIO_CTRL_HIGH_ACTIVE(u1H2CAPWoWlanCtrlParm,
|
|
gpio_high_active);
|
|
SET_H2CCMD_AP_WOW_GPIO_CTRL_EN(u1H2CAPWoWlanCtrlParm,
|
|
enable);
|
|
SET_H2CCMD_AP_WOW_GPIO_CTRL_DURATION(u1H2CAPWoWlanCtrlParm,
|
|
gpio_dur);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_AP_WOW_GPIO_CTRL,
|
|
H2C_AP_WOW_GPIO_CTRL_LEN,
|
|
u1H2CAPWoWlanCtrlParm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static u8 rtw_hal_set_ap_offload_ctrl_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
u8 u1H2CAPOffloadCtrlParm[H2C_WOWLAN_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
RTW_INFO("%s(): bFuncEn=%d\n", __func__, enable);
|
|
|
|
SET_H2CCMD_AP_WOWLAN_EN(u1H2CAPOffloadCtrlParm, enable);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_AP_OFFLOAD,
|
|
H2C_AP_OFFLOAD_LEN,
|
|
u1H2CAPOffloadCtrlParm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static u8 rtw_hal_set_ap_ps_cmd(_adapter *adapter, u8 enable)
|
|
{
|
|
u8 ap_ps_parm[H2C_AP_PS_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
RTW_INFO("%s(): enable=%d\n" , __func__ , enable);
|
|
|
|
SET_H2CCMD_AP_WOW_PS_EN(ap_ps_parm, enable);
|
|
#ifndef CONFIG_USB_HCI
|
|
SET_H2CCMD_AP_WOW_PS_32K_EN(ap_ps_parm, enable);
|
|
#endif /*CONFIG_USB_HCI*/
|
|
SET_H2CCMD_AP_WOW_PS_RF(ap_ps_parm, enable);
|
|
|
|
if (enable)
|
|
SET_H2CCMD_AP_WOW_PS_DURATION(ap_ps_parm, 0x32);
|
|
else
|
|
SET_H2CCMD_AP_WOW_PS_DURATION(ap_ps_parm, 0x0);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_SAP_PS_,
|
|
H2C_AP_PS_LEN, ap_ps_parm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void rtw_hal_set_ap_rsvdpage_loc_cmd(PADAPTER padapter,
|
|
PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
struct hal_ops *pHalFunc = &padapter->hal_func;
|
|
u8 rsvdparm[H2C_AOAC_RSVDPAGE_LOC_LEN] = {0};
|
|
u8 ret = _FAIL, header = 0;
|
|
|
|
if (pHalFunc->fill_h2c_cmd == NULL) {
|
|
RTW_INFO("%s: Please hook fill_h2c_cmd first!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
header = rtw_read8(padapter, REG_BCNQ_BDNY);
|
|
|
|
RTW_INFO("%s: beacon: %d, probeRsp: %d, header:0x%02x\n", __func__,
|
|
rsvdpageloc->LocApOffloadBCN,
|
|
rsvdpageloc->LocProbeRsp,
|
|
header);
|
|
|
|
SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_BCN(rsvdparm,
|
|
rsvdpageloc->LocApOffloadBCN + header);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(padapter, H2C_BCN_RSVDPAGE,
|
|
H2C_BCN_RSVDPAGE_LEN, rsvdparm);
|
|
|
|
if (ret == _FAIL)
|
|
RTW_INFO("%s: H2C_BCN_RSVDPAGE cmd fail\n", __func__);
|
|
|
|
rtw_msleep_os(10);
|
|
|
|
_rtw_memset(&rsvdparm, 0, sizeof(rsvdparm));
|
|
|
|
SET_H2CCMD_AP_WOWLAN_RSVDPAGE_LOC_ProbeRsp(rsvdparm,
|
|
rsvdpageloc->LocProbeRsp + header);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(padapter, H2C_PROBERSP_RSVDPAGE,
|
|
H2C_PROBERSP_RSVDPAGE_LEN, rsvdparm);
|
|
|
|
if (ret == _FAIL)
|
|
RTW_INFO("%s: H2C_PROBERSP_RSVDPAGE cmd fail\n", __func__);
|
|
|
|
rtw_msleep_os(10);
|
|
}
|
|
|
|
static void rtw_hal_set_fw_ap_wow_related_cmd(_adapter *padapter, u8 enable)
|
|
{
|
|
rtw_hal_set_ap_offload_ctrl_cmd(padapter, enable);
|
|
rtw_hal_set_ap_wowlan_ctrl_cmd(padapter, enable);
|
|
rtw_hal_set_ap_ps_cmd(padapter, enable);
|
|
}
|
|
|
|
static void rtw_hal_ap_wow_enable(_adapter *padapter)
|
|
{
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
|
|
struct sta_info *psta = NULL;
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
|
|
#ifdef DBG_CHECK_FW_PS_STATE
|
|
struct dvobj_priv *psdpriv = padapter->dvobj;
|
|
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
|
|
#endif /*DBG_CHECK_FW_PS_STATE*/
|
|
int res;
|
|
u16 media_status_rpt;
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
u8 val8 = 0;
|
|
#endif
|
|
|
|
RTW_INFO("%s, WOWLAN_AP_ENABLE\n", __func__);
|
|
#ifdef DBG_CHECK_FW_PS_STATE
|
|
if (rtw_fw_ps_state(padapter) == _FAIL) {
|
|
pdbgpriv->dbg_enwow_dload_fw_fail_cnt++;
|
|
RTW_PRINT("wowlan enable no leave 32k\n");
|
|
}
|
|
#endif /*DBG_CHECK_FW_PS_STATE*/
|
|
|
|
/* 1. Download WOWLAN FW*/
|
|
rtw_hal_fw_dl(padapter, _TRUE);
|
|
|
|
media_status_rpt = RT_MEDIA_CONNECT;
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
|
|
(u8 *)&media_status_rpt);
|
|
|
|
issue_beacon(padapter, 0);
|
|
|
|
rtw_msleep_os(2);
|
|
#if defined(CONFIG_RTL8188E)
|
|
if (IS_HARDWARE_TYPE_8188E(padapter))
|
|
rtw_hal_disable_tx_report(padapter);
|
|
#endif
|
|
/* RX DMA stop */
|
|
res = rtw_hal_pause_rx_dma(padapter);
|
|
if (res == _FAIL)
|
|
RTW_PRINT("[WARNING] pause RX DMA fail\n");
|
|
|
|
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
|
/* Enable CPWM2 only. */
|
|
res = rtw_hal_enable_cpwm2(padapter);
|
|
if (res == _FAIL)
|
|
RTW_PRINT("[WARNING] enable cpwm2 fail\n");
|
|
#endif
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
#ifdef CONFIG_RTW_ONE_PIN_GPIO
|
|
rtw_hal_switch_gpio_wl_ctrl(padapter, pwrpriv->wowlan_gpio_index, _TRUE);
|
|
rtw_hal_set_input_gpio(padapter, pwrpriv->wowlan_gpio_index);
|
|
#else
|
|
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
|
|
if (pwrctrlpriv->is_high_active == 0)
|
|
rtw_hal_set_input_gpio(padapter, pwrpriv->wowlan_gpio_index);
|
|
else
|
|
rtw_hal_set_output_gpio(padapter, pwrpriv->wowlan_gpio_index,
|
|
GPIO_OUTPUT_LOW);
|
|
#else
|
|
val8 = (pwrpriv->is_high_active == 0) ? 1 : 0;
|
|
rtw_hal_set_output_gpio(padapter, pwrpriv->wowlan_gpio_index, val8);
|
|
rtw_hal_switch_gpio_wl_ctrl(padapter, pwrpriv->wowlan_gpio_index, _TRUE);
|
|
RTW_INFO("%s: set GPIO_%d to OUTPUT %s state in ap wow suspend and %s_ACTIVE.\n",
|
|
__func__, pwrpriv->wowlan_gpio_index,
|
|
pwrpriv->wowlan_gpio_output_state ? "HIGH" : "LOW",
|
|
pwrpriv->is_high_active ? "HIGI" : "LOW");
|
|
#endif /* CONFIG_WAKEUP_GPIO_INPUT_MODE */
|
|
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
|
|
#endif /* CONFIG_GPIO_WAKEUP */
|
|
|
|
/* 5. Set Enable WOWLAN H2C command. */
|
|
RTW_PRINT("Set Enable AP WOWLan cmd\n");
|
|
rtw_hal_set_fw_ap_wow_related_cmd(padapter, 1);
|
|
|
|
rtw_write8(padapter, REG_MCUTST_WOWLAN, 0);
|
|
#ifdef CONFIG_USB_HCI
|
|
rtw_mi_intf_stop(padapter);
|
|
#endif
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
|
|
/* Invoid SE0 reset signal during suspending*/
|
|
rtw_write8(padapter, REG_RSV_CTRL, 0x20);
|
|
if (IS_8188F(pHalData->version_id) == FALSE
|
|
&& IS_8188GTV(pHalData->version_id) == FALSE)
|
|
rtw_write8(padapter, REG_RSV_CTRL, 0x60);
|
|
#endif
|
|
}
|
|
|
|
static void rtw_hal_ap_wow_disable(_adapter *padapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
|
|
#ifdef DBG_CHECK_FW_PS_STATE
|
|
struct dvobj_priv *psdpriv = padapter->dvobj;
|
|
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
|
|
#endif /*DBG_CHECK_FW_PS_STATE*/
|
|
u16 media_status_rpt;
|
|
|
|
RTW_INFO("%s, WOWLAN_AP_DISABLE\n", __func__);
|
|
/* 1. Read wakeup reason*/
|
|
pwrctl->wowlan_wake_reason = rtw_read8(padapter, REG_MCUTST_WOWLAN);
|
|
|
|
RTW_PRINT("wakeup_reason: 0x%02x\n",
|
|
pwrctl->wowlan_wake_reason);
|
|
|
|
rtw_hal_set_fw_ap_wow_related_cmd(padapter, 0);
|
|
|
|
rtw_msleep_os(2);
|
|
#ifdef DBG_CHECK_FW_PS_STATE
|
|
if (rtw_fw_ps_state(padapter) == _FAIL) {
|
|
pdbgpriv->dbg_diswow_dload_fw_fail_cnt++;
|
|
RTW_PRINT("wowlan enable no leave 32k\n");
|
|
}
|
|
#endif /*DBG_CHECK_FW_PS_STATE*/
|
|
|
|
#if defined(CONFIG_RTL8188E)
|
|
if (IS_HARDWARE_TYPE_8188E(padapter))
|
|
rtw_hal_enable_tx_report(padapter);
|
|
#endif
|
|
|
|
rtw_hal_force_enable_rxdma(padapter);
|
|
|
|
rtw_hal_fw_dl(padapter, _FALSE);
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
#ifdef CONFIG_RTW_ONE_PIN_GPIO
|
|
rtw_hal_set_input_gpio(padapter, pwrctl->wowlan_gpio_index);
|
|
#else
|
|
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
|
|
if (pwrctl->is_high_active == 0)
|
|
rtw_hal_set_input_gpio(padapter, pwrctl->wowlan_gpio_index);
|
|
else
|
|
rtw_hal_set_output_gpio(padapter, pwrctl->wowlan_gpio_index
|
|
, GPIO_OUTPUT_LOW);
|
|
#else
|
|
rtw_hal_set_output_gpio(padapter, pwrctl->wowlan_gpio_index,
|
|
pwrctl->wowlan_gpio_output_state);
|
|
RTW_INFO("%s: set GPIO_%d to OUTPUT %s state in ap wow resume and %s_ACTIVE.\n",
|
|
__func__, pwrctl->wowlan_gpio_index,
|
|
pwrctl->wowlan_gpio_output_state ? "HIGH" : "LOW",
|
|
pwrctl->is_high_active ? "HIGI" : "LOW");
|
|
#endif /*CONFIG_WAKEUP_GPIO_INPUT_MODE*/
|
|
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
|
|
#endif /* CONFIG_GPIO_WAKEUP */
|
|
media_status_rpt = RT_MEDIA_CONNECT;
|
|
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT,
|
|
(u8 *)&media_status_rpt);
|
|
|
|
issue_beacon(padapter, 0);
|
|
}
|
|
#endif /*CONFIG_AP_WOWLAN*/
|
|
|
|
#ifdef CONFIG_P2P_WOWLAN
|
|
static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
|
|
{
|
|
u8 *ssid_ie;
|
|
sint ssid_len_ori;
|
|
int len_diff = 0;
|
|
|
|
ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);
|
|
|
|
/* RTW_INFO("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
|
|
|
|
if (ssid_ie && ssid_len_ori > 0) {
|
|
switch (hidden_ssid_mode) {
|
|
case 1: {
|
|
u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
|
|
u32 remain_len = 0;
|
|
|
|
remain_len = ies_len - (next_ie - ies);
|
|
|
|
ssid_ie[1] = 0;
|
|
_rtw_memcpy(ssid_ie + 2, next_ie, remain_len);
|
|
len_diff -= ssid_len_ori;
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
_rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return len_diff;
|
|
}
|
|
|
|
static void rtw_hal_construct_P2PBeacon(_adapter *padapter, u8 *pframe, u32 *pLength)
|
|
{
|
|
/* struct xmit_frame *pmgntframe; */
|
|
/* struct pkt_attrib *pattrib; */
|
|
/* unsigned char *pframe; */
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
unsigned short *fctrl;
|
|
unsigned int rate_len;
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
u32 pktlen;
|
|
/* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
/* _irqL irqL;
|
|
* struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
* #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
|
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
#ifdef CONFIG_P2P
|
|
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
|
#endif /* CONFIG_P2P */
|
|
|
|
/* for debug */
|
|
u8 *dbgbuf = pframe;
|
|
u8 dbgbufLen = 0, index = 0;
|
|
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
/* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
/* _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
|
|
* #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
|
|
/* pmlmeext->mgnt_seq++; */
|
|
set_frame_sub_type(pframe, WIFI_BEACON);
|
|
|
|
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
|
|
if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
|
|
/* RTW_INFO("ie len=%d\n", cur_network->IELength); */
|
|
#ifdef CONFIG_P2P
|
|
/* for P2P : Primary Device Type & Device Name */
|
|
u32 wpsielen = 0, insert_len = 0;
|
|
u8 *wpsie = NULL;
|
|
wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
|
|
|
|
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
|
|
uint wps_offset, remainder_ielen;
|
|
u8 *premainder_ie, *pframe_wscie;
|
|
|
|
wps_offset = (uint)(wpsie - cur_network->IEs);
|
|
|
|
premainder_ie = wpsie + wpsielen;
|
|
|
|
remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
|
|
|
|
#ifdef CONFIG_IOCTL_CFG80211
|
|
if (pwdinfo->driver_interface == DRIVER_CFG80211) {
|
|
if (pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len > 0) {
|
|
_rtw_memcpy(pframe, cur_network->IEs, wps_offset);
|
|
pframe += wps_offset;
|
|
pktlen += wps_offset;
|
|
|
|
_rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
|
|
pframe += pmlmepriv->wps_beacon_ie_len;
|
|
pktlen += pmlmepriv->wps_beacon_ie_len;
|
|
|
|
/* copy remainder_ie to pframe */
|
|
_rtw_memcpy(pframe, premainder_ie, remainder_ielen);
|
|
pframe += remainder_ielen;
|
|
pktlen += remainder_ielen;
|
|
} else {
|
|
_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
|
|
pframe += cur_network->IELength;
|
|
pktlen += cur_network->IELength;
|
|
}
|
|
} else
|
|
#endif /* CONFIG_IOCTL_CFG80211 */
|
|
{
|
|
pframe_wscie = pframe + wps_offset;
|
|
_rtw_memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);
|
|
pframe += (wps_offset + wpsielen);
|
|
pktlen += (wps_offset + wpsielen);
|
|
|
|
/* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
|
|
/* Primary Device Type */
|
|
/* Type: */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
|
|
insert_len += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
|
|
insert_len += 2;
|
|
|
|
/* Value: */
|
|
/* Category ID */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
|
|
insert_len += 2;
|
|
|
|
/* OUI */
|
|
*(u32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
|
|
insert_len += 4;
|
|
|
|
/* Sub Category ID */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
|
|
insert_len += 2;
|
|
|
|
|
|
/* Device Name */
|
|
/* Type: */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
|
|
insert_len += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
|
|
insert_len += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
|
|
insert_len += pwdinfo->device_name_len;
|
|
|
|
|
|
/* update wsc ie length */
|
|
*(pframe_wscie + 1) = (wpsielen - 2) + insert_len;
|
|
|
|
/* pframe move to end */
|
|
pframe += insert_len;
|
|
pktlen += insert_len;
|
|
|
|
/* copy remainder_ie to pframe */
|
|
_rtw_memcpy(pframe, premainder_ie, remainder_ielen);
|
|
pframe += remainder_ielen;
|
|
pktlen += remainder_ielen;
|
|
}
|
|
} else
|
|
#endif /* CONFIG_P2P */
|
|
{
|
|
int len_diff;
|
|
_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
|
|
len_diff = update_hidden_ssid(
|
|
pframe + _BEACON_IE_OFFSET_
|
|
, cur_network->IELength - _BEACON_IE_OFFSET_
|
|
, pmlmeinfo->hidden_ssid_mode
|
|
);
|
|
pframe += (cur_network->IELength + len_diff);
|
|
pktlen += (cur_network->IELength + len_diff);
|
|
}
|
|
#if 0
|
|
{
|
|
u8 *wps_ie;
|
|
uint wps_ielen;
|
|
u8 sr = 0;
|
|
wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,
|
|
pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);
|
|
if (wps_ie && wps_ielen > 0)
|
|
rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
|
|
if (sr != 0)
|
|
set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
|
|
else
|
|
_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_P2P
|
|
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
|
|
u32 len;
|
|
#ifdef CONFIG_IOCTL_CFG80211
|
|
if (pwdinfo->driver_interface == DRIVER_CFG80211) {
|
|
len = pmlmepriv->p2p_beacon_ie_len;
|
|
if (pmlmepriv->p2p_beacon_ie && len > 0)
|
|
_rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
|
|
} else
|
|
#endif /* CONFIG_IOCTL_CFG80211 */
|
|
{
|
|
len = build_beacon_p2p_ie(pwdinfo, pframe);
|
|
}
|
|
|
|
pframe += len;
|
|
pktlen += len;
|
|
|
|
#ifdef CONFIG_WFD
|
|
len = rtw_append_beacon_wfd_ie(padapter, pframe);
|
|
pframe += len;
|
|
pktlen += len;
|
|
#endif
|
|
|
|
}
|
|
#endif /* CONFIG_P2P */
|
|
|
|
goto _issue_bcn;
|
|
|
|
}
|
|
|
|
/* below for ad-hoc mode */
|
|
|
|
/* timestamp will be inserted by hardware */
|
|
pframe += 8;
|
|
pktlen += 8;
|
|
|
|
/* beacon interval: 2 bytes */
|
|
|
|
_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
|
|
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
/* capability info: 2 bytes */
|
|
|
|
_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
|
|
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
/* SSID */
|
|
pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
|
|
|
|
/* supported rates... */
|
|
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
|
|
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
|
|
|
|
/* DS parameter set */
|
|
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
|
|
|
|
/* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
|
|
{
|
|
u8 erpinfo = 0;
|
|
u32 ATIMWindow;
|
|
/* IBSS Parameter Set... */
|
|
/* ATIMWindow = cur->Configuration.ATIMWindow; */
|
|
ATIMWindow = 0;
|
|
pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
|
|
|
|
/* ERP IE */
|
|
pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pktlen);
|
|
}
|
|
|
|
|
|
/* EXTERNDED SUPPORTED RATE */
|
|
if (rate_len > 8)
|
|
pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
|
|
|
|
|
|
/* todo:HT for adhoc */
|
|
|
|
_issue_bcn:
|
|
|
|
/* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
/* pmlmepriv->update_bcn = _FALSE;
|
|
*
|
|
* _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
|
|
* #endif */ /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */
|
|
|
|
*pLength = pktlen;
|
|
#if 0
|
|
/* printf dbg msg */
|
|
dbgbufLen = pktlen;
|
|
RTW_INFO("======> DBG MSG FOR CONSTRAUCT P2P BEACON\n");
|
|
|
|
for (index = 0; index < dbgbufLen; index++)
|
|
printk("%x ", *(dbgbuf + index));
|
|
|
|
printk("\n");
|
|
RTW_INFO("<====== DBG MSG FOR CONSTRAUCT P2P BEACON\n");
|
|
|
|
#endif
|
|
}
|
|
|
|
static void rtw_hal_construct_P2PProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength)
|
|
{
|
|
/* struct xmit_frame *pmgntframe; */
|
|
/* struct pkt_attrib *pattrib; */
|
|
/* unsigned char *pframe; */
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
unsigned short *fctrl;
|
|
unsigned char *mac;
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
/* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */
|
|
u16 beacon_interval = 100;
|
|
u16 capInfo = 0;
|
|
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
|
u8 wpsie[255] = { 0x00 };
|
|
u32 wpsielen = 0, p2pielen = 0;
|
|
u32 pktlen;
|
|
#ifdef CONFIG_WFD
|
|
u32 wfdielen = 0;
|
|
#endif
|
|
|
|
/* for debug */
|
|
u8 *dbgbuf = pframe;
|
|
u8 dbgbufLen = 0, index = 0;
|
|
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
mac = adapter_mac_addr(padapter);
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
/* DA filled by FW */
|
|
_rtw_memset(pwlanhdr->addr1, 0, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
|
|
|
|
/* Use the device address for BSSID field. */
|
|
_rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(fctrl, WIFI_PROBERSP);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pframe += pktlen;
|
|
|
|
|
|
/* timestamp will be inserted by hardware */
|
|
pframe += 8;
|
|
pktlen += 8;
|
|
|
|
/* beacon interval: 2 bytes */
|
|
_rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2);
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
/* capability info: 2 bytes */
|
|
/* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
|
|
capInfo |= cap_ShortPremble;
|
|
capInfo |= cap_ShortSlot;
|
|
|
|
_rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
|
|
/* SSID */
|
|
pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pktlen);
|
|
|
|
/* supported rates... */
|
|
/* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */
|
|
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pktlen);
|
|
|
|
/* DS parameter set */
|
|
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pktlen);
|
|
|
|
#ifdef CONFIG_IOCTL_CFG80211
|
|
if (pwdinfo->driver_interface == DRIVER_CFG80211) {
|
|
if (pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL) {
|
|
/* WPS IE */
|
|
_rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
|
|
pktlen += pmlmepriv->wps_probe_resp_ie_len;
|
|
pframe += pmlmepriv->wps_probe_resp_ie_len;
|
|
|
|
/* P2P IE */
|
|
_rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
|
|
pktlen += pmlmepriv->p2p_probe_resp_ie_len;
|
|
pframe += pmlmepriv->p2p_probe_resp_ie_len;
|
|
}
|
|
} else
|
|
#endif /* CONFIG_IOCTL_CFG80211 */
|
|
{
|
|
|
|
/* Todo: WPS IE */
|
|
/* Noted by Albert 20100907 */
|
|
/* According to the WPS specification, all the WPS attribute is presented by Big Endian. */
|
|
|
|
wpsielen = 0;
|
|
/* WPS OUI */
|
|
*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
|
|
wpsielen += 4;
|
|
|
|
/* WPS version */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
|
|
|
|
/* WiFi Simple Config State */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */
|
|
|
|
/* Response Type */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
|
|
|
|
/* UUID-E */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
if (pwdinfo->external_uuid == 0) {
|
|
_rtw_memset(wpsie + wpsielen, 0x0, 16);
|
|
_rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);
|
|
} else
|
|
_rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10);
|
|
wpsielen += 0x10;
|
|
|
|
/* Manufacturer */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(wpsie + wpsielen, "Realtek", 7);
|
|
wpsielen += 7;
|
|
|
|
/* Model Name */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(wpsie + wpsielen, "8192CU", 6);
|
|
wpsielen += 6;
|
|
|
|
/* Model Number */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = 0x31; /* character 1 */
|
|
|
|
/* Serial Number */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);
|
|
wpsielen += ETH_ALEN;
|
|
|
|
/* Primary Device Type */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
/* Category ID */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
|
|
wpsielen += 2;
|
|
|
|
/* OUI */
|
|
*(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
|
|
wpsielen += 4;
|
|
|
|
/* Sub Category ID */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
|
|
wpsielen += 2;
|
|
|
|
/* Device Name */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
|
|
wpsielen += pwdinfo->device_name_len;
|
|
|
|
/* Config Method */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
|
|
wpsielen += 2;
|
|
|
|
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen);
|
|
|
|
|
|
p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
|
|
pframe += p2pielen;
|
|
pktlen += p2pielen;
|
|
}
|
|
|
|
#ifdef CONFIG_WFD
|
|
wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe);
|
|
pframe += wfdielen;
|
|
pktlen += wfdielen;
|
|
#endif
|
|
|
|
*pLength = pktlen;
|
|
|
|
#if 0
|
|
/* printf dbg msg */
|
|
dbgbufLen = pktlen;
|
|
RTW_INFO("======> DBG MSG FOR CONSTRAUCT P2P Probe Rsp\n");
|
|
|
|
for (index = 0; index < dbgbufLen; index++)
|
|
printk("%x ", *(dbgbuf + index));
|
|
|
|
printk("\n");
|
|
RTW_INFO("<====== DBG MSG FOR CONSTRAUCT P2P Probe Rsp\n");
|
|
#endif
|
|
}
|
|
static void rtw_hal_construct_P2PNegoRsp(_adapter *padapter, u8 *pframe, u32 *pLength)
|
|
{
|
|
struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
|
|
unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
|
|
u8 action = P2P_PUB_ACTION_ACTION;
|
|
u32 p2poui = cpu_to_be32(P2POUI);
|
|
u8 oui_subtype = P2P_GO_NEGO_RESP;
|
|
u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
|
|
u8 p2pielen = 0, i;
|
|
uint wpsielen = 0;
|
|
u16 wps_devicepassword_id = 0x0000;
|
|
uint wps_devicepassword_id_len = 0;
|
|
u8 channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh;
|
|
u16 len_channellist_attr = 0;
|
|
u32 pktlen;
|
|
u8 dialogToken = 0;
|
|
|
|
/* struct xmit_frame *pmgntframe; */
|
|
/* struct pkt_attrib *pattrib; */
|
|
/* unsigned char *pframe; */
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
unsigned short *fctrl;
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
|
/* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */
|
|
|
|
#ifdef CONFIG_WFD
|
|
u32 wfdielen = 0;
|
|
#endif
|
|
|
|
/* for debug */
|
|
u8 *dbgbuf = pframe;
|
|
u8 dbgbufLen = 0, index = 0;
|
|
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
/* RA, filled by FW */
|
|
_rtw_memset(pwlanhdr->addr1, 0, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(pframe, WIFI_ACTION);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pframe += pktlen;
|
|
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen));
|
|
|
|
/* dialog token, filled by FW */
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen));
|
|
|
|
_rtw_memset(wpsie, 0x00, 255);
|
|
wpsielen = 0;
|
|
|
|
/* WPS Section */
|
|
wpsielen = 0;
|
|
/* WPS OUI */
|
|
*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
|
|
wpsielen += 4;
|
|
|
|
/* WPS version */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
|
|
|
|
/* Device Password ID */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
|
|
else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
|
|
else
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
|
|
wpsielen += 2;
|
|
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen);
|
|
|
|
|
|
/* P2P IE Section. */
|
|
|
|
/* P2P OUI */
|
|
p2pielen = 0;
|
|
p2pie[p2pielen++] = 0x50;
|
|
p2pie[p2pielen++] = 0x6F;
|
|
p2pie[p2pielen++] = 0x9A;
|
|
p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
|
|
|
|
/* Commented by Albert 20100908 */
|
|
/* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
|
|
/* 1. Status */
|
|
/* 2. P2P Capability */
|
|
/* 3. Group Owner Intent */
|
|
/* 4. Configuration Timeout */
|
|
/* 5. Operating Channel */
|
|
/* 6. Intended P2P Interface Address */
|
|
/* 7. Channel List */
|
|
/* 8. Device Info */
|
|
/* 9. Group ID ( Only GO ) */
|
|
|
|
|
|
/* ToDo: */
|
|
|
|
/* P2P Status */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_STATUS;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
|
|
p2pielen += 2;
|
|
|
|
/* Value, filled by FW */
|
|
p2pie[p2pielen++] = 1;
|
|
|
|
/* P2P Capability */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* Device Capability Bitmap, 1 byte */
|
|
|
|
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
|
|
/* Commented by Albert 2011/03/08 */
|
|
/* According to the P2P specification */
|
|
/* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
|
|
p2pie[p2pielen++] = 0;
|
|
} else {
|
|
/* Be group owner or meet the error case */
|
|
p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
|
|
}
|
|
|
|
/* Group Capability Bitmap, 1 byte */
|
|
if (pwdinfo->persistent_supported)
|
|
p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
|
|
else
|
|
p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
|
|
|
|
/* Group Owner Intent */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
if (pwdinfo->peer_intent & 0x01) {
|
|
/* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
|
|
p2pie[p2pielen++] = (pwdinfo->intent << 1);
|
|
} else {
|
|
/* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
|
|
p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
|
|
}
|
|
|
|
|
|
/* Configuration Timeout */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
|
|
p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
|
|
|
|
/* Operating Channel */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* Country String */
|
|
p2pie[p2pielen++] = 'X';
|
|
p2pie[p2pielen++] = 'X';
|
|
|
|
/* The third byte should be set to 0x04. */
|
|
/* Described in the "Operating Channel Attribute" section. */
|
|
p2pie[p2pielen++] = 0x04;
|
|
|
|
/* Operating Class */
|
|
if (pwdinfo->operating_channel <= 14) {
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = 0x51;
|
|
} else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = 0x73;
|
|
} else {
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = 0x7c;
|
|
}
|
|
|
|
/* Channel Number */
|
|
p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
|
|
|
|
/* Intended P2P Interface Address */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
|
|
p2pielen += ETH_ALEN;
|
|
|
|
/* Channel List */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
|
|
|
|
/* Country String(3) */
|
|
/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
|
|
/* + number of channels in all classes */
|
|
len_channellist_attr = 3
|
|
+ (1 + 1) * (u16)ch_list->reg_classes
|
|
+ get_reg_classes_full_count(ch_list);
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_buddy_check_fwstate(padapter, WIFI_ASOC_STATE))
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
|
|
else
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
|
|
|
|
#else
|
|
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
|
|
|
|
#endif
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* Country String */
|
|
p2pie[p2pielen++] = 'X';
|
|
p2pie[p2pielen++] = 'X';
|
|
|
|
/* The third byte should be set to 0x04. */
|
|
/* Described in the "Operating Channel Attribute" section. */
|
|
p2pie[p2pielen++] = 0x04;
|
|
|
|
/* Channel Entry List */
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_check_status(padapter, MI_LINKED)) {
|
|
u8 union_ch = rtw_mi_get_union_chan(padapter);
|
|
|
|
/* Operating Class */
|
|
if (union_ch > 14) {
|
|
if (union_ch >= 149)
|
|
p2pie[p2pielen++] = 0x7c;
|
|
else
|
|
p2pie[p2pielen++] = 0x73;
|
|
} else
|
|
p2pie[p2pielen++] = 0x51;
|
|
|
|
|
|
/* Number of Channels */
|
|
/* Just support 1 channel and this channel is AP's channel */
|
|
p2pie[p2pielen++] = 1;
|
|
|
|
/* Channel List */
|
|
p2pie[p2pielen++] = union_ch;
|
|
} else
|
|
#endif /* CONFIG_CONCURRENT_MODE */
|
|
{
|
|
int i, j;
|
|
for (j = 0; j < ch_list->reg_classes; j++) {
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
|
|
|
|
/* Number of Channels */
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].channels;
|
|
|
|
/* Channel List */
|
|
for (i = 0; i < ch_list->reg_class[j].channels; i++)
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
|
|
}
|
|
}
|
|
|
|
/* Device Info */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
|
|
|
|
/* Length: */
|
|
/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
|
|
/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* P2P Device Address */
|
|
_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
|
|
p2pielen += ETH_ALEN;
|
|
|
|
/* Config Method */
|
|
/* This field should be big endian. Noted by P2P specification. */
|
|
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
|
|
|
|
p2pielen += 2;
|
|
|
|
/* Primary Device Type */
|
|
/* Category ID */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
|
|
p2pielen += 2;
|
|
|
|
/* OUI */
|
|
*(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
|
|
p2pielen += 4;
|
|
|
|
/* Sub Category ID */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
|
|
p2pielen += 2;
|
|
|
|
/* Number of Secondary Device Types */
|
|
p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */
|
|
|
|
/* Device Name */
|
|
/* Type: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
|
|
p2pielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
|
|
p2pielen += pwdinfo->device_name_len;
|
|
|
|
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
|
|
/* Group ID Attribute */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* p2P Device Address */
|
|
_rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
|
|
p2pielen += ETH_ALEN;
|
|
|
|
/* SSID */
|
|
_rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
|
|
p2pielen += pwdinfo->nego_ssidlen;
|
|
|
|
}
|
|
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pktlen);
|
|
|
|
#ifdef CONFIG_WFD
|
|
wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
|
|
pframe += wfdielen;
|
|
pktlen += wfdielen;
|
|
#endif
|
|
|
|
*pLength = pktlen;
|
|
#if 0
|
|
/* printf dbg msg */
|
|
dbgbufLen = pktlen;
|
|
RTW_INFO("======> DBG MSG FOR CONSTRAUCT Nego Rsp\n");
|
|
|
|
for (index = 0; index < dbgbufLen; index++)
|
|
printk("%x ", *(dbgbuf + index));
|
|
|
|
printk("\n");
|
|
RTW_INFO("<====== DBG MSG FOR CONSTRAUCT Nego Rsp\n");
|
|
#endif
|
|
}
|
|
|
|
static void rtw_hal_construct_P2PInviteRsp(_adapter *padapter, u8 *pframe, u32 *pLength)
|
|
{
|
|
unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
|
|
u8 action = P2P_PUB_ACTION_ACTION;
|
|
u32 p2poui = cpu_to_be32(P2POUI);
|
|
u8 oui_subtype = P2P_INVIT_RESP;
|
|
u8 p2pie[255] = { 0x00 };
|
|
u8 p2pielen = 0, i;
|
|
u8 channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
|
|
u16 len_channellist_attr = 0;
|
|
u32 pktlen;
|
|
u8 dialogToken = 0;
|
|
#ifdef CONFIG_WFD
|
|
u32 wfdielen = 0;
|
|
#endif
|
|
|
|
/* struct xmit_frame *pmgntframe; */
|
|
/* struct pkt_attrib *pattrib; */
|
|
/* unsigned char *pframe; */
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
unsigned short *fctrl;
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
|
|
|
/* for debug */
|
|
u8 *dbgbuf = pframe;
|
|
u8 dbgbufLen = 0, index = 0;
|
|
|
|
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
/* RA fill by FW */
|
|
_rtw_memset(pwlanhdr->addr1, 0, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
|
|
/* BSSID fill by FW */
|
|
_rtw_memset(pwlanhdr->addr3, 0, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(pframe, WIFI_ACTION);
|
|
|
|
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen));
|
|
|
|
/* dialog token, filled by FW */
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen));
|
|
|
|
/* P2P IE Section. */
|
|
|
|
/* P2P OUI */
|
|
p2pielen = 0;
|
|
p2pie[p2pielen++] = 0x50;
|
|
p2pie[p2pielen++] = 0x6F;
|
|
p2pie[p2pielen++] = 0x9A;
|
|
p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
|
|
|
|
/* Commented by Albert 20101005 */
|
|
/* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
|
|
/* 1. Status */
|
|
/* 2. Configuration Timeout */
|
|
/* 3. Operating Channel ( Only GO ) */
|
|
/* 4. P2P Group BSSID ( Only GO ) */
|
|
/* 5. Channel List */
|
|
|
|
/* P2P Status */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_STATUS;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
|
|
p2pielen += 2;
|
|
|
|
/* Value: filled by FW, defult value is FAIL INFO UNAVAILABLE */
|
|
p2pie[p2pielen++] = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
|
|
|
|
/* Configuration Timeout */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */
|
|
p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */
|
|
|
|
/* due to defult value is FAIL INFO UNAVAILABLE, so the following IE is not needed */
|
|
#if 0
|
|
if (status_code == P2P_STATUS_SUCCESS) {
|
|
struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);
|
|
|
|
if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
|
|
/* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
|
|
/* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
|
|
/* First one is operating channel attribute. */
|
|
/* Second one is P2P Group BSSID attribute. */
|
|
|
|
/* Operating Channel */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* Country String */
|
|
p2pie[p2pielen++] = 'X';
|
|
p2pie[p2pielen++] = 'X';
|
|
|
|
/* The third byte should be set to 0x04. */
|
|
/* Described in the "Operating Channel Attribute" section. */
|
|
p2pie[p2pielen++] = 0x04;
|
|
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = 0x51; /* Copy from SD7 */
|
|
|
|
/* Channel Number */
|
|
p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */
|
|
|
|
|
|
/* P2P Group BSSID */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
|
|
|
|
/* Length: */
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* P2P Device Address for GO */
|
|
_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
|
|
p2pielen += ETH_ALEN;
|
|
|
|
}
|
|
|
|
/* Channel List */
|
|
/* Type: */
|
|
p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
|
|
|
|
/* Length: */
|
|
/* Country String(3) */
|
|
/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */
|
|
/* + number of channels in all classes */
|
|
len_channellist_attr = 3
|
|
+ (1 + 1) * (u16)ch_list->reg_classes
|
|
+ get_reg_classes_full_count(ch_list);
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_check_status(padapter, MI_LINKED))
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);
|
|
else
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
|
|
|
|
#else
|
|
|
|
*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
|
|
|
|
#endif
|
|
p2pielen += 2;
|
|
|
|
/* Value: */
|
|
/* Country String */
|
|
p2pie[p2pielen++] = 'X';
|
|
p2pie[p2pielen++] = 'X';
|
|
|
|
/* The third byte should be set to 0x04. */
|
|
/* Described in the "Operating Channel Attribute" section. */
|
|
p2pie[p2pielen++] = 0x04;
|
|
|
|
/* Channel Entry List */
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_check_status(padapter, MI_LINKED)) {
|
|
u8 union_ch = rtw_mi_get_union_chan(padapter);
|
|
|
|
/* Operating Class */
|
|
if (union_ch > 14) {
|
|
if (union_ch >= 149)
|
|
p2pie[p2pielen++] = 0x7c;
|
|
else
|
|
p2pie[p2pielen++] = 0x73;
|
|
|
|
} else
|
|
p2pie[p2pielen++] = 0x51;
|
|
|
|
|
|
/* Number of Channels */
|
|
/* Just support 1 channel and this channel is AP's channel */
|
|
p2pie[p2pielen++] = 1;
|
|
|
|
/* Channel List */
|
|
p2pie[p2pielen++] = union_ch;
|
|
} else
|
|
#endif /* CONFIG_CONCURRENT_MODE */
|
|
{
|
|
int i, j;
|
|
for (j = 0; j < ch_list->reg_classes; j++) {
|
|
/* Operating Class */
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;
|
|
|
|
/* Number of Channels */
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].channels;
|
|
|
|
/* Channel List */
|
|
for (i = 0; i < ch_list->reg_class[j].channels; i++)
|
|
p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pktlen);
|
|
|
|
#ifdef CONFIG_WFD
|
|
wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
|
|
pframe += wfdielen;
|
|
pktlen += wfdielen;
|
|
#endif
|
|
|
|
*pLength = pktlen;
|
|
|
|
#if 0
|
|
/* printf dbg msg */
|
|
dbgbufLen = pktlen;
|
|
RTW_INFO("======> DBG MSG FOR CONSTRAUCT Invite Rsp\n");
|
|
|
|
for (index = 0; index < dbgbufLen; index++)
|
|
printk("%x ", *(dbgbuf + index));
|
|
|
|
printk("\n");
|
|
RTW_INFO("<====== DBG MSG FOR CONSTRAUCT Invite Rsp\n");
|
|
#endif
|
|
}
|
|
|
|
|
|
static void rtw_hal_construct_P2PProvisionDisRsp(_adapter *padapter, u8 *pframe, u32 *pLength)
|
|
{
|
|
unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
|
|
u8 action = P2P_PUB_ACTION_ACTION;
|
|
u8 dialogToken = 0;
|
|
u32 p2poui = cpu_to_be32(P2POUI);
|
|
u8 oui_subtype = P2P_PROVISION_DISC_RESP;
|
|
u8 wpsie[100] = { 0x00 };
|
|
u8 wpsielen = 0;
|
|
u32 pktlen;
|
|
#ifdef CONFIG_WFD
|
|
u32 wfdielen = 0;
|
|
#endif
|
|
|
|
/* struct xmit_frame *pmgntframe; */
|
|
/* struct pkt_attrib *pattrib; */
|
|
/* unsigned char *pframe; */
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
unsigned short *fctrl;
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
|
|
|
|
/* for debug */
|
|
u8 *dbgbuf = pframe;
|
|
u8 dbgbufLen = 0, index = 0;
|
|
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
/* RA filled by FW */
|
|
_rtw_memset(pwlanhdr->addr1, 0, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(pframe, WIFI_ACTION);
|
|
|
|
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pktlen));
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pktlen));
|
|
/* dialog token, filled by FW */
|
|
pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pktlen));
|
|
|
|
wpsielen = 0;
|
|
/* WPS OUI */
|
|
/* *(u32*) ( wpsie ) = cpu_to_be32( WPSOUI ); */
|
|
RTW_PUT_BE32(wpsie, WPSOUI);
|
|
wpsielen += 4;
|
|
|
|
#if 0
|
|
/* WPS version */
|
|
/* Type: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
|
|
wpsielen += 2;
|
|
|
|
/* Value: */
|
|
wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
|
|
#endif
|
|
|
|
/* Config Method */
|
|
/* Type: */
|
|
/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD ); */
|
|
RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
|
|
wpsielen += 2;
|
|
|
|
/* Length: */
|
|
/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 ); */
|
|
RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
|
|
wpsielen += 2;
|
|
|
|
/* Value: filled by FW, default value is PBC */
|
|
/* *(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method ); */
|
|
RTW_PUT_BE16(wpsie + wpsielen, WPS_CM_PUSH_BUTTON);
|
|
wpsielen += 2;
|
|
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pktlen);
|
|
|
|
#ifdef CONFIG_WFD
|
|
wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
|
|
pframe += wfdielen;
|
|
pktlen += wfdielen;
|
|
#endif
|
|
|
|
*pLength = pktlen;
|
|
|
|
/* printf dbg msg */
|
|
#if 0
|
|
dbgbufLen = pktlen;
|
|
RTW_INFO("======> DBG MSG FOR CONSTRAUCT ProvisionDis Rsp\n");
|
|
|
|
for (index = 0; index < dbgbufLen; index++)
|
|
printk("%x ", *(dbgbuf + index));
|
|
|
|
printk("\n");
|
|
RTW_INFO("<====== DBG MSG FOR CONSTRAUCT ProvisionDis Rsp\n");
|
|
#endif
|
|
}
|
|
|
|
u8 rtw_hal_set_FwP2PRsvdPage_cmd(_adapter *adapter, PRSVDPAGE_LOC rsvdpageloc)
|
|
{
|
|
u8 u1H2CP2PRsvdPageParm[H2C_P2PRSVDPAGE_LOC_LEN] = {0};
|
|
struct hal_ops *pHalFunc = &adapter->hal_func;
|
|
u8 ret = _FAIL;
|
|
|
|
RTW_INFO("P2PRsvdPageLoc: P2PBeacon=%d P2PProbeRsp=%d NegoRsp=%d InviteRsp=%d PDRsp=%d\n",
|
|
rsvdpageloc->LocP2PBeacon, rsvdpageloc->LocP2PProbeRsp,
|
|
rsvdpageloc->LocNegoRsp, rsvdpageloc->LocInviteRsp,
|
|
rsvdpageloc->LocPDRsp);
|
|
|
|
SET_H2CCMD_RSVDPAGE_LOC_P2P_BCN(u1H2CP2PRsvdPageParm, rsvdpageloc->LocProbeRsp);
|
|
SET_H2CCMD_RSVDPAGE_LOC_P2P_PROBE_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocPsPoll);
|
|
SET_H2CCMD_RSVDPAGE_LOC_P2P_NEGO_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocNullData);
|
|
SET_H2CCMD_RSVDPAGE_LOC_P2P_INVITE_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocQosNull);
|
|
SET_H2CCMD_RSVDPAGE_LOC_P2P_PD_RSP(u1H2CP2PRsvdPageParm, rsvdpageloc->LocBTQosNull);
|
|
|
|
/* FillH2CCmd8723B(padapter, H2C_8723B_P2P_OFFLOAD_RSVD_PAGE, H2C_P2PRSVDPAGE_LOC_LEN, u1H2CP2PRsvdPageParm); */
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_P2P_OFFLOAD_RSVD_PAGE,
|
|
H2C_P2PRSVDPAGE_LOC_LEN,
|
|
u1H2CP2PRsvdPageParm);
|
|
|
|
return ret;
|
|
}
|
|
|
|
u8 rtw_hal_set_p2p_wowlan_offload_cmd(_adapter *adapter)
|
|
{
|
|
|
|
u8 offload_cmd[H2C_P2P_OFFLOAD_LEN] = {0};
|
|
struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
|
|
struct P2P_WoWlan_Offload_t *p2p_wowlan_offload = (struct P2P_WoWlan_Offload_t *)offload_cmd;
|
|
struct hal_ops *pHalFunc = &adapter->hal_func;
|
|
u8 ret = _FAIL;
|
|
|
|
_rtw_memset(p2p_wowlan_offload, 0 , sizeof(struct P2P_WoWlan_Offload_t));
|
|
RTW_INFO("%s\n", __func__);
|
|
switch (pwdinfo->role) {
|
|
case P2P_ROLE_DEVICE:
|
|
RTW_INFO("P2P_ROLE_DEVICE\n");
|
|
p2p_wowlan_offload->role = 0;
|
|
break;
|
|
case P2P_ROLE_CLIENT:
|
|
RTW_INFO("P2P_ROLE_CLIENT\n");
|
|
p2p_wowlan_offload->role = 1;
|
|
break;
|
|
case P2P_ROLE_GO:
|
|
RTW_INFO("P2P_ROLE_GO\n");
|
|
p2p_wowlan_offload->role = 2;
|
|
break;
|
|
default:
|
|
RTW_INFO("P2P_ROLE_DISABLE\n");
|
|
break;
|
|
}
|
|
p2p_wowlan_offload->Wps_Config[0] = pwdinfo->supported_wps_cm >> 8;
|
|
p2p_wowlan_offload->Wps_Config[1] = pwdinfo->supported_wps_cm;
|
|
offload_cmd = (u8 *)p2p_wowlan_offload;
|
|
RTW_INFO("p2p_wowlan_offload: %x:%x:%x\n", offload_cmd[0], offload_cmd[1], offload_cmd[2]);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_P2P_OFFLOAD,
|
|
H2C_P2P_OFFLOAD_LEN,
|
|
offload_cmd);
|
|
return ret;
|
|
|
|
/* FillH2CCmd8723B(adapter, H2C_8723B_P2P_OFFLOAD, sizeof(struct P2P_WoWlan_Offload_t), (u8 *)p2p_wowlan_offload); */
|
|
}
|
|
#endif /* CONFIG_P2P_WOWLAN */
|
|
|
|
void rtw_hal_construct_beacon(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
|
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
|
|
/* RTW_INFO("%s\n", __FUNCTION__); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
|
|
/* pmlmeext->mgnt_seq++; */
|
|
set_frame_sub_type(pframe, WIFI_BEACON);
|
|
|
|
pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
|
|
/* timestamp will be inserted by hardware */
|
|
pframe += 8;
|
|
pktlen += 8;
|
|
|
|
/* beacon interval: 2 bytes */
|
|
_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
|
|
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
#if 0
|
|
/* capability info: 2 bytes */
|
|
_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
|
|
|
|
pframe += 2;
|
|
pktlen += 2;
|
|
|
|
if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
|
|
/* RTW_INFO("ie len=%d\n", cur_network->IELength); */
|
|
pktlen += cur_network->IELength - sizeof(NDIS_802_11_FIXED_IEs);
|
|
_rtw_memcpy(pframe, cur_network->IEs + sizeof(NDIS_802_11_FIXED_IEs), pktlen);
|
|
|
|
goto _ConstructBeacon;
|
|
}
|
|
|
|
/* below for ad-hoc mode */
|
|
|
|
/* SSID */
|
|
pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pktlen);
|
|
|
|
/* supported rates... */
|
|
rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
|
|
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pktlen);
|
|
|
|
/* DS parameter set */
|
|
pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pktlen);
|
|
|
|
if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {
|
|
u32 ATIMWindow;
|
|
/* IBSS Parameter Set... */
|
|
/* ATIMWindow = cur->Configuration.ATIMWindow; */
|
|
ATIMWindow = 0;
|
|
pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pktlen);
|
|
}
|
|
|
|
|
|
/* todo: ERP IE */
|
|
|
|
|
|
/* EXTERNDED SUPPORTED RATE */
|
|
if (rate_len > 8)
|
|
pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pktlen);
|
|
|
|
/* todo:HT for adhoc */
|
|
|
|
_ConstructBeacon:
|
|
#endif
|
|
|
|
if ((pktlen + TXDESC_SIZE) > MAX_BEACON_LEN) {
|
|
RTW_ERR("beacon frame too large ,len(%d,%d)\n",
|
|
(pktlen + TXDESC_SIZE), MAX_BEACON_LEN);
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
|
|
*pLength = pktlen;
|
|
|
|
/* RTW_INFO("%s bcn_sz=%d\n", __FUNCTION__, pktlen); */
|
|
|
|
}
|
|
|
|
static void rtw_hal_construct_PSPoll(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
|
|
/* RTW_INFO("%s\n", __FUNCTION__); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
/* Frame control. */
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
SetPwrMgt(fctrl);
|
|
set_frame_sub_type(pframe, WIFI_PSPOLL);
|
|
|
|
/* AID. */
|
|
set_duration(pframe, (pmlmeinfo->aid | 0xc000));
|
|
|
|
/* BSSID. */
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
/* TA. */
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
|
|
*pLength = 16;
|
|
}
|
|
|
|
|
|
#ifdef DBG_FW_DEBUG_MSG_PKT
|
|
void rtw_hal_construct_fw_dbg_msg_pkt(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *plength)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct wlan_network *cur_network = &pmlmepriv->cur_network;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
|
|
set_frame_sub_type(pframe, WIFI_DATA);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
|
|
*plength = pktlen;
|
|
}
|
|
#endif /*DBG_FW_DEBUG_MSG_PKT*/
|
|
|
|
void rtw_hal_construct_NullFunctionData(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength,
|
|
u8 bQoS,
|
|
u8 AC,
|
|
u8 bEosp,
|
|
u8 bForcePowerSave)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct wlan_network *cur_network = &pmlmepriv->cur_network;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
u8 *sta_addr = NULL;
|
|
u8 bssid[ETH_ALEN] = {0};
|
|
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
if (bForcePowerSave)
|
|
SetPwrMgt(fctrl);
|
|
|
|
sta_addr = get_my_bssid(&pmlmeinfo->network);
|
|
if (NULL == sta_addr) {
|
|
_rtw_memcpy(bssid, adapter_mac_addr(padapter), ETH_ALEN);
|
|
sta_addr = bssid;
|
|
}
|
|
|
|
switch (cur_network->network.InfrastructureMode) {
|
|
case Ndis802_11Infrastructure:
|
|
SetToDs(fctrl);
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, sta_addr, ETH_ALEN);
|
|
break;
|
|
case Ndis802_11APMode:
|
|
SetFrDs(fctrl);
|
|
_rtw_memcpy(pwlanhdr->addr1, sta_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
|
|
break;
|
|
case Ndis802_11IBSS:
|
|
default:
|
|
_rtw_memcpy(pwlanhdr->addr1, sta_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
break;
|
|
}
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
if (bQoS == _TRUE) {
|
|
struct rtw_ieee80211_hdr_3addr_qos *pwlanqoshdr;
|
|
|
|
set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);
|
|
|
|
pwlanqoshdr = (struct rtw_ieee80211_hdr_3addr_qos *)pframe;
|
|
SetPriority(&pwlanqoshdr->qc, AC);
|
|
SetEOSP(&pwlanqoshdr->qc, bEosp);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
|
|
} else {
|
|
set_frame_sub_type(pframe, WIFI_DATA_NULL);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
}
|
|
|
|
*pLength = pktlen;
|
|
}
|
|
|
|
void rtw_hal_construct_ProbeRsp(_adapter *padapter, u8 *pframe, u32 *pLength,
|
|
BOOLEAN bHideSSID)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u8 *mac, *bssid, *sta_addr;
|
|
u32 pktlen;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
|
|
|
/*RTW_INFO("%s\n", __FUNCTION__);*/
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
mac = adapter_mac_addr(padapter);
|
|
bssid = cur_network->MacAddress;
|
|
sta_addr = get_my_bssid(&pmlmeinfo->network);
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
_rtw_memcpy(pwlanhdr->addr1, sta_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(fctrl, WIFI_PROBERSP);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pframe += pktlen;
|
|
|
|
if (cur_network->IELength > MAX_IE_SZ)
|
|
return;
|
|
|
|
_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
|
|
pframe += cur_network->IELength;
|
|
pktlen += cur_network->IELength;
|
|
|
|
*pLength = pktlen;
|
|
}
|
|
|
|
#ifdef CONFIG_WOWLAN
|
|
static void rtw_hal_append_tkip_mic(PADAPTER padapter,
|
|
u8 *pframe, u32 offset)
|
|
{
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
struct mic_data micdata;
|
|
struct sta_info *psta = NULL;
|
|
int res = 0;
|
|
|
|
u8 *payload = (u8 *)(pframe + offset);
|
|
|
|
u8 mic[8];
|
|
u8 priority[4] = {0x0};
|
|
u8 null_key[16] = {0x0};
|
|
|
|
RTW_INFO("%s(): Add MIC, offset: %d\n", __func__, offset);
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
psta = rtw_get_stainfo(&padapter->stapriv,
|
|
get_my_bssid(&(pmlmeinfo->network)));
|
|
if (psta != NULL) {
|
|
res = _rtw_memcmp(&psta->dot11tkiptxmickey.skey[0],
|
|
null_key, 16);
|
|
if (res == _TRUE)
|
|
RTW_INFO("%s(): STA dot11tkiptxmickey==0\n", __func__);
|
|
rtw_secmicsetkey(&micdata, &psta->dot11tkiptxmickey.skey[0]);
|
|
}
|
|
|
|
rtw_secmicappend(&micdata, pwlanhdr->addr3, 6); /* DA */
|
|
|
|
rtw_secmicappend(&micdata, pwlanhdr->addr2, 6); /* SA */
|
|
|
|
priority[0] = 0;
|
|
|
|
rtw_secmicappend(&micdata, &priority[0], 4);
|
|
|
|
rtw_secmicappend(&micdata, payload, 36); /* payload length = 8 + 28 */
|
|
|
|
rtw_secgetmic(&micdata, &(mic[0]));
|
|
|
|
payload += 36;
|
|
|
|
_rtw_memcpy(payload, &(mic[0]), 8);
|
|
}
|
|
/*
|
|
* Description:
|
|
* Construct the ARP response packet to support ARP offload.
|
|
* */
|
|
static void rtw_hal_construct_ARPRsp(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength,
|
|
u8 *pIPAddress
|
|
)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
static u8 ARPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x06};
|
|
u8 *pARPRspPkt = pframe;
|
|
/* for TKIP Cal MIC */
|
|
u8 *payload = pframe;
|
|
u8 EncryptionHeadOverhead = 0, arp_offset = 0;
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
/* set_frame_sub_type(fctrl, 0); */
|
|
SetToDs(fctrl);
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
/* SET_80211_HDR_FRAME_CONTROL(pARPRspPkt, 0); */
|
|
/* SET_80211_HDR_TYPE_AND_SUBTYPE(pARPRspPkt, Type_Data); */
|
|
/* SET_80211_HDR_TO_DS(pARPRspPkt, 1); */
|
|
/* SET_80211_HDR_ADDRESS1(pARPRspPkt, pMgntInfo->Bssid); */
|
|
/* SET_80211_HDR_ADDRESS2(pARPRspPkt, Adapter->CurrentAddress); */
|
|
/* SET_80211_HDR_ADDRESS3(pARPRspPkt, pMgntInfo->Bssid); */
|
|
|
|
/* SET_80211_HDR_DURATION(pARPRspPkt, 0); */
|
|
/* SET_80211_HDR_FRAGMENT_SEQUENCE(pARPRspPkt, 0); */
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
/* SET_80211_HDR_WEP(pARPRspPkt, 1); */ /* Suggested by CCW. */
|
|
SetPrivacy(fctrl);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
arp_offset = *pLength;
|
|
pARPRspPkt = (u8 *)(pframe + arp_offset);
|
|
payload = pARPRspPkt; /* Get Payload pointer */
|
|
/* LLC header */
|
|
_rtw_memcpy(pARPRspPkt, ARPLLCHeader, 8);
|
|
*pLength += 8;
|
|
|
|
/* ARP element */
|
|
pARPRspPkt += 8;
|
|
SET_ARP_HTYPE(pARPRspPkt, 1);
|
|
SET_ARP_PTYPE(pARPRspPkt, ETH_P_IP); /* IP protocol */
|
|
SET_ARP_HLEN(pARPRspPkt, ETH_ALEN);
|
|
SET_ARP_PLEN(pARPRspPkt, RTW_IP_ADDR_LEN);
|
|
SET_ARP_OPER(pARPRspPkt, 2); /* ARP response */
|
|
SET_ARP_SENDER_MAC_ADDR(pARPRspPkt, adapter_mac_addr(padapter));
|
|
SET_ARP_SENDER_IP_ADDR(pARPRspPkt, pIPAddress);
|
|
#ifdef CONFIG_ARP_KEEP_ALIVE
|
|
if (!is_zero_mac_addr(pmlmepriv->gw_mac_addr)) {
|
|
SET_ARP_TARGET_MAC_ADDR(pARPRspPkt, pmlmepriv->gw_mac_addr);
|
|
SET_ARP_TARGET_IP_ADDR(pARPRspPkt, pmlmepriv->gw_ip);
|
|
} else
|
|
#endif
|
|
{
|
|
SET_ARP_TARGET_MAC_ADDR(pARPRspPkt,
|
|
get_my_bssid(&(pmlmeinfo->network)));
|
|
SET_ARP_TARGET_IP_ADDR(pARPRspPkt,
|
|
pIPAddress);
|
|
RTW_INFO("%s Target Mac Addr:" MAC_FMT "\n", __FUNCTION__,
|
|
MAC_ARG(get_my_bssid(&(pmlmeinfo->network))));
|
|
RTW_INFO("%s Target IP Addr" IP_FMT "\n", __FUNCTION__,
|
|
IP_ARG(pIPAddress));
|
|
}
|
|
|
|
*pLength += 28;
|
|
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
if (IS_HARDWARE_TYPE_8188E(padapter) ||
|
|
IS_HARDWARE_TYPE_8812(padapter)) {
|
|
rtw_hal_append_tkip_mic(padapter, pframe, arp_offset);
|
|
}
|
|
*pLength += 8;
|
|
}
|
|
}
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
/*
|
|
* Description:
|
|
* Construct the Keep Alive packet to support specific Keep Alive packet.
|
|
* */
|
|
static void rtw_hal_construct_keepalive( PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength
|
|
){
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
|
|
static u8 LLCHeader[6] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00};
|
|
u8 *pKeepAlivePkt = pframe;
|
|
/* for TKIP Cal MIC */
|
|
u8 *payload = pframe;
|
|
u8 EncryptionHeadOverhead = 0, frame_offset = 0;
|
|
int i;
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
RTW_INFO("%s======>\n", __func__);
|
|
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
/* set_frame_sub_type(fctrl, 0); */
|
|
SetToDs(fctrl);
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, pwrpriv->keep_alive_pattern+6, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3,pwrpriv->keep_alive_pattern, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
/* SET_80211_HDR_WEP(pARPRspPkt, 1); */ /* Suggested by CCW. */
|
|
SetPrivacy(fctrl);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
frame_offset = *pLength;
|
|
pKeepAlivePkt = (u8 *)(pframe + frame_offset);
|
|
payload = pKeepAlivePkt; /* Get Payload pointer */
|
|
/* LLC header */
|
|
_rtw_memcpy(pKeepAlivePkt, LLCHeader, 6);
|
|
*pLength += 6;
|
|
|
|
/*From protocol type*/
|
|
pKeepAlivePkt+=6;
|
|
|
|
_rtw_memcpy(pKeepAlivePkt,pwrpriv->keep_alive_pattern+12,pwrpriv->keep_alive_pattern_len-12);
|
|
|
|
*pLength+=pwrpriv->keep_alive_pattern_len-12;
|
|
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
*pLength += 8;
|
|
}
|
|
|
|
/* for debug
|
|
for (i=0; i< (*pLength) ;i++) {
|
|
RTW_INFO("KA_Pkt[0x%x]=x%0x", i,pKeepAlivePkt[i]);
|
|
if((i%8) == 7)
|
|
RTW_INFO("\n");
|
|
}
|
|
*/
|
|
|
|
RTW_INFO("%s <======\n", __func__);
|
|
}
|
|
|
|
#endif/*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
|
|
|
|
#ifdef CONFIG_IPV6
|
|
/*
|
|
* Description: Neighbor Discovery Offload.
|
|
*/
|
|
static void rtw_hal_construct_na_message(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr = NULL;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
|
|
u32 pktlen = 0;
|
|
u16 *fctrl = NULL;
|
|
|
|
u8 ns_hdr[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xDD};
|
|
u8 ipv6_info[4] = {0x60, 0x00, 0x00, 0x00};
|
|
u8 ipv6_contx[4] = {0x00, 0x20, 0x3a, 0xff};
|
|
u8 icmpv6_hdr[8] = {0x88, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00};
|
|
u8 val8 = 0;
|
|
|
|
u8 *p_na_msg = pframe;
|
|
/* for TKIP Cal MIC */
|
|
u8 *payload = pframe;
|
|
u8 EncryptionHeadOverhead = 0, na_msg_offset = 0;
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
SetToDs(fctrl);
|
|
_rtw_memcpy(pwlanhdr->addr1,
|
|
get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2,
|
|
adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3,
|
|
get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
/* SET_80211_HDR_WEP(pARPRspPkt, 1); */ /* Suggested by CCW. */
|
|
SetPrivacy(fctrl);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
na_msg_offset = *pLength;
|
|
p_na_msg = (u8 *)(pframe + na_msg_offset);
|
|
payload = p_na_msg; /* Get Payload pointer */
|
|
|
|
/* LLC header */
|
|
val8 = sizeof(ns_hdr);
|
|
_rtw_memcpy(p_na_msg, ns_hdr, val8);
|
|
*pLength += val8;
|
|
p_na_msg += val8;
|
|
|
|
/* IPv6 Header */
|
|
/* 1 . Information (4 bytes): 0x60 0x00 0x00 0x00 */
|
|
val8 = sizeof(ipv6_info);
|
|
_rtw_memcpy(p_na_msg, ipv6_info, val8);
|
|
*pLength += val8;
|
|
p_na_msg += val8;
|
|
|
|
/* 2 . playload : 0x00 0x20 , NextProt : 0x3a (ICMPv6) HopLim : 0xff */
|
|
val8 = sizeof(ipv6_contx);
|
|
_rtw_memcpy(p_na_msg, ipv6_contx, val8);
|
|
*pLength += val8;
|
|
p_na_msg += val8;
|
|
|
|
/* 3 . SA : 16 bytes , DA : 16 bytes ( Fw will filled ) */
|
|
_rtw_memset(&(p_na_msg[*pLength]), 0, 32);
|
|
*pLength += 32;
|
|
p_na_msg += 32;
|
|
|
|
/* ICMPv6 */
|
|
/* 1. Type : 0x88 (NA)
|
|
* 2. Code : 0x00
|
|
* 3. ChechSum : 0x00 0x00 (RSvd)
|
|
* 4. NAFlag: 0x60 0x00 0x00 0x00 ( Solicited , Override)
|
|
*/
|
|
val8 = sizeof(icmpv6_hdr);
|
|
_rtw_memcpy(p_na_msg, icmpv6_hdr, val8);
|
|
*pLength += val8;
|
|
p_na_msg += val8;
|
|
|
|
/* TA: 16 bytes*/
|
|
_rtw_memset(&(p_na_msg[*pLength]), 0, 16);
|
|
*pLength += 16;
|
|
p_na_msg += 16;
|
|
|
|
/* ICMPv6 Target Link Layer Address */
|
|
p_na_msg[0] = 0x02; /* type */
|
|
p_na_msg[1] = 0x01; /* len 1 unit of 8 octes */
|
|
*pLength += 2;
|
|
p_na_msg += 2;
|
|
|
|
_rtw_memset(&(p_na_msg[*pLength]), 0, 6);
|
|
*pLength += 6;
|
|
p_na_msg += 6;
|
|
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
if (IS_HARDWARE_TYPE_8188E(padapter) ||
|
|
IS_HARDWARE_TYPE_8812(padapter)) {
|
|
rtw_hal_append_tkip_mic(padapter, pframe,
|
|
na_msg_offset);
|
|
}
|
|
*pLength += 8;
|
|
}
|
|
}
|
|
/*
|
|
* Description: Neighbor Discovery Protocol Information.
|
|
*/
|
|
static void rtw_hal_construct_ndp_info(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct mlme_ext_priv *pmlmeext = NULL;
|
|
struct mlme_ext_info *pmlmeinfo = NULL;
|
|
struct rtw_ndp_info ndp_info;
|
|
u8 *pndp_info = pframe;
|
|
u8 len = sizeof(struct rtw_ndp_info);
|
|
|
|
RTW_INFO("%s: len: %d\n", __func__, len);
|
|
|
|
pmlmeext = &padapter->mlmeextpriv;
|
|
pmlmeinfo = &pmlmeext->mlmext_info;
|
|
|
|
_rtw_memset(pframe, 0, len);
|
|
_rtw_memset(&ndp_info, 0, len);
|
|
|
|
ndp_info.enable = 1;
|
|
ndp_info.check_remote_ip = 0;
|
|
ndp_info.num_of_target_ip = 1;
|
|
|
|
_rtw_memcpy(&ndp_info.target_link_addr, adapter_mac_addr(padapter),
|
|
ETH_ALEN);
|
|
_rtw_memcpy(&ndp_info.target_ipv6_addr, pmlmeinfo->ip6_addr,
|
|
RTW_IPv6_ADDR_LEN);
|
|
|
|
_rtw_memcpy(pndp_info, &ndp_info, len);
|
|
}
|
|
#endif /* CONFIG_IPV6 */
|
|
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
void rtw_hal_construct_ProbeReq(_adapter *padapter, u8 *pframe,
|
|
u32 *pLength, pno_ssid_t *ssid)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
unsigned char *mac;
|
|
unsigned char bssrate[NumRates];
|
|
struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
|
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
int bssrate_len = 0;
|
|
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
mac = adapter_mac_addr(padapter);
|
|
|
|
fctrl = &(pwlanhdr->frame_ctl);
|
|
*(fctrl) = 0;
|
|
|
|
_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
|
|
|
|
_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_frame_sub_type(pframe, WIFI_PROBEREQ);
|
|
|
|
pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
|
|
pframe += pktlen;
|
|
|
|
if (ssid == NULL)
|
|
pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &pktlen);
|
|
else {
|
|
/* RTW_INFO("%s len:%d\n", ssid->SSID, ssid->SSID_len); */
|
|
pframe = rtw_set_ie(pframe, _SSID_IE_, ssid->SSID_len, ssid->SSID, &pktlen);
|
|
}
|
|
|
|
get_rate_set(padapter, bssrate, &bssrate_len);
|
|
|
|
if (bssrate_len > 8) {
|
|
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &pktlen);
|
|
pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &pktlen);
|
|
} else
|
|
pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &pktlen);
|
|
|
|
*pLength = pktlen;
|
|
}
|
|
|
|
static void rtw_hal_construct_PNO_info(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
|
|
int i;
|
|
|
|
u8 *pPnoInfoPkt = pframe;
|
|
pPnoInfoPkt = (u8 *)(pframe + *pLength);
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_num, 1);
|
|
|
|
pPnoInfoPkt += 1;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->hidden_ssid_num, 1);
|
|
|
|
pPnoInfoPkt += 3;
|
|
#ifdef RTW_HALMAC
|
|
/* Pattern check for 3081 ICs */
|
|
_rtw_memset(pPnoInfoPkt, 0xA5A5A5A5, 4);
|
|
pPnoInfoPkt += 12;
|
|
#else
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_period, 1);
|
|
|
|
pPnoInfoPkt += 4;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->fast_scan_iterations, 4);
|
|
|
|
pPnoInfoPkt += 4;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->slow_scan_period, 4);
|
|
|
|
pPnoInfoPkt += 4;
|
|
#endif
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_length, MAX_PNO_LIST_COUNT);
|
|
|
|
pPnoInfoPkt += MAX_PNO_LIST_COUNT;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_cipher_info, MAX_PNO_LIST_COUNT);
|
|
|
|
pPnoInfoPkt += MAX_PNO_LIST_COUNT;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->ssid_channel_info, MAX_PNO_LIST_COUNT);
|
|
|
|
pPnoInfoPkt += MAX_PNO_LIST_COUNT;
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pnlo_info->loc_probe_req, MAX_HIDDEN_AP);
|
|
|
|
pPnoInfoPkt += MAX_HIDDEN_AP;
|
|
|
|
#ifdef RTW_HALMAC
|
|
/* SSID is located at 72th byte in NLO info Page for ICs that have HAMMAC */
|
|
*pLength += 72;
|
|
pPnoInfoPkt = pframe + 72;
|
|
#else
|
|
/* SSID is located at 128th Byte in NLO info Page for ICs that don't have HAMMAC */
|
|
*pLength += 128;
|
|
pPnoInfoPkt = pframe + 128;
|
|
#endif
|
|
for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) {
|
|
_rtw_memcpy(pPnoInfoPkt, &pwrctl->pno_ssid_list->node[i].SSID,
|
|
pwrctl->pnlo_info->ssid_length[i]);
|
|
*pLength += WLAN_SSID_MAXLEN;
|
|
pPnoInfoPkt += WLAN_SSID_MAXLEN;
|
|
}
|
|
}
|
|
|
|
#ifndef RTW_HALMAC
|
|
static void rtw_hal_construct_ssid_list(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
|
|
u8 *pSSIDListPkt = pframe;
|
|
int i;
|
|
|
|
pSSIDListPkt = (u8 *)(pframe + *pLength);
|
|
|
|
for (i = 0; i < pwrctl->pnlo_info->ssid_num ; i++) {
|
|
_rtw_memcpy(pSSIDListPkt, &pwrctl->pno_ssid_list->node[i].SSID,
|
|
pwrctl->pnlo_info->ssid_length[i]);
|
|
|
|
*pLength += WLAN_SSID_MAXLEN;
|
|
pSSIDListPkt += WLAN_SSID_MAXLEN;
|
|
}
|
|
}
|
|
|
|
static void rtw_hal_construct_scan_info(_adapter *padapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
|
|
u8 *pScanInfoPkt = pframe;
|
|
int i;
|
|
|
|
pScanInfoPkt = (u8 *)(pframe + *pLength);
|
|
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->channel_num, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_ch, 1);
|
|
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_bw, 1);
|
|
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_40_offset, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->orig_80_offset, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->periodScan, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->period_scan_time, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->enableRFE, 1);
|
|
|
|
*pLength += 1;
|
|
pScanInfoPkt += 1;
|
|
_rtw_memcpy(pScanInfoPkt, &pwrctl->pscan_info->rfe_type, 8);
|
|
|
|
*pLength += 8;
|
|
pScanInfoPkt += 8;
|
|
|
|
for (i = 0 ; i < MAX_SCAN_LIST_COUNT ; i++) {
|
|
_rtw_memcpy(pScanInfoPkt,
|
|
&pwrctl->pscan_info->ssid_channel_info[i], 4);
|
|
*pLength += 4;
|
|
pScanInfoPkt += 4;
|
|
}
|
|
}
|
|
#endif /* !RTW_HALMAC */
|
|
#endif /* CONFIG_PNO_SUPPORT */
|
|
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V4
|
|
|
|
/*
|
|
* Description:
|
|
* Construct the MDNS V4 response packet to support MDNS offload.
|
|
*
|
|
*/
|
|
static void rtw_hal_construct_mdns_rsp_v4(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength,
|
|
u8 *pIPAddress
|
|
)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct wlan_network *cur_network = &pmlmepriv->cur_network;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
static u8 ICMPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00};
|
|
u8 mulicast_ipv4_addr[4] = {0xe0, 0x00, 0x00, 0xfb};
|
|
u8 mulicast_mac_addr_for_mdns[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb};
|
|
u8 *pMdnsRspPkt = pframe;
|
|
/* for TKIP Cal MIC */
|
|
u8 EncryptionHeadOverhead = 0, mdns_offset = 0;
|
|
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
|
|
struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
/* set_frame_sub_type(fctrl, 0); */
|
|
SetToDs(fctrl);
|
|
//_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, mulicast_mac_addr_for_mdns, ETH_ALEN );
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
/* SET_80211_HDR_WEP(pARPRspPkt, 1); */ /* Suggested by CCW. */
|
|
SetPrivacy(fctrl);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
mdns_offset = *pLength;
|
|
pMdnsRspPkt = (u8 *)(pframe + mdns_offset);
|
|
/* LLC header */
|
|
_rtw_memcpy(pMdnsRspPkt, ICMPLLCHeader, 8);
|
|
*pLength += 8;
|
|
|
|
/* IP element */
|
|
pMdnsRspPkt += 8;
|
|
SET_IPHDR_VERSION(pMdnsRspPkt, 0x45);
|
|
SET_IPHDR_DSCP(pMdnsRspPkt, 0);
|
|
SET_IPHDR_TOTAL_LEN(pMdnsRspPkt, 0); // filled by fw
|
|
SET_IPHDR_IDENTIFIER(pMdnsRspPkt, 0); // filled by fw
|
|
SET_IPHDR_FLAGS(pMdnsRspPkt, 0x40);
|
|
SET_IPHDR_FRAG_OFFSET(pMdnsRspPkt, 0);
|
|
SET_IPHDR_TTL(pMdnsRspPkt, 0x40);
|
|
SET_IPHDR_PROTOCOL(pMdnsRspPkt, 0x11); // ICMP-UDP
|
|
SET_IPHDR_HDR_CHECKSUM(pMdnsRspPkt, 0); // filled by fw
|
|
SET_IPHDR_SRC_IP_ADDR(pMdnsRspPkt, pIPAddress);
|
|
SET_IPHDR_DST_IP_ADDR(pMdnsRspPkt, mulicast_ipv4_addr); // filled by fw
|
|
|
|
*pLength += 20;
|
|
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
if (IS_HARDWARE_TYPE_8188E(padapter) ||
|
|
IS_HARDWARE_TYPE_8812(padapter)) {
|
|
rtw_hal_append_tkip_mic(padapter, pframe, mdns_offset);
|
|
}
|
|
*pLength += 8;
|
|
}
|
|
|
|
/* UDP element */
|
|
pMdnsRspPkt += 20;
|
|
SET_UDP_SRC_PORT(pMdnsRspPkt, 0xe914); // MDNS
|
|
SET_UDP_DST_PORT(pMdnsRspPkt, 0xe914); // MDNS
|
|
SET_UDP_LEN(pMdnsRspPkt, 0); // filled by fw
|
|
SET_UDP_CHECKSUM(pMdnsRspPkt, 0); // filled by fw
|
|
*pLength += 8;
|
|
|
|
/* MDNS Header */
|
|
pMdnsRspPkt += 8;
|
|
SET_MDNS_HDR_FLAG(pMdnsRspPkt, 0x84);
|
|
*pLength += 12;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V4 */
|
|
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V6
|
|
|
|
/*
|
|
* Description:
|
|
* Construct the MDNS response V6 packet to support MDNS offload.
|
|
*
|
|
*/
|
|
static void rtw_hal_construct_mdns_rsp_v6(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength,
|
|
u8 *pIPAddress
|
|
)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct wlan_network *cur_network = &pmlmepriv->cur_network;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
static u8 ICMPLLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xDD};
|
|
u8 mulicast_ipv6_addr[16] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
|
|
u8 mulicast_mac_addr_for_mdns[6] = {0x33, 0x33, 0x00, 0x00, 0x00, 0xfb}; /* could be revise by fw */
|
|
u8 *pMdnsRspPkt = pframe;
|
|
/* for TKIP Cal MIC */
|
|
u8 EncryptionHeadOverhead = 0, mdns_offset = 0;
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
|
|
struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
/* set_frame_sub_type(fctrl, 0); */
|
|
SetToDs(fctrl);
|
|
//_rtw_memcpy(pwlanhdr->addr1, mulicast_mac_addr_for_mdns, ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
|
|
//_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
_rtw_memcpy(pwlanhdr->addr3, mulicast_mac_addr_for_mdns, ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
SetPrivacy(fctrl);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
mdns_offset = *pLength;
|
|
pMdnsRspPkt = (u8 *)(pframe + mdns_offset);
|
|
/* LLC header */
|
|
_rtw_memcpy(pMdnsRspPkt, ICMPLLCHeader, 8);
|
|
*pLength += 8;
|
|
|
|
/* ICMP element */
|
|
pMdnsRspPkt += 8;
|
|
SET_IPHDRV6_VERSION(pMdnsRspPkt, 0x06);
|
|
SET_IPHDRV6_PAYLOAD_LENGTH(pMdnsRspPkt, 0); // filled by fw
|
|
SET_IPHDRV6_NEXT_HEADER(pMdnsRspPkt, 0x3A);
|
|
SET_IPHDRV6_HOP_LIMIT(pMdnsRspPkt, 0xFF);
|
|
SET_IPHDRV6_SRC_IP_ADDR(pMdnsRspPkt, pIPAddress); // filled by fw
|
|
SET_IPHDRV6_DST_IP_ADDR(pMdnsRspPkt, mulicast_ipv6_addr); // filled by fw
|
|
|
|
*pLength += 40;
|
|
|
|
if (psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) {
|
|
if (IS_HARDWARE_TYPE_8188E(padapter) ||
|
|
IS_HARDWARE_TYPE_8812(padapter)) {
|
|
rtw_hal_append_tkip_mic(padapter, pframe, mdns_offset);
|
|
}
|
|
*pLength += 8;
|
|
}
|
|
|
|
/* UDP element */
|
|
pMdnsRspPkt += 40;
|
|
SET_UDP_SRC_PORT(pMdnsRspPkt, 0xe914); // SNMP
|
|
SET_UDP_DST_PORT(pMdnsRspPkt, 0xe914); // SNMP
|
|
SET_UDP_LEN(pMdnsRspPkt, 0); // filled by fw
|
|
SET_UDP_CHECKSUM(pMdnsRspPkt, 0); // filled by fw
|
|
*pLength += 8;
|
|
|
|
/* MDNS Header */
|
|
pMdnsRspPkt += 8;
|
|
SET_MDNS_HDR_FLAG(pMdnsRspPkt, 0x84);
|
|
*pLength += 12;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V6 */
|
|
#endif
|
|
|
|
#ifdef CONFIG_GTK_OL
|
|
static void rtw_hal_construct_GTKRsp(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength
|
|
)
|
|
{
|
|
struct rtw_ieee80211_hdr *pwlanhdr;
|
|
u16 *fctrl;
|
|
u32 pktlen;
|
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
|
struct wlan_network *cur_network = &pmlmepriv->cur_network;
|
|
struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct security_priv *psecuritypriv = &padapter->securitypriv;
|
|
static u8 LLCHeader[8] = {0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x88, 0x8E};
|
|
static u8 GTKbody_a[11] = {0x01, 0x03, 0x00, 0x5F, 0x02, 0x03, 0x12, 0x00, 0x10, 0x42, 0x0B};
|
|
u8 *pGTKRspPkt = pframe;
|
|
u8 EncryptionHeadOverhead = 0;
|
|
/* RTW_INFO("%s:%d\n", __FUNCTION__, bForcePowerSave); */
|
|
|
|
pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
|
|
|
|
fctrl = &pwlanhdr->frame_ctl;
|
|
*(fctrl) = 0;
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* MAC Header. */
|
|
/* ------------------------------------------------------------------------- */
|
|
SetFrameType(fctrl, WIFI_DATA);
|
|
/* set_frame_sub_type(fctrl, 0); */
|
|
SetToDs(fctrl);
|
|
|
|
_rtw_memcpy(pwlanhdr->addr1,
|
|
get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
_rtw_memcpy(pwlanhdr->addr2,
|
|
adapter_mac_addr(padapter), ETH_ALEN);
|
|
|
|
_rtw_memcpy(pwlanhdr->addr3,
|
|
get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
|
|
|
|
SetSeqNum(pwlanhdr, 0);
|
|
set_duration(pwlanhdr, 0);
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
*pLength = sMacHdrLng;
|
|
#else
|
|
*pLength = 24;
|
|
#endif /* CONFIG_WAPI_SUPPORT */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Security Header: leave space for it if necessary. */
|
|
/* ------------------------------------------------------------------------- */
|
|
switch (psecuritypriv->dot11PrivacyAlgrthm) {
|
|
case _WEP40_:
|
|
case _WEP104_:
|
|
EncryptionHeadOverhead = 4;
|
|
break;
|
|
case _TKIP_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
case _AES_:
|
|
EncryptionHeadOverhead = 8;
|
|
break;
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case _SMS4_:
|
|
EncryptionHeadOverhead = 18;
|
|
break;
|
|
#endif /* CONFIG_WAPI_SUPPORT */
|
|
default:
|
|
EncryptionHeadOverhead = 0;
|
|
}
|
|
|
|
if (EncryptionHeadOverhead > 0) {
|
|
_rtw_memset(&(pframe[*pLength]), 0, EncryptionHeadOverhead);
|
|
*pLength += EncryptionHeadOverhead;
|
|
/* SET_80211_HDR_WEP(pGTKRspPkt, 1); */ /* Suggested by CCW. */
|
|
/* GTK's privacy bit is done by FW */
|
|
/* SetPrivacy(fctrl); */
|
|
}
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Frame Body. */
|
|
/* ------------------------------------------------------------------------- */
|
|
pGTKRspPkt = (u8 *)(pframe + *pLength);
|
|
/* LLC header */
|
|
_rtw_memcpy(pGTKRspPkt, LLCHeader, 8);
|
|
*pLength += 8;
|
|
|
|
/* GTK element */
|
|
pGTKRspPkt += 8;
|
|
|
|
/* GTK frame body after LLC, part 1 */
|
|
/* TKIP key_length = 32, AES key_length = 16 */
|
|
if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_)
|
|
GTKbody_a[8] = 0x20;
|
|
|
|
/* GTK frame body after LLC, part 1 */
|
|
_rtw_memcpy(pGTKRspPkt, GTKbody_a, 11);
|
|
*pLength += 11;
|
|
pGTKRspPkt += 11;
|
|
/* GTK frame body after LLC, part 2 */
|
|
_rtw_memset(&(pframe[*pLength]), 0, 88);
|
|
*pLength += 88;
|
|
pGTKRspPkt += 88;
|
|
|
|
if (psecuritypriv->dot118021XGrpPrivacy == _TKIP_)
|
|
*pLength += 8;
|
|
}
|
|
#endif /* CONFIG_GTK_OL */
|
|
|
|
#define PN_2_CCMPH(ch,key_id) ((ch) & 0x000000000000ffff) \
|
|
| (((ch) & 0x0000ffffffff0000) << 16) \
|
|
| (((key_id) << 30)) \
|
|
| BIT(29)
|
|
static void rtw_hal_construct_remote_control_info(_adapter *adapter,
|
|
u8 *pframe, u32 *pLength)
|
|
{
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct sta_priv *pstapriv = &adapter->stapriv;
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
|
|
struct sta_info *psta;
|
|
struct stainfo_rxcache *prxcache;
|
|
u8 cur_dot11rxiv[8], id = 0, tid_id = 0, i = 0;
|
|
size_t sz = 0, total = 0;
|
|
u64 ccmp_hdr = 0, tmp_key = 0;
|
|
|
|
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
|
|
|
|
if (psta == NULL) {
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
|
|
prxcache = &psta->sta_recvpriv.rxcache;
|
|
sz = sizeof(cur_dot11rxiv);
|
|
|
|
/* 3 SEC IV * 1 page */
|
|
rtw_get_sec_iv(adapter, cur_dot11rxiv,
|
|
get_my_bssid(&pmlmeinfo->network));
|
|
|
|
_rtw_memcpy(pframe, cur_dot11rxiv, sz);
|
|
*pLength += sz;
|
|
pframe += sz;
|
|
|
|
_rtw_memset(&cur_dot11rxiv, 0, sz);
|
|
|
|
if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
|
|
id = psecuritypriv->dot118021XGrpKeyid;
|
|
tid_id = prxcache->last_tid;
|
|
REMOTE_INFO_CTRL_SET_VALD_EN(cur_dot11rxiv, 0xdd);
|
|
REMOTE_INFO_CTRL_SET_PTK_EN(cur_dot11rxiv, 1);
|
|
REMOTE_INFO_CTRL_SET_GTK_EN(cur_dot11rxiv, 1);
|
|
REMOTE_INFO_CTRL_SET_GTK_IDX(cur_dot11rxiv, id);
|
|
_rtw_memcpy(pframe, cur_dot11rxiv, sz);
|
|
*pLength += sz;
|
|
pframe += sz;
|
|
|
|
_rtw_memcpy(pframe, prxcache->iv[tid_id], sz);
|
|
*pLength += sz;
|
|
pframe += sz;
|
|
|
|
total = sizeof(psecuritypriv->iv_seq);
|
|
total /= sizeof(psecuritypriv->iv_seq[0]);
|
|
|
|
for (i = 0 ; i < total ; i ++) {
|
|
ccmp_hdr =
|
|
le64_to_cpu(*(u64*)psecuritypriv->iv_seq[i]);
|
|
_rtw_memset(&cur_dot11rxiv, 0, sz);
|
|
if (ccmp_hdr != 0) {
|
|
tmp_key = i;
|
|
ccmp_hdr = PN_2_CCMPH(ccmp_hdr, tmp_key);
|
|
*(u64*)cur_dot11rxiv = cpu_to_le64(ccmp_hdr);
|
|
_rtw_memcpy(pframe, cur_dot11rxiv, sz);
|
|
}
|
|
*pLength += sz;
|
|
pframe += sz;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void rtw_hal_gate_bb(_adapter *adapter, bool stop)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
u8 i = 0, val8 = 0, empty = _FAIL;
|
|
|
|
if (stop) {
|
|
/* checking TX queue status */
|
|
for (i = 0 ; i < 5 ; i++) {
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_CHK_MGQ_CPU_EMPTY, &empty);
|
|
if (empty) {
|
|
break;
|
|
} else {
|
|
RTW_WARN("%s: MGQ_CPU is busy(%d)!\n",
|
|
__func__, i);
|
|
rtw_mdelay_os(10);
|
|
}
|
|
}
|
|
|
|
if (val8 == 5)
|
|
RTW_ERR("%s: Polling MGQ_CPU empty fail!\n", __func__);
|
|
|
|
/* Pause TX*/
|
|
pwrpriv->wowlan_txpause_status = rtw_read8(adapter, REG_TXPAUSE);
|
|
rtw_write8(adapter, REG_TXPAUSE, 0xff);
|
|
val8 = rtw_read8(adapter, REG_SYS_FUNC_EN);
|
|
val8 &= ~BIT(0);
|
|
rtw_write8(adapter, REG_SYS_FUNC_EN, val8);
|
|
RTW_INFO("%s: BB gated: 0x%02x, store TXPAUSE: %02x\n",
|
|
__func__,
|
|
rtw_read8(adapter, REG_SYS_FUNC_EN),
|
|
pwrpriv->wowlan_txpause_status);
|
|
} else {
|
|
val8 = rtw_read8(adapter, REG_SYS_FUNC_EN);
|
|
val8 |= BIT(0);
|
|
rtw_write8(adapter, REG_SYS_FUNC_EN, val8);
|
|
RTW_INFO("%s: BB release: 0x%02x, recover TXPAUSE:%02x\n",
|
|
__func__, rtw_read8(adapter, REG_SYS_FUNC_EN),
|
|
pwrpriv->wowlan_txpause_status);
|
|
/* release TX*/
|
|
rtw_write8(adapter, REG_TXPAUSE, pwrpriv->wowlan_txpause_status);
|
|
}
|
|
}
|
|
|
|
static u8 rtw_hal_wow_pattern_generate(_adapter *adapter, u8 idx, struct rtl_wow_pattern *pwow_pattern)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
u8 *pattern;
|
|
u8 len = 0;
|
|
u8 *mask;
|
|
|
|
u8 mask_hw[MAX_WKFM_SIZE] = {0};
|
|
u8 content[MAX_WKFM_PATTERN_SIZE] = {0};
|
|
u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
u8 multicast_addr1[2] = {0x33, 0x33};
|
|
u8 multicast_addr2[3] = {0x01, 0x00, 0x5e};
|
|
u8 mask_len = 0;
|
|
u8 mac_addr[ETH_ALEN] = {0};
|
|
u16 count = 0;
|
|
int i;
|
|
|
|
if (pwrctl->wowlan_pattern_idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("%s pattern_idx is more than MAX_FMC_NUM: %d\n",
|
|
__func__, MAX_WKFM_CAM_NUM);
|
|
return _FAIL;
|
|
}
|
|
|
|
pattern = pwrctl->patterns[idx].content;
|
|
len = pwrctl->patterns[idx].len;
|
|
mask = pwrctl->patterns[idx].mask;
|
|
|
|
_rtw_memcpy(mac_addr, adapter_mac_addr(adapter), ETH_ALEN);
|
|
_rtw_memset(pwow_pattern, 0, sizeof(struct rtl_wow_pattern));
|
|
|
|
mask_len = DIV_ROUND_UP(len, 8);
|
|
|
|
/* 1. setup A1 table */
|
|
if (memcmp(pattern, broadcast_addr, ETH_ALEN) == 0)
|
|
pwow_pattern->type = PATTERN_BROADCAST;
|
|
else if (memcmp(pattern, multicast_addr1, 2) == 0)
|
|
pwow_pattern->type = PATTERN_MULTICAST;
|
|
else if (memcmp(pattern, multicast_addr2, 3) == 0)
|
|
pwow_pattern->type = PATTERN_MULTICAST;
|
|
else if (memcmp(pattern, mac_addr, ETH_ALEN) == 0)
|
|
pwow_pattern->type = PATTERN_UNICAST;
|
|
else
|
|
pwow_pattern->type = PATTERN_INVALID;
|
|
|
|
/* translate mask from os to mask for hw */
|
|
|
|
/******************************************************************************
|
|
* pattern from OS uses 'ethenet frame', like this:
|
|
|
|
| 6 | 6 | 2 | 20 | Variable | 4 |
|
|
|--------+--------+------+-----------+------------+-----|
|
|
| 802.3 Mac Header | IP Header | TCP Packet | FCS |
|
|
| DA | SA | Type |
|
|
|
|
* BUT, packet catched by our HW is in '802.11 frame', begin from LLC,
|
|
|
|
| 24 or 30 | 6 | 2 | 20 | Variable | 4 |
|
|
|-------------------+--------+------+-----------+------------+-----|
|
|
| 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS |
|
|
| Others | Tpye |
|
|
|
|
* Therefore, we need translate mask_from_OS to mask_to_hw.
|
|
* We should left-shift mask by 6 bits, then set the new bit[0~5] = 0,
|
|
* because new mask[0~5] means 'SA', but our HW packet begins from LLC,
|
|
* bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
|
|
******************************************************************************/
|
|
/* Shift 6 bits */
|
|
for (i = 0; i < mask_len - 1; i++) {
|
|
mask_hw[i] = mask[i] >> 6;
|
|
mask_hw[i] |= (mask[i + 1] & 0x3F) << 2;
|
|
}
|
|
|
|
mask_hw[i] = (mask[i] >> 6) & 0x3F;
|
|
/* Set bit 0-5 to zero */
|
|
mask_hw[0] &= 0xC0;
|
|
|
|
for (i = 0; i < (MAX_WKFM_SIZE / 4); i++) {
|
|
pwow_pattern->mask[i] = mask_hw[i * 4];
|
|
pwow_pattern->mask[i] |= (mask_hw[i * 4 + 1] << 8);
|
|
pwow_pattern->mask[i] |= (mask_hw[i * 4 + 2] << 16);
|
|
pwow_pattern->mask[i] |= (mask_hw[i * 4 + 3] << 24);
|
|
}
|
|
|
|
/* To get the wake up pattern from the mask.
|
|
* We do not count first 12 bits which means
|
|
* DA[6] and SA[6] in the pattern to match HW design. */
|
|
count = 0;
|
|
for (i = 12; i < len; i++) {
|
|
if ((mask[i / 8] >> (i % 8)) & 0x01) {
|
|
content[count] = pattern[i];
|
|
count++;
|
|
}
|
|
}
|
|
|
|
pwow_pattern->crc = rtw_calc_crc(content, count);
|
|
|
|
if (pwow_pattern->crc != 0) {
|
|
if (pwow_pattern->type == PATTERN_INVALID)
|
|
pwow_pattern->type = PATTERN_VALID;
|
|
}
|
|
|
|
return _SUCCESS;
|
|
}
|
|
|
|
void rtw_dump_wow_pattern(void *sel, struct rtl_wow_pattern *pwow_pattern, u8 idx)
|
|
{
|
|
int j;
|
|
|
|
RTW_PRINT_SEL(sel, "=======WOW CAM-ID[%d]=======\n", idx);
|
|
RTW_PRINT_SEL(sel, "[WOW CAM] type:%d\n", pwow_pattern->type);
|
|
RTW_PRINT_SEL(sel, "[WOW CAM] crc:0x%04x\n", pwow_pattern->crc);
|
|
for (j = 0; j < 4; j++)
|
|
RTW_PRINT_SEL(sel, "[WOW CAM] Mask:0x%08x\n", pwow_pattern->mask[j]);
|
|
}
|
|
/*bit definition of pattern match format*/
|
|
#define WOW_VALID_BIT BIT31
|
|
#ifndef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
#define WOW_BC_BIT BIT26
|
|
#define WOW_MC_BIT BIT25
|
|
#define WOW_UC_BIT BIT24
|
|
#else
|
|
#define WOW_BC_BIT BIT18
|
|
#define WOW_UC_BIT BIT17
|
|
#define WOW_MC_BIT BIT16
|
|
#endif /*CONFIG_WOW_PATTERN_IN_TXFIFO*/
|
|
|
|
#ifndef CONFIG_WOW_PATTERN_HW_CAM
|
|
#ifndef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
static void rtw_hal_reset_mac_rx(_adapter *adapter)
|
|
{
|
|
u8 val8 = 0;
|
|
/* Set REG_CR bit1, bit3, bit7 to 0*/
|
|
val8 = rtw_read8(adapter, REG_CR);
|
|
val8 &= 0x75;
|
|
rtw_write8(adapter, REG_CR, val8);
|
|
val8 = rtw_read8(adapter, REG_CR);
|
|
/* Set REG_CR bit1, bit3, bit7 to 1*/
|
|
val8 |= 0x8a;
|
|
rtw_write8(adapter, REG_CR, val8);
|
|
RTW_INFO("0x%04x: %02x\n", REG_CR, rtw_read8(adapter, REG_CR));
|
|
}
|
|
static void rtw_hal_set_wow_rxff_boundary(_adapter *adapter, bool wow_mode)
|
|
{
|
|
u8 val8 = 0;
|
|
u16 rxff_bndy = 0;
|
|
u32 rx_dma_buff_sz = 0;
|
|
|
|
val8 = rtw_read8(adapter, REG_FIFOPAGE + 3);
|
|
if (val8 != 0)
|
|
RTW_INFO("%s:[%04x]some PKTs in TXPKTBUF\n",
|
|
__func__, (REG_FIFOPAGE + 3));
|
|
|
|
rtw_hal_reset_mac_rx(adapter);
|
|
|
|
if (wow_mode) {
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW,
|
|
(u8 *)&rx_dma_buff_sz);
|
|
rxff_bndy = rx_dma_buff_sz - 1;
|
|
|
|
rtw_write16(adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
|
|
RTW_INFO("%s: wow mode, 0x%04x: 0x%04x\n", __func__,
|
|
REG_TRXFF_BNDY + 2,
|
|
rtw_read16(adapter, (REG_TRXFF_BNDY + 2)));
|
|
} else {
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ,
|
|
(u8 *)&rx_dma_buff_sz);
|
|
rxff_bndy = rx_dma_buff_sz - 1;
|
|
rtw_write16(adapter, (REG_TRXFF_BNDY + 2), rxff_bndy);
|
|
RTW_INFO("%s: normal mode, 0x%04x: 0x%04x\n", __func__,
|
|
REG_TRXFF_BNDY + 2,
|
|
rtw_read16(adapter, (REG_TRXFF_BNDY + 2)));
|
|
}
|
|
}
|
|
#endif /* CONFIG_WOW_PATTERN_IN_TXFIFO*/
|
|
#ifndef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
bool rtw_read_from_frame_mask(_adapter *adapter, u8 idx)
|
|
{
|
|
u32 data_l = 0, data_h = 0, rx_dma_buff_sz = 0, page_sz = 0;
|
|
u16 offset, rx_buf_ptr = 0;
|
|
u16 cam_start_offset = 0;
|
|
u16 ctrl_l = 0, ctrl_h = 0;
|
|
u8 count = 0, tmp = 0;
|
|
int i = 0;
|
|
bool res = _TRUE;
|
|
|
|
if (idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("[Error]: %s, pattern index is out of range\n",
|
|
__func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW,
|
|
(u8 *)&rx_dma_buff_sz);
|
|
|
|
if (rx_dma_buff_sz == 0) {
|
|
RTW_INFO("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz);
|
|
|
|
if (page_sz == 0) {
|
|
RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
offset = (u16)PageNum(rx_dma_buff_sz, page_sz);
|
|
cam_start_offset = offset * page_sz;
|
|
|
|
ctrl_l = 0x0;
|
|
ctrl_h = 0x0;
|
|
|
|
/* Enable RX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT);
|
|
|
|
/* Read the WKFM CAM */
|
|
for (i = 0; i < (WKFMCAM_ADDR_NUM / 2); i++) {
|
|
/*
|
|
* Set Rx packet buffer offset.
|
|
* RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer.
|
|
* CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE
|
|
* RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
|
|
* * Index: The index of the wake up frame mask
|
|
* * WKFMCAM_SIZE: the total size of one WKFM CAM
|
|
* * per entry offset of a WKFM CAM: Addr i * 4 bytes
|
|
*/
|
|
rx_buf_ptr =
|
|
(cam_start_offset + idx * WKFMCAM_SIZE + i * 8) >> 3;
|
|
rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr);
|
|
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
|
|
data_l = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L);
|
|
data_h = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H);
|
|
|
|
RTW_INFO("[%d]: %08x %08x\n", i, data_h, data_l);
|
|
|
|
count = 0;
|
|
|
|
do {
|
|
tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL);
|
|
rtw_udelay_os(2);
|
|
count++;
|
|
} while (!tmp && count < 100);
|
|
|
|
if (count >= 100) {
|
|
RTW_INFO("%s count:%d\n", __func__, count);
|
|
res = _FALSE;
|
|
}
|
|
}
|
|
|
|
/* Disable RX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL,
|
|
DISABLE_TRXPKT_BUF_ACCESS);
|
|
return res;
|
|
}
|
|
|
|
bool rtw_write_to_frame_mask(_adapter *adapter, u8 idx,
|
|
struct rtl_wow_pattern *context)
|
|
{
|
|
u32 data = 0, rx_dma_buff_sz = 0, page_sz = 0;
|
|
u16 offset, rx_buf_ptr = 0;
|
|
u16 cam_start_offset = 0;
|
|
u16 ctrl_l = 0, ctrl_h = 0;
|
|
u8 count = 0, tmp = 0;
|
|
int res = 0, i = 0;
|
|
|
|
if (idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("[Error]: %s, pattern index is out of range\n",
|
|
__func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW,
|
|
(u8 *)&rx_dma_buff_sz);
|
|
|
|
if (rx_dma_buff_sz == 0) {
|
|
RTW_INFO("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz);
|
|
|
|
if (page_sz == 0) {
|
|
RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
offset = (u16)PageNum(rx_dma_buff_sz, page_sz);
|
|
|
|
cam_start_offset = offset * page_sz;
|
|
|
|
if (IS_HARDWARE_TYPE_8188E(adapter)) {
|
|
ctrl_l = 0x0001;
|
|
ctrl_h = 0x0001;
|
|
} else {
|
|
ctrl_l = 0x0f01;
|
|
ctrl_h = 0xf001;
|
|
}
|
|
|
|
/* Enable RX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT);
|
|
|
|
/* Write the WKFM CAM */
|
|
for (i = 0; i < WKFMCAM_ADDR_NUM; i++) {
|
|
/*
|
|
* Set Rx packet buffer offset.
|
|
* RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer.
|
|
* CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE
|
|
* RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
|
|
* * Index: The index of the wake up frame mask
|
|
* * WKFMCAM_SIZE: the total size of one WKFM CAM
|
|
* * per entry offset of a WKFM CAM: Addr i * 4 bytes
|
|
*/
|
|
rx_buf_ptr =
|
|
(cam_start_offset + idx * WKFMCAM_SIZE + i * 4) >> 3;
|
|
rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr);
|
|
|
|
if (i == 0) {
|
|
if (context->type == PATTERN_VALID)
|
|
data = WOW_VALID_BIT;
|
|
else if (context->type == PATTERN_BROADCAST)
|
|
data = WOW_VALID_BIT | WOW_BC_BIT;
|
|
else if (context->type == PATTERN_MULTICAST)
|
|
data = WOW_VALID_BIT | WOW_MC_BIT;
|
|
else if (context->type == PATTERN_UNICAST)
|
|
data = WOW_VALID_BIT | WOW_UC_BIT;
|
|
|
|
if (context->crc != 0)
|
|
data |= context->crc;
|
|
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data);
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
|
|
} else if (i == 1) {
|
|
data = 0;
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data);
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h);
|
|
} else if (i == 2 || i == 4) {
|
|
data = context->mask[i - 2];
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data);
|
|
/* write to RX packet buffer*/
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
|
|
} else if (i == 3 || i == 5) {
|
|
data = context->mask[i - 2];
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data);
|
|
/* write to RX packet buffer*/
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h);
|
|
}
|
|
|
|
count = 0;
|
|
do {
|
|
tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL);
|
|
rtw_udelay_os(2);
|
|
count++;
|
|
} while (tmp && count < 100);
|
|
|
|
if (count >= 100)
|
|
res = _FALSE;
|
|
else
|
|
res = _TRUE;
|
|
}
|
|
|
|
/* Disable RX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL,
|
|
DISABLE_TRXPKT_BUF_ACCESS);
|
|
|
|
return res;
|
|
}
|
|
void rtw_fill_pattern(_adapter *adapter)
|
|
{
|
|
int i = 0, total = 0, index;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct rtl_wow_pattern wow_pattern;
|
|
|
|
total = pwrpriv->wowlan_pattern_idx;
|
|
|
|
if (total > MAX_WKFM_CAM_NUM)
|
|
total = MAX_WKFM_CAM_NUM;
|
|
|
|
for (i = 0 ; i < total ; i++) {
|
|
if (_SUCCESS == rtw_hal_wow_pattern_generate(adapter, i, &wow_pattern)) {
|
|
|
|
index = i;
|
|
if (!pwrpriv->bInSuspend)
|
|
index += 2;
|
|
rtw_dump_wow_pattern(RTW_DBGDUMP, &wow_pattern, i);
|
|
if (rtw_write_to_frame_mask(adapter, index, &wow_pattern) == _FALSE)
|
|
RTW_INFO("%s: ERROR!! idx: %d write_to_frame_mask_cam fail\n", __func__, i);
|
|
}
|
|
|
|
}
|
|
rtw_write8(adapter, REG_WKFMCAM_NUM, total);
|
|
|
|
}
|
|
#else /* CONFIG_WOW_PATTERN_IN_TXFIFO */
|
|
bool rtw_read_from_frame_mask(_adapter *adapter, u8 idx)
|
|
{
|
|
u32 data_l = 0, data_h = 0, page_sz = 0;
|
|
u16 tx_page_start, tx_buf_ptr = 0;
|
|
u16 cam_start_offset = 0;
|
|
u16 ctrl_l = 0, ctrl_h = 0;
|
|
u8 count = 0, tmp = 0, last_entry = 0;
|
|
int i = 0;
|
|
bool res = _TRUE;
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
u32 buffer[WKFMCAM_ADDR_NUM];
|
|
|
|
|
|
if (idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("[Error]: %s, pattern index is out of range\n",
|
|
__func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&page_sz);
|
|
if (page_sz == 0) {
|
|
RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_BUFFER_LAST_ENTRY, (u8 *)&last_entry);
|
|
if (last_entry == 0) {
|
|
RTW_INFO("[Error]: %s, last entry of tx buffer is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
|
|
if(_rtw_wow_chk_cap(adapter, WOW_CAP_HALMAC_ACCESS_PATTERN_IN_TXFIFO)) {
|
|
/* 8723F cannot indirect access tx fifo
|
|
* rtw_halmac_dump_fifo(dvobj, fifo_sel, fifo_addr, buf_sz, buf)
|
|
*/
|
|
#ifdef RTW_HALMAC
|
|
rtw_halmac_dump_fifo(adapter_to_dvobj(adapter),
|
|
2,
|
|
(pwrctl->pattern_rsvd_page_loc * page_sz) + (idx * WKFMCAM_ADDR_NUM * 4),
|
|
WKFMCAM_ADDR_NUM*4, (u8*)buffer);
|
|
#endif
|
|
|
|
for (i = 0; i < (WKFMCAM_ADDR_NUM / 2); i++) {
|
|
RTW_INFO("[%d]: %08x %08x\n", i, *(buffer + i*2), *(buffer + i*2 + 1));
|
|
}
|
|
} else {
|
|
/* use the last 2 pages for wow pattern e.g. 0xfe and 0xff */
|
|
tx_page_start = last_entry - 1;
|
|
cam_start_offset = tx_page_start * page_sz / 8;
|
|
ctrl_l = 0x0;
|
|
ctrl_h = 0x0;
|
|
|
|
/* Enable TX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
|
|
|
|
/* Read the WKFM CAM */
|
|
for (i = 0; i < (WKFMCAM_ADDR_NUM / 2); i++) {
|
|
/*
|
|
* Set Tx packet buffer offset.
|
|
* TxBufer pointer increases 1, we can access 8 bytes in Tx packet buffer.
|
|
* CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE
|
|
* TxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
|
|
* * Index: The index of the wake up frame mask
|
|
* * WKFMCAM_SIZE: the total size of one WKFM CAM
|
|
* * per entry offset of a WKFM CAM: Addr i * 4 bytes
|
|
*/
|
|
tx_buf_ptr =
|
|
(cam_start_offset + idx * WKFMCAM_SIZE + i * 8) >> 3;
|
|
rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, tx_buf_ptr);
|
|
rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
|
|
data_l = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L);
|
|
data_h = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H);
|
|
|
|
RTW_INFO("[%d]: %08x %08x\n", i, data_h, data_l);
|
|
|
|
count = 0;
|
|
|
|
do {
|
|
tmp = rtw_read32(adapter, REG_PKTBUF_DBG_CTRL) & BIT23;
|
|
rtw_udelay_os(2);
|
|
count++;
|
|
} while (!tmp && count < 100);
|
|
|
|
if (count >= 100) {
|
|
RTW_INFO("%s count:%d\n", __func__, count);
|
|
res = _FALSE;
|
|
}
|
|
}
|
|
|
|
/* Disable RX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL,
|
|
DISABLE_TRXPKT_BUF_ACCESS);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
bool rtw_write_to_frame_mask(_adapter *adapter, u8 idx,
|
|
struct rtl_wow_pattern *context)
|
|
{
|
|
u32 tx_page_start = 0, page_sz = 0;
|
|
u16 tx_buf_ptr = 0;
|
|
u16 cam_start_offset = 0;
|
|
u32 data_l = 0, data_h = 0;
|
|
u8 count = 0, tmp = 0, last_entry = 0;
|
|
int res = 0, i = 0;
|
|
|
|
if (idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("[Error]: %s, pattern index is out of range\n",
|
|
__func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&page_sz);
|
|
if (page_sz == 0) {
|
|
RTW_INFO("[Error]: %s, page_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_BUFFER_LAST_ENTRY, (u8 *)&last_entry);
|
|
if (last_entry == 0) {
|
|
RTW_INFO("[Error]: %s, last entry of tx buffer is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
/* use the last 2 pages for wow pattern e.g. 0xfe and 0xff */
|
|
tx_page_start = last_entry - 1;
|
|
cam_start_offset = tx_page_start * page_sz / 8;
|
|
|
|
/* Write the PATTERN location to BIT_TXBUF_WKCAM_OFFSET */
|
|
rtw_write8(adapter, REG_TXBUF_WKCAM_OFFSET, cam_start_offset & 0xFF);
|
|
rtw_write8(adapter, REG_TXBUF_WKCAM_OFFSET + 1, (cam_start_offset >> 8) & 0xFF);
|
|
/* Enable TX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, TXPKT_BUF_SELECT);
|
|
|
|
/* Write the WKFM CAM */
|
|
for (i = 0; i < WKFMCAM_ADDR_NUM / 2; i++) {
|
|
/*
|
|
* Set Tx packet buffer offset.
|
|
* TxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer.
|
|
* CAM start offset (unit: 1 byte) = Index*WKFMCAM_SIZE
|
|
* TxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
|
|
* * Index: The index of the wake up frame mask
|
|
* * WKFMCAM_SIZE: the total size of one WKFM CAM
|
|
* * per entry offset of a WKFM CAM: Addr i * 4 bytes
|
|
*/
|
|
tx_buf_ptr = cam_start_offset + ((idx * WKFMCAM_SIZE + i * 8) >> 3);
|
|
|
|
if (i == 0) {
|
|
if (context->type == PATTERN_VALID)
|
|
data_l = WOW_VALID_BIT;
|
|
else if (context->type == PATTERN_BROADCAST)
|
|
data_l = WOW_VALID_BIT | WOW_BC_BIT;
|
|
else if (context->type == PATTERN_MULTICAST)
|
|
data_l = WOW_VALID_BIT | WOW_MC_BIT;
|
|
else if (context->type == PATTERN_UNICAST)
|
|
data_l = WOW_VALID_BIT | WOW_UC_BIT;
|
|
|
|
if (context->crc != 0)
|
|
data_l |= context->crc;
|
|
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data_l);
|
|
} else {
|
|
data_l = context->mask[i * 2 - 2];
|
|
data_h = context->mask[i * 2 - 1];
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data_l);
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data_h);
|
|
}
|
|
|
|
rtw_write32(adapter, REG_PKTBUF_DBG_CTRL, (tx_buf_ptr & 0x1FFF) | BIT23 | (0xff <<24));
|
|
count = 0;
|
|
do {
|
|
tmp = rtw_read32(adapter, REG_PKTBUF_DBG_CTRL) & BIT23;
|
|
rtw_udelay_os(2);
|
|
count++;
|
|
} while (tmp && count < 100);
|
|
|
|
if (count >= 100) {
|
|
res = _FALSE;
|
|
RTW_INFO("%s write failed\n", __func__);
|
|
} else {
|
|
res = _TRUE;
|
|
RTW_INFO("%s write OK\n", __func__);
|
|
}
|
|
}
|
|
|
|
/* Disable TX packet buffer access */
|
|
rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, DISABLE_TRXPKT_BUF_ACCESS);
|
|
return res;
|
|
}
|
|
bool rtw_write_to_frame_mask_buf(_adapter *adapter, u8 idx,
|
|
struct rtl_wow_pattern *context, char *pattern_info, u32 *ppattern_info_len)
|
|
{
|
|
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
u32 page_sz = 0;
|
|
int res = _FALSE, i = 0;
|
|
u32 tmp_pattern_buf[6] = {0};
|
|
|
|
if (pattern_info == NULL) {
|
|
RTW_ERR("[Error]: %s, pattern info is NULL\n", __func__);
|
|
}
|
|
if (idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_ERR("[Error]: %s, pattern index is out of range\n",
|
|
__func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&page_sz);
|
|
if (page_sz == 0) {
|
|
RTW_ERR("[Error]: %s, page_sz is 0!!\n", __func__);
|
|
return _FALSE;
|
|
}
|
|
|
|
/* Fill WKFM */
|
|
for (i = 0; i < WKFMCAM_ADDR_NUM / 2; i++) {
|
|
if (i == 0) {
|
|
if (context->type == PATTERN_VALID)
|
|
tmp_pattern_buf[0] = WOW_VALID_BIT;
|
|
else if (context->type == PATTERN_BROADCAST)
|
|
tmp_pattern_buf[0] = WOW_VALID_BIT | WOW_BC_BIT;
|
|
else if (context->type == PATTERN_MULTICAST)
|
|
tmp_pattern_buf[0] = WOW_VALID_BIT | WOW_MC_BIT;
|
|
else if (context->type == PATTERN_UNICAST)
|
|
tmp_pattern_buf[0] = WOW_VALID_BIT | WOW_UC_BIT;
|
|
|
|
if (context->crc != 0)
|
|
tmp_pattern_buf[0] |= context->crc;
|
|
/* pattern[1] is reserved in pattern format, dont care. */
|
|
|
|
} else {
|
|
tmp_pattern_buf[i * 2] = context->mask[i * 2 - 2];
|
|
tmp_pattern_buf[i * 2 + 1] = context->mask[i * 2 - 1];
|
|
}
|
|
}
|
|
|
|
|
|
/* put pattern to pattern_buf */
|
|
_rtw_memcpy((pattern_info + idx * WKFMCAM_SIZE) , tmp_pattern_buf, WKFMCAM_SIZE);
|
|
*ppattern_info_len += WKFMCAM_SIZE;
|
|
#ifdef CONFIG_WOW_PATTERN_IN_TXFIFO_DBG
|
|
RTW_INFO("\nidx : %u pattern_info_len : %u\n", idx, *ppattern_info_len);
|
|
RTW_INFO_DUMP("", (pattern_info + idx * WKFMCAM_SIZE), WKFMCAM_SIZE);
|
|
#endif
|
|
res = _TRUE;
|
|
|
|
|
|
return res;
|
|
}
|
|
#endif /* CONFIG_WOW_PATTERN_IN_TXFIFO */
|
|
|
|
void rtw_clean_pattern(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct rtl_wow_pattern zero_pattern;
|
|
int i = 0;
|
|
|
|
_rtw_memset(&zero_pattern, 0, sizeof(struct rtl_wow_pattern));
|
|
|
|
zero_pattern.type = PATTERN_INVALID;
|
|
/* pattern in tx fifo do not need clear to zero*/
|
|
|
|
rtw_write8(adapter, REG_WKFMCAM_NUM, 0);
|
|
}
|
|
#if 0
|
|
static int rtw_hal_set_pattern(_adapter *adapter, u8 *pattern,
|
|
u8 len, u8 *mask, u8 idx)
|
|
{
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct mlme_ext_priv *pmlmeext = NULL;
|
|
struct mlme_ext_info *pmlmeinfo = NULL;
|
|
struct rtl_wow_pattern wow_pattern;
|
|
u8 mask_hw[MAX_WKFM_SIZE] = {0};
|
|
u8 content[MAX_WKFM_PATTERN_SIZE] = {0};
|
|
u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
u8 multicast_addr1[2] = {0x33, 0x33};
|
|
u8 multicast_addr2[3] = {0x01, 0x00, 0x5e};
|
|
u8 res = _FALSE, index = 0, mask_len = 0;
|
|
u8 mac_addr[ETH_ALEN] = {0};
|
|
u16 count = 0;
|
|
int i, j;
|
|
|
|
if (pwrctl->wowlan_pattern_idx > MAX_WKFM_CAM_NUM) {
|
|
RTW_INFO("%s pattern_idx is more than MAX_FMC_NUM: %d\n",
|
|
__func__, MAX_WKFM_CAM_NUM);
|
|
return _FALSE;
|
|
}
|
|
|
|
pmlmeext = &adapter->mlmeextpriv;
|
|
pmlmeinfo = &pmlmeext->mlmext_info;
|
|
_rtw_memcpy(mac_addr, adapter_mac_addr(adapter), ETH_ALEN);
|
|
_rtw_memset(&wow_pattern, 0, sizeof(struct rtl_wow_pattern));
|
|
|
|
mask_len = DIV_ROUND_UP(len, 8);
|
|
|
|
/* 1. setup A1 table */
|
|
if (memcmp(pattern, broadcast_addr, ETH_ALEN) == 0)
|
|
wow_pattern.type = PATTERN_BROADCAST;
|
|
else if (memcmp(pattern, multicast_addr1, 2) == 0)
|
|
wow_pattern.type = PATTERN_MULTICAST;
|
|
else if (memcmp(pattern, multicast_addr2, 3) == 0)
|
|
wow_pattern.type = PATTERN_MULTICAST;
|
|
else if (memcmp(pattern, mac_addr, ETH_ALEN) == 0)
|
|
wow_pattern.type = PATTERN_UNICAST;
|
|
else
|
|
wow_pattern.type = PATTERN_INVALID;
|
|
|
|
/* translate mask from os to mask for hw */
|
|
|
|
/******************************************************************************
|
|
* pattern from OS uses 'ethenet frame', like this:
|
|
|
|
| 6 | 6 | 2 | 20 | Variable | 4 |
|
|
|--------+--------+------+-----------+------------+-----|
|
|
| 802.3 Mac Header | IP Header | TCP Packet | FCS |
|
|
| DA | SA | Type |
|
|
|
|
* BUT, packet catched by our HW is in '802.11 frame', begin from LLC,
|
|
|
|
| 24 or 30 | 6 | 2 | 20 | Variable | 4 |
|
|
|-------------------+--------+------+-----------+------------+-----|
|
|
| 802.11 MAC Header | LLC | IP Header | TCP Packet | FCS |
|
|
| Others | Tpye |
|
|
|
|
* Therefore, we need translate mask_from_OS to mask_to_hw.
|
|
* We should left-shift mask by 6 bits, then set the new bit[0~5] = 0,
|
|
* because new mask[0~5] means 'SA', but our HW packet begins from LLC,
|
|
* bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
|
|
******************************************************************************/
|
|
/* Shift 6 bits */
|
|
for (i = 0; i < mask_len - 1; i++) {
|
|
mask_hw[i] = mask[i] >> 6;
|
|
mask_hw[i] |= (mask[i + 1] & 0x3F) << 2;
|
|
}
|
|
|
|
mask_hw[i] = (mask[i] >> 6) & 0x3F;
|
|
/* Set bit 0-5 to zero */
|
|
mask_hw[0] &= 0xC0;
|
|
|
|
for (i = 0; i < (MAX_WKFM_SIZE / 4); i++) {
|
|
wow_pattern.mask[i] = mask_hw[i * 4];
|
|
wow_pattern.mask[i] |= (mask_hw[i * 4 + 1] << 8);
|
|
wow_pattern.mask[i] |= (mask_hw[i * 4 + 2] << 16);
|
|
wow_pattern.mask[i] |= (mask_hw[i * 4 + 3] << 24);
|
|
}
|
|
|
|
/* To get the wake up pattern from the mask.
|
|
* We do not count first 12 bits which means
|
|
* DA[6] and SA[6] in the pattern to match HW design. */
|
|
count = 0;
|
|
for (i = 12; i < len; i++) {
|
|
if ((mask[i / 8] >> (i % 8)) & 0x01) {
|
|
content[count] = pattern[i];
|
|
count++;
|
|
}
|
|
}
|
|
|
|
wow_pattern.crc = rtw_calc_crc(content, count);
|
|
|
|
if (wow_pattern.crc != 0) {
|
|
if (wow_pattern.type == PATTERN_INVALID)
|
|
wow_pattern.type = PATTERN_VALID;
|
|
}
|
|
|
|
index = idx;
|
|
|
|
if (!pwrctl->bInSuspend)
|
|
index += 2;
|
|
|
|
/* write pattern */
|
|
res = rtw_write_to_frame_mask(adapter, index, &wow_pattern);
|
|
|
|
if (res == _FALSE)
|
|
RTW_INFO("%s: ERROR!! idx: %d write_to_frame_mask_cam fail\n",
|
|
__func__, idx);
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
#else /*CONFIG_WOW_PATTERN_HW_CAM*/
|
|
|
|
#define WOW_CAM_ACCESS_TIMEOUT_MS 200
|
|
static u32 _rtw_wow_pattern_read_cam(_adapter *adapter, u8 addr)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
_mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex;
|
|
|
|
u32 rdata = 0;
|
|
u32 cnt = 0;
|
|
systime start = 0;
|
|
u8 timeout = 0;
|
|
u8 rst = _FALSE;
|
|
|
|
_enter_critical_mutex(mutex, NULL);
|
|
|
|
rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_ADDR_V2(addr));
|
|
|
|
start = rtw_get_current_time();
|
|
while (1) {
|
|
if (rtw_is_surprise_removed(adapter))
|
|
break;
|
|
|
|
cnt++;
|
|
if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1)) {
|
|
rst = _SUCCESS;
|
|
break;
|
|
}
|
|
if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) {
|
|
timeout = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rdata = rtw_read32(adapter, REG_WKFMCAM_RWD);
|
|
|
|
_exit_critical_mutex(mutex, NULL);
|
|
|
|
/*RTW_INFO("%s ==> addr:0x%02x , rdata:0x%08x\n", __func__, addr, rdata);*/
|
|
|
|
if (timeout)
|
|
RTW_ERR(FUNC_ADPT_FMT" failed due to polling timeout\n", FUNC_ADPT_ARG(adapter));
|
|
|
|
return rdata;
|
|
}
|
|
void rtw_wow_pattern_read_cam_ent(_adapter *adapter, u8 id, struct rtl_wow_pattern *context)
|
|
{
|
|
int i;
|
|
u32 rdata;
|
|
|
|
_rtw_memset(context, 0, sizeof(struct rtl_wow_pattern));
|
|
|
|
for (i = 4; i >= 0; i--) {
|
|
rdata = _rtw_wow_pattern_read_cam(adapter, (id << 3) | i);
|
|
|
|
switch (i) {
|
|
case 4:
|
|
if (rdata & WOW_BC_BIT)
|
|
context->type = PATTERN_BROADCAST;
|
|
else if (rdata & WOW_MC_BIT)
|
|
context->type = PATTERN_MULTICAST;
|
|
else if (rdata & WOW_UC_BIT)
|
|
context->type = PATTERN_UNICAST;
|
|
else
|
|
context->type = PATTERN_INVALID;
|
|
|
|
context->crc = rdata & 0xFFFF;
|
|
break;
|
|
default:
|
|
_rtw_memcpy(&context->mask[i], (u8 *)(&rdata), 4);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _rtw_wow_pattern_write_cam(_adapter *adapter, u8 addr, u32 wdata)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
_mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex;
|
|
u32 cnt = 0;
|
|
systime start = 0, end = 0;
|
|
u8 timeout = 0;
|
|
|
|
/*RTW_INFO("%s ==> addr:0x%02x , wdata:0x%08x\n", __func__, addr, wdata);*/
|
|
_enter_critical_mutex(mutex, NULL);
|
|
|
|
rtw_write32(adapter, REG_WKFMCAM_RWD, wdata);
|
|
rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_WE | BIT_WKFCAM_ADDR_V2(addr));
|
|
|
|
start = rtw_get_current_time();
|
|
while (1) {
|
|
if (rtw_is_surprise_removed(adapter))
|
|
break;
|
|
|
|
cnt++;
|
|
if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1))
|
|
break;
|
|
|
|
if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) {
|
|
timeout = 1;
|
|
break;
|
|
}
|
|
}
|
|
end = rtw_get_current_time();
|
|
|
|
_exit_critical_mutex(mutex, NULL);
|
|
|
|
if (timeout) {
|
|
RTW_ERR(FUNC_ADPT_FMT" addr:0x%02x, wdata:0x%08x, to:%u, polling:%u, %d ms\n"
|
|
, FUNC_ADPT_ARG(adapter), addr, wdata, timeout, cnt, rtw_get_time_interval_ms(start, end));
|
|
}
|
|
}
|
|
|
|
void rtw_wow_pattern_write_cam_ent(_adapter *adapter, u8 id, struct rtl_wow_pattern *context)
|
|
{
|
|
int j;
|
|
u8 addr;
|
|
u32 wdata = 0;
|
|
|
|
for (j = 4; j >= 0; j--) {
|
|
switch (j) {
|
|
case 4:
|
|
wdata = context->crc;
|
|
|
|
if (PATTERN_BROADCAST == context->type)
|
|
wdata |= WOW_BC_BIT;
|
|
if (PATTERN_MULTICAST == context->type)
|
|
wdata |= WOW_MC_BIT;
|
|
if (PATTERN_UNICAST == context->type)
|
|
wdata |= WOW_UC_BIT;
|
|
if (PATTERN_INVALID != context->type)
|
|
wdata |= WOW_VALID_BIT;
|
|
break;
|
|
default:
|
|
wdata = context->mask[j];
|
|
break;
|
|
}
|
|
|
|
addr = (id << 3) + j;
|
|
|
|
_rtw_wow_pattern_write_cam(adapter, addr, wdata);
|
|
}
|
|
}
|
|
|
|
static u8 _rtw_wow_pattern_clean_cam(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
_mutex *mutex = &pwrpriv->wowlan_pattern_cam_mutex;
|
|
u32 cnt = 0;
|
|
systime start = 0;
|
|
u8 timeout = 0;
|
|
u8 rst = _FAIL;
|
|
|
|
_enter_critical_mutex(mutex, NULL);
|
|
rtw_write32(adapter, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 | BIT_WKFCAM_CLR_V1);
|
|
|
|
start = rtw_get_current_time();
|
|
while (1) {
|
|
if (rtw_is_surprise_removed(adapter))
|
|
break;
|
|
|
|
cnt++;
|
|
if (0 == (rtw_read32(adapter, REG_WKFMCAM_CMD) & BIT_WKFCAM_POLLING_V1)) {
|
|
rst = _SUCCESS;
|
|
break;
|
|
}
|
|
if (rtw_get_passing_time_ms(start) > WOW_CAM_ACCESS_TIMEOUT_MS) {
|
|
timeout = 1;
|
|
break;
|
|
}
|
|
}
|
|
_exit_critical_mutex(mutex, NULL);
|
|
|
|
if (timeout)
|
|
RTW_ERR(FUNC_ADPT_FMT" falied ,polling timeout\n", FUNC_ADPT_ARG(adapter));
|
|
|
|
return rst;
|
|
}
|
|
|
|
void rtw_clean_pattern(_adapter *adapter)
|
|
{
|
|
if (_FAIL == _rtw_wow_pattern_clean_cam(adapter))
|
|
RTW_ERR("rtw_clean_pattern failed\n");
|
|
}
|
|
void rtw_fill_pattern(_adapter *adapter)
|
|
{
|
|
int i = 0, total = 0;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct rtl_wow_pattern wow_pattern;
|
|
|
|
total = pwrpriv->wowlan_pattern_idx;
|
|
|
|
if (total > MAX_WKFM_CAM_NUM)
|
|
total = MAX_WKFM_CAM_NUM;
|
|
|
|
for (i = 0 ; i < total ; i++) {
|
|
if (_SUCCESS == rtw_hal_wow_pattern_generate(adapter, i, &wow_pattern)) {
|
|
rtw_dump_wow_pattern(RTW_DBGDUMP, &wow_pattern, i);
|
|
rtw_wow_pattern_write_cam_ent(adapter, i, &wow_pattern);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
void rtw_wow_pattern_cam_dump(_adapter *adapter)
|
|
{
|
|
|
|
#ifndef CONFIG_WOW_PATTERN_HW_CAM
|
|
int i = 0, total = 0;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
total = pwrpriv->wowlan_pattern_idx;
|
|
|
|
if (total > MAX_WKFM_CAM_NUM)
|
|
total = MAX_WKFM_CAM_NUM;
|
|
|
|
for (i = 0 ; i < total; i++) {
|
|
RTW_INFO("=======[%d]=======\n", i);
|
|
rtw_read_from_frame_mask(adapter, i);
|
|
}
|
|
#else
|
|
struct rtl_wow_pattern context;
|
|
int i;
|
|
|
|
for (i = 0 ; i < MAX_WKFM_CAM_NUM; i++) {
|
|
rtw_wow_pattern_read_cam_ent(adapter, i, &context);
|
|
rtw_dump_wow_pattern(RTW_DBGDUMP, &context, i);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
static void rtw_hal_dl_pattern(_adapter *adapter, u8 mode)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
|
|
switch (mode) {
|
|
case 0:
|
|
rtw_clean_pattern(adapter);
|
|
RTW_INFO("%s: total patterns: %d\n", __func__, pwrpriv->wowlan_pattern_idx);
|
|
break;
|
|
case 1:
|
|
#if defined(CONFIG_WOW_PATTERN_IN_TXFIFO)
|
|
RTW_INFO("%s Patterns have been downloaded in rsvd pages\n", __func__);
|
|
#else
|
|
rtw_set_default_pattern(adapter);
|
|
rtw_fill_pattern(adapter);
|
|
RTW_INFO("%s: pattern total: %d downloaded\n", __func__, pwrpriv->wowlan_pattern_idx);
|
|
#endif
|
|
break;
|
|
case 2:
|
|
rtw_clean_pattern(adapter);
|
|
rtw_wow_pattern_sw_reset(adapter);
|
|
RTW_INFO("%s: clean patterns\n", __func__);
|
|
break;
|
|
default:
|
|
RTW_INFO("%s: unknown mode\n", __func__);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void rtw_hal_wow_enable(_adapter *adapter)
|
|
{
|
|
struct registry_priv *registry_par = &adapter->registrypriv;
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct sta_info *psta = NULL;
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(adapter);
|
|
int res;
|
|
u16 media_status_rpt;
|
|
u8 no_wake = 0, i;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface;
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
u8 val8 = 0;
|
|
#endif
|
|
|
|
#ifdef CONFIG_LPS_PG
|
|
u8 lps_pg_hdl_id = 0;
|
|
#endif
|
|
|
|
|
|
|
|
if(registry_par->suspend_type == FW_IPS_DISABLE_BBRF &&
|
|
!check_fwstate(pmlmepriv, WIFI_ASOC_STATE))
|
|
no_wake = 1;
|
|
|
|
RTW_PRINT(FUNC_ADPT_FMT " WOWLAN_ENABLE\n", FUNC_ADPT_ARG(adapter));
|
|
rtw_hal_gate_bb(adapter, _TRUE);
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
/* Start Usb TxDMA */
|
|
if(iface) {
|
|
RTW_INFO(ADPT_FMT "enable TX\n", ADPT_ARG(iface));
|
|
RTW_ENABLE_FUNC(iface, DF_TX_BIT);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_GTK_OL
|
|
if (psecuritypriv->binstallKCK_KEK == _TRUE)
|
|
rtw_hal_fw_sync_cam_id(adapter);
|
|
#endif
|
|
if (IS_HARDWARE_TYPE_8723B(adapter))
|
|
rtw_hal_backup_rate(adapter);
|
|
|
|
rtw_hal_fw_dl(adapter, _TRUE);
|
|
if(no_wake)
|
|
media_status_rpt = RT_MEDIA_DISCONNECT;
|
|
else
|
|
media_status_rpt = RT_MEDIA_CONNECT;
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT,
|
|
(u8 *)&media_status_rpt);
|
|
|
|
/* RX DMA stop */
|
|
#if defined(CONFIG_RTL8188E)
|
|
if (IS_HARDWARE_TYPE_8188E(adapter))
|
|
rtw_hal_disable_tx_report(adapter);
|
|
#endif
|
|
|
|
res = rtw_hal_pause_rx_dma(adapter);
|
|
if (res == _FAIL)
|
|
RTW_PRINT("[WARNING] pause RX DMA fail\n");
|
|
|
|
#ifndef CONFIG_WOW_PATTERN_HW_CAM
|
|
/* Reconfig RX_FF Boundary */
|
|
#ifndef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
rtw_hal_set_wow_rxff_boundary(adapter, _TRUE);
|
|
#endif /*CONFIG_WOW_PATTERN_IN_TXFIFO*/
|
|
#endif
|
|
|
|
/* redownload wow pattern */
|
|
if(!no_wake)
|
|
rtw_hal_dl_pattern(adapter, 1);
|
|
|
|
if (!pwrctl->wowlan_pno_enable) {
|
|
psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
|
|
|
|
if (psta != NULL) {
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
adapter_to_dvobj(adapter)->dft.port_id = 0xFF;
|
|
adapter_to_dvobj(adapter)->dft.mac_id = 0xFF;
|
|
rtw_hal_set_default_port_id_cmd(adapter, psta->cmn.mac_id);
|
|
#endif
|
|
if(!no_wake)
|
|
rtw_sta_media_status_rpt(adapter, psta, 1);
|
|
}
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
else {
|
|
if(registry_par->suspend_type == FW_IPS_WRC) {
|
|
adapter_to_dvobj(adapter)->dft.port_id = 0xFF;
|
|
adapter_to_dvobj(adapter)->dft.mac_id = 0xFF;
|
|
rtw_hal_set_default_port_id_cmd(adapter, 0);
|
|
}
|
|
}
|
|
#endif /* CONFIG_FW_MULTI_PORT_SUPPORT */
|
|
}
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
else {
|
|
rtw_hal_set_default_port_id_cmd(adapter, 0);
|
|
}
|
|
#endif /* CONFIG_FW_MULTI_PORT_SUPPORT */
|
|
|
|
#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
|
|
/* Enable CPWM2 only. */
|
|
res = rtw_hal_enable_cpwm2(adapter);
|
|
if (res == _FAIL)
|
|
RTW_PRINT("[WARNING] enable cpwm2 fail\n");
|
|
#endif
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
#ifdef CONFIG_RTW_ONE_PIN_GPIO
|
|
rtw_hal_switch_gpio_wl_ctrl(adapter, pwrctl->wowlan_gpio_index, _TRUE);
|
|
rtw_hal_set_input_gpio(adapter, pwrctl->wowlan_gpio_index);
|
|
#else
|
|
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
|
|
if (pwrctl->is_high_active == 0)
|
|
rtw_hal_set_input_gpio(adapter, pwrctl->wowlan_gpio_index);
|
|
else
|
|
rtw_hal_set_output_gpio(adapter, pwrctl->wowlan_gpio_index,
|
|
GPIO_OUTPUT_LOW);
|
|
#else
|
|
val8 = (pwrctl->is_high_active == 0) ? 1 : 0;
|
|
rtw_hal_set_output_gpio(adapter, pwrctl->wowlan_gpio_index, val8);
|
|
rtw_hal_switch_gpio_wl_ctrl(adapter, pwrctl->wowlan_gpio_index, _TRUE);
|
|
RTW_INFO("%s: set GPIO_%d to OUTPUT %s state in wow suspend and %s_ACTIVE.\n",
|
|
__func__, pwrctl->wowlan_gpio_index,
|
|
pwrctl->wowlan_gpio_output_state ? "HIGH" : "LOW",
|
|
pwrctl->is_high_active ? "HIGI" : "LOW");
|
|
#endif /* CONFIG_WAKEUP_GPIO_INPUT_MODE */
|
|
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
|
|
#endif /* CONFIG_GPIO_WAKEUP */
|
|
/* Set WOWLAN H2C command. */
|
|
RTW_PRINT("Set WOWLan cmd\n");
|
|
rtw_hal_set_fw_wow_related_cmd(adapter, 1);
|
|
|
|
res = rtw_hal_check_wow_ctrl(adapter, _TRUE);
|
|
|
|
if (res == _FALSE)
|
|
RTW_INFO("[Error]%s: set wowlan CMD fail!!\n", __func__);
|
|
|
|
pwrctl->wowlan_wake_reason =
|
|
rtw_read8(adapter, REG_WOWLAN_WAKE_REASON);
|
|
|
|
RTW_PRINT("wowlan_wake_reason: 0x%02x\n",
|
|
pwrctl->wowlan_wake_reason);
|
|
|
|
#if defined(RTW_HALMAC) && defined(CONFIG_PNO_SUPPORT)
|
|
if(pwrctl->wowlan_pno_enable)
|
|
rtw_halmac_pno_scanoffload(adapter->dvobj, 1);
|
|
#endif
|
|
|
|
#ifdef CONFIG_GTK_OL_DBG
|
|
dump_sec_cam(RTW_DBGDUMP, adapter);
|
|
dump_sec_cam_cache(RTW_DBGDUMP, adapter);
|
|
#endif
|
|
|
|
#ifdef CONFIG_LPS_PG
|
|
if (pwrctl->lps_level == LPS_PG) {
|
|
lps_pg_hdl_id = LPS_PG_INFO_CFG;
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_LPS_PG_HANDLE, (u8 *)(&lps_pg_hdl_id));
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_HCI
|
|
/* free adapter's resource */
|
|
rtw_mi_intf_stop(adapter);
|
|
|
|
#endif
|
|
#if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
|
|
/* Invoid SE0 reset signal during suspending*/
|
|
rtw_write8(adapter, REG_RSV_CTRL, 0x20);
|
|
if (IS_8188F(pHalData->version_id) == FALSE
|
|
&& IS_8188GTV(pHalData->version_id) == FALSE)
|
|
rtw_write8(adapter, REG_RSV_CTRL, 0x60);
|
|
#endif
|
|
|
|
rtw_hal_gate_bb(adapter, _FALSE);
|
|
}
|
|
|
|
#define DBG_WAKEUP_REASON
|
|
#ifdef DBG_WAKEUP_REASON
|
|
void _dbg_wake_up_reason_string(_adapter *adapter, const char *srt_res)
|
|
{
|
|
RTW_INFO(ADPT_FMT "- wake up reason - %s\n", ADPT_ARG(adapter), srt_res);
|
|
}
|
|
void _dbg_rtw_wake_up_reason(_adapter *adapter, u8 reason)
|
|
{
|
|
if (RX_PAIRWISEKEY == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx pairwise key");
|
|
else if (RX_GTK == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx GTK");
|
|
else if (RX_FOURWAY_HANDSHAKE == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx four way handshake");
|
|
else if (RX_DISASSOC == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx disassoc");
|
|
else if (RX_DEAUTH == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx deauth");
|
|
else if (RX_ARP_REQUEST == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx ARP request");
|
|
else if (FW_DECISION_DISCONNECT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "FW detect disconnect");
|
|
else if (RX_MAGIC_PKT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx magic packet");
|
|
else if (RX_UNICAST_PKT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx unicast packet");
|
|
else if (RX_PATTERN_PKT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx pattern packet");
|
|
else if (RX_PNO == reason)
|
|
_dbg_wake_up_reason_string(adapter, "RX PNO");
|
|
else if (RTD3_SSID_MATCH == reason)
|
|
_dbg_wake_up_reason_string(adapter, "RTD3 SSID match");
|
|
else if (RX_REALWOW_V2_WAKEUP_PKT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx real WOW V2 wakeup packet");
|
|
else if (RX_REALWOW_V2_ACK_LOST == reason)
|
|
_dbg_wake_up_reason_string(adapter, "Rx real WOW V2 ack lost");
|
|
else if (ENABLE_FAIL_DMA_IDLE == reason)
|
|
_dbg_wake_up_reason_string(adapter, "enable fail DMA idle");
|
|
else if (ENABLE_FAIL_DMA_PAUSE == reason)
|
|
_dbg_wake_up_reason_string(adapter, "enable fail DMA pause");
|
|
else if (AP_OFFLOAD_WAKEUP == reason)
|
|
_dbg_wake_up_reason_string(adapter, "AP offload wakeup");
|
|
else if (CLK_32K_UNLOCK == reason)
|
|
_dbg_wake_up_reason_string(adapter, "clk 32k unlock");
|
|
else if (RTIME_FAIL_DMA_IDLE == reason)
|
|
_dbg_wake_up_reason_string(adapter, "RTIME fail DMA idle");
|
|
else if (CLK_32K_LOCK == reason)
|
|
_dbg_wake_up_reason_string(adapter, "clk 32k lock");
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
else if (WOW_KEEPALIVE_ACK_TIMEOUT == reason)
|
|
_dbg_wake_up_reason_string(adapter, "rx keep alive ack timeout");
|
|
else if (WOW_KEEPALIVE_WAKE == reason)
|
|
_dbg_wake_up_reason_string(adapter, "rx keep alive wake pattern");
|
|
#endif /*CONFIG_WOW_KEEP_ALIVE_PATTERN*/
|
|
else
|
|
_dbg_wake_up_reason_string(adapter, "unknown reasoen");
|
|
}
|
|
#endif
|
|
|
|
static void rtw_hal_wow_disable(_adapter *adapter)
|
|
{
|
|
int i;
|
|
struct recv_reorder_ctrl *preorder_ctrl;
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct sta_info *psta = NULL;
|
|
struct registry_priv *registry_par = &adapter->registrypriv;
|
|
int res;
|
|
u16 media_status_rpt;
|
|
|
|
RTW_PRINT("%s, WOWLAN_DISABLE\n", __func__);
|
|
|
|
if(registry_par->suspend_type == FW_IPS_DISABLE_BBRF && !check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) {
|
|
RTW_INFO("FW_IPS_DISABLE_BBRF resume\n");
|
|
return;
|
|
}
|
|
|
|
if (!pwrctl->wowlan_pno_enable) {
|
|
psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
|
|
if (psta != NULL)
|
|
rtw_sta_media_status_rpt(adapter, psta, 0);
|
|
else
|
|
RTW_INFO("%s: psta is null\n", __func__);
|
|
}
|
|
#if defined(RTW_HALMAC) && defined(CONFIG_PNO_SUPPORT)
|
|
else {
|
|
rtw_halmac_pno_scanoffload(adapter->dvobj, 0);
|
|
}
|
|
#endif
|
|
|
|
if (0) {
|
|
RTW_INFO("0x630:0x%02x\n", rtw_read8(adapter, 0x630));
|
|
RTW_INFO("0x631:0x%02x\n", rtw_read8(adapter, 0x631));
|
|
RTW_INFO("0x634:0x%02x\n", rtw_read8(adapter, 0x634));
|
|
RTW_INFO("0x1c7:0x%02x\n", rtw_read8(adapter, 0x1c7));
|
|
}
|
|
|
|
pwrctl->wowlan_wake_reason = rtw_read8(adapter, REG_WOWLAN_WAKE_REASON);
|
|
|
|
RTW_PRINT("wakeup_reason: 0x%02x\n",
|
|
pwrctl->wowlan_wake_reason);
|
|
#ifdef DBG_WAKEUP_REASON
|
|
_dbg_rtw_wake_up_reason(adapter, pwrctl->wowlan_wake_reason);
|
|
#endif
|
|
|
|
rtw_hal_set_fw_wow_related_cmd(adapter, 0);
|
|
|
|
res = rtw_hal_check_wow_ctrl(adapter, _FALSE);
|
|
|
|
#if defined(CONFIG_RTL8188E)
|
|
if (IS_HARDWARE_TYPE_8188E(adapter))
|
|
rtw_hal_enable_tx_report(adapter);
|
|
#endif
|
|
|
|
if ((pwrctl->wowlan_wake_reason != RX_DISASSOC) &&
|
|
(pwrctl->wowlan_wake_reason != RX_DEAUTH) &&
|
|
(pwrctl->wowlan_wake_reason != FW_DECISION_DISCONNECT) &&
|
|
(pwrctl->wowlan_wake_reason != NO_WAKE_RX_PAIRWISEKEY) &&
|
|
(pwrctl->wowlan_wake_reason != NO_WAKE_RX_GTK) &&
|
|
(pwrctl->wowlan_wake_reason != NO_WAKE_RX_DISASSOC) &&
|
|
(pwrctl->wowlan_wake_reason != NO_WAKE_RX_DEAUTH) &&
|
|
(pwrctl->wowlan_wake_reason != NO_WAKE_RX_EAPREQ_IDENTIFY)) {
|
|
rtw_hal_get_aoac_rpt(adapter);
|
|
rtw_hal_update_sw_security_info(adapter);
|
|
}
|
|
|
|
if (res == _FALSE) {
|
|
RTW_INFO("[Error]%s: disable WOW cmd fail\n!!", __func__);
|
|
rtw_hal_force_enable_rxdma(adapter);
|
|
}
|
|
|
|
rtw_hal_gate_bb(adapter, _TRUE);
|
|
|
|
res = rtw_hal_pause_rx_dma(adapter);
|
|
if (res == _FAIL)
|
|
RTW_PRINT("[WARNING] pause RX DMA fail\n");
|
|
|
|
/* clean HW pattern match */
|
|
rtw_hal_dl_pattern(adapter, 0);
|
|
|
|
#ifndef CONFIG_WOW_PATTERN_HW_CAM
|
|
/* config RXFF boundary to original */
|
|
#ifndef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
rtw_hal_set_wow_rxff_boundary(adapter, _FALSE);
|
|
#endif /*CONFIG_WOW_PATTERN_IN_TXFIFO*/
|
|
#endif
|
|
rtw_hal_release_rx_dma(adapter);
|
|
|
|
rtw_hal_fw_dl(adapter, _FALSE);
|
|
|
|
#ifdef CONFIG_GPIO_WAKEUP
|
|
|
|
#ifdef CONFIG_RTW_ONE_PIN_GPIO
|
|
rtw_hal_set_input_gpio(adapter, pwrctl->wowlan_gpio_index);
|
|
#else
|
|
#ifdef CONFIG_WAKEUP_GPIO_INPUT_MODE
|
|
if (pwrctl->is_high_active == 0)
|
|
rtw_hal_set_input_gpio(adapter, pwrctl->wowlan_gpio_index);
|
|
else
|
|
rtw_hal_set_output_gpio(adapter, pwrctl->wowlan_gpio_index,
|
|
GPIO_OUTPUT_LOW);
|
|
#else
|
|
rtw_hal_set_output_gpio(adapter, pwrctl->wowlan_gpio_index
|
|
, pwrctl->wowlan_gpio_output_state);
|
|
RTW_INFO("%s: set GPIO_%d to OUTPUT %s state in wow resume and %s_ACTIVE.\n",
|
|
__func__, pwrctl->wowlan_gpio_index,
|
|
pwrctl->wowlan_gpio_output_state ? "HIGH" : "LOW",
|
|
pwrctl->is_high_active ? "HIGI" : "LOW");
|
|
#endif /* CONFIG_WAKEUP_GPIO_INPUT_MODE */
|
|
#endif /* CONFIG_RTW_ONE_PIN_GPIO */
|
|
#endif /* CONFIG_GPIO_WAKEUP */
|
|
if ((pwrctl->wowlan_wake_reason != FW_DECISION_DISCONNECT) &&
|
|
(pwrctl->wowlan_wake_reason != RX_PAIRWISEKEY) &&
|
|
(pwrctl->wowlan_wake_reason != RX_DISASSOC) &&
|
|
(pwrctl->wowlan_wake_reason != RX_DEAUTH)) {
|
|
|
|
media_status_rpt = RT_MEDIA_CONNECT;
|
|
rtw_hal_set_hwreg(adapter, HW_VAR_H2C_FW_JOINBSSRPT,
|
|
(u8 *)&media_status_rpt);
|
|
|
|
if (psta != NULL) {
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
adapter_to_dvobj(adapter)->dft.port_id = 0xFF;
|
|
adapter_to_dvobj(adapter)->dft.mac_id = 0xFF;
|
|
rtw_hal_set_default_port_id_cmd(adapter, psta->cmn.mac_id);
|
|
#endif
|
|
rtw_sta_media_status_rpt(adapter, psta, 1);
|
|
}
|
|
}
|
|
|
|
if (psta != NULL) {
|
|
RTW_PRINT("rtw_set_bit RTW_RECV_REORDER_WOW\n");
|
|
for (i = 0; i < TID_NUM; i++) {
|
|
preorder_ctrl = &psta->recvreorder_ctrl[i];
|
|
rtw_set_bit(RTW_RECV_REORDER_WOW,
|
|
&preorder_ctrl->rec_abba_rsp_ack);
|
|
}
|
|
}
|
|
|
|
rtw_hal_gate_bb(adapter, _FALSE);
|
|
}
|
|
#if defined(CONFIG_WOW_PATTERN_IN_TXFIFO)
|
|
static void rtw_hal_construct_pattern_info(
|
|
PADAPTER padapter,
|
|
u8 *pframe,
|
|
u32 *pLength
|
|
)
|
|
{
|
|
|
|
u32 pattern_info_len = 0;
|
|
int i = 0, total = 0, index;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
|
|
struct rtl_wow_pattern wow_pattern;
|
|
u32 page_sz = 0;
|
|
|
|
total = pwrpriv->wowlan_pattern_idx;
|
|
|
|
if (total > MAX_WKFM_CAM_NUM)
|
|
total = MAX_WKFM_CAM_NUM;
|
|
|
|
/* Generate default pattern */
|
|
rtw_set_default_pattern(padapter);
|
|
|
|
/* Convert pattern to WKFM_CAM pattern */
|
|
for (i = 0 ; i < total ; i++) {
|
|
if (_SUCCESS == rtw_hal_wow_pattern_generate(padapter, i, &wow_pattern)) {
|
|
|
|
index = i;
|
|
if (!pwrpriv->bInSuspend)
|
|
index += 2;
|
|
#ifdef CONFIG_WOW_PATTERN_IN_TXFIFO_DBG
|
|
rtw_dump_wow_pattern(RTW_DBGDUMP, &wow_pattern, i);
|
|
#endif
|
|
|
|
if (rtw_write_to_frame_mask_buf(padapter, index, &wow_pattern,
|
|
pframe, &pattern_info_len) == _FALSE)
|
|
RTW_INFO("%s: ERROR!! idx: %d write_to_frame_mask_cam fail\n", __func__, i);
|
|
}
|
|
}
|
|
*pLength = pattern_info_len;
|
|
|
|
|
|
}
|
|
#endif /* CONFIG_WOW_PATTERN_IN_TXFIFO */
|
|
void rtw_hal_set_wow_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 index,
|
|
u8 tx_desc, u32 page_size, u8 *page_num, u32 *total_pkt_len,
|
|
RSVDPAGE_LOC *rsvd_page_loc)
|
|
{
|
|
struct security_priv *psecuritypriv = &adapter->securitypriv;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct mlme_ext_priv *pmlmeext;
|
|
struct mlme_ext_info *pmlmeinfo;
|
|
u32 ARPLength = 0, GTKLength = 0, PNOLength = 0, ScanInfoLength = 0;
|
|
u32 ProbeReqLength = 0, ns_len = 0, rc_len = 0;
|
|
u8 CurtPktPageNum = 0;
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
u32 keep_alive_len=0;
|
|
int i;
|
|
#endif /*CONFIG_WOW_KEEP_ALIVE_PATTERN */
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
u16 tmp_idx = 0;
|
|
u32 buf_len = 0;
|
|
#endif
|
|
|
|
#ifdef CONFIG_GTK_OL
|
|
struct sta_priv *pstapriv = &adapter->stapriv;
|
|
struct sta_info *psta;
|
|
struct security_priv *psecpriv = &adapter->securitypriv;
|
|
u8 kek[RTW_KEK_LEN];
|
|
u8 kck[RTW_KCK_LEN];
|
|
#endif /* CONFIG_GTK_OL */
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
int pno_index;
|
|
u8 ssid_num;
|
|
#endif /* CONFIG_PNO_SUPPORT */
|
|
#ifdef CONFIG_WOW_PATTERN_IN_TXFIFO
|
|
u32 PatternLen = 0;
|
|
u32 cam_start_offset = 0;
|
|
u32 reg_cam_start_offset_val = 0;
|
|
#endif /* CONFIG_WOW_PATTERN_IN_TXFIFO */
|
|
|
|
pmlmeext = &adapter->mlmeextpriv;
|
|
pmlmeinfo = &pmlmeext->mlmext_info;
|
|
|
|
if (pwrctl->wowlan_pno_enable == _FALSE) {
|
|
/* ARP RSP * 1 page */
|
|
|
|
rsvd_page_loc->LocArpRsp = *page_num;
|
|
|
|
RTW_INFO("LocArpRsp: %d\n", rsvd_page_loc->LocArpRsp);
|
|
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
if ((0 != pwrctl->wowlan_war_offload_ipv4.ip_addr[0]) &&
|
|
(_FALSE == _rtw_memcmp(&pwrctl->wowlan_war_offload_ipv4.ip_addr[0], pmlmeinfo->ip_addr, 4))) {
|
|
_rtw_memcpy(pmlmeinfo->ip_addr, &pwrctl->wowlan_war_offload_ipv4.ip_addr[0], 4);
|
|
RTW_INFO("Update IP(%d.%d.%d.%d) to arp rsvd page\n",
|
|
pmlmeinfo->ip_addr[0], pmlmeinfo->ip_addr[1],
|
|
pmlmeinfo->ip_addr[2], pmlmeinfo->ip_addr[3]);
|
|
}
|
|
#endif /* CONFIG_WAR_OFFLOAD */
|
|
|
|
|
|
rtw_hal_construct_ARPRsp(adapter, &pframe[index],
|
|
&ARPLength, pmlmeinfo->ip_addr);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&pframe[index - tx_desc],
|
|
ARPLength, _FALSE, _FALSE, _TRUE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + ARPLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-ARPRsp", CurtPktPageNum, *page_num, 0);
|
|
#ifdef CONFIG_WOW_KEEP_ALIVE_PATTERN
|
|
/* Keep Alive * ? page*/
|
|
if(pwrctl->keep_alive_pattern_len){
|
|
rsvd_page_loc->LocKeepAlive = *page_num;
|
|
pwrctl->keep_alive_pattern_loc = rsvd_page_loc->LocKeepAlive;
|
|
RTW_INFO("pwrctl->keep_alive_pattern_loc: %d\n", pwrctl->keep_alive_pattern_loc);
|
|
rtw_hal_construct_keepalive(adapter,&pframe[index],&keep_alive_len);
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&pframe[index - tx_desc],
|
|
keep_alive_len, _FALSE, _FALSE, _TRUE);
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + keep_alive_len, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-KeepAlive:", CurtPktPageNum, *page_num, 0);
|
|
}
|
|
#endif /* CONFIG_WOW_KEEP_ALIVE_PATTERN*/
|
|
|
|
#ifdef CONFIG_IPV6
|
|
/* 2 NS offload and NDP Info*/
|
|
if (pwrctl->wowlan_ns_offload_en == _TRUE) {
|
|
rsvd_page_loc->LocNbrAdv = *page_num;
|
|
RTW_INFO("LocNbrAdv: %d\n", rsvd_page_loc->LocNbrAdv);
|
|
rtw_hal_construct_na_message(adapter,
|
|
&pframe[index], &ns_len);
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&pframe[index - tx_desc],
|
|
ns_len, _FALSE,
|
|
_FALSE, _TRUE);
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + ns_len,
|
|
page_size);
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-NbrAdv", CurtPktPageNum, *page_num, 0);
|
|
|
|
rsvd_page_loc->LocNDPInfo = *page_num;
|
|
RTW_INFO("LocNDPInfo: %d\n",
|
|
rsvd_page_loc->LocNDPInfo);
|
|
|
|
rtw_hal_construct_ndp_info(adapter,
|
|
&pframe[index - tx_desc],
|
|
&ns_len);
|
|
CurtPktPageNum =
|
|
(u8)PageNum(tx_desc + ns_len, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-NDPInfo", CurtPktPageNum, *page_num, 0);
|
|
|
|
}
|
|
#endif /*CONFIG_IPV6*/
|
|
/* 3 Remote Control Info. * 1 page */
|
|
rsvd_page_loc->LocRemoteCtrlInfo = *page_num;
|
|
RTW_INFO("LocRemoteCtrlInfo: %d\n", rsvd_page_loc->LocRemoteCtrlInfo);
|
|
rtw_hal_construct_remote_control_info(adapter,
|
|
&pframe[index - tx_desc],
|
|
&rc_len);
|
|
CurtPktPageNum = (u8)PageNum(rc_len, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
*total_pkt_len = index + rc_len;
|
|
RSVD_PAGE_CFG("WOW-RCI", CurtPktPageNum, *page_num, *total_pkt_len);
|
|
#ifdef CONFIG_GTK_OL
|
|
index += (CurtPktPageNum * page_size);
|
|
|
|
/* if the ap staion info. exists, get the kek, kck from staion info. */
|
|
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
|
|
if (psta == NULL) {
|
|
_rtw_memset(kek, 0, RTW_KEK_LEN);
|
|
_rtw_memset(kck, 0, RTW_KCK_LEN);
|
|
RTW_INFO("%s, KEK, KCK download rsvd page all zero\n",
|
|
__func__);
|
|
} else {
|
|
_rtw_memcpy(kek, psta->kek, RTW_KEK_LEN);
|
|
_rtw_memcpy(kck, psta->kck, RTW_KCK_LEN);
|
|
}
|
|
|
|
/* 3 KEK, KCK */
|
|
rsvd_page_loc->LocGTKInfo = *page_num;
|
|
RTW_INFO("LocGTKInfo: %d\n", rsvd_page_loc->LocGTKInfo);
|
|
|
|
if (IS_HARDWARE_TYPE_8188E(adapter) || IS_HARDWARE_TYPE_8812(adapter)) {
|
|
struct security_priv *psecpriv = NULL;
|
|
|
|
psecpriv = &adapter->securitypriv;
|
|
_rtw_memcpy(pframe + index - tx_desc,
|
|
&psecpriv->dot11PrivacyAlgrthm, 1);
|
|
_rtw_memcpy(pframe + index - tx_desc + 1,
|
|
&psecpriv->dot118021XGrpPrivacy, 1);
|
|
_rtw_memcpy(pframe + index - tx_desc + 2,
|
|
kck, RTW_KCK_LEN);
|
|
_rtw_memcpy(pframe + index - tx_desc + 2 + RTW_KCK_LEN,
|
|
kek, RTW_KEK_LEN);
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + 2 + RTW_KCK_LEN + RTW_KEK_LEN, page_size);
|
|
} else {
|
|
|
|
_rtw_memcpy(pframe + index - tx_desc, kck, RTW_KCK_LEN);
|
|
_rtw_memcpy(pframe + index - tx_desc + RTW_KCK_LEN,
|
|
kek, RTW_KEK_LEN);
|
|
GTKLength = tx_desc + RTW_KCK_LEN + RTW_KEK_LEN;
|
|
|
|
if (psta != NULL &&
|
|
psecuritypriv->dot118021XGrpPrivacy == _TKIP_) {
|
|
_rtw_memcpy(pframe + index - tx_desc + 56,
|
|
&psta->dot11tkiptxmickey, RTW_TKIP_MIC_LEN);
|
|
GTKLength += RTW_TKIP_MIC_LEN;
|
|
}
|
|
CurtPktPageNum = (u8)PageNum(GTKLength, page_size);
|
|
}
|
|
#if 0
|
|
{
|
|
int i;
|
|
printk("\ntoFW KCK: ");
|
|
for (i = 0; i < 16; i++)
|
|
printk(" %02x ", kck[i]);
|
|
printk("\ntoFW KEK: ");
|
|
for (i = 0; i < 16; i++)
|
|
printk(" %02x ", kek[i]);
|
|
printk("\n");
|
|
}
|
|
|
|
RTW_INFO("%s(): HW_VAR_SET_TX_CMD: KEK KCK %p %d\n",
|
|
__FUNCTION__, &pframe[index - tx_desc],
|
|
(tx_desc + RTW_KCK_LEN + RTW_KEK_LEN));
|
|
#endif
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-GTKInfo", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* 3 GTK Response */
|
|
rsvd_page_loc->LocGTKRsp = *page_num;
|
|
RTW_INFO("LocGTKRsp: %d\n", rsvd_page_loc->LocGTKRsp);
|
|
rtw_hal_construct_GTKRsp(adapter, &pframe[index], >KLength);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
GTKLength, _FALSE, _FALSE, _TRUE);
|
|
#if 0
|
|
{
|
|
int gj;
|
|
printk("123GTK pkt=>\n");
|
|
for (gj = 0; gj < GTKLength + tx_desc; gj++) {
|
|
printk(" %02x ", pframe[index - tx_desc + gj]);
|
|
if ((gj + 1) % 16 == 0)
|
|
printk("\n");
|
|
}
|
|
printk(" <=end\n");
|
|
}
|
|
|
|
RTW_INFO("%s(): HW_VAR_SET_TX_CMD: GTK RSP %p %d\n",
|
|
__FUNCTION__, &pframe[index - tx_desc],
|
|
(tx_desc + GTKLength));
|
|
#endif
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + GTKLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-GTKRsp", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* below page is empty for GTK extension memory */
|
|
/* 3(11) GTK EXT MEM */
|
|
rsvd_page_loc->LocGTKEXTMEM = *page_num;
|
|
RTW_INFO("LocGTKEXTMEM: %d\n", rsvd_page_loc->LocGTKEXTMEM);
|
|
CurtPktPageNum = 2;
|
|
|
|
if (page_size >= 256)
|
|
CurtPktPageNum = 1;
|
|
|
|
*page_num += CurtPktPageNum;
|
|
/* extension memory for FW */
|
|
*total_pkt_len = index + (page_size * CurtPktPageNum);
|
|
RSVD_PAGE_CFG("WOW-GTKEXTMEM", CurtPktPageNum, *page_num, *total_pkt_len);
|
|
#endif /* CONFIG_GTK_OL */
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
if(_TRUE == pwrctl->wowlan_war_offload_mode) {
|
|
u8 zero_ary[16] = {0x00};
|
|
u8 war_tmp_cnt = 0;
|
|
|
|
/* Reserve 2 page for Ip parameters */
|
|
/* First page
|
|
| Byte 15 -----------Byte 0 |
|
|
| IP-4 | IP-3 | IP-2 | IP-1 |
|
|
| location of each feature | mac addr |
|
|
| NetBIOS name |
|
|
| location of each feature |
|
|
Second page
|
|
| IPv6 - 1 |
|
|
| IPv6 - 2 |
|
|
| IPv6 - 3 |
|
|
| IPv6 - 4 |
|
|
| IPv6 - 5 |
|
|
| IPv6 - 6 |
|
|
| IPv6 - 7 |
|
|
| IPv6 - 8 |
|
|
*/
|
|
|
|
/* location of each feature : Byte 22 ~ Byte 31
|
|
* Byte22 : location of SNMP RX
|
|
* Byte23 : location of SNMP V4
|
|
* Byte24 : location of SNMP V6
|
|
* Byte25 : location of MDNS Param
|
|
* Byte26 : location of MDNS V4
|
|
* Byte27 : location of MDNS V6
|
|
* Byte28 : location of SSDP pattern
|
|
* Byte29 : location of WSD pattern
|
|
* Byte30 : location of SLP pattern
|
|
* Byte31 : location of LLMNR
|
|
*/
|
|
|
|
/* ipv4 : 4 */
|
|
if (0 == pwrctl->wowlan_war_offload_ipv4.ip_addr[0])
|
|
_rtw_memcpy(&pwrctl->wowlan_war_offload_ipv4.ip_addr[0], pmlmeinfo->ip_addr, 4);
|
|
for(war_tmp_cnt=0; war_tmp_cnt<4 ;war_tmp_cnt++)
|
|
_rtw_memcpy(pframe + index - tx_desc + (war_tmp_cnt*4), &pwrctl->wowlan_war_offload_ipv4.ip_addr[war_tmp_cnt], 4);
|
|
|
|
if (is_zero_mac_addr(pwrctl->wowlan_war_offload_mac)) {
|
|
_rtw_memcpy(pwrctl->wowlan_war_offload_mac, adapter_mac_addr(adapter), 6);
|
|
}
|
|
_rtw_memcpy(pframe + index + 16 - tx_desc, pwrctl->wowlan_war_offload_mac, 6);
|
|
|
|
|
|
/* ipv6 : 8 */
|
|
if (_TRUE == _rtw_memcmp(pwrctl->wowlan_war_offload_ipv6.ipv6_addr[0], zero_ary, RTW_IPv6_ADDR_LEN))
|
|
_rtw_memcpy(pwrctl->wowlan_war_offload_ipv6.ipv6_addr[0], pmlmeinfo->ip6_addr, RTW_IPv6_ADDR_LEN);
|
|
|
|
for(war_tmp_cnt=0; war_tmp_cnt<8 ;war_tmp_cnt++)
|
|
_rtw_memcpy(pframe + index + page_size - tx_desc + (war_tmp_cnt*16), pwrctl->wowlan_war_offload_ipv6.ipv6_addr[war_tmp_cnt], 16);
|
|
|
|
rsvd_page_loc->LocIpParm = *page_num;
|
|
|
|
tmp_idx = index;
|
|
CurtPktPageNum = 2;
|
|
*page_num += CurtPktPageNum;
|
|
*total_pkt_len = index + (page_size * CurtPktPageNum);
|
|
index += (CurtPktPageNum * page_size);
|
|
|
|
|
|
#if defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6)
|
|
if ( (WAR_MDNS_V4_RSP_EN & pwrctl->wowlan_war_offload_ctrl) ||
|
|
(WAR_MDNS_V6_RSP_EN & pwrctl->wowlan_war_offload_ctrl) ||
|
|
(WAR_MDNS_V4_WAKEUP_EN & pwrctl->wowlan_war_offload_ctrl) ||
|
|
(WAR_MDNS_V6_WAKEUP_EN & pwrctl->wowlan_war_offload_ctrl)) {
|
|
|
|
struct war_mdns_service_info *psinfo = pwrctl->wowlan_war_offload_mdns_service;
|
|
u8 txt_in_ptr[31]={ 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x00, 0x13, 0x09, 0x74, 0x78, 0x74, 0x76, 0x65, 0x72, 0x73,
|
|
0x3d, 0x31, 0x08, 0x71, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x3d, 0x31};
|
|
u16 mdns_offset = index - tx_desc;
|
|
u8 i = 0;
|
|
|
|
rsvd_page_loc->LocMdnsPara = *page_num;
|
|
RTW_INFO("LocMdnsPara : %d\n", rsvd_page_loc->LocMdnsPara);
|
|
|
|
/* 1. service info */
|
|
pframe[mdns_offset] = 0x01; // TLV(T)
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &pwrctl->wowlan_war_offload_mdns_service_info_num, 1);
|
|
mdns_offset += 1;
|
|
|
|
for(i=0; i<pwrctl->wowlan_war_offload_mdns_service_info_num ;i++)
|
|
{
|
|
u16 srv_rsp_len = 0;
|
|
|
|
// 1.1 : construct service name string
|
|
// : length of total service name string (service+transport+domain)
|
|
pframe[mdns_offset] = psinfo[i].service_len + psinfo[i].transport_len + psinfo[i].domain_len + 4;
|
|
mdns_offset += 1;
|
|
|
|
// : service name
|
|
pframe[mdns_offset] = psinfo[i].service_len;
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &psinfo[i].service, psinfo[i].service_len);
|
|
mdns_offset += psinfo[i].service_len;
|
|
|
|
// : transport name
|
|
pframe[mdns_offset] = psinfo[i].transport_len;
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &psinfo[i].transport, psinfo[i].transport_len);
|
|
mdns_offset += psinfo[i].transport_len;
|
|
|
|
// : domain name
|
|
pframe[mdns_offset] = psinfo[i].domain_len;
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &psinfo[i].domain, psinfo[i].domain_len);
|
|
mdns_offset += psinfo[i].domain_len;
|
|
|
|
// : delimiter
|
|
mdns_offset += 1;
|
|
|
|
// 1.2 : construct type srv rsp
|
|
pframe[mdns_offset] = psinfo[i].target_len + 19; // length
|
|
pframe[mdns_offset + 2] = 0x21; // rsp type (srv)
|
|
pframe[mdns_offset + 4] = 0x01; // cache flush + class
|
|
_rtw_memcpy(pframe + mdns_offset + 5, &psinfo[i].ttl, 4); // ttl
|
|
pframe[mdns_offset + 5] = (u8) ( (psinfo[i].ttl & 0xff000000) >> 24); // ttl - byte0
|
|
pframe[mdns_offset + 6] = (u8) ( (psinfo[i].ttl & 0x00ff0000) >> 16); // ttl - byte1
|
|
pframe[mdns_offset + 7] = (u8) ( (psinfo[i].ttl & 0x0000ff00) >> 8 ); // ttl - byte2
|
|
pframe[mdns_offset + 8] = (u8) (psinfo[i].ttl & 0x000000ff); // ttl - byte3
|
|
pframe[mdns_offset + 10] = psinfo[i].target_len + 9; // data length
|
|
_rtw_memcpy(pframe + mdns_offset + 15, &psinfo[i].port, 2); // port
|
|
_rtw_memcpy(pframe + mdns_offset + 17, &psinfo[i].target_len, 1); // target len
|
|
_rtw_memcpy(pframe + mdns_offset + 18, &psinfo[i].target, psinfo[i].target_len); // target
|
|
pframe[mdns_offset + 18 + psinfo[i].target_len] = 0xc0; // message compresion, offset will be filled by fw.
|
|
mdns_offset += (1 + psinfo[i].target_len + 19);
|
|
|
|
// 1.3 : set the idx of txt rsp
|
|
pframe[mdns_offset] = psinfo[i].txt_rsp_idx;
|
|
mdns_offset += 1;
|
|
}
|
|
|
|
/* 2. machine name */
|
|
pframe[mdns_offset] = 0x02; // TLV(T)
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &pwrctl->wowlan_war_offload_mdns_mnane_num, 1); // NUM
|
|
mdns_offset += 1;
|
|
|
|
for(i=0; i<pwrctl->wowlan_war_offload_mdns_mnane_num; i++)
|
|
{
|
|
pframe[mdns_offset] = pwrctl->wowlan_war_offload_mdns_mnane[i].name_len;
|
|
_rtw_memcpy(pframe + mdns_offset + 1, pwrctl->wowlan_war_offload_mdns_mnane[i].name,
|
|
pwrctl->wowlan_war_offload_mdns_mnane[i].name_len); // machine name
|
|
mdns_offset += (1+pwrctl->wowlan_war_offload_mdns_mnane[i].name_len);
|
|
}
|
|
|
|
/* 3. A rsp */
|
|
pframe[mdns_offset] = 0x03; // TLV(T)
|
|
pframe[mdns_offset + 1] = 14; // TLV(L)
|
|
pframe[mdns_offset + 3] = 0x01; // rsp type (a)
|
|
pframe[mdns_offset + 5] = 0x01; // cache flush + class
|
|
pframe[mdns_offset + 9] = 0xf0; // ttl (240 sec)
|
|
pframe[mdns_offset + 11] = 4; // length of ipv4 addr.
|
|
_rtw_memcpy(pframe + mdns_offset + 12, &pwrctl->wowlan_war_offload_ipv4.ip_addr[0], 4);
|
|
mdns_offset += (2 + 14);
|
|
|
|
/* 4. AAAA rsp */
|
|
pframe[mdns_offset] = 0x04; // TLV(T)
|
|
pframe[mdns_offset + 1] = 26; // TLV(L)
|
|
pframe[mdns_offset + 3] = 0x1c; // rsp type (aaaa)
|
|
pframe[mdns_offset + 5] = 0x01; // cache flush + class
|
|
pframe[mdns_offset + 9] = 0xf0; // ttl (240 sec)
|
|
pframe[mdns_offset + 11] = 16; // length of ipv6 addr.
|
|
_rtw_memcpy(pframe + mdns_offset + 12, &pwrctl->wowlan_war_offload_ipv6.ipv6_addr[0], 16);
|
|
mdns_offset += (2 + 26);
|
|
|
|
/* 5. PTR rsp */
|
|
pframe[mdns_offset] = 0x05; // TLV(T)
|
|
pframe[mdns_offset + 1] = 13 + pwrctl->wowlan_war_offload_mdns_domain_name_len; // TLV(L)
|
|
pframe[mdns_offset + 3] = 0x0c; // rsp type (aaaa)
|
|
pframe[mdns_offset + 5] = 0x01; // cache flush + class
|
|
pframe[mdns_offset + 8] = 0x1c; // ttl
|
|
pframe[mdns_offset + 9] = 0x20; // ttl (7200 sec)
|
|
pframe[mdns_offset + 11] = 3 + pwrctl->wowlan_war_offload_mdns_domain_name_len; // data length
|
|
pframe[mdns_offset + 12] = pwrctl->wowlan_war_offload_mdns_domain_name_len; // domain name length
|
|
_rtw_memcpy(pframe + mdns_offset + 13, &pwrctl->wowlan_war_offload_mdns_domain_name,
|
|
pwrctl->wowlan_war_offload_mdns_domain_name_len);
|
|
pframe[mdns_offset + 13 + pwrctl->wowlan_war_offload_mdns_domain_name_len] = 0xc0; // message compression
|
|
mdns_offset += (2 + 13 + pwrctl->wowlan_war_offload_mdns_domain_name_len);
|
|
|
|
/* 6. TXT in PTR rsp */
|
|
pframe[mdns_offset] = 0x06; // TLV(T)
|
|
pframe[mdns_offset + 1] = 31; // TLV(L)
|
|
_rtw_memcpy(pframe + mdns_offset + 2, &txt_in_ptr, 31);
|
|
mdns_offset += (2 + 31);
|
|
|
|
/* 7. TXT rsp */
|
|
pframe[mdns_offset] = 0x07; // TLV(T)
|
|
mdns_offset += 1;
|
|
_rtw_memcpy(pframe + mdns_offset, &pwrctl->wowlan_war_offload_mdns_txt_rsp_num, 1); // NUM
|
|
mdns_offset += 1;
|
|
|
|
for(i=0; i<pwrctl->wowlan_war_offload_mdns_txt_rsp_num; i++)
|
|
{
|
|
u16 txt_rsp_len = pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt_len;
|
|
|
|
if(pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt_len==0)
|
|
{
|
|
_rtw_memcpy(pframe + mdns_offset, &txt_rsp_len, 2);
|
|
mdns_offset += ( 2 + txt_rsp_len );
|
|
continue;
|
|
}
|
|
|
|
txt_rsp_len += 10;
|
|
_rtw_memcpy(pframe + mdns_offset, &txt_rsp_len, 2);
|
|
pframe[mdns_offset + 3] = 0x10; // rsp type (txt)
|
|
pframe[mdns_offset + 5] = 0x01; // cache flush + class
|
|
pframe[mdns_offset + 8] = 0x1c; // ttl
|
|
pframe[mdns_offset + 9] = 0x20; // ttl (7200 sec)
|
|
pframe[mdns_offset + 10] = (u8) ((pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt_len & 0xff00) >> 8);
|
|
pframe[mdns_offset + 11] = (u8) (pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt_len & 0x00ff);
|
|
_rtw_memcpy(pframe + mdns_offset + 12, &pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt,
|
|
pwrctl->wowlan_war_offload_mdns_txt_rsp[i].txt_len);
|
|
mdns_offset += ( 2 + txt_rsp_len );
|
|
}
|
|
|
|
CurtPktPageNum = (u8)PageNum(mdns_offset - index, page_size)+1;
|
|
*page_num += CurtPktPageNum;
|
|
*total_pkt_len = index + (page_size * CurtPktPageNum);
|
|
index += (CurtPktPageNum * page_size);
|
|
}
|
|
#endif /* defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6) */
|
|
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V4
|
|
if (WAR_MDNS_V4_RSP_EN & pwrctl->wowlan_war_offload_ctrl) {
|
|
rsvd_page_loc->LocMdnsv4 = *page_num;
|
|
RTW_INFO("LocMdnsv4: %d\n", rsvd_page_loc->LocMdnsv4);
|
|
|
|
rtw_hal_construct_mdns_rsp_v4(adapter, &pframe[index], &buf_len, pmlmeinfo->ip_addr);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], buf_len, _FALSE, _FALSE, _TRUE);
|
|
CurtPktPageNum = 16;
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
}
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V4 */
|
|
|
|
#ifdef CONFIG_OFFLOAD_MDNS_V6
|
|
if (WAR_MDNS_V6_RSP_EN & pwrctl->wowlan_war_offload_ctrl) {
|
|
rsvd_page_loc->LocMdnsv6 = *page_num;
|
|
RTW_INFO("LocMdnsv6: %d\n", rsvd_page_loc->LocMdnsv6);
|
|
|
|
rtw_hal_construct_mdns_rsp_v6(adapter, &pframe[index], &buf_len, pmlmeinfo->ip_addr);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc], buf_len, _FALSE, _FALSE, _TRUE);
|
|
CurtPktPageNum = 16;
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
}
|
|
#endif /* CONFIG_OFFLOAD_MDNS_V6 */
|
|
|
|
#if defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6)
|
|
*(pframe+tmp_idx+25-tx_desc) = rsvd_page_loc->LocMdnsPara;
|
|
*(pframe+tmp_idx+26-tx_desc) = rsvd_page_loc->LocMdnsv4;
|
|
*(pframe+tmp_idx+27-tx_desc) = rsvd_page_loc->LocMdnsv6;
|
|
#endif /* defined(CONFIG_OFFLOAD_MDNS_V4) || defined(CONFIG_OFFLOAD_MDNS_V6) */
|
|
|
|
}
|
|
//rtw_dump_rsvd_page(RTW_DBGDUMP, adapter, rsvd_page_loc->LocIpParm, 46);
|
|
#endif /* CONFIG_WAR_OFFLOAD */
|
|
|
|
#if defined(CONFIG_WOW_PATTERN_IN_TXFIFO)
|
|
/* pattern_rsvd_page_loc will be used by rtw_read_from_frame_mask() */
|
|
pwrctl->pattern_rsvd_page_loc = *page_num;
|
|
RTW_INFO("LocPatternInfo: %d\n", pwrctl->pattern_rsvd_page_loc);
|
|
rtw_hal_construct_pattern_info(adapter,
|
|
&pframe[index - tx_desc],
|
|
&PatternLen);
|
|
|
|
/* Set cam_start_offset to REG_TXBUF_WKCAM_OFFSET
|
|
* Cam address(TxBufer pointer) access 8 bytes at a time
|
|
*/
|
|
|
|
// Get rsvd page start page number + pattern located page
|
|
cam_start_offset = rtw_read8(adapter, REG_BCNQ_BDNY) + *page_num;
|
|
cam_start_offset *= page_size;
|
|
cam_start_offset /= 8;
|
|
|
|
reg_cam_start_offset_val = rtw_read32(adapter, REG_TXBUF_WKCAM_OFFSET);
|
|
reg_cam_start_offset_val &= ~(WKCAM_OFFSET_BIT_MASK << WKCAM_OFFSET_BIT_MASK_OFFSET);
|
|
reg_cam_start_offset_val |= (cam_start_offset << WKCAM_OFFSET_BIT_MASK_OFFSET);
|
|
rtw_write32(adapter, REG_TXBUF_WKCAM_OFFSET, reg_cam_start_offset_val);
|
|
|
|
/* Set pattern number to REG_WKFMCAM_NUM */
|
|
rtw_write8(adapter, REG_WKFMCAM_NUM, PatternLen / WKFMCAM_SIZE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(PatternLen, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-PatternInfo", CurtPktPageNum, *page_num, index);
|
|
|
|
#endif /* CONFIG_WOW_PATTERN_IN_TXFIFO */
|
|
|
|
/*Reserve 1 page for AOAC report*/
|
|
rsvd_page_loc->LocAOACReport = *page_num;
|
|
RTW_INFO("LocAOACReport: %d\n", rsvd_page_loc->LocAOACReport);
|
|
*page_num += 1;
|
|
*total_pkt_len = index + (page_size * 1);
|
|
RSVD_PAGE_CFG("WOW-AOAC", 1, *page_num, *total_pkt_len);
|
|
|
|
|
|
} else {
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
if (pwrctl->wowlan_in_resume == _FALSE &&
|
|
pwrctl->pno_inited == _TRUE) {
|
|
#ifndef RTW_HALMAC
|
|
/* Broadcast Probe Request */
|
|
rsvd_page_loc->LocProbePacket = *page_num;
|
|
|
|
RTW_INFO("loc_probe_req: %d\n",
|
|
rsvd_page_loc->LocProbePacket);
|
|
|
|
rtw_hal_construct_ProbeReq(
|
|
adapter,
|
|
&pframe[index],
|
|
&ProbeReqLength,
|
|
NULL);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&pframe[index - tx_desc],
|
|
ProbeReqLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum =
|
|
(u8)PageNum(tx_desc + ProbeReqLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-ProbeReq", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* Scan Info Page */
|
|
rsvd_page_loc->LocScanInfo = *page_num;
|
|
RTW_INFO("LocScanInfo: %d\n", rsvd_page_loc->LocScanInfo);
|
|
rtw_hal_construct_scan_info(adapter,
|
|
&pframe[index - tx_desc],
|
|
&ScanInfoLength);
|
|
|
|
CurtPktPageNum = (u8)PageNum(ScanInfoLength, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-ScanInfo", CurtPktPageNum, *page_num, *total_pkt_len);
|
|
#endif
|
|
/* Hidden SSID Probe Request */
|
|
ssid_num = pwrctl->pnlo_info->hidden_ssid_num;
|
|
|
|
for (pno_index = 0 ; pno_index < ssid_num ; pno_index++) {
|
|
pwrctl->pnlo_info->loc_probe_req[pno_index] =
|
|
*page_num;
|
|
|
|
rtw_hal_construct_ProbeReq(
|
|
adapter,
|
|
&pframe[index],
|
|
&ProbeReqLength,
|
|
&pwrctl->pno_ssid_list->node[pno_index]);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&pframe[index - tx_desc],
|
|
ProbeReqLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum =
|
|
(u8)PageNum(tx_desc + ProbeReqLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-ProbeReq", CurtPktPageNum, *page_num, 0);
|
|
}
|
|
|
|
/* PNO INFO Page */
|
|
rsvd_page_loc->LocPNOInfo = *page_num;
|
|
RTW_INFO("LocPNOInfo: %d\n", rsvd_page_loc->LocPNOInfo);
|
|
rtw_hal_construct_PNO_info(adapter,
|
|
&pframe[index - tx_desc],
|
|
&PNOLength);
|
|
|
|
CurtPktPageNum = (u8)PageNum(PNOLength, page_size);
|
|
*page_num += CurtPktPageNum;
|
|
*total_pkt_len = index + PNOLength;
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-PNOInfo", CurtPktPageNum, *page_num, 0);
|
|
}
|
|
#endif /* CONFIG_PNO_SUPPORT */
|
|
}
|
|
}
|
|
#endif /*CONFIG_WOWLAN*/
|
|
|
|
#ifdef CONFIG_P2P_WOWLAN
|
|
void rtw_hal_set_p2p_wow_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 index,
|
|
u8 tx_desc, u32 page_size, u8 *page_num, u32 *total_pkt_len,
|
|
RSVDPAGE_LOC *rsvd_page_loc)
|
|
{
|
|
u32 P2PNegoRspLength = 0, P2PInviteRspLength = 0;
|
|
u32 P2PPDRspLength = 0, P2PProbeRspLength = 0, P2PBCNLength = 0;
|
|
u8 CurtPktPageNum = 0;
|
|
|
|
/* P2P Beacon */
|
|
rsvd_page_loc->LocP2PBeacon = *page_num;
|
|
rtw_hal_construct_P2PBeacon(adapter, &pframe[index], &P2PBCNLength);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
P2PBCNLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
#if 0
|
|
RTW_INFO("%s(): HW_VAR_SET_TX_CMD: PROBE RSP %p %d\n",
|
|
__FUNCTION__, &pframe[index - tx_desc], (P2PBCNLength + tx_desc));
|
|
#endif
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + P2PBCNLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-P2P-Beacon", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* P2P Probe rsp */
|
|
rsvd_page_loc->LocP2PProbeRsp = *page_num;
|
|
rtw_hal_construct_P2PProbeRsp(adapter, &pframe[index],
|
|
&P2PProbeRspLength);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
P2PProbeRspLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
/* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: PROBE RSP %p %d\n", */
|
|
/* __FUNCTION__, &pframe[index-tx_desc], (P2PProbeRspLength+tx_desc)); */
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + P2PProbeRspLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-P2P-ProbeRsp", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* P2P nego rsp */
|
|
rsvd_page_loc->LocNegoRsp = *page_num;
|
|
rtw_hal_construct_P2PNegoRsp(adapter, &pframe[index],
|
|
&P2PNegoRspLength);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
P2PNegoRspLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
/* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */
|
|
/* __FUNCTION__, &pframe[index-tx_desc], (NegoRspLength+tx_desc)); */
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + P2PNegoRspLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-P2P-NegoRsp", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* P2P invite rsp */
|
|
rsvd_page_loc->LocInviteRsp = *page_num;
|
|
rtw_hal_construct_P2PInviteRsp(adapter, &pframe[index],
|
|
&P2PInviteRspLength);
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
P2PInviteRspLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
/* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */
|
|
/* __FUNCTION__, &pframe[index-tx_desc], (InviteRspLength+tx_desc)); */
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + P2PInviteRspLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
RSVD_PAGE_CFG("WOW-P2P-InviteRsp", CurtPktPageNum, *page_num, 0);
|
|
|
|
/* P2P provision discovery rsp */
|
|
rsvd_page_loc->LocPDRsp = *page_num;
|
|
rtw_hal_construct_P2PProvisionDisRsp(adapter,
|
|
&pframe[index], &P2PPDRspLength);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter, &pframe[index - tx_desc],
|
|
P2PPDRspLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
/* RTW_INFO("%s(): HW_VAR_SET_TX_CMD: QOS NULL DATA %p %d\n", */
|
|
/* __FUNCTION__, &pframe[index-tx_desc], (PDRspLength+tx_desc)); */
|
|
|
|
CurtPktPageNum = (u8)PageNum(tx_desc + P2PPDRspLength, page_size);
|
|
|
|
*page_num += CurtPktPageNum;
|
|
|
|
*total_pkt_len = index + P2PPDRspLength;
|
|
RSVD_PAGE_CFG("WOW-P2P-PDR", CurtPktPageNum, *page_num, *total_pkt_len);
|
|
|
|
index += (CurtPktPageNum * page_size);
|
|
|
|
|
|
}
|
|
#endif /* CONFIG_P2P_WOWLAN */
|
|
|
|
#ifdef CONFIG_LPS_PG
|
|
#ifndef DBG_LPSPG_INFO_DUMP
|
|
#define DBG_LPSPG_INFO_DUMP 1
|
|
#endif
|
|
|
|
#include "hal_halmac.h"
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
static int rtw_lps_pg_set_dpk_info_rsvd_page(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct dm_struct *dm = adapter_to_phydm(adapter);
|
|
struct rsvd_page_cache_t *cache = &pwrpriv->lpspg_dpk_info;
|
|
u8 *info = NULL;
|
|
u32 info_len;
|
|
int ret = _FAIL;
|
|
|
|
/* get length */
|
|
halrf_dpk_info_rsvd_page(dm, NULL, &info_len);
|
|
if (!info_len) {
|
|
RTW_ERR("get %s length fail\n", cache->name);
|
|
goto exit;
|
|
}
|
|
|
|
/* allocate buf */
|
|
info = rtw_zmalloc(info_len);
|
|
if (!info) {
|
|
RTW_ERR("alloc %s buffer fail(len=%d)\n", cache->name, info_len);
|
|
goto exit;
|
|
}
|
|
|
|
/* get content */
|
|
halrf_dpk_info_rsvd_page(dm, info, NULL);
|
|
|
|
if (rsvd_page_cache_update_data(cache, info, info_len)) {
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
RTW_INFO_DUMP(cache->name, info, info_len);
|
|
#endif
|
|
|
|
ret = rtw_halmac_download_rsvd_page(dvobj, cache->loc, info, info_len);
|
|
ret = !ret ? _SUCCESS : _FAIL;
|
|
if (ret != _SUCCESS) {
|
|
RTW_ERR("download %s rsvd page to offset:%u fail\n", cache->name, cache->loc);
|
|
goto free_mem;
|
|
}
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 2)
|
|
RTW_INFO("get %s from rsvd page offset:%d\n", cache->name, cache->loc);
|
|
rtw_dump_rsvd_page(RTW_DBGDUMP, adapter, cache->loc, cache->page_num);
|
|
#endif
|
|
}
|
|
|
|
free_mem:
|
|
rtw_mfree(info, info_len);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
static int rtw_lps_pg_set_iqk_info_rsvd_page(_adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct dm_struct *dm = adapter_to_phydm(adapter);
|
|
struct rsvd_page_cache_t *cache = &pwrpriv->lpspg_iqk_info;
|
|
u8 *info = NULL;
|
|
u32 info_len = 0;
|
|
int ret = _FAIL;
|
|
|
|
if (hal_data->RegIQKFWOffload) {
|
|
rsvd_page_cache_free_data(cache);
|
|
ret = _SUCCESS;
|
|
goto exit;
|
|
}
|
|
|
|
/* get length */
|
|
halrf_iqk_info_rsvd_page(dm, NULL, &info_len);
|
|
if (!info_len) {
|
|
RTW_ERR("get %s length fail\n", cache->name);
|
|
goto exit;
|
|
}
|
|
|
|
/* allocate buf */
|
|
info = rtw_zmalloc(info_len);
|
|
if (!info) {
|
|
RTW_ERR("alloc %s buffer fail(len=%d)\n", cache->name, info_len);
|
|
goto exit;
|
|
}
|
|
|
|
/* get content */
|
|
halrf_iqk_info_rsvd_page(dm, info, NULL);
|
|
|
|
if (rsvd_page_cache_update_data(cache, info, info_len)) {
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
RTW_INFO_DUMP(cache->name, info, info_len);
|
|
#endif
|
|
|
|
ret = rtw_halmac_download_rsvd_page(dvobj, cache->loc, info, info_len);
|
|
ret = !ret ? _SUCCESS : _FAIL;
|
|
if (ret != _SUCCESS) {
|
|
RTW_ERR("download %s rsvd page to offset:%u fail\n", cache->name, cache->loc);
|
|
goto free_mem;
|
|
}
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 2)
|
|
RTW_INFO("get %s from rsvd page offset:%d\n", cache->name, cache->loc);
|
|
rtw_dump_rsvd_page(RTW_DBGDUMP, adapter, cache->loc, cache->page_num);
|
|
#endif
|
|
}
|
|
|
|
free_mem:
|
|
rtw_mfree(info, info_len);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_RTL8822C */
|
|
|
|
static void rtw_hal_build_lps_pg_info_rsvd_page(struct dvobj_priv *dvobj, _adapter *ld_sta_iface, u8 *buf, u32 *buf_size)
|
|
{
|
|
#define LPS_PG_INFO_RSVD_LEN 16
|
|
|
|
if (buf) {
|
|
_adapter *adapter = dvobj_get_primary_adapter(dvobj);
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct sta_info *psta;
|
|
#ifdef CONFIG_MBSSID_CAM
|
|
u8 cam_id = INVALID_CAM_ID;
|
|
#endif
|
|
u8 *psec_cam_id = buf + 8;
|
|
u8 sec_cam_num = 0;
|
|
u8 drv_rsvdpage_num = 0;
|
|
|
|
if (ld_sta_iface) {
|
|
psta = rtw_get_stainfo(&ld_sta_iface->stapriv, get_bssid(&ld_sta_iface->mlmepriv));
|
|
if (!psta) {
|
|
RTW_ERR("%s [ERROR] sta is NULL\n", __func__);
|
|
rtw_warn_on(1);
|
|
goto size_chk;
|
|
}
|
|
/*Byte 0 - used macid*/
|
|
LPSPG_RSVD_PAGE_SET_MACID(buf, psta->cmn.mac_id);
|
|
RTW_INFO("[LPSPG-INFO] mac_id:%d\n", psta->cmn.mac_id);
|
|
}
|
|
|
|
#ifdef CONFIG_MBSSID_CAM
|
|
/*Byte 1 - used BSSID CAM entry*/
|
|
cam_id = rtw_mbid_cam_search_by_ifaceid(adapter, adapter->iface_id);
|
|
if (cam_id != INVALID_CAM_ID)
|
|
LPSPG_RSVD_PAGE_SET_MBSSCAMID(buf, cam_id);
|
|
RTW_INFO("[LPSPG-INFO] mbss_cam_id:%d\n", cam_id);
|
|
#endif
|
|
|
|
#ifdef CONFIG_WOWLAN /*&& pattern match cam used*/
|
|
/*Btye 2 - Max used Pattern Match CAM entry*/
|
|
if (pwrpriv->wowlan_mode == _TRUE
|
|
&& ld_sta_iface && check_fwstate(&ld_sta_iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
|
|
LPSPG_RSVD_PAGE_SET_PMC_NUM(buf, pwrpriv->wowlan_pattern_idx);
|
|
RTW_INFO("[LPSPG-INFO] Max Pattern Match CAM entry :%d\n", pwrpriv->wowlan_pattern_idx);
|
|
}
|
|
#endif
|
|
#ifdef CONFIG_BEAMFORMING /*&& MU BF*/
|
|
/*Btye 3 - Max MU rate table Group ID*/
|
|
LPSPG_RSVD_PAGE_SET_MU_RAID_GID(buf, 0);
|
|
RTW_INFO("[LPSPG-INFO] Max MU rate table Group ID :%d\n", 0);
|
|
#endif
|
|
|
|
/*Btye 8 ~15 - used Security CAM entry */
|
|
sec_cam_num = rtw_get_sec_camid(adapter, 8, psec_cam_id);
|
|
|
|
/*Btye 4 - used Security CAM entry number*/
|
|
if (sec_cam_num < 8)
|
|
LPSPG_RSVD_PAGE_SET_SEC_CAM_NUM(buf, sec_cam_num);
|
|
RTW_INFO("[LPSPG-INFO] Security CAM entry number :%d\n", sec_cam_num);
|
|
|
|
/*Btye 5 - Txbuf used page number for fw offload*/
|
|
if (pwrpriv->wowlan_mode == _TRUE || pwrpriv->wowlan_ap_mode == _TRUE)
|
|
drv_rsvdpage_num = rtw_hal_get_txbuff_rsvd_page_num(adapter, _TRUE);
|
|
else
|
|
drv_rsvdpage_num = rtw_hal_get_txbuff_rsvd_page_num(adapter, _FALSE);
|
|
LPSPG_RSVD_PAGE_SET_DRV_RSVDPAGE_NUM(buf, drv_rsvdpage_num);
|
|
RTW_INFO("[LPSPG-INFO] DRV's rsvd page numbers :%d\n", drv_rsvdpage_num);
|
|
}
|
|
|
|
size_chk:
|
|
if (buf_size)
|
|
*buf_size = LPS_PG_INFO_RSVD_LEN;
|
|
}
|
|
|
|
static int rtw_hal_set_lps_pg_info_rsvd_page(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct rsvd_page_cache_t *cache = &pwrpriv->lpspg_info;
|
|
u8 *info = NULL;
|
|
u32 info_len = 0;
|
|
int ret = _FAIL;
|
|
|
|
/* get length */
|
|
rtw_hal_build_lps_pg_info_rsvd_page(dvobj, adapter, NULL, &info_len);
|
|
if (!info_len) {
|
|
RTW_ERR("get %s length fail\n", cache->name);
|
|
goto exit;
|
|
}
|
|
|
|
/* allocate buf */
|
|
info = rtw_zmalloc(info_len);
|
|
if (!info) {
|
|
RTW_ERR("alloc %s buffer fail(len=%d)\n", cache->name, info_len);
|
|
goto exit;
|
|
}
|
|
|
|
/* get content */
|
|
rtw_hal_build_lps_pg_info_rsvd_page(dvobj, adapter, info, NULL);
|
|
|
|
if (rsvd_page_cache_update_data(cache, info, info_len)) {
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
RTW_INFO_DUMP(cache->name, info, info_len);
|
|
#endif
|
|
|
|
ret = rtw_halmac_download_rsvd_page(dvobj, cache->loc, info, info_len);
|
|
ret = !ret ? _SUCCESS : _FAIL;
|
|
if (ret != _SUCCESS) {
|
|
RTW_ERR("download %s rsvd page to offset:%u fail\n", cache->name, cache->loc);
|
|
goto free_mem;
|
|
}
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 2)
|
|
RTW_INFO("get %s from rsvd page offset:%d\n", cache->name, cache->loc);
|
|
rtw_dump_rsvd_page(RTW_DBGDUMP, adapter, cache->loc, cache->page_num);
|
|
#endif
|
|
}
|
|
|
|
free_mem:
|
|
rtw_mfree(info, info_len);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
static void rtw_lps_pg_set_rsvd_page(_adapter *adapter, u8 *frame, u16 *index
|
|
, u8 txdesc_size, u32 page_size, u8 *total_page_num
|
|
, bool is_wow_mode, _adapter *ld_sta_iface, bool only_get_page_num)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
|
|
struct rsvd_page_cache_t *cache;
|
|
bool rsvd = 1;
|
|
u8 *pos;
|
|
u32 len;
|
|
|
|
if (is_wow_mode) {
|
|
/* lps_level will not change when enter wow_mode */
|
|
if (pwrctl->lps_level != LPS_PG)
|
|
rsvd = 0;
|
|
} else {
|
|
if (!only_get_page_num && !ld_sta_iface)
|
|
rsvd = 0;
|
|
}
|
|
|
|
pos = only_get_page_num ? NULL : frame + *index;
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
if (IS_8822C_SERIES(hal_data->version_id)) {
|
|
/* LPSPG_DPK_INFO */
|
|
cache = &pwrctl->lpspg_dpk_info;
|
|
if (rsvd) {
|
|
if (pwrctl->lps_level != LPS_PG)
|
|
pos = NULL;
|
|
len = 0;
|
|
halrf_dpk_info_rsvd_page(adapter_to_phydm(adapter), pos, &len);
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
if (pos)
|
|
RTW_INFO_DUMP(cache->name, pos, len);
|
|
#endif
|
|
rsvd_page_cache_update_all(cache, *total_page_num, txdesc_size, page_size, pos, len);
|
|
*total_page_num += cache->page_num;
|
|
*index += page_size * cache->page_num;
|
|
pos = only_get_page_num ? NULL : frame + *index;
|
|
RSVD_PAGE_CFG(cache->name, cache->page_num, *total_page_num, *index);
|
|
} else
|
|
rsvd_page_cache_free(cache);
|
|
|
|
/* LPSPG_IQK_INFO */
|
|
cache = &pwrctl->lpspg_iqk_info;
|
|
if (rsvd
|
|
/* RegIQKFWOffload will not change when enter wow_mode */
|
|
&& !(is_wow_mode && hal_data->RegIQKFWOffload)
|
|
) {
|
|
if (pwrctl->lps_level != LPS_PG || hal_data->RegIQKFWOffload)
|
|
pos = NULL;
|
|
len = 0;
|
|
halrf_iqk_info_rsvd_page(adapter_to_phydm(adapter), pos, &len);
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
if (pos)
|
|
RTW_INFO_DUMP(cache->name, pos, len);
|
|
#endif
|
|
rsvd_page_cache_update_all(cache, *total_page_num, txdesc_size, page_size, pos, len);
|
|
*total_page_num += cache->page_num;
|
|
*index += page_size * cache->page_num;
|
|
pos = only_get_page_num ? NULL : frame + *index;
|
|
RSVD_PAGE_CFG(cache->name, cache->page_num, *total_page_num, *index);
|
|
} else
|
|
rsvd_page_cache_free(cache);
|
|
}
|
|
#endif
|
|
|
|
/* LPSPG_INFO */
|
|
cache = &pwrctl->lpspg_info;
|
|
if (rsvd) {
|
|
if (pwrctl->lps_level != LPS_PG)
|
|
pos = NULL;
|
|
rtw_hal_build_lps_pg_info_rsvd_page(adapter_to_dvobj(adapter), ld_sta_iface, pos, &len);
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
if (pos)
|
|
RTW_INFO_DUMP(cache->name, pos, len);
|
|
#endif
|
|
rsvd_page_cache_update_all(cache, *total_page_num, txdesc_size, page_size, pos, len);
|
|
*total_page_num += cache->page_num;
|
|
*index += page_size * cache->page_num;
|
|
pos = only_get_page_num ? NULL : frame + *index;
|
|
RSVD_PAGE_CFG(cache->name, cache->page_num, *total_page_num, *index);
|
|
} else
|
|
rsvd_page_cache_free(cache);
|
|
}
|
|
|
|
u8 rtw_hal_set_lps_pg_info_cmd(_adapter *adapter)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
|
|
u8 lpspg_info[H2C_LPS_PG_INFO_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
if (_NO_PRIVACY_ != adapter->securitypriv.dot11PrivacyAlgrthm)
|
|
SET_H2CCMD_LPSPG_SEC_CAM_EN(lpspg_info, 1); /*SecurityCAM_En*/
|
|
|
|
#ifdef CONFIG_MBSSID_CAM
|
|
SET_H2CCMD_LPSPG_MBID_CAM_EN(lpspg_info, 1); /*BSSIDCAM_En*/
|
|
#endif
|
|
|
|
#if defined(CONFIG_WOWLAN) && defined(CONFIG_WOW_PATTERN_HW_CAM)
|
|
if (pwrpriv->wowlan_mode == _TRUE &&
|
|
check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) {
|
|
|
|
SET_H2CCMD_LPSPG_PMC_CAM_EN(lpspg_info, 1); /*PatternMatchCAM_En*/
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_MACID_SEARCH
|
|
SET_H2CCMD_LPSPG_MACID_SEARCH_EN(lpspg_info, 1); /*MACIDSearch_En*/
|
|
#endif
|
|
|
|
#ifdef CONFIG_TX_SC
|
|
SET_H2CCMD_LPSPG_TXSC_EN(lpspg_info, 1); /*TXSC_En*/
|
|
#endif
|
|
|
|
#ifdef CONFIG_BEAMFORMING /*&& MU BF*/
|
|
SET_H2CCMD_LPSPG_MU_RATE_TB_EN(lpspg_info, 1); /*MURateTable_En*/
|
|
#endif
|
|
|
|
SET_H2CCMD_LPSPG_LOC(lpspg_info, pwrpriv->lpspg_info.loc);
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
if (pwrpriv->bFwCurrentInPSMode == _FALSE) {
|
|
SET_H2CCMD_LPSPG_DPK_INFO_LOC(lpspg_info, pwrpriv->lpspg_dpk_info.loc);
|
|
if (!GET_HAL_DATA(adapter)->RegIQKFWOffload)
|
|
SET_H2CCMD_LPSPG_IQK_INFO_LOC(lpspg_info, pwrpriv->lpspg_iqk_info.loc);
|
|
} else {
|
|
SET_H2CCMD_LPSPG_DPK_INFO_LOC(lpspg_info, 0);
|
|
if (!GET_HAL_DATA(adapter)->RegIQKFWOffload)
|
|
SET_H2CCMD_LPSPG_IQK_INFO_LOC(lpspg_info, 0);
|
|
}
|
|
#endif
|
|
|
|
#if (DBG_LPSPG_INFO_DUMP >= 1)
|
|
RTW_INFO_DUMP("H2C_LPS_PG_INFO: ", lpspg_info, H2C_LPS_PG_INFO_LEN);
|
|
#endif
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_LPS_PG_INFO,
|
|
H2C_LPS_PG_INFO_LEN,
|
|
lpspg_info);
|
|
return ret;
|
|
}
|
|
u8 rtw_hal_set_lps_pg_info(_adapter *adapter)
|
|
{
|
|
u8 ret = _FAIL;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
|
|
if (pwrpriv->lpspg_info.loc == 0) {
|
|
RTW_ERR("%s lpspg_info.loc = 0\n", __func__);
|
|
rtw_warn_on(1);
|
|
return ret;
|
|
}
|
|
#ifdef CONFIG_RTL8822C
|
|
rtw_lps_pg_set_dpk_info_rsvd_page(adapter);
|
|
rtw_lps_pg_set_iqk_info_rsvd_page(adapter);
|
|
#endif
|
|
rtw_hal_set_lps_pg_info_rsvd_page(adapter);
|
|
|
|
ret = rtw_hal_set_lps_pg_info_cmd(adapter);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void rtw_hal_lps_pg_rssi_lv_decide(_adapter *adapter, struct sta_info *sta)
|
|
{
|
|
#if 0
|
|
if (sta->cmn.ra_info.rssi_level >= 4)
|
|
sta->lps_pg_rssi_lv = 3; /*RSSI High - 1SS_VHT_MCS7*/
|
|
else if (sta->cmn.ra_info.rssi_level >= 2)
|
|
sta->lps_pg_rssi_lv = 2; /*RSSI Middle - 1SS_VHT_MCS3*/
|
|
else
|
|
sta->lps_pg_rssi_lv = 1; /*RSSI Lower - Lowest_rate*/
|
|
#else
|
|
sta->lps_pg_rssi_lv = 0;
|
|
#endif
|
|
RTW_INFO("%s mac-id:%d, rssi:%d, rssi_level:%d, lps_pg_rssi_lv:%d\n",
|
|
__func__, sta->cmn.mac_id, sta->cmn.rssi_stat.rssi, sta->cmn.ra_info.rssi_level, sta->lps_pg_rssi_lv);
|
|
}
|
|
|
|
void rtw_hal_lps_pg_handler(_adapter *adapter, enum lps_pg_hdl_id hdl_id)
|
|
{
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct sta_priv *pstapriv = &adapter->stapriv;
|
|
struct sta_info *sta;
|
|
|
|
sta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
|
|
|
|
switch (hdl_id) {
|
|
case LPS_PG_INFO_CFG:
|
|
rtw_hal_set_lps_pg_info(adapter);
|
|
break;
|
|
case LPS_PG_REDLEMEM:
|
|
if (IS_8822C_SERIES(GET_HAL_DATA(adapter)->version_id))
|
|
break;
|
|
|
|
/*set xmit_block*/
|
|
rtw_set_xmit_block(adapter, XMIT_BLOCK_REDLMEM);
|
|
if (_FAIL == rtw_hal_fw_mem_dl(adapter, FW_EMEM))
|
|
rtw_warn_on(1);
|
|
/*clearn xmit_block*/
|
|
rtw_clr_xmit_block(adapter, XMIT_BLOCK_REDLMEM);
|
|
break;
|
|
case LPS_PG_PHYDM_DIS:/*Disable RA and PT by H2C*/
|
|
if (IS_8822C_SERIES(GET_HAL_DATA(adapter)->version_id))
|
|
break;
|
|
|
|
if (sta)
|
|
rtw_phydm_lps_pg_hdl(adapter, sta, _TRUE);
|
|
break;
|
|
case LPS_PG_PHYDM_EN:/*Enable RA and PT by H2C*/
|
|
if (IS_8822C_SERIES(GET_HAL_DATA(adapter)->version_id))
|
|
break;
|
|
|
|
if (sta) {
|
|
rtw_hal_lps_pg_rssi_lv_decide(adapter, sta);
|
|
rtw_phydm_lps_pg_hdl(adapter, sta, _FALSE);
|
|
sta->lps_pg_rssi_lv = 0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif /*CONFIG_LPS_PG*/
|
|
|
|
static u8 _rtw_mi_assoc_if_num(_adapter *adapter)
|
|
{
|
|
u8 mi_iface_num = 0;
|
|
|
|
if (0) {
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - STA :%d", DEV_STA_LD_NUM(adapter_to_dvobj(adapter)));
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - AP:%d", DEV_AP_NUM(adapter_to_dvobj(adapter)));
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - AP starting :%d", DEV_AP_STARTING_NUM(adapter_to_dvobj(adapter)));
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - MESH :%d", DEV_MESH_NUM(adapter_to_dvobj(adapter)));
|
|
RTW_INFO("[IFS_ASSOC_STATUS] - ADHOC :%d", DEV_ADHOC_NUM(adapter_to_dvobj(adapter)));
|
|
/*RTW_INFO("[IFS_ASSOC_STATUS] - P2P-GC :%d", DEV_P2P_GC_NUM(adapter_to_dvobj(adapter)));*/
|
|
/*RTW_INFO("[IFS_ASSOC_STATUS] - P2P-GO :%d", DEV_P2P_GO_NUM(adapter_to_dvobj(adapter)));*/
|
|
}
|
|
|
|
mi_iface_num = (DEV_STA_LD_NUM(adapter_to_dvobj(adapter)) +
|
|
DEV_AP_NUM(adapter_to_dvobj(adapter)) +
|
|
DEV_AP_STARTING_NUM(adapter_to_dvobj(adapter)));
|
|
return mi_iface_num;
|
|
}
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
static _adapter *_rtw_search_sta_iface(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface = NULL;
|
|
_adapter *sta_iface = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_STATION_STATE) == _TRUE) {
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE) {
|
|
sta_iface = iface;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return sta_iface;
|
|
}
|
|
#if defined(CONFIG_AP_MODE) && defined(CONFIG_BT_COEXIST)
|
|
static _adapter *_rtw_search_ap_iface(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
_adapter *iface = NULL;
|
|
_adapter *ap_iface = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (check_fwstate(&iface->mlmepriv, WIFI_AP_STATE) == _TRUE ) {
|
|
ap_iface = iface;
|
|
break;
|
|
}
|
|
}
|
|
return ap_iface;
|
|
}
|
|
#endif/*CONFIG_AP_MODE*/
|
|
#endif/*CONFIG_CONCURRENT_MODE*/
|
|
|
|
#ifdef CONFIG_CUSTOMER01_SMART_ANTENNA
|
|
void rtw_hal_set_pathb_phase(_adapter *adapter, u8 phase_idx)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
|
|
struct PHY_DM_STRUCT *pDM_Odm = &pHalData->odmpriv;
|
|
|
|
return phydm_pathb_q_matrix_rotate(pDM_Odm, phase_idx);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Description: Fill the reserved packets that FW will use to RSVD page.
|
|
* Now we just send 4 types packet to rsvd page.
|
|
* (1)Beacon, (2)Ps-poll, (3)Null data, (4)ProbeRsp.
|
|
* Input:
|
|
* finished - FALSE:At the first time we will send all the packets as a large packet to Hw,
|
|
* so we need to set the packet length to total lengh.
|
|
* TRUE: At the second time, we should send the first packet (default:beacon)
|
|
* to Hw again and set the lengh in descriptor to the real beacon lengh.
|
|
* page_num - The amount of reserved page which driver need.
|
|
* If this is not NULL, this function doesn't real download reserved
|
|
* page, but just count the number of reserved page.
|
|
*
|
|
* 2009.10.15 by tynli.
|
|
* 2017.06.20 modified by Lucas.
|
|
*
|
|
* Page Size = 128: 8188e, 8723a/b, 8192c/d,
|
|
* Page Size = 256: 8192e, 8821a
|
|
* Page Size = 512: 8812a
|
|
*/
|
|
|
|
/*#define DBG_DUMP_SET_RSVD_PAGE*/
|
|
static void _rtw_hal_set_fw_rsvd_page(_adapter *adapter, bool finished, u8 *page_num)
|
|
{
|
|
PHAL_DATA_TYPE pHalData;
|
|
struct xmit_frame *pcmdframe = NULL;
|
|
struct pkt_attrib *pattrib;
|
|
struct xmit_priv *pxmitpriv;
|
|
struct pwrctrl_priv *pwrctl;
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
u32 BeaconLength = 0, ProbeRspLength = 0, PSPollLength = 0;
|
|
u32 NullDataLength = 0, QosNullLength = 0, BTQosNullLength = 0;
|
|
u32 ProbeReqLength = 0, NullFunctionDataLength = 0;
|
|
u8 TxDescLen = TXDESC_SIZE, TxDescOffset = TXDESC_OFFSET;
|
|
u8 TotalPageNum = 0 , CurtPktPageNum = 0 , RsvdPageNum = 0;
|
|
u8 *ReservedPagePacket;
|
|
u16 BufIndex = 0;
|
|
u32 TotalPacketLen = 0, MaxRsvdPageBufSize = 0, PageSize = 0;
|
|
RSVDPAGE_LOC RsvdPageLoc;
|
|
struct registry_priv *registry_par = &adapter->registrypriv;
|
|
|
|
#ifdef DBG_FW_DEBUG_MSG_PKT
|
|
u32 fw_dbg_msg_pkt_len = 0;
|
|
#endif /*DBG_FW_DEBUG_MSG_PKT*/
|
|
|
|
#ifdef DBG_CONFIG_ERROR_DETECT
|
|
struct sreset_priv *psrtpriv;
|
|
#endif /* DBG_CONFIG_ERROR_DETECT */
|
|
|
|
#ifdef CONFIG_MCC_MODE
|
|
u8 dl_mcc_page = _FAIL;
|
|
#endif /* CONFIG_MCC_MODE */
|
|
u8 nr_assoc_if;
|
|
|
|
_adapter *sta_iface = NULL;
|
|
_adapter *ap_iface = NULL;
|
|
|
|
bool is_wow_mode = _FALSE;
|
|
|
|
pHalData = GET_HAL_DATA(adapter);
|
|
#ifdef DBG_CONFIG_ERROR_DETECT
|
|
psrtpriv = &pHalData->srestpriv;
|
|
#endif
|
|
pxmitpriv = &adapter->xmitpriv;
|
|
pwrctl = adapter_to_pwrctl(adapter);
|
|
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&PageSize);
|
|
|
|
if (PageSize == 0) {
|
|
RTW_ERR("[Error]: %s, PageSize is zero!!\n", __func__);
|
|
return;
|
|
}
|
|
nr_assoc_if = _rtw_mi_assoc_if_num(adapter);
|
|
|
|
if ((pwrctl->wowlan_mode == _TRUE && pwrctl->wowlan_in_resume == _FALSE) ||
|
|
pwrctl->wowlan_ap_mode == _TRUE ||
|
|
pwrctl->wowlan_p2p_mode == _TRUE)
|
|
is_wow_mode = _TRUE;
|
|
|
|
/*page_num for init time to get rsvd page number*/
|
|
/* Prepare ReservedPagePacket */
|
|
if (page_num) {
|
|
ReservedPagePacket = rtw_zmalloc(MAX_CMDBUF_SZ);
|
|
if (!ReservedPagePacket) {
|
|
RTW_WARN("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
|
|
*page_num = 0xFF;
|
|
return;
|
|
}
|
|
RTW_INFO(FUNC_ADPT_FMT" Get [ %s ] RsvdPageNUm ==>\n",
|
|
FUNC_ADPT_ARG(adapter), (is_wow_mode) ? "WOW" : "NOR");
|
|
|
|
} else {
|
|
if (is_wow_mode)
|
|
RsvdPageNum = rtw_hal_get_txbuff_rsvd_page_num(adapter, _TRUE);
|
|
else
|
|
RsvdPageNum = rtw_hal_get_txbuff_rsvd_page_num(adapter, _FALSE);
|
|
|
|
RTW_INFO(FUNC_ADPT_FMT" PageSize: %d, [ %s ]-RsvdPageNUm: %d\n",
|
|
FUNC_ADPT_ARG(adapter), PageSize, (is_wow_mode) ? "WOW" : "NOR", RsvdPageNum);
|
|
|
|
MaxRsvdPageBufSize = RsvdPageNum * PageSize;
|
|
if (MaxRsvdPageBufSize > MAX_CMDBUF_SZ) {
|
|
RTW_ERR("%s MaxRsvdPageBufSize(%d) is larger than MAX_CMDBUF_SZ(%d)",
|
|
__func__, MaxRsvdPageBufSize, MAX_CMDBUF_SZ);
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
|
|
pcmdframe = rtw_alloc_cmdxmitframe(pxmitpriv);
|
|
if (pcmdframe == NULL) {
|
|
RTW_ERR("%s: alloc ReservedPagePacket fail!\n", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
ReservedPagePacket = pcmdframe->buf_addr;
|
|
}
|
|
|
|
_rtw_memset(&RsvdPageLoc, 0, sizeof(RSVDPAGE_LOC));
|
|
|
|
BufIndex = TxDescOffset;
|
|
|
|
/*======== beacon content =======*/
|
|
rtw_hal_construct_beacon(adapter,
|
|
&ReservedPagePacket[BufIndex], &BeaconLength);
|
|
|
|
/*
|
|
* When we count the first page size, we need to reserve description size for the RSVD
|
|
* packet, it will be filled in front of the packet in TXPKTBUF.
|
|
*/
|
|
BeaconLength = MAX_BEACON_LEN - TxDescLen;
|
|
CurtPktPageNum = (u8)PageNum((TxDescLen + BeaconLength), PageSize);
|
|
|
|
#if defined(CONFIG_FW_HANDLE_TXBCN) || defined(CONFIG_PORT_BASED_TXBCN)
|
|
CurtPktPageNum = CurtPktPageNum * CONFIG_LIMITED_AP_NUM;
|
|
#endif
|
|
TotalPageNum += CurtPktPageNum;
|
|
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
|
|
RSVD_PAGE_CFG("Beacon", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
|
|
/*======== probe response content ========*/
|
|
if (pwrctl->wowlan_ap_mode == _TRUE) {/*WOW mode*/
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (nr_assoc_if >= 2)
|
|
RTW_ERR("Not support > 2 net-interface in WOW\n");
|
|
#endif
|
|
/* (4) probe response*/
|
|
RsvdPageLoc.LocProbeRsp = TotalPageNum;
|
|
rtw_hal_construct_ProbeRsp(
|
|
adapter, &ReservedPagePacket[BufIndex],
|
|
&ProbeRspLength,
|
|
_FALSE);
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
ProbeRspLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(TxDescLen + ProbeRspLength, PageSize);
|
|
TotalPageNum += CurtPktPageNum;
|
|
TotalPacketLen = BufIndex + ProbeRspLength;
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
RSVD_PAGE_CFG("ProbeRsp", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
goto download_page;
|
|
}
|
|
|
|
/*======== ps-poll content * 1 page ========*/
|
|
sta_iface = adapter;
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (!MLME_IS_STA(sta_iface) && DEV_STA_LD_NUM(adapter_to_dvobj(sta_iface))) {
|
|
sta_iface = _rtw_search_sta_iface(adapter);
|
|
RTW_INFO("get ("ADPT_FMT") to create PS-Poll/Null/QosNull\n", ADPT_ARG(sta_iface));
|
|
}
|
|
#endif
|
|
|
|
if (MLME_IS_STA(sta_iface) || (nr_assoc_if == 0)) {
|
|
RsvdPageLoc.LocPsPoll = TotalPageNum;
|
|
RTW_INFO("LocPsPoll: %d\n", RsvdPageLoc.LocPsPoll);
|
|
rtw_hal_construct_PSPoll(sta_iface,
|
|
&ReservedPagePacket[BufIndex], &PSPollLength);
|
|
rtw_hal_fill_fake_txdesc(sta_iface,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
PSPollLength, _TRUE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum((TxDescLen + PSPollLength), PageSize);
|
|
|
|
TotalPageNum += CurtPktPageNum;
|
|
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
RSVD_PAGE_CFG("PSPoll", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
}
|
|
|
|
#ifdef CONFIG_MCC_MODE
|
|
/*======== MCC * n page ======== */
|
|
if (MCC_EN(adapter)) {/*Normal mode*/
|
|
dl_mcc_page = rtw_hal_dl_mcc_fw_rsvd_page(adapter, ReservedPagePacket,
|
|
&BufIndex, TxDescLen, PageSize, &TotalPageNum, &RsvdPageLoc, page_num);
|
|
} else {
|
|
dl_mcc_page = _FAIL;
|
|
}
|
|
|
|
if (dl_mcc_page == _FAIL)
|
|
#endif /* CONFIG_MCC_MODE */
|
|
{ /*======== null data * 1 page ======== */
|
|
if (MLME_IS_STA(sta_iface) || (nr_assoc_if == 0)) {
|
|
RsvdPageLoc.LocNullData = TotalPageNum;
|
|
RTW_INFO("LocNullData: %d\n", RsvdPageLoc.LocNullData);
|
|
rtw_hal_construct_NullFunctionData(
|
|
sta_iface,
|
|
&ReservedPagePacket[BufIndex],
|
|
&NullDataLength,
|
|
_FALSE, 0, 0, _FALSE);
|
|
rtw_hal_fill_fake_txdesc(sta_iface,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
NullDataLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(TxDescLen + NullDataLength, PageSize);
|
|
|
|
TotalPageNum += CurtPktPageNum;
|
|
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
RSVD_PAGE_CFG("NullData", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
}
|
|
}
|
|
|
|
/*======== Qos null data * 1 page ======== */
|
|
if (pwrctl->wowlan_mode == _FALSE ||
|
|
pwrctl->wowlan_in_resume == _TRUE) {/*Normal mode*/
|
|
if (MLME_IS_STA(sta_iface) || (nr_assoc_if == 0)) {
|
|
RsvdPageLoc.LocQosNull = TotalPageNum;
|
|
RTW_INFO("LocQosNull: %d\n", RsvdPageLoc.LocQosNull);
|
|
rtw_hal_construct_NullFunctionData(sta_iface,
|
|
&ReservedPagePacket[BufIndex],
|
|
&QosNullLength,
|
|
_TRUE, 0, 0, _FALSE);
|
|
rtw_hal_fill_fake_txdesc(sta_iface,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
QosNullLength, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(TxDescLen + QosNullLength,
|
|
PageSize);
|
|
|
|
TotalPageNum += CurtPktPageNum;
|
|
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
RSVD_PAGE_CFG("QosNull", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_BT_COEXIST
|
|
/*======== BT Qos null data * 1 page ======== */
|
|
if (pwrctl->wowlan_mode == _FALSE ||
|
|
pwrctl->wowlan_in_resume == _TRUE) {/*Normal mode*/
|
|
|
|
ap_iface = adapter;
|
|
#if defined (CONFIG_CONCURRENT_MODE) && defined(CONFIG_AP_MODE)
|
|
if (!MLME_IS_AP(ap_iface) && DEV_AP_NUM(adapter_to_dvobj(ap_iface))) { /*DEV_AP_STARTING_NUM*/
|
|
ap_iface = _rtw_search_ap_iface(adapter);
|
|
RTW_INFO("get ("ADPT_FMT") to create BTQoSNull\n", ADPT_ARG(ap_iface));
|
|
}
|
|
#endif
|
|
|
|
if (MLME_IS_AP(ap_iface) || (nr_assoc_if == 0)) {
|
|
RsvdPageLoc.LocBTQosNull = TotalPageNum;
|
|
|
|
RTW_INFO("LocBTQosNull: %d\n", RsvdPageLoc.LocBTQosNull);
|
|
|
|
rtw_hal_construct_NullFunctionData(ap_iface,
|
|
&ReservedPagePacket[BufIndex],
|
|
&BTQosNullLength,
|
|
_TRUE, 0, 0, _FALSE);
|
|
|
|
rtw_hal_fill_fake_txdesc(ap_iface,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
BTQosNullLength, _FALSE, _TRUE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(TxDescLen + BTQosNullLength,
|
|
PageSize);
|
|
|
|
TotalPageNum += CurtPktPageNum;
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
|
|
RSVD_PAGE_CFG("BTQosNull", CurtPktPageNum, TotalPageNum, TotalPacketLen);
|
|
}
|
|
}
|
|
#endif /* CONFIG_BT_COEXIT */
|
|
|
|
TotalPacketLen = BufIndex;
|
|
|
|
#ifdef DBG_FW_DEBUG_MSG_PKT
|
|
/*======== FW DEBUG MSG * n page ======== */
|
|
RsvdPageLoc.loc_fw_dbg_msg_pkt = TotalPageNum;
|
|
RTW_INFO("loc_fw_dbg_msg_pkt: %d\n", RsvdPageLoc.loc_fw_dbg_msg_pkt);
|
|
rtw_hal_construct_fw_dbg_msg_pkt(
|
|
adapter,
|
|
&ReservedPagePacket[BufIndex],
|
|
&fw_dbg_msg_pkt_len);
|
|
|
|
rtw_hal_fill_fake_txdesc(adapter,
|
|
&ReservedPagePacket[BufIndex - TxDescLen],
|
|
fw_dbg_msg_pkt_len, _FALSE, _FALSE, _FALSE);
|
|
|
|
CurtPktPageNum = (u8)PageNum(TxDescLen + fw_dbg_msg_pkt_len, PageSize);
|
|
|
|
if (CurtPktPageNum < 2)
|
|
CurtPktPageNum = 2; /*Need at least 2 rsvd page*/
|
|
TotalPageNum += CurtPktPageNum;
|
|
|
|
TotalPacketLen = BufIndex + fw_dbg_msg_pkt_len;
|
|
BufIndex += (CurtPktPageNum * PageSize);
|
|
#endif /*DBG_FW_DEBUG_MSG_PKT*/
|
|
|
|
#ifdef CONFIG_LPS_PG
|
|
rtw_lps_pg_set_rsvd_page(adapter, ReservedPagePacket, &BufIndex
|
|
, TxDescLen, PageSize, &TotalPageNum, is_wow_mode
|
|
, (sta_iface && MLME_IS_STA(sta_iface) && MLME_IS_ASOC(sta_iface)) ? sta_iface : NULL
|
|
, page_num ? 1 : 0
|
|
);
|
|
TotalPacketLen = BufIndex;
|
|
#endif
|
|
|
|
#ifdef CONFIG_WOWLAN
|
|
/*======== WOW * n page ======== */
|
|
if (pwrctl->wowlan_mode == _TRUE &&
|
|
pwrctl->wowlan_in_resume == _FALSE) {
|
|
rtw_hal_set_wow_fw_rsvd_page(adapter, ReservedPagePacket,
|
|
BufIndex, TxDescLen, PageSize,
|
|
&TotalPageNum, &TotalPacketLen, &RsvdPageLoc);
|
|
#ifdef CONFIG_WAR_OFFLOAD
|
|
rtw_hal_set_war_offload_parm(adapter, &RsvdPageLoc);
|
|
#endif /* CONFIG_WAR_OFFLOAD */
|
|
}
|
|
#endif /* CONFIG_WOWLAN */
|
|
|
|
#ifdef CONFIG_P2P_WOWLAN
|
|
/*======== P2P WOW * n page ======== */
|
|
if (_TRUE == pwrctl->wowlan_p2p_mode) {/*WOW mode*/
|
|
rtw_hal_set_p2p_wow_fw_rsvd_page(adapter, ReservedPagePacket,
|
|
BufIndex, TxDescLen, PageSize,
|
|
&TotalPageNum, &TotalPacketLen, &RsvdPageLoc);
|
|
}
|
|
#endif /* CONFIG_P2P_WOWLAN */
|
|
|
|
/*Note: BufIndex already add a TxDescOffset offset in first Beacon page
|
|
* The "TotalPacketLen" is calculate by BufIndex.
|
|
* We need to decrease TxDescOffset before doing length check. by yiwei
|
|
*/
|
|
TotalPacketLen = TotalPacketLen - TxDescOffset;
|
|
|
|
download_page:
|
|
if (page_num) {
|
|
*page_num = TotalPageNum;
|
|
rtw_mfree(ReservedPagePacket, MAX_CMDBUF_SZ);
|
|
ReservedPagePacket = NULL;
|
|
RTW_INFO(FUNC_ADPT_FMT" Get [ %s ] RsvdPageNUm <==\n",
|
|
FUNC_ADPT_ARG(adapter), (is_wow_mode) ? "WOW" : "NOR");
|
|
return;
|
|
}
|
|
|
|
/* RTW_INFO("%s BufIndex(%d), TxDescLen(%d), PageSize(%d)\n",__func__, BufIndex, TxDescLen, PageSize);*/
|
|
RTW_INFO("%s PageNum(%d), pktlen(%d)\n",
|
|
__func__, TotalPageNum, TotalPacketLen);
|
|
|
|
if (TotalPacketLen > MaxRsvdPageBufSize) {
|
|
RTW_ERR("%s : rsvd page size is not enough!!TotalPacketLen %d, MaxRsvdPageBufSize %d\n",
|
|
__FUNCTION__, TotalPacketLen, MaxRsvdPageBufSize);
|
|
rtw_warn_on(1);
|
|
goto error;
|
|
} else {
|
|
/* update attribute */
|
|
pattrib = &pcmdframe->attrib;
|
|
update_mgntframe_attrib(adapter, pattrib);
|
|
pattrib->qsel = QSLT_BEACON;
|
|
pattrib->pktlen = TotalPacketLen;
|
|
pattrib->last_txcmdsz = TotalPacketLen;
|
|
#ifdef CONFIG_PCI_HCI
|
|
dump_mgntframe(adapter, pcmdframe);
|
|
#else
|
|
dump_mgntframe_and_wait(adapter, pcmdframe, 100);
|
|
#endif
|
|
}
|
|
|
|
RTW_INFO("%s: Set RSVD page location to Fw ,TotalPacketLen(%d), TotalPageNum(%d)\n",
|
|
__func__, TotalPacketLen, TotalPageNum);
|
|
#ifdef DBG_DUMP_SET_RSVD_PAGE
|
|
RTW_INFO(" ==================================================\n");
|
|
RTW_INFO_DUMP("\n", ReservedPagePacket, TotalPacketLen);
|
|
RTW_INFO(" ==================================================\n");
|
|
#endif
|
|
|
|
|
|
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE)
|
|
|| MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)){
|
|
rtw_hal_set_FwRsvdPage_cmd(adapter, &RsvdPageLoc);
|
|
#ifdef DBG_FW_DEBUG_MSG_PKT
|
|
rtw_hal_set_fw_dbg_msg_pkt_rsvd_page_cmd(adapter, &RsvdPageLoc);
|
|
#endif /*DBG_FW_DEBUG_MSG_PKT*/
|
|
#ifdef CONFIG_WOWLAN
|
|
if (pwrctl->wowlan_mode == _TRUE &&
|
|
pwrctl->wowlan_in_resume == _FALSE)
|
|
rtw_hal_set_FwAoacRsvdPage_cmd(adapter, &RsvdPageLoc);
|
|
#endif /* CONFIG_WOWLAN */
|
|
#ifdef CONFIG_AP_WOWLAN
|
|
if (pwrctl->wowlan_ap_mode == _TRUE)
|
|
rtw_hal_set_ap_rsvdpage_loc_cmd(adapter, &RsvdPageLoc);
|
|
#endif /* CONFIG_AP_WOWLAN */
|
|
} else if (pwrctl->wowlan_pno_enable) {
|
|
#ifdef CONFIG_PNO_SUPPORT
|
|
rtw_hal_set_FwAoacRsvdPage_cmd(adapter, &RsvdPageLoc);
|
|
if (pwrctl->wowlan_in_resume)
|
|
rtw_hal_set_scan_offload_info_cmd(adapter,
|
|
&RsvdPageLoc, 0);
|
|
else
|
|
rtw_hal_set_scan_offload_info_cmd(adapter,
|
|
&RsvdPageLoc, 1);
|
|
#endif /* CONFIG_PNO_SUPPORT */
|
|
}
|
|
|
|
#ifdef CONFIG_P2P_WOWLAN
|
|
if (_TRUE == pwrctl->wowlan_p2p_mode)
|
|
rtw_hal_set_FwP2PRsvdPage_cmd(adapter, &RsvdPageLoc);
|
|
#endif /* CONFIG_P2P_WOWLAN */
|
|
|
|
return;
|
|
error:
|
|
rtw_free_xmitframe(pxmitpriv, pcmdframe);
|
|
}
|
|
|
|
void rtw_hal_set_fw_rsvd_page(struct _ADAPTER *adapter, bool finished)
|
|
{
|
|
#ifdef CONFIG_AP_MODE
|
|
if (finished)
|
|
rtw_mi_tx_beacon_hdl(adapter);
|
|
else
|
|
#endif
|
|
_rtw_hal_set_fw_rsvd_page(adapter, finished, NULL);
|
|
}
|
|
|
|
static u8 rtw_hal_set_fw_bcn_early_c2h_rpt_cmd(struct _ADAPTER *adapter, u8 enable)
|
|
{
|
|
u8 u1H2CSetPwrMode[H2C_PWRMODE_LEN] = {0};
|
|
u8 ret = _FAIL;
|
|
|
|
#ifdef CONFIG_TDLS
|
|
#ifdef CONFIG_TDLS_CH_SW
|
|
if (ATOMIC_READ(&adapter->tdlsinfo.chsw_info.chsw_on) == _TRUE)
|
|
{
|
|
SET_H2CCMD_PWRMODE_PARM_RLBM(u1H2CSetPwrMode, 1);
|
|
SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1H2CSetPwrMode, 0);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
SET_H2CCMD_PWRMODE_PARM_MODE(u1H2CSetPwrMode, 0);
|
|
SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1H2CSetPwrMode, 0x0C);
|
|
SET_H2CCMD_PWRMODE_PARM_BCN_EARLY_C2H_RPT(u1H2CSetPwrMode, enable);
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_SET_PWR_MODE,
|
|
H2C_PWRMODE_LEN,
|
|
u1H2CSetPwrMode);
|
|
|
|
RTW_PRINT("-%s()-\n", __func__);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_FW_MULTI_PORT_SUPPORT
|
|
u8 rtw_hal_set_ap_bcn_imr_cmd(struct _ADAPTER *adapter, u8 enable)
|
|
{
|
|
u8 ap_port_id;
|
|
u8 ret = _FAIL;
|
|
|
|
if (!MLME_IS_AP(adapter))
|
|
goto exit;
|
|
|
|
ap_port_id = get_hw_port(adapter);
|
|
if (ap_port_id != HW_PORT0) {
|
|
RTW_WARN("AP mode should use port0\n");
|
|
goto exit;
|
|
}
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter,
|
|
H2C_SET_AP_BCN_IMR,
|
|
H2C_AP_BCN_MIR_LEN,
|
|
&enable);
|
|
|
|
RTW_INFO(FUNC_ADPT_FMT" : AP mode %s beacon early IMR\n",
|
|
FUNC_ADPT_ARG(adapter), enable ? "enable" : "disable");
|
|
exit:
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* rtw_hal_get_rsvd_page_num() - Get needed reserved page number
|
|
* @adapter: struct _ADAPTER*
|
|
*
|
|
* Caculate needed reserved page number.
|
|
* In different state would get different number, for example normal mode and
|
|
* WOW mode would need different reserved page size.
|
|
*
|
|
* Return the number of reserved page which driver need.
|
|
*/
|
|
u8 rtw_hal_get_rsvd_page_num(struct _ADAPTER *adapter)
|
|
{
|
|
u8 num = 0;
|
|
|
|
|
|
_rtw_hal_set_fw_rsvd_page(adapter, _FALSE, &num);
|
|
|
|
return num;
|
|
}
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_BCN_FUNC
|
|
static void hw_var_set_bcn_func(_adapter *adapter, u8 enable)
|
|
{
|
|
u32 bcn_ctrl_reg;
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (adapter->hw_port == HW_PORT1)
|
|
bcn_ctrl_reg = REG_BCN_CTRL_1;
|
|
else
|
|
#endif
|
|
bcn_ctrl_reg = REG_BCN_CTRL;
|
|
|
|
if (enable)
|
|
rtw_write8(adapter, bcn_ctrl_reg, (EN_BCN_FUNCTION | EN_TXBCN_RPT));
|
|
else {
|
|
u8 val8;
|
|
|
|
val8 = rtw_read8(adapter, bcn_ctrl_reg);
|
|
val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT);
|
|
|
|
#ifdef CONFIG_BT_COEXIST
|
|
if (GET_HAL_DATA(adapter)->EEPROMBluetoothCoexist == 1) {
|
|
/* Always enable port0 beacon function for PSTDMA */
|
|
if (REG_BCN_CTRL == bcn_ctrl_reg)
|
|
val8 |= EN_BCN_FUNCTION;
|
|
}
|
|
#endif
|
|
|
|
rtw_write8(adapter, bcn_ctrl_reg, val8);
|
|
}
|
|
|
|
#ifdef CONFIG_RTL8192F
|
|
if (IS_HARDWARE_TYPE_8192F(adapter)) {
|
|
u16 val16, val16_ori;
|
|
|
|
val16_ori = val16 = rtw_read16(adapter, REG_WLAN_ACT_MASK_CTRL_1);
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (adapter->hw_port == HW_PORT1) {
|
|
if (enable)
|
|
val16 |= EN_PORT_1_FUNCTION;
|
|
else
|
|
val16 &= ~EN_PORT_1_FUNCTION;
|
|
} else
|
|
#endif
|
|
{
|
|
if (enable)
|
|
val16 |= EN_PORT_0_FUNCTION;
|
|
else
|
|
val16 &= ~EN_PORT_0_FUNCTION;
|
|
|
|
#ifdef CONFIG_BT_COEXIST
|
|
if (GET_HAL_DATA(adapter)->EEPROMBluetoothCoexist == 1)
|
|
val16 |= EN_PORT_0_FUNCTION;
|
|
#endif
|
|
}
|
|
|
|
if (val16 != val16_ori)
|
|
rtw_write16(adapter, REG_WLAN_ACT_MASK_CTRL_1, val16);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_MLME_DISCONNECT
|
|
static void hw_var_set_mlme_disconnect(_adapter *adapter)
|
|
{
|
|
u8 val8;
|
|
|
|
/* reject all data frames */
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (rtw_mi_check_status(adapter, MI_LINKED) == _FALSE)
|
|
#endif
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0x0000);
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (adapter->hw_port == HW_PORT1) {
|
|
/* reset TSF1 */
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(1));
|
|
|
|
/* disable update TSF1 */
|
|
rtw_iface_disable_tsf_update(adapter);
|
|
|
|
if (!IS_HARDWARE_TYPE_8723D(adapter)
|
|
&& !IS_HARDWARE_TYPE_8192F(adapter)
|
|
&& !IS_HARDWARE_TYPE_8710B(adapter)
|
|
) {
|
|
/* disable Port1's beacon function */
|
|
val8 = rtw_read8(adapter, REG_BCN_CTRL_1);
|
|
val8 &= ~EN_BCN_FUNCTION;
|
|
rtw_write8(adapter, REG_BCN_CTRL_1, val8);
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
/* reset TSF */
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(0));
|
|
|
|
/* disable update TSF */
|
|
rtw_iface_disable_tsf_update(adapter);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void hw_var_set_mlme_sitesurvey(_adapter *adapter, u8 enable)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u16 value_rxfltmap2;
|
|
|
|
#ifdef DBG_IFACE_STATUS
|
|
DBG_IFACE_STATUS_DUMP(adapter);
|
|
#endif
|
|
|
|
#ifdef CONFIG_FIND_BEST_CHANNEL
|
|
/* Receive all data frames */
|
|
value_rxfltmap2 = 0xFFFF;
|
|
#else
|
|
/* not to receive data frame */
|
|
value_rxfltmap2 = 0;
|
|
#endif
|
|
|
|
if (enable) { /* under sitesurvey */
|
|
/*
|
|
* 1. configure REG_RXFLTMAP2
|
|
* 2. disable TSF update & buddy TSF update to avoid updating wrong TSF due to clear RCR_CBSSID_BCN
|
|
* 3. config RCR to receive different BSSID BCN or probe rsp
|
|
*/
|
|
rtw_write16(adapter, REG_RXFLTMAP2, value_rxfltmap2);
|
|
|
|
rtw_hal_rcr_set_chk_bssid(adapter, MLME_SCAN_ENTER);
|
|
|
|
/* Save orignal RRSR setting, only 8812 set RRSR after set ch/bw/band */
|
|
#if defined (CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
|
|
hal_data->RegRRSR = rtw_read32(adapter, REG_RRSR);
|
|
hal_data->RegRRSR &= 0x000FFFFF;
|
|
#endif
|
|
|
|
#if defined(CONFIG_BEAMFORMING) && (defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A))
|
|
if (IS_8812_SERIES(hal_data->version_id) || IS_8821_SERIES(hal_data->version_id)) {
|
|
/* set 718[1:0]=2'b00 to avoid BF scan hang */
|
|
hal_data->backup_snd_ptcl_ctrl = rtw_read8(adapter, REG_SND_PTCL_CTRL_8812A);
|
|
rtw_write8(adapter, REG_SND_PTCL_CTRL_8812A, (hal_data->backup_snd_ptcl_ctrl & 0xfc));
|
|
}
|
|
#endif
|
|
|
|
if (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter))
|
|
StopTxBeacon(adapter);
|
|
} else { /* sitesurvey done */
|
|
/*
|
|
* 1. enable rx data frame
|
|
* 2. config RCR not to receive different BSSID BCN or probe rsp
|
|
* 3. doesn't enable TSF update & buddy TSF right now to avoid HW conflict
|
|
* so, we enable TSF update when rx first BCN after sitesurvey done
|
|
*/
|
|
if (rtw_mi_check_fwstate(adapter, WIFI_ASOC_STATE | WIFI_AP_STATE | WIFI_MESH_STATE)) {
|
|
/* enable to rx data frame */
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
}
|
|
|
|
rtw_hal_rcr_set_chk_bssid(adapter, MLME_SCAN_DONE);
|
|
|
|
/* Restore orignal RRSR setting,only 8812 set RRSR after set ch/bw/band */
|
|
#if defined (CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
|
|
rtw_phydm_set_rrsr(adapter, hal_data->RegRRSR, TRUE);
|
|
#endif
|
|
|
|
#if defined(CONFIG_BEAMFORMING) && (defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A))
|
|
if (IS_8812_SERIES(hal_data->version_id) || IS_8821_SERIES(hal_data->version_id)) {
|
|
/* Restore orignal 0x718 setting*/
|
|
rtw_write8(adapter, REG_SND_PTCL_CTRL_8812A, hal_data->backup_snd_ptcl_ctrl);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_AP_MODE
|
|
if (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter)) {
|
|
ResumeTxBeacon(adapter);
|
|
rtw_mi_tx_beacon_hdl(adapter);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_MLME_JOIN
|
|
static void hw_var_set_mlme_join(_adapter *adapter, u8 type)
|
|
{
|
|
u8 val8;
|
|
u16 val16;
|
|
u32 val32;
|
|
u8 RetryLimit = RL_VAL_STA;
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
if (type == 0) {
|
|
/* prepare to join */
|
|
if (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter))
|
|
StopTxBeacon(adapter);
|
|
|
|
/* enable to rx data frame.Accept all data frame */
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
|
|
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
|
|
RetryLimit = (hal_data->CustomerID == RT_CID_CCX) ? RL_VAL_AP : RL_VAL_STA;
|
|
else /* Ad-hoc Mode */
|
|
RetryLimit = RL_VAL_AP;
|
|
|
|
rtw_iface_enable_tsf_update(adapter);
|
|
|
|
} else if (type == 1) {
|
|
/* joinbss_event call back when join res < 0 */
|
|
if (rtw_mi_check_status(adapter, MI_LINKED) == _FALSE)
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
|
|
|
|
rtw_iface_disable_tsf_update(adapter);
|
|
|
|
if (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter)) {
|
|
ResumeTxBeacon(adapter);
|
|
|
|
/* reset TSF 1/2 after ResumeTxBeacon */
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(1) | BIT(0));
|
|
}
|
|
|
|
} else if (type == 2) {
|
|
/* sta add event call back */
|
|
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
|
|
/* fixed beacon issue for 8191su........... */
|
|
rtw_write8(adapter, 0x542 , 0x02);
|
|
RetryLimit = RL_VAL_AP;
|
|
}
|
|
|
|
if (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter)) {
|
|
ResumeTxBeacon(adapter);
|
|
|
|
/* reset TSF 1/2 after ResumeTxBeacon */
|
|
rtw_write8(adapter, REG_DUAL_TSF_RST, BIT(1) | BIT(0));
|
|
}
|
|
}
|
|
|
|
val16 = BIT_SRL(RetryLimit) | BIT_LRL(RetryLimit);
|
|
rtw_write16(adapter, REG_RETRY_LIMIT, val16);
|
|
#else /* !CONFIG_CONCURRENT_MODE */
|
|
if (type == 0) { /* prepare to join */
|
|
/* enable to rx data frame.Accept all data frame */
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
|
|
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
|
|
RetryLimit = (hal_data->CustomerID == RT_CID_CCX) ? RL_VAL_AP : RL_VAL_STA;
|
|
else /* Ad-hoc Mode */
|
|
RetryLimit = RL_VAL_AP;
|
|
|
|
rtw_iface_enable_tsf_update(adapter);
|
|
|
|
} else if (type == 1) { /* joinbss_event call back when join res < 0 */
|
|
rtw_write16(adapter, REG_RXFLTMAP2, 0x00);
|
|
|
|
rtw_iface_disable_tsf_update(adapter);
|
|
|
|
} else if (type == 2) { /* sta add event call back */
|
|
if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE))
|
|
RetryLimit = RL_VAL_AP;
|
|
}
|
|
|
|
val16 = BIT_SRL(RetryLimit) | BIT_LRL(RetryLimit);
|
|
rtw_write16(adapter, REG_RETRY_LIMIT, val16);
|
|
#endif /* !CONFIG_CONCURRENT_MODE */
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_TSF_RESET_OFFLOAD
|
|
static int rtw_hal_h2c_reset_tsf(_adapter *adapter, u8 reset_port)
|
|
{
|
|
u8 buf[2];
|
|
int ret;
|
|
|
|
if (reset_port == HW_PORT0) {
|
|
buf[0] = 0x1;
|
|
buf[1] = 0;
|
|
} else {
|
|
buf[0] = 0x0;
|
|
buf[1] = 0x1;
|
|
}
|
|
|
|
ret = rtw_hal_fill_h2c_cmd(adapter, H2C_RESET_TSF, 2, buf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int rtw_hal_reset_tsf(_adapter *adapter, u8 reset_port)
|
|
{
|
|
u8 reset_cnt_before = 0, reset_cnt_after = 0, loop_cnt = 0;
|
|
u32 reg_reset_tsf_cnt = (reset_port == HW_PORT0) ?
|
|
REG_FW_RESET_TSF_CNT_0 : REG_FW_RESET_TSF_CNT_1;
|
|
int ret;
|
|
|
|
/* site survey will cause reset tsf fail */
|
|
rtw_mi_buddy_scan_abort(adapter, _FALSE);
|
|
reset_cnt_after = reset_cnt_before = rtw_read8(adapter, reg_reset_tsf_cnt);
|
|
ret = rtw_hal_h2c_reset_tsf(adapter, reset_port);
|
|
if (ret != _SUCCESS)
|
|
return ret;
|
|
|
|
while ((reset_cnt_after == reset_cnt_before) && (loop_cnt < 10)) {
|
|
rtw_msleep_os(100);
|
|
loop_cnt++;
|
|
reset_cnt_after = rtw_read8(adapter, reg_reset_tsf_cnt);
|
|
}
|
|
|
|
return (loop_cnt >= 10) ? _FAIL : _SUCCESS;
|
|
}
|
|
#endif /* CONFIG_TSF_RESET_OFFLOAD */
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_CORRECT_TSF
|
|
#ifdef CONFIG_HW_P0_TSF_SYNC
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
static void hw_port0_tsf_sync_sel(_adapter *adapter, u8 benable, u8 hw_port, u16 tr_offset)
|
|
{
|
|
u8 val8;
|
|
u8 client_id = 0;
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
|
|
#ifdef CONFIG_MCC_MODE
|
|
if (MCC_EN(adapter) && (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))) {
|
|
RTW_INFO("[MCC] do not set HW TSF sync\n");
|
|
return;
|
|
}
|
|
#endif
|
|
/* check if port0 is already synced */
|
|
if (benable && dvobj->p0_tsf.sync_port != MAX_HW_PORT && dvobj->p0_tsf.sync_port == hw_port) {
|
|
RTW_WARN(FUNC_ADPT_FMT ": port0 already enable TSF sync(%d)\n",
|
|
FUNC_ADPT_ARG(adapter), dvobj->p0_tsf.sync_port);
|
|
return;
|
|
}
|
|
|
|
/* check if port0 already disable sync */
|
|
if (!benable && dvobj->p0_tsf.sync_port == MAX_HW_PORT) {
|
|
RTW_WARN(FUNC_ADPT_FMT ": port0 already disable TSF sync\n", FUNC_ADPT_ARG(adapter));
|
|
return;
|
|
}
|
|
|
|
/* check if port0 sync to port0 */
|
|
if (benable && hw_port == HW_PORT0) {
|
|
RTW_ERR(FUNC_ADPT_FMT ": hw_port is port0 under enable\n", FUNC_ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
|
|
/*0x5B4 [6:4] :SYNC_CLI_SEL - The selector for the CLINT port of sync tsft source for port 0*/
|
|
/* Bit[5:4] : 0 for clint0, 1 for clint1, 2 for clint2, 3 for clint3.
|
|
Bit6 : 1= enable sync to port 0. 0=disable sync to port 0.*/
|
|
|
|
val8 = rtw_read8(adapter, REG_TIMER0_SRC_SEL);
|
|
|
|
if (benable) {
|
|
/*Disable Port0's beacon function*/
|
|
rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) & ~BIT_EN_BCN_FUNCTION);
|
|
|
|
/*Reg 0x518[15:0]: TSFTR_SYN_OFFSET*/
|
|
if (tr_offset)
|
|
rtw_write16(adapter, REG_TSFTR_SYN_OFFSET, tr_offset);
|
|
|
|
/*reg 0x577[6]=1*/ /*auto sync by tbtt*/
|
|
rtw_write8(adapter, REG_MISC_CTRL, rtw_read8(adapter, REG_MISC_CTRL) | BIT_AUTO_SYNC_BY_TBTT);
|
|
|
|
if (HW_PORT1 == hw_port)
|
|
client_id = 0;
|
|
else if (HW_PORT2 == hw_port)
|
|
client_id = 1;
|
|
else if (HW_PORT3 == hw_port)
|
|
client_id = 2;
|
|
else if (HW_PORT4 == hw_port)
|
|
client_id = 3;
|
|
|
|
val8 &= 0x8F;
|
|
val8 |= (BIT(6) | (client_id << 4));
|
|
|
|
dvobj->p0_tsf.sync_port = hw_port;
|
|
dvobj->p0_tsf.offset = tr_offset;
|
|
rtw_write8(adapter, REG_TIMER0_SRC_SEL, val8);
|
|
|
|
/*Enable Port0's beacon function*/
|
|
rtw_write8(adapter, REG_BCN_CTRL, rtw_read8(adapter, REG_BCN_CTRL) | BIT_EN_BCN_FUNCTION);
|
|
RTW_INFO("%s Port_%d TSF sync to P0, timer offset :%d\n", __func__, hw_port, tr_offset);
|
|
} else {
|
|
val8 &= ~BIT(6);
|
|
|
|
dvobj->p0_tsf.sync_port = MAX_HW_PORT;
|
|
dvobj->p0_tsf.offset = 0;
|
|
rtw_write8(adapter, REG_TIMER0_SRC_SEL, val8);
|
|
RTW_INFO("%s P0 TSF sync disable\n", __func__);
|
|
}
|
|
}
|
|
static _adapter * _search_ld_sta(_adapter *adapter, u8 include_self)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
u8 i;
|
|
_adapter *iface = NULL;
|
|
|
|
if (rtw_mi_get_assoced_sta_num(adapter) == 0) {
|
|
RTW_ERR("STA_LD_NUM == 0\n");
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
if (include_self == _FALSE && adapter == iface)
|
|
continue;
|
|
if (is_client_associated_to_ap(iface))
|
|
break;
|
|
}
|
|
if (iface)
|
|
RTW_INFO("search STA iface -"ADPT_FMT"\n", ADPT_ARG(iface));
|
|
return iface;
|
|
}
|
|
#endif /*CONFIG_CONCURRENT_MODE*/
|
|
/*Correct port0's TSF*/
|
|
/*#define DBG_P0_TSF_SYNC*/
|
|
void hw_var_set_correct_tsf(PADAPTER adapter, u8 mlme_state)
|
|
{
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
_adapter *sta_if = NULL;
|
|
u8 hw_port;
|
|
|
|
RTW_INFO(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(adapter));
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] AP_NUM = %d\n", rtw_mi_get_ap_num(adapter));
|
|
RTW_INFO("[TSF_SYNC] MESH_NUM = %d\n", rtw_mi_get_mesh_num(adapter));
|
|
RTW_INFO("[TSF_SYNC] LD_STA_NUM = %d\n", rtw_mi_get_assoced_sta_num(adapter));
|
|
if (dvobj->p0_tsf.sync_port == MAX_HW_PORT)
|
|
RTW_INFO("[TSF_SYNC] org p0 sync port = N/A\n");
|
|
else
|
|
RTW_INFO("[TSF_SYNC] org p0 sync port = %d\n", dvobj->p0_tsf.sync_port);
|
|
RTW_INFO("[TSF_SYNC] timer offset = %d\n", dvobj->p0_tsf.offset);
|
|
#endif
|
|
switch (mlme_state) {
|
|
case MLME_STA_CONNECTED :
|
|
{
|
|
hw_port = rtw_hal_get_port(adapter);
|
|
|
|
if (!MLME_IS_STA(adapter)) {
|
|
RTW_ERR("STA CON state,but iface("ADPT_FMT") is not STA\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
if ((dvobj->p0_tsf.sync_port != MAX_HW_PORT) && (hw_port == HW_PORT0)) {
|
|
RTW_ERR(ADPT_FMT" is STA with P0 connected => DIS P0_TSF_SYNC\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
hw_port0_tsf_sync_sel(adapter, _FALSE, 0, 0);
|
|
}
|
|
|
|
if ((dvobj->p0_tsf.sync_port == MAX_HW_PORT) &&
|
|
(rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter))) {
|
|
hw_port0_tsf_sync_sel(adapter, _TRUE, hw_port, 50);/*timer offset 50ms*/
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] STA_LINKED => EN P0_TSF_SYNC\n");
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
case MLME_STA_DISCONNECTED :
|
|
{
|
|
hw_port = rtw_hal_get_port(adapter);
|
|
|
|
if (!MLME_IS_STA(adapter)) {
|
|
RTW_ERR("STA DIS_CON state,but iface("ADPT_FMT") is not STA\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
if (dvobj->p0_tsf.sync_port == hw_port) {
|
|
if (rtw_mi_get_assoced_sta_num(adapter) >= 2) {
|
|
/* search next appropriate sta*/
|
|
sta_if = _search_ld_sta(adapter, _FALSE);
|
|
if (sta_if) {
|
|
hw_port = rtw_hal_get_port(sta_if);
|
|
hw_port0_tsf_sync_sel(adapter, _TRUE, hw_port, 50);/*timer offset 50ms*/
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] STA_DIS_CON => CHANGE P0_TSF_SYNC\n");
|
|
#endif
|
|
}
|
|
} else if (rtw_mi_get_assoced_sta_num(adapter) == 1) {
|
|
hw_port0_tsf_sync_sel(adapter, _FALSE, 0, 0);
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] STA_DIS_CON => DIS P0_TSF_SYNC\n");
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#ifdef CONFIG_AP_MODE
|
|
case MLME_AP_STARTED :
|
|
case MLME_MESH_STARTED :
|
|
{
|
|
if (!(MLME_IS_AP(adapter) || MLME_IS_MESH(adapter))) {
|
|
RTW_ERR("AP START state,but iface("ADPT_FMT") is not AP\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
|
|
if ((dvobj->p0_tsf.sync_port == MAX_HW_PORT) &&
|
|
rtw_mi_get_assoced_sta_num(adapter)) {
|
|
/* get port of sta */
|
|
sta_if = _search_ld_sta(adapter, _FALSE);
|
|
if (sta_if) {
|
|
hw_port = rtw_hal_get_port(sta_if);
|
|
hw_port0_tsf_sync_sel(adapter, _TRUE, hw_port, 50);/*timer offset 50ms*/
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] AP_START => EN P0_TSF_SYNC\n");
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MLME_AP_STOPPED :
|
|
case MLME_MESH_STOPPED :
|
|
{
|
|
if (!(MLME_IS_AP(adapter) || MLME_IS_MESH(adapter))) {
|
|
RTW_ERR("AP START state,but iface("ADPT_FMT") is not AP\n", ADPT_ARG(adapter));
|
|
rtw_warn_on(1);
|
|
}
|
|
/*stop ap mode*/
|
|
if ((rtw_mi_get_ap_num(adapter) + rtw_mi_get_mesh_num(adapter) == 1) &&
|
|
(dvobj->p0_tsf.sync_port != MAX_HW_PORT)) {
|
|
hw_port0_tsf_sync_sel(adapter, _FALSE, 0, 0);
|
|
#ifdef DBG_P0_TSF_SYNC
|
|
RTW_INFO("[TSF_SYNC] AP_STOP => DIS P0_TSF_SYNC\n");
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
#endif /* CONFIG_AP_MODE */
|
|
default :
|
|
RTW_ERR(FUNC_ADPT_FMT" unknow state(0x%02x)\n", FUNC_ADPT_ARG(adapter), mlme_state);
|
|
break;
|
|
}
|
|
|
|
/*#ifdef DBG_P0_TSF_SYNC*/
|
|
#if 1
|
|
if (dvobj->p0_tsf.sync_port == MAX_HW_PORT)
|
|
RTW_INFO("[TSF_SYNC] p0 sync port = N/A\n");
|
|
else
|
|
RTW_INFO("[TSF_SYNC] p0 sync port = %d\n", dvobj->p0_tsf.sync_port);
|
|
RTW_INFO("[TSF_SYNC] timer offset = %d\n", dvobj->p0_tsf.offset);
|
|
#endif
|
|
#endif /*CONFIG_CONCURRENT_MODE*/
|
|
}
|
|
|
|
#else /*! CONFIG_HW_P0_TSF_SYNC*/
|
|
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
static void hw_var_set_correct_tsf(_adapter *adapter, u8 mlme_state)
|
|
{
|
|
/*do nothing*/
|
|
}
|
|
#else /* !CONFIG_MI_WITH_MBSSID_CAM*/
|
|
static void rtw_hal_correct_tsf(_adapter *padapter, u8 hw_port, u64 tsf)
|
|
{
|
|
if (hw_port == HW_PORT0) {
|
|
/*disable related TSF function*/
|
|
rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) & (~EN_BCN_FUNCTION));
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(padapter, REG_WLAN_ACT_MASK_CTRL_1, rtw_read16(padapter,
|
|
REG_WLAN_ACT_MASK_CTRL_1) & ~EN_PORT_0_FUNCTION);
|
|
#endif
|
|
|
|
rtw_write32(padapter, REG_TSFTR, tsf);
|
|
rtw_write32(padapter, REG_TSFTR + 4, tsf >> 32);
|
|
|
|
/*enable related TSF function*/
|
|
rtw_write8(padapter, REG_BCN_CTRL, rtw_read8(padapter, REG_BCN_CTRL) | EN_BCN_FUNCTION);
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(padapter, REG_WLAN_ACT_MASK_CTRL_1, rtw_read16(padapter,
|
|
REG_WLAN_ACT_MASK_CTRL_1) | EN_PORT_0_FUNCTION);
|
|
#endif
|
|
} else if (hw_port == HW_PORT1) {
|
|
/*disable related TSF function*/
|
|
rtw_write8(padapter, REG_BCN_CTRL_1, rtw_read8(padapter, REG_BCN_CTRL_1) & (~EN_BCN_FUNCTION));
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(padapter, REG_WLAN_ACT_MASK_CTRL_1, rtw_read16(padapter,
|
|
REG_WLAN_ACT_MASK_CTRL_1) & ~EN_PORT_1_FUNCTION);
|
|
#endif
|
|
|
|
rtw_write32(padapter, REG_TSFTR1, tsf);
|
|
rtw_write32(padapter, REG_TSFTR1 + 4, tsf >> 32);
|
|
|
|
/*enable related TSF function*/
|
|
rtw_write8(padapter, REG_BCN_CTRL_1, rtw_read8(padapter, REG_BCN_CTRL_1) | EN_BCN_FUNCTION);
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(padapter, REG_WLAN_ACT_MASK_CTRL_1, rtw_read16(padapter,
|
|
REG_WLAN_ACT_MASK_CTRL_1) | EN_PORT_1_FUNCTION);
|
|
#endif
|
|
} else
|
|
RTW_INFO("%s-[WARN] "ADPT_FMT" invalid hw_port:%d\n", __func__, ADPT_ARG(padapter), hw_port);
|
|
}
|
|
static void hw_var_set_correct_tsf(_adapter *adapter, u8 mlme_state)
|
|
{
|
|
u64 tsf;
|
|
struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);
|
|
|
|
tsf = mlmeext->TSFValue - rtw_modular64(mlmeext->TSFValue, (mlmeinfo->bcn_interval * 1024)) - 1024; /*us*/
|
|
|
|
if ((mlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE
|
|
|| (mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
|
|
StopTxBeacon(adapter);
|
|
|
|
rtw_hal_correct_tsf(adapter, adapter->hw_port, tsf);
|
|
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
/* Update buddy port's TSF if it is SoftAP/Mesh for beacon TX issue! */
|
|
if ((mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE
|
|
&& (rtw_mi_get_ap_num(adapter) || rtw_mi_get_mesh_num(adapter))
|
|
) {
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
int i;
|
|
_adapter *iface;
|
|
|
|
for (i = 0; i < dvobj->iface_nums; i++) {
|
|
iface = dvobj->padapters[i];
|
|
if (!iface)
|
|
continue;
|
|
if (iface == adapter)
|
|
continue;
|
|
|
|
#ifdef CONFIG_AP_MODE
|
|
if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))
|
|
&& check_fwstate(&iface->mlmepriv, WIFI_ASOC_STATE) == _TRUE
|
|
) {
|
|
rtw_hal_correct_tsf(iface, iface->hw_port, tsf);
|
|
#ifdef CONFIG_TSF_RESET_OFFLOAD
|
|
if (rtw_hal_reset_tsf(iface, iface->hw_port) == _FAIL)
|
|
RTW_INFO("%s-[ERROR] "ADPT_FMT" Reset port%d TSF fail\n"
|
|
, __func__, ADPT_ARG(iface), iface->hw_port);
|
|
#endif /* CONFIG_TSF_RESET_OFFLOAD*/
|
|
#ifdef CONFIG_TSF_SYNC
|
|
if(iface->hw_port == HW_PORT0)
|
|
rtw_write8(iface, REG_DUAL_TSF_RST, rtw_read8(iface, REG_DUAL_TSF_RST) | BIT(2));
|
|
else if(iface->hw_port == HW_PORT1)
|
|
rtw_write8(iface, REG_DUAL_TSF_RST, rtw_read8(iface, REG_DUAL_TSF_RST) | BIT(3));
|
|
#endif
|
|
}
|
|
#endif /* CONFIG_AP_MODE */
|
|
}
|
|
}
|
|
#endif /* CONFIG_CONCURRENT_MODE */
|
|
if ((mlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE
|
|
|| (mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)
|
|
ResumeTxBeacon(adapter);
|
|
}
|
|
#endif /*#ifdef CONFIG_MI_WITH_MBSSID_CAM*/
|
|
#endif /*#ifdef CONFIG_HW_P0_TSF_SYNC*/
|
|
#endif /*#ifndef CONFIG_HAS_HW_VAR_CORRECT_TSF*/
|
|
|
|
u64 rtw_hal_get_tsftr_by_port(_adapter *adapter, u8 port)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
u64 tsftr = 0;
|
|
|
|
if (port >= hal_spec->port_num) {
|
|
RTW_ERR("%s invalid port(%d) \n", __func__, port);
|
|
goto exit;
|
|
}
|
|
|
|
switch (rtw_get_chip_type(adapter)) {
|
|
#if defined(CONFIG_RTL8814B)
|
|
case RTL8814B:
|
|
{
|
|
u8 val8;
|
|
|
|
/* 0x1500[6:4] - BIT_BCN_TIMER_SEL_FWRD_V1 */
|
|
val8 = rtw_read8(adapter, REG_PORT_CTRL_SEL);
|
|
val8 &= ~0x70;
|
|
val8 |= port << 4;
|
|
rtw_write8(adapter, REG_PORT_CTRL_SEL, val8);
|
|
|
|
tsftr = rtw_read32(adapter, REG_TSFTR_HIGH);
|
|
tsftr = tsftr << 32;
|
|
tsftr |= rtw_read32(adapter, REG_TSFTR_LOW);
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(CONFIG_RTL8814A) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C)
|
|
case RTL8814A:
|
|
case RTL8822B:
|
|
case RTL8821C:
|
|
case RTL8822C:
|
|
{
|
|
u8 val8;
|
|
|
|
/* 0x554[30:28] - BIT_BCN_TIMER_SEL_FWRD */
|
|
val8 = rtw_read8(adapter, REG_MBSSID_BCN_SPACE + 3);
|
|
val8 &= 0x8F;
|
|
val8 |= port << 4;
|
|
rtw_write8(adapter, REG_MBSSID_BCN_SPACE + 3, val8);
|
|
|
|
tsftr = rtw_read32(adapter, REG_TSFTR + 4);
|
|
tsftr = tsftr << 32;
|
|
tsftr |= rtw_read32(adapter, REG_TSFTR);
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
#if defined(CONFIG_RTL8188E) || defined(CONFIG_RTL8188F) || defined(CONFIG_RTL8188GTV) \
|
|
|| defined(CONFIG_RTL8192E) || defined(CONFIG_RTL8192F) \
|
|
|| defined(CONFIG_RTL8723B) || defined(CONFIG_RTL8703B) || defined(CONFIG_RTL8723D) \
|
|
|| defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) \
|
|
|| defined(CONFIG_RTL8710B)
|
|
case RTL8188E:
|
|
case RTL8188F:
|
|
case RTL8188GTV:
|
|
case RTL8192E:
|
|
case RTL8192F:
|
|
case RTL8723B:
|
|
case RTL8703B:
|
|
case RTL8723D:
|
|
case RTL8812:
|
|
case RTL8821:
|
|
case RTL8710B:
|
|
{
|
|
u32 addr;
|
|
|
|
if (port == HW_PORT0)
|
|
addr = REG_TSFTR;
|
|
else if (port == HW_PORT1)
|
|
addr = REG_TSFTR1;
|
|
else {
|
|
RTW_ERR("%s unknown port(%d) \n", __func__, port);
|
|
goto exit;
|
|
}
|
|
|
|
tsftr = rtw_read32(adapter, addr + 4);
|
|
tsftr = tsftr << 32;
|
|
tsftr |= rtw_read32(adapter, addr);
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
RTW_ERR("%s unknow chip type\n", __func__);
|
|
}
|
|
|
|
exit:
|
|
return tsftr;
|
|
}
|
|
|
|
#ifdef CONFIG_TDLS
|
|
#ifdef CONFIG_TDLS_CH_SW
|
|
s32 rtw_hal_ch_sw_oper_offload(_adapter *padapter, u8 channel, u8 channel_offset, u16 bwmode)
|
|
{
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
|
|
u8 ch_sw_h2c_buf[4] = {0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
|
SET_H2CCMD_CH_SW_OPER_OFFLOAD_CH_NUM(ch_sw_h2c_buf, channel);
|
|
SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_MODE(ch_sw_h2c_buf, bwmode);
|
|
switch (bwmode) {
|
|
case CHANNEL_WIDTH_40:
|
|
SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_40M_SC(ch_sw_h2c_buf, channel_offset);
|
|
break;
|
|
case CHANNEL_WIDTH_80:
|
|
SET_H2CCMD_CH_SW_OPER_OFFLOAD_BW_80M_SC(ch_sw_h2c_buf, channel_offset);
|
|
break;
|
|
case CHANNEL_WIDTH_20:
|
|
default:
|
|
break;
|
|
}
|
|
SET_H2CCMD_CH_SW_OPER_OFFLOAD_RFE_TYPE(ch_sw_h2c_buf, pHalData->rfe_type);
|
|
|
|
return rtw_hal_fill_h2c_cmd(padapter, H2C_CHNL_SWITCH_OPER_OFFLOAD, sizeof(ch_sw_h2c_buf), ch_sw_h2c_buf);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_WMMPS_STA
|
|
void rtw_hal_update_uapsd_tid(_adapter *adapter)
|
|
{
|
|
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
|
|
struct qos_priv *pqospriv = &pmlmepriv->qospriv;
|
|
|
|
/* write complement of pqospriv->uapsd_tid to mac register 0x693 because
|
|
it's designed for "0" represents "enable" and "1" represents "disable" */
|
|
rtw_write8(adapter, REG_WMMPS_UAPSD_TID, (u8)(~pqospriv->uapsd_tid));
|
|
}
|
|
#endif /* CONFIG_WMMPS_STA */
|
|
|
|
#if defined(CONFIG_BT_COEXIST) && defined(CONFIG_FW_MULTI_PORT_SUPPORT)
|
|
/* For multi-port support, driver needs to inform the port ID to FW for btc operations */
|
|
s32 rtw_hal_set_wifi_btc_port_id_cmd(_adapter *adapter)
|
|
{
|
|
u8 h2c_buf[H2C_BTC_WL_PORT_ID_LEN] = {0};
|
|
u8 hw_port = rtw_hal_get_port(adapter);
|
|
|
|
SET_H2CCMD_BTC_WL_PORT_ID(h2c_buf, hw_port);
|
|
RTW_INFO("%s ("ADPT_FMT") - hw_port :%d\n", __func__, ADPT_ARG(adapter), hw_port);
|
|
return rtw_hal_fill_h2c_cmd(adapter, H2C_BTC_WL_PORT_ID, H2C_BTC_WL_PORT_ID_LEN, h2c_buf);
|
|
}
|
|
#endif
|
|
|
|
#define LPS_ACTIVE_TIMEOUT 50 /*number of times*/
|
|
void rtw_lps_state_chk(_adapter *adapter, u8 ps_mode)
|
|
{
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
struct sta_priv *pstapriv = &adapter->stapriv;
|
|
struct sta_info *psta = NULL;
|
|
u8 ps_ready = _FALSE;
|
|
s8 leave_wait_count = LPS_ACTIVE_TIMEOUT;
|
|
|
|
if (ps_mode == PS_MODE_ACTIVE) {
|
|
#ifdef CONFIG_LPS_ACK
|
|
if (rtw_sctx_wait(&pwrpriv->lps_ack_sctx, __func__)) {
|
|
if (pwrpriv->lps_ack_status > 0) {
|
|
psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
|
|
if (psta != NULL) {
|
|
if(issue_nulldata(adapter, psta->cmn.mac_addr, PS_MODE_ACTIVE, 3, 1) == _FAIL)
|
|
RTW_INFO(FUNC_ADPT_FMT" LPS state sync not yet finished.\n", FUNC_ADPT_ARG(adapter));
|
|
}
|
|
}
|
|
} else {
|
|
RTW_WARN("LPS sctx query timeout, operation abort!!\n");
|
|
return;
|
|
}
|
|
pwrpriv->lps_ack_status = -1;
|
|
#else
|
|
do {
|
|
if ((rtw_read8(adapter, REG_TCR) & BIT_PWRBIT_OW_EN) == 0) {
|
|
ps_ready = _TRUE;
|
|
break;
|
|
}
|
|
rtw_msleep_os(1);
|
|
} while (leave_wait_count--);
|
|
|
|
if (ps_ready == _FALSE) {
|
|
RTW_WARN(FUNC_ADPT_FMT" Power Bit Control is still in HW!\n", FUNC_ADPT_ARG(adapter));
|
|
return;
|
|
}
|
|
#endif /* CONFIG_LPS_ACK */
|
|
}
|
|
}
|
|
|
|
void rtw_var_set_basic_rate(PADAPTER padapter, u8 *val) {
|
|
|
|
PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
|
|
struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info;
|
|
u16 input_b = 0, masked = 0, ioted = 0, BrateCfg = 0;
|
|
u16 rrsr_2g_force_mask = RRSR_CCK_RATES;
|
|
u16 rrsr_2g_allow_mask = (RRSR_24M | RRSR_12M | RRSR_6M | RRSR_CCK_RATES);
|
|
#if CONFIG_IEEE80211_BAND_5GHZ
|
|
u16 rrsr_5g_force_mask = (RRSR_6M);
|
|
u16 rrsr_5g_allow_mask = (RRSR_OFDM_RATES);
|
|
#endif
|
|
u32 temp_RRSR;
|
|
|
|
HalSetBrateCfg(padapter, val, &BrateCfg);
|
|
input_b = BrateCfg;
|
|
|
|
/* apply force and allow mask */
|
|
#if CONFIG_IEEE80211_BAND_5GHZ
|
|
if (pHalData->current_band_type != BAND_ON_2_4G) {
|
|
BrateCfg |= rrsr_5g_force_mask;
|
|
BrateCfg &= rrsr_5g_allow_mask;
|
|
} else
|
|
#endif
|
|
{ /* 2.4G */
|
|
BrateCfg |= rrsr_2g_force_mask;
|
|
BrateCfg &= rrsr_2g_allow_mask;
|
|
}
|
|
masked = BrateCfg;
|
|
|
|
#ifdef CONFIG_CMCC_TEST
|
|
BrateCfg |= (RRSR_11M | RRSR_5_5M | RRSR_1M); /* use 11M to send ACK */
|
|
BrateCfg |= (RRSR_24M | RRSR_18M | RRSR_12M); /*CMCC_OFDM_ACK 12/18/24M */
|
|
#endif
|
|
|
|
/* IOT consideration */
|
|
if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) {
|
|
/* if peer is cisco and didn't use ofdm rate, we enable 6M ack */
|
|
if ((BrateCfg & (RRSR_24M | RRSR_12M | RRSR_6M)) == 0)
|
|
BrateCfg |= RRSR_6M;
|
|
}
|
|
ioted = BrateCfg;
|
|
|
|
#ifdef CONFIG_NARROWBAND_SUPPORTING
|
|
if ((padapter->registrypriv.rtw_nb_config == RTW_NB_CONFIG_WIDTH_10)
|
|
|| (padapter->registrypriv.rtw_nb_config == RTW_NB_CONFIG_WIDTH_5)) {
|
|
BrateCfg &= ~RRSR_CCK_RATES;
|
|
BrateCfg |= RRSR_6M;
|
|
}
|
|
#endif
|
|
pHalData->BasicRateSet = BrateCfg;
|
|
|
|
RTW_INFO("HW_VAR_BASIC_RATE: %#x->%#x->%#x\n", input_b, masked, ioted);
|
|
|
|
/* Set RRSR rate table. */
|
|
temp_RRSR = rtw_read32(padapter, REG_RRSR);
|
|
temp_RRSR &=0xFFFF0000;
|
|
temp_RRSR |=BrateCfg;
|
|
rtw_phydm_set_rrsr(padapter, temp_RRSR, TRUE);
|
|
|
|
rtw_write8(padapter, REG_RRSR + 2, rtw_read8(padapter, REG_RRSR + 2) & 0xf0);
|
|
|
|
#if defined(CONFIG_RTL8188E)
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_INIT_RTS_RATE, (u8 *)&BrateCfg);
|
|
#endif
|
|
}
|
|
|
|
u8 SetHwReg(_adapter *adapter, u8 variable, u8 *val)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 ret = _SUCCESS;
|
|
|
|
switch (variable) {
|
|
case HW_VAR_MEDIA_STATUS: {
|
|
u8 net_type = *((u8 *)val);
|
|
|
|
rtw_hal_set_msr(adapter, net_type);
|
|
}
|
|
break;
|
|
case HW_VAR_DO_IQK:
|
|
if (*val)
|
|
hal_data->bNeedIQK = _TRUE;
|
|
else
|
|
hal_data->bNeedIQK = _FALSE;
|
|
break;
|
|
case HW_VAR_MAC_ADDR:
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM
|
|
rtw_hal_set_macaddr_mbid(adapter, val);
|
|
#else
|
|
rtw_hal_set_macaddr_port(adapter, val);
|
|
#endif
|
|
break;
|
|
case HW_VAR_BSSID:
|
|
rtw_hal_set_bssid(adapter, val);
|
|
break;
|
|
case HW_VAR_RCR:
|
|
ret = hw_var_rcr_config(adapter, *((u32 *)val));
|
|
break;
|
|
case HW_VAR_ON_RCR_AM:
|
|
hw_var_set_rcr_am(adapter, 1);
|
|
break;
|
|
case HW_VAR_OFF_RCR_AM:
|
|
hw_var_set_rcr_am(adapter, 0);
|
|
break;
|
|
case HW_VAR_BEACON_INTERVAL:
|
|
hw_var_set_bcn_interval(adapter, *(u16 *)val);
|
|
break;
|
|
#ifdef CONFIG_MBSSID_CAM
|
|
case HW_VAR_MBSSID_CAM_WRITE: {
|
|
u32 cmd = 0;
|
|
u32 *cam_val = (u32 *)val;
|
|
|
|
rtw_write32(adapter, REG_MBIDCAMCFG_1, cam_val[0]);
|
|
cmd = BIT_MBIDCAM_POLL | BIT_MBIDCAM_WT_EN | BIT_MBIDCAM_VALID | cam_val[1];
|
|
rtw_write32(adapter, REG_MBIDCAMCFG_2, cmd);
|
|
}
|
|
break;
|
|
case HW_VAR_MBSSID_CAM_CLEAR: {
|
|
u32 cmd;
|
|
u8 entry_id = *(u8 *)val;
|
|
|
|
rtw_write32(adapter, REG_MBIDCAMCFG_1, 0);
|
|
|
|
cmd = BIT_MBIDCAM_POLL | BIT_MBIDCAM_WT_EN | ((entry_id & MBIDCAM_ADDR_MASK) << MBIDCAM_ADDR_SHIFT);
|
|
rtw_write32(adapter, REG_MBIDCAMCFG_2, cmd);
|
|
}
|
|
break;
|
|
case HW_VAR_RCR_MBSSID_EN:
|
|
if (*((u8 *)val))
|
|
rtw_hal_rcr_add(adapter, RCR_ENMBID);
|
|
else
|
|
rtw_hal_rcr_clear(adapter, RCR_ENMBID);
|
|
break;
|
|
#endif
|
|
case HW_VAR_PORT_SWITCH:
|
|
hw_var_port_switch(adapter);
|
|
break;
|
|
case HW_VAR_INIT_RTS_RATE: {
|
|
u16 brate_cfg = *((u16 *)val);
|
|
u8 rate_index = 0;
|
|
HAL_VERSION *hal_ver = &hal_data->version_id;
|
|
|
|
if (IS_8188E(*hal_ver)) {
|
|
|
|
while (brate_cfg > 0x1) {
|
|
brate_cfg = (brate_cfg >> 1);
|
|
rate_index++;
|
|
}
|
|
rtw_write8(adapter, REG_INIRTS_RATE_SEL, rate_index);
|
|
} else
|
|
rtw_warn_on(1);
|
|
}
|
|
break;
|
|
case HW_VAR_SEC_CFG: {
|
|
u16 reg_scr_ori;
|
|
u16 reg_scr;
|
|
|
|
reg_scr = reg_scr_ori = rtw_read16(adapter, REG_SECCFG);
|
|
reg_scr |= (SCR_CHK_KEYID | SCR_RxDecEnable | SCR_TxEncEnable);
|
|
|
|
if (_rtw_camctl_chk_cap(adapter, SEC_CAP_CHK_BMC))
|
|
reg_scr |= SCR_CHK_BMC;
|
|
|
|
if (_rtw_camctl_chk_flags(adapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH))
|
|
reg_scr |= SCR_NoSKMC;
|
|
|
|
if (reg_scr != reg_scr_ori)
|
|
rtw_write16(adapter, REG_SECCFG, reg_scr);
|
|
}
|
|
break;
|
|
case HW_VAR_SEC_DK_CFG: {
|
|
struct security_priv *sec = &adapter->securitypriv;
|
|
u8 reg_scr = rtw_read8(adapter, REG_SECCFG);
|
|
|
|
if (val) { /* Enable default key related setting */
|
|
reg_scr |= SCR_TXBCUSEDK;
|
|
if (sec->dot11AuthAlgrthm != dot11AuthAlgrthm_8021X)
|
|
reg_scr |= (SCR_RxUseDK | SCR_TxUseDK);
|
|
} else /* Disable default key related setting */
|
|
reg_scr &= ~(SCR_RXBCUSEDK | SCR_TXBCUSEDK | SCR_RxUseDK | SCR_TxUseDK);
|
|
|
|
rtw_write8(adapter, REG_SECCFG, reg_scr);
|
|
}
|
|
break;
|
|
|
|
case HW_VAR_ASIX_IOT:
|
|
/* enable ASIX IOT function */
|
|
if (*((u8 *)val) == _TRUE) {
|
|
/* 0xa2e[0]=0 (disable rake receiver) */
|
|
rtw_write8(adapter, rCCK0_FalseAlarmReport + 2,
|
|
rtw_read8(adapter, rCCK0_FalseAlarmReport + 2) & ~(BIT0));
|
|
/* 0xa1c=0xa0 (reset channel estimation if signal quality is bad) */
|
|
rtw_write8(adapter, rCCK0_DSPParameter2, 0xa0);
|
|
} else {
|
|
/* restore reg:0xa2e, reg:0xa1c */
|
|
rtw_write8(adapter, rCCK0_FalseAlarmReport + 2,
|
|
rtw_read8(adapter, rCCK0_FalseAlarmReport + 2) | (BIT0));
|
|
rtw_write8(adapter, rCCK0_DSPParameter2, 0x00);
|
|
}
|
|
break;
|
|
#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
|
|
case HW_VAR_WOWLAN: {
|
|
struct wowlan_ioctl_param *poidparam;
|
|
|
|
poidparam = (struct wowlan_ioctl_param *)val;
|
|
switch (poidparam->subcode) {
|
|
#ifdef CONFIG_WOWLAN
|
|
case WOWLAN_PATTERN_CLEAN:
|
|
rtw_hal_dl_pattern(adapter, 2);
|
|
break;
|
|
case WOWLAN_ENABLE:
|
|
rtw_hal_wow_enable(adapter);
|
|
break;
|
|
case WOWLAN_DISABLE:
|
|
rtw_hal_wow_disable(adapter);
|
|
break;
|
|
#endif /*CONFIG_WOWLAN*/
|
|
#ifdef CONFIG_AP_WOWLAN
|
|
case WOWLAN_AP_ENABLE:
|
|
rtw_hal_ap_wow_enable(adapter);
|
|
break;
|
|
case WOWLAN_AP_DISABLE:
|
|
rtw_hal_ap_wow_disable(adapter);
|
|
break;
|
|
#endif /*CONFIG_AP_WOWLAN*/
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
#endif /*defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)*/
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_BCN_FUNC
|
|
case HW_VAR_BCN_FUNC:
|
|
hw_var_set_bcn_func(adapter, *val);
|
|
break;
|
|
#endif
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_MLME_DISCONNECT
|
|
case HW_VAR_MLME_DISCONNECT:
|
|
hw_var_set_mlme_disconnect(adapter);
|
|
break;
|
|
#endif
|
|
|
|
case HW_VAR_MLME_SITESURVEY:
|
|
hw_var_set_mlme_sitesurvey(adapter, *val);
|
|
#ifdef CONFIG_BT_COEXIST
|
|
if (hal_data->EEPROMBluetoothCoexist == 1)
|
|
rtw_btcoex_ScanNotify(adapter, *val ? _TRUE : _FALSE);
|
|
#endif
|
|
break;
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_MLME_JOIN
|
|
case HW_VAR_MLME_JOIN:
|
|
hw_var_set_mlme_join(adapter, *val);
|
|
break;
|
|
#endif
|
|
|
|
case HW_VAR_EN_HW_UPDATE_TSF:
|
|
rtw_hal_set_hw_update_tsf(adapter);
|
|
break;
|
|
#ifndef CONFIG_HAS_HW_VAR_CORRECT_TSF
|
|
case HW_VAR_CORRECT_TSF:
|
|
hw_var_set_correct_tsf(adapter, *val);
|
|
break;
|
|
#endif
|
|
|
|
#if defined(CONFIG_HW_P0_TSF_SYNC) && defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_MCC_MODE)
|
|
case HW_VAR_TSF_AUTO_SYNC:
|
|
if (*val == _TRUE)
|
|
hw_port0_tsf_sync_sel(adapter, _TRUE, adapter->hw_port, 50);
|
|
else
|
|
hw_port0_tsf_sync_sel(adapter, _FALSE, adapter->hw_port, 50);
|
|
break;
|
|
#endif
|
|
case HW_VAR_APFM_ON_MAC:
|
|
hal_data->bMacPwrCtrlOn = *val;
|
|
RTW_INFO("%s: bMacPwrCtrlOn=%d\n", __func__, hal_data->bMacPwrCtrlOn);
|
|
break;
|
|
#ifdef CONFIG_WMMPS_STA
|
|
case HW_VAR_UAPSD_TID:
|
|
rtw_hal_update_uapsd_tid(adapter);
|
|
break;
|
|
#endif /* CONFIG_WMMPS_STA */
|
|
#ifdef CONFIG_LPS_PG
|
|
case HW_VAR_LPS_PG_HANDLE:
|
|
rtw_hal_lps_pg_handler(adapter, *val);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_LPS_LCLK_WD_TIMER
|
|
case HW_VAR_DM_IN_LPS_LCLK:
|
|
rtw_phydm_wd_lps_lclk_hdl(adapter);
|
|
break;
|
|
#endif
|
|
case HW_VAR_ENABLE_RX_BAR:
|
|
if (*val == _TRUE) {
|
|
/* enable RX BAR */
|
|
u16 val16 = rtw_read16(adapter, REG_RXFLTMAP1);
|
|
|
|
val16 |= BIT(8);
|
|
rtw_write16(adapter, REG_RXFLTMAP1, val16);
|
|
} else {
|
|
/* disable RX BAR */
|
|
u16 val16 = rtw_read16(adapter, REG_RXFLTMAP1);
|
|
|
|
val16 &= (~BIT(8));
|
|
rtw_write16(adapter, REG_RXFLTMAP1, val16);
|
|
}
|
|
RTW_INFO("[HW_VAR_ENABLE_RX_BAR] 0x%02X=0x%02X\n",
|
|
REG_RXFLTMAP1, rtw_read16(adapter, REG_RXFLTMAP1));
|
|
break;
|
|
case HW_VAR_HCI_SUS_STATE:
|
|
hal_data->hci_sus_state = *(u8 *)val;
|
|
RTW_INFO("%s: hci_sus_state=%u\n", __func__, hal_data->hci_sus_state);
|
|
break;
|
|
#if defined(CONFIG_AP_MODE) && defined(CONFIG_FW_HANDLE_TXBCN) && defined(CONFIG_SUPPORT_MULTI_BCN)
|
|
case HW_VAR_BCN_HEAD_SEL:
|
|
{
|
|
u8 vap_id = *(u8 *)val;
|
|
|
|
if ((vap_id >= CONFIG_LIMITED_AP_NUM) && (vap_id != 0xFF)) {
|
|
RTW_ERR(ADPT_FMT " vap_id(%d:%d) is invalid\n", ADPT_ARG(adapter),vap_id, adapter->vap_id);
|
|
rtw_warn_on(1);
|
|
}
|
|
if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {
|
|
u16 drv_pg_bndy = 0, bcn_addr = 0;
|
|
u32 page_size = 0;
|
|
|
|
/*rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_BOUNDARY, &drv_pg_bndy);*/
|
|
rtw_halmac_get_rsvd_drv_pg_bndy(adapter_to_dvobj(adapter), &drv_pg_bndy);
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, (u8 *)&page_size);
|
|
|
|
if (vap_id != 0xFF)
|
|
bcn_addr = drv_pg_bndy + (vap_id * (MAX_BEACON_LEN / page_size));
|
|
else
|
|
bcn_addr = drv_pg_bndy;
|
|
RTW_INFO(ADPT_FMT" vap_id(%d) change BCN HEAD to 0x%04x\n",
|
|
ADPT_ARG(adapter), vap_id, bcn_addr);
|
|
rtw_write16(adapter, REG_FIFOPAGE_CTRL_2,
|
|
(bcn_addr & BIT_MASK_BCN_HEAD_1_V1) | BIT_BCN_VALID_V1);
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
case HW_VAR_LPS_STATE_CHK :
|
|
rtw_lps_state_chk(adapter, *(u8 *)val);
|
|
break;
|
|
|
|
#ifdef CONFIG_RTS_FULL_BW
|
|
case HW_VAR_SET_RTS_BW:
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
rtw_halmac_set_rts_full_bw(adapter_to_dvobj(adapter), (*val));
|
|
#else
|
|
u8 temp;
|
|
if(*val)
|
|
temp = (( rtw_read8(adapter, REG_INIRTS_RATE_SEL)) | BIT5 );
|
|
else
|
|
temp = (( rtw_read8(adapter, REG_INIRTS_RATE_SEL)) & (~BIT5));
|
|
rtw_write8(adapter, REG_INIRTS_RATE_SEL, temp);
|
|
/*RTW_INFO("HW_VAR_SET_RTS_BW val=%u REG480=0x%x\n", *val, rtw_read8(adapter, REG_INIRTS_RATE_SEL));*/
|
|
#endif
|
|
}
|
|
break;
|
|
#endif/*CONFIG_RTS_FULL_BW*/
|
|
#if defined(CONFIG_PCI_HCI)
|
|
case HW_VAR_ENSWBCN:
|
|
if (*val == _TRUE) {
|
|
rtw_write8(adapter, REG_CR + 1,
|
|
rtw_read8(adapter, REG_CR + 1) | BIT(0));
|
|
} else
|
|
rtw_write8(adapter, REG_CR + 1,
|
|
rtw_read8(adapter, REG_CR + 1) & ~BIT(0));
|
|
break;
|
|
#endif
|
|
case HW_VAR_BCN_EARLY_C2H_RPT:
|
|
rtw_hal_set_fw_bcn_early_c2h_rpt_cmd(adapter, *(u8 *)val);
|
|
break;
|
|
default:
|
|
if (0)
|
|
RTW_PRINT(FUNC_ADPT_FMT" variable(%d) not defined!\n",
|
|
FUNC_ADPT_ARG(adapter), variable);
|
|
ret = _FAIL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void GetHwReg(_adapter *adapter, u8 variable, u8 *val)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u64 val64;
|
|
|
|
|
|
switch (variable) {
|
|
case HW_VAR_MAC_ADDR:
|
|
#ifndef CONFIG_MI_WITH_MBSSID_CAM
|
|
rtw_hal_get_macaddr_port(adapter, val);
|
|
#endif
|
|
break;
|
|
case HW_VAR_BASIC_RATE:
|
|
*((u16 *)val) = hal_data->BasicRateSet;
|
|
break;
|
|
case HW_VAR_MEDIA_STATUS:
|
|
rtw_hal_get_msr(adapter, val);
|
|
break;
|
|
case HW_VAR_DO_IQK:
|
|
*val = hal_data->bNeedIQK;
|
|
break;
|
|
case HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO:
|
|
if (hal_is_band_support(adapter, BAND_ON_5G))
|
|
*val = _TRUE;
|
|
else
|
|
*val = _FALSE;
|
|
break;
|
|
case HW_VAR_APFM_ON_MAC:
|
|
*val = hal_data->bMacPwrCtrlOn;
|
|
break;
|
|
case HW_VAR_RCR:
|
|
hw_var_rcr_get(adapter, (u32 *)val);
|
|
break;
|
|
case HW_VAR_FWLPS_RF_ON:
|
|
/* When we halt NIC, we should check if FW LPS is leave. */
|
|
if (rtw_is_surprise_removed(adapter)
|
|
|| (adapter_to_pwrctl(adapter)->rf_pwrstate == rf_off)
|
|
) {
|
|
/*
|
|
* If it is in HW/SW Radio OFF or IPS state,
|
|
* we do not check Fw LPS Leave,
|
|
* because Fw is unload.
|
|
*/
|
|
*val = _TRUE;
|
|
} else {
|
|
u32 rcr = 0;
|
|
|
|
rtw_hal_get_hwreg(adapter, HW_VAR_RCR, (u8 *)&rcr);
|
|
if (rcr & (RCR_UC_MD_EN | RCR_BC_MD_EN | RCR_TIM_PARSER_EN))
|
|
*val = _FALSE;
|
|
else
|
|
*val = _TRUE;
|
|
}
|
|
break;
|
|
|
|
case HW_VAR_HCI_SUS_STATE:
|
|
*((u8 *)val) = hal_data->hci_sus_state;
|
|
break;
|
|
|
|
#ifndef CONFIG_HAS_HW_VAR_BCN_CTRL_ADDR
|
|
case HW_VAR_BCN_CTRL_ADDR:
|
|
*((u32 *)val) = hw_bcn_ctrl_addr(adapter, adapter->hw_port);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_WAPI_SUPPORT
|
|
case HW_VAR_CAM_EMPTY_ENTRY: {
|
|
u8 ucIndex = *((u8 *)val);
|
|
u8 i;
|
|
u32 ulCommand = 0;
|
|
u32 ulContent = 0;
|
|
u32 ulEncAlgo = CAM_AES;
|
|
|
|
for (i = 0; i < CAM_CONTENT_COUNT; i++) {
|
|
/* filled id in CAM config 2 byte */
|
|
if (i == 0)
|
|
ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo) << 2);
|
|
else
|
|
ulContent = 0;
|
|
/* polling bit, and No Write enable, and address */
|
|
ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
|
|
ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
|
|
/* write content 0 is equall to mark invalid */
|
|
rtw_write32(adapter, REG_CAMWRITE, ulContent); /* delay_ms(40); */
|
|
rtw_write32(adapter, REG_CAMCMD, ulCommand); /* delay_ms(40); */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
default:
|
|
if (0)
|
|
RTW_PRINT(FUNC_ADPT_FMT" variable(%d) not defined!\n",
|
|
FUNC_ADPT_ARG(adapter), variable);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static u32 _get_page_size(struct _ADAPTER *a)
|
|
{
|
|
#ifdef RTW_HALMAC
|
|
struct dvobj_priv *d;
|
|
u32 size = 0;
|
|
int err = 0;
|
|
|
|
|
|
d = adapter_to_dvobj(a);
|
|
|
|
err = rtw_halmac_get_page_size(d, &size);
|
|
if (!err)
|
|
return size;
|
|
|
|
RTW_WARN(FUNC_ADPT_FMT ": Fail to get Page size!!(err=%d)\n",
|
|
FUNC_ADPT_ARG(a), err);
|
|
#endif /* RTW_HALMAC */
|
|
|
|
return PAGE_SIZE_128;
|
|
}
|
|
|
|
u8
|
|
SetHalDefVar(_adapter *adapter, HAL_DEF_VARIABLE variable, void *value)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 bResult = _SUCCESS;
|
|
|
|
switch (variable) {
|
|
|
|
case HAL_DEF_DBG_DUMP_RXPKT:
|
|
hal_data->bDumpRxPkt = *((u8 *)value);
|
|
break;
|
|
case HAL_DEF_DBG_DUMP_TXPKT:
|
|
hal_data->bDumpTxPkt = *((u8 *)value);
|
|
break;
|
|
case HAL_DEF_ANT_DETECT:
|
|
hal_data->AntDetection = *((u8 *)value);
|
|
break;
|
|
default:
|
|
RTW_PRINT("%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n", __FUNCTION__, variable);
|
|
bResult = _FAIL;
|
|
break;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
#ifdef CONFIG_BEAMFORMING
|
|
u8 rtw_hal_query_txbfer_rf_num(_adapter *adapter)
|
|
{
|
|
struct registry_priv *pregistrypriv = &adapter->registrypriv;
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
|
|
if ((pregistrypriv->beamformer_rf_num) && (IS_HARDWARE_TYPE_8814AE(adapter) || IS_HARDWARE_TYPE_8814AU(adapter) || IS_HARDWARE_TYPE_8822BU(adapter) || IS_HARDWARE_TYPE_8821C(adapter)))
|
|
return pregistrypriv->beamformer_rf_num;
|
|
else if (IS_HARDWARE_TYPE_8814AE(adapter)
|
|
#if 0
|
|
#if defined(CONFIG_USB_HCI)
|
|
|| (IS_HARDWARE_TYPE_8814AU(adapter) && (pUsbModeMech->CurUsbMode == 2 || pUsbModeMech->HubUsbMode == 2)) /* for USB3.0 */
|
|
#endif
|
|
#endif
|
|
) {
|
|
/*BF cap provided by Yu Chen, Sean, 2015, 01 */
|
|
if (hal_data->rf_type == RF_3T3R)
|
|
return 2;
|
|
else if (hal_data->rf_type == RF_4T4R)
|
|
return 3;
|
|
else
|
|
return 1;
|
|
} else
|
|
return 1;
|
|
|
|
}
|
|
u8 rtw_hal_query_txbfee_rf_num(_adapter *adapter)
|
|
{
|
|
struct registry_priv *pregistrypriv = &adapter->registrypriv;
|
|
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
|
|
if ((pregistrypriv->beamformee_rf_num) && (IS_HARDWARE_TYPE_8814AE(adapter) || IS_HARDWARE_TYPE_8814AU(adapter) || IS_HARDWARE_TYPE_8822BU(adapter) || IS_HARDWARE_TYPE_8821C(adapter)))
|
|
return pregistrypriv->beamformee_rf_num;
|
|
else if (IS_HARDWARE_TYPE_8814AE(adapter) || IS_HARDWARE_TYPE_8814AU(adapter)) {
|
|
if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM)
|
|
return 2;
|
|
else
|
|
return 2;/*TODO: May be 3 in the future, by ChenYu. */
|
|
} else
|
|
return 1;
|
|
|
|
}
|
|
#ifdef RTW_BEAMFORMING_VERSION_2
|
|
void rtw_hal_beamforming_config_csirate(PADAPTER adapter)
|
|
{
|
|
struct dm_struct *p_dm_odm;
|
|
struct beamforming_info *bf_info;
|
|
u8 fix_rate_enable = 0;
|
|
u8 new_csi_rate_idx;
|
|
u8 rrsr_54_en;
|
|
u32 temp_rrsr;
|
|
|
|
/* Acting as BFee */
|
|
if (IS_BEAMFORMEE(adapter)) {
|
|
#if 0
|
|
/* Do not enable now because it will affect MU performance and CTS/BA rate. 2016.07.19. by tynli. [PCIE-1660] */
|
|
if (IS_HARDWARE_TYPE_8821C(Adapter))
|
|
FixRateEnable = 1; /* Support after 8821C */
|
|
#endif
|
|
|
|
p_dm_odm = adapter_to_phydm(adapter);
|
|
bf_info = GET_BEAMFORM_INFO(adapter);
|
|
|
|
rtw_halmac_bf_cfg_csi_rate(adapter_to_dvobj(adapter),
|
|
p_dm_odm->rssi_min,
|
|
bf_info->cur_csi_rpt_rate,
|
|
fix_rate_enable, &new_csi_rate_idx, &rrsr_54_en);
|
|
|
|
temp_rrsr = rtw_read32(adapter, REG_RRSR);
|
|
if (rrsr_54_en == 1)
|
|
temp_rrsr |= RRSR_54M;
|
|
else if (rrsr_54_en == 0)
|
|
temp_rrsr &= ~RRSR_54M;
|
|
rtw_phydm_set_rrsr(adapter, temp_rrsr, FALSE);
|
|
|
|
if (new_csi_rate_idx != bf_info->cur_csi_rpt_rate)
|
|
bf_info->cur_csi_rpt_rate = new_csi_rate_idx;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
u8
|
|
GetHalDefVar(_adapter *adapter, HAL_DEF_VARIABLE variable, void *value)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 bResult = _SUCCESS;
|
|
|
|
switch (variable) {
|
|
case HAL_DEF_UNDERCORATEDSMOOTHEDPWDB: {
|
|
struct mlme_priv *pmlmepriv;
|
|
struct sta_priv *pstapriv;
|
|
struct sta_info *psta;
|
|
|
|
pmlmepriv = &adapter->mlmepriv;
|
|
pstapriv = &adapter->stapriv;
|
|
psta = rtw_get_stainfo(pstapriv, pmlmepriv->cur_network.network.MacAddress);
|
|
if (psta)
|
|
*((int *)value) = psta->cmn.rssi_stat.rssi;
|
|
}
|
|
break;
|
|
case HAL_DEF_DBG_DUMP_RXPKT:
|
|
*((u8 *)value) = hal_data->bDumpRxPkt;
|
|
break;
|
|
case HAL_DEF_DBG_DUMP_TXPKT:
|
|
*((u8 *)value) = hal_data->bDumpTxPkt;
|
|
break;
|
|
case HAL_DEF_ANT_DETECT:
|
|
*((u8 *)value) = hal_data->AntDetection;
|
|
break;
|
|
case HAL_DEF_TX_PAGE_SIZE:
|
|
*((u32 *)value) = _get_page_size(adapter);
|
|
break;
|
|
case HAL_DEF_TX_STBC:
|
|
#ifdef CONFIG_ALPHA_SMART_ANTENNA
|
|
*(u8 *)value = 0;
|
|
#else
|
|
*(u8 *)value = hal_data->max_tx_cnt > 1 ? 1 : 0;
|
|
#endif
|
|
break;
|
|
case HAL_DEF_EXPLICIT_BEAMFORMER:
|
|
case HAL_DEF_EXPLICIT_BEAMFORMEE:
|
|
case HAL_DEF_VHT_MU_BEAMFORMER:
|
|
case HAL_DEF_VHT_MU_BEAMFORMEE:
|
|
*(u8 *)value = _FALSE;
|
|
break;
|
|
#ifdef CONFIG_BEAMFORMING
|
|
case HAL_DEF_BEAMFORMER_CAP:
|
|
*(u8 *)value = rtw_hal_query_txbfer_rf_num(adapter);
|
|
break;
|
|
case HAL_DEF_BEAMFORMEE_CAP:
|
|
*(u8 *)value = rtw_hal_query_txbfee_rf_num(adapter);
|
|
break;
|
|
#endif
|
|
default:
|
|
RTW_PRINT("%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n", __FUNCTION__, variable);
|
|
bResult = _FAIL;
|
|
break;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/*
|
|
* Description:
|
|
* Translate a character to hex digit.
|
|
* */
|
|
u32
|
|
MapCharToHexDigit(
|
|
char chTmp
|
|
)
|
|
{
|
|
if (chTmp >= '0' && chTmp <= '9')
|
|
return chTmp - '0';
|
|
else if (chTmp >= 'a' && chTmp <= 'f')
|
|
return 10 + (chTmp - 'a');
|
|
else if (chTmp >= 'A' && chTmp <= 'F')
|
|
return 10 + (chTmp - 'A');
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Description:
|
|
* Parse hex number from the string pucStr.
|
|
* */
|
|
BOOLEAN
|
|
GetHexValueFromString(
|
|
char *szStr,
|
|
u32 *pu4bVal,
|
|
u32 *pu4bMove
|
|
)
|
|
{
|
|
char *szScan = szStr;
|
|
|
|
/* Check input parameter. */
|
|
if (szStr == NULL || pu4bVal == NULL || pu4bMove == NULL) {
|
|
RTW_INFO("GetHexValueFromString(): Invalid inpur argumetns! szStr: %p, pu4bVal: %p, pu4bMove: %p\n", szStr, pu4bVal, pu4bMove);
|
|
return _FALSE;
|
|
}
|
|
|
|
/* Initialize output. */
|
|
*pu4bMove = 0;
|
|
*pu4bVal = 0;
|
|
|
|
/* Skip leading space. */
|
|
while (*szScan != '\0' &&
|
|
(*szScan == ' ' || *szScan == '\t')) {
|
|
szScan++;
|
|
(*pu4bMove)++;
|
|
}
|
|
|
|
/* Skip leading '0x' or '0X'. */
|
|
if (*szScan == '0' && (*(szScan + 1) == 'x' || *(szScan + 1) == 'X')) {
|
|
szScan += 2;
|
|
(*pu4bMove) += 2;
|
|
}
|
|
|
|
/* Check if szScan is now pointer to a character for hex digit, */
|
|
/* if not, it means this is not a valid hex number. */
|
|
if (!IsHexDigit(*szScan))
|
|
return _FALSE;
|
|
|
|
/* Parse each digit. */
|
|
do {
|
|
(*pu4bVal) <<= 4;
|
|
*pu4bVal += MapCharToHexDigit(*szScan);
|
|
|
|
szScan++;
|
|
(*pu4bMove)++;
|
|
} while (IsHexDigit(*szScan));
|
|
|
|
return _TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
GetFractionValueFromString(
|
|
char *szStr,
|
|
u8 *pInteger,
|
|
u8 *pFraction,
|
|
u32 *pu4bMove
|
|
)
|
|
{
|
|
char *szScan = szStr;
|
|
|
|
/* Initialize output. */
|
|
*pu4bMove = 0;
|
|
*pInteger = 0;
|
|
*pFraction = 0;
|
|
|
|
/* Skip leading space. */
|
|
while (*szScan != '\0' && (*szScan == ' ' || *szScan == '\t')) {
|
|
++szScan;
|
|
++(*pu4bMove);
|
|
}
|
|
|
|
if (*szScan < '0' || *szScan > '9')
|
|
return _FALSE;
|
|
|
|
/* Parse each digit. */
|
|
do {
|
|
(*pInteger) *= 10;
|
|
*pInteger += (*szScan - '0');
|
|
|
|
++szScan;
|
|
++(*pu4bMove);
|
|
|
|
if (*szScan == '.') {
|
|
++szScan;
|
|
++(*pu4bMove);
|
|
|
|
if (*szScan < '0' || *szScan > '9')
|
|
return _FALSE;
|
|
|
|
*pFraction += (*szScan - '0') * 10;
|
|
++szScan;
|
|
++(*pu4bMove);
|
|
|
|
if (*szScan >= '0' && *szScan <= '9') {
|
|
*pFraction += *szScan - '0';
|
|
++szScan;
|
|
++(*pu4bMove);
|
|
}
|
|
return _TRUE;
|
|
}
|
|
} while (*szScan >= '0' && *szScan <= '9');
|
|
|
|
return _TRUE;
|
|
}
|
|
|
|
/*
|
|
* Description:
|
|
* Return TRUE if szStr is comment out with leading " */ /* ".
|
|
* */
|
|
BOOLEAN
|
|
IsCommentString(
|
|
char *szStr
|
|
)
|
|
{
|
|
if (*szStr == '/' && *(szStr + 1) == '/')
|
|
return _TRUE;
|
|
else
|
|
return _FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
GetU1ByteIntegerFromStringInDecimal(
|
|
char *Str,
|
|
u8 *pInt
|
|
)
|
|
{
|
|
u16 i = 0;
|
|
*pInt = 0;
|
|
|
|
while (Str[i] != '\0') {
|
|
if (Str[i] >= '0' && Str[i] <= '9') {
|
|
*pInt *= 10;
|
|
*pInt += (Str[i] - '0');
|
|
} else
|
|
return _FALSE;
|
|
++i;
|
|
}
|
|
|
|
return _TRUE;
|
|
}
|
|
|
|
/* <20121004, Kordan> For example,
|
|
* ParseQualifiedString(inString, 0, outString, '[', ']') gets "Kordan" from a string "Hello [Kordan]".
|
|
* If RightQualifier does not exist, it will hang on in the while loop */
|
|
BOOLEAN
|
|
ParseQualifiedString(
|
|
char *In,
|
|
u32 *Start,
|
|
char *Out,
|
|
char LeftQualifier,
|
|
char RightQualifier
|
|
)
|
|
{
|
|
u32 i = 0, j = 0;
|
|
char c = In[(*Start)++];
|
|
|
|
if (c != LeftQualifier)
|
|
return _FALSE;
|
|
|
|
i = (*Start);
|
|
c = In[(*Start)++];
|
|
while (c != RightQualifier && c != '\0')
|
|
c = In[(*Start)++];
|
|
|
|
if (c == '\0')
|
|
return _FALSE;
|
|
|
|
j = (*Start) - 2;
|
|
strncpy((char *)Out, (const char *)(In + i), j - i + 1);
|
|
|
|
return _TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
isAllSpaceOrTab(
|
|
u8 *data,
|
|
u8 size
|
|
)
|
|
{
|
|
u8 cnt = 0, NumOfSpaceAndTab = 0;
|
|
|
|
while (size > cnt) {
|
|
if (data[cnt] == ' ' || data[cnt] == '\t' || data[cnt] == '\0')
|
|
++NumOfSpaceAndTab;
|
|
|
|
++cnt;
|
|
}
|
|
|
|
return size == NumOfSpaceAndTab;
|
|
}
|
|
|
|
|
|
void rtw_hal_check_rxfifo_full(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *psdpriv = adapter->dvobj;
|
|
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
|
|
struct registry_priv *regsty = &adapter->registrypriv;
|
|
int save_cnt = _FALSE;
|
|
|
|
if (regsty->check_hw_status == 1) {
|
|
/* switch counter to RX fifo */
|
|
if (IS_8188E(pHalData->version_id) ||
|
|
IS_8188F(pHalData->version_id) ||
|
|
IS_8188GTV(pHalData->version_id) ||
|
|
IS_8812_SERIES(pHalData->version_id) ||
|
|
IS_8821_SERIES(pHalData->version_id) ||
|
|
IS_8723B_SERIES(pHalData->version_id) ||
|
|
IS_8192E(pHalData->version_id) ||
|
|
IS_8703B_SERIES(pHalData->version_id) ||
|
|
IS_8723D_SERIES(pHalData->version_id) ||
|
|
IS_8192F_SERIES(pHalData->version_id) ||
|
|
IS_8822C_SERIES(pHalData->version_id)) {
|
|
rtw_write8(adapter, REG_RXERR_RPT + 3, rtw_read8(adapter, REG_RXERR_RPT + 3) | 0xa0);
|
|
save_cnt = _TRUE;
|
|
} else {
|
|
/* todo: other chips */
|
|
}
|
|
|
|
|
|
if (save_cnt) {
|
|
pdbgpriv->dbg_rx_fifo_last_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow;
|
|
pdbgpriv->dbg_rx_fifo_curr_overflow = rtw_read16(adapter, REG_RXERR_RPT);
|
|
pdbgpriv->dbg_rx_fifo_diff_overflow = pdbgpriv->dbg_rx_fifo_curr_overflow - pdbgpriv->dbg_rx_fifo_last_overflow;
|
|
} else {
|
|
/* special value to indicate no implementation */
|
|
pdbgpriv->dbg_rx_fifo_last_overflow = 1;
|
|
pdbgpriv->dbg_rx_fifo_curr_overflow = 1;
|
|
pdbgpriv->dbg_rx_fifo_diff_overflow = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void linked_info_dump(_adapter *padapter, u8 benable)
|
|
{
|
|
struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
|
|
|
|
if (padapter->bLinkInfoDump == benable)
|
|
return;
|
|
|
|
RTW_INFO("%s %s\n", __FUNCTION__, (benable) ? "enable" : "disable");
|
|
|
|
if (benable) {
|
|
#ifdef CONFIG_LPS
|
|
pwrctrlpriv->org_power_mgnt = pwrctrlpriv->power_mgnt;/* keep org value */
|
|
rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
|
|
#endif
|
|
|
|
#ifdef CONFIG_IPS
|
|
pwrctrlpriv->ips_org_mode = pwrctrlpriv->ips_mode;/* keep org value */
|
|
rtw_pm_set_ips(padapter, IPS_NONE);
|
|
#endif
|
|
} else {
|
|
#ifdef CONFIG_IPS
|
|
rtw_pm_set_ips(padapter, pwrctrlpriv->ips_org_mode);
|
|
#endif /* CONFIG_IPS */
|
|
|
|
#ifdef CONFIG_LPS
|
|
rtw_pm_set_lps(padapter, pwrctrlpriv->org_power_mgnt);
|
|
#endif /* CONFIG_LPS */
|
|
}
|
|
padapter->bLinkInfoDump = benable ;
|
|
}
|
|
|
|
#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
|
|
void rtw_get_raw_rssi_info(void *sel, _adapter *padapter)
|
|
{
|
|
u8 isCCKrate, rf_path;
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
|
|
struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
|
|
RTW_PRINT_SEL(sel, "RxRate = %s, PWDBALL = %d(%%), rx_pwr_all = %d(dBm)\n",
|
|
HDATA_RATE(psample_pkt_rssi->data_rate), psample_pkt_rssi->pwdball, psample_pkt_rssi->pwr_all);
|
|
isCCKrate = (psample_pkt_rssi->data_rate <= DESC_RATE11M) ? TRUE : FALSE;
|
|
|
|
if (isCCKrate)
|
|
psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball;
|
|
|
|
for (rf_path = 0; rf_path < hal_spec->rf_reg_path_num; rf_path++) {
|
|
if (!(GET_HAL_RX_PATH_BMP(padapter) & BIT(rf_path)))
|
|
continue;
|
|
RTW_PRINT_SEL(sel, "RF_PATH_%d=>signal_strength:%d(%%),signal_quality:%d(%%)\n"
|
|
, rf_path, psample_pkt_rssi->mimo_signal_strength[rf_path], psample_pkt_rssi->mimo_signal_quality[rf_path]);
|
|
|
|
if (!isCCKrate) {
|
|
RTW_PRINT_SEL(sel, "\trx_ofdm_pwr:%d(dBm),rx_ofdm_snr:%d(dB)\n",
|
|
psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void rtw_dump_raw_rssi_info(_adapter *padapter, void *sel)
|
|
{
|
|
u8 isCCKrate, rf_path;
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
|
|
struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
|
|
_RTW_PRINT_SEL(sel, "============ RAW Rx Info dump ===================\n");
|
|
_RTW_PRINT_SEL(sel, "RxRate = %s, PWDBALL = %d(%%), rx_pwr_all = %d(dBm)\n", HDATA_RATE(psample_pkt_rssi->data_rate), psample_pkt_rssi->pwdball, psample_pkt_rssi->pwr_all);
|
|
|
|
isCCKrate = (psample_pkt_rssi->data_rate <= DESC_RATE11M) ? TRUE : FALSE;
|
|
|
|
if (isCCKrate)
|
|
psample_pkt_rssi->mimo_signal_strength[0] = psample_pkt_rssi->pwdball;
|
|
|
|
for (rf_path = 0; rf_path < hal_spec->rf_reg_path_num; rf_path++) {
|
|
if (!(GET_HAL_RX_PATH_BMP(padapter) & BIT(rf_path)))
|
|
continue;
|
|
_RTW_PRINT_SEL(sel , "RF_PATH_%d=>signal_strength:%d(%%),signal_quality:%d(%%)"
|
|
, rf_path, psample_pkt_rssi->mimo_signal_strength[rf_path], psample_pkt_rssi->mimo_signal_quality[rf_path]);
|
|
|
|
if (!isCCKrate)
|
|
_RTW_PRINT_SEL(sel , ",rx_ofdm_pwr:%d(dBm),rx_ofdm_snr:%d(dB)\n", psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]);
|
|
else
|
|
_RTW_PRINT_SEL(sel , "\n");
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef DBG_RX_DFRAME_RAW_DATA
|
|
void rtw_dump_rx_dframe_info(_adapter *padapter, void *sel)
|
|
{
|
|
#define DBG_RX_DFRAME_RAW_DATA_UC 0
|
|
#define DBG_RX_DFRAME_RAW_DATA_BMC 1
|
|
#define DBG_RX_DFRAME_RAW_DATA_TYPES 2
|
|
|
|
_irqL irqL;
|
|
u8 isCCKrate, rf_path;
|
|
struct recv_priv *precvpriv = &(padapter->recvpriv);
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
|
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
|
struct sta_info *psta;
|
|
struct sta_recv_dframe_info *psta_dframe_info;
|
|
int i, j;
|
|
_list *plist, *phead;
|
|
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
u8 null_addr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
if (precvpriv->store_law_data_flag) {
|
|
|
|
_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
|
|
|
|
for (i = 0; i < NUM_STA; i++) {
|
|
phead = &(pstapriv->sta_hash[i]);
|
|
plist = get_next(phead);
|
|
|
|
while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
|
|
|
|
psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
|
|
plist = get_next(plist);
|
|
|
|
if (psta) {
|
|
if ((_rtw_memcmp(psta->cmn.mac_addr, bc_addr, ETH_ALEN) != _TRUE)
|
|
&& (_rtw_memcmp(psta->cmn.mac_addr, null_addr, ETH_ALEN) != _TRUE)
|
|
&& (_rtw_memcmp(psta->cmn.mac_addr, adapter_mac_addr(padapter), ETH_ALEN) != _TRUE)) {
|
|
|
|
RTW_PRINT_SEL(sel, "==============================\n");
|
|
RTW_PRINT_SEL(sel, "macaddr =" MAC_FMT "\n", MAC_ARG(psta->cmn.mac_addr));
|
|
|
|
for (j = 0; j < DBG_RX_DFRAME_RAW_DATA_TYPES; j++) {
|
|
if (j == DBG_RX_DFRAME_RAW_DATA_UC) {
|
|
psta_dframe_info = &psta->sta_dframe_info;
|
|
RTW_PRINT_SEL(sel, "\n");
|
|
RTW_PRINT_SEL(sel, "Unicast:\n");
|
|
} else if (j == DBG_RX_DFRAME_RAW_DATA_BMC) {
|
|
psta_dframe_info = &psta->sta_dframe_info_bmc;
|
|
RTW_PRINT_SEL(sel, "\n");
|
|
RTW_PRINT_SEL(sel, "Broadcast/Multicast:\n");
|
|
}
|
|
|
|
isCCKrate = (psta_dframe_info->sta_data_rate <= DESC_RATE11M) ? TRUE : FALSE;
|
|
|
|
RTW_PRINT_SEL(sel, "BW=%s, sgi =%d\n", ch_width_str(psta_dframe_info->sta_bw_mode), psta_dframe_info->sta_sgi);
|
|
RTW_PRINT_SEL(sel, "Rx_Data_Rate = %s\n", HDATA_RATE(psta_dframe_info->sta_data_rate));
|
|
|
|
for (rf_path = 0; rf_path < hal_spec->rf_reg_path_num; rf_path++) {
|
|
if (!(GET_HAL_RX_PATH_BMP(padapter) & BIT(rf_path)))
|
|
continue;
|
|
if (!isCCKrate) {
|
|
RTW_PRINT_SEL(sel , "RF_PATH_%d RSSI:%d(dBm)", rf_path, psta_dframe_info->sta_RxPwr[rf_path]);
|
|
_RTW_PRINT_SEL(sel , ",rx_ofdm_snr:%d(dB)\n", psta_dframe_info->sta_ofdm_snr[rf_path]);
|
|
} else
|
|
RTW_PRINT_SEL(sel , "RF_PATH_%d RSSI:%d(dBm)\n", rf_path, (psta_dframe_info->sta_mimo_signal_strength[rf_path]) - 100);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
|
|
}
|
|
}
|
|
#endif
|
|
void rtw_store_phy_info(_adapter *padapter, union recv_frame *prframe)
|
|
{
|
|
u8 isCCKrate, rf_path , dframe_type;
|
|
u8 *ptr;
|
|
u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
#ifdef DBG_RX_DFRAME_RAW_DATA
|
|
struct sta_recv_dframe_info *psta_dframe_info;
|
|
#endif
|
|
struct recv_priv *precvpriv = &(padapter->recvpriv);
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
|
|
struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
|
|
struct sta_info *psta = prframe->u.hdr.psta;
|
|
struct phydm_phyinfo_struct *p_phy_info = &pattrib->phy_info;
|
|
struct rx_raw_rssi *psample_pkt_rssi = &padapter->recvpriv.raw_rssi_info;
|
|
psample_pkt_rssi->data_rate = pattrib->data_rate;
|
|
ptr = prframe->u.hdr.rx_data;
|
|
dframe_type = GetFrameType(ptr);
|
|
/*RTW_INFO("=>%s\n", __FUNCTION__);*/
|
|
|
|
|
|
if (precvpriv->store_law_data_flag) {
|
|
isCCKrate = (pattrib->data_rate <= DESC_RATE11M) ? TRUE : FALSE;
|
|
|
|
psample_pkt_rssi->pwdball = p_phy_info->rx_pwdb_all;
|
|
psample_pkt_rssi->pwr_all = p_phy_info->recv_signal_power;
|
|
|
|
for (rf_path = 0; rf_path < hal_spec->rf_reg_path_num; rf_path++) {
|
|
psample_pkt_rssi->mimo_signal_strength[rf_path] = p_phy_info->rx_mimo_signal_strength[rf_path];
|
|
psample_pkt_rssi->mimo_signal_quality[rf_path] = p_phy_info->rx_mimo_signal_quality[rf_path];
|
|
if (!isCCKrate) {
|
|
psample_pkt_rssi->ofdm_pwr[rf_path] = p_phy_info->rx_pwr[rf_path];
|
|
psample_pkt_rssi->ofdm_snr[rf_path] = p_phy_info->rx_snr[rf_path];
|
|
}
|
|
}
|
|
#ifdef DBG_RX_DFRAME_RAW_DATA
|
|
if ((dframe_type == WIFI_DATA_TYPE) || (dframe_type == WIFI_QOS_DATA_TYPE) || (padapter->registrypriv.mp_mode == 1)) {
|
|
|
|
/*RTW_INFO("=>%s WIFI_DATA_TYPE or WIFI_QOS_DATA_TYPE\n", __FUNCTION__);*/
|
|
if (psta) {
|
|
if (IS_MCAST(get_ra(get_recvframe_data(prframe))))
|
|
psta_dframe_info = &psta->sta_dframe_info_bmc;
|
|
else
|
|
psta_dframe_info = &psta->sta_dframe_info;
|
|
/*RTW_INFO("=>%s psta->cmn.mac_addr="MAC_FMT" !\n",
|
|
__FUNCTION__, MAC_ARG(psta->cmn.mac_addr));*/
|
|
if ((_rtw_memcmp(psta->cmn.mac_addr, bc_addr, ETH_ALEN) != _TRUE) || (padapter->registrypriv.mp_mode == 1)) {
|
|
psta_dframe_info->sta_data_rate = pattrib->data_rate;
|
|
psta_dframe_info->sta_sgi = pattrib->sgi;
|
|
psta_dframe_info->sta_bw_mode = pattrib->bw;
|
|
for (rf_path = 0; rf_path < hal_spec->rf_reg_path_num; rf_path++) {
|
|
|
|
psta_dframe_info->sta_mimo_signal_strength[rf_path] = (p_phy_info->rx_mimo_signal_strength[rf_path]);/*Percentage to dbm*/
|
|
|
|
if (!isCCKrate) {
|
|
psta_dframe_info->sta_ofdm_snr[rf_path] = p_phy_info->rx_snr[rf_path];
|
|
psta_dframe_info->sta_RxPwr[rf_path] = p_phy_info->rx_pwr[rf_path];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
int hal_efuse_macaddr_offset(_adapter *adapter)
|
|
{
|
|
u8 interface_type = 0;
|
|
int addr_offset = -1;
|
|
|
|
interface_type = rtw_get_intf_type(adapter);
|
|
|
|
switch (rtw_get_chip_type(adapter)) {
|
|
#ifdef CONFIG_RTL8723B
|
|
case RTL8723B:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8723BU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8723BS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8723BE;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8703B
|
|
case RTL8703B:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8703BU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8703BS;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8723D
|
|
case RTL8723D:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8723DU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8723DS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8723DE;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTL8188E
|
|
case RTL8188E:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_88EU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_88ES;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_88EE;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8188F
|
|
case RTL8188F:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8188FU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8188FS;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8188GTV
|
|
case RTL8188GTV:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8188GTVU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8188GTVS;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8812A
|
|
case RTL8812:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8812AU;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8812AE;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8821A
|
|
case RTL8821:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8821AU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8821AS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8821AE;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8192E
|
|
case RTL8192E:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8192EU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8192ES;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8192EE;
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8814A
|
|
case RTL8814A:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8814AU;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8814AE;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTL8822B
|
|
case RTL8822B:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8822BU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8822BS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8822BE;
|
|
break;
|
|
#endif /* CONFIG_RTL8822B */
|
|
|
|
#ifdef CONFIG_RTL8821C
|
|
case RTL8821C:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8821CU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8821CS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8821CE;
|
|
break;
|
|
#endif /* CONFIG_RTL8821C */
|
|
|
|
#ifdef CONFIG_RTL8710B
|
|
case RTL8710B:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8710B;
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_RTL8192F
|
|
case RTL8192F:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8192FU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8192FS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8192FE;
|
|
break;
|
|
#endif /* CONFIG_RTL8192F */
|
|
|
|
#ifdef CONFIG_RTL8822C
|
|
case RTL8822C:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8822CU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8822CS;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8822CE;
|
|
break;
|
|
#endif /* CONFIG_RTL8822C */
|
|
|
|
#ifdef CONFIG_RTL8814B
|
|
case RTL8814B:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8814BU;
|
|
else if (interface_type == RTW_PCIE)
|
|
addr_offset = EEPROM_MAC_ADDR_8814BE;
|
|
break;
|
|
#endif /* CONFIG_RTL8814B */
|
|
|
|
#ifdef CONFIG_RTL8723F
|
|
case RTL8723F:
|
|
if (interface_type == RTW_USB)
|
|
addr_offset = EEPROM_MAC_ADDR_8723FU;
|
|
else if (interface_type == RTW_SDIO)
|
|
addr_offset = EEPROM_MAC_ADDR_8723FS;
|
|
break;
|
|
#endif /* CONFIG_RTL8723F */
|
|
}
|
|
|
|
if (addr_offset == -1) {
|
|
RTW_ERR("%s: unknown combination - chip_type:%u, interface:%u\n"
|
|
, __func__, rtw_get_chip_type(adapter), rtw_get_intf_type(adapter));
|
|
}
|
|
|
|
return addr_offset;
|
|
}
|
|
|
|
int Hal_GetPhyEfuseMACAddr(PADAPTER padapter, u8 *mac_addr)
|
|
{
|
|
int ret = _FAIL;
|
|
int addr_offset;
|
|
|
|
addr_offset = hal_efuse_macaddr_offset(padapter);
|
|
if (addr_offset == -1)
|
|
goto exit;
|
|
|
|
ret = rtw_efuse_map_read(padapter, addr_offset, ETH_ALEN, mac_addr);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
void rtw_dump_cur_efuse(PADAPTER padapter)
|
|
{
|
|
int mapsize =0;
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
|
|
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&mapsize, _FALSE);
|
|
|
|
if (mapsize <= 0 || mapsize > EEPROM_MAX_SIZE) {
|
|
RTW_ERR("wrong map size %d\n", mapsize);
|
|
return;
|
|
}
|
|
|
|
#ifdef CONFIG_RTW_DEBUG
|
|
if (hal_data->efuse_file_status == EFUSE_FILE_LOADED)
|
|
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "EFUSE FILE", hal_data->efuse_eeprom_data, mapsize);
|
|
else {
|
|
#ifdef CONFIG_MP_INCLUDED
|
|
if (rtw_mp_mode_check(padapter) && GET_EFUSE_UPDATE_ON(padapter))
|
|
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "FAKE EFUSE", hal_data->efuse_eeprom_data, mapsize);
|
|
else
|
|
#endif
|
|
RTW_MAP_DUMP_SEL(RTW_DBGDUMP, "HW EFUSE", hal_data->efuse_eeprom_data, mapsize);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_EFUSE_CONFIG_FILE
|
|
u32 Hal_readPGDataFromConfigFile(PADAPTER padapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
u32 ret = _FALSE;
|
|
u32 maplen = 0;
|
|
#ifdef CONFIG_MP_INCLUDED
|
|
struct mp_priv *pmp_priv = &padapter->mppriv;
|
|
#endif
|
|
|
|
EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN , (void *)&maplen, _FALSE);
|
|
|
|
if (maplen < 256 || maplen > EEPROM_MAX_SIZE) {
|
|
RTW_ERR("eFuse length error :%d\n", maplen);
|
|
return _FALSE;
|
|
}
|
|
#ifdef CONFIG_MP_INCLUDED
|
|
if (pmp_priv->efuse_update_file == _TRUE && (rtw_mp_mode_check(padapter))) {
|
|
RTW_INFO("%s, eFuse read from file :%s\n", __func__, pmp_priv->efuse_file_path);
|
|
ret = rtw_read_efuse_from_file(pmp_priv->efuse_file_path, hal_data->efuse_eeprom_data, maplen);
|
|
pmp_priv->efuse_update_file = _FALSE;
|
|
} else
|
|
#endif
|
|
{
|
|
ret = rtw_read_efuse_from_file(EFUSE_MAP_PATH, hal_data->efuse_eeprom_data, maplen);
|
|
}
|
|
|
|
hal_data->efuse_file_status = ((ret == _FAIL) ? EFUSE_FILE_FAILED : EFUSE_FILE_LOADED);
|
|
|
|
if (hal_data->efuse_file_status == EFUSE_FILE_LOADED)
|
|
rtw_dump_cur_efuse(padapter);
|
|
|
|
return ret;
|
|
}
|
|
|
|
u32 Hal_ReadMACAddrFromFile(PADAPTER padapter, u8 *mac_addr)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
u32 ret = _FAIL;
|
|
|
|
if (rtw_read_macaddr_from_file(WIFIMAC_PATH, mac_addr) == _SUCCESS
|
|
&& rtw_check_invalid_mac_address(mac_addr, _TRUE) == _FALSE
|
|
) {
|
|
hal_data->macaddr_file_status = MACADDR_FILE_LOADED;
|
|
ret = _SUCCESS;
|
|
} else
|
|
hal_data->macaddr_file_status = MACADDR_FILE_FAILED;
|
|
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_EFUSE_CONFIG_FILE */
|
|
|
|
int hal_config_macaddr(_adapter *adapter, bool autoload_fail)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 addr[ETH_ALEN];
|
|
int addr_offset = hal_efuse_macaddr_offset(adapter);
|
|
u8 *hw_addr = NULL;
|
|
int ret = _SUCCESS;
|
|
#if defined(CONFIG_RTL8822B) && defined(CONFIG_USB_HCI)
|
|
u8 ft_mac_addr[ETH_ALEN] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff}; /* FT USB2 for 8822B */
|
|
#endif
|
|
|
|
if (autoload_fail)
|
|
goto bypass_hw_pg;
|
|
|
|
if (addr_offset != -1)
|
|
hw_addr = &hal_data->efuse_eeprom_data[addr_offset];
|
|
|
|
#ifdef CONFIG_EFUSE_CONFIG_FILE
|
|
/* if the hw_addr is written by efuse file, set to NULL */
|
|
if (hal_data->efuse_file_status == EFUSE_FILE_LOADED)
|
|
hw_addr = NULL;
|
|
#endif
|
|
|
|
if (!hw_addr) {
|
|
/* try getting hw pg data */
|
|
if (Hal_GetPhyEfuseMACAddr(adapter, addr) == _SUCCESS)
|
|
hw_addr = addr;
|
|
}
|
|
|
|
#if defined(CONFIG_RTL8822B) && defined(CONFIG_USB_HCI)
|
|
if (_rtw_memcmp(hw_addr, ft_mac_addr, ETH_ALEN))
|
|
hw_addr[0] = 0xff;
|
|
#endif
|
|
|
|
/* check hw pg data */
|
|
if (hw_addr && rtw_check_invalid_mac_address(hw_addr, _TRUE) == _FALSE) {
|
|
_rtw_memcpy(hal_data->EEPROMMACAddr, hw_addr, ETH_ALEN);
|
|
goto exit;
|
|
}
|
|
|
|
bypass_hw_pg:
|
|
|
|
#ifdef CONFIG_EFUSE_CONFIG_FILE
|
|
/* check wifi mac file */
|
|
if (Hal_ReadMACAddrFromFile(adapter, addr) == _SUCCESS) {
|
|
_rtw_memcpy(hal_data->EEPROMMACAddr, addr, ETH_ALEN);
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
_rtw_memset(hal_data->EEPROMMACAddr, 0, ETH_ALEN);
|
|
ret = _FAIL;
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_RF_POWER_TRIM
|
|
u32 Array_kfreemap[] = {
|
|
0x08, 0xe,
|
|
0x06, 0xc,
|
|
0x04, 0xa,
|
|
0x02, 0x8,
|
|
0x00, 0x6,
|
|
0x03, 0x4,
|
|
0x05, 0x2,
|
|
0x07, 0x0,
|
|
0x09, 0x0,
|
|
0x0c, 0x0,
|
|
};
|
|
|
|
void rtw_bb_rf_gain_offset(_adapter *padapter)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
struct registry_priv *registry_par = &padapter->registrypriv;
|
|
struct kfree_data_t *kfree_data = &pHalData->kfree_data;
|
|
u8 value = pHalData->EEPROMRFGainOffset;
|
|
u8 tmp = 0x3e;
|
|
u32 res, i = 0;
|
|
u32 ArrayLen = sizeof(Array_kfreemap) / sizeof(u32);
|
|
u32 *Array = Array_kfreemap;
|
|
u32 v1 = 0, v2 = 0, GainValue = 0, target = 0;
|
|
|
|
if (registry_par->RegPwrTrimEnable == 2) {
|
|
RTW_INFO("Registry kfree default force disable.\n");
|
|
return;
|
|
}
|
|
|
|
#if defined(CONFIG_RTL8723B)
|
|
if (value & BIT4 && (registry_par->RegPwrTrimEnable == 1)) {
|
|
RTW_INFO("Offset RF Gain.\n");
|
|
RTW_INFO("Offset RF Gain. pHalData->EEPROMRFGainVal=0x%x\n", pHalData->EEPROMRFGainVal);
|
|
|
|
if (pHalData->EEPROMRFGainVal != 0xff) {
|
|
|
|
if (pHalData->ant_path == RF_PATH_A)
|
|
GainValue = (pHalData->EEPROMRFGainVal & 0x0f);
|
|
|
|
else
|
|
GainValue = (pHalData->EEPROMRFGainVal & 0xf0) >> 4;
|
|
RTW_INFO("Ant PATH_%d GainValue Offset = 0x%x\n", (pHalData->ant_path == RF_PATH_A) ? (RF_PATH_A) : (RF_PATH_B), GainValue);
|
|
|
|
for (i = 0; i < ArrayLen; i += 2) {
|
|
/* RTW_INFO("ArrayLen in =%d ,Array 1 =0x%x ,Array2 =0x%x\n",i,Array[i],Array[i]+1); */
|
|
v1 = Array[i];
|
|
v2 = Array[i + 1];
|
|
if (v1 == GainValue) {
|
|
RTW_INFO("Offset RF Gain. got v1 =0x%x ,v2 =0x%x\n", v1, v2);
|
|
target = v2;
|
|
break;
|
|
}
|
|
}
|
|
RTW_INFO("pHalData->EEPROMRFGainVal=0x%x ,Gain offset Target Value=0x%x\n", pHalData->EEPROMRFGainVal, target);
|
|
|
|
res = rtw_hal_read_rfreg(padapter, RF_PATH_A, 0x7f, 0xffffffff);
|
|
RTW_INFO("Offset RF Gain. before reg 0x7f=0x%08x\n", res);
|
|
phy_set_rf_reg(padapter, RF_PATH_A, REG_RF_BB_GAIN_OFFSET, BIT18 | BIT17 | BIT16 | BIT15, target);
|
|
res = rtw_hal_read_rfreg(padapter, RF_PATH_A, 0x7f, 0xffffffff);
|
|
|
|
RTW_INFO("Offset RF Gain. After reg 0x7f=0x%08x\n", res);
|
|
|
|
} else
|
|
|
|
RTW_INFO("Offset RF Gain. pHalData->EEPROMRFGainVal=0x%x != 0xff, didn't run Kfree\n", pHalData->EEPROMRFGainVal);
|
|
} else
|
|
RTW_INFO("Using the default RF gain.\n");
|
|
|
|
#elif defined(CONFIG_RTL8188E)
|
|
if (value & BIT4 && (registry_par->RegPwrTrimEnable == 1)) {
|
|
RTW_INFO("8188ES Offset RF Gain.\n");
|
|
RTW_INFO("8188ES Offset RF Gain. EEPROMRFGainVal=0x%x\n",
|
|
pHalData->EEPROMRFGainVal);
|
|
|
|
if (pHalData->EEPROMRFGainVal != 0xff) {
|
|
res = rtw_hal_read_rfreg(padapter, RF_PATH_A,
|
|
REG_RF_BB_GAIN_OFFSET, 0xffffffff);
|
|
|
|
RTW_INFO("Offset RF Gain. reg 0x55=0x%x\n", res);
|
|
res &= 0xfff87fff;
|
|
|
|
res |= (pHalData->EEPROMRFGainVal & 0x0f) << 15;
|
|
RTW_INFO("Offset RF Gain. res=0x%x\n", res);
|
|
|
|
rtw_hal_write_rfreg(padapter, RF_PATH_A,
|
|
REG_RF_BB_GAIN_OFFSET,
|
|
RF_GAIN_OFFSET_MASK, res);
|
|
} else {
|
|
RTW_INFO("Offset RF Gain. EEPROMRFGainVal=0x%x == 0xff, didn't run Kfree\n",
|
|
pHalData->EEPROMRFGainVal);
|
|
}
|
|
} else
|
|
RTW_INFO("Using the default RF gain.\n");
|
|
#else
|
|
/* TODO: call this when channel switch */
|
|
if (kfree_data->flag & KFREE_FLAG_ON)
|
|
rtw_rf_apply_tx_gain_offset(padapter, 6); /* input ch6 to select BB_GAIN_2G */
|
|
#endif
|
|
|
|
}
|
|
#endif /*CONFIG_RF_POWER_TRIM */
|
|
|
|
bool kfree_data_is_bb_gain_empty(struct kfree_data_t *data)
|
|
{
|
|
#ifdef CONFIG_RF_POWER_TRIM
|
|
int i, j;
|
|
|
|
for (i = 0; i < BB_GAIN_NUM; i++)
|
|
for (j = 0; j < RF_PATH_MAX; j++)
|
|
if (data->bb_gain[i][j] != 0)
|
|
return 0;
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
#ifdef CONFIG_USB_RX_AGGREGATION
|
|
void rtw_set_usb_agg_by_mode_normal(_adapter *padapter, u8 cur_wireless_mode)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
if (cur_wireless_mode < WIRELESS_11_24N
|
|
&& cur_wireless_mode > 0) { /* ABG mode */
|
|
#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
|
|
u32 remainder = 0;
|
|
u8 quotient = 0;
|
|
|
|
remainder = MAX_RECVBUF_SZ % (4 * 1024);
|
|
quotient = (u8)(MAX_RECVBUF_SZ >> 12);
|
|
|
|
if (quotient > 5) {
|
|
pHalData->rxagg_usb_size = 0x6;
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
} else {
|
|
if (remainder >= 2048) {
|
|
pHalData->rxagg_usb_size = quotient;
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
} else {
|
|
pHalData->rxagg_usb_size = (quotient - 1);
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
}
|
|
}
|
|
#else /* !CONFIG_PREALLOC_RX_SKB_BUFFER */
|
|
if (0x6 != pHalData->rxagg_usb_size || 0x10 != pHalData->rxagg_usb_timeout) {
|
|
pHalData->rxagg_usb_size = 0x6;
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
rtw_write16(padapter, REG_RXDMA_AGG_PG_TH,
|
|
pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8));
|
|
}
|
|
#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */
|
|
|
|
} else if (cur_wireless_mode >= WIRELESS_11_24N
|
|
&& cur_wireless_mode <= WIRELESS_MODE_MAX) { /* N AC mode */
|
|
#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
|
|
u32 remainder = 0;
|
|
u8 quotient = 0;
|
|
|
|
remainder = MAX_RECVBUF_SZ % (4 * 1024);
|
|
quotient = (u8)(MAX_RECVBUF_SZ >> 12);
|
|
|
|
if (quotient > 5) {
|
|
pHalData->rxagg_usb_size = 0x5;
|
|
pHalData->rxagg_usb_timeout = 0x20;
|
|
} else {
|
|
if (remainder >= 2048) {
|
|
pHalData->rxagg_usb_size = quotient;
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
} else {
|
|
pHalData->rxagg_usb_size = (quotient - 1);
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
}
|
|
}
|
|
#else /* !CONFIG_PREALLOC_RX_SKB_BUFFER */
|
|
if ((0x5 != pHalData->rxagg_usb_size) || (0x20 != pHalData->rxagg_usb_timeout)) {
|
|
pHalData->rxagg_usb_size = 0x5;
|
|
pHalData->rxagg_usb_timeout = 0x20;
|
|
rtw_write16(padapter, REG_RXDMA_AGG_PG_TH,
|
|
pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8));
|
|
}
|
|
#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */
|
|
|
|
} else {
|
|
/* RTW_INFO("%s: Unknow wireless mode(0x%x)\n",__func__,padapter->mlmeextpriv.cur_wireless_mode); */
|
|
}
|
|
}
|
|
|
|
void rtw_set_usb_agg_by_mode_customer(_adapter *padapter, u8 cur_wireless_mode, u8 UsbDmaSize, u8 Legacy_UsbDmaSize)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
|
|
if (cur_wireless_mode < WIRELESS_11_24N
|
|
&& cur_wireless_mode > 0) { /* ABG mode */
|
|
if (Legacy_UsbDmaSize != pHalData->rxagg_usb_size
|
|
|| 0x10 != pHalData->rxagg_usb_timeout) {
|
|
pHalData->rxagg_usb_size = Legacy_UsbDmaSize;
|
|
pHalData->rxagg_usb_timeout = 0x10;
|
|
rtw_write16(padapter, REG_RXDMA_AGG_PG_TH,
|
|
pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8));
|
|
}
|
|
} else if (cur_wireless_mode >= WIRELESS_11_24N
|
|
&& cur_wireless_mode <= WIRELESS_MODE_MAX) { /* N AC mode */
|
|
if (UsbDmaSize != pHalData->rxagg_usb_size
|
|
|| 0x20 != pHalData->rxagg_usb_timeout) {
|
|
pHalData->rxagg_usb_size = UsbDmaSize;
|
|
pHalData->rxagg_usb_timeout = 0x20;
|
|
rtw_write16(padapter, REG_RXDMA_AGG_PG_TH,
|
|
pHalData->rxagg_usb_size | (pHalData->rxagg_usb_timeout << 8));
|
|
}
|
|
} else {
|
|
/* RTW_INFO("%s: Unknown wireless mode(0x%x)\n",__func__,padapter->mlmeextpriv.cur_wireless_mode); */
|
|
}
|
|
}
|
|
|
|
void rtw_set_usb_agg_by_mode(_adapter *padapter, u8 cur_wireless_mode)
|
|
{
|
|
#ifdef CONFIG_PLATFORM_NOVATEK_NT72668
|
|
rtw_set_usb_agg_by_mode_customer(padapter, cur_wireless_mode, 0x3, 0x3);
|
|
return;
|
|
#endif /* CONFIG_PLATFORM_NOVATEK_NT72668 */
|
|
|
|
rtw_set_usb_agg_by_mode_normal(padapter, cur_wireless_mode);
|
|
}
|
|
#endif /* CONFIG_USB_RX_AGGREGATION */
|
|
|
|
/* To avoid RX affect TX throughput */
|
|
void dm_DynamicUsbTxAgg(_adapter *padapter, u8 from_timer)
|
|
{
|
|
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
|
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
struct registry_priv *registry_par = &padapter->registrypriv;
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
u8 cur_wireless_mode = WIRELESS_INVALID;
|
|
|
|
#ifdef CONFIG_USB_RX_AGGREGATION
|
|
if (!registry_par->dynamic_agg_enable)
|
|
return;
|
|
|
|
#ifdef RTW_HALMAC
|
|
if (IS_HARDWARE_TYPE_8822BU(padapter) || IS_HARDWARE_TYPE_8821CU(padapter)
|
|
|| IS_HARDWARE_TYPE_8822CU(padapter) || IS_HARDWARE_TYPE_8814BU(padapter)
|
|
|| IS_HARDWARE_TYPE_8723FU(padapter))
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, NULL);
|
|
#else /* !RTW_HALMAC */
|
|
if (IS_HARDWARE_TYPE_8821U(padapter)) { /* || IS_HARDWARE_TYPE_8192EU(padapter)) */
|
|
/* This AGG_PH_TH only for UsbRxAggMode == USB_RX_AGG_USB */
|
|
if ((pHalData->rxagg_mode == RX_AGG_USB) && (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)) {
|
|
if (pdvobjpriv->traffic_stat.cur_tx_tp > 2 && pdvobjpriv->traffic_stat.cur_rx_tp < 30)
|
|
rtw_write16(padapter , REG_RXDMA_AGG_PG_TH , 0x1010);
|
|
else if (pdvobjpriv->traffic_stat.last_tx_bytes > 220000 && pdvobjpriv->traffic_stat.cur_rx_tp < 30)
|
|
rtw_write16(padapter , REG_RXDMA_AGG_PG_TH , 0x1006);
|
|
else
|
|
rtw_write16(padapter, REG_RXDMA_AGG_PG_TH, 0x2005); /* dmc agg th 20K */
|
|
|
|
/* RTW_INFO("TX_TP=%u, RX_TP=%u\n", pdvobjpriv->traffic_stat.cur_tx_tp, pdvobjpriv->traffic_stat.cur_rx_tp); */
|
|
}
|
|
} else if (IS_HARDWARE_TYPE_8812(padapter)) {
|
|
#ifdef CONFIG_CONCURRENT_MODE
|
|
u8 i;
|
|
_adapter *iface;
|
|
u8 bassocaed = _FALSE;
|
|
struct mlme_ext_priv *mlmeext;
|
|
|
|
for (i = 0; i < pdvobjpriv->iface_nums; i++) {
|
|
iface = pdvobjpriv->padapters[i];
|
|
mlmeext = &iface->mlmeextpriv;
|
|
if (rtw_linked_check(iface) == _TRUE) {
|
|
if (mlmeext->cur_wireless_mode >= cur_wireless_mode)
|
|
cur_wireless_mode = mlmeext->cur_wireless_mode;
|
|
bassocaed = _TRUE;
|
|
}
|
|
}
|
|
if (bassocaed)
|
|
#endif
|
|
rtw_set_usb_agg_by_mode(padapter, cur_wireless_mode);
|
|
#ifdef CONFIG_PLATFORM_NOVATEK_NT72668
|
|
} else {
|
|
rtw_set_usb_agg_by_mode(padapter, cur_wireless_mode);
|
|
#endif /* CONFIG_PLATFORM_NOVATEK_NT72668 */
|
|
}
|
|
#endif /* RTW_HALMAC */
|
|
#endif /* CONFIG_USB_RX_AGGREGATION */
|
|
|
|
}
|
|
|
|
/* bus-agg check for SoftAP mode */
|
|
inline u8 rtw_hal_busagg_qsel_check(_adapter *padapter, u8 pre_qsel, u8 next_qsel)
|
|
{
|
|
#ifdef CONFIG_AP_MODE
|
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
|
u8 chk_rst = _SUCCESS;
|
|
|
|
if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter))
|
|
return chk_rst;
|
|
|
|
/* if((pre_qsel == 0xFF)||(next_qsel== 0xFF)) */
|
|
/* return chk_rst; */
|
|
|
|
if (((pre_qsel == QSLT_HIGH) || ((next_qsel == QSLT_HIGH)))
|
|
&& (pre_qsel != next_qsel)) {
|
|
/* RTW_INFO("### bus-agg break cause of qsel misatch, pre_qsel=0x%02x,next_qsel=0x%02x ###\n", */
|
|
/* pre_qsel,next_qsel); */
|
|
chk_rst = _FAIL;
|
|
}
|
|
return chk_rst;
|
|
#else
|
|
return _SUCCESS;
|
|
#endif /* CONFIG_AP_MODE */
|
|
}
|
|
|
|
#ifdef CONFIG_WOWLAN
|
|
/*
|
|
* Description:
|
|
* dump_TX_FIFO: This is only used to dump TX_FIFO for debug WoW mode offload
|
|
* contant.
|
|
*
|
|
* Input:
|
|
* adapter: adapter pointer.
|
|
* page_num: The max. page number that user want to dump.
|
|
* page_size: page size of each page. eg. 128 bytes, 256 bytes, 512byte.
|
|
*/
|
|
void dump_TX_FIFO(_adapter *padapter, u8 page_num, u16 page_size)
|
|
{
|
|
|
|
int i;
|
|
u8 val = 0;
|
|
u8 base = 0;
|
|
u32 addr = 0;
|
|
u32 count = (page_size / 8);
|
|
|
|
if (page_num <= 0) {
|
|
RTW_INFO("!!%s: incorrect input page_num paramter!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (page_size < 128 || page_size > 512) {
|
|
RTW_INFO("!!%s: incorrect input page_size paramter!\n", __func__);
|
|
return;
|
|
}
|
|
|
|
RTW_INFO("+%s+\n", __func__);
|
|
val = rtw_read8(padapter, 0x106);
|
|
rtw_write8(padapter, 0x106, 0x69);
|
|
RTW_INFO("0x106: 0x%02x\n", val);
|
|
base = rtw_read8(padapter, 0x209);
|
|
RTW_INFO("0x209: 0x%02x\n", base);
|
|
|
|
addr = ((base)*page_size) / 8;
|
|
for (i = 0 ; i < page_num * count ; i += 2) {
|
|
rtw_write32(padapter, 0x140, addr + i);
|
|
printk(" %08x %08x ", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148));
|
|
rtw_write32(padapter, 0x140, addr + i + 1);
|
|
printk(" %08x %08x\n", rtw_read32(padapter, 0x144), rtw_read32(padapter, 0x148));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_GPIO_API
|
|
u8 rtw_hal_get_gpio(_adapter *adapter, u8 gpio_num)
|
|
{
|
|
u8 value = 0;
|
|
u8 direction = 0;
|
|
u32 gpio_pin_input_val = REG_GPIO_PIN_CTRL;
|
|
u32 gpio_pin_output_val = REG_GPIO_PIN_CTRL + 1;
|
|
u32 gpio_pin_output_en = REG_GPIO_PIN_CTRL + 2;
|
|
u8 gpio_num_to_set = gpio_num;
|
|
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(adapter);
|
|
|
|
if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL)
|
|
return value;
|
|
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
|
|
RTW_INFO("rf_pwrstate=0x%02x\n", pwrpriv->rf_pwrstate);
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
if (gpio_num > 7) {
|
|
gpio_pin_input_val = REG_GPIO_PIN_CTRL_2;
|
|
gpio_pin_output_val = REG_GPIO_PIN_CTRL_2 + 1;
|
|
gpio_pin_output_en = REG_GPIO_PIN_CTRL_2 + 2;
|
|
gpio_num_to_set = gpio_num - 8;
|
|
}
|
|
|
|
/* Read GPIO Direction */
|
|
direction = (rtw_read8(adapter, gpio_pin_output_en) & BIT(gpio_num_to_set)) >> gpio_num_to_set;
|
|
|
|
/* According the direction to read register value */
|
|
if (direction)
|
|
value = (rtw_read8(adapter, gpio_pin_output_val) & BIT(gpio_num_to_set)) >> gpio_num_to_set;
|
|
else
|
|
value = (rtw_read8(adapter, gpio_pin_input_val) & BIT(gpio_num_to_set)) >> gpio_num_to_set;
|
|
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
RTW_INFO("%s direction=%d value=%d\n", __FUNCTION__, direction, value);
|
|
|
|
return value;
|
|
}
|
|
|
|
int rtw_hal_set_gpio_output_value(_adapter *adapter, u8 gpio_num, bool isHigh)
|
|
{
|
|
u8 direction = 0;
|
|
u8 res = -1;
|
|
u32 gpio_pin_output_val = REG_GPIO_PIN_CTRL + 1;
|
|
u32 gpio_pin_output_en = REG_GPIO_PIN_CTRL + 2;
|
|
u8 gpio_num_to_set = gpio_num;
|
|
|
|
if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL)
|
|
return -1;
|
|
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
if (gpio_num > 7) {
|
|
gpio_pin_output_val = REG_GPIO_PIN_CTRL_2 + 1;
|
|
gpio_pin_output_en = REG_GPIO_PIN_CTRL_2 + 2;
|
|
gpio_num_to_set = gpio_num - 8;
|
|
}
|
|
|
|
/* Read GPIO direction */
|
|
direction = (rtw_read8(adapter, gpio_pin_output_en) & BIT(gpio_num_to_set)) >> gpio_num_to_set;
|
|
|
|
/* If GPIO is output direction, setting value. */
|
|
if (direction) {
|
|
if (isHigh)
|
|
rtw_write8(adapter, gpio_pin_output_val, rtw_read8(adapter, gpio_pin_output_val) | BIT(gpio_num_to_set));
|
|
else
|
|
rtw_write8(adapter, gpio_pin_output_val, rtw_read8(adapter, gpio_pin_output_val) & ~BIT(gpio_num_to_set));
|
|
|
|
RTW_INFO("%s Set gpio %x[%d]=%d\n", __FUNCTION__, REG_GPIO_PIN_CTRL + 1, gpio_num, isHigh);
|
|
res = 0;
|
|
} else {
|
|
RTW_INFO("%s The gpio is input,not be set!\n", __FUNCTION__);
|
|
res = -1;
|
|
}
|
|
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
return res;
|
|
}
|
|
|
|
int rtw_hal_config_gpio(_adapter *adapter, u8 gpio_num, bool isOutput)
|
|
{
|
|
u32 gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL + 2;
|
|
u8 gpio_num_to_set = gpio_num;
|
|
|
|
if (rtw_hal_gpio_func_check(adapter, gpio_num) == _FAIL)
|
|
return -1;
|
|
|
|
RTW_INFO("%s gpio_num =%d direction=%d\n", __FUNCTION__, gpio_num, isOutput);
|
|
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
rtw_hal_gpio_multi_func_reset(adapter, gpio_num);
|
|
|
|
if (gpio_num > 7) {
|
|
gpio_ctrl_reg_to_set = REG_GPIO_PIN_CTRL_2 + 2;
|
|
gpio_num_to_set = gpio_num - 8;
|
|
}
|
|
|
|
if (isOutput)
|
|
rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) | BIT(gpio_num_to_set));
|
|
else
|
|
rtw_write8(adapter, gpio_ctrl_reg_to_set, rtw_read8(adapter, gpio_ctrl_reg_to_set) & ~BIT(gpio_num_to_set));
|
|
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
|
|
return 0;
|
|
}
|
|
int rtw_hal_register_gpio_interrupt(_adapter *adapter, int gpio_num, void(*callback)(u8 level))
|
|
{
|
|
u8 value;
|
|
u8 direction;
|
|
PHAL_DATA_TYPE phal = GET_HAL_DATA(adapter);
|
|
|
|
if (IS_HARDWARE_TYPE_8188E(adapter)) {
|
|
if (gpio_num > 7 || gpio_num < 4) {
|
|
RTW_PRINT("%s The gpio number does not included 4~7.\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
/* Read GPIO direction */
|
|
direction = (rtw_read8(adapter, REG_GPIO_PIN_CTRL + 2) & BIT(gpio_num)) >> gpio_num;
|
|
if (direction) {
|
|
RTW_PRINT("%s Can't register output gpio as interrupt.\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
|
|
/* Config GPIO Mode */
|
|
rtw_write8(adapter, REG_GPIO_PIN_CTRL + 3, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 3) | BIT(gpio_num));
|
|
|
|
/* Register GPIO interrupt handler*/
|
|
adapter->gpiointpriv.callback[gpio_num] = callback;
|
|
|
|
/* Set GPIO interrupt mode, 0:positive edge, 1:negative edge */
|
|
value = rtw_read8(adapter, REG_GPIO_PIN_CTRL) & BIT(gpio_num);
|
|
adapter->gpiointpriv.interrupt_mode = rtw_read8(adapter, REG_HSIMR + 2) ^ value;
|
|
rtw_write8(adapter, REG_GPIO_INTM, adapter->gpiointpriv.interrupt_mode);
|
|
|
|
/* Enable GPIO interrupt */
|
|
adapter->gpiointpriv.interrupt_enable_mask = rtw_read8(adapter, REG_HSIMR + 2) | BIT(gpio_num);
|
|
rtw_write8(adapter, REG_HSIMR + 2, adapter->gpiointpriv.interrupt_enable_mask);
|
|
|
|
rtw_hal_update_hisr_hsisr_ind(adapter, 1);
|
|
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
|
|
return 0;
|
|
}
|
|
int rtw_hal_disable_gpio_interrupt(_adapter *adapter, int gpio_num)
|
|
{
|
|
u8 value;
|
|
u8 direction;
|
|
PHAL_DATA_TYPE phal = GET_HAL_DATA(adapter);
|
|
|
|
if (IS_HARDWARE_TYPE_8188E(adapter)) {
|
|
if (gpio_num > 7 || gpio_num < 4) {
|
|
RTW_INFO("%s The gpio number does not included 4~7.\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
rtw_ps_deny(adapter, PS_DENY_IOCTL);
|
|
|
|
LeaveAllPowerSaveModeDirect(adapter);
|
|
|
|
/* Config GPIO Mode */
|
|
rtw_write8(adapter, REG_GPIO_PIN_CTRL + 3, rtw_read8(adapter, REG_GPIO_PIN_CTRL + 3) & ~BIT(gpio_num));
|
|
|
|
/* Unregister GPIO interrupt handler*/
|
|
adapter->gpiointpriv.callback[gpio_num] = NULL;
|
|
|
|
/* Reset GPIO interrupt mode, 0:positive edge, 1:negative edge */
|
|
adapter->gpiointpriv.interrupt_mode = rtw_read8(adapter, REG_GPIO_INTM) & ~BIT(gpio_num);
|
|
rtw_write8(adapter, REG_GPIO_INTM, 0x00);
|
|
|
|
/* Disable GPIO interrupt */
|
|
adapter->gpiointpriv.interrupt_enable_mask = rtw_read8(adapter, REG_HSIMR + 2) & ~BIT(gpio_num);
|
|
rtw_write8(adapter, REG_HSIMR + 2, adapter->gpiointpriv.interrupt_enable_mask);
|
|
|
|
if (!adapter->gpiointpriv.interrupt_enable_mask)
|
|
rtw_hal_update_hisr_hsisr_ind(adapter, 0);
|
|
|
|
rtw_ps_deny_cancel(adapter, PS_DENY_IOCTL);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
s8 rtw_hal_ch_sw_iqk_info_search(_adapter *padapter, u8 central_chnl, u8 bw_mode)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
u8 i;
|
|
|
|
for (i = 0; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++) {
|
|
if ((pHalData->iqk_reg_backup[i].central_chnl != 0)) {
|
|
if ((pHalData->iqk_reg_backup[i].central_chnl == central_chnl)
|
|
&& (pHalData->iqk_reg_backup[i].bw_mode == bw_mode))
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void rtw_hal_ch_sw_iqk_info_backup(_adapter *padapter)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
s8 res;
|
|
u8 i;
|
|
|
|
/* If it's an existed record, overwrite it */
|
|
res = rtw_hal_ch_sw_iqk_info_search(padapter, pHalData->current_channel, pHalData->current_channel_bw);
|
|
if ((res >= 0) && (res < MAX_IQK_INFO_BACKUP_CHNL_NUM)) {
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[res]));
|
|
return;
|
|
}
|
|
|
|
/* Search for the empty record to use */
|
|
for (i = 0; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++) {
|
|
if (pHalData->iqk_reg_backup[i].central_chnl == 0) {
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[i]));
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Else, overwrite the oldest record */
|
|
for (i = 1; i < MAX_IQK_INFO_BACKUP_CHNL_NUM; i++)
|
|
_rtw_memcpy(&(pHalData->iqk_reg_backup[i - 1]), &(pHalData->iqk_reg_backup[i]), sizeof(struct hal_iqk_reg_backup));
|
|
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_BACKUP, (u8 *)&(pHalData->iqk_reg_backup[MAX_IQK_INFO_BACKUP_CHNL_NUM - 1]));
|
|
}
|
|
|
|
void rtw_hal_ch_sw_iqk_info_restore(_adapter *padapter, u8 ch_sw_use_case)
|
|
{
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_CH_SW_IQK_INFO_RESTORE, &ch_sw_use_case);
|
|
}
|
|
|
|
void rtw_dump_mac_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter)
|
|
{
|
|
u32 mac_cck_ok = 0, mac_ofdm_ok = 0, mac_ht_ok = 0, mac_vht_ok = 0;
|
|
u32 mac_cck_err = 0, mac_ofdm_err = 0, mac_ht_err = 0, mac_vht_err = 0;
|
|
u32 mac_cck_fa = 0, mac_ofdm_fa = 0, mac_ht_fa = 0;
|
|
u32 DropPacket = 0;
|
|
|
|
if (!rx_counter) {
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter))
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT26, 0x0);/*clear bit-26*/
|
|
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x3);
|
|
mac_cck_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x0);
|
|
mac_ofdm_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x6);
|
|
mac_ht_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
mac_vht_ok = 0;
|
|
if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter)) {
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x0);
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT26, 0x1);
|
|
mac_vht_ok = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0]*/
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT26, 0x0);/*clear bit-26*/
|
|
}
|
|
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x4);
|
|
mac_cck_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x1);
|
|
mac_ofdm_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x7);
|
|
mac_ht_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
mac_vht_err = 0;
|
|
if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter)) {
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x1);
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT26, 0x1);
|
|
mac_vht_err = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0]*/
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT26, 0x0);/*clear bit-26*/
|
|
}
|
|
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x5);
|
|
mac_cck_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x2);
|
|
mac_ofdm_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT28 | BIT29 | BIT30 | BIT31, 0x9);
|
|
mac_ht_fa = phy_query_mac_reg(padapter, REG_RXERR_RPT, bMaskLWord);/* [15:0] */
|
|
|
|
/* Mac_DropPacket */
|
|
rtw_write32(padapter, REG_RXERR_RPT, (rtw_read32(padapter, REG_RXERR_RPT) & 0x0FFFFFFF) | Mac_DropPacket);
|
|
DropPacket = rtw_read32(padapter, REG_RXERR_RPT) & 0x0000FFFF;
|
|
|
|
rx_counter->rx_pkt_ok = mac_cck_ok + mac_ofdm_ok + mac_ht_ok + mac_vht_ok;
|
|
rx_counter->rx_pkt_crc_error = mac_cck_err + mac_ofdm_err + mac_ht_err + mac_vht_err;
|
|
rx_counter->rx_cck_fa = mac_cck_fa;
|
|
rx_counter->rx_ofdm_fa = mac_ofdm_fa;
|
|
rx_counter->rx_ht_fa = mac_ht_fa;
|
|
rx_counter->rx_pkt_drop = DropPacket;
|
|
}
|
|
void rtw_reset_mac_rx_counters(_adapter *padapter)
|
|
{
|
|
|
|
/* If no packet rx, MaxRx clock be gating ,BIT_DISGCLK bit19 set 1 for fix*/
|
|
if (IS_HARDWARE_TYPE_8703B(padapter) ||
|
|
IS_HARDWARE_TYPE_8723D(padapter) ||
|
|
IS_HARDWARE_TYPE_8188F(padapter) ||
|
|
IS_HARDWARE_TYPE_8188GTV(padapter) ||
|
|
IS_HARDWARE_TYPE_8192F(padapter) ||
|
|
IS_HARDWARE_TYPE_8822C(padapter))
|
|
phy_set_mac_reg(padapter, REG_RCR, BIT19, 0x1);
|
|
|
|
/* reset mac counter */
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT27, 0x1);
|
|
phy_set_mac_reg(padapter, REG_RXERR_RPT, BIT27, 0x0);
|
|
}
|
|
|
|
void rtw_dump_phy_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter)
|
|
{
|
|
u32 cckok = 0, cckcrc = 0, ofdmok = 0, ofdmcrc = 0, htok = 0, htcrc = 0, OFDM_FA = 0, CCK_FA = 0, vht_ok = 0, vht_err = 0;
|
|
if (!rx_counter) {
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter)) {
|
|
cckok = phy_query_bb_reg(padapter, 0xF04, 0x3FFF); /* [13:0] */
|
|
ofdmok = phy_query_bb_reg(padapter, 0xF14, 0x3FFF); /* [13:0] */
|
|
htok = phy_query_bb_reg(padapter, 0xF10, 0x3FFF); /* [13:0] */
|
|
vht_ok = phy_query_bb_reg(padapter, 0xF0C, 0x3FFF); /* [13:0] */
|
|
cckcrc = phy_query_bb_reg(padapter, 0xF04, 0x3FFF0000); /* [29:16] */
|
|
ofdmcrc = phy_query_bb_reg(padapter, 0xF14, 0x3FFF0000); /* [29:16] */
|
|
htcrc = phy_query_bb_reg(padapter, 0xF10, 0x3FFF0000); /* [29:16] */
|
|
vht_err = phy_query_bb_reg(padapter, 0xF0C, 0x3FFF0000); /* [29:16] */
|
|
CCK_FA = phy_query_bb_reg(padapter, 0xA5C, bMaskLWord);
|
|
OFDM_FA = phy_query_bb_reg(padapter, 0xF48, bMaskLWord);
|
|
} else if(IS_HARDWARE_TYPE_JAGUAR3(padapter)){
|
|
cckok = phy_query_bb_reg(padapter, 0x2c04, 0xffff);
|
|
ofdmok = phy_query_bb_reg(padapter, 0x2c14, 0xffff);
|
|
htok = phy_query_bb_reg(padapter, 0x2c10, 0xffff);
|
|
vht_ok = phy_query_bb_reg(padapter, 0x2c0c, 0xffff);
|
|
cckcrc = phy_query_bb_reg(padapter, 0x2c04, 0xffff0000);
|
|
ofdmcrc = phy_query_bb_reg(padapter, 0x2c14, 0xffff0000);
|
|
htcrc = phy_query_bb_reg(padapter, 0x2c10, 0xffff0000);
|
|
vht_err = phy_query_bb_reg(padapter, 0x2c0c, 0xffff0000);
|
|
CCK_FA = phy_query_bb_reg(padapter, 0x1a5c, bMaskLWord);
|
|
OFDM_FA = phy_query_bb_reg(padapter, 0x2d00, bMaskLWord) - phy_query_bb_reg(padapter, 0x2de0, bMaskLWord);
|
|
} else if(IS_HARDWARE_TYPE_JAGUAR3_11N(padapter)){
|
|
cckok = phy_query_bb_reg(padapter, 0x2aac, 0xffff);
|
|
ofdmok = phy_query_bb_reg(padapter, 0x2c14, 0xffff);
|
|
htok = phy_query_bb_reg(padapter, 0x2c10, 0xffff);
|
|
cckcrc = phy_query_bb_reg(padapter, 0x2aac, 0xffff0000);
|
|
ofdmcrc = phy_query_bb_reg(padapter, 0x2c14, 0xffff0000);
|
|
htcrc = phy_query_bb_reg(padapter, 0x2c10, 0xffff0000);
|
|
CCK_FA = phy_query_bb_reg(padapter, 0x2aa8, 0xffff0000) + phy_query_bb_reg(padapter, 0x2aa8, 0x0000ffff);
|
|
OFDM_FA = phy_query_bb_reg(padapter, 0x2d00, bMaskLWord) - phy_query_bb_reg(padapter, 0x2de0, bMaskLWord);
|
|
} else {
|
|
cckok = phy_query_bb_reg(padapter, 0xF88, bMaskDWord);
|
|
ofdmok = phy_query_bb_reg(padapter, 0xF94, bMaskLWord);
|
|
htok = phy_query_bb_reg(padapter, 0xF90, bMaskLWord);
|
|
vht_ok = 0;
|
|
cckcrc = phy_query_bb_reg(padapter, 0xF84, bMaskDWord);
|
|
ofdmcrc = phy_query_bb_reg(padapter, 0xF94, bMaskHWord);
|
|
htcrc = phy_query_bb_reg(padapter, 0xF90, bMaskHWord);
|
|
vht_err = 0;
|
|
OFDM_FA = phy_query_bb_reg(padapter, 0xCF0, bMaskLWord) + phy_query_bb_reg(padapter, 0xCF0, bMaskHWord) +
|
|
phy_query_bb_reg(padapter, 0xDA0, bMaskHWord) + phy_query_bb_reg(padapter, 0xDA4, bMaskLWord) +
|
|
phy_query_bb_reg(padapter, 0xDA4, bMaskHWord) + phy_query_bb_reg(padapter, 0xDA8, bMaskLWord);
|
|
|
|
CCK_FA = (rtw_read8(padapter, 0xA5B) << 8) | (rtw_read8(padapter, 0xA5C));
|
|
}
|
|
|
|
rx_counter->rx_pkt_ok = cckok + ofdmok + htok + vht_ok;
|
|
rx_counter->rx_pkt_crc_error = cckcrc + ofdmcrc + htcrc + vht_err;
|
|
rx_counter->rx_ofdm_fa = OFDM_FA;
|
|
rx_counter->rx_cck_fa = CCK_FA;
|
|
|
|
}
|
|
|
|
void rtw_reset_phy_trx_ok_counters(_adapter *padapter)
|
|
{
|
|
if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter)) {
|
|
phy_set_bb_reg(padapter, 0xB58, BIT0, 0x1);
|
|
phy_set_bb_reg(padapter, 0xB58, BIT0, 0x0);
|
|
} else if(IS_HARDWARE_TYPE_JAGUAR3(padapter) || IS_HARDWARE_TYPE_JAGUAR3_11N(padapter)) {
|
|
phy_set_bb_reg(padapter, 0x1EB4, BIT25, 0x1);
|
|
phy_set_bb_reg(padapter, 0x1EB4, BIT25, 0x0);
|
|
} else {
|
|
phy_set_bb_reg(padapter, 0xF14, BIT16, 0x1);
|
|
phy_set_bb_reg(padapter, 0xF14, BIT16, 0x0);
|
|
}
|
|
}
|
|
|
|
void rtw_reset_phy_rx_counters(_adapter *padapter)
|
|
{
|
|
/* reset phy counter */
|
|
if (IS_HARDWARE_TYPE_JAGUAR3(padapter)) {
|
|
/* reset CCK FA counter */
|
|
phy_set_bb_reg(padapter, 0x1a2c, BIT(15) | BIT(14), 0);
|
|
phy_set_bb_reg(padapter, 0x1a2c, BIT(15) | BIT(14), 2);
|
|
|
|
/* reset CCK CCA counter */
|
|
phy_set_bb_reg(padapter, 0x1a2c, BIT(13) | BIT(12), 0);
|
|
phy_set_bb_reg(padapter, 0x1a2c, BIT(13) | BIT(12), 2);
|
|
rtw_reset_phy_trx_ok_counters(padapter);
|
|
|
|
} else if (IS_HARDWARE_TYPE_JAGUAR3_11N(padapter)) {
|
|
/* reset CCK FA and CCK CCA counter */
|
|
phy_set_bb_reg(padapter, 0x2a44, BIT21, 0);
|
|
phy_set_bb_reg(padapter, 0x2a44, BIT21, 1);
|
|
rtw_reset_phy_trx_ok_counters(padapter);
|
|
|
|
} else if (IS_HARDWARE_TYPE_JAGUAR(padapter) || IS_HARDWARE_TYPE_JAGUAR2(padapter)) {
|
|
rtw_reset_phy_trx_ok_counters(padapter);
|
|
|
|
phy_set_bb_reg(padapter, 0x9A4, BIT17, 0x1);/* reset OFDA FA counter */
|
|
phy_set_bb_reg(padapter, 0x9A4, BIT17, 0x0);
|
|
|
|
phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x0);/* reset CCK FA counter */
|
|
phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x1);
|
|
} else {
|
|
phy_set_bb_reg(padapter, 0xF14, BIT16, 0x1);
|
|
rtw_msleep_os(10);
|
|
phy_set_bb_reg(padapter, 0xF14, BIT16, 0x0);
|
|
|
|
phy_set_bb_reg(padapter, 0xD00, BIT27, 0x1);/* reset OFDA FA counter */
|
|
phy_set_bb_reg(padapter, 0xC0C, BIT31, 0x1);/* reset OFDA FA counter */
|
|
phy_set_bb_reg(padapter, 0xD00, BIT27, 0x0);
|
|
phy_set_bb_reg(padapter, 0xC0C, BIT31, 0x0);
|
|
|
|
phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x0);/* reset CCK FA counter */
|
|
phy_set_bb_reg(padapter, 0xA2C, BIT15, 0x1);
|
|
}
|
|
}
|
|
#ifdef DBG_RX_COUNTER_DUMP
|
|
void rtw_dump_drv_rx_counters(_adapter *padapter, struct dbg_rx_counter *rx_counter)
|
|
{
|
|
struct recv_priv *precvpriv = &padapter->recvpriv;
|
|
if (!rx_counter) {
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
rx_counter->rx_pkt_ok = padapter->drv_rx_cnt_ok;
|
|
rx_counter->rx_pkt_crc_error = padapter->drv_rx_cnt_crcerror;
|
|
rx_counter->rx_pkt_drop = precvpriv->rx_drop - padapter->drv_rx_cnt_drop;
|
|
}
|
|
void rtw_reset_drv_rx_counters(_adapter *padapter)
|
|
{
|
|
struct recv_priv *precvpriv = &padapter->recvpriv;
|
|
padapter->drv_rx_cnt_ok = 0;
|
|
padapter->drv_rx_cnt_crcerror = 0;
|
|
padapter->drv_rx_cnt_drop = precvpriv->rx_drop;
|
|
}
|
|
void rtw_dump_phy_rxcnts_preprocess(_adapter *padapter, u8 rx_cnt_mode)
|
|
{
|
|
u8 initialgain;
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
|
|
if ((!(padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER)) && (rx_cnt_mode & DUMP_PHY_RX_COUNTER)) {
|
|
rtw_hal_get_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, NULL);
|
|
RTW_INFO("%s CurIGValue:0x%02x\n", __FUNCTION__, initialgain);
|
|
rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);
|
|
/*disable dynamic functions, such as high power, DIG*/
|
|
rtw_phydm_ability_backup(padapter);
|
|
rtw_phydm_func_clr(padapter, (ODM_BB_DIG | ODM_BB_FA_CNT));
|
|
} else if ((padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER) && (!(rx_cnt_mode & DUMP_PHY_RX_COUNTER))) {
|
|
/* turn on phy-dynamic functions */
|
|
rtw_phydm_ability_restore(padapter);
|
|
initialgain = 0xff; /* restore RX GAIN */
|
|
rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
void rtw_dump_rx_counters(_adapter *padapter)
|
|
{
|
|
struct dbg_rx_counter rx_counter;
|
|
|
|
if (padapter->dump_rx_cnt_mode & DUMP_DRV_RX_COUNTER) {
|
|
_rtw_memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
|
|
rtw_dump_drv_rx_counters(padapter, &rx_counter);
|
|
RTW_INFO("Drv Received packet OK:%d CRC error:%d Drop Packets: %d\n",
|
|
rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error, rx_counter.rx_pkt_drop);
|
|
rtw_reset_drv_rx_counters(padapter);
|
|
}
|
|
|
|
if (padapter->dump_rx_cnt_mode & DUMP_MAC_RX_COUNTER) {
|
|
_rtw_memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
|
|
rtw_dump_mac_rx_counters(padapter, &rx_counter);
|
|
RTW_INFO("Mac Received packet OK:%d CRC error:%d FA Counter: %d Drop Packets: %d\n",
|
|
rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error,
|
|
rx_counter.rx_cck_fa + rx_counter.rx_ofdm_fa + rx_counter.rx_ht_fa,
|
|
rx_counter.rx_pkt_drop);
|
|
rtw_reset_mac_rx_counters(padapter);
|
|
}
|
|
|
|
if (padapter->dump_rx_cnt_mode & DUMP_PHY_RX_COUNTER) {
|
|
_rtw_memset(&rx_counter, 0, sizeof(struct dbg_rx_counter));
|
|
rtw_dump_phy_rx_counters(padapter, &rx_counter);
|
|
/* RTW_INFO("%s: OFDM_FA =%d\n", __FUNCTION__, rx_counter.rx_ofdm_fa); */
|
|
/* RTW_INFO("%s: CCK_FA =%d\n", __FUNCTION__, rx_counter.rx_cck_fa); */
|
|
RTW_INFO("Phy Received packet OK:%d CRC error:%d FA Counter: %d\n", rx_counter.rx_pkt_ok, rx_counter.rx_pkt_crc_error,
|
|
rx_counter.rx_ofdm_fa + rx_counter.rx_cck_fa);
|
|
rtw_reset_phy_rx_counters(padapter);
|
|
}
|
|
}
|
|
#endif
|
|
u8 rtw_get_current_tx_sgi(_adapter *padapter, struct sta_info *psta)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
u8 curr_tx_sgi = 0;
|
|
struct ra_sta_info *ra_info;
|
|
|
|
if (!psta)
|
|
return curr_tx_sgi;
|
|
|
|
if (padapter->fix_rate == 0xff) {
|
|
#if defined(CONFIG_RTL8188E)
|
|
#if (RATE_ADAPTIVE_SUPPORT == 1)
|
|
curr_tx_sgi = hal_data->odmpriv.ra_info[psta->cmn.mac_id].rate_sgi;
|
|
#endif /* (RATE_ADAPTIVE_SUPPORT == 1)*/
|
|
#else
|
|
ra_info = &psta->cmn.ra_info;
|
|
curr_tx_sgi = ((ra_info->curr_tx_rate) & 0x80) >> 7;
|
|
#endif
|
|
} else {
|
|
curr_tx_sgi = ((padapter->fix_rate) & 0x80) >> 7;
|
|
}
|
|
|
|
return curr_tx_sgi;
|
|
}
|
|
|
|
u8 rtw_get_current_tx_rate(_adapter *padapter, struct sta_info *psta)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
u8 rate_id = 0;
|
|
struct ra_sta_info *ra_info;
|
|
|
|
if (!psta)
|
|
return rate_id;
|
|
|
|
if (padapter->fix_rate == 0xff) {
|
|
#if defined(CONFIG_RTL8188E)
|
|
#if (RATE_ADAPTIVE_SUPPORT == 1)
|
|
rate_id = hal_data->odmpriv.ra_info[psta->cmn.mac_id].decision_rate;
|
|
#endif /* (RATE_ADAPTIVE_SUPPORT == 1)*/
|
|
#else
|
|
ra_info = &psta->cmn.ra_info;
|
|
rate_id = ra_info->curr_tx_rate & 0x7f;
|
|
#endif
|
|
} else {
|
|
rate_id = padapter->fix_rate & 0x7f;
|
|
}
|
|
|
|
return rate_id;
|
|
}
|
|
|
|
void update_IOT_info(_adapter *padapter)
|
|
{
|
|
struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
|
|
switch (pmlmeinfo->assoc_AP_vendor) {
|
|
case HT_IOT_PEER_MARVELL:
|
|
pmlmeinfo->turboMode_cts2self = 1;
|
|
pmlmeinfo->turboMode_rtsen = 0;
|
|
break;
|
|
|
|
case HT_IOT_PEER_RALINK:
|
|
pmlmeinfo->turboMode_cts2self = 0;
|
|
pmlmeinfo->turboMode_rtsen = 1;
|
|
break;
|
|
case HT_IOT_PEER_REALTEK:
|
|
/* rtw_write16(padapter, 0x4cc, 0xffff); */
|
|
/* rtw_write16(padapter, 0x546, 0x01c0); */
|
|
break;
|
|
default:
|
|
pmlmeinfo->turboMode_cts2self = 0;
|
|
pmlmeinfo->turboMode_rtsen = 1;
|
|
break;
|
|
}
|
|
|
|
}
|
|
#ifdef CONFIG_RTS_FULL_BW
|
|
/*
|
|
8188E: not support full RTS BW feature(mac REG no define 480[5])
|
|
*/
|
|
void rtw_set_rts_bw(_adapter *padapter) {
|
|
int i;
|
|
u8 enable = 1;
|
|
bool connect_to_8812 = _FALSE;
|
|
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
|
|
struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
|
|
struct sta_info *station = NULL;
|
|
|
|
for (i = 0; i < macid_ctl->num; i++) {
|
|
if (rtw_macid_is_used(macid_ctl, i)) {
|
|
|
|
station = NULL;
|
|
station = macid_ctl->sta[i];
|
|
if(station) {
|
|
|
|
_adapter *sta_adapter =station->padapter;
|
|
struct mlme_ext_priv *pmlmeext = &(sta_adapter->mlmeextpriv);
|
|
struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
|
|
|
if ( pmlmeinfo->state != WIFI_FW_NULL_STATE) {
|
|
if(_rtw_memcmp(macid_ctl->sta[i]->cmn.mac_addr, bc_addr, ETH_ALEN) != _TRUE) {
|
|
if ( macid_ctl->sta[i]->vendor_8812) {
|
|
connect_to_8812 = _TRUE;
|
|
enable = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(connect_to_8812)
|
|
break;
|
|
}
|
|
|
|
RTW_INFO("%s connect_to_8812=%d,enable=%u\n", __FUNCTION__,connect_to_8812,enable);
|
|
rtw_hal_set_hwreg(padapter, HW_VAR_SET_RTS_BW, &enable);
|
|
}
|
|
#endif/*CONFIG_RTS_FULL_BW*/
|
|
|
|
int hal_spec_init(_adapter *adapter)
|
|
{
|
|
u8 interface_type = 0;
|
|
int ret = _SUCCESS;
|
|
|
|
interface_type = rtw_get_intf_type(adapter);
|
|
|
|
switch (rtw_get_chip_type(adapter)) {
|
|
#ifdef CONFIG_RTL8723B
|
|
case RTL8723B:
|
|
init_hal_spec_8723b(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8703B
|
|
case RTL8703B:
|
|
init_hal_spec_8703b(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8723D
|
|
case RTL8723D:
|
|
init_hal_spec_8723d(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8188E
|
|
case RTL8188E:
|
|
init_hal_spec_8188e(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8188F
|
|
case RTL8188F:
|
|
init_hal_spec_8188f(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8188GTV
|
|
case RTL8188GTV:
|
|
init_hal_spec_8188gtv(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8812A
|
|
case RTL8812:
|
|
init_hal_spec_8812a(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8821A
|
|
case RTL8821:
|
|
init_hal_spec_8821a(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8192E
|
|
case RTL8192E:
|
|
init_hal_spec_8192e(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8814A
|
|
case RTL8814A:
|
|
init_hal_spec_8814a(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8822B
|
|
case RTL8822B:
|
|
rtl8822b_init_hal_spec(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8821C
|
|
case RTL8821C:
|
|
init_hal_spec_rtl8821c(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8710B
|
|
case RTL8710B:
|
|
init_hal_spec_8710b(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8192F
|
|
case RTL8192F:
|
|
init_hal_spec_8192f(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8822C
|
|
case RTL8822C:
|
|
rtl8822c_init_hal_spec(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8814B
|
|
case RTL8814B:
|
|
rtl8814b_init_hal_spec(adapter);
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_RTL8723F
|
|
case RTL8723F:
|
|
rtl8723f_init_hal_spec(adapter);
|
|
break;
|
|
#endif
|
|
default:
|
|
RTW_ERR("%s: unknown chip_type:%u\n"
|
|
, __func__, rtw_get_chip_type(adapter));
|
|
ret = _FAIL;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static const char *const _band_cap_str[] = {
|
|
/* BIT0 */"2G",
|
|
/* BIT1 */"5G",
|
|
};
|
|
|
|
static const char *const _bw_cap_str[] = {
|
|
/* BIT0 */"5M",
|
|
/* BIT1 */"10M",
|
|
/* BIT2 */"20M",
|
|
/* BIT3 */"40M",
|
|
/* BIT4 */"80M",
|
|
/* BIT5 */"160M",
|
|
/* BIT6 */"80_80M",
|
|
};
|
|
|
|
static const char *const _proto_cap_str[] = {
|
|
/* BIT0 */"b",
|
|
/* BIT1 */"g",
|
|
/* BIT2 */"n",
|
|
/* BIT3 */"ac",
|
|
};
|
|
|
|
static const char *const _wl_func_str[] = {
|
|
/* BIT0 */"P2P",
|
|
/* BIT1 */"MIRACAST",
|
|
/* BIT2 */"TDLS",
|
|
/* BIT3 */"FTM",
|
|
};
|
|
|
|
void dump_hal_spec(void *sel, _adapter *adapter)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
int i;
|
|
|
|
RTW_PRINT_SEL(sel, "macid_num:%u\n", hal_spec->macid_num);
|
|
RTW_PRINT_SEL(sel, "macid_cap:%u\n", hal_spec->macid_cap);
|
|
RTW_PRINT_SEL(sel, "sec_cap:0x%02x\n", hal_spec->sec_cap);
|
|
RTW_PRINT_SEL(sel, "sec_cam_ent_num:%u\n", hal_spec->sec_cam_ent_num);
|
|
|
|
RTW_PRINT_SEL(sel, "rfpath_num_2g:%u\n", hal_spec->rfpath_num_2g);
|
|
RTW_PRINT_SEL(sel, "rfpath_num_5g:%u\n", hal_spec->rfpath_num_5g);
|
|
RTW_PRINT_SEL(sel, "rf_reg_path_num:%u\n", hal_spec->rf_reg_path_num);
|
|
RTW_PRINT_SEL(sel, "rf_reg_path_avail_num:%u\n", hal_spec->rf_reg_path_avail_num);
|
|
RTW_PRINT_SEL(sel, "rf_reg_trx_path_bmp:0x%02x\n", hal_spec->rf_reg_trx_path_bmp);
|
|
RTW_PRINT_SEL(sel, "max_tx_cnt:%u\n", hal_spec->max_tx_cnt);
|
|
|
|
RTW_PRINT_SEL(sel, "tx_nss_num:%u\n", hal_spec->tx_nss_num);
|
|
RTW_PRINT_SEL(sel, "rx_nss_num:%u\n", hal_spec->rx_nss_num);
|
|
|
|
RTW_PRINT_SEL(sel, "band_cap:");
|
|
for (i = 0; i < BAND_CAP_BIT_NUM; i++) {
|
|
if (((hal_spec->band_cap) >> i) & BIT0 && _band_cap_str[i])
|
|
_RTW_PRINT_SEL(sel, "%s ", _band_cap_str[i]);
|
|
}
|
|
_RTW_PRINT_SEL(sel, "\n");
|
|
|
|
RTW_PRINT_SEL(sel, "bw_cap:");
|
|
for (i = 0; i < BW_CAP_BIT_NUM; i++) {
|
|
if (((hal_spec->bw_cap) >> i) & BIT0 && _bw_cap_str[i])
|
|
_RTW_PRINT_SEL(sel, "%s ", _bw_cap_str[i]);
|
|
}
|
|
_RTW_PRINT_SEL(sel, "\n");
|
|
|
|
RTW_PRINT_SEL(sel, "proto_cap:");
|
|
for (i = 0; i < PROTO_CAP_BIT_NUM; i++) {
|
|
if (((hal_spec->proto_cap) >> i) & BIT0 && _proto_cap_str[i])
|
|
_RTW_PRINT_SEL(sel, "%s ", _proto_cap_str[i]);
|
|
}
|
|
_RTW_PRINT_SEL(sel, "\n");
|
|
|
|
RTW_PRINT_SEL(sel, "txgi_max:%u\n", hal_spec->txgi_max);
|
|
RTW_PRINT_SEL(sel, "txgi_pdbm:%u\n", hal_spec->txgi_pdbm);
|
|
|
|
RTW_PRINT_SEL(sel, "wl_func:");
|
|
for (i = 0; i < WL_FUNC_BIT_NUM; i++) {
|
|
if (((hal_spec->wl_func) >> i) & BIT0 && _wl_func_str[i])
|
|
_RTW_PRINT_SEL(sel, "%s ", _wl_func_str[i]);
|
|
}
|
|
_RTW_PRINT_SEL(sel, "\n");
|
|
|
|
#if CONFIG_TX_AC_LIFETIME
|
|
RTW_PRINT_SEL(sel, "tx_aclt_unit_factor:%u (unit:%uus)\n"
|
|
, hal_spec->tx_aclt_unit_factor, hal_spec->tx_aclt_unit_factor * 32);
|
|
#endif
|
|
|
|
RTW_PRINT_SEL(sel, "rx_tsf_filter:%u\n", hal_spec->rx_tsf_filter);
|
|
|
|
RTW_PRINT_SEL(sel, "pg_txpwr_saddr:0x%X\n", hal_spec->pg_txpwr_saddr);
|
|
RTW_PRINT_SEL(sel, "pg_txgi_diff_factor:%u\n", hal_spec->pg_txgi_diff_factor);
|
|
}
|
|
|
|
inline bool hal_chk_band_cap(_adapter *adapter, u8 cap)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->band_cap & cap;
|
|
}
|
|
|
|
inline bool hal_chk_bw_cap(_adapter *adapter, u8 cap)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->bw_cap & cap;
|
|
}
|
|
|
|
inline bool hal_chk_proto_cap(_adapter *adapter, u8 cap)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->proto_cap & cap;
|
|
}
|
|
|
|
inline bool hal_chk_wl_func(_adapter *adapter, u8 func)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->wl_func & func;
|
|
}
|
|
|
|
inline bool hal_is_band_support(_adapter *adapter, u8 band)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->band_cap & band_to_band_cap(band);
|
|
}
|
|
|
|
inline bool hal_is_bw_support(_adapter *adapter, u8 bw)
|
|
{
|
|
return GET_HAL_SPEC(adapter)->bw_cap & ch_width_to_bw_cap(bw);
|
|
}
|
|
|
|
inline bool hal_is_wireless_mode_support(_adapter *adapter, u8 mode)
|
|
{
|
|
u8 proto_cap = GET_HAL_SPEC(adapter)->proto_cap;
|
|
|
|
if (mode == WIRELESS_11B)
|
|
if ((proto_cap & PROTO_CAP_11B) && hal_chk_band_cap(adapter, BAND_CAP_2G))
|
|
return 1;
|
|
|
|
if (mode == WIRELESS_11G)
|
|
if ((proto_cap & PROTO_CAP_11G) && hal_chk_band_cap(adapter, BAND_CAP_2G))
|
|
return 1;
|
|
|
|
if (mode == WIRELESS_11A)
|
|
if ((proto_cap & PROTO_CAP_11G) && hal_chk_band_cap(adapter, BAND_CAP_5G))
|
|
return 1;
|
|
|
|
if (mode == WIRELESS_11_24N)
|
|
if ((proto_cap & PROTO_CAP_11N) && hal_chk_band_cap(adapter, BAND_CAP_2G))
|
|
return 1;
|
|
|
|
if (mode == WIRELESS_11_5N)
|
|
if ((proto_cap & PROTO_CAP_11N) && hal_chk_band_cap(adapter, BAND_CAP_5G))
|
|
return 1;
|
|
|
|
if (mode == WIRELESS_11AC)
|
|
if ((proto_cap & PROTO_CAP_11AC) && hal_chk_band_cap(adapter, BAND_CAP_5G))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
inline bool hal_is_mimo_support(_adapter *adapter)
|
|
{
|
|
if ((GET_HAL_TX_NSS(adapter) == 1) &&
|
|
(GET_HAL_RX_NSS(adapter) == 1))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* hal_largest_bw - starting from in_bw, get largest bw supported by HAL
|
|
* @adapter:
|
|
* @in_bw: starting bw, value of enum channel_width
|
|
*
|
|
* Returns: value of enum channel_width
|
|
*/
|
|
u8 hal_largest_bw(_adapter *adapter, u8 in_bw)
|
|
{
|
|
for (; in_bw > CHANNEL_WIDTH_20; in_bw--) {
|
|
if (hal_is_bw_support(adapter, in_bw))
|
|
break;
|
|
}
|
|
|
|
if (!hal_is_bw_support(adapter, in_bw))
|
|
rtw_warn_on(1);
|
|
|
|
return in_bw;
|
|
}
|
|
|
|
#ifndef CONFIG_HAS_TX_BEACON_PAUSE
|
|
void ResumeTxBeacon(_adapter *padapter)
|
|
{
|
|
RTW_DBG("ResumeTxBeacon\n");
|
|
#ifdef CONFIG_STOP_RESUME_BCN_BY_TXPAUSE
|
|
rtw_write8(padapter, REG_TXPAUSE,
|
|
rtw_read8(padapter, REG_TXPAUSE) & (~BIT6));
|
|
#else
|
|
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
|
|
rtw_read8(padapter, REG_FWHW_TXQ_CTRL + 2) | BIT(6));
|
|
#endif
|
|
|
|
#ifdef RTW_HALMAC
|
|
/* Add this for driver using HALMAC because driver doesn't have setup time init by self */
|
|
/* TBTT setup time */
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT, TBTT_PROHIBIT_SETUP_TIME);
|
|
#endif
|
|
/* TBTT hold time: 0x540[19:8] */
|
|
#ifdef CONFIG_NARROWBAND_SUPPORTING
|
|
if (padapter->registrypriv.rtw_nb_config == RTW_NB_CONFIG_WIDTH_10)
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xc8);
|
|
else
|
|
#endif
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, TBTT_PROHIBIT_HOLD_TIME & 0xFF);
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT + 2,
|
|
(rtw_read8(padapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROHIBIT_HOLD_TIME >> 8));
|
|
}
|
|
|
|
void StopTxBeacon(_adapter *padapter)
|
|
{
|
|
RTW_DBG("StopTxBeacon\n");
|
|
#ifdef CONFIG_STOP_RESUME_BCN_BY_TXPAUSE
|
|
rtw_write8(padapter, REG_TXPAUSE,
|
|
rtw_read8(padapter, REG_TXPAUSE) | BIT6);
|
|
#else
|
|
rtw_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
|
|
rtw_read8(padapter, REG_FWHW_TXQ_CTRL + 2) & (~BIT6));
|
|
#endif
|
|
|
|
/* TBTT hold time: 0x540[19:8] */
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT + 1, TBTT_PROHIBIT_HOLD_TIME_STOP_BCN & 0xFF);
|
|
rtw_write8(padapter, REG_TBTT_PROHIBIT + 2,
|
|
(rtw_read8(padapter, REG_TBTT_PROHIBIT + 2) & 0xF0) | (TBTT_PROHIBIT_HOLD_TIME_STOP_BCN >> 8));
|
|
}
|
|
#endif /* CONFIG_HAS_TX_BEACON_PAUSE */
|
|
|
|
#ifdef CONFIG_MI_WITH_MBSSID_CAM /*HW port0 - MBSS*/
|
|
|
|
#ifdef CONFIG_CLIENT_PORT_CFG
|
|
const u8 _clt_port_id[MAX_CLIENT_PORT_NUM] = {
|
|
CLT_PORT0,
|
|
CLT_PORT1,
|
|
CLT_PORT2,
|
|
CLT_PORT3
|
|
};
|
|
|
|
void rtw_clt_port_init(struct clt_port_t *cltp)
|
|
{
|
|
cltp->bmp = 0;
|
|
cltp->num = 0;
|
|
_rtw_spinlock_init(&cltp->lock);
|
|
}
|
|
void rtw_clt_port_deinit(struct clt_port_t *cltp)
|
|
{
|
|
_rtw_spinlock_free(&cltp->lock);
|
|
}
|
|
static void _hw_client_port_alloc(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct clt_port_t *cltp = &dvobj->clt_port;
|
|
_irqL irql;
|
|
int i;
|
|
|
|
#if 0
|
|
if (cltp->num > MAX_CLIENT_PORT_NUM) {
|
|
RTW_ERR(ADPT_FMT" cann't alloc client (%d)\n", ADPT_ARG(adapter), cltp->num);
|
|
rtw_warn_on(1);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (adapter->client_id != MAX_CLIENT_PORT_NUM) {
|
|
RTW_INFO(ADPT_FMT" client_id %d has allocated port:%d\n",
|
|
ADPT_ARG(adapter), adapter->client_id, adapter->client_port);
|
|
return;
|
|
}
|
|
_enter_critical_bh(&cltp->lock, &irql);
|
|
for (i = 0; i < MAX_CLIENT_PORT_NUM; i++) {
|
|
if (!(cltp->bmp & BIT(i)))
|
|
break;
|
|
}
|
|
|
|
if (i < MAX_CLIENT_PORT_NUM) {
|
|
adapter->client_id = i;
|
|
cltp->bmp |= BIT(i);
|
|
adapter->client_port = _clt_port_id[i];
|
|
}
|
|
cltp->num++;
|
|
_exit_critical_bh(&cltp->lock, &irql);
|
|
RTW_INFO("%s("ADPT_FMT")id:%d, port:%d clt_num:%d\n",
|
|
__func__, ADPT_ARG(adapter), adapter->client_id, adapter->client_port, cltp->num);
|
|
}
|
|
static void _hw_client_port_free(_adapter *adapter)
|
|
{
|
|
struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
|
|
struct clt_port_t *cltp = &dvobj->clt_port;
|
|
_irqL irql;
|
|
|
|
#if 0
|
|
if (adapter->client_id >= MAX_CLIENT_PORT_NUM) {
|
|
RTW_ERR(ADPT_FMT" client_id %d is invalid\n", ADPT_ARG(adapter), adapter->client_id);
|
|
/*rtw_warn_on(1);*/
|
|
}
|
|
#endif
|
|
|
|
RTW_INFO("%s ("ADPT_FMT") id:%d, port:%d clt_num:%d\n",
|
|
__func__, ADPT_ARG(adapter), adapter->client_id, adapter->client_port, cltp->num);
|
|
|
|
_enter_critical_bh(&cltp->lock, &irql);
|
|
if (adapter->client_id != MAX_CLIENT_PORT_NUM) {
|
|
cltp->bmp &= ~ BIT(adapter->client_id);
|
|
adapter->client_id = MAX_CLIENT_PORT_NUM;
|
|
adapter->client_port = CLT_PORT_INVALID;
|
|
}
|
|
cltp->num--;
|
|
if (cltp->num < 0)
|
|
cltp->num = 0;
|
|
_exit_critical_bh(&cltp->lock, &irql);
|
|
}
|
|
void rtw_hw_client_port_allocate(_adapter *adapter)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
|
|
if (hal_spec->port_num != 5)
|
|
return;
|
|
|
|
_hw_client_port_alloc(adapter);
|
|
}
|
|
void rtw_hw_client_port_release(_adapter *adapter)
|
|
{
|
|
struct hal_spec_t *hal_spec = GET_HAL_SPEC(adapter);
|
|
|
|
if (hal_spec->port_num != 5)
|
|
return;
|
|
|
|
_hw_client_port_free(adapter);
|
|
}
|
|
#endif /*CONFIG_CLIENT_PORT_CFG*/
|
|
|
|
void hw_var_set_opmode_mbid(_adapter *Adapter, u8 mode)
|
|
{
|
|
RTW_INFO("%s()-"ADPT_FMT" mode = %d\n", __func__, ADPT_ARG(Adapter), mode);
|
|
|
|
rtw_hal_rcr_set_chk_bssid(Adapter, MLME_ACTION_NONE);
|
|
|
|
/* set net_type */
|
|
Set_MSR(Adapter, mode);
|
|
|
|
if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
|
|
if (!rtw_mi_get_ap_num(Adapter) && !rtw_mi_get_mesh_num(Adapter))
|
|
StopTxBeacon(Adapter);
|
|
} else if (mode == _HW_STATE_ADHOC_)
|
|
ResumeTxBeacon(Adapter);
|
|
else if (mode == _HW_STATE_AP_)
|
|
/* enable rx ps-poll */
|
|
rtw_write16(Adapter, REG_RXFLTMAP1, rtw_read16(Adapter, REG_RXFLTMAP1) | BIT_CTRLFLT10EN);
|
|
|
|
/* enable rx data frame */
|
|
rtw_write16(Adapter, REG_RXFLTMAP2, 0xFFFF);
|
|
|
|
#ifdef CONFIG_CLIENT_PORT_CFG
|
|
if (mode == _HW_STATE_STATION_)
|
|
rtw_hw_client_port_allocate(Adapter);
|
|
else
|
|
rtw_hw_client_port_release(Adapter);
|
|
#endif
|
|
#if defined(CONFIG_RTL8192F)
|
|
rtw_write16(Adapter, REG_WLAN_ACT_MASK_CTRL_1, rtw_read16(Adapter,
|
|
REG_WLAN_ACT_MASK_CTRL_1) | EN_PORT_0_FUNCTION);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_ANTENNA_DIVERSITY
|
|
u8 rtw_hal_antdiv_before_linked(_adapter *padapter)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
u8 cur_ant, change_ant;
|
|
|
|
if (!pHalData->AntDivCfg)
|
|
return _FALSE;
|
|
|
|
if (pHalData->sw_antdiv_bl_state == 0) {
|
|
pHalData->sw_antdiv_bl_state = 1;
|
|
|
|
rtw_hal_get_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &cur_ant, NULL);
|
|
change_ant = (cur_ant == MAIN_ANT) ? AUX_ANT : MAIN_ANT;
|
|
|
|
return rtw_antenna_select_cmd(padapter, change_ant, _FALSE);
|
|
}
|
|
|
|
pHalData->sw_antdiv_bl_state = 0;
|
|
return _FALSE;
|
|
}
|
|
|
|
void rtw_hal_antdiv_rssi_compared(_adapter *padapter, WLAN_BSSID_EX *dst, WLAN_BSSID_EX *src)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
|
|
if (pHalData->AntDivCfg) {
|
|
/*RTW_INFO("update_network=> org-RSSI(%d), new-RSSI(%d)\n", dst->Rssi, src->Rssi);*/
|
|
/*select optimum_antenna for before linked =>For antenna diversity*/
|
|
if (dst->Rssi >= src->Rssi) {/*keep org parameter*/
|
|
src->Rssi = dst->Rssi;
|
|
src->PhyInfo.Optimum_antenna = dst->PhyInfo.Optimum_antenna;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_PROC_DEBUG
|
|
#ifdef CONFIG_PHY_CAPABILITY_QUERY
|
|
void rtw_dump_phy_cap_by_phydmapi(void *sel, _adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
|
|
struct phy_spec_t *phy_spec = &pHalData->phy_spec;
|
|
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] TRx Capability : 0x%08x\n", phy_spec->trx_cap);
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] Tx Stream Num Index : %d\n", (phy_spec->trx_cap >> 24) & 0xFF); /*Tx Stream Num Index [31:24]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] Rx Stream Num Index : %d\n", (phy_spec->trx_cap >> 16) & 0xFF); /*Rx Stream Num Index [23:16]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] Tx Path Num Index : %d\n", (phy_spec->trx_cap >> 8) & 0xFF);/*Tx Path Num Index [15:8]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] Rx Path Num Index : %d\n\n", (phy_spec->trx_cap & 0xFF));/*Rx Path Num Index [7:0]*/
|
|
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] STBC Capability : 0x%08x\n", phy_spec->stbc_cap);
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT STBC Tx : %s\n", ((phy_spec->stbc_cap >> 24) & 0xFF) ? "Supported" : "N/A"); /*VHT STBC Tx [31:24]*/
|
|
/*VHT STBC Rx [23:16]
|
|
0 = not support
|
|
1 = support for 1 spatial stream
|
|
2 = support for 1 or 2 spatial streams
|
|
3 = support for 1 or 2 or 3 spatial streams
|
|
4 = support for 1 or 2 or 3 or 4 spatial streams*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT STBC Rx :%d\n", ((phy_spec->stbc_cap >> 16) & 0xFF));
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT STBC Tx : %s\n", ((phy_spec->stbc_cap >> 8) & 0xFF) ? "Supported" : "N/A"); /*HT STBC Tx [15:8]*/
|
|
/*HT STBC Rx [7:0]
|
|
0 = not support
|
|
1 = support for 1 spatial stream
|
|
2 = support for 1 or 2 spatial streams
|
|
3 = support for 1 or 2 or 3 spatial streams*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT STBC Rx : %d\n\n", (phy_spec->stbc_cap & 0xFF));
|
|
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] LDPC Capability : 0x%08x\n", phy_spec->ldpc_cap);
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT LDPC Tx : %s\n", ((phy_spec->ldpc_cap >> 24) & 0xFF) ? "Supported" : "N/A"); /*VHT LDPC Tx [31:24]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT LDPC Rx : %s\n", ((phy_spec->ldpc_cap >> 16) & 0xFF) ? "Supported" : "N/A"); /*VHT LDPC Rx [23:16]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT LDPC Tx : %s\n", ((phy_spec->ldpc_cap >> 8) & 0xFF) ? "Supported" : "N/A"); /*HT LDPC Tx [15:8]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT LDPC Rx : %s\n\n", (phy_spec->ldpc_cap & 0xFF) ? "Supported" : "N/A"); /*HT LDPC Rx [7:0]*/
|
|
#ifdef CONFIG_BEAMFORMING
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] TxBF Capability : 0x%08x\n", phy_spec->txbf_cap);
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT MU Bfer : %s\n", ((phy_spec->txbf_cap >> 28) & 0xF) ? "Supported" : "N/A"); /*VHT MU Bfer [31:28]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT MU Bfee : %s\n", ((phy_spec->txbf_cap >> 24) & 0xF) ? "Supported" : "N/A"); /*VHT MU Bfee [27:24]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT SU Bfer : %s\n", ((phy_spec->txbf_cap >> 20) & 0xF) ? "Supported" : "N/A"); /*VHT SU Bfer [23:20]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT SU Bfee : %s\n", ((phy_spec->txbf_cap >> 16) & 0xF) ? "Supported" : "N/A"); /*VHT SU Bfee [19:16]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT Bfer : %s\n", ((phy_spec->txbf_cap >> 4) & 0xF) ? "Supported" : "N/A"); /*HT Bfer [7:4]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT Bfee : %s\n\n", (phy_spec->txbf_cap & 0xF) ? "Supported" : "N/A"); /*HT Bfee [3:0]*/
|
|
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] TxBF parameter : 0x%08x\n", phy_spec->txbf_param);
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT Sounding Dim : %d\n", (phy_spec->txbf_param >> 24) & 0xFF); /*VHT Sounding Dim [31:24]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] VHT Steering Ant : %d\n", (phy_spec->txbf_param >> 16) & 0xFF); /*VHT Steering Ant [23:16]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT Sounding Dim : %d\n", (phy_spec->txbf_param >> 8) & 0xFF); /*HT Sounding Dim [15:8]*/
|
|
RTW_PRINT_SEL(sel, "[PHY SPEC] HT Steering Ant : %d\n", phy_spec->txbf_param & 0xFF); /*HT Steering Ant [7:0]*/
|
|
#endif
|
|
}
|
|
#else
|
|
void rtw_dump_phy_cap_by_hal(void *sel, _adapter *adapter)
|
|
{
|
|
u8 phy_cap = _FALSE;
|
|
|
|
/* STBC */
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_STBC, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] STBC Tx : %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_STBC, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] STBC Rx : %s\n\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
/* LDPC support */
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_TX_LDPC, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] LDPC Tx : %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_RX_LDPC, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] LDPC Rx : %s\n\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
#ifdef CONFIG_BEAMFORMING
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] Beamformer: %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] Beamformee: %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_VHT_MU_BEAMFORMER, &phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] VHT MU Beamformer: %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
|
|
phy_cap = _FALSE;
|
|
rtw_hal_get_def_var(adapter, HAL_DEF_VHT_MU_BEAMFORMEE, &phy_cap);
|
|
RTW_PRINT_SEL(sel, "[HAL] VHT MU Beamformee: %s\n", (_TRUE == phy_cap) ? "Supported" : "N/A");
|
|
#endif
|
|
}
|
|
#endif
|
|
void rtw_dump_phy_cap(void *sel, _adapter *adapter)
|
|
{
|
|
RTW_PRINT_SEL(sel, "\n ======== PHY Capability ========\n");
|
|
#ifdef CONFIG_PHY_CAPABILITY_QUERY
|
|
rtw_dump_phy_cap_by_phydmapi(sel, adapter);
|
|
#else
|
|
rtw_dump_phy_cap_by_hal(sel, adapter);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
inline s16 translate_dbm_to_percentage(s16 signal)
|
|
{
|
|
if ((signal <= -100) || (signal >= 20))
|
|
return 0;
|
|
else if (signal >= 0)
|
|
return 100;
|
|
else
|
|
return 100 + signal;
|
|
}
|
|
|
|
#ifdef CONFIG_SWTIMER_BASED_TXBCN
|
|
#ifdef CONFIG_BCN_RECOVERY
|
|
#define REG_CPU_MGQ_INFO 0x041C
|
|
#define BIT_BCN_POLL BIT(28)
|
|
u8 rtw_ap_bcn_recovery(_adapter *padapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
|
|
|
|
if (hal_data->issue_bcn_fail >= 2) {
|
|
RTW_ERR("%s ISSUE BCN Fail\n", __func__);
|
|
rtw_write8(padapter, REG_CPU_MGQ_INFO + 3, 0x10);
|
|
hal_data->issue_bcn_fail = 0;
|
|
}
|
|
return _SUCCESS;
|
|
}
|
|
#endif /*CONFIG_BCN_RECOVERY*/
|
|
|
|
#ifdef CONFIG_BCN_XMIT_PROTECT
|
|
u8 rtw_ap_bcn_queue_empty_check(_adapter *padapter, u32 txbcn_timer_ms)
|
|
{
|
|
u32 start_time = rtw_get_current_time();
|
|
u8 bcn_queue_empty = _FALSE;
|
|
|
|
do {
|
|
if (rtw_read16(padapter, REG_TXPKT_EMPTY) & BIT(11)) {
|
|
bcn_queue_empty = _TRUE;
|
|
break;
|
|
}
|
|
} while (rtw_get_passing_time_ms(start_time) <= (txbcn_timer_ms + 10));
|
|
|
|
if (bcn_queue_empty == _FALSE)
|
|
RTW_ERR("%s BCN queue not empty\n", __func__);
|
|
|
|
return bcn_queue_empty;
|
|
}
|
|
#endif /*CONFIG_BCN_XMIT_PROTECT*/
|
|
#endif /*CONFIG_SWTIMER_BASED_TXBCN*/
|
|
|
|
/**
|
|
* rtw_hal_get_trx_path() - Get RF path related information
|
|
* @d: struct dvobj_priv*
|
|
* @type: RF type, nTnR
|
|
* @tx: Tx path
|
|
* @rx: Rx path
|
|
*
|
|
* Get RF type, TX path and RX path information.
|
|
*/
|
|
void rtw_hal_get_trx_path(struct dvobj_priv *d, enum rf_type *type,
|
|
enum bb_path *tx, enum bb_path *rx)
|
|
{
|
|
struct _ADAPTER *a = dvobj_get_primary_adapter(d);
|
|
enum rf_type t = GET_HAL_RFPATH(a);
|
|
|
|
if (type)
|
|
*type = t;
|
|
|
|
if (tx || rx) {
|
|
u8 tx_bmp = GET_HAL_TX_PATH_BMP(a);
|
|
u8 rx_bmp = GET_HAL_RX_PATH_BMP(a);
|
|
|
|
if (!tx_bmp && !rx_bmp)
|
|
rf_type_to_default_trx_bmp(t, tx, rx);
|
|
else {
|
|
if (tx)
|
|
*tx = GET_HAL_TX_PATH_BMP(a);
|
|
if (rx)
|
|
*rx = GET_HAL_RX_PATH_BMP(a);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef RTW_CHANNEL_SWITCH_OFFLOAD
|
|
void rtw_hal_switch_chnl_and_set_bw_offload(_adapter *adapter, u8 central_ch, u8 pri_ch_idx, u8 bw)
|
|
{
|
|
u8 h2c[H2C_SINGLE_CHANNELSWITCH_V2_LEN] = {0};
|
|
PHAL_DATA_TYPE hal;
|
|
struct submit_ctx *chsw_sctx;
|
|
|
|
hal = GET_HAL_DATA(adapter);
|
|
chsw_sctx = &hal->chsw_sctx;
|
|
|
|
SET_H2CCMD_SINGLE_CH_SWITCH_V2_CENTRAL_CH_NUM(h2c, central_ch);
|
|
SET_H2CCMD_SINGLE_CH_SWITCH_V2_PRIMARY_CH_IDX(h2c, pri_ch_idx);
|
|
SET_H2CCMD_SINGLE_CH_SWITCH_V2_BW(h2c, bw);
|
|
SET_H2CCMD_SINGLE_CH_SWITCH_V2_IQK_UPDATE_EN(h2c, 1);
|
|
|
|
rtw_sctx_init(chsw_sctx, 10);
|
|
rtw_hal_fill_h2c_cmd(adapter, H2C_SINGLE_CHANNELSWITCH_V2, H2C_SINGLE_CHANNELSWITCH_V2_LEN, h2c);
|
|
rtw_sctx_wait(chsw_sctx, __func__);
|
|
}
|
|
#endif /* RTW_CHANNEL_SWITCH_OFFLOAD */
|
|
|
|
u8 phy_get_capable_tx_num(_adapter *adapter, enum MGN_RATE rate)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 tx_num = 0;
|
|
|
|
if (IS_1T_RATE(rate))
|
|
tx_num = hal_data->txpath_cap_num_nss[0];
|
|
else if (IS_2T_RATE(rate))
|
|
tx_num = hal_data->txpath_cap_num_nss[1];
|
|
else if (IS_3T_RATE(rate))
|
|
tx_num = hal_data->txpath_cap_num_nss[2];
|
|
else if (IS_4T_RATE(rate))
|
|
tx_num = hal_data->txpath_cap_num_nss[3];
|
|
else
|
|
rtw_warn_on(1);
|
|
|
|
return tx_num == 0 ? RF_1TX : tx_num - 1;
|
|
}
|
|
|
|
u8 phy_get_current_tx_num(_adapter *adapter, enum MGN_RATE rate)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
u8 tx_num = 0;
|
|
PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
|
|
ANTENNA_PATH anttx = hal->antenna_tx_path;
|
|
|
|
if (rtw_mp_mode_check(adapter)) {
|
|
switch (anttx) {
|
|
case ANTENNA_A:
|
|
case ANTENNA_B:
|
|
case ANTENNA_C:
|
|
case ANTENNA_D:
|
|
tx_num = RF_1TX;
|
|
break;
|
|
case ANTENNA_AB:
|
|
case ANTENNA_AC:
|
|
case ANTENNA_AD:
|
|
case ANTENNA_BC:
|
|
case ANTENNA_BD:
|
|
case ANTENNA_CD:
|
|
tx_num = RF_2TX;
|
|
break;
|
|
case ANTENNA_ABC:
|
|
case ANTENNA_BCD:
|
|
case ANTENNA_ABD:
|
|
case ANTENNA_ACD:
|
|
tx_num = RF_3TX;
|
|
break;
|
|
case ANTENNA_ABCD:
|
|
tx_num = RF_4TX;
|
|
break;
|
|
default:
|
|
tx_num = RF_1TX;
|
|
break;
|
|
}
|
|
|
|
return tx_num;
|
|
} else {
|
|
if (IS_1T_RATE(rate))
|
|
tx_num = hal_data->txpath_num_nss[0];
|
|
else if (IS_2T_RATE(rate))
|
|
tx_num = hal_data->txpath_num_nss[1];
|
|
else if (IS_3T_RATE(rate))
|
|
tx_num = hal_data->txpath_num_nss[2];
|
|
else if (IS_4T_RATE(rate))
|
|
tx_num = hal_data->txpath_num_nss[3];
|
|
else
|
|
rtw_warn_on(1);
|
|
|
|
return tx_num == 0 ? RF_1TX : tx_num - 1;
|
|
}
|
|
}
|
|
|
|
#ifdef CONFIG_RTL8812A
|
|
u8 * rtw_hal_set_8812a_vendor_ie(_adapter *padapter , u8 *pframe ,uint *frlen ) {
|
|
int vender_len = 7;
|
|
unsigned char vendor_info[vender_len];
|
|
unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
|
|
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
|
|
|
|
if( !IS_HARDWARE_TYPE_8812(padapter) )
|
|
return pframe;
|
|
|
|
_rtw_memset(vendor_info,0,vender_len);
|
|
_rtw_memcpy(vendor_info, REALTEK_OUI, 3);
|
|
vendor_info[4] =2;
|
|
if(pHalData->version_id.CUTVersion > B_CUT_VERSION )
|
|
vendor_info[6] = RT_HT_CAP_USE_JAGUAR_CCUT;
|
|
else
|
|
vendor_info[6] = RT_HT_CAP_USE_JAGUAR_BCUT;
|
|
pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_,vender_len,vendor_info , frlen);
|
|
|
|
return pframe;
|
|
}
|
|
#endif /*CONFIG_RTL8812A*/
|
|
|
|
static inline void rtw_enter_protsel(struct protsel *protsel, u32 sel)
|
|
{
|
|
int refcnt;
|
|
|
|
_enter_critical_mutex(&protsel->mutex, NULL);
|
|
|
|
refcnt = ATOMIC_INC_RETURN(&protsel->refcnt);
|
|
|
|
WARN_ON(refcnt > 1 && protsel->sel != sel);
|
|
|
|
protsel->sel = sel;
|
|
|
|
_exit_critical_mutex(&protsel->mutex, NULL);
|
|
}
|
|
|
|
static inline void rtw_leave_protsel(struct protsel *protsel)
|
|
{
|
|
int refcnt;
|
|
|
|
_enter_critical_mutex(&protsel->mutex, NULL);
|
|
|
|
refcnt = ATOMIC_DEC_RETURN(&protsel->refcnt);
|
|
|
|
_exit_critical_mutex(&protsel->mutex, NULL);
|
|
|
|
WARN_ON(refcnt < 0);
|
|
}
|
|
|
|
static inline bool rtw_assert_protsel(struct protsel *protsel)
|
|
{
|
|
int refcnt = ATOMIC_READ(&protsel->refcnt);
|
|
|
|
if (refcnt > 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
#ifdef CONFIG_PROTSEL_PORT
|
|
void rtw_enter_protsel_port(_adapter *padapter, u8 port_sel)
|
|
{
|
|
u8 val8;
|
|
|
|
rtw_enter_protsel(&padapter->dvobj->protsel_port, port_sel);
|
|
|
|
val8 = rtw_read8(padapter, REG_PORT_CTRL_SEL);
|
|
val8 &= ~BIT_MASK_PORT_CTRL_SEL;
|
|
val8 |= BIT_PORT_CTRL_SEL(port_sel);
|
|
rtw_write8(padapter, REG_PORT_CTRL_SEL, val8);
|
|
}
|
|
|
|
bool rtw_assert_protsel_port(_adapter *padapter, u32 addr, u8 len)
|
|
{
|
|
if (!padapter->bup) /* don't assert before IF up */
|
|
return true;
|
|
|
|
return rtw_assert_protsel(&padapter->dvobj->protsel_port);
|
|
}
|
|
|
|
void rtw_leave_protsel_port(_adapter *padapter)
|
|
{
|
|
rtw_leave_protsel(&padapter->dvobj->protsel_port);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_PROTSEL_ATIMDTIM
|
|
void rtw_enter_protsel_atimdtim(_adapter *padapter, u8 port_sel)
|
|
{
|
|
/* 0~15 is for port 0 MBSSID setting
|
|
* 16 is for port 1 setting
|
|
* 17 is for port 2 setting
|
|
* 18 is for port 3 setting
|
|
* 19 is for port 4 setting
|
|
*/
|
|
u8 val8;
|
|
|
|
if (port_sel >= 1 && port_sel <= 4)
|
|
port_sel += 15;
|
|
|
|
rtw_enter_protsel(&padapter->dvobj->protsel_atimdtim, port_sel);
|
|
|
|
val8 = rtw_read8(padapter, REG_ATIM_DTIM_CTRL_SEL);
|
|
val8 &= ~BIT_MASK_ATIM_DTIM_SEL;
|
|
val8 |= BIT_ATIM_DTIM_SEL(port_sel);
|
|
rtw_write8(padapter, REG_ATIM_DTIM_CTRL_SEL, val8);
|
|
}
|
|
|
|
bool rtw_assert_protsel_atimdtim(_adapter *padapter, u32 addr, u8 len)
|
|
{
|
|
return rtw_assert_protsel(&padapter->dvobj->protsel_atimdtim);
|
|
}
|
|
|
|
void rtw_leave_protsel_atimdtim(_adapter *padapter)
|
|
{
|
|
rtw_leave_protsel(&padapter->dvobj->protsel_atimdtim);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_PROTSEL_MACSLEEP
|
|
void rtw_enter_protsel_macsleep(_adapter *padapter, u8 sel)
|
|
{
|
|
u32 val32;
|
|
|
|
rtw_enter_protsel(&padapter->dvobj->protsel_macsleep, sel);
|
|
|
|
val32 = rtw_read32(padapter, REG_MACID_SLEEP_CTRL);
|
|
val32 &= ~BIT_MASK_MACID_SLEEP_SEL;
|
|
val32 |= BIT_MACID_SLEEP_SEL(sel);
|
|
rtw_write32(padapter, REG_MACID_SLEEP_CTRL, val32);
|
|
}
|
|
|
|
bool rtw_assert_protsel_macsleep(_adapter *padapter, u32 addr, u8 len)
|
|
{
|
|
return rtw_assert_protsel(&padapter->dvobj->protsel_macsleep);
|
|
}
|
|
|
|
void rtw_leave_protsel_macsleep(_adapter *padapter)
|
|
{
|
|
rtw_leave_protsel(&padapter->dvobj->protsel_macsleep);
|
|
}
|
|
#endif
|
|
|
|
void rtw_hal_bcn_early_rpt_c2h_handler(_adapter *padapter)
|
|
{
|
|
if(0)
|
|
RTW_INFO("Recv Bcn Early report!!\n");
|
|
|
|
#ifdef CONFIG_AP_MODE
|
|
rtw_mi_update_csa(padapter);
|
|
#endif
|
|
|
|
#ifdef CONFIG_TDLS
|
|
#ifdef CONFIG_TDLS_CH_SW
|
|
if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) == _TRUE)
|
|
rtw_tdls_ch_sw_back_to_base_chnl(padapter);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#ifndef RTW_HALMAC
|
|
void rtw_hal_init_sifs_backup(_adapter *adapter)
|
|
{
|
|
HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
|
|
|
|
hal_data->init_reg_0x428 = rtw_read16(adapter, 0x428);
|
|
hal_data->init_reg_0x514 = rtw_read32(adapter, 0x514);
|
|
hal_data->init_reg_0x63a = rtw_read16(adapter, 0x63a);
|
|
hal_data->init_reg_0x63c = rtw_read32(adapter, 0x63c);
|
|
|
|
#ifndef RTW_SIFS_INIT_CHK
|
|
#define RTW_SIFS_INIT_CHK 1
|
|
#endif
|
|
|
|
#if RTW_SIFS_INIT_CHK
|
|
/*
|
|
the expected initial values:
|
|
0x428[15:0]=0x100A
|
|
0x514[31:0]=0x0E0A0E0A
|
|
0x63A[15:0]=0x100A
|
|
0x63C[31:0]=0x0E0E0A0A
|
|
*/
|
|
#define INIT_REG_0x428 0x100A
|
|
#define INIT_REG_0x514 0x0E0A0E0A
|
|
#define INIT_REG_0x63A 0x100A
|
|
#define INIT_REG_0x63C 0x0E0E0A0A
|
|
|
|
if (hal_data->init_reg_0x428 != INIT_REG_0x428) {
|
|
RTW_WARN("init_reg_0x428:0x%04x != 0x%04x\n", hal_data->init_reg_0x428, INIT_REG_0x428);
|
|
#if RTW_SIFS_INIT_CHK > 1
|
|
hal_data->init_reg_0x428 = INIT_REG_0x428;
|
|
rtw_write16(adapter, 0x428, hal_data->init_reg_0x428);
|
|
#endif
|
|
}
|
|
if (hal_data->init_reg_0x514 != INIT_REG_0x514) {
|
|
RTW_WARN("init_reg_0x514:0x%08x != 0x%08x\n", hal_data->init_reg_0x514, INIT_REG_0x514);
|
|
#if RTW_SIFS_INIT_CHK > 1
|
|
hal_data->init_reg_0x514 = INIT_REG_0x514;
|
|
rtw_write32(adapter, 0x514, hal_data->init_reg_0x514);
|
|
#endif
|
|
}
|
|
if (hal_data->init_reg_0x63a != INIT_REG_0x63A) {
|
|
RTW_WARN("init_reg_0x63a:0x%04x != 0x%04x\n", hal_data->init_reg_0x63a, INIT_REG_0x63A);
|
|
#if RTW_SIFS_INIT_CHK > 1
|
|
hal_data->init_reg_0x63a = INIT_REG_0x63A;
|
|
rtw_write16(adapter, 0x63a, hal_data->init_reg_0x63a);
|
|
#endif
|
|
}
|
|
if (hal_data->init_reg_0x63c != INIT_REG_0x63C) {
|
|
RTW_WARN("init_reg_0x63c:0x%08x != 0x%08x\n", hal_data->init_reg_0x63c, INIT_REG_0x63C);
|
|
#if RTW_SIFS_INIT_CHK > 1
|
|
hal_data->init_reg_0x63c = INIT_REG_0x63C;
|
|
rtw_write32(adapter, 0x63c, hal_data->init_reg_0x63c);
|
|
#endif
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|