18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * NXP Wireless LAN device driver: station command response 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_ci
308c2ecf20Sopenharmony_ci/*
318c2ecf20Sopenharmony_ci * This function handles the command response error case.
328c2ecf20Sopenharmony_ci *
338c2ecf20Sopenharmony_ci * For scan response error, the function cancels all the pending
348c2ecf20Sopenharmony_ci * scan commands and generates an event to inform the applications
358c2ecf20Sopenharmony_ci * of the scan completion.
368c2ecf20Sopenharmony_ci *
378c2ecf20Sopenharmony_ci * For Power Save command failure, we do not retry enter PS
388c2ecf20Sopenharmony_ci * command in case of Ad-hoc mode.
398c2ecf20Sopenharmony_ci *
408c2ecf20Sopenharmony_ci * For all other response errors, the current command buffer is freed
418c2ecf20Sopenharmony_ci * and returned to the free command queue.
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_cistatic void
448c2ecf20Sopenharmony_cimwifiex_process_cmdresp_error(struct mwifiex_private *priv,
458c2ecf20Sopenharmony_ci			      struct host_cmd_ds_command *resp)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
488c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_ps_mode_enh *pm;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	mwifiex_dbg(adapter, ERROR,
518c2ecf20Sopenharmony_ci		    "CMD_RESP: cmd %#x error, result=%#x\n",
528c2ecf20Sopenharmony_ci		    resp->command, resp->result);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (adapter->curr_cmd->wait_q_enabled)
558c2ecf20Sopenharmony_ci		adapter->cmd_wait_q.status = -1;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	switch (le16_to_cpu(resp->command)) {
588c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_PS_MODE_ENH:
598c2ecf20Sopenharmony_ci		pm = &resp->params.psmode_enh;
608c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, ERROR,
618c2ecf20Sopenharmony_ci			    "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n",
628c2ecf20Sopenharmony_ci			    resp->result, le16_to_cpu(pm->action));
638c2ecf20Sopenharmony_ci		/* We do not re-try enter-ps command in ad-hoc mode. */
648c2ecf20Sopenharmony_ci		if (le16_to_cpu(pm->action) == EN_AUTO_PS &&
658c2ecf20Sopenharmony_ci		    (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) &&
668c2ecf20Sopenharmony_ci		    priv->bss_mode == NL80211_IFTYPE_ADHOC)
678c2ecf20Sopenharmony_ci			adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci		break;
708c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SCAN:
718c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SCAN_EXT:
728c2ecf20Sopenharmony_ci		mwifiex_cancel_scan(adapter);
738c2ecf20Sopenharmony_ci		break;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	case HostCmd_CMD_MAC_CONTROL:
768c2ecf20Sopenharmony_ci		break;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
798c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, MSG,
808c2ecf20Sopenharmony_ci			    "SDIO RX single-port aggregation Not support\n");
818c2ecf20Sopenharmony_ci		break;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	default:
848c2ecf20Sopenharmony_ci		break;
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci	/* Handling errors here */
878c2ecf20Sopenharmony_ci	mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	spin_lock_bh(&adapter->mwifiex_cmd_lock);
908c2ecf20Sopenharmony_ci	adapter->curr_cmd = NULL;
918c2ecf20Sopenharmony_ci	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/*
958c2ecf20Sopenharmony_ci * This function handles the command response of get RSSI info.
968c2ecf20Sopenharmony_ci *
978c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
988c2ecf20Sopenharmony_ci * and saving the following parameters in driver -
998c2ecf20Sopenharmony_ci *      - Last data and beacon RSSI value
1008c2ecf20Sopenharmony_ci *      - Average data and beacon RSSI value
1018c2ecf20Sopenharmony_ci *      - Last data and beacon NF value
1028c2ecf20Sopenharmony_ci *      - Average data and beacon NF value
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci * The parameters are send to the application as well, along with
1058c2ecf20Sopenharmony_ci * calculated SNR values.
1068c2ecf20Sopenharmony_ci */
1078c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
1088c2ecf20Sopenharmony_ci					struct host_cmd_ds_command *resp)
1098c2ecf20Sopenharmony_ci{
1108c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
1118c2ecf20Sopenharmony_ci						&resp->params.rssi_info_rsp;
1128c2ecf20Sopenharmony_ci	struct mwifiex_ds_misc_subsc_evt *subsc_evt =
1138c2ecf20Sopenharmony_ci						&priv->async_subsc_evt_storage;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
1168c2ecf20Sopenharmony_ci	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
1198c2ecf20Sopenharmony_ci	priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
1228c2ecf20Sopenharmony_ci	priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
1258c2ecf20Sopenharmony_ci	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
1288c2ecf20Sopenharmony_ci		return 0;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	/* Resubscribe low and high rssi events with new thresholds */
1338c2ecf20Sopenharmony_ci	subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
1348c2ecf20Sopenharmony_ci	subsc_evt->action = HostCmd_ACT_BITWISE_SET;
1358c2ecf20Sopenharmony_ci	if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
1368c2ecf20Sopenharmony_ci		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
1378c2ecf20Sopenharmony_ci				priv->cqm_rssi_hyst);
1388c2ecf20Sopenharmony_ci		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
1398c2ecf20Sopenharmony_ci	} else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
1408c2ecf20Sopenharmony_ci		subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
1418c2ecf20Sopenharmony_ci		subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
1428c2ecf20Sopenharmony_ci				priv->cqm_rssi_hyst);
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci	subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
1458c2ecf20Sopenharmony_ci	subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	priv->subsc_evt_rssi_state = EVENT_HANDLED;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1508c2ecf20Sopenharmony_ci			 0, 0, subsc_evt, false);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	return 0;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/*
1568c2ecf20Sopenharmony_ci * This function handles the command response of set/get SNMP
1578c2ecf20Sopenharmony_ci * MIB parameters.
1588c2ecf20Sopenharmony_ci *
1598c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
1608c2ecf20Sopenharmony_ci * and saving the parameter in driver.
1618c2ecf20Sopenharmony_ci *
1628c2ecf20Sopenharmony_ci * The following parameters are supported -
1638c2ecf20Sopenharmony_ci *      - Fragmentation threshold
1648c2ecf20Sopenharmony_ci *      - RTS threshold
1658c2ecf20Sopenharmony_ci *      - Short retry limit
1668c2ecf20Sopenharmony_ci */
1678c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
1688c2ecf20Sopenharmony_ci				       struct host_cmd_ds_command *resp,
1698c2ecf20Sopenharmony_ci				       u32 *data_buf)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
1728c2ecf20Sopenharmony_ci	u16 oid = le16_to_cpu(smib->oid);
1738c2ecf20Sopenharmony_ci	u16 query_type = le16_to_cpu(smib->query_type);
1748c2ecf20Sopenharmony_ci	u32 ul_temp;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, INFO,
1778c2ecf20Sopenharmony_ci		    "info: SNMP_RESP: oid value = %#x,\t"
1788c2ecf20Sopenharmony_ci		    "query_type = %#x, buf size = %#x\n",
1798c2ecf20Sopenharmony_ci		    oid, query_type, le16_to_cpu(smib->buf_size));
1808c2ecf20Sopenharmony_ci	if (query_type == HostCmd_ACT_GEN_GET) {
1818c2ecf20Sopenharmony_ci		ul_temp = get_unaligned_le16(smib->value);
1828c2ecf20Sopenharmony_ci		if (data_buf)
1838c2ecf20Sopenharmony_ci			*data_buf = ul_temp;
1848c2ecf20Sopenharmony_ci		switch (oid) {
1858c2ecf20Sopenharmony_ci		case FRAG_THRESH_I:
1868c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO,
1878c2ecf20Sopenharmony_ci				    "info: SNMP_RESP: FragThsd =%u\n",
1888c2ecf20Sopenharmony_ci				    ul_temp);
1898c2ecf20Sopenharmony_ci			break;
1908c2ecf20Sopenharmony_ci		case RTS_THRESH_I:
1918c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO,
1928c2ecf20Sopenharmony_ci				    "info: SNMP_RESP: RTSThsd =%u\n",
1938c2ecf20Sopenharmony_ci				    ul_temp);
1948c2ecf20Sopenharmony_ci			break;
1958c2ecf20Sopenharmony_ci		case SHORT_RETRY_LIM_I:
1968c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO,
1978c2ecf20Sopenharmony_ci				    "info: SNMP_RESP: TxRetryCount=%u\n",
1988c2ecf20Sopenharmony_ci				    ul_temp);
1998c2ecf20Sopenharmony_ci			break;
2008c2ecf20Sopenharmony_ci		case DTIM_PERIOD_I:
2018c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO,
2028c2ecf20Sopenharmony_ci				    "info: SNMP_RESP: DTIM period=%u\n",
2038c2ecf20Sopenharmony_ci				    ul_temp);
2048c2ecf20Sopenharmony_ci		default:
2058c2ecf20Sopenharmony_ci			break;
2068c2ecf20Sopenharmony_ci		}
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	return 0;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci/*
2138c2ecf20Sopenharmony_ci * This function handles the command response of get log request
2148c2ecf20Sopenharmony_ci *
2158c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
2168c2ecf20Sopenharmony_ci * and sending the received parameters to application.
2178c2ecf20Sopenharmony_ci */
2188c2ecf20Sopenharmony_cistatic int mwifiex_ret_get_log(struct mwifiex_private *priv,
2198c2ecf20Sopenharmony_ci			       struct host_cmd_ds_command *resp,
2208c2ecf20Sopenharmony_ci			       struct mwifiex_ds_get_stats *stats)
2218c2ecf20Sopenharmony_ci{
2228c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_get_log *get_log =
2238c2ecf20Sopenharmony_ci		&resp->params.get_log;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	if (stats) {
2268c2ecf20Sopenharmony_ci		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
2278c2ecf20Sopenharmony_ci		stats->failed = le32_to_cpu(get_log->failed);
2288c2ecf20Sopenharmony_ci		stats->retry = le32_to_cpu(get_log->retry);
2298c2ecf20Sopenharmony_ci		stats->multi_retry = le32_to_cpu(get_log->multi_retry);
2308c2ecf20Sopenharmony_ci		stats->frame_dup = le32_to_cpu(get_log->frame_dup);
2318c2ecf20Sopenharmony_ci		stats->rts_success = le32_to_cpu(get_log->rts_success);
2328c2ecf20Sopenharmony_ci		stats->rts_failure = le32_to_cpu(get_log->rts_failure);
2338c2ecf20Sopenharmony_ci		stats->ack_failure = le32_to_cpu(get_log->ack_failure);
2348c2ecf20Sopenharmony_ci		stats->rx_frag = le32_to_cpu(get_log->rx_frag);
2358c2ecf20Sopenharmony_ci		stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
2368c2ecf20Sopenharmony_ci		stats->fcs_error = le32_to_cpu(get_log->fcs_error);
2378c2ecf20Sopenharmony_ci		stats->tx_frame = le32_to_cpu(get_log->tx_frame);
2388c2ecf20Sopenharmony_ci		stats->wep_icv_error[0] =
2398c2ecf20Sopenharmony_ci			le32_to_cpu(get_log->wep_icv_err_cnt[0]);
2408c2ecf20Sopenharmony_ci		stats->wep_icv_error[1] =
2418c2ecf20Sopenharmony_ci			le32_to_cpu(get_log->wep_icv_err_cnt[1]);
2428c2ecf20Sopenharmony_ci		stats->wep_icv_error[2] =
2438c2ecf20Sopenharmony_ci			le32_to_cpu(get_log->wep_icv_err_cnt[2]);
2448c2ecf20Sopenharmony_ci		stats->wep_icv_error[3] =
2458c2ecf20Sopenharmony_ci			le32_to_cpu(get_log->wep_icv_err_cnt[3]);
2468c2ecf20Sopenharmony_ci		stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt);
2478c2ecf20Sopenharmony_ci		stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt);
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	return 0;
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci/*
2548c2ecf20Sopenharmony_ci * This function handles the command response of set/get Tx rate
2558c2ecf20Sopenharmony_ci * configurations.
2568c2ecf20Sopenharmony_ci *
2578c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
2588c2ecf20Sopenharmony_ci * and saving the following parameters in driver -
2598c2ecf20Sopenharmony_ci *      - DSSS rate bitmap
2608c2ecf20Sopenharmony_ci *      - OFDM rate bitmap
2618c2ecf20Sopenharmony_ci *      - HT MCS rate bitmaps
2628c2ecf20Sopenharmony_ci *
2638c2ecf20Sopenharmony_ci * Based on the new rate bitmaps, the function re-evaluates if
2648c2ecf20Sopenharmony_ci * auto data rate has been activated. If not, it sends another
2658c2ecf20Sopenharmony_ci * query to the firmware to get the current Tx data rate.
2668c2ecf20Sopenharmony_ci */
2678c2ecf20Sopenharmony_cistatic int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
2688c2ecf20Sopenharmony_ci				   struct host_cmd_ds_command *resp)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
2718c2ecf20Sopenharmony_ci	struct mwifiex_rate_scope *rate_scope;
2728c2ecf20Sopenharmony_ci	struct mwifiex_ie_types_header *head;
2738c2ecf20Sopenharmony_ci	u16 tlv, tlv_buf_len, tlv_buf_left;
2748c2ecf20Sopenharmony_ci	u8 *tlv_buf;
2758c2ecf20Sopenharmony_ci	u32 i;
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
2788c2ecf20Sopenharmony_ci	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	while (tlv_buf_left >= sizeof(*head)) {
2818c2ecf20Sopenharmony_ci		head = (struct mwifiex_ie_types_header *)tlv_buf;
2828c2ecf20Sopenharmony_ci		tlv = le16_to_cpu(head->type);
2838c2ecf20Sopenharmony_ci		tlv_buf_len = le16_to_cpu(head->len);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
2868c2ecf20Sopenharmony_ci			break;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		switch (tlv) {
2898c2ecf20Sopenharmony_ci		case TLV_TYPE_RATE_SCOPE:
2908c2ecf20Sopenharmony_ci			rate_scope = (struct mwifiex_rate_scope *) tlv_buf;
2918c2ecf20Sopenharmony_ci			priv->bitmap_rates[0] =
2928c2ecf20Sopenharmony_ci				le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
2938c2ecf20Sopenharmony_ci			priv->bitmap_rates[1] =
2948c2ecf20Sopenharmony_ci				le16_to_cpu(rate_scope->ofdm_rate_bitmap);
2958c2ecf20Sopenharmony_ci			for (i = 0;
2968c2ecf20Sopenharmony_ci			     i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap);
2978c2ecf20Sopenharmony_ci			     i++)
2988c2ecf20Sopenharmony_ci				priv->bitmap_rates[2 + i] =
2998c2ecf20Sopenharmony_ci					le16_to_cpu(rate_scope->
3008c2ecf20Sopenharmony_ci						    ht_mcs_rate_bitmap[i]);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci			if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) {
3038c2ecf20Sopenharmony_ci				for (i = 0; i < ARRAY_SIZE(rate_scope->
3048c2ecf20Sopenharmony_ci							   vht_mcs_rate_bitmap);
3058c2ecf20Sopenharmony_ci				     i++)
3068c2ecf20Sopenharmony_ci					priv->bitmap_rates[10 + i] =
3078c2ecf20Sopenharmony_ci					    le16_to_cpu(rate_scope->
3088c2ecf20Sopenharmony_ci							vht_mcs_rate_bitmap[i]);
3098c2ecf20Sopenharmony_ci			}
3108c2ecf20Sopenharmony_ci			break;
3118c2ecf20Sopenharmony_ci			/* Add RATE_DROP tlv here */
3128c2ecf20Sopenharmony_ci		}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci		tlv_buf += (sizeof(*head) + tlv_buf_len);
3158c2ecf20Sopenharmony_ci		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci	priv->is_data_rate_auto = mwifiex_is_rate_auto(priv);
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	if (priv->is_data_rate_auto)
3218c2ecf20Sopenharmony_ci		priv->data_rate = 0;
3228c2ecf20Sopenharmony_ci	else
3238c2ecf20Sopenharmony_ci		return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
3248c2ecf20Sopenharmony_ci					HostCmd_ACT_GEN_GET, 0, NULL, false);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return 0;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci/*
3308c2ecf20Sopenharmony_ci * This function handles the command response of get Tx power level.
3318c2ecf20Sopenharmony_ci *
3328c2ecf20Sopenharmony_ci * Handling includes saving the maximum and minimum Tx power levels
3338c2ecf20Sopenharmony_ci * in driver, as well as sending the values to user.
3348c2ecf20Sopenharmony_ci */
3358c2ecf20Sopenharmony_cistatic int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	int length, max_power = -1, min_power = -1;
3388c2ecf20Sopenharmony_ci	struct mwifiex_types_power_group *pg_tlv_hdr;
3398c2ecf20Sopenharmony_ci	struct mwifiex_power_group *pg;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	if (!data_buf)
3428c2ecf20Sopenharmony_ci		return -1;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf);
3458c2ecf20Sopenharmony_ci	pg = (struct mwifiex_power_group *)
3468c2ecf20Sopenharmony_ci		((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group));
3478c2ecf20Sopenharmony_ci	length = le16_to_cpu(pg_tlv_hdr->length);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	/* At least one structure required to update power */
3508c2ecf20Sopenharmony_ci	if (length < sizeof(struct mwifiex_power_group))
3518c2ecf20Sopenharmony_ci		return 0;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	max_power = pg->power_max;
3548c2ecf20Sopenharmony_ci	min_power = pg->power_min;
3558c2ecf20Sopenharmony_ci	length -= sizeof(struct mwifiex_power_group);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	while (length >= sizeof(struct mwifiex_power_group)) {
3588c2ecf20Sopenharmony_ci		pg++;
3598c2ecf20Sopenharmony_ci		if (max_power < pg->power_max)
3608c2ecf20Sopenharmony_ci			max_power = pg->power_max;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		if (min_power > pg->power_min)
3638c2ecf20Sopenharmony_ci			min_power = pg->power_min;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci		length -= sizeof(struct mwifiex_power_group);
3668c2ecf20Sopenharmony_ci	}
3678c2ecf20Sopenharmony_ci	priv->min_tx_power_level = (u8) min_power;
3688c2ecf20Sopenharmony_ci	priv->max_tx_power_level = (u8) max_power;
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	return 0;
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci/*
3748c2ecf20Sopenharmony_ci * This function handles the command response of set/get Tx power
3758c2ecf20Sopenharmony_ci * configurations.
3768c2ecf20Sopenharmony_ci *
3778c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
3788c2ecf20Sopenharmony_ci * and saving the current Tx power level in driver.
3798c2ecf20Sopenharmony_ci */
3808c2ecf20Sopenharmony_cistatic int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
3818c2ecf20Sopenharmony_ci				    struct host_cmd_ds_command *resp)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
3848c2ecf20Sopenharmony_ci	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
3858c2ecf20Sopenharmony_ci	struct mwifiex_types_power_group *pg_tlv_hdr;
3868c2ecf20Sopenharmony_ci	struct mwifiex_power_group *pg;
3878c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(txp_cfg->action);
3888c2ecf20Sopenharmony_ci	u16 tlv_buf_left;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	pg_tlv_hdr = (struct mwifiex_types_power_group *)
3918c2ecf20Sopenharmony_ci		((u8 *)txp_cfg +
3928c2ecf20Sopenharmony_ci		 sizeof(struct host_cmd_ds_txpwr_cfg));
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	pg = (struct mwifiex_power_group *)
3958c2ecf20Sopenharmony_ci		((u8 *)pg_tlv_hdr +
3968c2ecf20Sopenharmony_ci		 sizeof(struct mwifiex_types_power_group));
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
3998c2ecf20Sopenharmony_ci	if (tlv_buf_left <
4008c2ecf20Sopenharmony_ci			le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
4018c2ecf20Sopenharmony_ci		return 0;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	switch (action) {
4048c2ecf20Sopenharmony_ci	case HostCmd_ACT_GEN_GET:
4058c2ecf20Sopenharmony_ci		if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
4068c2ecf20Sopenharmony_ci			mwifiex_get_power_level(priv, pg_tlv_hdr);
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci		priv->tx_power_level = (u16) pg->power_min;
4098c2ecf20Sopenharmony_ci		break;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	case HostCmd_ACT_GEN_SET:
4128c2ecf20Sopenharmony_ci		if (!le32_to_cpu(txp_cfg->mode))
4138c2ecf20Sopenharmony_ci			break;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci		if (pg->power_max == pg->power_min)
4168c2ecf20Sopenharmony_ci			priv->tx_power_level = (u16) pg->power_min;
4178c2ecf20Sopenharmony_ci		break;
4188c2ecf20Sopenharmony_ci	default:
4198c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, ERROR,
4208c2ecf20Sopenharmony_ci			    "CMD_RESP: unknown cmd action %d\n",
4218c2ecf20Sopenharmony_ci			    action);
4228c2ecf20Sopenharmony_ci		return 0;
4238c2ecf20Sopenharmony_ci	}
4248c2ecf20Sopenharmony_ci	mwifiex_dbg(adapter, INFO,
4258c2ecf20Sopenharmony_ci		    "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
4268c2ecf20Sopenharmony_ci		    priv->tx_power_level, priv->max_tx_power_level,
4278c2ecf20Sopenharmony_ci		    priv->min_tx_power_level);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return 0;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/*
4338c2ecf20Sopenharmony_ci * This function handles the command response of get RF Tx power.
4348c2ecf20Sopenharmony_ci */
4358c2ecf20Sopenharmony_cistatic int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv,
4368c2ecf20Sopenharmony_ci				   struct host_cmd_ds_command *resp)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
4398c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(txp->action);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	priv->tx_power_level = le16_to_cpu(txp->cur_level);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	if (action == HostCmd_ACT_GEN_GET) {
4448c2ecf20Sopenharmony_ci		priv->max_tx_power_level = txp->max_power;
4458c2ecf20Sopenharmony_ci		priv->min_tx_power_level = txp->min_power;
4468c2ecf20Sopenharmony_ci	}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, INFO,
4498c2ecf20Sopenharmony_ci		    "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
4508c2ecf20Sopenharmony_ci		    priv->tx_power_level, priv->max_tx_power_level,
4518c2ecf20Sopenharmony_ci		    priv->min_tx_power_level);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	return 0;
4548c2ecf20Sopenharmony_ci}
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/*
4578c2ecf20Sopenharmony_ci * This function handles the command response of set rf antenna
4588c2ecf20Sopenharmony_ci */
4598c2ecf20Sopenharmony_cistatic int mwifiex_ret_rf_antenna(struct mwifiex_private *priv,
4608c2ecf20Sopenharmony_ci				  struct host_cmd_ds_command *resp)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
4638c2ecf20Sopenharmony_ci	struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
4648c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
4678c2ecf20Sopenharmony_ci		priv->tx_ant = le16_to_cpu(ant_mimo->tx_ant_mode);
4688c2ecf20Sopenharmony_ci		priv->rx_ant = le16_to_cpu(ant_mimo->rx_ant_mode);
4698c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, INFO,
4708c2ecf20Sopenharmony_ci			    "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
4718c2ecf20Sopenharmony_ci			    "Rx action = 0x%x, Rx Mode = 0x%04x\n",
4728c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_mimo->action_tx),
4738c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_mimo->tx_ant_mode),
4748c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_mimo->action_rx),
4758c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_mimo->rx_ant_mode));
4768c2ecf20Sopenharmony_ci	} else {
4778c2ecf20Sopenharmony_ci		priv->tx_ant = le16_to_cpu(ant_siso->ant_mode);
4788c2ecf20Sopenharmony_ci		priv->rx_ant = le16_to_cpu(ant_siso->ant_mode);
4798c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, INFO,
4808c2ecf20Sopenharmony_ci			    "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
4818c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_siso->action),
4828c2ecf20Sopenharmony_ci			    le16_to_cpu(ant_siso->ant_mode));
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci	return 0;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci/*
4888c2ecf20Sopenharmony_ci * This function handles the command response of set/get MAC address.
4898c2ecf20Sopenharmony_ci *
4908c2ecf20Sopenharmony_ci * Handling includes saving the MAC address in driver.
4918c2ecf20Sopenharmony_ci */
4928c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv,
4938c2ecf20Sopenharmony_ci					  struct host_cmd_ds_command *resp)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_mac_address *cmd_mac_addr =
4968c2ecf20Sopenharmony_ci							&resp->params.mac_addr;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, INFO,
5018c2ecf20Sopenharmony_ci		    "info: set mac address: %pM\n", priv->curr_addr);
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	return 0;
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci/*
5078c2ecf20Sopenharmony_ci * This function handles the command response of set/get MAC multicast
5088c2ecf20Sopenharmony_ci * address.
5098c2ecf20Sopenharmony_ci */
5108c2ecf20Sopenharmony_cistatic int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv,
5118c2ecf20Sopenharmony_ci					 struct host_cmd_ds_command *resp)
5128c2ecf20Sopenharmony_ci{
5138c2ecf20Sopenharmony_ci	return 0;
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci/*
5178c2ecf20Sopenharmony_ci * This function handles the command response of get Tx rate query.
5188c2ecf20Sopenharmony_ci *
5198c2ecf20Sopenharmony_ci * Handling includes changing the header fields into CPU format
5208c2ecf20Sopenharmony_ci * and saving the Tx rate and HT information parameters in driver.
5218c2ecf20Sopenharmony_ci *
5228c2ecf20Sopenharmony_ci * Both rate configuration and current data rate can be retrieved
5238c2ecf20Sopenharmony_ci * with this request.
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv,
5268c2ecf20Sopenharmony_ci					    struct host_cmd_ds_command *resp)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	priv->tx_rate = resp->params.tx_rate.tx_rate;
5298c2ecf20Sopenharmony_ci	priv->tx_htinfo = resp->params.tx_rate.ht_info;
5308c2ecf20Sopenharmony_ci	if (!priv->is_data_rate_auto)
5318c2ecf20Sopenharmony_ci		priv->data_rate =
5328c2ecf20Sopenharmony_ci			mwifiex_index_to_data_rate(priv, priv->tx_rate,
5338c2ecf20Sopenharmony_ci						   priv->tx_htinfo);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	return 0;
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci/*
5398c2ecf20Sopenharmony_ci * This function handles the command response of a deauthenticate
5408c2ecf20Sopenharmony_ci * command.
5418c2ecf20Sopenharmony_ci *
5428c2ecf20Sopenharmony_ci * If the deauthenticated MAC matches the current BSS MAC, the connection
5438c2ecf20Sopenharmony_ci * state is reset.
5448c2ecf20Sopenharmony_ci */
5458c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv,
5468c2ecf20Sopenharmony_ci					     struct host_cmd_ds_command *resp)
5478c2ecf20Sopenharmony_ci{
5488c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	adapter->dbg.num_cmd_deauth++;
5518c2ecf20Sopenharmony_ci	if (!memcmp(resp->params.deauth.mac_addr,
5528c2ecf20Sopenharmony_ci		    &priv->curr_bss_params.bss_descriptor.mac_address,
5538c2ecf20Sopenharmony_ci		    sizeof(resp->params.deauth.mac_addr)))
5548c2ecf20Sopenharmony_ci		mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING,
5558c2ecf20Sopenharmony_ci					    false);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return 0;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/*
5618c2ecf20Sopenharmony_ci * This function handles the command response of ad-hoc stop.
5628c2ecf20Sopenharmony_ci *
5638c2ecf20Sopenharmony_ci * The function resets the connection state in driver.
5648c2ecf20Sopenharmony_ci */
5658c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv,
5668c2ecf20Sopenharmony_ci					  struct host_cmd_ds_command *resp)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING, false);
5698c2ecf20Sopenharmony_ci	return 0;
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci/*
5738c2ecf20Sopenharmony_ci * This function handles the command response of set/get v1 key material.
5748c2ecf20Sopenharmony_ci *
5758c2ecf20Sopenharmony_ci * Handling includes updating the driver parameters to reflect the
5768c2ecf20Sopenharmony_ci * changes.
5778c2ecf20Sopenharmony_ci */
5788c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
5798c2ecf20Sopenharmony_ci					      struct host_cmd_ds_command *resp)
5808c2ecf20Sopenharmony_ci{
5818c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_key_material *key =
5828c2ecf20Sopenharmony_ci						&resp->params.key_material;
5838c2ecf20Sopenharmony_ci	int len;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	len = le16_to_cpu(key->key_param_set.key_len);
5868c2ecf20Sopenharmony_ci	if (len > sizeof(key->key_param_set.key))
5878c2ecf20Sopenharmony_ci		return -EINVAL;
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
5908c2ecf20Sopenharmony_ci		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
5918c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO,
5928c2ecf20Sopenharmony_ci				    "info: key: GTK is set\n");
5938c2ecf20Sopenharmony_ci			priv->wpa_is_gtk_set = true;
5948c2ecf20Sopenharmony_ci			priv->scan_block = false;
5958c2ecf20Sopenharmony_ci			priv->port_open = true;
5968c2ecf20Sopenharmony_ci		}
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	memset(priv->aes_key.key_param_set.key, 0,
6008c2ecf20Sopenharmony_ci	       sizeof(key->key_param_set.key));
6018c2ecf20Sopenharmony_ci	priv->aes_key.key_param_set.key_len = cpu_to_le16(len);
6028c2ecf20Sopenharmony_ci	memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, len);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	return 0;
6058c2ecf20Sopenharmony_ci}
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci/*
6088c2ecf20Sopenharmony_ci * This function handles the command response of set/get v2 key material.
6098c2ecf20Sopenharmony_ci *
6108c2ecf20Sopenharmony_ci * Handling includes updating the driver parameters to reflect the
6118c2ecf20Sopenharmony_ci * changes.
6128c2ecf20Sopenharmony_ci */
6138c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
6148c2ecf20Sopenharmony_ci					      struct host_cmd_ds_command *resp)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_key_material_v2 *key_v2;
6178c2ecf20Sopenharmony_ci	int len;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	key_v2 = &resp->params.key_material_v2;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len);
6228c2ecf20Sopenharmony_ci	if (len > sizeof(key_v2->key_param_set.key_params.aes.key))
6238c2ecf20Sopenharmony_ci		return -EINVAL;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
6268c2ecf20Sopenharmony_ci		if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
6278c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
6288c2ecf20Sopenharmony_ci			priv->wpa_is_gtk_set = true;
6298c2ecf20Sopenharmony_ci			priv->scan_block = false;
6308c2ecf20Sopenharmony_ci			priv->port_open = true;
6318c2ecf20Sopenharmony_ci		}
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES)
6358c2ecf20Sopenharmony_ci		return 0;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
6388c2ecf20Sopenharmony_ci	       sizeof(key_v2->key_param_set.key_params.aes.key));
6398c2ecf20Sopenharmony_ci	priv->aes_key_v2.key_param_set.key_params.aes.key_len =
6408c2ecf20Sopenharmony_ci				cpu_to_le16(len);
6418c2ecf20Sopenharmony_ci	memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
6428c2ecf20Sopenharmony_ci	       key_v2->key_param_set.key_params.aes.key, len);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	return 0;
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci/* Wrapper function for processing response of key material command */
6488c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv,
6498c2ecf20Sopenharmony_ci					   struct host_cmd_ds_command *resp)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
6528c2ecf20Sopenharmony_ci		return mwifiex_ret_802_11_key_material_v2(priv, resp);
6538c2ecf20Sopenharmony_ci	else
6548c2ecf20Sopenharmony_ci		return mwifiex_ret_802_11_key_material_v1(priv, resp);
6558c2ecf20Sopenharmony_ci}
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci/*
6588c2ecf20Sopenharmony_ci * This function handles the command response of get 11d domain information.
6598c2ecf20Sopenharmony_ci */
6608c2ecf20Sopenharmony_cistatic int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
6618c2ecf20Sopenharmony_ci					   struct host_cmd_ds_command *resp)
6628c2ecf20Sopenharmony_ci{
6638c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
6648c2ecf20Sopenharmony_ci		&resp->params.domain_info_resp;
6658c2ecf20Sopenharmony_ci	struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain;
6668c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(domain_info->action);
6678c2ecf20Sopenharmony_ci	u8 no_of_triplet;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	no_of_triplet = (u8) ((le16_to_cpu(domain->header.len)
6708c2ecf20Sopenharmony_ci				- IEEE80211_COUNTRY_STRING_LEN)
6718c2ecf20Sopenharmony_ci			      / sizeof(struct ieee80211_country_ie_triplet));
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, INFO,
6748c2ecf20Sopenharmony_ci		    "info: 11D Domain Info Resp: no_of_triplet=%d\n",
6758c2ecf20Sopenharmony_ci		    no_of_triplet);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) {
6788c2ecf20Sopenharmony_ci		mwifiex_dbg(priv->adapter, FATAL,
6798c2ecf20Sopenharmony_ci			    "11D: invalid number of triplets %d returned\n",
6808c2ecf20Sopenharmony_ci			    no_of_triplet);
6818c2ecf20Sopenharmony_ci		return -1;
6828c2ecf20Sopenharmony_ci	}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	switch (action) {
6858c2ecf20Sopenharmony_ci	case HostCmd_ACT_GEN_SET:  /* Proc Set Action */
6868c2ecf20Sopenharmony_ci		break;
6878c2ecf20Sopenharmony_ci	case HostCmd_ACT_GEN_GET:
6888c2ecf20Sopenharmony_ci		break;
6898c2ecf20Sopenharmony_ci	default:
6908c2ecf20Sopenharmony_ci		mwifiex_dbg(priv->adapter, ERROR,
6918c2ecf20Sopenharmony_ci			    "11D: invalid action:%d\n", domain_info->action);
6928c2ecf20Sopenharmony_ci		return -1;
6938c2ecf20Sopenharmony_ci	}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	return 0;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci/*
6998c2ecf20Sopenharmony_ci * This function handles the command response of get extended version.
7008c2ecf20Sopenharmony_ci *
7018c2ecf20Sopenharmony_ci * Handling includes forming the extended version string and sending it
7028c2ecf20Sopenharmony_ci * to application.
7038c2ecf20Sopenharmony_ci */
7048c2ecf20Sopenharmony_cistatic int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
7058c2ecf20Sopenharmony_ci			       struct host_cmd_ds_command *resp,
7068c2ecf20Sopenharmony_ci			       struct host_cmd_ds_version_ext *version_ext)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	if (version_ext) {
7118c2ecf20Sopenharmony_ci		version_ext->version_str_sel = ver_ext->version_str_sel;
7128c2ecf20Sopenharmony_ci		memcpy(version_ext->version_str, ver_ext->version_str,
7138c2ecf20Sopenharmony_ci		       sizeof(char) * 128);
7148c2ecf20Sopenharmony_ci		memcpy(priv->version_str, ver_ext->version_str, 128);
7158c2ecf20Sopenharmony_ci	}
7168c2ecf20Sopenharmony_ci	return 0;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci/*
7208c2ecf20Sopenharmony_ci * This function handles the command response of remain on channel.
7218c2ecf20Sopenharmony_ci */
7228c2ecf20Sopenharmony_cistatic int
7238c2ecf20Sopenharmony_cimwifiex_ret_remain_on_chan(struct mwifiex_private *priv,
7248c2ecf20Sopenharmony_ci			   struct host_cmd_ds_command *resp,
7258c2ecf20Sopenharmony_ci			   struct host_cmd_ds_remain_on_chan *roc_cfg)
7268c2ecf20Sopenharmony_ci{
7278c2ecf20Sopenharmony_ci	struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	if (roc_cfg)
7308c2ecf20Sopenharmony_ci		memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	return 0;
7338c2ecf20Sopenharmony_ci}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci/*
7368c2ecf20Sopenharmony_ci * This function handles the command response of P2P mode cfg.
7378c2ecf20Sopenharmony_ci */
7388c2ecf20Sopenharmony_cistatic int
7398c2ecf20Sopenharmony_cimwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv,
7408c2ecf20Sopenharmony_ci			 struct host_cmd_ds_command *resp,
7418c2ecf20Sopenharmony_ci			 void *data_buf)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg;
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	if (data_buf)
7468c2ecf20Sopenharmony_ci		put_unaligned_le16(le16_to_cpu(mode_cfg->mode), data_buf);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	return 0;
7498c2ecf20Sopenharmony_ci}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci/* This function handles the command response of mem_access command
7528c2ecf20Sopenharmony_ci */
7538c2ecf20Sopenharmony_cistatic int
7548c2ecf20Sopenharmony_cimwifiex_ret_mem_access(struct mwifiex_private *priv,
7558c2ecf20Sopenharmony_ci		       struct host_cmd_ds_command *resp, void *pioctl_buf)
7568c2ecf20Sopenharmony_ci{
7578c2ecf20Sopenharmony_ci	struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	priv->mem_rw.addr = le32_to_cpu(mem->addr);
7608c2ecf20Sopenharmony_ci	priv->mem_rw.value = le32_to_cpu(mem->value);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci	return 0;
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci/*
7658c2ecf20Sopenharmony_ci * This function handles the command response of register access.
7668c2ecf20Sopenharmony_ci *
7678c2ecf20Sopenharmony_ci * The register value and offset are returned to the user. For EEPROM
7688c2ecf20Sopenharmony_ci * access, the byte count is also returned.
7698c2ecf20Sopenharmony_ci */
7708c2ecf20Sopenharmony_cistatic int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
7718c2ecf20Sopenharmony_ci				  void *data_buf)
7728c2ecf20Sopenharmony_ci{
7738c2ecf20Sopenharmony_ci	struct mwifiex_ds_reg_rw *reg_rw;
7748c2ecf20Sopenharmony_ci	struct mwifiex_ds_read_eeprom *eeprom;
7758c2ecf20Sopenharmony_ci	union reg {
7768c2ecf20Sopenharmony_ci		struct host_cmd_ds_mac_reg_access *mac;
7778c2ecf20Sopenharmony_ci		struct host_cmd_ds_bbp_reg_access *bbp;
7788c2ecf20Sopenharmony_ci		struct host_cmd_ds_rf_reg_access *rf;
7798c2ecf20Sopenharmony_ci		struct host_cmd_ds_pmic_reg_access *pmic;
7808c2ecf20Sopenharmony_ci		struct host_cmd_ds_802_11_eeprom_access *eeprom;
7818c2ecf20Sopenharmony_ci	} r;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	if (!data_buf)
7848c2ecf20Sopenharmony_ci		return 0;
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci	reg_rw = data_buf;
7878c2ecf20Sopenharmony_ci	eeprom = data_buf;
7888c2ecf20Sopenharmony_ci	switch (type) {
7898c2ecf20Sopenharmony_ci	case HostCmd_CMD_MAC_REG_ACCESS:
7908c2ecf20Sopenharmony_ci		r.mac = &resp->params.mac_reg;
7918c2ecf20Sopenharmony_ci		reg_rw->offset = (u32) le16_to_cpu(r.mac->offset);
7928c2ecf20Sopenharmony_ci		reg_rw->value = le32_to_cpu(r.mac->value);
7938c2ecf20Sopenharmony_ci		break;
7948c2ecf20Sopenharmony_ci	case HostCmd_CMD_BBP_REG_ACCESS:
7958c2ecf20Sopenharmony_ci		r.bbp = &resp->params.bbp_reg;
7968c2ecf20Sopenharmony_ci		reg_rw->offset = (u32) le16_to_cpu(r.bbp->offset);
7978c2ecf20Sopenharmony_ci		reg_rw->value = (u32) r.bbp->value;
7988c2ecf20Sopenharmony_ci		break;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	case HostCmd_CMD_RF_REG_ACCESS:
8018c2ecf20Sopenharmony_ci		r.rf = &resp->params.rf_reg;
8028c2ecf20Sopenharmony_ci		reg_rw->offset = (u32) le16_to_cpu(r.rf->offset);
8038c2ecf20Sopenharmony_ci		reg_rw->value = (u32) r.bbp->value;
8048c2ecf20Sopenharmony_ci		break;
8058c2ecf20Sopenharmony_ci	case HostCmd_CMD_PMIC_REG_ACCESS:
8068c2ecf20Sopenharmony_ci		r.pmic = &resp->params.pmic_reg;
8078c2ecf20Sopenharmony_ci		reg_rw->offset = (u32) le16_to_cpu(r.pmic->offset);
8088c2ecf20Sopenharmony_ci		reg_rw->value = (u32) r.pmic->value;
8098c2ecf20Sopenharmony_ci		break;
8108c2ecf20Sopenharmony_ci	case HostCmd_CMD_CAU_REG_ACCESS:
8118c2ecf20Sopenharmony_ci		r.rf = &resp->params.rf_reg;
8128c2ecf20Sopenharmony_ci		reg_rw->offset = (u32) le16_to_cpu(r.rf->offset);
8138c2ecf20Sopenharmony_ci		reg_rw->value = (u32) r.rf->value;
8148c2ecf20Sopenharmony_ci		break;
8158c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_EEPROM_ACCESS:
8168c2ecf20Sopenharmony_ci		r.eeprom = &resp->params.eeprom;
8178c2ecf20Sopenharmony_ci		pr_debug("info: EEPROM read len=%x\n",
8188c2ecf20Sopenharmony_ci				le16_to_cpu(r.eeprom->byte_count));
8198c2ecf20Sopenharmony_ci		if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) {
8208c2ecf20Sopenharmony_ci			eeprom->byte_count = 0;
8218c2ecf20Sopenharmony_ci			pr_debug("info: EEPROM read length is too big\n");
8228c2ecf20Sopenharmony_ci			return -1;
8238c2ecf20Sopenharmony_ci		}
8248c2ecf20Sopenharmony_ci		eeprom->offset = le16_to_cpu(r.eeprom->offset);
8258c2ecf20Sopenharmony_ci		eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count);
8268c2ecf20Sopenharmony_ci		if (eeprom->byte_count > 0)
8278c2ecf20Sopenharmony_ci			memcpy(&eeprom->value, &r.eeprom->value,
8288c2ecf20Sopenharmony_ci			       min((u16)MAX_EEPROM_DATA, eeprom->byte_count));
8298c2ecf20Sopenharmony_ci		break;
8308c2ecf20Sopenharmony_ci	default:
8318c2ecf20Sopenharmony_ci		return -1;
8328c2ecf20Sopenharmony_ci	}
8338c2ecf20Sopenharmony_ci	return 0;
8348c2ecf20Sopenharmony_ci}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci/*
8378c2ecf20Sopenharmony_ci * This function handles the command response of get IBSS coalescing status.
8388c2ecf20Sopenharmony_ci *
8398c2ecf20Sopenharmony_ci * If the received BSSID is different than the current one, the current BSSID,
8408c2ecf20Sopenharmony_ci * beacon interval, ATIM window and ERP information are updated, along with
8418c2ecf20Sopenharmony_ci * changing the ad-hoc state accordingly.
8428c2ecf20Sopenharmony_ci */
8438c2ecf20Sopenharmony_cistatic int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
8448c2ecf20Sopenharmony_ci					      struct host_cmd_ds_command *resp)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp =
8478c2ecf20Sopenharmony_ci					&(resp->params.ibss_coalescing);
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET)
8508c2ecf20Sopenharmony_ci		return 0;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, INFO,
8538c2ecf20Sopenharmony_ci		    "info: new BSSID %pM\n", ibss_coal_resp->bssid);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	/* If rsp has NULL BSSID, Just return..... No Action */
8568c2ecf20Sopenharmony_ci	if (is_zero_ether_addr(ibss_coal_resp->bssid)) {
8578c2ecf20Sopenharmony_ci		mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n");
8588c2ecf20Sopenharmony_ci		return 0;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci	/* If BSSID is diff, modify current BSS parameters */
8628c2ecf20Sopenharmony_ci	if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) {
8638c2ecf20Sopenharmony_ci		/* BSSID */
8648c2ecf20Sopenharmony_ci		memcpy(priv->curr_bss_params.bss_descriptor.mac_address,
8658c2ecf20Sopenharmony_ci		       ibss_coal_resp->bssid, ETH_ALEN);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci		/* Beacon Interval */
8688c2ecf20Sopenharmony_ci		priv->curr_bss_params.bss_descriptor.beacon_period
8698c2ecf20Sopenharmony_ci			= le16_to_cpu(ibss_coal_resp->beacon_interval);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci		/* ERP Information */
8728c2ecf20Sopenharmony_ci		priv->curr_bss_params.bss_descriptor.erp_flags =
8738c2ecf20Sopenharmony_ci			(u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect);
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci		priv->adhoc_state = ADHOC_COALESCED;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	return 0;
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_cistatic int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
8818c2ecf20Sopenharmony_ci				 struct host_cmd_ds_command *resp)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper;
8848c2ecf20Sopenharmony_ci	u16 reason = le16_to_cpu(cmd_tdls_oper->reason);
8858c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action);
8868c2ecf20Sopenharmony_ci	struct mwifiex_sta_node *node =
8878c2ecf20Sopenharmony_ci			   mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac);
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	switch (action) {
8908c2ecf20Sopenharmony_ci	case ACT_TDLS_DELETE:
8918c2ecf20Sopenharmony_ci		if (reason) {
8928c2ecf20Sopenharmony_ci			if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
8938c2ecf20Sopenharmony_ci				mwifiex_dbg(priv->adapter, MSG,
8948c2ecf20Sopenharmony_ci					    "TDLS link delete for %pM failed: reason %d\n",
8958c2ecf20Sopenharmony_ci					    cmd_tdls_oper->peer_mac, reason);
8968c2ecf20Sopenharmony_ci			else
8978c2ecf20Sopenharmony_ci				mwifiex_dbg(priv->adapter, ERROR,
8988c2ecf20Sopenharmony_ci					    "TDLS link delete for %pM failed: reason %d\n",
8998c2ecf20Sopenharmony_ci					    cmd_tdls_oper->peer_mac, reason);
9008c2ecf20Sopenharmony_ci		} else {
9018c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, MSG,
9028c2ecf20Sopenharmony_ci				    "TDLS link delete for %pM successful\n",
9038c2ecf20Sopenharmony_ci				    cmd_tdls_oper->peer_mac);
9048c2ecf20Sopenharmony_ci		}
9058c2ecf20Sopenharmony_ci		break;
9068c2ecf20Sopenharmony_ci	case ACT_TDLS_CREATE:
9078c2ecf20Sopenharmony_ci		if (reason) {
9088c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, ERROR,
9098c2ecf20Sopenharmony_ci				    "TDLS link creation for %pM failed: reason %d",
9108c2ecf20Sopenharmony_ci				    cmd_tdls_oper->peer_mac, reason);
9118c2ecf20Sopenharmony_ci			if (node && reason != TDLS_ERR_LINK_EXISTS)
9128c2ecf20Sopenharmony_ci				node->tdls_status = TDLS_SETUP_FAILURE;
9138c2ecf20Sopenharmony_ci		} else {
9148c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, MSG,
9158c2ecf20Sopenharmony_ci				    "TDLS link creation for %pM successful",
9168c2ecf20Sopenharmony_ci				    cmd_tdls_oper->peer_mac);
9178c2ecf20Sopenharmony_ci		}
9188c2ecf20Sopenharmony_ci		break;
9198c2ecf20Sopenharmony_ci	case ACT_TDLS_CONFIG:
9208c2ecf20Sopenharmony_ci		if (reason) {
9218c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, ERROR,
9228c2ecf20Sopenharmony_ci				    "TDLS link config for %pM failed, reason %d\n",
9238c2ecf20Sopenharmony_ci				    cmd_tdls_oper->peer_mac, reason);
9248c2ecf20Sopenharmony_ci			if (node)
9258c2ecf20Sopenharmony_ci				node->tdls_status = TDLS_SETUP_FAILURE;
9268c2ecf20Sopenharmony_ci		} else {
9278c2ecf20Sopenharmony_ci			mwifiex_dbg(priv->adapter, MSG,
9288c2ecf20Sopenharmony_ci				    "TDLS link config for %pM successful\n",
9298c2ecf20Sopenharmony_ci				    cmd_tdls_oper->peer_mac);
9308c2ecf20Sopenharmony_ci		}
9318c2ecf20Sopenharmony_ci		break;
9328c2ecf20Sopenharmony_ci	default:
9338c2ecf20Sopenharmony_ci		mwifiex_dbg(priv->adapter, ERROR,
9348c2ecf20Sopenharmony_ci			    "Unknown TDLS command action response %d", action);
9358c2ecf20Sopenharmony_ci		return -1;
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	return 0;
9398c2ecf20Sopenharmony_ci}
9408c2ecf20Sopenharmony_ci/*
9418c2ecf20Sopenharmony_ci * This function handles the command response for subscribe event command.
9428c2ecf20Sopenharmony_ci */
9438c2ecf20Sopenharmony_cistatic int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
9448c2ecf20Sopenharmony_ci				 struct host_cmd_ds_command *resp)
9458c2ecf20Sopenharmony_ci{
9468c2ecf20Sopenharmony_ci	struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
9478c2ecf20Sopenharmony_ci		&resp->params.subsc_evt;
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci	/* For every subscribe event command (Get/Set/Clear), FW reports the
9508c2ecf20Sopenharmony_ci	 * current set of subscribed events*/
9518c2ecf20Sopenharmony_ci	mwifiex_dbg(priv->adapter, EVENT,
9528c2ecf20Sopenharmony_ci		    "Bitmap of currently subscribed events: %16x\n",
9538c2ecf20Sopenharmony_ci		    le16_to_cpu(cmd_sub_event->events));
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	return 0;
9568c2ecf20Sopenharmony_ci}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_cistatic int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv,
9598c2ecf20Sopenharmony_ci				    struct host_cmd_ds_command *resp)
9608c2ecf20Sopenharmony_ci{
9618c2ecf20Sopenharmony_ci	struct host_cmd_ds_sta_list *sta_list =
9628c2ecf20Sopenharmony_ci		&resp->params.sta_list;
9638c2ecf20Sopenharmony_ci	struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv;
9648c2ecf20Sopenharmony_ci	int i;
9658c2ecf20Sopenharmony_ci	struct mwifiex_sta_node *sta_node;
9668c2ecf20Sopenharmony_ci
9678c2ecf20Sopenharmony_ci	for (i = 0; i < (le16_to_cpu(sta_list->sta_count)); i++) {
9688c2ecf20Sopenharmony_ci		sta_node = mwifiex_get_sta_entry(priv, sta_info->mac);
9698c2ecf20Sopenharmony_ci		if (unlikely(!sta_node))
9708c2ecf20Sopenharmony_ci			continue;
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci		sta_node->stats.rssi = sta_info->rssi;
9738c2ecf20Sopenharmony_ci		sta_info++;
9748c2ecf20Sopenharmony_ci	}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	return 0;
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci/* This function handles the command response of set_cfg_data */
9808c2ecf20Sopenharmony_cistatic int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
9818c2ecf20Sopenharmony_ci				struct host_cmd_ds_command *resp)
9828c2ecf20Sopenharmony_ci{
9838c2ecf20Sopenharmony_ci	if (resp->result != HostCmd_RESULT_OK) {
9848c2ecf20Sopenharmony_ci		mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
9858c2ecf20Sopenharmony_ci		return -1;
9868c2ecf20Sopenharmony_ci	}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	return 0;
9898c2ecf20Sopenharmony_ci}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci/** This Function handles the command response of sdio rx aggr */
9928c2ecf20Sopenharmony_cistatic int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv,
9938c2ecf20Sopenharmony_ci					struct host_cmd_ds_command *resp)
9948c2ecf20Sopenharmony_ci{
9958c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
9968c2ecf20Sopenharmony_ci	struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
9978c2ecf20Sopenharmony_ci				&resp->params.sdio_rx_aggr_cfg;
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	adapter->sdio_rx_aggr_enable = cfg->enable;
10008c2ecf20Sopenharmony_ci	adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	return 0;
10038c2ecf20Sopenharmony_ci}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_cistatic int mwifiex_ret_robust_coex(struct mwifiex_private *priv,
10068c2ecf20Sopenharmony_ci				   struct host_cmd_ds_command *resp,
10078c2ecf20Sopenharmony_ci				   bool *is_timeshare)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
10108c2ecf20Sopenharmony_ci	struct mwifiex_ie_types_robust_coex *coex_tlv;
10118c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(coex->action);
10128c2ecf20Sopenharmony_ci	u32 mode;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	coex_tlv = (struct mwifiex_ie_types_robust_coex
10158c2ecf20Sopenharmony_ci		    *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
10168c2ecf20Sopenharmony_ci	if (action == HostCmd_ACT_GEN_GET) {
10178c2ecf20Sopenharmony_ci		mode = le32_to_cpu(coex_tlv->mode);
10188c2ecf20Sopenharmony_ci		if (mode == MWIFIEX_COEX_MODE_TIMESHARE)
10198c2ecf20Sopenharmony_ci			*is_timeshare = true;
10208c2ecf20Sopenharmony_ci		else
10218c2ecf20Sopenharmony_ci			*is_timeshare = false;
10228c2ecf20Sopenharmony_ci	}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	return 0;
10258c2ecf20Sopenharmony_ci}
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_cistatic struct ieee80211_regdomain *
10288c2ecf20Sopenharmony_cimwifiex_create_custom_regdomain(struct mwifiex_private *priv,
10298c2ecf20Sopenharmony_ci				u8 *buf, u16 buf_len)
10308c2ecf20Sopenharmony_ci{
10318c2ecf20Sopenharmony_ci	u16 num_chan = buf_len / 2;
10328c2ecf20Sopenharmony_ci	struct ieee80211_regdomain *regd;
10338c2ecf20Sopenharmony_ci	struct ieee80211_reg_rule *rule;
10348c2ecf20Sopenharmony_ci	bool new_rule;
10358c2ecf20Sopenharmony_ci	int idx, freq, prev_freq = 0;
10368c2ecf20Sopenharmony_ci	u32 bw, prev_bw = 0;
10378c2ecf20Sopenharmony_ci	u8 chflags, prev_chflags = 0, valid_rules = 0;
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci	if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
10408c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	regd = kzalloc(struct_size(regd, reg_rules, num_chan), GFP_KERNEL);
10438c2ecf20Sopenharmony_ci	if (!regd)
10448c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	for (idx = 0; idx < num_chan; idx++) {
10478c2ecf20Sopenharmony_ci		u8 chan;
10488c2ecf20Sopenharmony_ci		enum nl80211_band band;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci		chan = *buf++;
10518c2ecf20Sopenharmony_ci		if (!chan) {
10528c2ecf20Sopenharmony_ci			kfree(regd);
10538c2ecf20Sopenharmony_ci			return NULL;
10548c2ecf20Sopenharmony_ci		}
10558c2ecf20Sopenharmony_ci		chflags = *buf++;
10568c2ecf20Sopenharmony_ci		band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
10578c2ecf20Sopenharmony_ci		freq = ieee80211_channel_to_frequency(chan, band);
10588c2ecf20Sopenharmony_ci		new_rule = false;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci		if (chflags & MWIFIEX_CHANNEL_DISABLED)
10618c2ecf20Sopenharmony_ci			continue;
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci		if (band == NL80211_BAND_5GHZ) {
10648c2ecf20Sopenharmony_ci			if (!(chflags & MWIFIEX_CHANNEL_NOHT80))
10658c2ecf20Sopenharmony_ci				bw = MHZ_TO_KHZ(80);
10668c2ecf20Sopenharmony_ci			else if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
10678c2ecf20Sopenharmony_ci				bw = MHZ_TO_KHZ(40);
10688c2ecf20Sopenharmony_ci			else
10698c2ecf20Sopenharmony_ci				bw = MHZ_TO_KHZ(20);
10708c2ecf20Sopenharmony_ci		} else {
10718c2ecf20Sopenharmony_ci			if (!(chflags & MWIFIEX_CHANNEL_NOHT40))
10728c2ecf20Sopenharmony_ci				bw = MHZ_TO_KHZ(40);
10738c2ecf20Sopenharmony_ci			else
10748c2ecf20Sopenharmony_ci				bw = MHZ_TO_KHZ(20);
10758c2ecf20Sopenharmony_ci		}
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci		if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
10788c2ecf20Sopenharmony_ci		    freq - prev_freq > 20) {
10798c2ecf20Sopenharmony_ci			valid_rules++;
10808c2ecf20Sopenharmony_ci			new_rule = true;
10818c2ecf20Sopenharmony_ci		}
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci		rule = &regd->reg_rules[valid_rules - 1];
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci		rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci		prev_chflags = chflags;
10888c2ecf20Sopenharmony_ci		prev_freq = freq;
10898c2ecf20Sopenharmony_ci		prev_bw = bw;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		if (!new_rule)
10928c2ecf20Sopenharmony_ci			continue;
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci		rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
10958c2ecf20Sopenharmony_ci		rule->power_rule.max_eirp = DBM_TO_MBM(19);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ci		if (chflags & MWIFIEX_CHANNEL_PASSIVE)
10988c2ecf20Sopenharmony_ci			rule->flags = NL80211_RRF_NO_IR;
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci		if (chflags & MWIFIEX_CHANNEL_DFS)
11018c2ecf20Sopenharmony_ci			rule->flags = NL80211_RRF_DFS;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci		rule->freq_range.max_bandwidth_khz = bw;
11048c2ecf20Sopenharmony_ci	}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	regd->n_reg_rules = valid_rules;
11078c2ecf20Sopenharmony_ci	regd->alpha2[0] = '9';
11088c2ecf20Sopenharmony_ci	regd->alpha2[1] = '9';
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	return regd;
11118c2ecf20Sopenharmony_ci}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_cistatic int mwifiex_ret_chan_region_cfg(struct mwifiex_private *priv,
11148c2ecf20Sopenharmony_ci				       struct host_cmd_ds_command *resp)
11158c2ecf20Sopenharmony_ci{
11168c2ecf20Sopenharmony_ci	struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg;
11178c2ecf20Sopenharmony_ci	u16 action = le16_to_cpu(reg->action);
11188c2ecf20Sopenharmony_ci	u16 tlv, tlv_buf_len, tlv_buf_left;
11198c2ecf20Sopenharmony_ci	struct mwifiex_ie_types_header *head;
11208c2ecf20Sopenharmony_ci	struct ieee80211_regdomain *regd;
11218c2ecf20Sopenharmony_ci	u8 *tlv_buf;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	if (action != HostCmd_ACT_GEN_GET)
11248c2ecf20Sopenharmony_ci		return 0;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	tlv_buf = (u8 *)reg + sizeof(*reg);
11278c2ecf20Sopenharmony_ci	tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	while (tlv_buf_left >= sizeof(*head)) {
11308c2ecf20Sopenharmony_ci		head = (struct mwifiex_ie_types_header *)tlv_buf;
11318c2ecf20Sopenharmony_ci		tlv = le16_to_cpu(head->type);
11328c2ecf20Sopenharmony_ci		tlv_buf_len = le16_to_cpu(head->len);
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci		if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
11358c2ecf20Sopenharmony_ci			break;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		switch (tlv) {
11388c2ecf20Sopenharmony_ci		case TLV_TYPE_CHAN_ATTR_CFG:
11398c2ecf20Sopenharmony_ci			mwifiex_dbg_dump(priv->adapter, CMD_D, "CHAN:",
11408c2ecf20Sopenharmony_ci					 (u8 *)head + sizeof(*head),
11418c2ecf20Sopenharmony_ci					 tlv_buf_len);
11428c2ecf20Sopenharmony_ci			regd = mwifiex_create_custom_regdomain(priv,
11438c2ecf20Sopenharmony_ci				(u8 *)head + sizeof(*head), tlv_buf_len);
11448c2ecf20Sopenharmony_ci			if (!IS_ERR(regd))
11458c2ecf20Sopenharmony_ci				priv->adapter->regd = regd;
11468c2ecf20Sopenharmony_ci			break;
11478c2ecf20Sopenharmony_ci		}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci		tlv_buf += (sizeof(*head) + tlv_buf_len);
11508c2ecf20Sopenharmony_ci		tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
11518c2ecf20Sopenharmony_ci	}
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	return 0;
11548c2ecf20Sopenharmony_ci}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_cistatic int mwifiex_ret_pkt_aggr_ctrl(struct mwifiex_private *priv,
11578c2ecf20Sopenharmony_ci				     struct host_cmd_ds_command *resp)
11588c2ecf20Sopenharmony_ci{
11598c2ecf20Sopenharmony_ci	struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
11608c2ecf20Sopenharmony_ci					&resp->params.pkt_aggr_ctrl;
11618c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
11648c2ecf20Sopenharmony_ci	if (adapter->bus_aggr.enable)
11658c2ecf20Sopenharmony_ci		adapter->intf_hdr_len = INTF_HEADER_LEN;
11668c2ecf20Sopenharmony_ci	adapter->bus_aggr.mode = MWIFIEX_BUS_AGGR_MODE_LEN_V2;
11678c2ecf20Sopenharmony_ci	adapter->bus_aggr.tx_aggr_max_size =
11688c2ecf20Sopenharmony_ci				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
11698c2ecf20Sopenharmony_ci	adapter->bus_aggr.tx_aggr_max_num =
11708c2ecf20Sopenharmony_ci				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
11718c2ecf20Sopenharmony_ci	adapter->bus_aggr.tx_aggr_align =
11728c2ecf20Sopenharmony_ci				le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	return 0;
11758c2ecf20Sopenharmony_ci}
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_cistatic int mwifiex_ret_get_chan_info(struct mwifiex_private *priv,
11788c2ecf20Sopenharmony_ci				     struct host_cmd_ds_command *resp,
11798c2ecf20Sopenharmony_ci				     struct mwifiex_channel_band *channel_band)
11808c2ecf20Sopenharmony_ci{
11818c2ecf20Sopenharmony_ci	struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg;
11828c2ecf20Sopenharmony_ci	struct host_cmd_tlv_channel_band *tlv_band_channel;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	tlv_band_channel =
11858c2ecf20Sopenharmony_ci	(struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
11868c2ecf20Sopenharmony_ci	memcpy(&channel_band->band_config, &tlv_band_channel->band_config,
11878c2ecf20Sopenharmony_ci	       sizeof(struct mwifiex_band_config));
11888c2ecf20Sopenharmony_ci	channel_band->channel = tlv_band_channel->channel;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	return 0;
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci/*
11948c2ecf20Sopenharmony_ci * This function handles the command responses.
11958c2ecf20Sopenharmony_ci *
11968c2ecf20Sopenharmony_ci * This is a generic function, which calls command specific
11978c2ecf20Sopenharmony_ci * response handlers based on the command ID.
11988c2ecf20Sopenharmony_ci */
11998c2ecf20Sopenharmony_ciint mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
12008c2ecf20Sopenharmony_ci				struct host_cmd_ds_command *resp)
12018c2ecf20Sopenharmony_ci{
12028c2ecf20Sopenharmony_ci	int ret = 0;
12038c2ecf20Sopenharmony_ci	struct mwifiex_adapter *adapter = priv->adapter;
12048c2ecf20Sopenharmony_ci	void *data_buf = adapter->curr_cmd->data_buf;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	/* If the command is not successful, cleanup and return failure */
12078c2ecf20Sopenharmony_ci	if (resp->result != HostCmd_RESULT_OK) {
12088c2ecf20Sopenharmony_ci		mwifiex_process_cmdresp_error(priv, resp);
12098c2ecf20Sopenharmony_ci		return -1;
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci	/* Command successful, handle response */
12128c2ecf20Sopenharmony_ci	switch (cmdresp_no) {
12138c2ecf20Sopenharmony_ci	case HostCmd_CMD_GET_HW_SPEC:
12148c2ecf20Sopenharmony_ci		ret = mwifiex_ret_get_hw_spec(priv, resp);
12158c2ecf20Sopenharmony_ci		break;
12168c2ecf20Sopenharmony_ci	case HostCmd_CMD_CFG_DATA:
12178c2ecf20Sopenharmony_ci		ret = mwifiex_ret_cfg_data(priv, resp);
12188c2ecf20Sopenharmony_ci		break;
12198c2ecf20Sopenharmony_ci	case HostCmd_CMD_MAC_CONTROL:
12208c2ecf20Sopenharmony_ci		break;
12218c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_MAC_ADDRESS:
12228c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_mac_address(priv, resp);
12238c2ecf20Sopenharmony_ci		break;
12248c2ecf20Sopenharmony_ci	case HostCmd_CMD_MAC_MULTICAST_ADR:
12258c2ecf20Sopenharmony_ci		ret = mwifiex_ret_mac_multicast_adr(priv, resp);
12268c2ecf20Sopenharmony_ci		break;
12278c2ecf20Sopenharmony_ci	case HostCmd_CMD_TX_RATE_CFG:
12288c2ecf20Sopenharmony_ci		ret = mwifiex_ret_tx_rate_cfg(priv, resp);
12298c2ecf20Sopenharmony_ci		break;
12308c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SCAN:
12318c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_scan(priv, resp);
12328c2ecf20Sopenharmony_ci		adapter->curr_cmd->wait_q_enabled = false;
12338c2ecf20Sopenharmony_ci		break;
12348c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SCAN_EXT:
12358c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_scan_ext(priv, resp);
12368c2ecf20Sopenharmony_ci		adapter->curr_cmd->wait_q_enabled = false;
12378c2ecf20Sopenharmony_ci		break;
12388c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_BG_SCAN_QUERY:
12398c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_scan(priv, resp);
12408c2ecf20Sopenharmony_ci		cfg80211_sched_scan_results(priv->wdev.wiphy, 0);
12418c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, CMD,
12428c2ecf20Sopenharmony_ci			    "info: CMD_RESP: BG_SCAN result is ready!\n");
12438c2ecf20Sopenharmony_ci		break;
12448c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_BG_SCAN_CONFIG:
12458c2ecf20Sopenharmony_ci		break;
12468c2ecf20Sopenharmony_ci	case HostCmd_CMD_TXPWR_CFG:
12478c2ecf20Sopenharmony_ci		ret = mwifiex_ret_tx_power_cfg(priv, resp);
12488c2ecf20Sopenharmony_ci		break;
12498c2ecf20Sopenharmony_ci	case HostCmd_CMD_RF_TX_PWR:
12508c2ecf20Sopenharmony_ci		ret = mwifiex_ret_rf_tx_power(priv, resp);
12518c2ecf20Sopenharmony_ci		break;
12528c2ecf20Sopenharmony_ci	case HostCmd_CMD_RF_ANTENNA:
12538c2ecf20Sopenharmony_ci		ret = mwifiex_ret_rf_antenna(priv, resp);
12548c2ecf20Sopenharmony_ci		break;
12558c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_PS_MODE_ENH:
12568c2ecf20Sopenharmony_ci		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
12578c2ecf20Sopenharmony_ci		break;
12588c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_HS_CFG_ENH:
12598c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_hs_cfg(priv, resp);
12608c2ecf20Sopenharmony_ci		break;
12618c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_ASSOCIATE:
12628c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_associate(priv, resp);
12638c2ecf20Sopenharmony_ci		break;
12648c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_DEAUTHENTICATE:
12658c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_deauthenticate(priv, resp);
12668c2ecf20Sopenharmony_ci		break;
12678c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_AD_HOC_START:
12688c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_AD_HOC_JOIN:
12698c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_ad_hoc(priv, resp);
12708c2ecf20Sopenharmony_ci		break;
12718c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_AD_HOC_STOP:
12728c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp);
12738c2ecf20Sopenharmony_ci		break;
12748c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_GET_LOG:
12758c2ecf20Sopenharmony_ci		ret = mwifiex_ret_get_log(priv, resp, data_buf);
12768c2ecf20Sopenharmony_ci		break;
12778c2ecf20Sopenharmony_ci	case HostCmd_CMD_RSSI_INFO:
12788c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_rssi_info(priv, resp);
12798c2ecf20Sopenharmony_ci		break;
12808c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SNMP_MIB:
12818c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf);
12828c2ecf20Sopenharmony_ci		break;
12838c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_TX_RATE_QUERY:
12848c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
12858c2ecf20Sopenharmony_ci		break;
12868c2ecf20Sopenharmony_ci	case HostCmd_CMD_VERSION_EXT:
12878c2ecf20Sopenharmony_ci		ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
12888c2ecf20Sopenharmony_ci		break;
12898c2ecf20Sopenharmony_ci	case HostCmd_CMD_REMAIN_ON_CHAN:
12908c2ecf20Sopenharmony_ci		ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf);
12918c2ecf20Sopenharmony_ci		break;
12928c2ecf20Sopenharmony_ci	case HostCmd_CMD_11AC_CFG:
12938c2ecf20Sopenharmony_ci		break;
12948c2ecf20Sopenharmony_ci	case HostCmd_CMD_PACKET_AGGR_CTRL:
12958c2ecf20Sopenharmony_ci		ret = mwifiex_ret_pkt_aggr_ctrl(priv, resp);
12968c2ecf20Sopenharmony_ci		break;
12978c2ecf20Sopenharmony_ci	case HostCmd_CMD_P2P_MODE_CFG:
12988c2ecf20Sopenharmony_ci		ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf);
12998c2ecf20Sopenharmony_ci		break;
13008c2ecf20Sopenharmony_ci	case HostCmd_CMD_MGMT_FRAME_REG:
13018c2ecf20Sopenharmony_ci	case HostCmd_CMD_FUNC_INIT:
13028c2ecf20Sopenharmony_ci	case HostCmd_CMD_FUNC_SHUTDOWN:
13038c2ecf20Sopenharmony_ci		break;
13048c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_KEY_MATERIAL:
13058c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11_key_material(priv, resp);
13068c2ecf20Sopenharmony_ci		break;
13078c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11D_DOMAIN_INFO:
13088c2ecf20Sopenharmony_ci		ret = mwifiex_ret_802_11d_domain_info(priv, resp);
13098c2ecf20Sopenharmony_ci		break;
13108c2ecf20Sopenharmony_ci	case HostCmd_CMD_11N_ADDBA_REQ:
13118c2ecf20Sopenharmony_ci		ret = mwifiex_ret_11n_addba_req(priv, resp);
13128c2ecf20Sopenharmony_ci		break;
13138c2ecf20Sopenharmony_ci	case HostCmd_CMD_11N_DELBA:
13148c2ecf20Sopenharmony_ci		ret = mwifiex_ret_11n_delba(priv, resp);
13158c2ecf20Sopenharmony_ci		break;
13168c2ecf20Sopenharmony_ci	case HostCmd_CMD_11N_ADDBA_RSP:
13178c2ecf20Sopenharmony_ci		ret = mwifiex_ret_11n_addba_resp(priv, resp);
13188c2ecf20Sopenharmony_ci		break;
13198c2ecf20Sopenharmony_ci	case HostCmd_CMD_RECONFIGURE_TX_BUFF:
13208c2ecf20Sopenharmony_ci		if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
13218c2ecf20Sopenharmony_ci			if (adapter->iface_type == MWIFIEX_USB &&
13228c2ecf20Sopenharmony_ci			    adapter->usb_mc_setup) {
13238c2ecf20Sopenharmony_ci				if (adapter->if_ops.multi_port_resync)
13248c2ecf20Sopenharmony_ci					adapter->if_ops.
13258c2ecf20Sopenharmony_ci						multi_port_resync(adapter);
13268c2ecf20Sopenharmony_ci				adapter->usb_mc_setup = false;
13278c2ecf20Sopenharmony_ci				adapter->tx_lock_flag = false;
13288c2ecf20Sopenharmony_ci			}
13298c2ecf20Sopenharmony_ci			break;
13308c2ecf20Sopenharmony_ci		}
13318c2ecf20Sopenharmony_ci		adapter->tx_buf_size = (u16) le16_to_cpu(resp->params.
13328c2ecf20Sopenharmony_ci							     tx_buf.buff_size);
13338c2ecf20Sopenharmony_ci		adapter->tx_buf_size = (adapter->tx_buf_size
13348c2ecf20Sopenharmony_ci					/ MWIFIEX_SDIO_BLOCK_SIZE)
13358c2ecf20Sopenharmony_ci				       * MWIFIEX_SDIO_BLOCK_SIZE;
13368c2ecf20Sopenharmony_ci		adapter->curr_tx_buf_size = adapter->tx_buf_size;
13378c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
13388c2ecf20Sopenharmony_ci			    adapter->curr_tx_buf_size);
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci		if (adapter->if_ops.update_mp_end_port)
13418c2ecf20Sopenharmony_ci			adapter->if_ops.update_mp_end_port(adapter,
13428c2ecf20Sopenharmony_ci				le16_to_cpu(resp->params.tx_buf.mp_end_port));
13438c2ecf20Sopenharmony_ci		break;
13448c2ecf20Sopenharmony_ci	case HostCmd_CMD_AMSDU_AGGR_CTRL:
13458c2ecf20Sopenharmony_ci		break;
13468c2ecf20Sopenharmony_ci	case HostCmd_CMD_WMM_GET_STATUS:
13478c2ecf20Sopenharmony_ci		ret = mwifiex_ret_wmm_get_status(priv, resp);
13488c2ecf20Sopenharmony_ci		break;
13498c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS:
13508c2ecf20Sopenharmony_ci		ret = mwifiex_ret_ibss_coalescing_status(priv, resp);
13518c2ecf20Sopenharmony_ci		break;
13528c2ecf20Sopenharmony_ci	case HostCmd_CMD_MEM_ACCESS:
13538c2ecf20Sopenharmony_ci		ret = mwifiex_ret_mem_access(priv, resp, data_buf);
13548c2ecf20Sopenharmony_ci		break;
13558c2ecf20Sopenharmony_ci	case HostCmd_CMD_MAC_REG_ACCESS:
13568c2ecf20Sopenharmony_ci	case HostCmd_CMD_BBP_REG_ACCESS:
13578c2ecf20Sopenharmony_ci	case HostCmd_CMD_RF_REG_ACCESS:
13588c2ecf20Sopenharmony_ci	case HostCmd_CMD_PMIC_REG_ACCESS:
13598c2ecf20Sopenharmony_ci	case HostCmd_CMD_CAU_REG_ACCESS:
13608c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_EEPROM_ACCESS:
13618c2ecf20Sopenharmony_ci		ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf);
13628c2ecf20Sopenharmony_ci		break;
13638c2ecf20Sopenharmony_ci	case HostCmd_CMD_SET_BSS_MODE:
13648c2ecf20Sopenharmony_ci		break;
13658c2ecf20Sopenharmony_ci	case HostCmd_CMD_11N_CFG:
13668c2ecf20Sopenharmony_ci		break;
13678c2ecf20Sopenharmony_ci	case HostCmd_CMD_PCIE_DESC_DETAILS:
13688c2ecf20Sopenharmony_ci		break;
13698c2ecf20Sopenharmony_ci	case HostCmd_CMD_802_11_SUBSCRIBE_EVENT:
13708c2ecf20Sopenharmony_ci		ret = mwifiex_ret_subsc_evt(priv, resp);
13718c2ecf20Sopenharmony_ci		break;
13728c2ecf20Sopenharmony_ci	case HostCmd_CMD_UAP_SYS_CONFIG:
13738c2ecf20Sopenharmony_ci		break;
13748c2ecf20Sopenharmony_ci	case HOST_CMD_APCMD_STA_LIST:
13758c2ecf20Sopenharmony_ci		ret = mwifiex_ret_uap_sta_list(priv, resp);
13768c2ecf20Sopenharmony_ci		break;
13778c2ecf20Sopenharmony_ci	case HostCmd_CMD_UAP_BSS_START:
13788c2ecf20Sopenharmony_ci		adapter->tx_lock_flag = false;
13798c2ecf20Sopenharmony_ci		adapter->pps_uapsd_mode = false;
13808c2ecf20Sopenharmony_ci		adapter->delay_null_pkt = false;
13818c2ecf20Sopenharmony_ci		priv->bss_started = 1;
13828c2ecf20Sopenharmony_ci		break;
13838c2ecf20Sopenharmony_ci	case HostCmd_CMD_UAP_BSS_STOP:
13848c2ecf20Sopenharmony_ci		priv->bss_started = 0;
13858c2ecf20Sopenharmony_ci		break;
13868c2ecf20Sopenharmony_ci	case HostCmd_CMD_UAP_STA_DEAUTH:
13878c2ecf20Sopenharmony_ci		break;
13888c2ecf20Sopenharmony_ci	case HOST_CMD_APCMD_SYS_RESET:
13898c2ecf20Sopenharmony_ci		break;
13908c2ecf20Sopenharmony_ci	case HostCmd_CMD_MEF_CFG:
13918c2ecf20Sopenharmony_ci		break;
13928c2ecf20Sopenharmony_ci	case HostCmd_CMD_COALESCE_CFG:
13938c2ecf20Sopenharmony_ci		break;
13948c2ecf20Sopenharmony_ci	case HostCmd_CMD_TDLS_OPER:
13958c2ecf20Sopenharmony_ci		ret = mwifiex_ret_tdls_oper(priv, resp);
13968c2ecf20Sopenharmony_ci	case HostCmd_CMD_MC_POLICY:
13978c2ecf20Sopenharmony_ci		break;
13988c2ecf20Sopenharmony_ci	case HostCmd_CMD_CHAN_REPORT_REQUEST:
13998c2ecf20Sopenharmony_ci		break;
14008c2ecf20Sopenharmony_ci	case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
14018c2ecf20Sopenharmony_ci		ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
14028c2ecf20Sopenharmony_ci		break;
14038c2ecf20Sopenharmony_ci	case HostCmd_CMD_HS_WAKEUP_REASON:
14048c2ecf20Sopenharmony_ci		ret = mwifiex_ret_wakeup_reason(priv, resp, data_buf);
14058c2ecf20Sopenharmony_ci		break;
14068c2ecf20Sopenharmony_ci	case HostCmd_CMD_TDLS_CONFIG:
14078c2ecf20Sopenharmony_ci		break;
14088c2ecf20Sopenharmony_ci	case HostCmd_CMD_ROBUST_COEX:
14098c2ecf20Sopenharmony_ci		ret = mwifiex_ret_robust_coex(priv, resp, data_buf);
14108c2ecf20Sopenharmony_ci		break;
14118c2ecf20Sopenharmony_ci	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
14128c2ecf20Sopenharmony_ci		break;
14138c2ecf20Sopenharmony_ci	case HostCmd_CMD_CHAN_REGION_CFG:
14148c2ecf20Sopenharmony_ci		ret = mwifiex_ret_chan_region_cfg(priv, resp);
14158c2ecf20Sopenharmony_ci		break;
14168c2ecf20Sopenharmony_ci	case HostCmd_CMD_STA_CONFIGURE:
14178c2ecf20Sopenharmony_ci		ret = mwifiex_ret_get_chan_info(priv, resp, data_buf);
14188c2ecf20Sopenharmony_ci		break;
14198c2ecf20Sopenharmony_ci	default:
14208c2ecf20Sopenharmony_ci		mwifiex_dbg(adapter, ERROR,
14218c2ecf20Sopenharmony_ci			    "CMD_RESP: unknown cmd response %#x\n",
14228c2ecf20Sopenharmony_ci			    resp->command);
14238c2ecf20Sopenharmony_ci		break;
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	return ret;
14278c2ecf20Sopenharmony_ci}
1428