18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * NXP Wireless LAN device driver: station command handling 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2011-2020 NXP 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software file (the "File") is distributed by NXP 78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License Version 2, June 1991 88c2ecf20Sopenharmony_ci * (the "License"). You may use, redistribute and/or modify this File in 98c2ecf20Sopenharmony_ci * accordance with the terms and conditions of the License, a copy of which 108c2ecf20Sopenharmony_ci * is available by writing to the Free Software Foundation, Inc., 118c2ecf20Sopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 128c2ecf20Sopenharmony_ci * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 158c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 168c2ecf20Sopenharmony_ci * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 178c2ecf20Sopenharmony_ci * this warranty disclaimer. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "decl.h" 218c2ecf20Sopenharmony_ci#include "ioctl.h" 228c2ecf20Sopenharmony_ci#include "util.h" 238c2ecf20Sopenharmony_ci#include "fw.h" 248c2ecf20Sopenharmony_ci#include "main.h" 258c2ecf20Sopenharmony_ci#include "wmm.h" 268c2ecf20Sopenharmony_ci#include "11n.h" 278c2ecf20Sopenharmony_ci#include "11ac.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic bool drcs; 308c2ecf20Sopenharmony_cimodule_param(drcs, bool, 0644); 318c2ecf20Sopenharmony_ciMODULE_PARM_DESC(drcs, "multi-channel operation:1, single-channel operation:0"); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic bool disable_auto_ds; 348c2ecf20Sopenharmony_cimodule_param(disable_auto_ds, bool, 0); 358c2ecf20Sopenharmony_ciMODULE_PARM_DESC(disable_auto_ds, 368c2ecf20Sopenharmony_ci "deepsleep enabled=0(default), deepsleep disabled=1"); 378c2ecf20Sopenharmony_ci/* 388c2ecf20Sopenharmony_ci * This function prepares command to set/get RSSI information. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * Preparation includes - 418c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 428c2ecf20Sopenharmony_ci * - Setting data/beacon average factors 438c2ecf20Sopenharmony_ci * - Resetting SNR/NF/RSSI values in private structure 448c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_cistatic int 478c2ecf20Sopenharmony_cimwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv, 488c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, u16 cmd_action) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO); 518c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + 528c2ecf20Sopenharmony_ci S_DS_GEN); 538c2ecf20Sopenharmony_ci cmd->params.rssi_info.action = cpu_to_le16(cmd_action); 548c2ecf20Sopenharmony_ci cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); 558c2ecf20Sopenharmony_ci cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* Reset SNR/NF/RSSI values in private structure */ 588c2ecf20Sopenharmony_ci priv->data_rssi_last = 0; 598c2ecf20Sopenharmony_ci priv->data_nf_last = 0; 608c2ecf20Sopenharmony_ci priv->data_rssi_avg = 0; 618c2ecf20Sopenharmony_ci priv->data_nf_avg = 0; 628c2ecf20Sopenharmony_ci priv->bcn_rssi_last = 0; 638c2ecf20Sopenharmony_ci priv->bcn_nf_last = 0; 648c2ecf20Sopenharmony_ci priv->bcn_rssi_avg = 0; 658c2ecf20Sopenharmony_ci priv->bcn_nf_avg = 0; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return 0; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * This function prepares command to set MAC control. 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * Preparation includes - 748c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 758c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_cistatic int mwifiex_cmd_mac_control(struct mwifiex_private *priv, 788c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 798c2ecf20Sopenharmony_ci u16 cmd_action, u32 *action) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (cmd_action != HostCmd_ACT_GEN_SET) { 848c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 858c2ecf20Sopenharmony_ci "mac_control: only support set cmd\n"); 868c2ecf20Sopenharmony_ci return -1; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL); 908c2ecf20Sopenharmony_ci cmd->size = 918c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); 928c2ecf20Sopenharmony_ci mac_ctrl->action = cpu_to_le32(*action); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci return 0; 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* 988c2ecf20Sopenharmony_ci * This function prepares command to set/get SNMP MIB. 998c2ecf20Sopenharmony_ci * 1008c2ecf20Sopenharmony_ci * Preparation includes - 1018c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 1028c2ecf20Sopenharmony_ci * - Setting SNMP MIB OID number and value 1038c2ecf20Sopenharmony_ci * (as required) 1048c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 1058c2ecf20Sopenharmony_ci * 1068c2ecf20Sopenharmony_ci * The following SNMP MIB OIDs are supported - 1078c2ecf20Sopenharmony_ci * - FRAG_THRESH_I : Fragmentation threshold 1088c2ecf20Sopenharmony_ci * - RTS_THRESH_I : RTS threshold 1098c2ecf20Sopenharmony_ci * - SHORT_RETRY_LIM_I : Short retry limit 1108c2ecf20Sopenharmony_ci * - DOT11D_I : 11d support 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_cistatic int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, 1138c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 1148c2ecf20Sopenharmony_ci u16 cmd_action, u32 cmd_oid, 1158c2ecf20Sopenharmony_ci u16 *ul_temp) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 1208c2ecf20Sopenharmony_ci "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); 1218c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); 1228c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) 1238c2ecf20Sopenharmony_ci - 1 + S_DS_GEN); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci snmp_mib->oid = cpu_to_le16((u16)cmd_oid); 1268c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_GET) { 1278c2ecf20Sopenharmony_ci snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); 1288c2ecf20Sopenharmony_ci snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); 1298c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); 1308c2ecf20Sopenharmony_ci } else if (cmd_action == HostCmd_ACT_GEN_SET) { 1318c2ecf20Sopenharmony_ci snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); 1328c2ecf20Sopenharmony_ci snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); 1338c2ecf20Sopenharmony_ci put_unaligned_le16(*ul_temp, snmp_mib->value); 1348c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, sizeof(u16)); 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 1388c2ecf20Sopenharmony_ci "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t" 1398c2ecf20Sopenharmony_ci "OIDSize=0x%x, Value=0x%x\n", 1408c2ecf20Sopenharmony_ci cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size), 1418c2ecf20Sopenharmony_ci get_unaligned_le16(snmp_mib->value)); 1428c2ecf20Sopenharmony_ci return 0; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* 1468c2ecf20Sopenharmony_ci * This function prepares command to get log. 1478c2ecf20Sopenharmony_ci * 1488c2ecf20Sopenharmony_ci * Preparation includes - 1498c2ecf20Sopenharmony_ci * - Setting command ID and proper size 1508c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_cistatic int 1538c2ecf20Sopenharmony_cimwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); 1568c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + 1578c2ecf20Sopenharmony_ci S_DS_GEN); 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci/* 1628c2ecf20Sopenharmony_ci * This function prepares command to set/get Tx data rate configuration. 1638c2ecf20Sopenharmony_ci * 1648c2ecf20Sopenharmony_ci * Preparation includes - 1658c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 1668c2ecf20Sopenharmony_ci * - Setting configuration index, rate scope and rate drop pattern 1678c2ecf20Sopenharmony_ci * parameters (as required) 1688c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_cistatic int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, 1718c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 1728c2ecf20Sopenharmony_ci u16 cmd_action, u16 *pbitmap_rates) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; 1758c2ecf20Sopenharmony_ci struct mwifiex_rate_scope *rate_scope; 1768c2ecf20Sopenharmony_ci struct mwifiex_rate_drop_pattern *rate_drop; 1778c2ecf20Sopenharmony_ci u32 i; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci rate_cfg->action = cpu_to_le16(cmd_action); 1828c2ecf20Sopenharmony_ci rate_cfg->cfg_index = 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg + 1858c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_tx_rate_cfg)); 1868c2ecf20Sopenharmony_ci rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); 1878c2ecf20Sopenharmony_ci rate_scope->length = cpu_to_le16 1888c2ecf20Sopenharmony_ci (sizeof(*rate_scope) - sizeof(struct mwifiex_ie_types_header)); 1898c2ecf20Sopenharmony_ci if (pbitmap_rates != NULL) { 1908c2ecf20Sopenharmony_ci rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); 1918c2ecf20Sopenharmony_ci rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); 1928c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) 1938c2ecf20Sopenharmony_ci rate_scope->ht_mcs_rate_bitmap[i] = 1948c2ecf20Sopenharmony_ci cpu_to_le16(pbitmap_rates[2 + i]); 1958c2ecf20Sopenharmony_ci if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { 1968c2ecf20Sopenharmony_ci for (i = 0; 1978c2ecf20Sopenharmony_ci i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); 1988c2ecf20Sopenharmony_ci i++) 1998c2ecf20Sopenharmony_ci rate_scope->vht_mcs_rate_bitmap[i] = 2008c2ecf20Sopenharmony_ci cpu_to_le16(pbitmap_rates[10 + i]); 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci } else { 2038c2ecf20Sopenharmony_ci rate_scope->hr_dsss_rate_bitmap = 2048c2ecf20Sopenharmony_ci cpu_to_le16(priv->bitmap_rates[0]); 2058c2ecf20Sopenharmony_ci rate_scope->ofdm_rate_bitmap = 2068c2ecf20Sopenharmony_ci cpu_to_le16(priv->bitmap_rates[1]); 2078c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++) 2088c2ecf20Sopenharmony_ci rate_scope->ht_mcs_rate_bitmap[i] = 2098c2ecf20Sopenharmony_ci cpu_to_le16(priv->bitmap_rates[2 + i]); 2108c2ecf20Sopenharmony_ci if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { 2118c2ecf20Sopenharmony_ci for (i = 0; 2128c2ecf20Sopenharmony_ci i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); 2138c2ecf20Sopenharmony_ci i++) 2148c2ecf20Sopenharmony_ci rate_scope->vht_mcs_rate_bitmap[i] = 2158c2ecf20Sopenharmony_ci cpu_to_le16(priv->bitmap_rates[10 + i]); 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + 2208c2ecf20Sopenharmony_ci sizeof(struct mwifiex_rate_scope)); 2218c2ecf20Sopenharmony_ci rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); 2228c2ecf20Sopenharmony_ci rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); 2238c2ecf20Sopenharmony_ci rate_drop->rate_drop_mode = 0; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci cmd->size = 2268c2ecf20Sopenharmony_ci cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + 2278c2ecf20Sopenharmony_ci sizeof(struct mwifiex_rate_scope) + 2288c2ecf20Sopenharmony_ci sizeof(struct mwifiex_rate_drop_pattern)); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci return 0; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/* 2348c2ecf20Sopenharmony_ci * This function prepares command to set/get Tx power configuration. 2358c2ecf20Sopenharmony_ci * 2368c2ecf20Sopenharmony_ci * Preparation includes - 2378c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 2388c2ecf20Sopenharmony_ci * - Setting Tx power mode, power group TLV 2398c2ecf20Sopenharmony_ci * (as required) 2408c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_cistatic int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, 2438c2ecf20Sopenharmony_ci u16 cmd_action, 2448c2ecf20Sopenharmony_ci struct host_cmd_ds_txpwr_cfg *txp) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct mwifiex_types_power_group *pg_tlv; 2478c2ecf20Sopenharmony_ci struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); 2508c2ecf20Sopenharmony_ci cmd->size = 2518c2ecf20Sopenharmony_ci cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); 2528c2ecf20Sopenharmony_ci switch (cmd_action) { 2538c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_SET: 2548c2ecf20Sopenharmony_ci if (txp->mode) { 2558c2ecf20Sopenharmony_ci pg_tlv = (struct mwifiex_types_power_group 2568c2ecf20Sopenharmony_ci *) ((unsigned long) txp + 2578c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_txpwr_cfg)); 2588c2ecf20Sopenharmony_ci memmove(cmd_txp_cfg, txp, 2598c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_txpwr_cfg) + 2608c2ecf20Sopenharmony_ci sizeof(struct mwifiex_types_power_group) + 2618c2ecf20Sopenharmony_ci le16_to_cpu(pg_tlv->length)); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci pg_tlv = (struct mwifiex_types_power_group *) ((u8 *) 2648c2ecf20Sopenharmony_ci cmd_txp_cfg + 2658c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_txpwr_cfg)); 2668c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + 2678c2ecf20Sopenharmony_ci sizeof(struct mwifiex_types_power_group) + 2688c2ecf20Sopenharmony_ci le16_to_cpu(pg_tlv->length)); 2698c2ecf20Sopenharmony_ci } else { 2708c2ecf20Sopenharmony_ci memmove(cmd_txp_cfg, txp, sizeof(*txp)); 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci cmd_txp_cfg->action = cpu_to_le16(cmd_action); 2738c2ecf20Sopenharmony_ci break; 2748c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_GET: 2758c2ecf20Sopenharmony_ci cmd_txp_cfg->action = cpu_to_le16(cmd_action); 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return 0; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci/* 2838c2ecf20Sopenharmony_ci * This function prepares command to get RF Tx power. 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_cistatic int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv, 2868c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 2878c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr) 2928c2ecf20Sopenharmony_ci + S_DS_GEN); 2938c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR); 2948c2ecf20Sopenharmony_ci txp->action = cpu_to_le16(cmd_action); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci return 0; 2978c2ecf20Sopenharmony_ci} 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci/* 3008c2ecf20Sopenharmony_ci * This function prepares command to set rf antenna. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_cistatic int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv, 3038c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 3048c2ecf20Sopenharmony_ci u16 cmd_action, 3058c2ecf20Sopenharmony_ci struct mwifiex_ds_ant_cfg *ant_cfg) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo; 3088c2ecf20Sopenharmony_ci struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci switch (cmd_action) { 3138c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_SET: 3148c2ecf20Sopenharmony_ci if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 3158c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct 3168c2ecf20Sopenharmony_ci host_cmd_ds_rf_ant_mimo) 3178c2ecf20Sopenharmony_ci + S_DS_GEN); 3188c2ecf20Sopenharmony_ci ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX); 3198c2ecf20Sopenharmony_ci ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg-> 3208c2ecf20Sopenharmony_ci tx_ant); 3218c2ecf20Sopenharmony_ci ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX); 3228c2ecf20Sopenharmony_ci ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg-> 3238c2ecf20Sopenharmony_ci rx_ant); 3248c2ecf20Sopenharmony_ci } else { 3258c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct 3268c2ecf20Sopenharmony_ci host_cmd_ds_rf_ant_siso) + 3278c2ecf20Sopenharmony_ci S_DS_GEN); 3288c2ecf20Sopenharmony_ci ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH); 3298c2ecf20Sopenharmony_ci ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci break; 3328c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_GET: 3338c2ecf20Sopenharmony_ci if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 3348c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct 3358c2ecf20Sopenharmony_ci host_cmd_ds_rf_ant_mimo) + 3368c2ecf20Sopenharmony_ci S_DS_GEN); 3378c2ecf20Sopenharmony_ci ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_GET_TX); 3388c2ecf20Sopenharmony_ci ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_GET_RX); 3398c2ecf20Sopenharmony_ci } else { 3408c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct 3418c2ecf20Sopenharmony_ci host_cmd_ds_rf_ant_siso) + 3428c2ecf20Sopenharmony_ci S_DS_GEN); 3438c2ecf20Sopenharmony_ci ant_siso->action = cpu_to_le16(HostCmd_ACT_GET_BOTH); 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci return 0; 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/* 3518c2ecf20Sopenharmony_ci * This function prepares command to set Host Sleep configuration. 3528c2ecf20Sopenharmony_ci * 3538c2ecf20Sopenharmony_ci * Preparation includes - 3548c2ecf20Sopenharmony_ci * - Setting command ID and proper size 3558c2ecf20Sopenharmony_ci * - Setting Host Sleep action, conditions, ARP filters 3568c2ecf20Sopenharmony_ci * (as required) 3578c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 3588c2ecf20Sopenharmony_ci */ 3598c2ecf20Sopenharmony_cistatic int 3608c2ecf20Sopenharmony_cimwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, 3618c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 3628c2ecf20Sopenharmony_ci u16 cmd_action, 3638c2ecf20Sopenharmony_ci struct mwifiex_hs_config_param *hscfg_param) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 3668c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; 3678c2ecf20Sopenharmony_ci u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); 3688c2ecf20Sopenharmony_ci struct mwifiex_ps_param_in_hs *psparam_tlv = NULL; 3698c2ecf20Sopenharmony_ci bool hs_activate = false; 3708c2ecf20Sopenharmony_ci u16 size; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (!hscfg_param) 3738c2ecf20Sopenharmony_ci /* New Activate command */ 3748c2ecf20Sopenharmony_ci hs_activate = true; 3758c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci if (!hs_activate && 3788c2ecf20Sopenharmony_ci (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && 3798c2ecf20Sopenharmony_ci ((adapter->arp_filter_size > 0) && 3808c2ecf20Sopenharmony_ci (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { 3818c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, CMD, 3828c2ecf20Sopenharmony_ci "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", 3838c2ecf20Sopenharmony_ci adapter->arp_filter_size); 3848c2ecf20Sopenharmony_ci memcpy(((u8 *) hs_cfg) + 3858c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), 3868c2ecf20Sopenharmony_ci adapter->arp_filter, adapter->arp_filter_size); 3878c2ecf20Sopenharmony_ci size = adapter->arp_filter_size + 3888c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) 3898c2ecf20Sopenharmony_ci + S_DS_GEN; 3908c2ecf20Sopenharmony_ci tlv = (u8 *)hs_cfg 3918c2ecf20Sopenharmony_ci + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) 3928c2ecf20Sopenharmony_ci + adapter->arp_filter_size; 3938c2ecf20Sopenharmony_ci } else { 3948c2ecf20Sopenharmony_ci size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci if (hs_activate) { 3978c2ecf20Sopenharmony_ci hs_cfg->action = cpu_to_le16(HS_ACTIVATE); 3988c2ecf20Sopenharmony_ci hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED); 3998c2ecf20Sopenharmony_ci } else { 4008c2ecf20Sopenharmony_ci hs_cfg->action = cpu_to_le16(HS_CONFIGURE); 4018c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.conditions = hscfg_param->conditions; 4028c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.gpio = hscfg_param->gpio; 4038c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.gap = hscfg_param->gap; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci size += sizeof(struct mwifiex_ps_param_in_hs); 4068c2ecf20Sopenharmony_ci psparam_tlv = (struct mwifiex_ps_param_in_hs *)tlv; 4078c2ecf20Sopenharmony_ci psparam_tlv->header.type = 4088c2ecf20Sopenharmony_ci cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS); 4098c2ecf20Sopenharmony_ci psparam_tlv->header.len = 4108c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_ps_param_in_hs) 4118c2ecf20Sopenharmony_ci - sizeof(struct mwifiex_ie_types_header)); 4128c2ecf20Sopenharmony_ci psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL); 4138c2ecf20Sopenharmony_ci psparam_tlv->hs_inact_timeout = 4148c2ecf20Sopenharmony_ci cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, CMD, 4178c2ecf20Sopenharmony_ci "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", 4188c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.conditions, 4198c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.gpio, 4208c2ecf20Sopenharmony_ci hs_cfg->params.hs_config.gap); 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(size); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* 4288c2ecf20Sopenharmony_ci * This function prepares command to set/get MAC address. 4298c2ecf20Sopenharmony_ci * 4308c2ecf20Sopenharmony_ci * Preparation includes - 4318c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 4328c2ecf20Sopenharmony_ci * - Setting MAC address (for SET only) 4338c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 4348c2ecf20Sopenharmony_ci */ 4358c2ecf20Sopenharmony_cistatic int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, 4368c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 4378c2ecf20Sopenharmony_ci u16 cmd_action) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS); 4408c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + 4418c2ecf20Sopenharmony_ci S_DS_GEN); 4428c2ecf20Sopenharmony_ci cmd->result = 0; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci cmd->params.mac_addr.action = cpu_to_le16(cmd_action); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_SET) 4478c2ecf20Sopenharmony_ci memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, 4488c2ecf20Sopenharmony_ci ETH_ALEN); 4498c2ecf20Sopenharmony_ci return 0; 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci/* 4538c2ecf20Sopenharmony_ci * This function prepares command to set MAC multicast address. 4548c2ecf20Sopenharmony_ci * 4558c2ecf20Sopenharmony_ci * Preparation includes - 4568c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 4578c2ecf20Sopenharmony_ci * - Setting MAC multicast address 4588c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 4598c2ecf20Sopenharmony_ci */ 4608c2ecf20Sopenharmony_cistatic int 4618c2ecf20Sopenharmony_cimwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, 4628c2ecf20Sopenharmony_ci u16 cmd_action, 4638c2ecf20Sopenharmony_ci struct mwifiex_multicast_list *mcast_list) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + 4688c2ecf20Sopenharmony_ci S_DS_GEN); 4698c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci mcast_addr->action = cpu_to_le16(cmd_action); 4728c2ecf20Sopenharmony_ci mcast_addr->num_of_adrs = 4738c2ecf20Sopenharmony_ci cpu_to_le16((u16) mcast_list->num_multicast_addr); 4748c2ecf20Sopenharmony_ci memcpy(mcast_addr->mac_list, mcast_list->mac_list, 4758c2ecf20Sopenharmony_ci mcast_list->num_multicast_addr * ETH_ALEN); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci return 0; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* 4818c2ecf20Sopenharmony_ci * This function prepares command to deauthenticate. 4828c2ecf20Sopenharmony_ci * 4838c2ecf20Sopenharmony_ci * Preparation includes - 4848c2ecf20Sopenharmony_ci * - Setting command ID and proper size 4858c2ecf20Sopenharmony_ci * - Setting AP MAC address and reason code 4868c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 4878c2ecf20Sopenharmony_ci */ 4888c2ecf20Sopenharmony_cistatic int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, 4898c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 4908c2ecf20Sopenharmony_ci u8 *mac) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE); 4958c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) 4968c2ecf20Sopenharmony_ci + S_DS_GEN); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci /* Set AP MAC address */ 4998c2ecf20Sopenharmony_ci memcpy(deauth->mac_addr, mac, ETH_ALEN); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci return 0; 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci/* 5098c2ecf20Sopenharmony_ci * This function prepares command to stop Ad-Hoc network. 5108c2ecf20Sopenharmony_ci * 5118c2ecf20Sopenharmony_ci * Preparation includes - 5128c2ecf20Sopenharmony_ci * - Setting command ID and proper size 5138c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_cistatic int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); 5188c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(S_DS_GEN); 5198c2ecf20Sopenharmony_ci return 0; 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/* 5238c2ecf20Sopenharmony_ci * This function sets WEP key(s) to key parameter TLV(s). 5248c2ecf20Sopenharmony_ci * 5258c2ecf20Sopenharmony_ci * Multi-key parameter TLVs are supported, so we can send multiple 5268c2ecf20Sopenharmony_ci * WEP keys in a single buffer. 5278c2ecf20Sopenharmony_ci */ 5288c2ecf20Sopenharmony_cistatic int 5298c2ecf20Sopenharmony_cimwifiex_set_keyparamset_wep(struct mwifiex_private *priv, 5308c2ecf20Sopenharmony_ci struct mwifiex_ie_type_key_param_set *key_param_set, 5318c2ecf20Sopenharmony_ci u16 *key_param_len) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci int cur_key_param_len; 5348c2ecf20Sopenharmony_ci u8 i; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* Multi-key_param_set TLV is supported */ 5378c2ecf20Sopenharmony_ci for (i = 0; i < NUM_WEP_KEYS; i++) { 5388c2ecf20Sopenharmony_ci if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) || 5398c2ecf20Sopenharmony_ci (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) { 5408c2ecf20Sopenharmony_ci key_param_set->type = 5418c2ecf20Sopenharmony_ci cpu_to_le16(TLV_TYPE_KEY_MATERIAL); 5428c2ecf20Sopenharmony_ci/* Key_param_set WEP fixed length */ 5438c2ecf20Sopenharmony_ci#define KEYPARAMSET_WEP_FIXED_LEN 8 5448c2ecf20Sopenharmony_ci key_param_set->length = cpu_to_le16((u16) 5458c2ecf20Sopenharmony_ci (priv->wep_key[i]. 5468c2ecf20Sopenharmony_ci key_length + 5478c2ecf20Sopenharmony_ci KEYPARAMSET_WEP_FIXED_LEN)); 5488c2ecf20Sopenharmony_ci key_param_set->key_type_id = 5498c2ecf20Sopenharmony_ci cpu_to_le16(KEY_TYPE_ID_WEP); 5508c2ecf20Sopenharmony_ci key_param_set->key_info = 5518c2ecf20Sopenharmony_ci cpu_to_le16(KEY_ENABLED | KEY_UNICAST | 5528c2ecf20Sopenharmony_ci KEY_MCAST); 5538c2ecf20Sopenharmony_ci key_param_set->key_len = 5548c2ecf20Sopenharmony_ci cpu_to_le16(priv->wep_key[i].key_length); 5558c2ecf20Sopenharmony_ci /* Set WEP key index */ 5568c2ecf20Sopenharmony_ci key_param_set->key[0] = i; 5578c2ecf20Sopenharmony_ci /* Set default Tx key flag */ 5588c2ecf20Sopenharmony_ci if (i == 5598c2ecf20Sopenharmony_ci (priv-> 5608c2ecf20Sopenharmony_ci wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) 5618c2ecf20Sopenharmony_ci key_param_set->key[1] = 1; 5628c2ecf20Sopenharmony_ci else 5638c2ecf20Sopenharmony_ci key_param_set->key[1] = 0; 5648c2ecf20Sopenharmony_ci memmove(&key_param_set->key[2], 5658c2ecf20Sopenharmony_ci priv->wep_key[i].key_material, 5668c2ecf20Sopenharmony_ci priv->wep_key[i].key_length); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci cur_key_param_len = priv->wep_key[i].key_length + 5698c2ecf20Sopenharmony_ci KEYPARAMSET_WEP_FIXED_LEN + 5708c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header); 5718c2ecf20Sopenharmony_ci *key_param_len += (u16) cur_key_param_len; 5728c2ecf20Sopenharmony_ci key_param_set = 5738c2ecf20Sopenharmony_ci (struct mwifiex_ie_type_key_param_set *) 5748c2ecf20Sopenharmony_ci ((u8 *)key_param_set + 5758c2ecf20Sopenharmony_ci cur_key_param_len); 5768c2ecf20Sopenharmony_ci } else if (!priv->wep_key[i].key_length) { 5778c2ecf20Sopenharmony_ci continue; 5788c2ecf20Sopenharmony_ci } else { 5798c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 5808c2ecf20Sopenharmony_ci "key%d Length = %d is incorrect\n", 5818c2ecf20Sopenharmony_ci (i + 1), priv->wep_key[i].key_length); 5828c2ecf20Sopenharmony_ci return -1; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci return 0; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci/* This function populates key material v2 command 5908c2ecf20Sopenharmony_ci * to set network key for AES & CMAC AES. 5918c2ecf20Sopenharmony_ci */ 5928c2ecf20Sopenharmony_cistatic int mwifiex_set_aes_key_v2(struct mwifiex_private *priv, 5938c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 5948c2ecf20Sopenharmony_ci struct mwifiex_ds_encrypt_key *enc_key, 5958c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_key_material_v2 *km) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 5988c2ecf20Sopenharmony_ci u16 size, len = KEY_PARAMS_FIXED_LEN; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (enc_key->is_igtk_key) { 6018c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 6028c2ecf20Sopenharmony_ci "%s: Set CMAC AES Key\n", __func__); 6038c2ecf20Sopenharmony_ci if (enc_key->is_rx_seq_valid) 6048c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.cmac_aes.ipn, 6058c2ecf20Sopenharmony_ci enc_key->pn, enc_key->pn_len); 6068c2ecf20Sopenharmony_ci km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST); 6078c2ecf20Sopenharmony_ci km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK); 6088c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; 6098c2ecf20Sopenharmony_ci km->key_param_set.key_params.cmac_aes.key_len = 6108c2ecf20Sopenharmony_ci cpu_to_le16(enc_key->key_len); 6118c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.cmac_aes.key, 6128c2ecf20Sopenharmony_ci enc_key->key_material, enc_key->key_len); 6138c2ecf20Sopenharmony_ci len += sizeof(struct mwifiex_cmac_aes_param); 6148c2ecf20Sopenharmony_ci } else if (enc_key->is_igtk_def_key) { 6158c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 6168c2ecf20Sopenharmony_ci "%s: Set CMAC default Key index\n", __func__); 6178c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC_DEF; 6188c2ecf20Sopenharmony_ci km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 6198c2ecf20Sopenharmony_ci } else { 6208c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 6218c2ecf20Sopenharmony_ci "%s: Set AES Key\n", __func__); 6228c2ecf20Sopenharmony_ci if (enc_key->is_rx_seq_valid) 6238c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.aes.pn, 6248c2ecf20Sopenharmony_ci enc_key->pn, enc_key->pn_len); 6258c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_AES; 6268c2ecf20Sopenharmony_ci km->key_param_set.key_params.aes.key_len = 6278c2ecf20Sopenharmony_ci cpu_to_le16(enc_key->key_len); 6288c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.aes.key, 6298c2ecf20Sopenharmony_ci enc_key->key_material, enc_key->key_len); 6308c2ecf20Sopenharmony_ci len += sizeof(struct mwifiex_aes_param); 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(len); 6348c2ecf20Sopenharmony_ci size = len + sizeof(struct mwifiex_ie_types_header) + 6358c2ecf20Sopenharmony_ci sizeof(km->action) + S_DS_GEN; 6368c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(size); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci return 0; 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci/* This function prepares command to set/get/reset network key(s). 6428c2ecf20Sopenharmony_ci * This function prepares key material command for V2 format. 6438c2ecf20Sopenharmony_ci * Preparation includes - 6448c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 6458c2ecf20Sopenharmony_ci * - Setting WEP keys, WAPI keys or WPA keys along with required 6468c2ecf20Sopenharmony_ci * encryption (TKIP, AES) (as required) 6478c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 6488c2ecf20Sopenharmony_ci */ 6498c2ecf20Sopenharmony_cistatic int 6508c2ecf20Sopenharmony_cimwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv, 6518c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 6528c2ecf20Sopenharmony_ci u16 cmd_action, u32 cmd_oid, 6538c2ecf20Sopenharmony_ci struct mwifiex_ds_encrypt_key *enc_key) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 6568c2ecf20Sopenharmony_ci u8 *mac = enc_key->mac_addr; 6578c2ecf20Sopenharmony_ci u16 key_info, len = KEY_PARAMS_FIXED_LEN; 6588c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_key_material_v2 *km = 6598c2ecf20Sopenharmony_ci &cmd->params.key_material_v2; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); 6628c2ecf20Sopenharmony_ci km->action = cpu_to_le16(cmd_action); 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_GET) { 6658c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "%s: Get key\n", __func__); 6668c2ecf20Sopenharmony_ci km->key_param_set.key_idx = 6678c2ecf20Sopenharmony_ci enc_key->key_index & KEY_INDEX_MASK; 6688c2ecf20Sopenharmony_ci km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 6698c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); 6708c2ecf20Sopenharmony_ci memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) 6738c2ecf20Sopenharmony_ci key_info = KEY_UNICAST; 6748c2ecf20Sopenharmony_ci else 6758c2ecf20Sopenharmony_ci key_info = KEY_MCAST; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci if (enc_key->is_igtk_key) 6788c2ecf20Sopenharmony_ci key_info |= KEY_IGTK; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci km->key_param_set.key_info = cpu_to_le16(key_info); 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + 6838c2ecf20Sopenharmony_ci S_DS_GEN + KEY_PARAMS_FIXED_LEN + 6848c2ecf20Sopenharmony_ci sizeof(km->action)); 6858c2ecf20Sopenharmony_ci return 0; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci memset(&km->key_param_set, 0, 6898c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_type_key_param_set_v2)); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (enc_key->key_disable) { 6928c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "%s: Remove key\n", __func__); 6938c2ecf20Sopenharmony_ci km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE); 6948c2ecf20Sopenharmony_ci km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 6958c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); 6968c2ecf20Sopenharmony_ci km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 6978c2ecf20Sopenharmony_ci key_info = KEY_MCAST | KEY_UNICAST; 6988c2ecf20Sopenharmony_ci km->key_param_set.key_info = cpu_to_le16(key_info); 6998c2ecf20Sopenharmony_ci memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); 7008c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + 7018c2ecf20Sopenharmony_ci S_DS_GEN + KEY_PARAMS_FIXED_LEN + 7028c2ecf20Sopenharmony_ci sizeof(km->action)); 7038c2ecf20Sopenharmony_ci return 0; 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci km->action = cpu_to_le16(HostCmd_ACT_GEN_SET); 7078c2ecf20Sopenharmony_ci km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; 7088c2ecf20Sopenharmony_ci km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); 7098c2ecf20Sopenharmony_ci key_info = KEY_ENABLED; 7108c2ecf20Sopenharmony_ci memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) { 7138c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__); 7148c2ecf20Sopenharmony_ci len += sizeof(struct mwifiex_wep_param); 7158c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(len); 7168c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_WEP; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { 7198c2ecf20Sopenharmony_ci key_info |= KEY_MCAST | KEY_UNICAST; 7208c2ecf20Sopenharmony_ci } else { 7218c2ecf20Sopenharmony_ci if (enc_key->is_current_wep_key) { 7228c2ecf20Sopenharmony_ci key_info |= KEY_MCAST | KEY_UNICAST; 7238c2ecf20Sopenharmony_ci if (km->key_param_set.key_idx == 7248c2ecf20Sopenharmony_ci (priv->wep_key_curr_index & KEY_INDEX_MASK)) 7258c2ecf20Sopenharmony_ci key_info |= KEY_DEFAULT; 7268c2ecf20Sopenharmony_ci } else { 7278c2ecf20Sopenharmony_ci if (is_broadcast_ether_addr(mac)) 7288c2ecf20Sopenharmony_ci key_info |= KEY_MCAST; 7298c2ecf20Sopenharmony_ci else 7308c2ecf20Sopenharmony_ci key_info |= KEY_UNICAST | KEY_DEFAULT; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci } 7338c2ecf20Sopenharmony_ci km->key_param_set.key_info = cpu_to_le16(key_info); 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci km->key_param_set.key_params.wep.key_len = 7368c2ecf20Sopenharmony_ci cpu_to_le16(enc_key->key_len); 7378c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.wep.key, 7388c2ecf20Sopenharmony_ci enc_key->key_material, enc_key->key_len); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + 7418c2ecf20Sopenharmony_ci len + sizeof(km->action) + S_DS_GEN); 7428c2ecf20Sopenharmony_ci return 0; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (is_broadcast_ether_addr(mac)) 7468c2ecf20Sopenharmony_ci key_info |= KEY_MCAST | KEY_RX_KEY; 7478c2ecf20Sopenharmony_ci else 7488c2ecf20Sopenharmony_ci key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci if (enc_key->is_wapi_key) { 7518c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, "%s: Set WAPI Key\n", __func__); 7528c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_WAPI; 7538c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn, 7548c2ecf20Sopenharmony_ci PN_LEN); 7558c2ecf20Sopenharmony_ci km->key_param_set.key_params.wapi.key_len = 7568c2ecf20Sopenharmony_ci cpu_to_le16(enc_key->key_len); 7578c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.wapi.key, 7588c2ecf20Sopenharmony_ci enc_key->key_material, enc_key->key_len); 7598c2ecf20Sopenharmony_ci if (is_broadcast_ether_addr(mac)) 7608c2ecf20Sopenharmony_ci priv->sec_info.wapi_key_on = true; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci if (!priv->sec_info.wapi_key_on) 7638c2ecf20Sopenharmony_ci key_info |= KEY_DEFAULT; 7648c2ecf20Sopenharmony_ci km->key_param_set.key_info = cpu_to_le16(key_info); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci len += sizeof(struct mwifiex_wapi_param); 7678c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(len); 7688c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + 7698c2ecf20Sopenharmony_ci len + sizeof(km->action) + S_DS_GEN); 7708c2ecf20Sopenharmony_ci return 0; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { 7748c2ecf20Sopenharmony_ci key_info |= KEY_DEFAULT; 7758c2ecf20Sopenharmony_ci /* Enable unicast bit for WPA-NONE/ADHOC_AES */ 7768c2ecf20Sopenharmony_ci if (!priv->sec_info.wpa2_enabled && 7778c2ecf20Sopenharmony_ci !is_broadcast_ether_addr(mac)) 7788c2ecf20Sopenharmony_ci key_info |= KEY_UNICAST; 7798c2ecf20Sopenharmony_ci } else { 7808c2ecf20Sopenharmony_ci /* Enable default key for WPA/WPA2 */ 7818c2ecf20Sopenharmony_ci if (!priv->wpa_is_gtk_set) 7828c2ecf20Sopenharmony_ci key_info |= KEY_DEFAULT; 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci km->key_param_set.key_info = cpu_to_le16(key_info); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (enc_key->key_len == WLAN_KEY_LEN_CCMP) 7888c2ecf20Sopenharmony_ci return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { 7918c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 7928c2ecf20Sopenharmony_ci "%s: Set TKIP Key\n", __func__); 7938c2ecf20Sopenharmony_ci if (enc_key->is_rx_seq_valid) 7948c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.tkip.pn, 7958c2ecf20Sopenharmony_ci enc_key->pn, enc_key->pn_len); 7968c2ecf20Sopenharmony_ci km->key_param_set.key_type = KEY_TYPE_ID_TKIP; 7978c2ecf20Sopenharmony_ci km->key_param_set.key_params.tkip.key_len = 7988c2ecf20Sopenharmony_ci cpu_to_le16(enc_key->key_len); 7998c2ecf20Sopenharmony_ci memcpy(km->key_param_set.key_params.tkip.key, 8008c2ecf20Sopenharmony_ci enc_key->key_material, enc_key->key_len); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci len += sizeof(struct mwifiex_tkip_param); 8038c2ecf20Sopenharmony_ci km->key_param_set.len = cpu_to_le16(len); 8048c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + 8058c2ecf20Sopenharmony_ci len + sizeof(km->action) + S_DS_GEN); 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci return 0; 8098c2ecf20Sopenharmony_ci} 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci/* 8128c2ecf20Sopenharmony_ci * This function prepares command to set/get/reset network key(s). 8138c2ecf20Sopenharmony_ci * This function prepares key material command for V1 format. 8148c2ecf20Sopenharmony_ci * 8158c2ecf20Sopenharmony_ci * Preparation includes - 8168c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 8178c2ecf20Sopenharmony_ci * - Setting WEP keys, WAPI keys or WPA keys along with required 8188c2ecf20Sopenharmony_ci * encryption (TKIP, AES) (as required) 8198c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 8208c2ecf20Sopenharmony_ci */ 8218c2ecf20Sopenharmony_cistatic int 8228c2ecf20Sopenharmony_cimwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv, 8238c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 8248c2ecf20Sopenharmony_ci u16 cmd_action, u32 cmd_oid, 8258c2ecf20Sopenharmony_ci struct mwifiex_ds_encrypt_key *enc_key) 8268c2ecf20Sopenharmony_ci{ 8278c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_key_material *key_material = 8288c2ecf20Sopenharmony_ci &cmd->params.key_material; 8298c2ecf20Sopenharmony_ci struct host_cmd_tlv_mac_addr *tlv_mac; 8308c2ecf20Sopenharmony_ci u16 key_param_len = 0, cmd_size; 8318c2ecf20Sopenharmony_ci int ret = 0; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); 8348c2ecf20Sopenharmony_ci key_material->action = cpu_to_le16(cmd_action); 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_GET) { 8378c2ecf20Sopenharmony_ci cmd->size = 8388c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(key_material->action) + S_DS_GEN); 8398c2ecf20Sopenharmony_ci return ret; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci if (!enc_key) { 8438c2ecf20Sopenharmony_ci memset(&key_material->key_param_set, 0, 8448c2ecf20Sopenharmony_ci (NUM_WEP_KEYS * 8458c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_type_key_param_set))); 8468c2ecf20Sopenharmony_ci ret = mwifiex_set_keyparamset_wep(priv, 8478c2ecf20Sopenharmony_ci &key_material->key_param_set, 8488c2ecf20Sopenharmony_ci &key_param_len); 8498c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(key_param_len + 8508c2ecf20Sopenharmony_ci sizeof(key_material->action) + S_DS_GEN); 8518c2ecf20Sopenharmony_ci return ret; 8528c2ecf20Sopenharmony_ci } else 8538c2ecf20Sopenharmony_ci memset(&key_material->key_param_set, 0, 8548c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_type_key_param_set)); 8558c2ecf20Sopenharmony_ci if (enc_key->is_wapi_key) { 8568c2ecf20Sopenharmony_ci struct mwifiex_ie_type_key_param_set *set; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: Set WAPI Key\n"); 8598c2ecf20Sopenharmony_ci set = &key_material->key_param_set; 8608c2ecf20Sopenharmony_ci set->key_type_id = cpu_to_le16(KEY_TYPE_ID_WAPI); 8618c2ecf20Sopenharmony_ci if (cmd_oid == KEY_INFO_ENABLED) 8628c2ecf20Sopenharmony_ci set->key_info = cpu_to_le16(KEY_ENABLED); 8638c2ecf20Sopenharmony_ci else 8648c2ecf20Sopenharmony_ci set->key_info = cpu_to_le16(!KEY_ENABLED); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci set->key[0] = enc_key->key_index; 8678c2ecf20Sopenharmony_ci if (!priv->sec_info.wapi_key_on) 8688c2ecf20Sopenharmony_ci set->key[1] = 1; 8698c2ecf20Sopenharmony_ci else 8708c2ecf20Sopenharmony_ci /* set 0 when re-key */ 8718c2ecf20Sopenharmony_ci set->key[1] = 0; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (!is_broadcast_ether_addr(enc_key->mac_addr)) { 8748c2ecf20Sopenharmony_ci /* WAPI pairwise key: unicast */ 8758c2ecf20Sopenharmony_ci set->key_info |= cpu_to_le16(KEY_UNICAST); 8768c2ecf20Sopenharmony_ci } else { /* WAPI group key: multicast */ 8778c2ecf20Sopenharmony_ci set->key_info |= cpu_to_le16(KEY_MCAST); 8788c2ecf20Sopenharmony_ci priv->sec_info.wapi_key_on = true; 8798c2ecf20Sopenharmony_ci } 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci set->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); 8828c2ecf20Sopenharmony_ci set->key_len = cpu_to_le16(WAPI_KEY_LEN); 8838c2ecf20Sopenharmony_ci memcpy(&set->key[2], enc_key->key_material, enc_key->key_len); 8848c2ecf20Sopenharmony_ci memcpy(&set->key[2 + enc_key->key_len], enc_key->pn, PN_LEN); 8858c2ecf20Sopenharmony_ci set->length = cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + 8888c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header); 8898c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(key_material->action) 8908c2ecf20Sopenharmony_ci + S_DS_GEN + key_param_len); 8918c2ecf20Sopenharmony_ci return ret; 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { 8948c2ecf20Sopenharmony_ci if (enc_key->is_igtk_key) { 8958c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, "cmd: CMAC_AES\n"); 8968c2ecf20Sopenharmony_ci key_material->key_param_set.key_type_id = 8978c2ecf20Sopenharmony_ci cpu_to_le16(KEY_TYPE_ID_AES_CMAC); 8988c2ecf20Sopenharmony_ci if (cmd_oid == KEY_INFO_ENABLED) 8998c2ecf20Sopenharmony_ci key_material->key_param_set.key_info = 9008c2ecf20Sopenharmony_ci cpu_to_le16(KEY_ENABLED); 9018c2ecf20Sopenharmony_ci else 9028c2ecf20Sopenharmony_ci key_material->key_param_set.key_info = 9038c2ecf20Sopenharmony_ci cpu_to_le16(!KEY_ENABLED); 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci key_material->key_param_set.key_info |= 9068c2ecf20Sopenharmony_ci cpu_to_le16(KEY_IGTK); 9078c2ecf20Sopenharmony_ci } else { 9088c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_AES\n"); 9098c2ecf20Sopenharmony_ci key_material->key_param_set.key_type_id = 9108c2ecf20Sopenharmony_ci cpu_to_le16(KEY_TYPE_ID_AES); 9118c2ecf20Sopenharmony_ci if (cmd_oid == KEY_INFO_ENABLED) 9128c2ecf20Sopenharmony_ci key_material->key_param_set.key_info = 9138c2ecf20Sopenharmony_ci cpu_to_le16(KEY_ENABLED); 9148c2ecf20Sopenharmony_ci else 9158c2ecf20Sopenharmony_ci key_material->key_param_set.key_info = 9168c2ecf20Sopenharmony_ci cpu_to_le16(!KEY_ENABLED); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) 9198c2ecf20Sopenharmony_ci /* AES pairwise key: unicast */ 9208c2ecf20Sopenharmony_ci key_material->key_param_set.key_info |= 9218c2ecf20Sopenharmony_ci cpu_to_le16(KEY_UNICAST); 9228c2ecf20Sopenharmony_ci else /* AES group key: multicast */ 9238c2ecf20Sopenharmony_ci key_material->key_param_set.key_info |= 9248c2ecf20Sopenharmony_ci cpu_to_le16(KEY_MCAST); 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { 9278c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_TKIP\n"); 9288c2ecf20Sopenharmony_ci key_material->key_param_set.key_type_id = 9298c2ecf20Sopenharmony_ci cpu_to_le16(KEY_TYPE_ID_TKIP); 9308c2ecf20Sopenharmony_ci key_material->key_param_set.key_info = 9318c2ecf20Sopenharmony_ci cpu_to_le16(KEY_ENABLED); 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) 9348c2ecf20Sopenharmony_ci /* TKIP pairwise key: unicast */ 9358c2ecf20Sopenharmony_ci key_material->key_param_set.key_info |= 9368c2ecf20Sopenharmony_ci cpu_to_le16(KEY_UNICAST); 9378c2ecf20Sopenharmony_ci else /* TKIP group key: multicast */ 9388c2ecf20Sopenharmony_ci key_material->key_param_set.key_info |= 9398c2ecf20Sopenharmony_ci cpu_to_le16(KEY_MCAST); 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci if (key_material->key_param_set.key_type_id) { 9438c2ecf20Sopenharmony_ci key_material->key_param_set.type = 9448c2ecf20Sopenharmony_ci cpu_to_le16(TLV_TYPE_KEY_MATERIAL); 9458c2ecf20Sopenharmony_ci key_material->key_param_set.key_len = 9468c2ecf20Sopenharmony_ci cpu_to_le16((u16) enc_key->key_len); 9478c2ecf20Sopenharmony_ci memcpy(key_material->key_param_set.key, enc_key->key_material, 9488c2ecf20Sopenharmony_ci enc_key->key_len); 9498c2ecf20Sopenharmony_ci key_material->key_param_set.length = 9508c2ecf20Sopenharmony_ci cpu_to_le16((u16) enc_key->key_len + 9518c2ecf20Sopenharmony_ci KEYPARAMSET_FIXED_LEN); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN) 9548c2ecf20Sopenharmony_ci + sizeof(struct mwifiex_ie_types_header); 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci if (le16_to_cpu(key_material->key_param_set.key_type_id) == 9578c2ecf20Sopenharmony_ci KEY_TYPE_ID_AES_CMAC) { 9588c2ecf20Sopenharmony_ci struct mwifiex_cmac_param *param = 9598c2ecf20Sopenharmony_ci (void *)key_material->key_param_set.key; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN); 9628c2ecf20Sopenharmony_ci memcpy(param->key, enc_key->key_material, 9638c2ecf20Sopenharmony_ci WLAN_KEY_LEN_AES_CMAC); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci key_param_len = sizeof(struct mwifiex_cmac_param); 9668c2ecf20Sopenharmony_ci key_material->key_param_set.key_len = 9678c2ecf20Sopenharmony_ci cpu_to_le16(key_param_len); 9688c2ecf20Sopenharmony_ci key_param_len += KEYPARAMSET_FIXED_LEN; 9698c2ecf20Sopenharmony_ci key_material->key_param_set.length = 9708c2ecf20Sopenharmony_ci cpu_to_le16(key_param_len); 9718c2ecf20Sopenharmony_ci key_param_len += sizeof(struct mwifiex_ie_types_header); 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN 9758c2ecf20Sopenharmony_ci + key_param_len); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { 9788c2ecf20Sopenharmony_ci tlv_mac = (void *)((u8 *)&key_material->key_param_set + 9798c2ecf20Sopenharmony_ci key_param_len); 9808c2ecf20Sopenharmony_ci tlv_mac->header.type = 9818c2ecf20Sopenharmony_ci cpu_to_le16(TLV_TYPE_STA_MAC_ADDR); 9828c2ecf20Sopenharmony_ci tlv_mac->header.len = cpu_to_le16(ETH_ALEN); 9838c2ecf20Sopenharmony_ci memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN); 9848c2ecf20Sopenharmony_ci cmd_size = key_param_len + S_DS_GEN + 9858c2ecf20Sopenharmony_ci sizeof(key_material->action) + 9868c2ecf20Sopenharmony_ci sizeof(struct host_cmd_tlv_mac_addr); 9878c2ecf20Sopenharmony_ci } else { 9888c2ecf20Sopenharmony_ci cmd_size = key_param_len + S_DS_GEN + 9898c2ecf20Sopenharmony_ci sizeof(key_material->action); 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(cmd_size); 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci return ret; 9958c2ecf20Sopenharmony_ci} 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci/* Wrapper function for setting network key depending upon FW KEY API version */ 9988c2ecf20Sopenharmony_cistatic int 9998c2ecf20Sopenharmony_cimwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, 10008c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 10018c2ecf20Sopenharmony_ci u16 cmd_action, u32 cmd_oid, 10028c2ecf20Sopenharmony_ci struct mwifiex_ds_encrypt_key *enc_key) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) 10058c2ecf20Sopenharmony_ci return mwifiex_cmd_802_11_key_material_v2(priv, cmd, 10068c2ecf20Sopenharmony_ci cmd_action, cmd_oid, 10078c2ecf20Sopenharmony_ci enc_key); 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci else 10108c2ecf20Sopenharmony_ci return mwifiex_cmd_802_11_key_material_v1(priv, cmd, 10118c2ecf20Sopenharmony_ci cmd_action, cmd_oid, 10128c2ecf20Sopenharmony_ci enc_key); 10138c2ecf20Sopenharmony_ci} 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci/* 10168c2ecf20Sopenharmony_ci * This function prepares command to set/get 11d domain information. 10178c2ecf20Sopenharmony_ci * 10188c2ecf20Sopenharmony_ci * Preparation includes - 10198c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 10208c2ecf20Sopenharmony_ci * - Setting domain information fields (for SET only) 10218c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 10228c2ecf20Sopenharmony_ci */ 10238c2ecf20Sopenharmony_cistatic int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv, 10248c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 10258c2ecf20Sopenharmony_ci u16 cmd_action) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 10288c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11d_domain_info *domain_info = 10298c2ecf20Sopenharmony_ci &cmd->params.domain_info; 10308c2ecf20Sopenharmony_ci struct mwifiex_ietypes_domain_param_set *domain = 10318c2ecf20Sopenharmony_ci &domain_info->domain; 10328c2ecf20Sopenharmony_ci u8 no_of_triplet = adapter->domain_reg.no_of_triplet; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 10358c2ecf20Sopenharmony_ci "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); 10388c2ecf20Sopenharmony_ci domain_info->action = cpu_to_le16(cmd_action); 10398c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_GET) { 10408c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); 10418c2ecf20Sopenharmony_ci return 0; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci /* Set domain info fields */ 10458c2ecf20Sopenharmony_ci domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); 10468c2ecf20Sopenharmony_ci memcpy(domain->country_code, adapter->domain_reg.country_code, 10478c2ecf20Sopenharmony_ci sizeof(domain->country_code)); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci domain->header.len = 10508c2ecf20Sopenharmony_ci cpu_to_le16((no_of_triplet * 10518c2ecf20Sopenharmony_ci sizeof(struct ieee80211_country_ie_triplet)) 10528c2ecf20Sopenharmony_ci + sizeof(domain->country_code)); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci if (no_of_triplet) { 10558c2ecf20Sopenharmony_ci memcpy(domain->triplet, adapter->domain_reg.triplet, 10568c2ecf20Sopenharmony_ci no_of_triplet * sizeof(struct 10578c2ecf20Sopenharmony_ci ieee80211_country_ie_triplet)); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(domain_info->action) + 10608c2ecf20Sopenharmony_ci le16_to_cpu(domain->header.len) + 10618c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header) 10628c2ecf20Sopenharmony_ci + S_DS_GEN); 10638c2ecf20Sopenharmony_ci } else { 10648c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci return 0; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci/* 10718c2ecf20Sopenharmony_ci * This function prepares command to set/get IBSS coalescing status. 10728c2ecf20Sopenharmony_ci * 10738c2ecf20Sopenharmony_ci * Preparation includes - 10748c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 10758c2ecf20Sopenharmony_ci * - Setting status to enable or disable (for SET only) 10768c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 10778c2ecf20Sopenharmony_ci */ 10788c2ecf20Sopenharmony_cistatic int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd, 10798c2ecf20Sopenharmony_ci u16 cmd_action, u16 *enable) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_ibss_status *ibss_coal = 10828c2ecf20Sopenharmony_ci &(cmd->params.ibss_coalescing); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); 10858c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + 10868c2ecf20Sopenharmony_ci S_DS_GEN); 10878c2ecf20Sopenharmony_ci cmd->result = 0; 10888c2ecf20Sopenharmony_ci ibss_coal->action = cpu_to_le16(cmd_action); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci switch (cmd_action) { 10918c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_SET: 10928c2ecf20Sopenharmony_ci if (enable) 10938c2ecf20Sopenharmony_ci ibss_coal->enable = cpu_to_le16(*enable); 10948c2ecf20Sopenharmony_ci else 10958c2ecf20Sopenharmony_ci ibss_coal->enable = 0; 10968c2ecf20Sopenharmony_ci break; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci /* In other case.. Nothing to do */ 10998c2ecf20Sopenharmony_ci case HostCmd_ACT_GEN_GET: 11008c2ecf20Sopenharmony_ci default: 11018c2ecf20Sopenharmony_ci break; 11028c2ecf20Sopenharmony_ci } 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci return 0; 11058c2ecf20Sopenharmony_ci} 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci/* This function prepares command buffer to get/set memory location value. 11088c2ecf20Sopenharmony_ci */ 11098c2ecf20Sopenharmony_cistatic int 11108c2ecf20Sopenharmony_cimwifiex_cmd_mem_access(struct host_cmd_ds_command *cmd, u16 cmd_action, 11118c2ecf20Sopenharmony_ci void *pdata_buf) 11128c2ecf20Sopenharmony_ci{ 11138c2ecf20Sopenharmony_ci struct mwifiex_ds_mem_rw *mem_rw = (void *)pdata_buf; 11148c2ecf20Sopenharmony_ci struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS); 11178c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) + 11188c2ecf20Sopenharmony_ci S_DS_GEN); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci mem_access->action = cpu_to_le16(cmd_action); 11218c2ecf20Sopenharmony_ci mem_access->addr = cpu_to_le32(mem_rw->addr); 11228c2ecf20Sopenharmony_ci mem_access->value = cpu_to_le32(mem_rw->value); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return 0; 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci/* 11288c2ecf20Sopenharmony_ci * This function prepares command to set/get register value. 11298c2ecf20Sopenharmony_ci * 11308c2ecf20Sopenharmony_ci * Preparation includes - 11318c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 11328c2ecf20Sopenharmony_ci * - Setting register offset (for both GET and SET) and 11338c2ecf20Sopenharmony_ci * register value (for SET only) 11348c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 11358c2ecf20Sopenharmony_ci * 11368c2ecf20Sopenharmony_ci * The following type of registers can be accessed with this function - 11378c2ecf20Sopenharmony_ci * - MAC register 11388c2ecf20Sopenharmony_ci * - BBP register 11398c2ecf20Sopenharmony_ci * - RF register 11408c2ecf20Sopenharmony_ci * - PMIC register 11418c2ecf20Sopenharmony_ci * - CAU register 11428c2ecf20Sopenharmony_ci * - EEPROM 11438c2ecf20Sopenharmony_ci */ 11448c2ecf20Sopenharmony_cistatic int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, 11458c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 11468c2ecf20Sopenharmony_ci{ 11478c2ecf20Sopenharmony_ci struct mwifiex_ds_reg_rw *reg_rw = data_buf; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci switch (le16_to_cpu(cmd->command)) { 11508c2ecf20Sopenharmony_ci case HostCmd_CMD_MAC_REG_ACCESS: 11518c2ecf20Sopenharmony_ci { 11528c2ecf20Sopenharmony_ci struct host_cmd_ds_mac_reg_access *mac_reg; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); 11558c2ecf20Sopenharmony_ci mac_reg = &cmd->params.mac_reg; 11568c2ecf20Sopenharmony_ci mac_reg->action = cpu_to_le16(cmd_action); 11578c2ecf20Sopenharmony_ci mac_reg->offset = cpu_to_le16((u16) reg_rw->offset); 11588c2ecf20Sopenharmony_ci mac_reg->value = cpu_to_le32(reg_rw->value); 11598c2ecf20Sopenharmony_ci break; 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci case HostCmd_CMD_BBP_REG_ACCESS: 11628c2ecf20Sopenharmony_ci { 11638c2ecf20Sopenharmony_ci struct host_cmd_ds_bbp_reg_access *bbp_reg; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); 11668c2ecf20Sopenharmony_ci bbp_reg = &cmd->params.bbp_reg; 11678c2ecf20Sopenharmony_ci bbp_reg->action = cpu_to_le16(cmd_action); 11688c2ecf20Sopenharmony_ci bbp_reg->offset = cpu_to_le16((u16) reg_rw->offset); 11698c2ecf20Sopenharmony_ci bbp_reg->value = (u8) reg_rw->value; 11708c2ecf20Sopenharmony_ci break; 11718c2ecf20Sopenharmony_ci } 11728c2ecf20Sopenharmony_ci case HostCmd_CMD_RF_REG_ACCESS: 11738c2ecf20Sopenharmony_ci { 11748c2ecf20Sopenharmony_ci struct host_cmd_ds_rf_reg_access *rf_reg; 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); 11778c2ecf20Sopenharmony_ci rf_reg = &cmd->params.rf_reg; 11788c2ecf20Sopenharmony_ci rf_reg->action = cpu_to_le16(cmd_action); 11798c2ecf20Sopenharmony_ci rf_reg->offset = cpu_to_le16((u16) reg_rw->offset); 11808c2ecf20Sopenharmony_ci rf_reg->value = (u8) reg_rw->value; 11818c2ecf20Sopenharmony_ci break; 11828c2ecf20Sopenharmony_ci } 11838c2ecf20Sopenharmony_ci case HostCmd_CMD_PMIC_REG_ACCESS: 11848c2ecf20Sopenharmony_ci { 11858c2ecf20Sopenharmony_ci struct host_cmd_ds_pmic_reg_access *pmic_reg; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); 11888c2ecf20Sopenharmony_ci pmic_reg = &cmd->params.pmic_reg; 11898c2ecf20Sopenharmony_ci pmic_reg->action = cpu_to_le16(cmd_action); 11908c2ecf20Sopenharmony_ci pmic_reg->offset = cpu_to_le16((u16) reg_rw->offset); 11918c2ecf20Sopenharmony_ci pmic_reg->value = (u8) reg_rw->value; 11928c2ecf20Sopenharmony_ci break; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci case HostCmd_CMD_CAU_REG_ACCESS: 11958c2ecf20Sopenharmony_ci { 11968c2ecf20Sopenharmony_ci struct host_cmd_ds_rf_reg_access *cau_reg; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); 11998c2ecf20Sopenharmony_ci cau_reg = &cmd->params.rf_reg; 12008c2ecf20Sopenharmony_ci cau_reg->action = cpu_to_le16(cmd_action); 12018c2ecf20Sopenharmony_ci cau_reg->offset = cpu_to_le16((u16) reg_rw->offset); 12028c2ecf20Sopenharmony_ci cau_reg->value = (u8) reg_rw->value; 12038c2ecf20Sopenharmony_ci break; 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_EEPROM_ACCESS: 12068c2ecf20Sopenharmony_ci { 12078c2ecf20Sopenharmony_ci struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf; 12088c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = 12098c2ecf20Sopenharmony_ci &cmd->params.eeprom; 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); 12128c2ecf20Sopenharmony_ci cmd_eeprom->action = cpu_to_le16(cmd_action); 12138c2ecf20Sopenharmony_ci cmd_eeprom->offset = cpu_to_le16(rd_eeprom->offset); 12148c2ecf20Sopenharmony_ci cmd_eeprom->byte_count = cpu_to_le16(rd_eeprom->byte_count); 12158c2ecf20Sopenharmony_ci cmd_eeprom->value = 0; 12168c2ecf20Sopenharmony_ci break; 12178c2ecf20Sopenharmony_ci } 12188c2ecf20Sopenharmony_ci default: 12198c2ecf20Sopenharmony_ci return -1; 12208c2ecf20Sopenharmony_ci } 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci return 0; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci/* 12268c2ecf20Sopenharmony_ci * This function prepares command to set PCI-Express 12278c2ecf20Sopenharmony_ci * host buffer configuration 12288c2ecf20Sopenharmony_ci * 12298c2ecf20Sopenharmony_ci * Preparation includes - 12308c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 12318c2ecf20Sopenharmony_ci * - Setting host buffer configuration 12328c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 12338c2ecf20Sopenharmony_ci */ 12348c2ecf20Sopenharmony_cistatic int 12358c2ecf20Sopenharmony_cimwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, 12368c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, u16 action) 12378c2ecf20Sopenharmony_ci{ 12388c2ecf20Sopenharmony_ci struct host_cmd_ds_pcie_details *host_spec = 12398c2ecf20Sopenharmony_ci &cmd->params.pcie_host_spec; 12408c2ecf20Sopenharmony_ci struct pcie_service_card *card = priv->adapter->card; 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS); 12438c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct 12448c2ecf20Sopenharmony_ci host_cmd_ds_pcie_details) + S_DS_GEN); 12458c2ecf20Sopenharmony_ci cmd->result = 0; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details)); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci if (action != HostCmd_ACT_GEN_SET) 12508c2ecf20Sopenharmony_ci return 0; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci /* Send the ring base addresses and count to firmware */ 12538c2ecf20Sopenharmony_ci host_spec->txbd_addr_lo = cpu_to_le32((u32)(card->txbd_ring_pbase)); 12548c2ecf20Sopenharmony_ci host_spec->txbd_addr_hi = 12558c2ecf20Sopenharmony_ci cpu_to_le32((u32)(((u64)card->txbd_ring_pbase) >> 32)); 12568c2ecf20Sopenharmony_ci host_spec->txbd_count = cpu_to_le32(MWIFIEX_MAX_TXRX_BD); 12578c2ecf20Sopenharmony_ci host_spec->rxbd_addr_lo = cpu_to_le32((u32)(card->rxbd_ring_pbase)); 12588c2ecf20Sopenharmony_ci host_spec->rxbd_addr_hi = 12598c2ecf20Sopenharmony_ci cpu_to_le32((u32)(((u64)card->rxbd_ring_pbase) >> 32)); 12608c2ecf20Sopenharmony_ci host_spec->rxbd_count = cpu_to_le32(MWIFIEX_MAX_TXRX_BD); 12618c2ecf20Sopenharmony_ci host_spec->evtbd_addr_lo = cpu_to_le32((u32)(card->evtbd_ring_pbase)); 12628c2ecf20Sopenharmony_ci host_spec->evtbd_addr_hi = 12638c2ecf20Sopenharmony_ci cpu_to_le32((u32)(((u64)card->evtbd_ring_pbase) >> 32)); 12648c2ecf20Sopenharmony_ci host_spec->evtbd_count = cpu_to_le32(MWIFIEX_MAX_EVT_BD); 12658c2ecf20Sopenharmony_ci if (card->sleep_cookie_vbase) { 12668c2ecf20Sopenharmony_ci host_spec->sleep_cookie_addr_lo = 12678c2ecf20Sopenharmony_ci cpu_to_le32((u32)(card->sleep_cookie_pbase)); 12688c2ecf20Sopenharmony_ci host_spec->sleep_cookie_addr_hi = cpu_to_le32((u32)(((u64) 12698c2ecf20Sopenharmony_ci (card->sleep_cookie_pbase)) >> 32)); 12708c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 12718c2ecf20Sopenharmony_ci "sleep_cook_lo phy addr: 0x%x\n", 12728c2ecf20Sopenharmony_ci host_spec->sleep_cookie_addr_lo); 12738c2ecf20Sopenharmony_ci } 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci return 0; 12768c2ecf20Sopenharmony_ci} 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci/* 12798c2ecf20Sopenharmony_ci * This function prepares command for event subscription, configuration 12808c2ecf20Sopenharmony_ci * and query. Events can be subscribed or unsubscribed. Current subscribed 12818c2ecf20Sopenharmony_ci * events can be queried. Also, current subscribed events are reported in 12828c2ecf20Sopenharmony_ci * every FW response. 12838c2ecf20Sopenharmony_ci */ 12848c2ecf20Sopenharmony_cistatic int 12858c2ecf20Sopenharmony_cimwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, 12868c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 12878c2ecf20Sopenharmony_ci struct mwifiex_ds_misc_subsc_evt *subsc_evt_cfg) 12888c2ecf20Sopenharmony_ci{ 12898c2ecf20Sopenharmony_ci struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt; 12908c2ecf20Sopenharmony_ci struct mwifiex_ie_types_rssi_threshold *rssi_tlv; 12918c2ecf20Sopenharmony_ci u16 event_bitmap; 12928c2ecf20Sopenharmony_ci u8 *pos; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT); 12958c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) + 12968c2ecf20Sopenharmony_ci S_DS_GEN); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action); 12998c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 13008c2ecf20Sopenharmony_ci "cmd: action: %d\n", subsc_evt_cfg->action); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci /*For query requests, no configuration TLV structures are to be added.*/ 13038c2ecf20Sopenharmony_ci if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET) 13048c2ecf20Sopenharmony_ci return 0; 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci event_bitmap = subsc_evt_cfg->events; 13098c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n", 13108c2ecf20Sopenharmony_ci event_bitmap); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) || 13138c2ecf20Sopenharmony_ci (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) && 13148c2ecf20Sopenharmony_ci (event_bitmap == 0)) { 13158c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 13168c2ecf20Sopenharmony_ci "Error: No event specified\t" 13178c2ecf20Sopenharmony_ci "for bitwise action type\n"); 13188c2ecf20Sopenharmony_ci return -EINVAL; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci /* 13228c2ecf20Sopenharmony_ci * Append TLV structures for each of the specified events for 13238c2ecf20Sopenharmony_ci * subscribing or re-configuring. This is not required for 13248c2ecf20Sopenharmony_ci * bitwise unsubscribing request. 13258c2ecf20Sopenharmony_ci */ 13268c2ecf20Sopenharmony_ci if (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) 13278c2ecf20Sopenharmony_ci return 0; 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci pos = ((u8 *)subsc_evt) + 13308c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_802_11_subsc_evt); 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci if (event_bitmap & BITMASK_BCN_RSSI_LOW) { 13338c2ecf20Sopenharmony_ci rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW); 13368c2ecf20Sopenharmony_ci rssi_tlv->header.len = 13378c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - 13388c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 13398c2ecf20Sopenharmony_ci rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value; 13408c2ecf20Sopenharmony_ci rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq; 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, EVENT, 13438c2ecf20Sopenharmony_ci "Cfg Beacon Low Rssi event,\t" 13448c2ecf20Sopenharmony_ci "RSSI:-%d dBm, Freq:%d\n", 13458c2ecf20Sopenharmony_ci subsc_evt_cfg->bcn_l_rssi_cfg.abs_value, 13468c2ecf20Sopenharmony_ci subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci pos += sizeof(struct mwifiex_ie_types_rssi_threshold); 13498c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, 13508c2ecf20Sopenharmony_ci sizeof( 13518c2ecf20Sopenharmony_ci struct mwifiex_ie_types_rssi_threshold)); 13528c2ecf20Sopenharmony_ci } 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci if (event_bitmap & BITMASK_BCN_RSSI_HIGH) { 13558c2ecf20Sopenharmony_ci rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH); 13588c2ecf20Sopenharmony_ci rssi_tlv->header.len = 13598c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - 13608c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 13618c2ecf20Sopenharmony_ci rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; 13628c2ecf20Sopenharmony_ci rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, EVENT, 13658c2ecf20Sopenharmony_ci "Cfg Beacon High Rssi event,\t" 13668c2ecf20Sopenharmony_ci "RSSI:-%d dBm, Freq:%d\n", 13678c2ecf20Sopenharmony_ci subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, 13688c2ecf20Sopenharmony_ci subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci pos += sizeof(struct mwifiex_ie_types_rssi_threshold); 13718c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, 13728c2ecf20Sopenharmony_ci sizeof( 13738c2ecf20Sopenharmony_ci struct mwifiex_ie_types_rssi_threshold)); 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci return 0; 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_cistatic int 13808c2ecf20Sopenharmony_cimwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, 13818c2ecf20Sopenharmony_ci struct mwifiex_mef_entry *mef_entry, 13828c2ecf20Sopenharmony_ci u8 **buffer) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci struct mwifiex_mef_filter *filter = mef_entry->filter; 13858c2ecf20Sopenharmony_ci int i, byte_len; 13868c2ecf20Sopenharmony_ci u8 *stack_ptr = *buffer; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_MEF_MAX_FILTERS; i++) { 13898c2ecf20Sopenharmony_ci filter = &mef_entry->filter[i]; 13908c2ecf20Sopenharmony_ci if (!filter->filt_type) 13918c2ecf20Sopenharmony_ci break; 13928c2ecf20Sopenharmony_ci put_unaligned_le32((u32)filter->repeat, stack_ptr); 13938c2ecf20Sopenharmony_ci stack_ptr += 4; 13948c2ecf20Sopenharmony_ci *stack_ptr = TYPE_DNUM; 13958c2ecf20Sopenharmony_ci stack_ptr += 1; 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci byte_len = filter->byte_seq[MWIFIEX_MEF_MAX_BYTESEQ]; 13988c2ecf20Sopenharmony_ci memcpy(stack_ptr, filter->byte_seq, byte_len); 13998c2ecf20Sopenharmony_ci stack_ptr += byte_len; 14008c2ecf20Sopenharmony_ci *stack_ptr = byte_len; 14018c2ecf20Sopenharmony_ci stack_ptr += 1; 14028c2ecf20Sopenharmony_ci *stack_ptr = TYPE_BYTESEQ; 14038c2ecf20Sopenharmony_ci stack_ptr += 1; 14048c2ecf20Sopenharmony_ci put_unaligned_le32((u32)filter->offset, stack_ptr); 14058c2ecf20Sopenharmony_ci stack_ptr += 4; 14068c2ecf20Sopenharmony_ci *stack_ptr = TYPE_DNUM; 14078c2ecf20Sopenharmony_ci stack_ptr += 1; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci *stack_ptr = filter->filt_type; 14108c2ecf20Sopenharmony_ci stack_ptr += 1; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci if (filter->filt_action) { 14138c2ecf20Sopenharmony_ci *stack_ptr = filter->filt_action; 14148c2ecf20Sopenharmony_ci stack_ptr += 1; 14158c2ecf20Sopenharmony_ci } 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci if (stack_ptr - *buffer > STACK_NBYTES) 14188c2ecf20Sopenharmony_ci return -1; 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci *buffer = stack_ptr; 14228c2ecf20Sopenharmony_ci return 0; 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_cistatic int 14268c2ecf20Sopenharmony_cimwifiex_cmd_mef_cfg(struct mwifiex_private *priv, 14278c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 14288c2ecf20Sopenharmony_ci struct mwifiex_ds_mef_cfg *mef) 14298c2ecf20Sopenharmony_ci{ 14308c2ecf20Sopenharmony_ci struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; 14318c2ecf20Sopenharmony_ci struct mwifiex_fw_mef_entry *mef_entry = NULL; 14328c2ecf20Sopenharmony_ci u8 *pos = (u8 *)mef_cfg; 14338c2ecf20Sopenharmony_ci u16 i; 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci mef_cfg->criteria = cpu_to_le32(mef->criteria); 14388c2ecf20Sopenharmony_ci mef_cfg->num_entries = cpu_to_le16(mef->num_entries); 14398c2ecf20Sopenharmony_ci pos += sizeof(*mef_cfg); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci for (i = 0; i < mef->num_entries; i++) { 14428c2ecf20Sopenharmony_ci mef_entry = (struct mwifiex_fw_mef_entry *)pos; 14438c2ecf20Sopenharmony_ci mef_entry->mode = mef->mef_entry[i].mode; 14448c2ecf20Sopenharmony_ci mef_entry->action = mef->mef_entry[i].action; 14458c2ecf20Sopenharmony_ci pos += sizeof(*mef_cfg->mef_entry); 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci if (mwifiex_cmd_append_rpn_expression(priv, 14488c2ecf20Sopenharmony_ci &mef->mef_entry[i], &pos)) 14498c2ecf20Sopenharmony_ci return -1; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci mef_entry->exprsize = 14528c2ecf20Sopenharmony_ci cpu_to_le16(pos - mef_entry->expr); 14538c2ecf20Sopenharmony_ci } 14548c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci return 0; 14578c2ecf20Sopenharmony_ci} 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci/* This function parse cal data from ASCII to hex */ 14608c2ecf20Sopenharmony_cistatic u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci u8 *s = src, *d = dst; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci while (s - src < len) { 14658c2ecf20Sopenharmony_ci if (*s && (isspace(*s) || *s == '\t')) { 14668c2ecf20Sopenharmony_ci s++; 14678c2ecf20Sopenharmony_ci continue; 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci if (isxdigit(*s)) { 14708c2ecf20Sopenharmony_ci *d++ = simple_strtol(s, NULL, 16); 14718c2ecf20Sopenharmony_ci s += 2; 14728c2ecf20Sopenharmony_ci } else { 14738c2ecf20Sopenharmony_ci s++; 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci } 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci return d - dst; 14788c2ecf20Sopenharmony_ci} 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ciint mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, 14818c2ecf20Sopenharmony_ci struct device_node *node, const char *prefix) 14828c2ecf20Sopenharmony_ci{ 14838c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 14848c2ecf20Sopenharmony_ci struct property *prop; 14858c2ecf20Sopenharmony_ci size_t len = strlen(prefix); 14868c2ecf20Sopenharmony_ci int ret; 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci /* look for all matching property names */ 14898c2ecf20Sopenharmony_ci for_each_property_of_node(node, prop) { 14908c2ecf20Sopenharmony_ci if (len > strlen(prop->name) || 14918c2ecf20Sopenharmony_ci strncmp(prop->name, prefix, len)) 14928c2ecf20Sopenharmony_ci continue; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci /* property header is 6 bytes, data must fit in cmd buffer */ 14958c2ecf20Sopenharmony_ci if (prop->value && prop->length > 6 && 14968c2ecf20Sopenharmony_ci prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) { 14978c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, 14988c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 14998c2ecf20Sopenharmony_ci prop, true); 15008c2ecf20Sopenharmony_ci if (ret) 15018c2ecf20Sopenharmony_ci return ret; 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci } 15048c2ecf20Sopenharmony_ci#endif 15058c2ecf20Sopenharmony_ci return 0; 15068c2ecf20Sopenharmony_ci} 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci/* This function prepares command of set_cfg_data. */ 15098c2ecf20Sopenharmony_cistatic int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, 15108c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, void *data_buf) 15118c2ecf20Sopenharmony_ci{ 15128c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 15138c2ecf20Sopenharmony_ci struct property *prop = data_buf; 15148c2ecf20Sopenharmony_ci u32 len; 15158c2ecf20Sopenharmony_ci u8 *data = (u8 *)cmd + S_DS_GEN; 15168c2ecf20Sopenharmony_ci int ret; 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci if (prop) { 15198c2ecf20Sopenharmony_ci len = prop->length; 15208c2ecf20Sopenharmony_ci ret = of_property_read_u8_array(adapter->dt_node, prop->name, 15218c2ecf20Sopenharmony_ci data, len); 15228c2ecf20Sopenharmony_ci if (ret) 15238c2ecf20Sopenharmony_ci return ret; 15248c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 15258c2ecf20Sopenharmony_ci "download cfg_data from device tree: %s\n", 15268c2ecf20Sopenharmony_ci prop->name); 15278c2ecf20Sopenharmony_ci } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { 15288c2ecf20Sopenharmony_ci len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, 15298c2ecf20Sopenharmony_ci adapter->cal_data->size, data); 15308c2ecf20Sopenharmony_ci mwifiex_dbg(adapter, INFO, 15318c2ecf20Sopenharmony_ci "download cfg_data from config file\n"); 15328c2ecf20Sopenharmony_ci } else { 15338c2ecf20Sopenharmony_ci return -1; 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); 15378c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(S_DS_GEN + len); 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci return 0; 15408c2ecf20Sopenharmony_ci} 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_cistatic int 15438c2ecf20Sopenharmony_cimwifiex_cmd_set_mc_policy(struct mwifiex_private *priv, 15448c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 15458c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 15468c2ecf20Sopenharmony_ci{ 15478c2ecf20Sopenharmony_ci struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy; 15488c2ecf20Sopenharmony_ci const u16 *drcs_info = data_buf; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci mc_pol->action = cpu_to_le16(cmd_action); 15518c2ecf20Sopenharmony_ci mc_pol->policy = cpu_to_le16(*drcs_info); 15528c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_MC_POLICY); 15538c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) + 15548c2ecf20Sopenharmony_ci S_DS_GEN); 15558c2ecf20Sopenharmony_ci return 0; 15568c2ecf20Sopenharmony_ci} 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_cistatic int mwifiex_cmd_robust_coex(struct mwifiex_private *priv, 15598c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 15608c2ecf20Sopenharmony_ci u16 cmd_action, bool *is_timeshare) 15618c2ecf20Sopenharmony_ci{ 15628c2ecf20Sopenharmony_ci struct host_cmd_ds_robust_coex *coex = &cmd->params.coex; 15638c2ecf20Sopenharmony_ci struct mwifiex_ie_types_robust_coex *coex_tlv; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX); 15668c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci coex->action = cpu_to_le16(cmd_action); 15698c2ecf20Sopenharmony_ci coex_tlv = (struct mwifiex_ie_types_robust_coex *) 15708c2ecf20Sopenharmony_ci ((u8 *)coex + sizeof(*coex)); 15718c2ecf20Sopenharmony_ci coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX); 15728c2ecf20Sopenharmony_ci coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode)); 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci if (coex->action == HostCmd_ACT_GEN_GET) 15758c2ecf20Sopenharmony_ci return 0; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (*is_timeshare) 15788c2ecf20Sopenharmony_ci coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE); 15798c2ecf20Sopenharmony_ci else 15808c2ecf20Sopenharmony_ci coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci return 0; 15838c2ecf20Sopenharmony_ci} 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_cistatic int mwifiex_cmd_gtk_rekey_offload(struct mwifiex_private *priv, 15868c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 15878c2ecf20Sopenharmony_ci u16 cmd_action, 15888c2ecf20Sopenharmony_ci struct cfg80211_gtk_rekey_data *data) 15898c2ecf20Sopenharmony_ci{ 15908c2ecf20Sopenharmony_ci struct host_cmd_ds_gtk_rekey_params *rekey = &cmd->params.rekey; 15918c2ecf20Sopenharmony_ci u64 rekey_ctr; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG); 15948c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*rekey) + S_DS_GEN); 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci rekey->action = cpu_to_le16(cmd_action); 15978c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_SET) { 15988c2ecf20Sopenharmony_ci memcpy(rekey->kek, data->kek, NL80211_KEK_LEN); 15998c2ecf20Sopenharmony_ci memcpy(rekey->kck, data->kck, NL80211_KCK_LEN); 16008c2ecf20Sopenharmony_ci rekey_ctr = be64_to_cpup((__be64 *)data->replay_ctr); 16018c2ecf20Sopenharmony_ci rekey->replay_ctr_low = cpu_to_le32((u32)rekey_ctr); 16028c2ecf20Sopenharmony_ci rekey->replay_ctr_high = 16038c2ecf20Sopenharmony_ci cpu_to_le32((u32)((u64)rekey_ctr >> 32)); 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci return 0; 16078c2ecf20Sopenharmony_ci} 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_cistatic int mwifiex_cmd_chan_region_cfg(struct mwifiex_private *priv, 16108c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 16118c2ecf20Sopenharmony_ci u16 cmd_action) 16128c2ecf20Sopenharmony_ci{ 16138c2ecf20Sopenharmony_ci struct host_cmd_ds_chan_region_cfg *reg = &cmd->params.reg_cfg; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REGION_CFG); 16168c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*reg) + S_DS_GEN); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_GET) 16198c2ecf20Sopenharmony_ci reg->action = cpu_to_le16(cmd_action); 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci return 0; 16228c2ecf20Sopenharmony_ci} 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_cistatic int 16258c2ecf20Sopenharmony_cimwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, 16268c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 16278c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 16288c2ecf20Sopenharmony_ci{ 16298c2ecf20Sopenharmony_ci struct host_cmd_ds_coalesce_cfg *coalesce_cfg = 16308c2ecf20Sopenharmony_ci &cmd->params.coalesce_cfg; 16318c2ecf20Sopenharmony_ci struct mwifiex_ds_coalesce_cfg *cfg = data_buf; 16328c2ecf20Sopenharmony_ci struct coalesce_filt_field_param *param; 16338c2ecf20Sopenharmony_ci u16 cnt, idx, length; 16348c2ecf20Sopenharmony_ci struct coalesce_receive_filt_rule *rule; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_COALESCE_CFG); 16378c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(S_DS_GEN); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci coalesce_cfg->action = cpu_to_le16(cmd_action); 16408c2ecf20Sopenharmony_ci coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules); 16418c2ecf20Sopenharmony_ci rule = coalesce_cfg->rule; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci for (cnt = 0; cnt < cfg->num_of_rules; cnt++) { 16448c2ecf20Sopenharmony_ci rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE); 16458c2ecf20Sopenharmony_ci rule->max_coalescing_delay = 16468c2ecf20Sopenharmony_ci cpu_to_le16(cfg->rule[cnt].max_coalescing_delay); 16478c2ecf20Sopenharmony_ci rule->pkt_type = cfg->rule[cnt].pkt_type; 16488c2ecf20Sopenharmony_ci rule->num_of_fields = cfg->rule[cnt].num_of_fields; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci length = 0; 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci param = rule->params; 16538c2ecf20Sopenharmony_ci for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) { 16548c2ecf20Sopenharmony_ci param->operation = cfg->rule[cnt].params[idx].operation; 16558c2ecf20Sopenharmony_ci param->operand_len = 16568c2ecf20Sopenharmony_ci cfg->rule[cnt].params[idx].operand_len; 16578c2ecf20Sopenharmony_ci param->offset = 16588c2ecf20Sopenharmony_ci cpu_to_le16(cfg->rule[cnt].params[idx].offset); 16598c2ecf20Sopenharmony_ci memcpy(param->operand_byte_stream, 16608c2ecf20Sopenharmony_ci cfg->rule[cnt].params[idx].operand_byte_stream, 16618c2ecf20Sopenharmony_ci param->operand_len); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci length += sizeof(struct coalesce_filt_field_param); 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci param++; 16668c2ecf20Sopenharmony_ci } 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci /* Total rule length is sizeof max_coalescing_delay(u16), 16698c2ecf20Sopenharmony_ci * num_of_fields(u8), pkt_type(u8) and total length of the all 16708c2ecf20Sopenharmony_ci * params 16718c2ecf20Sopenharmony_ci */ 16728c2ecf20Sopenharmony_ci rule->header.len = cpu_to_le16(length + sizeof(u16) + 16738c2ecf20Sopenharmony_ci sizeof(u8) + sizeof(u8)); 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci /* Add the rule length to the command size*/ 16768c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, 16778c2ecf20Sopenharmony_ci le16_to_cpu(rule->header.len) + 16788c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci rule = (void *)((u8 *)rule->params + length); 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* Add sizeof action, num_of_rules to total command length */ 16848c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16)); 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci return 0; 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_cistatic int 16908c2ecf20Sopenharmony_cimwifiex_cmd_tdls_config(struct mwifiex_private *priv, 16918c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 16928c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 16938c2ecf20Sopenharmony_ci{ 16948c2ecf20Sopenharmony_ci struct host_cmd_ds_tdls_config *tdls_config = &cmd->params.tdls_config; 16958c2ecf20Sopenharmony_ci struct mwifiex_tdls_init_cs_params *config; 16968c2ecf20Sopenharmony_ci struct mwifiex_tdls_config *init_config; 16978c2ecf20Sopenharmony_ci u16 len; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_CONFIG); 17008c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(S_DS_GEN); 17018c2ecf20Sopenharmony_ci tdls_config->tdls_action = cpu_to_le16(cmd_action); 17028c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, sizeof(tdls_config->tdls_action)); 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci switch (cmd_action) { 17058c2ecf20Sopenharmony_ci case ACT_TDLS_CS_ENABLE_CONFIG: 17068c2ecf20Sopenharmony_ci init_config = data_buf; 17078c2ecf20Sopenharmony_ci len = sizeof(*init_config); 17088c2ecf20Sopenharmony_ci memcpy(tdls_config->tdls_data, init_config, len); 17098c2ecf20Sopenharmony_ci break; 17108c2ecf20Sopenharmony_ci case ACT_TDLS_CS_INIT: 17118c2ecf20Sopenharmony_ci config = data_buf; 17128c2ecf20Sopenharmony_ci len = sizeof(*config); 17138c2ecf20Sopenharmony_ci memcpy(tdls_config->tdls_data, config, len); 17148c2ecf20Sopenharmony_ci break; 17158c2ecf20Sopenharmony_ci case ACT_TDLS_CS_STOP: 17168c2ecf20Sopenharmony_ci len = sizeof(struct mwifiex_tdls_stop_cs_params); 17178c2ecf20Sopenharmony_ci memcpy(tdls_config->tdls_data, data_buf, len); 17188c2ecf20Sopenharmony_ci break; 17198c2ecf20Sopenharmony_ci case ACT_TDLS_CS_PARAMS: 17208c2ecf20Sopenharmony_ci len = sizeof(struct mwifiex_tdls_config_cs_params); 17218c2ecf20Sopenharmony_ci memcpy(tdls_config->tdls_data, data_buf, len); 17228c2ecf20Sopenharmony_ci break; 17238c2ecf20Sopenharmony_ci default: 17248c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 17258c2ecf20Sopenharmony_ci "Unknown TDLS configuration\n"); 17268c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, len); 17308c2ecf20Sopenharmony_ci return 0; 17318c2ecf20Sopenharmony_ci} 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_cistatic int 17348c2ecf20Sopenharmony_cimwifiex_cmd_tdls_oper(struct mwifiex_private *priv, 17358c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd, 17368c2ecf20Sopenharmony_ci void *data_buf) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; 17398c2ecf20Sopenharmony_ci struct mwifiex_ds_tdls_oper *oper = data_buf; 17408c2ecf20Sopenharmony_ci struct host_cmd_tlv_rates *tlv_rates; 17418c2ecf20Sopenharmony_ci struct mwifiex_ie_types_htcap *ht_capab; 17428c2ecf20Sopenharmony_ci struct mwifiex_ie_types_qos_info *wmm_qos_info; 17438c2ecf20Sopenharmony_ci struct mwifiex_ie_types_extcap *extcap; 17448c2ecf20Sopenharmony_ci struct mwifiex_ie_types_vhtcap *vht_capab; 17458c2ecf20Sopenharmony_ci struct mwifiex_ie_types_aid *aid; 17468c2ecf20Sopenharmony_ci struct mwifiex_ie_types_tdls_idle_timeout *timeout; 17478c2ecf20Sopenharmony_ci u8 *pos; 17488c2ecf20Sopenharmony_ci u16 config_len = 0; 17498c2ecf20Sopenharmony_ci struct station_parameters *params = priv->sta_params; 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER); 17528c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(S_DS_GEN); 17538c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, 17548c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_tdls_oper)); 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci tdls_oper->reason = 0; 17578c2ecf20Sopenharmony_ci memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper); 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci switch (oper->tdls_action) { 17628c2ecf20Sopenharmony_ci case MWIFIEX_TDLS_DISABLE_LINK: 17638c2ecf20Sopenharmony_ci tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE); 17648c2ecf20Sopenharmony_ci break; 17658c2ecf20Sopenharmony_ci case MWIFIEX_TDLS_CREATE_LINK: 17668c2ecf20Sopenharmony_ci tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE); 17678c2ecf20Sopenharmony_ci break; 17688c2ecf20Sopenharmony_ci case MWIFIEX_TDLS_CONFIG_LINK: 17698c2ecf20Sopenharmony_ci tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci if (!params) { 17728c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 17738c2ecf20Sopenharmony_ci "TDLS config params not available for %pM\n", 17748c2ecf20Sopenharmony_ci oper->peer_mac); 17758c2ecf20Sopenharmony_ci return -ENODATA; 17768c2ecf20Sopenharmony_ci } 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci put_unaligned_le16(params->capability, pos); 17798c2ecf20Sopenharmony_ci config_len += sizeof(params->capability); 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci wmm_qos_info = (void *)(pos + config_len); 17828c2ecf20Sopenharmony_ci wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA); 17838c2ecf20Sopenharmony_ci wmm_qos_info->header.len = 17848c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(wmm_qos_info->qos_info)); 17858c2ecf20Sopenharmony_ci wmm_qos_info->qos_info = 0; 17868c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_qos_info); 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci if (params->ht_capa) { 17898c2ecf20Sopenharmony_ci ht_capab = (struct mwifiex_ie_types_htcap *)(pos + 17908c2ecf20Sopenharmony_ci config_len); 17918c2ecf20Sopenharmony_ci ht_capab->header.type = 17928c2ecf20Sopenharmony_ci cpu_to_le16(WLAN_EID_HT_CAPABILITY); 17938c2ecf20Sopenharmony_ci ht_capab->header.len = 17948c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct ieee80211_ht_cap)); 17958c2ecf20Sopenharmony_ci memcpy(&ht_capab->ht_cap, params->ht_capa, 17968c2ecf20Sopenharmony_ci sizeof(struct ieee80211_ht_cap)); 17978c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_htcap); 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci if (params->supported_rates && params->supported_rates_len) { 18018c2ecf20Sopenharmony_ci tlv_rates = (struct host_cmd_tlv_rates *)(pos + 18028c2ecf20Sopenharmony_ci config_len); 18038c2ecf20Sopenharmony_ci tlv_rates->header.type = 18048c2ecf20Sopenharmony_ci cpu_to_le16(WLAN_EID_SUPP_RATES); 18058c2ecf20Sopenharmony_ci tlv_rates->header.len = 18068c2ecf20Sopenharmony_ci cpu_to_le16(params->supported_rates_len); 18078c2ecf20Sopenharmony_ci memcpy(tlv_rates->rates, params->supported_rates, 18088c2ecf20Sopenharmony_ci params->supported_rates_len); 18098c2ecf20Sopenharmony_ci config_len += sizeof(struct host_cmd_tlv_rates) + 18108c2ecf20Sopenharmony_ci params->supported_rates_len; 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci if (params->ext_capab && params->ext_capab_len) { 18148c2ecf20Sopenharmony_ci extcap = (struct mwifiex_ie_types_extcap *)(pos + 18158c2ecf20Sopenharmony_ci config_len); 18168c2ecf20Sopenharmony_ci extcap->header.type = 18178c2ecf20Sopenharmony_ci cpu_to_le16(WLAN_EID_EXT_CAPABILITY); 18188c2ecf20Sopenharmony_ci extcap->header.len = cpu_to_le16(params->ext_capab_len); 18198c2ecf20Sopenharmony_ci memcpy(extcap->ext_capab, params->ext_capab, 18208c2ecf20Sopenharmony_ci params->ext_capab_len); 18218c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_extcap) + 18228c2ecf20Sopenharmony_ci params->ext_capab_len; 18238c2ecf20Sopenharmony_ci } 18248c2ecf20Sopenharmony_ci if (params->vht_capa) { 18258c2ecf20Sopenharmony_ci vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos + 18268c2ecf20Sopenharmony_ci config_len); 18278c2ecf20Sopenharmony_ci vht_capab->header.type = 18288c2ecf20Sopenharmony_ci cpu_to_le16(WLAN_EID_VHT_CAPABILITY); 18298c2ecf20Sopenharmony_ci vht_capab->header.len = 18308c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct ieee80211_vht_cap)); 18318c2ecf20Sopenharmony_ci memcpy(&vht_capab->vht_cap, params->vht_capa, 18328c2ecf20Sopenharmony_ci sizeof(struct ieee80211_vht_cap)); 18338c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_vhtcap); 18348c2ecf20Sopenharmony_ci } 18358c2ecf20Sopenharmony_ci if (params->aid) { 18368c2ecf20Sopenharmony_ci aid = (struct mwifiex_ie_types_aid *)(pos + config_len); 18378c2ecf20Sopenharmony_ci aid->header.type = cpu_to_le16(WLAN_EID_AID); 18388c2ecf20Sopenharmony_ci aid->header.len = cpu_to_le16(sizeof(params->aid)); 18398c2ecf20Sopenharmony_ci aid->aid = cpu_to_le16(params->aid); 18408c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_aid); 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci 18438c2ecf20Sopenharmony_ci timeout = (void *)(pos + config_len); 18448c2ecf20Sopenharmony_ci timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); 18458c2ecf20Sopenharmony_ci timeout->header.len = cpu_to_le16(sizeof(timeout->value)); 18468c2ecf20Sopenharmony_ci timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC); 18478c2ecf20Sopenharmony_ci config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); 18488c2ecf20Sopenharmony_ci 18498c2ecf20Sopenharmony_ci break; 18508c2ecf20Sopenharmony_ci default: 18518c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS operation\n"); 18528c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 18538c2ecf20Sopenharmony_ci } 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci le16_unaligned_add_cpu(&cmd->size, config_len); 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci return 0; 18588c2ecf20Sopenharmony_ci} 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci/* This function prepares command of sdio rx aggr info. */ 18618c2ecf20Sopenharmony_cistatic int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, 18628c2ecf20Sopenharmony_ci u16 cmd_action, void *data_buf) 18638c2ecf20Sopenharmony_ci{ 18648c2ecf20Sopenharmony_ci struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = 18658c2ecf20Sopenharmony_ci &cmd->params.sdio_rx_aggr_cfg; 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG); 18688c2ecf20Sopenharmony_ci cmd->size = 18698c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + 18708c2ecf20Sopenharmony_ci S_DS_GEN); 18718c2ecf20Sopenharmony_ci cfg->action = cmd_action; 18728c2ecf20Sopenharmony_ci if (cmd_action == HostCmd_ACT_GEN_SET) 18738c2ecf20Sopenharmony_ci cfg->enable = *(u8 *)data_buf; 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci return 0; 18768c2ecf20Sopenharmony_ci} 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci/* This function prepares command to get HS wakeup reason. 18798c2ecf20Sopenharmony_ci * 18808c2ecf20Sopenharmony_ci * Preparation includes - 18818c2ecf20Sopenharmony_ci * - Setting command ID, action and proper size 18828c2ecf20Sopenharmony_ci * - Ensuring correct endian-ness 18838c2ecf20Sopenharmony_ci */ 18848c2ecf20Sopenharmony_cistatic int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv, 18858c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd) 18868c2ecf20Sopenharmony_ci{ 18878c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON); 18888c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) + 18898c2ecf20Sopenharmony_ci S_DS_GEN); 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci return 0; 18928c2ecf20Sopenharmony_ci} 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_cistatic int mwifiex_cmd_get_chan_info(struct host_cmd_ds_command *cmd, 18958c2ecf20Sopenharmony_ci u16 cmd_action) 18968c2ecf20Sopenharmony_ci{ 18978c2ecf20Sopenharmony_ci struct host_cmd_ds_sta_configure *sta_cfg_cmd = &cmd->params.sta_cfg; 18988c2ecf20Sopenharmony_ci struct host_cmd_tlv_channel_band *tlv_band_channel = 18998c2ecf20Sopenharmony_ci (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci cmd->command = cpu_to_le16(HostCmd_CMD_STA_CONFIGURE); 19028c2ecf20Sopenharmony_ci cmd->size = cpu_to_le16(sizeof(*sta_cfg_cmd) + 19038c2ecf20Sopenharmony_ci sizeof(*tlv_band_channel) + S_DS_GEN); 19048c2ecf20Sopenharmony_ci sta_cfg_cmd->action = cpu_to_le16(cmd_action); 19058c2ecf20Sopenharmony_ci memset(tlv_band_channel, 0, sizeof(*tlv_band_channel)); 19068c2ecf20Sopenharmony_ci tlv_band_channel->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); 19078c2ecf20Sopenharmony_ci tlv_band_channel->header.len = cpu_to_le16(sizeof(*tlv_band_channel) - 19088c2ecf20Sopenharmony_ci sizeof(struct mwifiex_ie_types_header)); 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci return 0; 19118c2ecf20Sopenharmony_ci} 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci/* This function check if the command is supported by firmware */ 19148c2ecf20Sopenharmony_cistatic int mwifiex_is_cmd_supported(struct mwifiex_private *priv, u16 cmd_no) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci if (!ISSUPP_ADHOC_ENABLED(priv->adapter->fw_cap_info)) { 19178c2ecf20Sopenharmony_ci switch (cmd_no) { 19188c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: 19198c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_START: 19208c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_JOIN: 19218c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_STOP: 19228c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 19238c2ecf20Sopenharmony_ci default: 19248c2ecf20Sopenharmony_ci break; 19258c2ecf20Sopenharmony_ci } 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci return 0; 19298c2ecf20Sopenharmony_ci} 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci/* 19328c2ecf20Sopenharmony_ci * This function prepares the commands before sending them to the firmware. 19338c2ecf20Sopenharmony_ci * 19348c2ecf20Sopenharmony_ci * This is a generic function which calls specific command preparation 19358c2ecf20Sopenharmony_ci * routines based upon the command number. 19368c2ecf20Sopenharmony_ci */ 19378c2ecf20Sopenharmony_ciint mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, 19388c2ecf20Sopenharmony_ci u16 cmd_action, u32 cmd_oid, 19398c2ecf20Sopenharmony_ci void *data_buf, void *cmd_buf) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci struct host_cmd_ds_command *cmd_ptr = cmd_buf; 19428c2ecf20Sopenharmony_ci int ret = 0; 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci if (mwifiex_is_cmd_supported(priv, cmd_no)) { 19458c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 19468c2ecf20Sopenharmony_ci "0x%x command not supported by firmware\n", 19478c2ecf20Sopenharmony_ci cmd_no); 19488c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 19498c2ecf20Sopenharmony_ci } 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci /* Prepare command */ 19528c2ecf20Sopenharmony_ci switch (cmd_no) { 19538c2ecf20Sopenharmony_ci case HostCmd_CMD_GET_HW_SPEC: 19548c2ecf20Sopenharmony_ci ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); 19558c2ecf20Sopenharmony_ci break; 19568c2ecf20Sopenharmony_ci case HostCmd_CMD_CFG_DATA: 19578c2ecf20Sopenharmony_ci ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf); 19588c2ecf20Sopenharmony_ci break; 19598c2ecf20Sopenharmony_ci case HostCmd_CMD_MAC_CONTROL: 19608c2ecf20Sopenharmony_ci ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, 19618c2ecf20Sopenharmony_ci data_buf); 19628c2ecf20Sopenharmony_ci break; 19638c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_MAC_ADDRESS: 19648c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr, 19658c2ecf20Sopenharmony_ci cmd_action); 19668c2ecf20Sopenharmony_ci break; 19678c2ecf20Sopenharmony_ci case HostCmd_CMD_MAC_MULTICAST_ADR: 19688c2ecf20Sopenharmony_ci ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action, 19698c2ecf20Sopenharmony_ci data_buf); 19708c2ecf20Sopenharmony_ci break; 19718c2ecf20Sopenharmony_ci case HostCmd_CMD_TX_RATE_CFG: 19728c2ecf20Sopenharmony_ci ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action, 19738c2ecf20Sopenharmony_ci data_buf); 19748c2ecf20Sopenharmony_ci break; 19758c2ecf20Sopenharmony_ci case HostCmd_CMD_TXPWR_CFG: 19768c2ecf20Sopenharmony_ci ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action, 19778c2ecf20Sopenharmony_ci data_buf); 19788c2ecf20Sopenharmony_ci break; 19798c2ecf20Sopenharmony_ci case HostCmd_CMD_RF_TX_PWR: 19808c2ecf20Sopenharmony_ci ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action, 19818c2ecf20Sopenharmony_ci data_buf); 19828c2ecf20Sopenharmony_ci break; 19838c2ecf20Sopenharmony_ci case HostCmd_CMD_RF_ANTENNA: 19848c2ecf20Sopenharmony_ci ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action, 19858c2ecf20Sopenharmony_ci data_buf); 19868c2ecf20Sopenharmony_ci break; 19878c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_PS_MODE_ENH: 19888c2ecf20Sopenharmony_ci ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, 19898c2ecf20Sopenharmony_ci (uint16_t)cmd_oid, data_buf); 19908c2ecf20Sopenharmony_ci break; 19918c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_HS_CFG_ENH: 19928c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action, 19938c2ecf20Sopenharmony_ci (struct mwifiex_hs_config_param *) data_buf); 19948c2ecf20Sopenharmony_ci break; 19958c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_SCAN: 19968c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); 19978c2ecf20Sopenharmony_ci break; 19988c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_BG_SCAN_CONFIG: 19998c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_bg_scan_config(priv, cmd_ptr, 20008c2ecf20Sopenharmony_ci data_buf); 20018c2ecf20Sopenharmony_ci break; 20028c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_BG_SCAN_QUERY: 20038c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); 20048c2ecf20Sopenharmony_ci break; 20058c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_ASSOCIATE: 20068c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); 20078c2ecf20Sopenharmony_ci break; 20088c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_DEAUTHENTICATE: 20098c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr, 20108c2ecf20Sopenharmony_ci data_buf); 20118c2ecf20Sopenharmony_ci break; 20128c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_START: 20138c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr, 20148c2ecf20Sopenharmony_ci data_buf); 20158c2ecf20Sopenharmony_ci break; 20168c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_GET_LOG: 20178c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_get_log(cmd_ptr); 20188c2ecf20Sopenharmony_ci break; 20198c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_JOIN: 20208c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr, 20218c2ecf20Sopenharmony_ci data_buf); 20228c2ecf20Sopenharmony_ci break; 20238c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_STOP: 20248c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr); 20258c2ecf20Sopenharmony_ci break; 20268c2ecf20Sopenharmony_ci case HostCmd_CMD_RSSI_INFO: 20278c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); 20288c2ecf20Sopenharmony_ci break; 20298c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_SNMP_MIB: 20308c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action, 20318c2ecf20Sopenharmony_ci cmd_oid, data_buf); 20328c2ecf20Sopenharmony_ci break; 20338c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_TX_RATE_QUERY: 20348c2ecf20Sopenharmony_ci cmd_ptr->command = 20358c2ecf20Sopenharmony_ci cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); 20368c2ecf20Sopenharmony_ci cmd_ptr->size = 20378c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + 20388c2ecf20Sopenharmony_ci S_DS_GEN); 20398c2ecf20Sopenharmony_ci priv->tx_rate = 0; 20408c2ecf20Sopenharmony_ci ret = 0; 20418c2ecf20Sopenharmony_ci break; 20428c2ecf20Sopenharmony_ci case HostCmd_CMD_VERSION_EXT: 20438c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20448c2ecf20Sopenharmony_ci cmd_ptr->params.verext.version_str_sel = 20458c2ecf20Sopenharmony_ci (u8)(get_unaligned((u32 *)data_buf)); 20468c2ecf20Sopenharmony_ci memcpy(&cmd_ptr->params, data_buf, 20478c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_version_ext)); 20488c2ecf20Sopenharmony_ci cmd_ptr->size = 20498c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + 20508c2ecf20Sopenharmony_ci S_DS_GEN); 20518c2ecf20Sopenharmony_ci ret = 0; 20528c2ecf20Sopenharmony_ci break; 20538c2ecf20Sopenharmony_ci case HostCmd_CMD_MGMT_FRAME_REG: 20548c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20558c2ecf20Sopenharmony_ci cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action); 20568c2ecf20Sopenharmony_ci cmd_ptr->params.reg_mask.mask = cpu_to_le32( 20578c2ecf20Sopenharmony_ci get_unaligned((u32 *)data_buf)); 20588c2ecf20Sopenharmony_ci cmd_ptr->size = 20598c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + 20608c2ecf20Sopenharmony_ci S_DS_GEN); 20618c2ecf20Sopenharmony_ci ret = 0; 20628c2ecf20Sopenharmony_ci break; 20638c2ecf20Sopenharmony_ci case HostCmd_CMD_REMAIN_ON_CHAN: 20648c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20658c2ecf20Sopenharmony_ci memcpy(&cmd_ptr->params, data_buf, 20668c2ecf20Sopenharmony_ci sizeof(struct host_cmd_ds_remain_on_chan)); 20678c2ecf20Sopenharmony_ci cmd_ptr->size = 20688c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + 20698c2ecf20Sopenharmony_ci S_DS_GEN); 20708c2ecf20Sopenharmony_ci break; 20718c2ecf20Sopenharmony_ci case HostCmd_CMD_11AC_CFG: 20728c2ecf20Sopenharmony_ci ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf); 20738c2ecf20Sopenharmony_ci break; 20748c2ecf20Sopenharmony_ci case HostCmd_CMD_PACKET_AGGR_CTRL: 20758c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20768c2ecf20Sopenharmony_ci cmd_ptr->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action); 20778c2ecf20Sopenharmony_ci cmd_ptr->params.pkt_aggr_ctrl.enable = 20788c2ecf20Sopenharmony_ci cpu_to_le16(*(u16 *)data_buf); 20798c2ecf20Sopenharmony_ci cmd_ptr->size = 20808c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) + 20818c2ecf20Sopenharmony_ci S_DS_GEN); 20828c2ecf20Sopenharmony_ci break; 20838c2ecf20Sopenharmony_ci case HostCmd_CMD_P2P_MODE_CFG: 20848c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20858c2ecf20Sopenharmony_ci cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); 20868c2ecf20Sopenharmony_ci cmd_ptr->params.mode_cfg.mode = cpu_to_le16( 20878c2ecf20Sopenharmony_ci get_unaligned((u16 *)data_buf)); 20888c2ecf20Sopenharmony_ci cmd_ptr->size = 20898c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) + 20908c2ecf20Sopenharmony_ci S_DS_GEN); 20918c2ecf20Sopenharmony_ci break; 20928c2ecf20Sopenharmony_ci case HostCmd_CMD_FUNC_INIT: 20938c2ecf20Sopenharmony_ci if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) 20948c2ecf20Sopenharmony_ci priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; 20958c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 20968c2ecf20Sopenharmony_ci cmd_ptr->size = cpu_to_le16(S_DS_GEN); 20978c2ecf20Sopenharmony_ci break; 20988c2ecf20Sopenharmony_ci case HostCmd_CMD_FUNC_SHUTDOWN: 20998c2ecf20Sopenharmony_ci priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET; 21008c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 21018c2ecf20Sopenharmony_ci cmd_ptr->size = cpu_to_le16(S_DS_GEN); 21028c2ecf20Sopenharmony_ci break; 21038c2ecf20Sopenharmony_ci case HostCmd_CMD_11N_ADDBA_REQ: 21048c2ecf20Sopenharmony_ci ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf); 21058c2ecf20Sopenharmony_ci break; 21068c2ecf20Sopenharmony_ci case HostCmd_CMD_11N_DELBA: 21078c2ecf20Sopenharmony_ci ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf); 21088c2ecf20Sopenharmony_ci break; 21098c2ecf20Sopenharmony_ci case HostCmd_CMD_11N_ADDBA_RSP: 21108c2ecf20Sopenharmony_ci ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); 21118c2ecf20Sopenharmony_ci break; 21128c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_KEY_MATERIAL: 21138c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr, 21148c2ecf20Sopenharmony_ci cmd_action, cmd_oid, 21158c2ecf20Sopenharmony_ci data_buf); 21168c2ecf20Sopenharmony_ci break; 21178c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11D_DOMAIN_INFO: 21188c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr, 21198c2ecf20Sopenharmony_ci cmd_action); 21208c2ecf20Sopenharmony_ci break; 21218c2ecf20Sopenharmony_ci case HostCmd_CMD_RECONFIGURE_TX_BUFF: 21228c2ecf20Sopenharmony_ci ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action, 21238c2ecf20Sopenharmony_ci data_buf); 21248c2ecf20Sopenharmony_ci break; 21258c2ecf20Sopenharmony_ci case HostCmd_CMD_AMSDU_AGGR_CTRL: 21268c2ecf20Sopenharmony_ci ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action, 21278c2ecf20Sopenharmony_ci data_buf); 21288c2ecf20Sopenharmony_ci break; 21298c2ecf20Sopenharmony_ci case HostCmd_CMD_11N_CFG: 21308c2ecf20Sopenharmony_ci ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf); 21318c2ecf20Sopenharmony_ci break; 21328c2ecf20Sopenharmony_ci case HostCmd_CMD_WMM_GET_STATUS: 21338c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, CMD, 21348c2ecf20Sopenharmony_ci "cmd: WMM: WMM_GET_STATUS cmd sent\n"); 21358c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); 21368c2ecf20Sopenharmony_ci cmd_ptr->size = 21378c2ecf20Sopenharmony_ci cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + 21388c2ecf20Sopenharmony_ci S_DS_GEN); 21398c2ecf20Sopenharmony_ci ret = 0; 21408c2ecf20Sopenharmony_ci break; 21418c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: 21428c2ecf20Sopenharmony_ci ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, 21438c2ecf20Sopenharmony_ci data_buf); 21448c2ecf20Sopenharmony_ci break; 21458c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_SCAN_EXT: 21468c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf); 21478c2ecf20Sopenharmony_ci break; 21488c2ecf20Sopenharmony_ci case HostCmd_CMD_MEM_ACCESS: 21498c2ecf20Sopenharmony_ci ret = mwifiex_cmd_mem_access(cmd_ptr, cmd_action, data_buf); 21508c2ecf20Sopenharmony_ci break; 21518c2ecf20Sopenharmony_ci case HostCmd_CMD_MAC_REG_ACCESS: 21528c2ecf20Sopenharmony_ci case HostCmd_CMD_BBP_REG_ACCESS: 21538c2ecf20Sopenharmony_ci case HostCmd_CMD_RF_REG_ACCESS: 21548c2ecf20Sopenharmony_ci case HostCmd_CMD_PMIC_REG_ACCESS: 21558c2ecf20Sopenharmony_ci case HostCmd_CMD_CAU_REG_ACCESS: 21568c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_EEPROM_ACCESS: 21578c2ecf20Sopenharmony_ci ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf); 21588c2ecf20Sopenharmony_ci break; 21598c2ecf20Sopenharmony_ci case HostCmd_CMD_SET_BSS_MODE: 21608c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 21618c2ecf20Sopenharmony_ci if (priv->bss_mode == NL80211_IFTYPE_ADHOC) 21628c2ecf20Sopenharmony_ci cmd_ptr->params.bss_mode.con_type = 21638c2ecf20Sopenharmony_ci CONNECTION_TYPE_ADHOC; 21648c2ecf20Sopenharmony_ci else if (priv->bss_mode == NL80211_IFTYPE_STATION || 21658c2ecf20Sopenharmony_ci priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) 21668c2ecf20Sopenharmony_ci cmd_ptr->params.bss_mode.con_type = 21678c2ecf20Sopenharmony_ci CONNECTION_TYPE_INFRA; 21688c2ecf20Sopenharmony_ci else if (priv->bss_mode == NL80211_IFTYPE_AP || 21698c2ecf20Sopenharmony_ci priv->bss_mode == NL80211_IFTYPE_P2P_GO) 21708c2ecf20Sopenharmony_ci cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP; 21718c2ecf20Sopenharmony_ci cmd_ptr->size = cpu_to_le16(sizeof(struct 21728c2ecf20Sopenharmony_ci host_cmd_ds_set_bss_mode) + S_DS_GEN); 21738c2ecf20Sopenharmony_ci ret = 0; 21748c2ecf20Sopenharmony_ci break; 21758c2ecf20Sopenharmony_ci case HostCmd_CMD_PCIE_DESC_DETAILS: 21768c2ecf20Sopenharmony_ci ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action); 21778c2ecf20Sopenharmony_ci break; 21788c2ecf20Sopenharmony_ci case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: 21798c2ecf20Sopenharmony_ci ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); 21808c2ecf20Sopenharmony_ci break; 21818c2ecf20Sopenharmony_ci case HostCmd_CMD_MEF_CFG: 21828c2ecf20Sopenharmony_ci ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); 21838c2ecf20Sopenharmony_ci break; 21848c2ecf20Sopenharmony_ci case HostCmd_CMD_COALESCE_CFG: 21858c2ecf20Sopenharmony_ci ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action, 21868c2ecf20Sopenharmony_ci data_buf); 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci case HostCmd_CMD_TDLS_OPER: 21898c2ecf20Sopenharmony_ci ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); 21908c2ecf20Sopenharmony_ci break; 21918c2ecf20Sopenharmony_ci case HostCmd_CMD_TDLS_CONFIG: 21928c2ecf20Sopenharmony_ci ret = mwifiex_cmd_tdls_config(priv, cmd_ptr, cmd_action, 21938c2ecf20Sopenharmony_ci data_buf); 21948c2ecf20Sopenharmony_ci break; 21958c2ecf20Sopenharmony_ci case HostCmd_CMD_CHAN_REPORT_REQUEST: 21968c2ecf20Sopenharmony_ci ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, 21978c2ecf20Sopenharmony_ci data_buf); 21988c2ecf20Sopenharmony_ci break; 21998c2ecf20Sopenharmony_ci case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: 22008c2ecf20Sopenharmony_ci ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, 22018c2ecf20Sopenharmony_ci data_buf); 22028c2ecf20Sopenharmony_ci break; 22038c2ecf20Sopenharmony_ci case HostCmd_CMD_HS_WAKEUP_REASON: 22048c2ecf20Sopenharmony_ci ret = mwifiex_cmd_get_wakeup_reason(priv, cmd_ptr); 22058c2ecf20Sopenharmony_ci break; 22068c2ecf20Sopenharmony_ci case HostCmd_CMD_MC_POLICY: 22078c2ecf20Sopenharmony_ci ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, 22088c2ecf20Sopenharmony_ci data_buf); 22098c2ecf20Sopenharmony_ci break; 22108c2ecf20Sopenharmony_ci case HostCmd_CMD_ROBUST_COEX: 22118c2ecf20Sopenharmony_ci ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action, 22128c2ecf20Sopenharmony_ci data_buf); 22138c2ecf20Sopenharmony_ci break; 22148c2ecf20Sopenharmony_ci case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG: 22158c2ecf20Sopenharmony_ci ret = mwifiex_cmd_gtk_rekey_offload(priv, cmd_ptr, cmd_action, 22168c2ecf20Sopenharmony_ci data_buf); 22178c2ecf20Sopenharmony_ci break; 22188c2ecf20Sopenharmony_ci case HostCmd_CMD_CHAN_REGION_CFG: 22198c2ecf20Sopenharmony_ci ret = mwifiex_cmd_chan_region_cfg(priv, cmd_ptr, cmd_action); 22208c2ecf20Sopenharmony_ci break; 22218c2ecf20Sopenharmony_ci case HostCmd_CMD_FW_DUMP_EVENT: 22228c2ecf20Sopenharmony_ci cmd_ptr->command = cpu_to_le16(cmd_no); 22238c2ecf20Sopenharmony_ci cmd_ptr->size = cpu_to_le16(S_DS_GEN); 22248c2ecf20Sopenharmony_ci break; 22258c2ecf20Sopenharmony_ci case HostCmd_CMD_STA_CONFIGURE: 22268c2ecf20Sopenharmony_ci ret = mwifiex_cmd_get_chan_info(cmd_ptr, cmd_action); 22278c2ecf20Sopenharmony_ci break; 22288c2ecf20Sopenharmony_ci default: 22298c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 22308c2ecf20Sopenharmony_ci "PREP_CMD: unknown cmd- %#x\n", cmd_no); 22318c2ecf20Sopenharmony_ci ret = -1; 22328c2ecf20Sopenharmony_ci break; 22338c2ecf20Sopenharmony_ci } 22348c2ecf20Sopenharmony_ci return ret; 22358c2ecf20Sopenharmony_ci} 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci/* 22388c2ecf20Sopenharmony_ci * This function issues commands to initialize firmware. 22398c2ecf20Sopenharmony_ci * 22408c2ecf20Sopenharmony_ci * This is called after firmware download to bring the card to 22418c2ecf20Sopenharmony_ci * working state. 22428c2ecf20Sopenharmony_ci * Function is also called during reinitialization of virtual 22438c2ecf20Sopenharmony_ci * interfaces. 22448c2ecf20Sopenharmony_ci * 22458c2ecf20Sopenharmony_ci * The following commands are issued sequentially - 22468c2ecf20Sopenharmony_ci * - Set PCI-Express host buffer configuration (PCIE only) 22478c2ecf20Sopenharmony_ci * - Function init (for first interface only) 22488c2ecf20Sopenharmony_ci * - Read MAC address (for first interface only) 22498c2ecf20Sopenharmony_ci * - Reconfigure Tx buffer size (for first interface only) 22508c2ecf20Sopenharmony_ci * - Enable auto deep sleep (for first interface only) 22518c2ecf20Sopenharmony_ci * - Get Tx rate 22528c2ecf20Sopenharmony_ci * - Get Tx power 22538c2ecf20Sopenharmony_ci * - Set IBSS coalescing status 22548c2ecf20Sopenharmony_ci * - Set AMSDU aggregation control 22558c2ecf20Sopenharmony_ci * - Set 11d control 22568c2ecf20Sopenharmony_ci * - Set MAC control (this must be the last command to initialize firmware) 22578c2ecf20Sopenharmony_ci */ 22588c2ecf20Sopenharmony_ciint mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) 22598c2ecf20Sopenharmony_ci{ 22608c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 22618c2ecf20Sopenharmony_ci int ret; 22628c2ecf20Sopenharmony_ci struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; 22638c2ecf20Sopenharmony_ci struct mwifiex_ds_auto_ds auto_ds; 22648c2ecf20Sopenharmony_ci enum state_11d_t state_11d; 22658c2ecf20Sopenharmony_ci struct mwifiex_ds_11n_tx_cfg tx_cfg; 22668c2ecf20Sopenharmony_ci u8 sdio_sp_rx_aggr_enable; 22678c2ecf20Sopenharmony_ci u16 packet_aggr_enable; 22688c2ecf20Sopenharmony_ci int data; 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci if (first_sta) { 22718c2ecf20Sopenharmony_ci if (priv->adapter->iface_type == MWIFIEX_PCIE) { 22728c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, 22738c2ecf20Sopenharmony_ci HostCmd_CMD_PCIE_DESC_DETAILS, 22748c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, NULL, 22758c2ecf20Sopenharmony_ci true); 22768c2ecf20Sopenharmony_ci if (ret) 22778c2ecf20Sopenharmony_ci return -1; 22788c2ecf20Sopenharmony_ci } 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_FUNC_INIT, 22818c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, NULL, true); 22828c2ecf20Sopenharmony_ci if (ret) 22838c2ecf20Sopenharmony_ci return -1; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci /* Download calibration data to firmware. 22868c2ecf20Sopenharmony_ci * The cal-data can be read from device tree and/or 22878c2ecf20Sopenharmony_ci * a configuration file and downloaded to firmware. 22888c2ecf20Sopenharmony_ci */ 22898c2ecf20Sopenharmony_ci if (adapter->dt_node) { 22908c2ecf20Sopenharmony_ci if (of_property_read_u32(adapter->dt_node, 22918c2ecf20Sopenharmony_ci "marvell,wakeup-pin", 22928c2ecf20Sopenharmony_ci &data) == 0) { 22938c2ecf20Sopenharmony_ci pr_debug("Wakeup pin = 0x%x\n", data); 22948c2ecf20Sopenharmony_ci adapter->hs_cfg.gpio = data; 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, 22988c2ecf20Sopenharmony_ci "marvell,caldata"); 22998c2ecf20Sopenharmony_ci } 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci if (adapter->cal_data) 23028c2ecf20Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, 23038c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, NULL, true); 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci /* Read MAC address from HW */ 23068c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC, 23078c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, true); 23088c2ecf20Sopenharmony_ci if (ret) 23098c2ecf20Sopenharmony_ci return -1; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci /** Set SDIO Single Port RX Aggr Info */ 23128c2ecf20Sopenharmony_ci if (priv->adapter->iface_type == MWIFIEX_SDIO && 23138c2ecf20Sopenharmony_ci ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && 23148c2ecf20Sopenharmony_ci !priv->adapter->host_disable_sdio_rx_aggr) { 23158c2ecf20Sopenharmony_ci sdio_sp_rx_aggr_enable = true; 23168c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, 23178c2ecf20Sopenharmony_ci HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, 23188c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 23198c2ecf20Sopenharmony_ci &sdio_sp_rx_aggr_enable, 23208c2ecf20Sopenharmony_ci true); 23218c2ecf20Sopenharmony_ci if (ret) { 23228c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 23238c2ecf20Sopenharmony_ci "error while enabling SP aggregation..disable it"); 23248c2ecf20Sopenharmony_ci adapter->sdio_rx_aggr_enable = false; 23258c2ecf20Sopenharmony_ci } 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci /* Reconfigure tx buf size */ 23298c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, 23308c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 23318c2ecf20Sopenharmony_ci &priv->adapter->tx_buf_size, true); 23328c2ecf20Sopenharmony_ci if (ret) 23338c2ecf20Sopenharmony_ci return -1; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { 23368c2ecf20Sopenharmony_ci /* Enable IEEE PS by default */ 23378c2ecf20Sopenharmony_ci priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; 23388c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, 23398c2ecf20Sopenharmony_ci HostCmd_CMD_802_11_PS_MODE_ENH, 23408c2ecf20Sopenharmony_ci EN_AUTO_PS, BITMAP_STA_PS, NULL, 23418c2ecf20Sopenharmony_ci true); 23428c2ecf20Sopenharmony_ci if (ret) 23438c2ecf20Sopenharmony_ci return -1; 23448c2ecf20Sopenharmony_ci } 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci if (drcs) { 23478c2ecf20Sopenharmony_ci adapter->drcs_enabled = true; 23488c2ecf20Sopenharmony_ci if (ISSUPP_DRCS_ENABLED(adapter->fw_cap_info)) 23498c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, 23508c2ecf20Sopenharmony_ci HostCmd_CMD_MC_POLICY, 23518c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 23528c2ecf20Sopenharmony_ci &adapter->drcs_enabled, 23538c2ecf20Sopenharmony_ci true); 23548c2ecf20Sopenharmony_ci if (ret) 23558c2ecf20Sopenharmony_ci return -1; 23568c2ecf20Sopenharmony_ci } 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG, 23598c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, true); 23608c2ecf20Sopenharmony_ci } 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci /* get tx rate */ 23638c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, 23648c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, true); 23658c2ecf20Sopenharmony_ci if (ret) 23668c2ecf20Sopenharmony_ci return -1; 23678c2ecf20Sopenharmony_ci priv->data_rate = 0; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci /* get tx power */ 23708c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR, 23718c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, true); 23728c2ecf20Sopenharmony_ci if (ret) 23738c2ecf20Sopenharmony_ci return -1; 23748c2ecf20Sopenharmony_ci 23758c2ecf20Sopenharmony_ci memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); 23768c2ecf20Sopenharmony_ci amsdu_aggr_ctrl.enable = true; 23778c2ecf20Sopenharmony_ci /* Send request to firmware */ 23788c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, 23798c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 23808c2ecf20Sopenharmony_ci &amsdu_aggr_ctrl, true); 23818c2ecf20Sopenharmony_ci if (ret) 23828c2ecf20Sopenharmony_ci return -1; 23838c2ecf20Sopenharmony_ci /* MAC Control must be the last command in init_fw */ 23848c2ecf20Sopenharmony_ci /* set MAC Control */ 23858c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, 23868c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 23878c2ecf20Sopenharmony_ci &priv->curr_pkt_filter, true); 23888c2ecf20Sopenharmony_ci if (ret) 23898c2ecf20Sopenharmony_ci return -1; 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci if (!disable_auto_ds && first_sta && 23928c2ecf20Sopenharmony_ci priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { 23938c2ecf20Sopenharmony_ci /* Enable auto deep sleep */ 23948c2ecf20Sopenharmony_ci auto_ds.auto_ds = DEEP_SLEEP_ON; 23958c2ecf20Sopenharmony_ci auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; 23968c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, 23978c2ecf20Sopenharmony_ci EN_AUTO_PS, BITMAP_AUTO_DS, 23988c2ecf20Sopenharmony_ci &auto_ds, true); 23998c2ecf20Sopenharmony_ci if (ret) 24008c2ecf20Sopenharmony_ci return -1; 24018c2ecf20Sopenharmony_ci } 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { 24048c2ecf20Sopenharmony_ci /* Send cmd to FW to enable/disable 11D function */ 24058c2ecf20Sopenharmony_ci state_11d = ENABLE_11D; 24068c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, 24078c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, DOT11D_I, 24088c2ecf20Sopenharmony_ci &state_11d, true); 24098c2ecf20Sopenharmony_ci if (ret) 24108c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 24118c2ecf20Sopenharmony_ci "11D: failed to enable 11D\n"); 24128c2ecf20Sopenharmony_ci } 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci /* Pacekt aggregation handshake with firmware */ 24158c2ecf20Sopenharmony_ci if (aggr_ctrl) { 24168c2ecf20Sopenharmony_ci packet_aggr_enable = true; 24178c2ecf20Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_PACKET_AGGR_CTRL, 24188c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, 24198c2ecf20Sopenharmony_ci &packet_aggr_enable, true); 24208c2ecf20Sopenharmony_ci } 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci /* Send cmd to FW to configure 11n specific configuration 24238c2ecf20Sopenharmony_ci * (Short GI, Channel BW, Green field support etc.) for transmit 24248c2ecf20Sopenharmony_ci */ 24258c2ecf20Sopenharmony_ci tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; 24268c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, 24278c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci if (init) { 24308c2ecf20Sopenharmony_ci /* set last_init_cmd before sending the command */ 24318c2ecf20Sopenharmony_ci priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; 24328c2ecf20Sopenharmony_ci ret = -EINPROGRESS; 24338c2ecf20Sopenharmony_ci } 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci return ret; 24368c2ecf20Sopenharmony_ci} 2437