162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * NXP Wireless LAN device driver: station command response handling 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2011-2020 NXP 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "decl.h" 962306a36Sopenharmony_ci#include "ioctl.h" 1062306a36Sopenharmony_ci#include "util.h" 1162306a36Sopenharmony_ci#include "fw.h" 1262306a36Sopenharmony_ci#include "main.h" 1362306a36Sopenharmony_ci#include "wmm.h" 1462306a36Sopenharmony_ci#include "11n.h" 1562306a36Sopenharmony_ci#include "11ac.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* 1962306a36Sopenharmony_ci * This function handles the command response error case. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * For scan response error, the function cancels all the pending 2262306a36Sopenharmony_ci * scan commands and generates an event to inform the applications 2362306a36Sopenharmony_ci * of the scan completion. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * For Power Save command failure, we do not retry enter PS 2662306a36Sopenharmony_ci * command in case of Ad-hoc mode. 2762306a36Sopenharmony_ci * 2862306a36Sopenharmony_ci * For all other response errors, the current command buffer is freed 2962306a36Sopenharmony_ci * and returned to the free command queue. 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_cistatic void 3262306a36Sopenharmony_cimwifiex_process_cmdresp_error(struct mwifiex_private *priv, 3362306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 3662306a36Sopenharmony_ci struct host_cmd_ds_802_11_ps_mode_enh *pm; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 3962306a36Sopenharmony_ci "CMD_RESP: cmd %#x error, result=%#x\n", 4062306a36Sopenharmony_ci resp->command, resp->result); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci if (adapter->curr_cmd->wait_q_enabled) 4362306a36Sopenharmony_ci adapter->cmd_wait_q.status = -1; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci switch (le16_to_cpu(resp->command)) { 4662306a36Sopenharmony_ci case HostCmd_CMD_802_11_PS_MODE_ENH: 4762306a36Sopenharmony_ci pm = &resp->params.psmode_enh; 4862306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 4962306a36Sopenharmony_ci "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n", 5062306a36Sopenharmony_ci resp->result, le16_to_cpu(pm->action)); 5162306a36Sopenharmony_ci /* We do not re-try enter-ps command in ad-hoc mode. */ 5262306a36Sopenharmony_ci if (le16_to_cpu(pm->action) == EN_AUTO_PS && 5362306a36Sopenharmony_ci (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) && 5462306a36Sopenharmony_ci priv->bss_mode == NL80211_IFTYPE_ADHOC) 5562306a36Sopenharmony_ci adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci break; 5862306a36Sopenharmony_ci case HostCmd_CMD_802_11_SCAN: 5962306a36Sopenharmony_ci case HostCmd_CMD_802_11_SCAN_EXT: 6062306a36Sopenharmony_ci mwifiex_cancel_scan(adapter); 6162306a36Sopenharmony_ci break; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci case HostCmd_CMD_MAC_CONTROL: 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: 6762306a36Sopenharmony_ci mwifiex_dbg(adapter, MSG, 6862306a36Sopenharmony_ci "SDIO RX single-port aggregation Not support\n"); 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci default: 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci /* Handling errors here */ 7562306a36Sopenharmony_ci mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci spin_lock_bh(&adapter->mwifiex_cmd_lock); 7862306a36Sopenharmony_ci adapter->curr_cmd = NULL; 7962306a36Sopenharmony_ci spin_unlock_bh(&adapter->mwifiex_cmd_lock); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* 8362306a36Sopenharmony_ci * This function handles the command response of get RSSI info. 8462306a36Sopenharmony_ci * 8562306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 8662306a36Sopenharmony_ci * and saving the following parameters in driver - 8762306a36Sopenharmony_ci * - Last data and beacon RSSI value 8862306a36Sopenharmony_ci * - Average data and beacon RSSI value 8962306a36Sopenharmony_ci * - Last data and beacon NF value 9062306a36Sopenharmony_ci * - Average data and beacon NF value 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * The parameters are send to the application as well, along with 9362306a36Sopenharmony_ci * calculated SNR values. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, 9662306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = 9962306a36Sopenharmony_ci &resp->params.rssi_info_rsp; 10062306a36Sopenharmony_ci struct mwifiex_ds_misc_subsc_evt *subsc_evt = 10162306a36Sopenharmony_ci &priv->async_subsc_evt_storage; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); 10462306a36Sopenharmony_ci priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); 10762306a36Sopenharmony_ci priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); 11062306a36Sopenharmony_ci priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); 11362306a36Sopenharmony_ci priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (priv->subsc_evt_rssi_state == EVENT_HANDLED) 11662306a36Sopenharmony_ci return 0; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Resubscribe low and high rssi events with new thresholds */ 12162306a36Sopenharmony_ci subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; 12262306a36Sopenharmony_ci subsc_evt->action = HostCmd_ACT_BITWISE_SET; 12362306a36Sopenharmony_ci if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { 12462306a36Sopenharmony_ci subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - 12562306a36Sopenharmony_ci priv->cqm_rssi_hyst); 12662306a36Sopenharmony_ci subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); 12762306a36Sopenharmony_ci } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { 12862306a36Sopenharmony_ci subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); 12962306a36Sopenharmony_ci subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + 13062306a36Sopenharmony_ci priv->cqm_rssi_hyst); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci subsc_evt->bcn_l_rssi_cfg.evt_freq = 1; 13362306a36Sopenharmony_ci subsc_evt->bcn_h_rssi_cfg.evt_freq = 1; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci priv->subsc_evt_rssi_state = EVENT_HANDLED; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, 13862306a36Sopenharmony_ci 0, 0, subsc_evt, false); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* 14462306a36Sopenharmony_ci * This function handles the command response of set/get SNMP 14562306a36Sopenharmony_ci * MIB parameters. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 14862306a36Sopenharmony_ci * and saving the parameter in driver. 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci * The following parameters are supported - 15162306a36Sopenharmony_ci * - Fragmentation threshold 15262306a36Sopenharmony_ci * - RTS threshold 15362306a36Sopenharmony_ci * - Short retry limit 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_cistatic int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, 15662306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 15762306a36Sopenharmony_ci u32 *data_buf) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; 16062306a36Sopenharmony_ci u16 oid = le16_to_cpu(smib->oid); 16162306a36Sopenharmony_ci u16 query_type = le16_to_cpu(smib->query_type); 16262306a36Sopenharmony_ci u32 ul_temp; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 16562306a36Sopenharmony_ci "info: SNMP_RESP: oid value = %#x,\t" 16662306a36Sopenharmony_ci "query_type = %#x, buf size = %#x\n", 16762306a36Sopenharmony_ci oid, query_type, le16_to_cpu(smib->buf_size)); 16862306a36Sopenharmony_ci if (query_type == HostCmd_ACT_GEN_GET) { 16962306a36Sopenharmony_ci ul_temp = get_unaligned_le16(smib->value); 17062306a36Sopenharmony_ci if (data_buf) 17162306a36Sopenharmony_ci *data_buf = ul_temp; 17262306a36Sopenharmony_ci switch (oid) { 17362306a36Sopenharmony_ci case FRAG_THRESH_I: 17462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 17562306a36Sopenharmony_ci "info: SNMP_RESP: FragThsd =%u\n", 17662306a36Sopenharmony_ci ul_temp); 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci case RTS_THRESH_I: 17962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 18062306a36Sopenharmony_ci "info: SNMP_RESP: RTSThsd =%u\n", 18162306a36Sopenharmony_ci ul_temp); 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci case SHORT_RETRY_LIM_I: 18462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 18562306a36Sopenharmony_ci "info: SNMP_RESP: TxRetryCount=%u\n", 18662306a36Sopenharmony_ci ul_temp); 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci case DTIM_PERIOD_I: 18962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 19062306a36Sopenharmony_ci "info: SNMP_RESP: DTIM period=%u\n", 19162306a36Sopenharmony_ci ul_temp); 19262306a36Sopenharmony_ci break; 19362306a36Sopenharmony_ci default: 19462306a36Sopenharmony_ci break; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci } 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/* 20262306a36Sopenharmony_ci * This function handles the command response of get log request 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 20562306a36Sopenharmony_ci * and sending the received parameters to application. 20662306a36Sopenharmony_ci */ 20762306a36Sopenharmony_cistatic int mwifiex_ret_get_log(struct mwifiex_private *priv, 20862306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 20962306a36Sopenharmony_ci struct mwifiex_ds_get_stats *stats) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci struct host_cmd_ds_802_11_get_log *get_log = 21262306a36Sopenharmony_ci &resp->params.get_log; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (stats) { 21562306a36Sopenharmony_ci stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); 21662306a36Sopenharmony_ci stats->failed = le32_to_cpu(get_log->failed); 21762306a36Sopenharmony_ci stats->retry = le32_to_cpu(get_log->retry); 21862306a36Sopenharmony_ci stats->multi_retry = le32_to_cpu(get_log->multi_retry); 21962306a36Sopenharmony_ci stats->frame_dup = le32_to_cpu(get_log->frame_dup); 22062306a36Sopenharmony_ci stats->rts_success = le32_to_cpu(get_log->rts_success); 22162306a36Sopenharmony_ci stats->rts_failure = le32_to_cpu(get_log->rts_failure); 22262306a36Sopenharmony_ci stats->ack_failure = le32_to_cpu(get_log->ack_failure); 22362306a36Sopenharmony_ci stats->rx_frag = le32_to_cpu(get_log->rx_frag); 22462306a36Sopenharmony_ci stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); 22562306a36Sopenharmony_ci stats->fcs_error = le32_to_cpu(get_log->fcs_error); 22662306a36Sopenharmony_ci stats->tx_frame = le32_to_cpu(get_log->tx_frame); 22762306a36Sopenharmony_ci stats->wep_icv_error[0] = 22862306a36Sopenharmony_ci le32_to_cpu(get_log->wep_icv_err_cnt[0]); 22962306a36Sopenharmony_ci stats->wep_icv_error[1] = 23062306a36Sopenharmony_ci le32_to_cpu(get_log->wep_icv_err_cnt[1]); 23162306a36Sopenharmony_ci stats->wep_icv_error[2] = 23262306a36Sopenharmony_ci le32_to_cpu(get_log->wep_icv_err_cnt[2]); 23362306a36Sopenharmony_ci stats->wep_icv_error[3] = 23462306a36Sopenharmony_ci le32_to_cpu(get_log->wep_icv_err_cnt[3]); 23562306a36Sopenharmony_ci stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt); 23662306a36Sopenharmony_ci stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return 0; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci/* 24362306a36Sopenharmony_ci * This function handles the command response of set/get Tx rate 24462306a36Sopenharmony_ci * configurations. 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 24762306a36Sopenharmony_ci * and saving the following parameters in driver - 24862306a36Sopenharmony_ci * - DSSS rate bitmap 24962306a36Sopenharmony_ci * - OFDM rate bitmap 25062306a36Sopenharmony_ci * - HT MCS rate bitmaps 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * Based on the new rate bitmaps, the function re-evaluates if 25362306a36Sopenharmony_ci * auto data rate has been activated. If not, it sends another 25462306a36Sopenharmony_ci * query to the firmware to get the current Tx data rate. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_cistatic int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, 25762306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; 26062306a36Sopenharmony_ci struct mwifiex_rate_scope *rate_scope; 26162306a36Sopenharmony_ci struct mwifiex_ie_types_header *head; 26262306a36Sopenharmony_ci u16 tlv, tlv_buf_len, tlv_buf_left; 26362306a36Sopenharmony_ci u8 *tlv_buf; 26462306a36Sopenharmony_ci u32 i; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg); 26762306a36Sopenharmony_ci tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci while (tlv_buf_left >= sizeof(*head)) { 27062306a36Sopenharmony_ci head = (struct mwifiex_ie_types_header *)tlv_buf; 27162306a36Sopenharmony_ci tlv = le16_to_cpu(head->type); 27262306a36Sopenharmony_ci tlv_buf_len = le16_to_cpu(head->len); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci switch (tlv) { 27862306a36Sopenharmony_ci case TLV_TYPE_RATE_SCOPE: 27962306a36Sopenharmony_ci rate_scope = (struct mwifiex_rate_scope *) tlv_buf; 28062306a36Sopenharmony_ci priv->bitmap_rates[0] = 28162306a36Sopenharmony_ci le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); 28262306a36Sopenharmony_ci priv->bitmap_rates[1] = 28362306a36Sopenharmony_ci le16_to_cpu(rate_scope->ofdm_rate_bitmap); 28462306a36Sopenharmony_ci for (i = 0; 28562306a36Sopenharmony_ci i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); 28662306a36Sopenharmony_ci i++) 28762306a36Sopenharmony_ci priv->bitmap_rates[2 + i] = 28862306a36Sopenharmony_ci le16_to_cpu(rate_scope-> 28962306a36Sopenharmony_ci ht_mcs_rate_bitmap[i]); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { 29262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rate_scope-> 29362306a36Sopenharmony_ci vht_mcs_rate_bitmap); 29462306a36Sopenharmony_ci i++) 29562306a36Sopenharmony_ci priv->bitmap_rates[10 + i] = 29662306a36Sopenharmony_ci le16_to_cpu(rate_scope-> 29762306a36Sopenharmony_ci vht_mcs_rate_bitmap[i]); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci /* Add RATE_DROP tlv here */ 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci tlv_buf += (sizeof(*head) + tlv_buf_len); 30462306a36Sopenharmony_ci tlv_buf_left -= (sizeof(*head) + tlv_buf_len); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (priv->is_data_rate_auto) 31062306a36Sopenharmony_ci priv->data_rate = 0; 31162306a36Sopenharmony_ci else 31262306a36Sopenharmony_ci return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, 31362306a36Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, NULL, false); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/* 31962306a36Sopenharmony_ci * This function handles the command response of get Tx power level. 32062306a36Sopenharmony_ci * 32162306a36Sopenharmony_ci * Handling includes saving the maximum and minimum Tx power levels 32262306a36Sopenharmony_ci * in driver, as well as sending the values to user. 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_cistatic int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci int length, max_power = -1, min_power = -1; 32762306a36Sopenharmony_ci struct mwifiex_types_power_group *pg_tlv_hdr; 32862306a36Sopenharmony_ci struct mwifiex_power_group *pg; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci if (!data_buf) 33162306a36Sopenharmony_ci return -1; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf); 33462306a36Sopenharmony_ci pg = (struct mwifiex_power_group *) 33562306a36Sopenharmony_ci ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group)); 33662306a36Sopenharmony_ci length = le16_to_cpu(pg_tlv_hdr->length); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* At least one structure required to update power */ 33962306a36Sopenharmony_ci if (length < sizeof(struct mwifiex_power_group)) 34062306a36Sopenharmony_ci return 0; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci max_power = pg->power_max; 34362306a36Sopenharmony_ci min_power = pg->power_min; 34462306a36Sopenharmony_ci length -= sizeof(struct mwifiex_power_group); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci while (length >= sizeof(struct mwifiex_power_group)) { 34762306a36Sopenharmony_ci pg++; 34862306a36Sopenharmony_ci if (max_power < pg->power_max) 34962306a36Sopenharmony_ci max_power = pg->power_max; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (min_power > pg->power_min) 35262306a36Sopenharmony_ci min_power = pg->power_min; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci length -= sizeof(struct mwifiex_power_group); 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci priv->min_tx_power_level = (u8) min_power; 35762306a36Sopenharmony_ci priv->max_tx_power_level = (u8) max_power; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return 0; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci/* 36362306a36Sopenharmony_ci * This function handles the command response of set/get Tx power 36462306a36Sopenharmony_ci * configurations. 36562306a36Sopenharmony_ci * 36662306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 36762306a36Sopenharmony_ci * and saving the current Tx power level in driver. 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_cistatic int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, 37062306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 37362306a36Sopenharmony_ci struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; 37462306a36Sopenharmony_ci struct mwifiex_types_power_group *pg_tlv_hdr; 37562306a36Sopenharmony_ci struct mwifiex_power_group *pg; 37662306a36Sopenharmony_ci u16 action = le16_to_cpu(txp_cfg->action); 37762306a36Sopenharmony_ci u16 tlv_buf_left; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci pg_tlv_hdr = (struct mwifiex_types_power_group *) 38062306a36Sopenharmony_ci ((u8 *)txp_cfg + 38162306a36Sopenharmony_ci sizeof(struct host_cmd_ds_txpwr_cfg)); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci pg = (struct mwifiex_power_group *) 38462306a36Sopenharmony_ci ((u8 *)pg_tlv_hdr + 38562306a36Sopenharmony_ci sizeof(struct mwifiex_types_power_group)); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); 38862306a36Sopenharmony_ci if (tlv_buf_left < 38962306a36Sopenharmony_ci le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci switch (action) { 39362306a36Sopenharmony_ci case HostCmd_ACT_GEN_GET: 39462306a36Sopenharmony_ci if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) 39562306a36Sopenharmony_ci mwifiex_get_power_level(priv, pg_tlv_hdr); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci priv->tx_power_level = (u16) pg->power_min; 39862306a36Sopenharmony_ci break; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci case HostCmd_ACT_GEN_SET: 40162306a36Sopenharmony_ci if (!le32_to_cpu(txp_cfg->mode)) 40262306a36Sopenharmony_ci break; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (pg->power_max == pg->power_min) 40562306a36Sopenharmony_ci priv->tx_power_level = (u16) pg->power_min; 40662306a36Sopenharmony_ci break; 40762306a36Sopenharmony_ci default: 40862306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 40962306a36Sopenharmony_ci "CMD_RESP: unknown cmd action %d\n", 41062306a36Sopenharmony_ci action); 41162306a36Sopenharmony_ci return 0; 41262306a36Sopenharmony_ci } 41362306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 41462306a36Sopenharmony_ci "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", 41562306a36Sopenharmony_ci priv->tx_power_level, priv->max_tx_power_level, 41662306a36Sopenharmony_ci priv->min_tx_power_level); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci/* 42262306a36Sopenharmony_ci * This function handles the command response of get RF Tx power. 42362306a36Sopenharmony_ci */ 42462306a36Sopenharmony_cistatic int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv, 42562306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp; 42862306a36Sopenharmony_ci u16 action = le16_to_cpu(txp->action); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci priv->tx_power_level = le16_to_cpu(txp->cur_level); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (action == HostCmd_ACT_GEN_GET) { 43362306a36Sopenharmony_ci priv->max_tx_power_level = txp->max_power; 43462306a36Sopenharmony_ci priv->min_tx_power_level = txp->min_power; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 43862306a36Sopenharmony_ci "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n", 43962306a36Sopenharmony_ci priv->tx_power_level, priv->max_tx_power_level, 44062306a36Sopenharmony_ci priv->min_tx_power_level); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return 0; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci/* 44662306a36Sopenharmony_ci * This function handles the command response of set rf antenna 44762306a36Sopenharmony_ci */ 44862306a36Sopenharmony_cistatic int mwifiex_ret_rf_antenna(struct mwifiex_private *priv, 44962306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo; 45262306a36Sopenharmony_ci struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso; 45362306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) { 45662306a36Sopenharmony_ci priv->tx_ant = le16_to_cpu(ant_mimo->tx_ant_mode); 45762306a36Sopenharmony_ci priv->rx_ant = le16_to_cpu(ant_mimo->rx_ant_mode); 45862306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 45962306a36Sopenharmony_ci "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t" 46062306a36Sopenharmony_ci "Rx action = 0x%x, Rx Mode = 0x%04x\n", 46162306a36Sopenharmony_ci le16_to_cpu(ant_mimo->action_tx), 46262306a36Sopenharmony_ci le16_to_cpu(ant_mimo->tx_ant_mode), 46362306a36Sopenharmony_ci le16_to_cpu(ant_mimo->action_rx), 46462306a36Sopenharmony_ci le16_to_cpu(ant_mimo->rx_ant_mode)); 46562306a36Sopenharmony_ci } else { 46662306a36Sopenharmony_ci priv->tx_ant = le16_to_cpu(ant_siso->ant_mode); 46762306a36Sopenharmony_ci priv->rx_ant = le16_to_cpu(ant_siso->ant_mode); 46862306a36Sopenharmony_ci mwifiex_dbg(adapter, INFO, 46962306a36Sopenharmony_ci "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", 47062306a36Sopenharmony_ci le16_to_cpu(ant_siso->action), 47162306a36Sopenharmony_ci le16_to_cpu(ant_siso->ant_mode)); 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci return 0; 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci/* 47762306a36Sopenharmony_ci * This function handles the command response of set/get MAC address. 47862306a36Sopenharmony_ci * 47962306a36Sopenharmony_ci * Handling includes saving the MAC address in driver. 48062306a36Sopenharmony_ci */ 48162306a36Sopenharmony_cistatic int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, 48262306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = 48562306a36Sopenharmony_ci &resp->params.mac_addr; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 49062306a36Sopenharmony_ci "info: set mac address: %pM\n", priv->curr_addr); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* 49662306a36Sopenharmony_ci * This function handles the command response of set/get MAC multicast 49762306a36Sopenharmony_ci * address. 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_cistatic int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, 50062306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 50162306a36Sopenharmony_ci{ 50262306a36Sopenharmony_ci return 0; 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci/* 50662306a36Sopenharmony_ci * This function handles the command response of get Tx rate query. 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * Handling includes changing the header fields into CPU format 50962306a36Sopenharmony_ci * and saving the Tx rate and HT information parameters in driver. 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * Both rate configuration and current data rate can be retrieved 51262306a36Sopenharmony_ci * with this request. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_cistatic int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, 51562306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci priv->tx_rate = resp->params.tx_rate.tx_rate; 51862306a36Sopenharmony_ci priv->tx_htinfo = resp->params.tx_rate.ht_info; 51962306a36Sopenharmony_ci if (!priv->is_data_rate_auto) 52062306a36Sopenharmony_ci priv->data_rate = 52162306a36Sopenharmony_ci mwifiex_index_to_data_rate(priv, priv->tx_rate, 52262306a36Sopenharmony_ci priv->tx_htinfo); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci return 0; 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci/* 52862306a36Sopenharmony_ci * This function handles the command response of a deauthenticate 52962306a36Sopenharmony_ci * command. 53062306a36Sopenharmony_ci * 53162306a36Sopenharmony_ci * If the deauthenticated MAC matches the current BSS MAC, the connection 53262306a36Sopenharmony_ci * state is reset. 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_cistatic int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, 53562306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci adapter->dbg.num_cmd_deauth++; 54062306a36Sopenharmony_ci if (!memcmp(resp->params.deauth.mac_addr, 54162306a36Sopenharmony_ci &priv->curr_bss_params.bss_descriptor.mac_address, 54262306a36Sopenharmony_ci sizeof(resp->params.deauth.mac_addr))) 54362306a36Sopenharmony_ci mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING, 54462306a36Sopenharmony_ci false); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci return 0; 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/* 55062306a36Sopenharmony_ci * This function handles the command response of ad-hoc stop. 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * The function resets the connection state in driver. 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_cistatic int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, 55562306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING, false); 55862306a36Sopenharmony_ci return 0; 55962306a36Sopenharmony_ci} 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci/* 56262306a36Sopenharmony_ci * This function handles the command response of set/get v1 key material. 56362306a36Sopenharmony_ci * 56462306a36Sopenharmony_ci * Handling includes updating the driver parameters to reflect the 56562306a36Sopenharmony_ci * changes. 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_cistatic int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv, 56862306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci struct host_cmd_ds_802_11_key_material *key = 57162306a36Sopenharmony_ci &resp->params.key_material; 57262306a36Sopenharmony_ci int len; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci len = le16_to_cpu(key->key_param_set.key_len); 57562306a36Sopenharmony_ci if (len > sizeof(key->key_param_set.key)) 57662306a36Sopenharmony_ci return -EINVAL; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { 57962306a36Sopenharmony_ci if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { 58062306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 58162306a36Sopenharmony_ci "info: key: GTK is set\n"); 58262306a36Sopenharmony_ci priv->wpa_is_gtk_set = true; 58362306a36Sopenharmony_ci priv->scan_block = false; 58462306a36Sopenharmony_ci priv->port_open = true; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci memset(priv->aes_key.key_param_set.key, 0, 58962306a36Sopenharmony_ci sizeof(key->key_param_set.key)); 59062306a36Sopenharmony_ci priv->aes_key.key_param_set.key_len = cpu_to_le16(len); 59162306a36Sopenharmony_ci memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, len); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci return 0; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci/* 59762306a36Sopenharmony_ci * This function handles the command response of set/get v2 key material. 59862306a36Sopenharmony_ci * 59962306a36Sopenharmony_ci * Handling includes updating the driver parameters to reflect the 60062306a36Sopenharmony_ci * changes. 60162306a36Sopenharmony_ci */ 60262306a36Sopenharmony_cistatic int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, 60362306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct host_cmd_ds_802_11_key_material_v2 *key_v2; 60662306a36Sopenharmony_ci int len; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci key_v2 = &resp->params.key_material_v2; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len); 61162306a36Sopenharmony_ci if (len > sizeof(key_v2->key_param_set.key_params.aes.key)) 61262306a36Sopenharmony_ci return -EINVAL; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) { 61562306a36Sopenharmony_ci if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) { 61662306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n"); 61762306a36Sopenharmony_ci priv->wpa_is_gtk_set = true; 61862306a36Sopenharmony_ci priv->scan_block = false; 61962306a36Sopenharmony_ci priv->port_open = true; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES) 62462306a36Sopenharmony_ci return 0; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0, 62762306a36Sopenharmony_ci sizeof(key_v2->key_param_set.key_params.aes.key)); 62862306a36Sopenharmony_ci priv->aes_key_v2.key_param_set.key_params.aes.key_len = 62962306a36Sopenharmony_ci cpu_to_le16(len); 63062306a36Sopenharmony_ci memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key, 63162306a36Sopenharmony_ci key_v2->key_param_set.key_params.aes.key, len); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci return 0; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci/* Wrapper function for processing response of key material command */ 63762306a36Sopenharmony_cistatic int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, 63862306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) 64162306a36Sopenharmony_ci return mwifiex_ret_802_11_key_material_v2(priv, resp); 64262306a36Sopenharmony_ci else 64362306a36Sopenharmony_ci return mwifiex_ret_802_11_key_material_v1(priv, resp); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci/* 64762306a36Sopenharmony_ci * This function handles the command response of get 11d domain information. 64862306a36Sopenharmony_ci */ 64962306a36Sopenharmony_cistatic int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, 65062306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = 65362306a36Sopenharmony_ci &resp->params.domain_info_resp; 65462306a36Sopenharmony_ci struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; 65562306a36Sopenharmony_ci u16 action = le16_to_cpu(domain_info->action); 65662306a36Sopenharmony_ci u8 no_of_triplet; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) 65962306a36Sopenharmony_ci - IEEE80211_COUNTRY_STRING_LEN) 66062306a36Sopenharmony_ci / sizeof(struct ieee80211_country_ie_triplet)); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 66362306a36Sopenharmony_ci "info: 11D Domain Info Resp: no_of_triplet=%d\n", 66462306a36Sopenharmony_ci no_of_triplet); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { 66762306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, FATAL, 66862306a36Sopenharmony_ci "11D: invalid number of triplets %d returned\n", 66962306a36Sopenharmony_ci no_of_triplet); 67062306a36Sopenharmony_ci return -1; 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci switch (action) { 67462306a36Sopenharmony_ci case HostCmd_ACT_GEN_SET: /* Proc Set Action */ 67562306a36Sopenharmony_ci break; 67662306a36Sopenharmony_ci case HostCmd_ACT_GEN_GET: 67762306a36Sopenharmony_ci break; 67862306a36Sopenharmony_ci default: 67962306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 68062306a36Sopenharmony_ci "11D: invalid action:%d\n", domain_info->action); 68162306a36Sopenharmony_ci return -1; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return 0; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci/* 68862306a36Sopenharmony_ci * This function handles the command response of get extended version. 68962306a36Sopenharmony_ci * 69062306a36Sopenharmony_ci * Handling includes forming the extended version string and sending it 69162306a36Sopenharmony_ci * to application. 69262306a36Sopenharmony_ci */ 69362306a36Sopenharmony_cistatic int mwifiex_ret_ver_ext(struct mwifiex_private *priv, 69462306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 69562306a36Sopenharmony_ci struct host_cmd_ds_version_ext *version_ext) 69662306a36Sopenharmony_ci{ 69762306a36Sopenharmony_ci struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (test_and_clear_bit(MWIFIEX_IS_REQUESTING_FW_VEREXT, &priv->adapter->work_flags)) { 70062306a36Sopenharmony_ci if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)", 70162306a36Sopenharmony_ci MWIFIEX_VERSION_STR_LENGTH) == 0) { 70262306a36Sopenharmony_ci struct mwifiex_ds_auto_ds auto_ds = { 70362306a36Sopenharmony_ci .auto_ds = DEEP_SLEEP_OFF, 70462306a36Sopenharmony_ci }; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 70762306a36Sopenharmony_ci "Bad HW revision detected, disabling deep sleep\n"); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, 71062306a36Sopenharmony_ci DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false)) { 71162306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 71262306a36Sopenharmony_ci "Disabling deep sleep failed.\n"); 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return 0; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (version_ext) { 72062306a36Sopenharmony_ci version_ext->version_str_sel = ver_ext->version_str_sel; 72162306a36Sopenharmony_ci memcpy(version_ext->version_str, ver_ext->version_str, 72262306a36Sopenharmony_ci MWIFIEX_VERSION_STR_LENGTH); 72362306a36Sopenharmony_ci memcpy(priv->version_str, ver_ext->version_str, 72462306a36Sopenharmony_ci MWIFIEX_VERSION_STR_LENGTH); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* Ensure the version string from the firmware is 0-terminated */ 72762306a36Sopenharmony_ci priv->version_str[MWIFIEX_VERSION_STR_LENGTH - 1] = '\0'; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci return 0; 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci/* 73362306a36Sopenharmony_ci * This function handles the command response of remain on channel. 73462306a36Sopenharmony_ci */ 73562306a36Sopenharmony_cistatic int 73662306a36Sopenharmony_cimwifiex_ret_remain_on_chan(struct mwifiex_private *priv, 73762306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 73862306a36Sopenharmony_ci struct host_cmd_ds_remain_on_chan *roc_cfg) 73962306a36Sopenharmony_ci{ 74062306a36Sopenharmony_ci struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (roc_cfg) 74362306a36Sopenharmony_ci memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci return 0; 74662306a36Sopenharmony_ci} 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci/* 74962306a36Sopenharmony_ci * This function handles the command response of P2P mode cfg. 75062306a36Sopenharmony_ci */ 75162306a36Sopenharmony_cistatic int 75262306a36Sopenharmony_cimwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv, 75362306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 75462306a36Sopenharmony_ci void *data_buf) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci if (data_buf) 75962306a36Sopenharmony_ci put_unaligned_le16(le16_to_cpu(mode_cfg->mode), data_buf); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return 0; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* This function handles the command response of mem_access command 76562306a36Sopenharmony_ci */ 76662306a36Sopenharmony_cistatic int 76762306a36Sopenharmony_cimwifiex_ret_mem_access(struct mwifiex_private *priv, 76862306a36Sopenharmony_ci struct host_cmd_ds_command *resp, void *pioctl_buf) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci priv->mem_rw.addr = le32_to_cpu(mem->addr); 77362306a36Sopenharmony_ci priv->mem_rw.value = le32_to_cpu(mem->value); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci return 0; 77662306a36Sopenharmony_ci} 77762306a36Sopenharmony_ci/* 77862306a36Sopenharmony_ci * This function handles the command response of register access. 77962306a36Sopenharmony_ci * 78062306a36Sopenharmony_ci * The register value and offset are returned to the user. For EEPROM 78162306a36Sopenharmony_ci * access, the byte count is also returned. 78262306a36Sopenharmony_ci */ 78362306a36Sopenharmony_cistatic int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, 78462306a36Sopenharmony_ci void *data_buf) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci struct mwifiex_ds_reg_rw *reg_rw; 78762306a36Sopenharmony_ci struct mwifiex_ds_read_eeprom *eeprom; 78862306a36Sopenharmony_ci union reg { 78962306a36Sopenharmony_ci struct host_cmd_ds_mac_reg_access *mac; 79062306a36Sopenharmony_ci struct host_cmd_ds_bbp_reg_access *bbp; 79162306a36Sopenharmony_ci struct host_cmd_ds_rf_reg_access *rf; 79262306a36Sopenharmony_ci struct host_cmd_ds_pmic_reg_access *pmic; 79362306a36Sopenharmony_ci struct host_cmd_ds_802_11_eeprom_access *eeprom; 79462306a36Sopenharmony_ci } r; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci if (!data_buf) 79762306a36Sopenharmony_ci return 0; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci reg_rw = data_buf; 80062306a36Sopenharmony_ci eeprom = data_buf; 80162306a36Sopenharmony_ci switch (type) { 80262306a36Sopenharmony_ci case HostCmd_CMD_MAC_REG_ACCESS: 80362306a36Sopenharmony_ci r.mac = &resp->params.mac_reg; 80462306a36Sopenharmony_ci reg_rw->offset = (u32) le16_to_cpu(r.mac->offset); 80562306a36Sopenharmony_ci reg_rw->value = le32_to_cpu(r.mac->value); 80662306a36Sopenharmony_ci break; 80762306a36Sopenharmony_ci case HostCmd_CMD_BBP_REG_ACCESS: 80862306a36Sopenharmony_ci r.bbp = &resp->params.bbp_reg; 80962306a36Sopenharmony_ci reg_rw->offset = (u32) le16_to_cpu(r.bbp->offset); 81062306a36Sopenharmony_ci reg_rw->value = (u32) r.bbp->value; 81162306a36Sopenharmony_ci break; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci case HostCmd_CMD_RF_REG_ACCESS: 81462306a36Sopenharmony_ci r.rf = &resp->params.rf_reg; 81562306a36Sopenharmony_ci reg_rw->offset = (u32) le16_to_cpu(r.rf->offset); 81662306a36Sopenharmony_ci reg_rw->value = (u32) r.bbp->value; 81762306a36Sopenharmony_ci break; 81862306a36Sopenharmony_ci case HostCmd_CMD_PMIC_REG_ACCESS: 81962306a36Sopenharmony_ci r.pmic = &resp->params.pmic_reg; 82062306a36Sopenharmony_ci reg_rw->offset = (u32) le16_to_cpu(r.pmic->offset); 82162306a36Sopenharmony_ci reg_rw->value = (u32) r.pmic->value; 82262306a36Sopenharmony_ci break; 82362306a36Sopenharmony_ci case HostCmd_CMD_CAU_REG_ACCESS: 82462306a36Sopenharmony_ci r.rf = &resp->params.rf_reg; 82562306a36Sopenharmony_ci reg_rw->offset = (u32) le16_to_cpu(r.rf->offset); 82662306a36Sopenharmony_ci reg_rw->value = (u32) r.rf->value; 82762306a36Sopenharmony_ci break; 82862306a36Sopenharmony_ci case HostCmd_CMD_802_11_EEPROM_ACCESS: 82962306a36Sopenharmony_ci r.eeprom = &resp->params.eeprom; 83062306a36Sopenharmony_ci pr_debug("info: EEPROM read len=%x\n", 83162306a36Sopenharmony_ci le16_to_cpu(r.eeprom->byte_count)); 83262306a36Sopenharmony_ci if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) { 83362306a36Sopenharmony_ci eeprom->byte_count = 0; 83462306a36Sopenharmony_ci pr_debug("info: EEPROM read length is too big\n"); 83562306a36Sopenharmony_ci return -1; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci eeprom->offset = le16_to_cpu(r.eeprom->offset); 83862306a36Sopenharmony_ci eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count); 83962306a36Sopenharmony_ci if (eeprom->byte_count > 0) 84062306a36Sopenharmony_ci memcpy(&eeprom->value, &r.eeprom->value, 84162306a36Sopenharmony_ci min((u16)MAX_EEPROM_DATA, eeprom->byte_count)); 84262306a36Sopenharmony_ci break; 84362306a36Sopenharmony_ci default: 84462306a36Sopenharmony_ci return -1; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci return 0; 84762306a36Sopenharmony_ci} 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci/* 85062306a36Sopenharmony_ci * This function handles the command response of get IBSS coalescing status. 85162306a36Sopenharmony_ci * 85262306a36Sopenharmony_ci * If the received BSSID is different than the current one, the current BSSID, 85362306a36Sopenharmony_ci * beacon interval, ATIM window and ERP information are updated, along with 85462306a36Sopenharmony_ci * changing the ad-hoc state accordingly. 85562306a36Sopenharmony_ci */ 85662306a36Sopenharmony_cistatic int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, 85762306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = 86062306a36Sopenharmony_ci &(resp->params.ibss_coalescing); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) 86362306a36Sopenharmony_ci return 0; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, INFO, 86662306a36Sopenharmony_ci "info: new BSSID %pM\n", ibss_coal_resp->bssid); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci /* If rsp has NULL BSSID, Just return..... No Action */ 86962306a36Sopenharmony_ci if (is_zero_ether_addr(ibss_coal_resp->bssid)) { 87062306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n"); 87162306a36Sopenharmony_ci return 0; 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci /* If BSSID is diff, modify current BSS parameters */ 87562306a36Sopenharmony_ci if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) { 87662306a36Sopenharmony_ci /* BSSID */ 87762306a36Sopenharmony_ci memcpy(priv->curr_bss_params.bss_descriptor.mac_address, 87862306a36Sopenharmony_ci ibss_coal_resp->bssid, ETH_ALEN); 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci /* Beacon Interval */ 88162306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.beacon_period 88262306a36Sopenharmony_ci = le16_to_cpu(ibss_coal_resp->beacon_interval); 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci /* ERP Information */ 88562306a36Sopenharmony_ci priv->curr_bss_params.bss_descriptor.erp_flags = 88662306a36Sopenharmony_ci (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci priv->adhoc_state = ADHOC_COALESCED; 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci return 0; 89262306a36Sopenharmony_ci} 89362306a36Sopenharmony_cistatic int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, 89462306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper; 89762306a36Sopenharmony_ci u16 reason = le16_to_cpu(cmd_tdls_oper->reason); 89862306a36Sopenharmony_ci u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action); 89962306a36Sopenharmony_ci struct mwifiex_sta_node *node = 90062306a36Sopenharmony_ci mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci switch (action) { 90362306a36Sopenharmony_ci case ACT_TDLS_DELETE: 90462306a36Sopenharmony_ci if (reason) { 90562306a36Sopenharmony_ci if (!node || reason == TDLS_ERR_LINK_NONEXISTENT) 90662306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 90762306a36Sopenharmony_ci "TDLS link delete for %pM failed: reason %d\n", 90862306a36Sopenharmony_ci cmd_tdls_oper->peer_mac, reason); 90962306a36Sopenharmony_ci else 91062306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 91162306a36Sopenharmony_ci "TDLS link delete for %pM failed: reason %d\n", 91262306a36Sopenharmony_ci cmd_tdls_oper->peer_mac, reason); 91362306a36Sopenharmony_ci } else { 91462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 91562306a36Sopenharmony_ci "TDLS link delete for %pM successful\n", 91662306a36Sopenharmony_ci cmd_tdls_oper->peer_mac); 91762306a36Sopenharmony_ci } 91862306a36Sopenharmony_ci break; 91962306a36Sopenharmony_ci case ACT_TDLS_CREATE: 92062306a36Sopenharmony_ci if (reason) { 92162306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 92262306a36Sopenharmony_ci "TDLS link creation for %pM failed: reason %d", 92362306a36Sopenharmony_ci cmd_tdls_oper->peer_mac, reason); 92462306a36Sopenharmony_ci if (node && reason != TDLS_ERR_LINK_EXISTS) 92562306a36Sopenharmony_ci node->tdls_status = TDLS_SETUP_FAILURE; 92662306a36Sopenharmony_ci } else { 92762306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 92862306a36Sopenharmony_ci "TDLS link creation for %pM successful", 92962306a36Sopenharmony_ci cmd_tdls_oper->peer_mac); 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci case ACT_TDLS_CONFIG: 93362306a36Sopenharmony_ci if (reason) { 93462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 93562306a36Sopenharmony_ci "TDLS link config for %pM failed, reason %d\n", 93662306a36Sopenharmony_ci cmd_tdls_oper->peer_mac, reason); 93762306a36Sopenharmony_ci if (node) 93862306a36Sopenharmony_ci node->tdls_status = TDLS_SETUP_FAILURE; 93962306a36Sopenharmony_ci } else { 94062306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, MSG, 94162306a36Sopenharmony_ci "TDLS link config for %pM successful\n", 94262306a36Sopenharmony_ci cmd_tdls_oper->peer_mac); 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci break; 94562306a36Sopenharmony_ci default: 94662306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 94762306a36Sopenharmony_ci "Unknown TDLS command action response %d", action); 94862306a36Sopenharmony_ci return -1; 94962306a36Sopenharmony_ci } 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci return 0; 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci/* 95462306a36Sopenharmony_ci * This function handles the command response for subscribe event command. 95562306a36Sopenharmony_ci */ 95662306a36Sopenharmony_cistatic int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, 95762306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = 96062306a36Sopenharmony_ci &resp->params.subsc_evt; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci /* For every subscribe event command (Get/Set/Clear), FW reports the 96362306a36Sopenharmony_ci * current set of subscribed events*/ 96462306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, EVENT, 96562306a36Sopenharmony_ci "Bitmap of currently subscribed events: %16x\n", 96662306a36Sopenharmony_ci le16_to_cpu(cmd_sub_event->events)); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci return 0; 96962306a36Sopenharmony_ci} 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_cistatic int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv, 97262306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci struct host_cmd_ds_sta_list *sta_list = 97562306a36Sopenharmony_ci &resp->params.sta_list; 97662306a36Sopenharmony_ci struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv; 97762306a36Sopenharmony_ci int i; 97862306a36Sopenharmony_ci struct mwifiex_sta_node *sta_node; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci for (i = 0; i < (le16_to_cpu(sta_list->sta_count)); i++) { 98162306a36Sopenharmony_ci sta_node = mwifiex_get_sta_entry(priv, sta_info->mac); 98262306a36Sopenharmony_ci if (unlikely(!sta_node)) 98362306a36Sopenharmony_ci continue; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci sta_node->stats.rssi = sta_info->rssi; 98662306a36Sopenharmony_ci sta_info++; 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci return 0; 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci/* This function handles the command response of set_cfg_data */ 99362306a36Sopenharmony_cistatic int mwifiex_ret_cfg_data(struct mwifiex_private *priv, 99462306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 99562306a36Sopenharmony_ci{ 99662306a36Sopenharmony_ci if (resp->result != HostCmd_RESULT_OK) { 99762306a36Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n"); 99862306a36Sopenharmony_ci return -1; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci return 0; 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci/** This Function handles the command response of sdio rx aggr */ 100562306a36Sopenharmony_cistatic int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, 100662306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 100962306a36Sopenharmony_ci struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = 101062306a36Sopenharmony_ci &resp->params.sdio_rx_aggr_cfg; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci adapter->sdio_rx_aggr_enable = cfg->enable; 101362306a36Sopenharmony_ci adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci return 0; 101662306a36Sopenharmony_ci} 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_cistatic int mwifiex_ret_robust_coex(struct mwifiex_private *priv, 101962306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 102062306a36Sopenharmony_ci bool *is_timeshare) 102162306a36Sopenharmony_ci{ 102262306a36Sopenharmony_ci struct host_cmd_ds_robust_coex *coex = &resp->params.coex; 102362306a36Sopenharmony_ci struct mwifiex_ie_types_robust_coex *coex_tlv; 102462306a36Sopenharmony_ci u16 action = le16_to_cpu(coex->action); 102562306a36Sopenharmony_ci u32 mode; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci coex_tlv = (struct mwifiex_ie_types_robust_coex 102862306a36Sopenharmony_ci *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); 102962306a36Sopenharmony_ci if (action == HostCmd_ACT_GEN_GET) { 103062306a36Sopenharmony_ci mode = le32_to_cpu(coex_tlv->mode); 103162306a36Sopenharmony_ci if (mode == MWIFIEX_COEX_MODE_TIMESHARE) 103262306a36Sopenharmony_ci *is_timeshare = true; 103362306a36Sopenharmony_ci else 103462306a36Sopenharmony_ci *is_timeshare = false; 103562306a36Sopenharmony_ci } 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci return 0; 103862306a36Sopenharmony_ci} 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_cistatic struct ieee80211_regdomain * 104162306a36Sopenharmony_cimwifiex_create_custom_regdomain(struct mwifiex_private *priv, 104262306a36Sopenharmony_ci u8 *buf, u16 buf_len) 104362306a36Sopenharmony_ci{ 104462306a36Sopenharmony_ci u16 num_chan = buf_len / 2; 104562306a36Sopenharmony_ci struct ieee80211_regdomain *regd; 104662306a36Sopenharmony_ci struct ieee80211_reg_rule *rule; 104762306a36Sopenharmony_ci bool new_rule; 104862306a36Sopenharmony_ci int idx, freq, prev_freq = 0; 104962306a36Sopenharmony_ci u32 bw, prev_bw = 0; 105062306a36Sopenharmony_ci u8 chflags, prev_chflags = 0, valid_rules = 0; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES)) 105362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci regd = kzalloc(struct_size(regd, reg_rules, num_chan), GFP_KERNEL); 105662306a36Sopenharmony_ci if (!regd) 105762306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci for (idx = 0; idx < num_chan; idx++) { 106062306a36Sopenharmony_ci u8 chan; 106162306a36Sopenharmony_ci enum nl80211_band band; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci chan = *buf++; 106462306a36Sopenharmony_ci if (!chan) { 106562306a36Sopenharmony_ci kfree(regd); 106662306a36Sopenharmony_ci return NULL; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci chflags = *buf++; 106962306a36Sopenharmony_ci band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ; 107062306a36Sopenharmony_ci freq = ieee80211_channel_to_frequency(chan, band); 107162306a36Sopenharmony_ci new_rule = false; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci if (chflags & MWIFIEX_CHANNEL_DISABLED) 107462306a36Sopenharmony_ci continue; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (band == NL80211_BAND_5GHZ) { 107762306a36Sopenharmony_ci if (!(chflags & MWIFIEX_CHANNEL_NOHT80)) 107862306a36Sopenharmony_ci bw = MHZ_TO_KHZ(80); 107962306a36Sopenharmony_ci else if (!(chflags & MWIFIEX_CHANNEL_NOHT40)) 108062306a36Sopenharmony_ci bw = MHZ_TO_KHZ(40); 108162306a36Sopenharmony_ci else 108262306a36Sopenharmony_ci bw = MHZ_TO_KHZ(20); 108362306a36Sopenharmony_ci } else { 108462306a36Sopenharmony_ci if (!(chflags & MWIFIEX_CHANNEL_NOHT40)) 108562306a36Sopenharmony_ci bw = MHZ_TO_KHZ(40); 108662306a36Sopenharmony_ci else 108762306a36Sopenharmony_ci bw = MHZ_TO_KHZ(20); 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci if (idx == 0 || prev_chflags != chflags || prev_bw != bw || 109162306a36Sopenharmony_ci freq - prev_freq > 20) { 109262306a36Sopenharmony_ci valid_rules++; 109362306a36Sopenharmony_ci new_rule = true; 109462306a36Sopenharmony_ci } 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci rule = ®d->reg_rules[valid_rules - 1]; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10); 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci prev_chflags = chflags; 110162306a36Sopenharmony_ci prev_freq = freq; 110262306a36Sopenharmony_ci prev_bw = bw; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci if (!new_rule) 110562306a36Sopenharmony_ci continue; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10); 110862306a36Sopenharmony_ci rule->power_rule.max_eirp = DBM_TO_MBM(19); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci if (chflags & MWIFIEX_CHANNEL_PASSIVE) 111162306a36Sopenharmony_ci rule->flags = NL80211_RRF_NO_IR; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci if (chflags & MWIFIEX_CHANNEL_DFS) 111462306a36Sopenharmony_ci rule->flags = NL80211_RRF_DFS; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci rule->freq_range.max_bandwidth_khz = bw; 111762306a36Sopenharmony_ci } 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci regd->n_reg_rules = valid_rules; 112062306a36Sopenharmony_ci regd->alpha2[0] = '9'; 112162306a36Sopenharmony_ci regd->alpha2[1] = '9'; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci return regd; 112462306a36Sopenharmony_ci} 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_cistatic int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv, 112762306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 112862306a36Sopenharmony_ci{ 112962306a36Sopenharmony_ci struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg; 113062306a36Sopenharmony_ci u16 action = le16_to_cpu(reg->action); 113162306a36Sopenharmony_ci u16 tlv, tlv_buf_len, tlv_buf_left; 113262306a36Sopenharmony_ci struct mwifiex_ie_types_header *head; 113362306a36Sopenharmony_ci struct ieee80211_regdomain *regd; 113462306a36Sopenharmony_ci u8 *tlv_buf; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci if (action != HostCmd_ACT_GEN_GET) 113762306a36Sopenharmony_ci return 0; 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci tlv_buf = (u8 *)reg + sizeof(*reg); 114062306a36Sopenharmony_ci tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg); 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci while (tlv_buf_left >= sizeof(*head)) { 114362306a36Sopenharmony_ci head = (struct mwifiex_ie_types_header *)tlv_buf; 114462306a36Sopenharmony_ci tlv = le16_to_cpu(head->type); 114562306a36Sopenharmony_ci tlv_buf_len = le16_to_cpu(head->len); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) 114862306a36Sopenharmony_ci break; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci switch (tlv) { 115162306a36Sopenharmony_ci case TLV_TYPE_CHAN_ATTR_CFG: 115262306a36Sopenharmony_ci mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:", 115362306a36Sopenharmony_ci (u8 *)head + sizeof(*head), 115462306a36Sopenharmony_ci tlv_buf_len); 115562306a36Sopenharmony_ci regd = mwifiex_create_custom_regdomain(priv, 115662306a36Sopenharmony_ci (u8 *)head + sizeof(*head), tlv_buf_len); 115762306a36Sopenharmony_ci if (!IS_ERR(regd)) 115862306a36Sopenharmony_ci priv->adapter->regd = regd; 115962306a36Sopenharmony_ci break; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci tlv_buf += (sizeof(*head) + tlv_buf_len); 116362306a36Sopenharmony_ci tlv_buf_left -= (sizeof(*head) + tlv_buf_len); 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci return 0; 116762306a36Sopenharmony_ci} 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_cistatic int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv, 117062306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 117162306a36Sopenharmony_ci{ 117262306a36Sopenharmony_ci struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl = 117362306a36Sopenharmony_ci &resp->params.pkt_aggr_ctrl; 117462306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable); 117762306a36Sopenharmony_ci if (adapter->bus_aggr.enable) 117862306a36Sopenharmony_ci adapter->intf_hdr_len = INTF_HEADER_LEN; 117962306a36Sopenharmony_ci adapter->bus_aggr.mode = MWIFIEX_BUS_AGGR_MODE_LEN_V2; 118062306a36Sopenharmony_ci adapter->bus_aggr.tx_aggr_max_size = 118162306a36Sopenharmony_ci le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size); 118262306a36Sopenharmony_ci adapter->bus_aggr.tx_aggr_max_num = 118362306a36Sopenharmony_ci le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num); 118462306a36Sopenharmony_ci adapter->bus_aggr.tx_aggr_align = 118562306a36Sopenharmony_ci le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align); 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci return 0; 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_cistatic int mwifiex_ret_get_chan_info(struct mwifiex_private *priv, 119162306a36Sopenharmony_ci struct host_cmd_ds_command *resp, 119262306a36Sopenharmony_ci struct mwifiex_channel_band *channel_band) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg; 119562306a36Sopenharmony_ci struct host_cmd_tlv_channel_band *tlv_band_channel; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci tlv_band_channel = 119862306a36Sopenharmony_ci (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer; 119962306a36Sopenharmony_ci memcpy(&channel_band->band_config, &tlv_band_channel->band_config, 120062306a36Sopenharmony_ci sizeof(struct mwifiex_band_config)); 120162306a36Sopenharmony_ci channel_band->channel = tlv_band_channel->channel; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci return 0; 120462306a36Sopenharmony_ci} 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci/* 120762306a36Sopenharmony_ci * This function handles the command responses. 120862306a36Sopenharmony_ci * 120962306a36Sopenharmony_ci * This is a generic function, which calls command specific 121062306a36Sopenharmony_ci * response handlers based on the command ID. 121162306a36Sopenharmony_ci */ 121262306a36Sopenharmony_ciint mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, 121362306a36Sopenharmony_ci struct host_cmd_ds_command *resp) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci int ret = 0; 121662306a36Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 121762306a36Sopenharmony_ci void *data_buf = adapter->curr_cmd->data_buf; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci /* If the command is not successful, cleanup and return failure */ 122062306a36Sopenharmony_ci if (resp->result != HostCmd_RESULT_OK) { 122162306a36Sopenharmony_ci mwifiex_process_cmdresp_error(priv, resp); 122262306a36Sopenharmony_ci return -1; 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci /* Command successful, handle response */ 122562306a36Sopenharmony_ci switch (cmdresp_no) { 122662306a36Sopenharmony_ci case HostCmd_CMD_GET_HW_SPEC: 122762306a36Sopenharmony_ci ret = mwifiex_ret_get_hw_spec(priv, resp); 122862306a36Sopenharmony_ci break; 122962306a36Sopenharmony_ci case HostCmd_CMD_CFG_DATA: 123062306a36Sopenharmony_ci ret = mwifiex_ret_cfg_data(priv, resp); 123162306a36Sopenharmony_ci break; 123262306a36Sopenharmony_ci case HostCmd_CMD_MAC_CONTROL: 123362306a36Sopenharmony_ci break; 123462306a36Sopenharmony_ci case HostCmd_CMD_802_11_MAC_ADDRESS: 123562306a36Sopenharmony_ci ret = mwifiex_ret_802_11_mac_address(priv, resp); 123662306a36Sopenharmony_ci break; 123762306a36Sopenharmony_ci case HostCmd_CMD_MAC_MULTICAST_ADR: 123862306a36Sopenharmony_ci ret = mwifiex_ret_mac_multicast_adr(priv, resp); 123962306a36Sopenharmony_ci break; 124062306a36Sopenharmony_ci case HostCmd_CMD_TX_RATE_CFG: 124162306a36Sopenharmony_ci ret = mwifiex_ret_tx_rate_cfg(priv, resp); 124262306a36Sopenharmony_ci break; 124362306a36Sopenharmony_ci case HostCmd_CMD_802_11_SCAN: 124462306a36Sopenharmony_ci ret = mwifiex_ret_802_11_scan(priv, resp); 124562306a36Sopenharmony_ci adapter->curr_cmd->wait_q_enabled = false; 124662306a36Sopenharmony_ci break; 124762306a36Sopenharmony_ci case HostCmd_CMD_802_11_SCAN_EXT: 124862306a36Sopenharmony_ci ret = mwifiex_ret_802_11_scan_ext(priv, resp); 124962306a36Sopenharmony_ci adapter->curr_cmd->wait_q_enabled = false; 125062306a36Sopenharmony_ci break; 125162306a36Sopenharmony_ci case HostCmd_CMD_802_11_BG_SCAN_QUERY: 125262306a36Sopenharmony_ci ret = mwifiex_ret_802_11_scan(priv, resp); 125362306a36Sopenharmony_ci cfg80211_sched_scan_results(priv->wdev.wiphy, 0); 125462306a36Sopenharmony_ci mwifiex_dbg(adapter, CMD, 125562306a36Sopenharmony_ci "info: CMD_RESP: BG_SCAN result is ready!\n"); 125662306a36Sopenharmony_ci break; 125762306a36Sopenharmony_ci case HostCmd_CMD_802_11_BG_SCAN_CONFIG: 125862306a36Sopenharmony_ci break; 125962306a36Sopenharmony_ci case HostCmd_CMD_TXPWR_CFG: 126062306a36Sopenharmony_ci ret = mwifiex_ret_tx_power_cfg(priv, resp); 126162306a36Sopenharmony_ci break; 126262306a36Sopenharmony_ci case HostCmd_CMD_RF_TX_PWR: 126362306a36Sopenharmony_ci ret = mwifiex_ret_rf_tx_power(priv, resp); 126462306a36Sopenharmony_ci break; 126562306a36Sopenharmony_ci case HostCmd_CMD_RF_ANTENNA: 126662306a36Sopenharmony_ci ret = mwifiex_ret_rf_antenna(priv, resp); 126762306a36Sopenharmony_ci break; 126862306a36Sopenharmony_ci case HostCmd_CMD_802_11_PS_MODE_ENH: 126962306a36Sopenharmony_ci ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); 127062306a36Sopenharmony_ci break; 127162306a36Sopenharmony_ci case HostCmd_CMD_802_11_HS_CFG_ENH: 127262306a36Sopenharmony_ci ret = mwifiex_ret_802_11_hs_cfg(priv, resp); 127362306a36Sopenharmony_ci break; 127462306a36Sopenharmony_ci case HostCmd_CMD_802_11_ASSOCIATE: 127562306a36Sopenharmony_ci ret = mwifiex_ret_802_11_associate(priv, resp); 127662306a36Sopenharmony_ci break; 127762306a36Sopenharmony_ci case HostCmd_CMD_802_11_DEAUTHENTICATE: 127862306a36Sopenharmony_ci ret = mwifiex_ret_802_11_deauthenticate(priv, resp); 127962306a36Sopenharmony_ci break; 128062306a36Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_START: 128162306a36Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_JOIN: 128262306a36Sopenharmony_ci ret = mwifiex_ret_802_11_ad_hoc(priv, resp); 128362306a36Sopenharmony_ci break; 128462306a36Sopenharmony_ci case HostCmd_CMD_802_11_AD_HOC_STOP: 128562306a36Sopenharmony_ci ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); 128662306a36Sopenharmony_ci break; 128762306a36Sopenharmony_ci case HostCmd_CMD_802_11_GET_LOG: 128862306a36Sopenharmony_ci ret = mwifiex_ret_get_log(priv, resp, data_buf); 128962306a36Sopenharmony_ci break; 129062306a36Sopenharmony_ci case HostCmd_CMD_RSSI_INFO: 129162306a36Sopenharmony_ci ret = mwifiex_ret_802_11_rssi_info(priv, resp); 129262306a36Sopenharmony_ci break; 129362306a36Sopenharmony_ci case HostCmd_CMD_802_11_SNMP_MIB: 129462306a36Sopenharmony_ci ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); 129562306a36Sopenharmony_ci break; 129662306a36Sopenharmony_ci case HostCmd_CMD_802_11_TX_RATE_QUERY: 129762306a36Sopenharmony_ci ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); 129862306a36Sopenharmony_ci break; 129962306a36Sopenharmony_ci case HostCmd_CMD_VERSION_EXT: 130062306a36Sopenharmony_ci ret = mwifiex_ret_ver_ext(priv, resp, data_buf); 130162306a36Sopenharmony_ci break; 130262306a36Sopenharmony_ci case HostCmd_CMD_REMAIN_ON_CHAN: 130362306a36Sopenharmony_ci ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); 130462306a36Sopenharmony_ci break; 130562306a36Sopenharmony_ci case HostCmd_CMD_11AC_CFG: 130662306a36Sopenharmony_ci break; 130762306a36Sopenharmony_ci case HostCmd_CMD_PACKET_AGGR_CTRL: 130862306a36Sopenharmony_ci ret = mwifiex_ret_pkt_aggr_ctrl(priv, resp); 130962306a36Sopenharmony_ci break; 131062306a36Sopenharmony_ci case HostCmd_CMD_P2P_MODE_CFG: 131162306a36Sopenharmony_ci ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); 131262306a36Sopenharmony_ci break; 131362306a36Sopenharmony_ci case HostCmd_CMD_MGMT_FRAME_REG: 131462306a36Sopenharmony_ci case HostCmd_CMD_FUNC_INIT: 131562306a36Sopenharmony_ci case HostCmd_CMD_FUNC_SHUTDOWN: 131662306a36Sopenharmony_ci break; 131762306a36Sopenharmony_ci case HostCmd_CMD_802_11_KEY_MATERIAL: 131862306a36Sopenharmony_ci ret = mwifiex_ret_802_11_key_material(priv, resp); 131962306a36Sopenharmony_ci break; 132062306a36Sopenharmony_ci case HostCmd_CMD_802_11D_DOMAIN_INFO: 132162306a36Sopenharmony_ci ret = mwifiex_ret_802_11d_domain_info(priv, resp); 132262306a36Sopenharmony_ci break; 132362306a36Sopenharmony_ci case HostCmd_CMD_11N_ADDBA_REQ: 132462306a36Sopenharmony_ci ret = mwifiex_ret_11n_addba_req(priv, resp); 132562306a36Sopenharmony_ci break; 132662306a36Sopenharmony_ci case HostCmd_CMD_11N_DELBA: 132762306a36Sopenharmony_ci ret = mwifiex_ret_11n_delba(priv, resp); 132862306a36Sopenharmony_ci break; 132962306a36Sopenharmony_ci case HostCmd_CMD_11N_ADDBA_RSP: 133062306a36Sopenharmony_ci ret = mwifiex_ret_11n_addba_resp(priv, resp); 133162306a36Sopenharmony_ci break; 133262306a36Sopenharmony_ci case HostCmd_CMD_RECONFIGURE_TX_BUFF: 133362306a36Sopenharmony_ci if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { 133462306a36Sopenharmony_ci if (adapter->iface_type == MWIFIEX_USB && 133562306a36Sopenharmony_ci adapter->usb_mc_setup) { 133662306a36Sopenharmony_ci if (adapter->if_ops.multi_port_resync) 133762306a36Sopenharmony_ci adapter->if_ops. 133862306a36Sopenharmony_ci multi_port_resync(adapter); 133962306a36Sopenharmony_ci adapter->usb_mc_setup = false; 134062306a36Sopenharmony_ci adapter->tx_lock_flag = false; 134162306a36Sopenharmony_ci } 134262306a36Sopenharmony_ci break; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. 134562306a36Sopenharmony_ci tx_buf.buff_size); 134662306a36Sopenharmony_ci adapter->tx_buf_size = (adapter->tx_buf_size 134762306a36Sopenharmony_ci / MWIFIEX_SDIO_BLOCK_SIZE) 134862306a36Sopenharmony_ci * MWIFIEX_SDIO_BLOCK_SIZE; 134962306a36Sopenharmony_ci adapter->curr_tx_buf_size = adapter->tx_buf_size; 135062306a36Sopenharmony_ci mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n", 135162306a36Sopenharmony_ci adapter->curr_tx_buf_size); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci if (adapter->if_ops.update_mp_end_port) 135462306a36Sopenharmony_ci adapter->if_ops.update_mp_end_port(adapter, 135562306a36Sopenharmony_ci le16_to_cpu(resp->params.tx_buf.mp_end_port)); 135662306a36Sopenharmony_ci break; 135762306a36Sopenharmony_ci case HostCmd_CMD_AMSDU_AGGR_CTRL: 135862306a36Sopenharmony_ci break; 135962306a36Sopenharmony_ci case HostCmd_CMD_WMM_GET_STATUS: 136062306a36Sopenharmony_ci ret = mwifiex_ret_wmm_get_status(priv, resp); 136162306a36Sopenharmony_ci break; 136262306a36Sopenharmony_ci case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: 136362306a36Sopenharmony_ci ret = mwifiex_ret_ibss_coalescing_status(priv, resp); 136462306a36Sopenharmony_ci break; 136562306a36Sopenharmony_ci case HostCmd_CMD_MEM_ACCESS: 136662306a36Sopenharmony_ci ret = mwifiex_ret_mem_access(priv, resp, data_buf); 136762306a36Sopenharmony_ci break; 136862306a36Sopenharmony_ci case HostCmd_CMD_MAC_REG_ACCESS: 136962306a36Sopenharmony_ci case HostCmd_CMD_BBP_REG_ACCESS: 137062306a36Sopenharmony_ci case HostCmd_CMD_RF_REG_ACCESS: 137162306a36Sopenharmony_ci case HostCmd_CMD_PMIC_REG_ACCESS: 137262306a36Sopenharmony_ci case HostCmd_CMD_CAU_REG_ACCESS: 137362306a36Sopenharmony_ci case HostCmd_CMD_802_11_EEPROM_ACCESS: 137462306a36Sopenharmony_ci ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); 137562306a36Sopenharmony_ci break; 137662306a36Sopenharmony_ci case HostCmd_CMD_SET_BSS_MODE: 137762306a36Sopenharmony_ci break; 137862306a36Sopenharmony_ci case HostCmd_CMD_11N_CFG: 137962306a36Sopenharmony_ci break; 138062306a36Sopenharmony_ci case HostCmd_CMD_PCIE_DESC_DETAILS: 138162306a36Sopenharmony_ci break; 138262306a36Sopenharmony_ci case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: 138362306a36Sopenharmony_ci ret = mwifiex_ret_subsc_evt(priv, resp); 138462306a36Sopenharmony_ci break; 138562306a36Sopenharmony_ci case HostCmd_CMD_UAP_SYS_CONFIG: 138662306a36Sopenharmony_ci break; 138762306a36Sopenharmony_ci case HOST_CMD_APCMD_STA_LIST: 138862306a36Sopenharmony_ci ret = mwifiex_ret_uap_sta_list(priv, resp); 138962306a36Sopenharmony_ci break; 139062306a36Sopenharmony_ci case HostCmd_CMD_UAP_BSS_START: 139162306a36Sopenharmony_ci adapter->tx_lock_flag = false; 139262306a36Sopenharmony_ci adapter->pps_uapsd_mode = false; 139362306a36Sopenharmony_ci adapter->delay_null_pkt = false; 139462306a36Sopenharmony_ci priv->bss_started = 1; 139562306a36Sopenharmony_ci break; 139662306a36Sopenharmony_ci case HostCmd_CMD_UAP_BSS_STOP: 139762306a36Sopenharmony_ci priv->bss_started = 0; 139862306a36Sopenharmony_ci break; 139962306a36Sopenharmony_ci case HostCmd_CMD_UAP_STA_DEAUTH: 140062306a36Sopenharmony_ci break; 140162306a36Sopenharmony_ci case HOST_CMD_APCMD_SYS_RESET: 140262306a36Sopenharmony_ci break; 140362306a36Sopenharmony_ci case HostCmd_CMD_MEF_CFG: 140462306a36Sopenharmony_ci break; 140562306a36Sopenharmony_ci case HostCmd_CMD_COALESCE_CFG: 140662306a36Sopenharmony_ci break; 140762306a36Sopenharmony_ci case HostCmd_CMD_TDLS_OPER: 140862306a36Sopenharmony_ci ret = mwifiex_ret_tdls_oper(priv, resp); 140962306a36Sopenharmony_ci break; 141062306a36Sopenharmony_ci case HostCmd_CMD_MC_POLICY: 141162306a36Sopenharmony_ci break; 141262306a36Sopenharmony_ci case HostCmd_CMD_CHAN_REPORT_REQUEST: 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: 141562306a36Sopenharmony_ci ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); 141662306a36Sopenharmony_ci break; 141762306a36Sopenharmony_ci case HostCmd_CMD_HS_WAKEUP_REASON: 141862306a36Sopenharmony_ci ret = mwifiex_ret_wakeup_reason(priv, resp, data_buf); 141962306a36Sopenharmony_ci break; 142062306a36Sopenharmony_ci case HostCmd_CMD_TDLS_CONFIG: 142162306a36Sopenharmony_ci break; 142262306a36Sopenharmony_ci case HostCmd_CMD_ROBUST_COEX: 142362306a36Sopenharmony_ci ret = mwifiex_ret_robust_coex(priv, resp, data_buf); 142462306a36Sopenharmony_ci break; 142562306a36Sopenharmony_ci case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG: 142662306a36Sopenharmony_ci break; 142762306a36Sopenharmony_ci case HostCmd_CMD_CHAN_REGION_CFG: 142862306a36Sopenharmony_ci ret = mwifiex_ret_chan_region_cfg(priv, resp); 142962306a36Sopenharmony_ci break; 143062306a36Sopenharmony_ci case HostCmd_CMD_STA_CONFIGURE: 143162306a36Sopenharmony_ci ret = mwifiex_ret_get_chan_info(priv, resp, data_buf); 143262306a36Sopenharmony_ci break; 143362306a36Sopenharmony_ci default: 143462306a36Sopenharmony_ci mwifiex_dbg(adapter, ERROR, 143562306a36Sopenharmony_ci "CMD_RESP: unknown cmd response %#x\n", 143662306a36Sopenharmony_ci resp->command); 143762306a36Sopenharmony_ci break; 143862306a36Sopenharmony_ci } 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci return ret; 144162306a36Sopenharmony_ci} 1442