173b01e57SJeff Chen // SPDX-License-Identifier: GPL-2.0-only
273b01e57SJeff Chen /*
373b01e57SJeff Chen * nxpwifi: station command handling
473b01e57SJeff Chen *
573b01e57SJeff Chen * Copyright 2011-2024 NXP
673b01e57SJeff Chen */
773b01e57SJeff Chen
873b01e57SJeff Chen #include "cfg.h"
973b01e57SJeff Chen #include "util.h"
1073b01e57SJeff Chen #include "fw.h"
1173b01e57SJeff Chen #include "main.h"
1273b01e57SJeff Chen #include "cmdevt.h"
1373b01e57SJeff Chen #include "wmm.h"
1473b01e57SJeff Chen #include "11n.h"
1573b01e57SJeff Chen #include "11ac.h"
1673b01e57SJeff Chen #include "11ax.h"
1773b01e57SJeff Chen
1873b01e57SJeff Chen static bool disable_auto_ds;
1973b01e57SJeff Chen
2073b01e57SJeff Chen static int
nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)2173b01e57SJeff Chen nxpwifi_cmd_sta_get_hw_spec(struct nxpwifi_private *priv,
2273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
2373b01e57SJeff Chen u16 cmd_no, void *data_buf,
2473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
2573b01e57SJeff Chen {
2673b01e57SJeff Chen struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec;
2773b01e57SJeff Chen
2873b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_GET_HW_SPEC);
2973b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) +
3073b01e57SJeff Chen S_DS_GEN);
3173b01e57SJeff Chen memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN);
3273b01e57SJeff Chen
3373b01e57SJeff Chen return 0;
3473b01e57SJeff Chen }
3573b01e57SJeff Chen
3673b01e57SJeff Chen static int
nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)3773b01e57SJeff Chen nxpwifi_ret_sta_get_hw_spec(struct nxpwifi_private *priv,
3873b01e57SJeff Chen struct host_cmd_ds_command *resp,
3973b01e57SJeff Chen u16 cmdresp_no,
4073b01e57SJeff Chen void *data_buf)
4173b01e57SJeff Chen {
4273b01e57SJeff Chen struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec;
4373b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
4473b01e57SJeff Chen struct nxpwifi_ie_types_header *tlv;
4573b01e57SJeff Chen struct hw_spec_api_rev *api_rev;
4673b01e57SJeff Chen struct hw_spec_max_conn *max_conn;
4773b01e57SJeff Chen struct hw_spec_extension *hw_he_cap;
4873b01e57SJeff Chen struct hw_spec_fw_cap_info *fw_cap;
4973b01e57SJeff Chen struct hw_spec_secure_boot_uuid *sb_uuid;
5073b01e57SJeff Chen u16 resp_size, api_id;
5173b01e57SJeff Chen int i, left_len, parsed_len = 0;
5273b01e57SJeff Chen
5373b01e57SJeff Chen adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info);
5473b01e57SJeff Chen
5573b01e57SJeff Chen if (IS_SUPPORT_MULTI_BANDS(adapter))
5673b01e57SJeff Chen adapter->fw_bands = GET_FW_DEFAULT_BANDS(adapter);
5773b01e57SJeff Chen else
5873b01e57SJeff Chen adapter->fw_bands = BAND_B;
5973b01e57SJeff Chen
6073b01e57SJeff Chen if ((adapter->fw_bands & BAND_A) && (adapter->fw_bands & BAND_GN))
6173b01e57SJeff Chen adapter->fw_bands |= BAND_AN;
6273b01e57SJeff Chen if (!(adapter->fw_bands & BAND_G) && (adapter->fw_bands & BAND_GN))
6373b01e57SJeff Chen adapter->fw_bands &= ~BAND_GN;
6473b01e57SJeff Chen
6573b01e57SJeff Chen adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number);
6673b01e57SJeff Chen adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff;
6773b01e57SJeff Chen adapter->number_of_antenna =
6873b01e57SJeff Chen le16_to_cpu(hw_spec->number_of_antenna) & 0xf;
6973b01e57SJeff Chen
7073b01e57SJeff Chen if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) {
7173b01e57SJeff Chen adapter->is_hw_11ac_capable = true;
7273b01e57SJeff Chen
7373b01e57SJeff Chen /* Copy 11AC cap */
7473b01e57SJeff Chen adapter->hw_dot_11ac_dev_cap =
7573b01e57SJeff Chen le32_to_cpu(hw_spec->dot_11ac_dev_cap);
7673b01e57SJeff Chen adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap
7773b01e57SJeff Chen & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK;
7873b01e57SJeff Chen adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap
7973b01e57SJeff Chen & ~NXPWIFI_DEF_11AC_CAP_BF_RESET_MASK;
8073b01e57SJeff Chen
8173b01e57SJeff Chen /* Copy 11AC mcs */
8273b01e57SJeff Chen adapter->hw_dot_11ac_mcs_support =
8373b01e57SJeff Chen le32_to_cpu(hw_spec->dot_11ac_mcs_support);
8473b01e57SJeff Chen adapter->usr_dot_11ac_mcs_support =
8573b01e57SJeff Chen adapter->hw_dot_11ac_mcs_support;
8673b01e57SJeff Chen } else {
8773b01e57SJeff Chen adapter->is_hw_11ac_capable = false;
8873b01e57SJeff Chen }
8973b01e57SJeff Chen
9073b01e57SJeff Chen resp_size = le16_to_cpu(resp->size) - S_DS_GEN;
9173b01e57SJeff Chen if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) {
9273b01e57SJeff Chen /* we have variable HW SPEC information */
9373b01e57SJeff Chen left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec);
9473b01e57SJeff Chen while (left_len > sizeof(struct nxpwifi_ie_types_header)) {
9573b01e57SJeff Chen tlv = (void *)&hw_spec->tlv + parsed_len;
9673b01e57SJeff Chen switch (le16_to_cpu(tlv->type)) {
9773b01e57SJeff Chen case TLV_TYPE_API_REV:
9873b01e57SJeff Chen api_rev = (struct hw_spec_api_rev *)tlv;
9973b01e57SJeff Chen api_id = le16_to_cpu(api_rev->api_id);
10073b01e57SJeff Chen switch (api_id) {
10173b01e57SJeff Chen case KEY_API_VER_ID:
10273b01e57SJeff Chen adapter->key_api_major_ver =
10373b01e57SJeff Chen api_rev->major_ver;
10473b01e57SJeff Chen adapter->key_api_minor_ver =
10573b01e57SJeff Chen api_rev->minor_ver;
10673b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
10773b01e57SJeff Chen "key_api v%d.%d\n",
10873b01e57SJeff Chen adapter->key_api_major_ver,
10973b01e57SJeff Chen adapter->key_api_minor_ver);
11073b01e57SJeff Chen break;
11173b01e57SJeff Chen case FW_API_VER_ID:
11273b01e57SJeff Chen adapter->fw_api_ver =
11373b01e57SJeff Chen api_rev->major_ver;
11473b01e57SJeff Chen nxpwifi_dbg(adapter, MSG,
11573b01e57SJeff Chen "Firmware api version %d.%d\n",
11673b01e57SJeff Chen adapter->fw_api_ver,
11773b01e57SJeff Chen api_rev->minor_ver);
11873b01e57SJeff Chen break;
11973b01e57SJeff Chen case UAP_FW_API_VER_ID:
12073b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
12173b01e57SJeff Chen "uAP api version %d.%d\n",
12273b01e57SJeff Chen api_rev->major_ver,
12373b01e57SJeff Chen api_rev->minor_ver);
12473b01e57SJeff Chen break;
12573b01e57SJeff Chen case CHANRPT_API_VER_ID:
12673b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
12773b01e57SJeff Chen "channel report api version %d.%d\n",
12873b01e57SJeff Chen api_rev->major_ver,
12973b01e57SJeff Chen api_rev->minor_ver);
13073b01e57SJeff Chen break;
13173b01e57SJeff Chen case FW_HOTFIX_VER_ID:
13273b01e57SJeff Chen adapter->fw_hotfix_ver =
13373b01e57SJeff Chen api_rev->major_ver;
13473b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
13573b01e57SJeff Chen "Firmware hotfix version %d\n",
13673b01e57SJeff Chen api_rev->major_ver);
13773b01e57SJeff Chen break;
13873b01e57SJeff Chen default:
13973b01e57SJeff Chen nxpwifi_dbg(adapter, FATAL,
14073b01e57SJeff Chen "Unknown api_id: %d\n",
14173b01e57SJeff Chen api_id);
14273b01e57SJeff Chen break;
14373b01e57SJeff Chen }
14473b01e57SJeff Chen break;
14573b01e57SJeff Chen case TLV_TYPE_MAX_CONN:
14673b01e57SJeff Chen max_conn = (struct hw_spec_max_conn *)tlv;
14773b01e57SJeff Chen adapter->max_sta_conn = max_conn->max_sta_conn;
14873b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
14973b01e57SJeff Chen "max sta connections: %u\n",
15073b01e57SJeff Chen adapter->max_sta_conn);
15173b01e57SJeff Chen break;
15273b01e57SJeff Chen case TLV_TYPE_EXTENSION_ID:
15373b01e57SJeff Chen hw_he_cap = (struct hw_spec_extension *)tlv;
15473b01e57SJeff Chen if (hw_he_cap->ext_id ==
15573b01e57SJeff Chen WLAN_EID_EXT_HE_CAPABILITY)
15673b01e57SJeff Chen nxpwifi_update_11ax_cap(adapter, hw_he_cap);
15773b01e57SJeff Chen break;
15873b01e57SJeff Chen case TLV_TYPE_FW_CAP_INFO:
15973b01e57SJeff Chen fw_cap = (struct hw_spec_fw_cap_info *)tlv;
16073b01e57SJeff Chen adapter->fw_cap_info =
16173b01e57SJeff Chen le32_to_cpu(fw_cap->fw_cap_info);
16273b01e57SJeff Chen adapter->fw_cap_ext =
16373b01e57SJeff Chen le32_to_cpu(fw_cap->fw_cap_ext);
16473b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
16573b01e57SJeff Chen "fw_cap_info:%#x fw_cap_ext:%#x\n",
16673b01e57SJeff Chen adapter->fw_cap_info,
16773b01e57SJeff Chen adapter->fw_cap_ext);
16873b01e57SJeff Chen break;
16973b01e57SJeff Chen case TLV_TYPE_SECURE_BOOT_UUID:
17073b01e57SJeff Chen sb_uuid = (struct hw_spec_secure_boot_uuid *)tlv;
17173b01e57SJeff Chen adapter->uuid_lo =
17273b01e57SJeff Chen le64_to_cpu(sb_uuid->uuid_lo);
17373b01e57SJeff Chen adapter->uuid_hi =
17473b01e57SJeff Chen le64_to_cpu(sb_uuid->uuid_hi);
17573b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
17673b01e57SJeff Chen "uuid: %#llx%#llx\n",
17773b01e57SJeff Chen adapter->uuid_lo, adapter->uuid_hi);
17873b01e57SJeff Chen break;
17973b01e57SJeff Chen default:
18073b01e57SJeff Chen nxpwifi_dbg(adapter, FATAL,
18173b01e57SJeff Chen "Unknown GET_HW_SPEC TLV type: %#x\n",
18273b01e57SJeff Chen le16_to_cpu(tlv->type));
18373b01e57SJeff Chen break;
18473b01e57SJeff Chen }
18573b01e57SJeff Chen parsed_len += le16_to_cpu(tlv->len) +
18673b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header);
18773b01e57SJeff Chen left_len -= le16_to_cpu(tlv->len) +
18873b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header);
18973b01e57SJeff Chen }
19073b01e57SJeff Chen }
19173b01e57SJeff Chen
19273b01e57SJeff Chen if (adapter->key_api_major_ver < KEY_API_VER_MAJOR_V2)
19373b01e57SJeff Chen return -EOPNOTSUPP;
19473b01e57SJeff Chen
19573b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
19673b01e57SJeff Chen "info: GET_HW_SPEC: fw_release_number- %#x\n",
19773b01e57SJeff Chen adapter->fw_release_number);
19873b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
19973b01e57SJeff Chen "info: GET_HW_SPEC: permanent addr: %pM\n",
20073b01e57SJeff Chen hw_spec->permanent_addr);
20173b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
20273b01e57SJeff Chen "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n",
20373b01e57SJeff Chen le16_to_cpu(hw_spec->hw_if_version),
20473b01e57SJeff Chen le16_to_cpu(hw_spec->version));
20573b01e57SJeff Chen
20673b01e57SJeff Chen ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr);
20773b01e57SJeff Chen adapter->region_code = le16_to_cpu(hw_spec->region_code);
20873b01e57SJeff Chen
20973b01e57SJeff Chen /* If it's unidentified region code, use the default (USA/FCC) */
21073b01e57SJeff Chen if (!nxpwifi_is_valid_region_code(adapter->region_code)) {
21173b01e57SJeff Chen nxpwifi_dbg(adapter, WARN,
21273b01e57SJeff Chen "cmd: unknown region code %#x, use default (USA/%#x)\n",
21373b01e57SJeff Chen adapter->region_code, NXPWIFI_DEFAULT_REGION_CODE);
21473b01e57SJeff Chen adapter->region_code = NXPWIFI_DEFAULT_REGION_CODE;
21573b01e57SJeff Chen }
21673b01e57SJeff Chen
21773b01e57SJeff Chen adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap);
21873b01e57SJeff Chen adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support;
21973b01e57SJeff Chen adapter->hw_mpdu_density = GET_MPDU_DENSITY(le32_to_cpu(hw_spec->hw_dev_cap));
22073b01e57SJeff Chen adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support;
22173b01e57SJeff Chen adapter->user_htstream = adapter->hw_dev_mcs_support;
22273b01e57SJeff Chen if (adapter->fw_bands & BAND_A)
22373b01e57SJeff Chen adapter->user_htstream |= (adapter->user_htstream << 8);
22473b01e57SJeff Chen
22573b01e57SJeff Chen if (adapter->if_ops.update_mp_end_port) {
22673b01e57SJeff Chen u16 mp_end_port;
22773b01e57SJeff Chen
22873b01e57SJeff Chen mp_end_port = le16_to_cpu(hw_spec->mp_end_port);
22973b01e57SJeff Chen adapter->if_ops.update_mp_end_port(adapter, mp_end_port);
23073b01e57SJeff Chen }
23173b01e57SJeff Chen
23273b01e57SJeff Chen if (adapter->fw_api_ver == NXPWIFI_FW_V15)
23373b01e57SJeff Chen adapter->scan_chan_gap_enabled = true;
23473b01e57SJeff Chen
23573b01e57SJeff Chen for (i = 0; i < adapter->priv_num; i++)
23673b01e57SJeff Chen adapter->priv[i]->config_bands = adapter->fw_bands;
23773b01e57SJeff Chen
23873b01e57SJeff Chen return 0;
23973b01e57SJeff Chen }
24073b01e57SJeff Chen
24173b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)24273b01e57SJeff Chen nxpwifi_cmd_sta_802_11_scan(struct nxpwifi_private *priv,
24373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
24473b01e57SJeff Chen u16 cmd_no, void *data_buf,
24573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
24673b01e57SJeff Chen {
24773b01e57SJeff Chen return nxpwifi_cmd_802_11_scan(cmd, data_buf);
24873b01e57SJeff Chen }
24973b01e57SJeff Chen
25073b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)25173b01e57SJeff Chen nxpwifi_ret_sta_802_11_scan(struct nxpwifi_private *priv,
25273b01e57SJeff Chen struct host_cmd_ds_command *resp,
25373b01e57SJeff Chen u16 cmdresp_no,
25473b01e57SJeff Chen void *data_buf)
25573b01e57SJeff Chen {
25673b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
25773b01e57SJeff Chen int ret;
25873b01e57SJeff Chen
25973b01e57SJeff Chen ret = nxpwifi_ret_802_11_scan(priv, resp);
26073b01e57SJeff Chen adapter->curr_cmd->wait_q_enabled = false;
26173b01e57SJeff Chen
26273b01e57SJeff Chen return ret;
26373b01e57SJeff Chen }
26473b01e57SJeff Chen
26573b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)26673b01e57SJeff Chen nxpwifi_cmd_sta_802_11_get_log(struct nxpwifi_private *priv,
26773b01e57SJeff Chen struct host_cmd_ds_command *cmd,
26873b01e57SJeff Chen u16 cmd_no, void *data_buf,
26973b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
27073b01e57SJeff Chen {
27173b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_GET_LOG);
27273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) +
27373b01e57SJeff Chen S_DS_GEN);
27473b01e57SJeff Chen
27573b01e57SJeff Chen return 0;
27673b01e57SJeff Chen }
27773b01e57SJeff Chen
27873b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)27973b01e57SJeff Chen nxpwifi_ret_sta_802_11_get_log(struct nxpwifi_private *priv,
28073b01e57SJeff Chen struct host_cmd_ds_command *resp,
28173b01e57SJeff Chen u16 cmdresp_no,
28273b01e57SJeff Chen void *data_buf)
28373b01e57SJeff Chen {
28473b01e57SJeff Chen struct host_cmd_ds_802_11_get_log *get_log =
28573b01e57SJeff Chen &resp->params.get_log;
28673b01e57SJeff Chen struct nxpwifi_ds_get_stats *stats =
28773b01e57SJeff Chen (struct nxpwifi_ds_get_stats *)data_buf;
28873b01e57SJeff Chen
28973b01e57SJeff Chen if (stats) {
29073b01e57SJeff Chen stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
29173b01e57SJeff Chen stats->failed = le32_to_cpu(get_log->failed);
29273b01e57SJeff Chen stats->retry = le32_to_cpu(get_log->retry);
29373b01e57SJeff Chen stats->multi_retry = le32_to_cpu(get_log->multi_retry);
29473b01e57SJeff Chen stats->frame_dup = le32_to_cpu(get_log->frame_dup);
29573b01e57SJeff Chen stats->rts_success = le32_to_cpu(get_log->rts_success);
29673b01e57SJeff Chen stats->rts_failure = le32_to_cpu(get_log->rts_failure);
29773b01e57SJeff Chen stats->ack_failure = le32_to_cpu(get_log->ack_failure);
29873b01e57SJeff Chen stats->rx_frag = le32_to_cpu(get_log->rx_frag);
29973b01e57SJeff Chen stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame);
30073b01e57SJeff Chen stats->fcs_error = le32_to_cpu(get_log->fcs_error);
30173b01e57SJeff Chen stats->tx_frame = le32_to_cpu(get_log->tx_frame);
30273b01e57SJeff Chen stats->wep_icv_error[0] =
30373b01e57SJeff Chen le32_to_cpu(get_log->wep_icv_err_cnt[0]);
30473b01e57SJeff Chen stats->wep_icv_error[1] =
30573b01e57SJeff Chen le32_to_cpu(get_log->wep_icv_err_cnt[1]);
30673b01e57SJeff Chen stats->wep_icv_error[2] =
30773b01e57SJeff Chen le32_to_cpu(get_log->wep_icv_err_cnt[2]);
30873b01e57SJeff Chen stats->wep_icv_error[3] =
30973b01e57SJeff Chen le32_to_cpu(get_log->wep_icv_err_cnt[3]);
31073b01e57SJeff Chen stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt);
31173b01e57SJeff Chen stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt);
31273b01e57SJeff Chen }
31373b01e57SJeff Chen
31473b01e57SJeff Chen return 0;
31573b01e57SJeff Chen }
31673b01e57SJeff Chen
31773b01e57SJeff Chen static int
nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)31873b01e57SJeff Chen nxpwifi_cmd_sta_mac_multicast_adr(struct nxpwifi_private *priv,
31973b01e57SJeff Chen struct host_cmd_ds_command *cmd,
32073b01e57SJeff Chen u16 cmd_no, void *data_buf,
32173b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
32273b01e57SJeff Chen {
32373b01e57SJeff Chen struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
32473b01e57SJeff Chen struct nxpwifi_multicast_list *mcast_list =
32573b01e57SJeff Chen (struct nxpwifi_multicast_list *)data_buf;
32673b01e57SJeff Chen
32773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
32873b01e57SJeff Chen S_DS_GEN);
32973b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_MAC_MULTICAST_ADR);
33073b01e57SJeff Chen
33173b01e57SJeff Chen mcast_addr->action = cpu_to_le16(cmd_action);
33273b01e57SJeff Chen mcast_addr->num_of_adrs =
33373b01e57SJeff Chen cpu_to_le16((u16)mcast_list->num_multicast_addr);
33473b01e57SJeff Chen memcpy(mcast_addr->mac_list, mcast_list->mac_list,
33573b01e57SJeff Chen mcast_list->num_multicast_addr * ETH_ALEN);
33673b01e57SJeff Chen
33773b01e57SJeff Chen return 0;
33873b01e57SJeff Chen }
33973b01e57SJeff Chen
34073b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)34173b01e57SJeff Chen nxpwifi_cmd_sta_802_11_associate(struct nxpwifi_private *priv,
34273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
34373b01e57SJeff Chen u16 cmd_no, void *data_buf,
34473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
34573b01e57SJeff Chen {
34673b01e57SJeff Chen return nxpwifi_cmd_802_11_associate(priv, cmd, data_buf);
34773b01e57SJeff Chen }
34873b01e57SJeff Chen
34973b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)35073b01e57SJeff Chen nxpwifi_ret_sta_802_11_associate(struct nxpwifi_private *priv,
35173b01e57SJeff Chen struct host_cmd_ds_command *resp,
35273b01e57SJeff Chen u16 cmdresp_no,
35373b01e57SJeff Chen void *data_buf)
35473b01e57SJeff Chen {
35573b01e57SJeff Chen return nxpwifi_ret_802_11_associate(priv, resp);
35673b01e57SJeff Chen }
35773b01e57SJeff Chen
35873b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)35973b01e57SJeff Chen nxpwifi_cmd_sta_802_11_snmp_mib(struct nxpwifi_private *priv,
36073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
36173b01e57SJeff Chen u16 cmd_no, void *data_buf,
36273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
36373b01e57SJeff Chen {
36473b01e57SJeff Chen struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
36573b01e57SJeff Chen u16 *ul_temp = (u16 *)data_buf;
36673b01e57SJeff Chen
36773b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
36873b01e57SJeff Chen "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_type);
36973b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_SNMP_MIB);
37073b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib)
37173b01e57SJeff Chen + S_DS_GEN);
37273b01e57SJeff Chen
37373b01e57SJeff Chen snmp_mib->oid = cpu_to_le16((u16)cmd_type);
37473b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_GET) {
37573b01e57SJeff Chen snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_GET);
37673b01e57SJeff Chen snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE);
37773b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE);
37873b01e57SJeff Chen } else if (cmd_action == HOST_ACT_GEN_SET) {
37973b01e57SJeff Chen snmp_mib->query_type = cpu_to_le16(HOST_ACT_GEN_SET);
38073b01e57SJeff Chen snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
38173b01e57SJeff Chen put_unaligned_le16(*ul_temp, snmp_mib->value);
38273b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, sizeof(u16));
38373b01e57SJeff Chen }
38473b01e57SJeff Chen
38573b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
38673b01e57SJeff Chen "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
38773b01e57SJeff Chen "OIDSize=0x%x, Value=0x%x\n",
38873b01e57SJeff Chen cmd_action, cmd_type, le16_to_cpu(snmp_mib->buf_size),
38973b01e57SJeff Chen get_unaligned_le16(snmp_mib->value));
39073b01e57SJeff Chen
39173b01e57SJeff Chen return 0;
39273b01e57SJeff Chen }
39373b01e57SJeff Chen
39473b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)39573b01e57SJeff Chen nxpwifi_ret_sta_802_11_snmp_mib(struct nxpwifi_private *priv,
39673b01e57SJeff Chen struct host_cmd_ds_command *resp,
39773b01e57SJeff Chen u16 cmdresp_no,
39873b01e57SJeff Chen void *data_buf)
39973b01e57SJeff Chen {
40073b01e57SJeff Chen struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
40173b01e57SJeff Chen u16 oid = le16_to_cpu(smib->oid);
40273b01e57SJeff Chen u16 query_type = le16_to_cpu(smib->query_type);
40373b01e57SJeff Chen u32 ul_temp;
40473b01e57SJeff Chen
40573b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
40673b01e57SJeff Chen "info: SNMP_RESP: oid value = %#x,\t"
40773b01e57SJeff Chen "query_type = %#x, buf size = %#x\n",
40873b01e57SJeff Chen oid, query_type, le16_to_cpu(smib->buf_size));
40973b01e57SJeff Chen if (query_type == HOST_ACT_GEN_GET) {
41073b01e57SJeff Chen ul_temp = get_unaligned_le16(smib->value);
41173b01e57SJeff Chen if (data_buf)
41273b01e57SJeff Chen *(u32 *)data_buf = ul_temp;
41373b01e57SJeff Chen switch (oid) {
41473b01e57SJeff Chen case FRAG_THRESH_I:
41573b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
41673b01e57SJeff Chen "info: SNMP_RESP: FragThsd =%u\n",
41773b01e57SJeff Chen ul_temp);
41873b01e57SJeff Chen break;
41973b01e57SJeff Chen case RTS_THRESH_I:
42073b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
42173b01e57SJeff Chen "info: SNMP_RESP: RTSThsd =%u\n",
42273b01e57SJeff Chen ul_temp);
42373b01e57SJeff Chen break;
42473b01e57SJeff Chen case SHORT_RETRY_LIM_I:
42573b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
42673b01e57SJeff Chen "info: SNMP_RESP: TxRetryCount=%u\n",
42773b01e57SJeff Chen ul_temp);
42873b01e57SJeff Chen break;
42973b01e57SJeff Chen case DTIM_PERIOD_I:
43073b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
43173b01e57SJeff Chen "info: SNMP_RESP: DTIM period=%u\n",
43273b01e57SJeff Chen ul_temp);
43373b01e57SJeff Chen break;
43473b01e57SJeff Chen default:
43573b01e57SJeff Chen break;
43673b01e57SJeff Chen }
43773b01e57SJeff Chen }
43873b01e57SJeff Chen
43973b01e57SJeff Chen return 0;
44073b01e57SJeff Chen }
44173b01e57SJeff Chen
nxpwifi_cmd_sta_reg_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)44273b01e57SJeff Chen static int nxpwifi_cmd_sta_reg_access(struct nxpwifi_private *priv,
44373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
44473b01e57SJeff Chen u16 cmd_no, void *data_buf,
44573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
44673b01e57SJeff Chen {
44773b01e57SJeff Chen struct nxpwifi_ds_reg_rw *reg_rw = data_buf;
44873b01e57SJeff Chen
44973b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
45073b01e57SJeff Chen
45173b01e57SJeff Chen switch (cmd_no) {
45273b01e57SJeff Chen case HOST_CMD_MAC_REG_ACCESS:
45373b01e57SJeff Chen {
45473b01e57SJeff Chen struct host_cmd_ds_mac_reg_access *mac_reg;
45573b01e57SJeff Chen
45673b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
45773b01e57SJeff Chen mac_reg = &cmd->params.mac_reg;
45873b01e57SJeff Chen mac_reg->action = cpu_to_le16(cmd_action);
45973b01e57SJeff Chen mac_reg->offset = cpu_to_le16((u16)reg_rw->offset);
46073b01e57SJeff Chen mac_reg->value = cpu_to_le32(reg_rw->value);
46173b01e57SJeff Chen break;
46273b01e57SJeff Chen }
46373b01e57SJeff Chen case HOST_CMD_BBP_REG_ACCESS:
46473b01e57SJeff Chen {
46573b01e57SJeff Chen struct host_cmd_ds_bbp_reg_access *bbp_reg;
46673b01e57SJeff Chen
46773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
46873b01e57SJeff Chen bbp_reg = &cmd->params.bbp_reg;
46973b01e57SJeff Chen bbp_reg->action = cpu_to_le16(cmd_action);
47073b01e57SJeff Chen bbp_reg->offset = cpu_to_le16((u16)reg_rw->offset);
47173b01e57SJeff Chen bbp_reg->value = (u8)reg_rw->value;
47273b01e57SJeff Chen break;
47373b01e57SJeff Chen }
47473b01e57SJeff Chen case HOST_CMD_RF_REG_ACCESS:
47573b01e57SJeff Chen {
47673b01e57SJeff Chen struct host_cmd_ds_rf_reg_access *rf_reg;
47773b01e57SJeff Chen
47873b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
47973b01e57SJeff Chen rf_reg = &cmd->params.rf_reg;
48073b01e57SJeff Chen rf_reg->action = cpu_to_le16(cmd_action);
48173b01e57SJeff Chen rf_reg->offset = cpu_to_le16((u16)reg_rw->offset);
48273b01e57SJeff Chen rf_reg->value = (u8)reg_rw->value;
48373b01e57SJeff Chen break;
48473b01e57SJeff Chen }
48573b01e57SJeff Chen case HOST_CMD_PMIC_REG_ACCESS:
48673b01e57SJeff Chen {
48773b01e57SJeff Chen struct host_cmd_ds_pmic_reg_access *pmic_reg;
48873b01e57SJeff Chen
48973b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN);
49073b01e57SJeff Chen pmic_reg = &cmd->params.pmic_reg;
49173b01e57SJeff Chen pmic_reg->action = cpu_to_le16(cmd_action);
49273b01e57SJeff Chen pmic_reg->offset = cpu_to_le16((u16)reg_rw->offset);
49373b01e57SJeff Chen pmic_reg->value = (u8)reg_rw->value;
49473b01e57SJeff Chen break;
49573b01e57SJeff Chen }
49673b01e57SJeff Chen case HOST_CMD_CAU_REG_ACCESS:
49773b01e57SJeff Chen {
49873b01e57SJeff Chen struct host_cmd_ds_rf_reg_access *cau_reg;
49973b01e57SJeff Chen
50073b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
50173b01e57SJeff Chen cau_reg = &cmd->params.rf_reg;
50273b01e57SJeff Chen cau_reg->action = cpu_to_le16(cmd_action);
50373b01e57SJeff Chen cau_reg->offset = cpu_to_le16((u16)reg_rw->offset);
50473b01e57SJeff Chen cau_reg->value = (u8)reg_rw->value;
50573b01e57SJeff Chen break;
50673b01e57SJeff Chen }
50773b01e57SJeff Chen case HOST_CMD_802_11_EEPROM_ACCESS:
50873b01e57SJeff Chen {
50973b01e57SJeff Chen struct nxpwifi_ds_read_eeprom *rd_eeprom = data_buf;
51073b01e57SJeff Chen struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
51173b01e57SJeff Chen &cmd->params.eeprom;
51273b01e57SJeff Chen
51373b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN);
51473b01e57SJeff Chen cmd_eeprom->action = cpu_to_le16(cmd_action);
51573b01e57SJeff Chen cmd_eeprom->offset = cpu_to_le16(rd_eeprom->offset);
51673b01e57SJeff Chen cmd_eeprom->byte_count = cpu_to_le16(rd_eeprom->byte_count);
51773b01e57SJeff Chen cmd_eeprom->value = 0;
51873b01e57SJeff Chen break;
51973b01e57SJeff Chen }
52073b01e57SJeff Chen default:
52173b01e57SJeff Chen return -EINVAL;
52273b01e57SJeff Chen }
52373b01e57SJeff Chen
52473b01e57SJeff Chen return 0;
52573b01e57SJeff Chen }
52673b01e57SJeff Chen
52773b01e57SJeff Chen static int
nxpwifi_ret_sta_reg_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)52873b01e57SJeff Chen nxpwifi_ret_sta_reg_access(struct nxpwifi_private *priv,
52973b01e57SJeff Chen struct host_cmd_ds_command *resp,
53073b01e57SJeff Chen u16 cmdresp_no,
53173b01e57SJeff Chen void *data_buf)
53273b01e57SJeff Chen {
53373b01e57SJeff Chen struct nxpwifi_ds_reg_rw *reg_rw;
53473b01e57SJeff Chen struct nxpwifi_ds_read_eeprom *eeprom;
53573b01e57SJeff Chen union reg {
53673b01e57SJeff Chen struct host_cmd_ds_mac_reg_access *mac;
53773b01e57SJeff Chen struct host_cmd_ds_bbp_reg_access *bbp;
53873b01e57SJeff Chen struct host_cmd_ds_rf_reg_access *rf;
53973b01e57SJeff Chen struct host_cmd_ds_pmic_reg_access *pmic;
54073b01e57SJeff Chen struct host_cmd_ds_802_11_eeprom_access *eeprom;
54173b01e57SJeff Chen } r;
54273b01e57SJeff Chen
54373b01e57SJeff Chen if (!data_buf)
54473b01e57SJeff Chen return 0;
54573b01e57SJeff Chen
54673b01e57SJeff Chen reg_rw = data_buf;
54773b01e57SJeff Chen eeprom = data_buf;
54873b01e57SJeff Chen switch (cmdresp_no) {
54973b01e57SJeff Chen case HOST_CMD_MAC_REG_ACCESS:
55073b01e57SJeff Chen r.mac = &resp->params.mac_reg;
55173b01e57SJeff Chen reg_rw->offset = (u32)le16_to_cpu(r.mac->offset);
55273b01e57SJeff Chen reg_rw->value = le32_to_cpu(r.mac->value);
55373b01e57SJeff Chen break;
55473b01e57SJeff Chen case HOST_CMD_BBP_REG_ACCESS:
55573b01e57SJeff Chen r.bbp = &resp->params.bbp_reg;
55673b01e57SJeff Chen reg_rw->offset = (u32)le16_to_cpu(r.bbp->offset);
55773b01e57SJeff Chen reg_rw->value = (u32)r.bbp->value;
55873b01e57SJeff Chen break;
55973b01e57SJeff Chen
56073b01e57SJeff Chen case HOST_CMD_RF_REG_ACCESS:
56173b01e57SJeff Chen r.rf = &resp->params.rf_reg;
56273b01e57SJeff Chen reg_rw->offset = (u32)le16_to_cpu(r.rf->offset);
56373b01e57SJeff Chen reg_rw->value = (u32)r.bbp->value;
56473b01e57SJeff Chen break;
56573b01e57SJeff Chen case HOST_CMD_PMIC_REG_ACCESS:
56673b01e57SJeff Chen r.pmic = &resp->params.pmic_reg;
56773b01e57SJeff Chen reg_rw->offset = (u32)le16_to_cpu(r.pmic->offset);
56873b01e57SJeff Chen reg_rw->value = (u32)r.pmic->value;
56973b01e57SJeff Chen break;
57073b01e57SJeff Chen case HOST_CMD_CAU_REG_ACCESS:
57173b01e57SJeff Chen r.rf = &resp->params.rf_reg;
57273b01e57SJeff Chen reg_rw->offset = (u32)le16_to_cpu(r.rf->offset);
57373b01e57SJeff Chen reg_rw->value = (u32)r.rf->value;
57473b01e57SJeff Chen break;
57573b01e57SJeff Chen case HOST_CMD_802_11_EEPROM_ACCESS:
57673b01e57SJeff Chen r.eeprom = &resp->params.eeprom;
57773b01e57SJeff Chen pr_debug("info: EEPROM read len=%x\n",
57873b01e57SJeff Chen le16_to_cpu(r.eeprom->byte_count));
57973b01e57SJeff Chen if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) {
58073b01e57SJeff Chen eeprom->byte_count = 0;
58173b01e57SJeff Chen pr_debug("info: EEPROM read length is too big\n");
58273b01e57SJeff Chen return -ENOMEM;
58373b01e57SJeff Chen }
58473b01e57SJeff Chen eeprom->offset = le16_to_cpu(r.eeprom->offset);
58573b01e57SJeff Chen eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count);
58673b01e57SJeff Chen if (eeprom->byte_count > 0)
58773b01e57SJeff Chen memcpy(&eeprom->value, &r.eeprom->value,
58873b01e57SJeff Chen min((u16)MAX_EEPROM_DATA, eeprom->byte_count));
58973b01e57SJeff Chen break;
59073b01e57SJeff Chen default:
59173b01e57SJeff Chen return -EINVAL;
59273b01e57SJeff Chen }
59373b01e57SJeff Chen return 0;
59473b01e57SJeff Chen }
59573b01e57SJeff Chen
59673b01e57SJeff Chen static int
nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)59773b01e57SJeff Chen nxpwifi_cmd_sta_rf_tx_pwr(struct nxpwifi_private *priv,
59873b01e57SJeff Chen struct host_cmd_ds_command *cmd,
59973b01e57SJeff Chen u16 cmd_no, void *data_buf,
60073b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
60173b01e57SJeff Chen {
60273b01e57SJeff Chen struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp;
60373b01e57SJeff Chen
60473b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr)
60573b01e57SJeff Chen + S_DS_GEN);
60673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_RF_TX_PWR);
60773b01e57SJeff Chen txp->action = cpu_to_le16(cmd_action);
60873b01e57SJeff Chen
60973b01e57SJeff Chen return 0;
61073b01e57SJeff Chen }
61173b01e57SJeff Chen
61273b01e57SJeff Chen static int
nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)61373b01e57SJeff Chen nxpwifi_ret_sta_rf_tx_pwr(struct nxpwifi_private *priv,
61473b01e57SJeff Chen struct host_cmd_ds_command *resp,
61573b01e57SJeff Chen u16 cmdresp_no,
61673b01e57SJeff Chen void *data_buf)
61773b01e57SJeff Chen {
61873b01e57SJeff Chen struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp;
61973b01e57SJeff Chen u16 action = le16_to_cpu(txp->action);
62073b01e57SJeff Chen
62173b01e57SJeff Chen priv->tx_power_level = le16_to_cpu(txp->cur_level);
62273b01e57SJeff Chen
62373b01e57SJeff Chen if (action == HOST_ACT_GEN_GET) {
62473b01e57SJeff Chen priv->max_tx_power_level = txp->max_power;
62573b01e57SJeff Chen priv->min_tx_power_level = txp->min_power;
62673b01e57SJeff Chen }
62773b01e57SJeff Chen
62873b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
62973b01e57SJeff Chen "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n",
63073b01e57SJeff Chen priv->tx_power_level, priv->max_tx_power_level,
63173b01e57SJeff Chen priv->min_tx_power_level);
63273b01e57SJeff Chen
63373b01e57SJeff Chen return 0;
63473b01e57SJeff Chen }
63573b01e57SJeff Chen
63673b01e57SJeff Chen static int
nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)63773b01e57SJeff Chen nxpwifi_cmd_sta_rf_antenna(struct nxpwifi_private *priv,
63873b01e57SJeff Chen struct host_cmd_ds_command *cmd,
63973b01e57SJeff Chen u16 cmd_no, void *data_buf,
64073b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
64173b01e57SJeff Chen {
64273b01e57SJeff Chen struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo;
64373b01e57SJeff Chen struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso;
64473b01e57SJeff Chen struct nxpwifi_ds_ant_cfg *ant_cfg =
64573b01e57SJeff Chen (struct nxpwifi_ds_ant_cfg *)data_buf;
64673b01e57SJeff Chen
64773b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_RF_ANTENNA);
64873b01e57SJeff Chen
64973b01e57SJeff Chen switch (cmd_action) {
65073b01e57SJeff Chen case HOST_ACT_GEN_SET:
65173b01e57SJeff Chen if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
65273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct
65373b01e57SJeff Chen host_cmd_ds_rf_ant_mimo)
65473b01e57SJeff Chen + S_DS_GEN);
65573b01e57SJeff Chen ant_mimo->action_tx = cpu_to_le16(HOST_ACT_SET_TX);
65673b01e57SJeff Chen ant_mimo->tx_ant_mode =
65773b01e57SJeff Chen cpu_to_le16((u16)ant_cfg->tx_ant);
65873b01e57SJeff Chen ant_mimo->action_rx = cpu_to_le16(HOST_ACT_SET_RX);
65973b01e57SJeff Chen ant_mimo->rx_ant_mode =
66073b01e57SJeff Chen cpu_to_le16((u16)ant_cfg->rx_ant);
66173b01e57SJeff Chen } else {
66273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct
66373b01e57SJeff Chen host_cmd_ds_rf_ant_siso) +
66473b01e57SJeff Chen S_DS_GEN);
66573b01e57SJeff Chen ant_siso->action = cpu_to_le16(HOST_ACT_SET_BOTH);
66673b01e57SJeff Chen ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant);
66773b01e57SJeff Chen }
66873b01e57SJeff Chen break;
66973b01e57SJeff Chen case HOST_ACT_GEN_GET:
67073b01e57SJeff Chen if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
67173b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct
67273b01e57SJeff Chen host_cmd_ds_rf_ant_mimo) +
67373b01e57SJeff Chen S_DS_GEN);
67473b01e57SJeff Chen ant_mimo->action_tx = cpu_to_le16(HOST_ACT_GET_TX);
67573b01e57SJeff Chen ant_mimo->action_rx = cpu_to_le16(HOST_ACT_GET_RX);
67673b01e57SJeff Chen } else {
67773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct
67873b01e57SJeff Chen host_cmd_ds_rf_ant_siso) +
67973b01e57SJeff Chen S_DS_GEN);
68073b01e57SJeff Chen ant_siso->action = cpu_to_le16(HOST_ACT_GET_BOTH);
68173b01e57SJeff Chen }
68273b01e57SJeff Chen break;
68373b01e57SJeff Chen }
68473b01e57SJeff Chen return 0;
68573b01e57SJeff Chen }
68673b01e57SJeff Chen
68773b01e57SJeff Chen static int
nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)68873b01e57SJeff Chen nxpwifi_ret_sta_rf_antenna(struct nxpwifi_private *priv,
68973b01e57SJeff Chen struct host_cmd_ds_command *resp,
69073b01e57SJeff Chen u16 cmdresp_no,
69173b01e57SJeff Chen void *data_buf)
69273b01e57SJeff Chen {
69373b01e57SJeff Chen struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo;
69473b01e57SJeff Chen struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso;
69573b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
69673b01e57SJeff Chen
69773b01e57SJeff Chen if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) {
69873b01e57SJeff Chen priv->tx_ant = le16_to_cpu(ant_mimo->tx_ant_mode);
69973b01e57SJeff Chen priv->rx_ant = le16_to_cpu(ant_mimo->rx_ant_mode);
70073b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
70173b01e57SJeff Chen "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t"
70273b01e57SJeff Chen "Rx action = 0x%x, Rx Mode = 0x%04x\n",
70373b01e57SJeff Chen le16_to_cpu(ant_mimo->action_tx),
70473b01e57SJeff Chen le16_to_cpu(ant_mimo->tx_ant_mode),
70573b01e57SJeff Chen le16_to_cpu(ant_mimo->action_rx),
70673b01e57SJeff Chen le16_to_cpu(ant_mimo->rx_ant_mode));
70773b01e57SJeff Chen } else {
70873b01e57SJeff Chen priv->tx_ant = le16_to_cpu(ant_siso->ant_mode);
70973b01e57SJeff Chen priv->rx_ant = le16_to_cpu(ant_siso->ant_mode);
71073b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
71173b01e57SJeff Chen "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n",
71273b01e57SJeff Chen le16_to_cpu(ant_siso->action),
71373b01e57SJeff Chen le16_to_cpu(ant_siso->ant_mode));
71473b01e57SJeff Chen }
71573b01e57SJeff Chen return 0;
71673b01e57SJeff Chen }
71773b01e57SJeff Chen
71873b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)71973b01e57SJeff Chen nxpwifi_cmd_sta_802_11_deauthenticate(struct nxpwifi_private *priv,
72073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
72173b01e57SJeff Chen u16 cmd_no, void *data_buf,
72273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
72373b01e57SJeff Chen {
72473b01e57SJeff Chen struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
72573b01e57SJeff Chen u8 *mac = (u8 *)data_buf;
72673b01e57SJeff Chen
72773b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_DEAUTHENTICATE);
72873b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate)
72973b01e57SJeff Chen + S_DS_GEN);
73073b01e57SJeff Chen
73173b01e57SJeff Chen /* Set AP MAC address */
73273b01e57SJeff Chen memcpy(deauth->mac_addr, mac, ETH_ALEN);
73373b01e57SJeff Chen
73473b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr);
73573b01e57SJeff Chen
73673b01e57SJeff Chen deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING);
73773b01e57SJeff Chen
73873b01e57SJeff Chen return 0;
73973b01e57SJeff Chen }
74073b01e57SJeff Chen
74173b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)74273b01e57SJeff Chen nxpwifi_ret_sta_802_11_deauthenticate(struct nxpwifi_private *priv,
74373b01e57SJeff Chen struct host_cmd_ds_command *resp,
74473b01e57SJeff Chen u16 cmdresp_no,
74573b01e57SJeff Chen void *data_buf)
74673b01e57SJeff Chen {
74773b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
74873b01e57SJeff Chen
74973b01e57SJeff Chen adapter->dbg.num_cmd_deauth++;
75073b01e57SJeff Chen if (!memcmp(resp->params.deauth.mac_addr,
75173b01e57SJeff Chen &priv->curr_bss_params.bss_descriptor.mac_address,
75273b01e57SJeff Chen sizeof(resp->params.deauth.mac_addr)))
75373b01e57SJeff Chen nxpwifi_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING,
75473b01e57SJeff Chen false);
75573b01e57SJeff Chen
75673b01e57SJeff Chen return 0;
75773b01e57SJeff Chen }
75873b01e57SJeff Chen
75973b01e57SJeff Chen static int
nxpwifi_cmd_sta_mac_control(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)76073b01e57SJeff Chen nxpwifi_cmd_sta_mac_control(struct nxpwifi_private *priv,
76173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
76273b01e57SJeff Chen u16 cmd_no, void *data_buf,
76373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
76473b01e57SJeff Chen {
76573b01e57SJeff Chen struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
76673b01e57SJeff Chen u32 *action = (u32 *)data_buf;
76773b01e57SJeff Chen
76873b01e57SJeff Chen if (cmd_action != HOST_ACT_GEN_SET) {
76973b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
77073b01e57SJeff Chen "mac_control: only support set cmd\n");
77173b01e57SJeff Chen return -EINVAL;
77273b01e57SJeff Chen }
77373b01e57SJeff Chen
77473b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_MAC_CONTROL);
77573b01e57SJeff Chen cmd->size =
77673b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
77773b01e57SJeff Chen mac_ctrl->action = cpu_to_le32(*action);
77873b01e57SJeff Chen
77973b01e57SJeff Chen return 0;
78073b01e57SJeff Chen }
78173b01e57SJeff Chen
78273b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)78373b01e57SJeff Chen nxpwifi_cmd_sta_802_11_mac_address(struct nxpwifi_private *priv,
78473b01e57SJeff Chen struct host_cmd_ds_command *cmd,
78573b01e57SJeff Chen u16 cmd_no, void *data_buf,
78673b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
78773b01e57SJeff Chen {
78873b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_MAC_ADDRESS);
78973b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) +
79073b01e57SJeff Chen S_DS_GEN);
79173b01e57SJeff Chen cmd->result = 0;
79273b01e57SJeff Chen
79373b01e57SJeff Chen cmd->params.mac_addr.action = cpu_to_le16(cmd_action);
79473b01e57SJeff Chen
79573b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_SET)
79673b01e57SJeff Chen memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr,
79773b01e57SJeff Chen ETH_ALEN);
79873b01e57SJeff Chen
79973b01e57SJeff Chen return 0;
80073b01e57SJeff Chen }
80173b01e57SJeff Chen
80273b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)80373b01e57SJeff Chen nxpwifi_ret_sta_802_11_mac_address(struct nxpwifi_private *priv,
80473b01e57SJeff Chen struct host_cmd_ds_command *resp,
80573b01e57SJeff Chen u16 cmdresp_no,
80673b01e57SJeff Chen void *data_buf)
80773b01e57SJeff Chen {
80873b01e57SJeff Chen struct host_cmd_ds_802_11_mac_address *cmd_mac_addr;
80973b01e57SJeff Chen
81073b01e57SJeff Chen cmd_mac_addr = &resp->params.mac_addr;
81173b01e57SJeff Chen
81273b01e57SJeff Chen memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN);
81373b01e57SJeff Chen
81473b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
81573b01e57SJeff Chen "info: set mac address: %pM\n", priv->curr_addr);
81673b01e57SJeff Chen
81773b01e57SJeff Chen return 0;
81873b01e57SJeff Chen }
81973b01e57SJeff Chen
82073b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)82173b01e57SJeff Chen nxpwifi_cmd_sta_802_11d_domain_info(struct nxpwifi_private *priv,
82273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
82373b01e57SJeff Chen u16 cmd_no, void *data_buf,
82473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
82573b01e57SJeff Chen {
82673b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
82773b01e57SJeff Chen struct host_cmd_ds_802_11d_domain_info *domain_info =
82873b01e57SJeff Chen &cmd->params.domain_info;
82973b01e57SJeff Chen struct nxpwifi_ietypes_domain_param_set *domain =
83073b01e57SJeff Chen &domain_info->domain;
83173b01e57SJeff Chen struct nxpwifi_ietypes_domain_code *domain_code;
83273b01e57SJeff Chen u8 no_of_triplet = adapter->domain_reg.no_of_triplet;
83373b01e57SJeff Chen int triplet_size;
83473b01e57SJeff Chen
83573b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
83673b01e57SJeff Chen "info: 11D: no_of_triplet=0x%x\n", no_of_triplet);
83773b01e57SJeff Chen
83873b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11D_DOMAIN_INFO);
83973b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN);
84073b01e57SJeff Chen domain_info->action = cpu_to_le16(cmd_action);
84173b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, sizeof(domain_info->action));
84273b01e57SJeff Chen
84373b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_GET)
84473b01e57SJeff Chen return 0;
84573b01e57SJeff Chen
84673b01e57SJeff Chen triplet_size = no_of_triplet *
84773b01e57SJeff Chen sizeof(struct ieee80211_country_ie_triplet);
84873b01e57SJeff Chen
84973b01e57SJeff Chen domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY);
85073b01e57SJeff Chen domain->header.len =
85173b01e57SJeff Chen cpu_to_le16(sizeof(domain->country_code) + triplet_size);
85273b01e57SJeff Chen memcpy(domain->country_code, adapter->domain_reg.country_code,
85373b01e57SJeff Chen sizeof(domain->country_code));
85473b01e57SJeff Chen if (no_of_triplet)
85573b01e57SJeff Chen memcpy(domain->triplet, adapter->domain_reg.triplet,
85673b01e57SJeff Chen triplet_size);
85773b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, sizeof(*domain) + triplet_size);
85873b01e57SJeff Chen
85973b01e57SJeff Chen domain_code = (struct nxpwifi_ietypes_domain_code *)((u8 *)cmd +
86073b01e57SJeff Chen le16_to_cpu(cmd->size));
86173b01e57SJeff Chen domain_code->header.type = cpu_to_le16(TLV_TYPE_REGION_DOMAIN_CODE);
86273b01e57SJeff Chen domain_code->header.len =
86373b01e57SJeff Chen cpu_to_le16(sizeof(*domain_code) -
86473b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
86573b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, sizeof(*domain_code));
86673b01e57SJeff Chen
86773b01e57SJeff Chen return 0;
86873b01e57SJeff Chen }
86973b01e57SJeff Chen
87073b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)87173b01e57SJeff Chen nxpwifi_ret_sta_802_11d_domain_info(struct nxpwifi_private *priv,
87273b01e57SJeff Chen struct host_cmd_ds_command *resp,
87373b01e57SJeff Chen u16 cmdresp_no,
87473b01e57SJeff Chen void *data_buf)
87573b01e57SJeff Chen {
87673b01e57SJeff Chen struct host_cmd_ds_802_11d_domain_info_rsp *domain_info =
87773b01e57SJeff Chen &resp->params.domain_info_resp;
87873b01e57SJeff Chen struct nxpwifi_ietypes_domain_param_set *domain = &domain_info->domain;
87973b01e57SJeff Chen u16 action = le16_to_cpu(domain_info->action);
88073b01e57SJeff Chen u8 no_of_triplet;
88173b01e57SJeff Chen
88273b01e57SJeff Chen no_of_triplet = (u8)((le16_to_cpu(domain->header.len)
88373b01e57SJeff Chen - IEEE80211_COUNTRY_STRING_LEN)
88473b01e57SJeff Chen / sizeof(struct ieee80211_country_ie_triplet));
88573b01e57SJeff Chen
88673b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
88773b01e57SJeff Chen "info: 11D Domain Info Resp: no_of_triplet=%d\n",
88873b01e57SJeff Chen no_of_triplet);
88973b01e57SJeff Chen
89073b01e57SJeff Chen if (no_of_triplet > NXPWIFI_MAX_TRIPLET_802_11D) {
89173b01e57SJeff Chen nxpwifi_dbg(priv->adapter, FATAL,
89273b01e57SJeff Chen "11D: invalid number of triplets %d returned\n",
89373b01e57SJeff Chen no_of_triplet);
89473b01e57SJeff Chen return -EINVAL;
89573b01e57SJeff Chen }
89673b01e57SJeff Chen
89773b01e57SJeff Chen switch (action) {
89873b01e57SJeff Chen case HOST_ACT_GEN_SET: /* Proc Set Action */
89973b01e57SJeff Chen break;
90073b01e57SJeff Chen case HOST_ACT_GEN_GET:
90173b01e57SJeff Chen break;
90273b01e57SJeff Chen default:
90373b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
90473b01e57SJeff Chen "11D: invalid action:%d\n", domain_info->action);
90573b01e57SJeff Chen return -EINVAL;
90673b01e57SJeff Chen }
90773b01e57SJeff Chen
90873b01e57SJeff Chen return 0;
90973b01e57SJeff Chen }
91073b01e57SJeff Chen
nxpwifi_set_aes_key(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,struct nxpwifi_ds_encrypt_key * enc_key,struct host_cmd_ds_802_11_key_material * km)91173b01e57SJeff Chen static int nxpwifi_set_aes_key(struct nxpwifi_private *priv,
91273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
91373b01e57SJeff Chen struct nxpwifi_ds_encrypt_key *enc_key,
91473b01e57SJeff Chen struct host_cmd_ds_802_11_key_material *km)
91573b01e57SJeff Chen {
91673b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
91773b01e57SJeff Chen u16 size, len = KEY_PARAMS_FIXED_LEN;
91873b01e57SJeff Chen u8 key_type, key_type_igtk;
91973b01e57SJeff Chen
92073b01e57SJeff Chen if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
92173b01e57SJeff Chen key_type = KEY_TYPE_ID_AES;
92273b01e57SJeff Chen key_type_igtk = KEY_TYPE_ID_AES_CMAC;
92373b01e57SJeff Chen } else {
92473b01e57SJeff Chen key_type = KEY_TYPE_ID_GCMP_256;
92573b01e57SJeff Chen key_type_igtk = KEY_TYPE_ID_BIP_GMAC_256;
92673b01e57SJeff Chen }
92773b01e57SJeff Chen
92873b01e57SJeff Chen if (enc_key->is_igtk_key) {
92973b01e57SJeff Chen km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST);
93073b01e57SJeff Chen km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK);
93173b01e57SJeff Chen km->key_param_set.key_type = key_type_igtk;
93273b01e57SJeff Chen if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
93373b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
93473b01e57SJeff Chen "%s: Set CMAC AES Key\n", __func__);
93573b01e57SJeff Chen if (enc_key->is_rx_seq_valid)
93673b01e57SJeff Chen memcpy(km->key_param_set.key_params.cmac_aes.ipn,
93773b01e57SJeff Chen enc_key->pn, enc_key->pn_len);
93873b01e57SJeff Chen km->key_param_set.key_params.cmac_aes.key_len =
93973b01e57SJeff Chen cpu_to_le16(enc_key->key_len);
94073b01e57SJeff Chen memcpy(km->key_param_set.key_params.cmac_aes.key,
94173b01e57SJeff Chen enc_key->key_material, enc_key->key_len);
94273b01e57SJeff Chen len += sizeof(struct nxpwifi_cmac_aes_param);
94373b01e57SJeff Chen } else {
94473b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
94573b01e57SJeff Chen "%s: Set GMAC AES Key\n", __func__);
94673b01e57SJeff Chen if (enc_key->is_rx_seq_valid)
94773b01e57SJeff Chen memcpy(km->key_param_set.key_params.gmac_aes.ipn,
94873b01e57SJeff Chen enc_key->pn, enc_key->pn_len);
94973b01e57SJeff Chen km->key_param_set.key_params.gmac_aes.key_len =
95073b01e57SJeff Chen cpu_to_le16(enc_key->key_len);
95173b01e57SJeff Chen memcpy(km->key_param_set.key_params.gmac_aes.key,
95273b01e57SJeff Chen enc_key->key_material, enc_key->key_len);
95373b01e57SJeff Chen len += sizeof(struct nxpwifi_gmac_aes_param);
95473b01e57SJeff Chen }
95573b01e57SJeff Chen } else if (enc_key->is_igtk_def_key) {
95673b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
95773b01e57SJeff Chen "%s: Set CMAC default Key index\n", __func__);
95873b01e57SJeff Chen km->key_param_set.key_type = key_type_igtk;
95973b01e57SJeff Chen km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
96073b01e57SJeff Chen } else {
96173b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
96273b01e57SJeff Chen "%s: Set AES Key\n", __func__);
96373b01e57SJeff Chen if (enc_key->is_rx_seq_valid)
96473b01e57SJeff Chen memcpy(km->key_param_set.key_params.aes.pn,
96573b01e57SJeff Chen enc_key->pn, enc_key->pn_len);
96673b01e57SJeff Chen km->key_param_set.key_type = key_type;
96773b01e57SJeff Chen km->key_param_set.key_params.aes.key_len =
96873b01e57SJeff Chen cpu_to_le16(enc_key->key_len);
96973b01e57SJeff Chen memcpy(km->key_param_set.key_params.aes.key,
97073b01e57SJeff Chen enc_key->key_material, enc_key->key_len);
97173b01e57SJeff Chen len += sizeof(struct nxpwifi_aes_param);
97273b01e57SJeff Chen }
97373b01e57SJeff Chen
97473b01e57SJeff Chen km->key_param_set.len = cpu_to_le16(len);
97573b01e57SJeff Chen size = len + sizeof(struct nxpwifi_ie_types_header) +
97673b01e57SJeff Chen sizeof(km->action) + S_DS_GEN;
97773b01e57SJeff Chen cmd->size = cpu_to_le16(size);
97873b01e57SJeff Chen
97973b01e57SJeff Chen return 0;
98073b01e57SJeff Chen }
98173b01e57SJeff Chen
98273b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)98373b01e57SJeff Chen nxpwifi_cmd_sta_802_11_key_material(struct nxpwifi_private *priv,
98473b01e57SJeff Chen struct host_cmd_ds_command *cmd,
98573b01e57SJeff Chen u16 cmd_no, void *data_buf,
98673b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
98773b01e57SJeff Chen {
98873b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
98973b01e57SJeff Chen struct nxpwifi_ds_encrypt_key *enc_key =
99073b01e57SJeff Chen (struct nxpwifi_ds_encrypt_key *)data_buf;
99173b01e57SJeff Chen u8 *mac = enc_key->mac_addr;
99273b01e57SJeff Chen u16 key_info, len = KEY_PARAMS_FIXED_LEN;
99373b01e57SJeff Chen struct host_cmd_ds_802_11_key_material *km =
99473b01e57SJeff Chen &cmd->params.key_material;
99573b01e57SJeff Chen
99673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_KEY_MATERIAL);
99773b01e57SJeff Chen km->action = cpu_to_le16(cmd_action);
99873b01e57SJeff Chen
99973b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_GET) {
100073b01e57SJeff Chen nxpwifi_dbg(adapter, INFO, "%s: Get key\n", __func__);
100173b01e57SJeff Chen km->key_param_set.key_idx =
100273b01e57SJeff Chen enc_key->key_index & KEY_INDEX_MASK;
100373b01e57SJeff Chen km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
100473b01e57SJeff Chen km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
100573b01e57SJeff Chen ether_addr_copy(km->key_param_set.mac_addr, mac);
100673b01e57SJeff Chen
100773b01e57SJeff Chen if (enc_key->key_index & NXPWIFI_KEY_INDEX_UNICAST)
100873b01e57SJeff Chen key_info = KEY_UNICAST;
100973b01e57SJeff Chen else
101073b01e57SJeff Chen key_info = KEY_MCAST;
101173b01e57SJeff Chen
101273b01e57SJeff Chen if (enc_key->is_igtk_key)
101373b01e57SJeff Chen key_info |= KEY_IGTK;
101473b01e57SJeff Chen
101573b01e57SJeff Chen km->key_param_set.key_info = cpu_to_le16(key_info);
101673b01e57SJeff Chen
101773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
101873b01e57SJeff Chen S_DS_GEN + KEY_PARAMS_FIXED_LEN +
101973b01e57SJeff Chen sizeof(km->action));
102073b01e57SJeff Chen return 0;
102173b01e57SJeff Chen }
102273b01e57SJeff Chen
102373b01e57SJeff Chen memset(&km->key_param_set, 0,
102473b01e57SJeff Chen sizeof(struct nxpwifi_ie_type_key_param_set));
102573b01e57SJeff Chen
102673b01e57SJeff Chen if (enc_key->key_disable) {
102773b01e57SJeff Chen nxpwifi_dbg(adapter, INFO, "%s: Remove key\n", __func__);
102873b01e57SJeff Chen km->action = cpu_to_le16(HOST_ACT_GEN_REMOVE);
102973b01e57SJeff Chen km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
103073b01e57SJeff Chen km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN);
103173b01e57SJeff Chen km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
103273b01e57SJeff Chen key_info = KEY_MCAST | KEY_UNICAST;
103373b01e57SJeff Chen km->key_param_set.key_info = cpu_to_le16(key_info);
103473b01e57SJeff Chen ether_addr_copy(km->key_param_set.mac_addr, mac);
103573b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
103673b01e57SJeff Chen S_DS_GEN + KEY_PARAMS_FIXED_LEN +
103773b01e57SJeff Chen sizeof(km->action));
103873b01e57SJeff Chen return 0;
103973b01e57SJeff Chen }
104073b01e57SJeff Chen
104173b01e57SJeff Chen km->action = cpu_to_le16(HOST_ACT_GEN_SET);
104273b01e57SJeff Chen km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK;
104373b01e57SJeff Chen km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2);
104473b01e57SJeff Chen key_info = KEY_ENABLED;
104573b01e57SJeff Chen ether_addr_copy(km->key_param_set.mac_addr, mac);
104673b01e57SJeff Chen
104773b01e57SJeff Chen if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) {
104873b01e57SJeff Chen nxpwifi_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__);
104973b01e57SJeff Chen len += sizeof(struct nxpwifi_wep_param);
105073b01e57SJeff Chen km->key_param_set.len = cpu_to_le16(len);
105173b01e57SJeff Chen km->key_param_set.key_type = KEY_TYPE_ID_WEP;
105273b01e57SJeff Chen
105373b01e57SJeff Chen if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_UAP) {
105473b01e57SJeff Chen key_info |= KEY_MCAST | KEY_UNICAST;
105573b01e57SJeff Chen } else {
105673b01e57SJeff Chen if (enc_key->is_current_wep_key) {
105773b01e57SJeff Chen key_info |= KEY_MCAST | KEY_UNICAST;
105873b01e57SJeff Chen if (km->key_param_set.key_idx ==
105973b01e57SJeff Chen (priv->wep_key_curr_index & KEY_INDEX_MASK))
106073b01e57SJeff Chen key_info |= KEY_DEFAULT;
106173b01e57SJeff Chen } else {
106273b01e57SJeff Chen if (is_broadcast_ether_addr(mac))
106373b01e57SJeff Chen key_info |= KEY_MCAST;
106473b01e57SJeff Chen else
106573b01e57SJeff Chen key_info |= KEY_UNICAST | KEY_DEFAULT;
106673b01e57SJeff Chen }
106773b01e57SJeff Chen }
106873b01e57SJeff Chen km->key_param_set.key_info = cpu_to_le16(key_info);
106973b01e57SJeff Chen
107073b01e57SJeff Chen km->key_param_set.key_params.wep.key_len =
107173b01e57SJeff Chen cpu_to_le16(enc_key->key_len);
107273b01e57SJeff Chen memcpy(km->key_param_set.key_params.wep.key,
107373b01e57SJeff Chen enc_key->key_material, enc_key->key_len);
107473b01e57SJeff Chen
107573b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
107673b01e57SJeff Chen len + sizeof(km->action) + S_DS_GEN);
107773b01e57SJeff Chen return 0;
107873b01e57SJeff Chen }
107973b01e57SJeff Chen
108073b01e57SJeff Chen if (is_broadcast_ether_addr(mac))
108173b01e57SJeff Chen key_info |= KEY_MCAST | KEY_RX_KEY;
108273b01e57SJeff Chen else
108373b01e57SJeff Chen key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY;
108473b01e57SJeff Chen
108573b01e57SJeff Chen /* Enable default key for WPA/WPA2 */
108673b01e57SJeff Chen if (!priv->wpa_is_gtk_set)
108773b01e57SJeff Chen key_info |= KEY_DEFAULT;
108873b01e57SJeff Chen
108973b01e57SJeff Chen km->key_param_set.key_info = cpu_to_le16(key_info);
109073b01e57SJeff Chen
109173b01e57SJeff Chen if (enc_key->key_cipher != WLAN_CIPHER_SUITE_TKIP &&
109273b01e57SJeff Chen enc_key->key_len >= WLAN_KEY_LEN_CCMP)
109373b01e57SJeff Chen return nxpwifi_set_aes_key(priv, cmd, enc_key, km);
109473b01e57SJeff Chen
109573b01e57SJeff Chen if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
109673b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
109773b01e57SJeff Chen "%s: Set TKIP Key\n", __func__);
109873b01e57SJeff Chen if (enc_key->is_rx_seq_valid)
109973b01e57SJeff Chen memcpy(km->key_param_set.key_params.tkip.pn,
110073b01e57SJeff Chen enc_key->pn, enc_key->pn_len);
110173b01e57SJeff Chen km->key_param_set.key_type = KEY_TYPE_ID_TKIP;
110273b01e57SJeff Chen km->key_param_set.key_params.tkip.key_len =
110373b01e57SJeff Chen cpu_to_le16(enc_key->key_len);
110473b01e57SJeff Chen memcpy(km->key_param_set.key_params.tkip.key,
110573b01e57SJeff Chen enc_key->key_material, enc_key->key_len);
110673b01e57SJeff Chen
110773b01e57SJeff Chen len += sizeof(struct nxpwifi_tkip_param);
110873b01e57SJeff Chen km->key_param_set.len = cpu_to_le16(len);
110973b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct nxpwifi_ie_types_header) +
111073b01e57SJeff Chen len + sizeof(km->action) + S_DS_GEN);
111173b01e57SJeff Chen }
111273b01e57SJeff Chen
111373b01e57SJeff Chen return 0;
111473b01e57SJeff Chen }
111573b01e57SJeff Chen
111673b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)111773b01e57SJeff Chen nxpwifi_ret_sta_802_11_key_material(struct nxpwifi_private *priv,
111873b01e57SJeff Chen struct host_cmd_ds_command *resp,
111973b01e57SJeff Chen u16 cmdresp_no,
112073b01e57SJeff Chen void *data_buf)
112173b01e57SJeff Chen {
112273b01e57SJeff Chen struct host_cmd_ds_802_11_key_material *key;
112373b01e57SJeff Chen int len;
112473b01e57SJeff Chen
112573b01e57SJeff Chen key = &resp->params.key_material;
112673b01e57SJeff Chen
112773b01e57SJeff Chen len = le16_to_cpu(key->key_param_set.key_params.aes.key_len);
112873b01e57SJeff Chen if (len > sizeof(key->key_param_set.key_params.aes.key))
112973b01e57SJeff Chen return -EINVAL;
113073b01e57SJeff Chen
113173b01e57SJeff Chen if (le16_to_cpu(key->action) == HOST_ACT_GEN_SET) {
113273b01e57SJeff Chen if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
113373b01e57SJeff Chen nxpwifi_dbg(priv->adapter, INFO,
113473b01e57SJeff Chen "info: key: GTK is set\n");
113573b01e57SJeff Chen priv->wpa_is_gtk_set = true;
113673b01e57SJeff Chen priv->scan_block = false;
113773b01e57SJeff Chen priv->port_open = true;
113873b01e57SJeff Chen }
113973b01e57SJeff Chen }
114073b01e57SJeff Chen
114173b01e57SJeff Chen if (key->key_param_set.key_type != KEY_TYPE_ID_AES &&
114273b01e57SJeff Chen key->key_param_set.key_type != KEY_TYPE_ID_GCMP_256)
114373b01e57SJeff Chen return 0;
114473b01e57SJeff Chen
114573b01e57SJeff Chen memset(priv->aes_key.key_param_set.key_params.aes.key, 0,
114673b01e57SJeff Chen sizeof(key->key_param_set.key_params.aes.key));
114773b01e57SJeff Chen priv->aes_key.key_param_set.key_params.aes.key_len = cpu_to_le16(len);
114873b01e57SJeff Chen memcpy(priv->aes_key.key_param_set.key_params.aes.key,
114973b01e57SJeff Chen key->key_param_set.key_params.aes.key, len);
115073b01e57SJeff Chen
115173b01e57SJeff Chen return 0;
115273b01e57SJeff Chen }
115373b01e57SJeff Chen
115473b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)115573b01e57SJeff Chen nxpwifi_cmd_sta_802_11_bg_scan_config(struct nxpwifi_private *priv,
115673b01e57SJeff Chen struct host_cmd_ds_command *cmd,
115773b01e57SJeff Chen u16 cmd_no, void *data_buf,
115873b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
115973b01e57SJeff Chen {
116073b01e57SJeff Chen return nxpwifi_cmd_802_11_bg_scan_config(priv, cmd, data_buf);
116173b01e57SJeff Chen }
116273b01e57SJeff Chen
116373b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)116473b01e57SJeff Chen nxpwifi_cmd_sta_802_11_bg_scan_query(struct nxpwifi_private *priv,
116573b01e57SJeff Chen struct host_cmd_ds_command *cmd,
116673b01e57SJeff Chen u16 cmd_no, void *data_buf,
116773b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
116873b01e57SJeff Chen {
116973b01e57SJeff Chen return nxpwifi_cmd_802_11_bg_scan_query(cmd);
117073b01e57SJeff Chen }
117173b01e57SJeff Chen
117273b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)117373b01e57SJeff Chen nxpwifi_ret_sta_802_11_bg_scan_query(struct nxpwifi_private *priv,
117473b01e57SJeff Chen struct host_cmd_ds_command *resp,
117573b01e57SJeff Chen u16 cmdresp_no,
117673b01e57SJeff Chen void *data_buf)
117773b01e57SJeff Chen {
117873b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
117973b01e57SJeff Chen int ret;
118073b01e57SJeff Chen
118173b01e57SJeff Chen ret = nxpwifi_ret_802_11_scan(priv, resp);
118273b01e57SJeff Chen cfg80211_sched_scan_results(priv->wdev.wiphy, 0);
118373b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
118473b01e57SJeff Chen "info: CMD_RESP: BG_SCAN result is ready!\n");
118573b01e57SJeff Chen
118673b01e57SJeff Chen return ret;
118773b01e57SJeff Chen }
118873b01e57SJeff Chen
118973b01e57SJeff Chen static int
nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)119073b01e57SJeff Chen nxpwifi_cmd_sta_wmm_get_status(struct nxpwifi_private *priv,
119173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
119273b01e57SJeff Chen u16 cmd_no, void *data_buf,
119373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
119473b01e57SJeff Chen {
119573b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_WMM_GET_STATUS);
119673b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) +
119773b01e57SJeff Chen S_DS_GEN);
119873b01e57SJeff Chen
119973b01e57SJeff Chen return 0;
120073b01e57SJeff Chen }
120173b01e57SJeff Chen
120273b01e57SJeff Chen static int
nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)120373b01e57SJeff Chen nxpwifi_ret_sta_wmm_get_status(struct nxpwifi_private *priv,
120473b01e57SJeff Chen struct host_cmd_ds_command *resp,
120573b01e57SJeff Chen u16 cmdresp_no,
120673b01e57SJeff Chen void *data_buf)
120773b01e57SJeff Chen {
120873b01e57SJeff Chen return nxpwifi_ret_wmm_get_status(priv, resp);
120973b01e57SJeff Chen }
121073b01e57SJeff Chen
121173b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)121273b01e57SJeff Chen nxpwifi_cmd_sta_802_11_subsc_evt(struct nxpwifi_private *priv,
121373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
121473b01e57SJeff Chen u16 cmd_no, void *data_buf,
121573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
121673b01e57SJeff Chen {
121773b01e57SJeff Chen struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt;
121873b01e57SJeff Chen struct nxpwifi_ds_misc_subsc_evt *subsc_evt_cfg =
121973b01e57SJeff Chen (struct nxpwifi_ds_misc_subsc_evt *)data_buf;
122073b01e57SJeff Chen struct nxpwifi_ie_types_rssi_threshold *rssi_tlv;
122173b01e57SJeff Chen u16 event_bitmap;
122273b01e57SJeff Chen u8 *pos;
122373b01e57SJeff Chen
122473b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_SUBSCRIBE_EVENT);
122573b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) +
122673b01e57SJeff Chen S_DS_GEN);
122773b01e57SJeff Chen
122873b01e57SJeff Chen subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action);
122973b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
123073b01e57SJeff Chen "cmd: action: %d\n", subsc_evt_cfg->action);
123173b01e57SJeff Chen
123273b01e57SJeff Chen /* For query requests, no configuration TLV structures are to be added. */
123373b01e57SJeff Chen if (subsc_evt_cfg->action == HOST_ACT_GEN_GET)
123473b01e57SJeff Chen return 0;
123573b01e57SJeff Chen
123673b01e57SJeff Chen subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events);
123773b01e57SJeff Chen
123873b01e57SJeff Chen event_bitmap = subsc_evt_cfg->events;
123973b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n",
124073b01e57SJeff Chen event_bitmap);
124173b01e57SJeff Chen
124273b01e57SJeff Chen if ((subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR ||
124373b01e57SJeff Chen subsc_evt_cfg->action == HOST_ACT_BITWISE_SET) &&
124473b01e57SJeff Chen event_bitmap == 0) {
124573b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
124673b01e57SJeff Chen "Error: No event specified\t"
124773b01e57SJeff Chen "for bitwise action type\n");
124873b01e57SJeff Chen return -EINVAL;
124973b01e57SJeff Chen }
125073b01e57SJeff Chen
125173b01e57SJeff Chen /*
125273b01e57SJeff Chen * Append TLV structures for each of the specified events for
125373b01e57SJeff Chen * subscribing or re-configuring. This is not required for
125473b01e57SJeff Chen * bitwise unsubscribing request.
125573b01e57SJeff Chen */
125673b01e57SJeff Chen if (subsc_evt_cfg->action == HOST_ACT_BITWISE_CLR)
125773b01e57SJeff Chen return 0;
125873b01e57SJeff Chen
125973b01e57SJeff Chen pos = ((u8 *)subsc_evt) +
126073b01e57SJeff Chen sizeof(struct host_cmd_ds_802_11_subsc_evt);
126173b01e57SJeff Chen
126273b01e57SJeff Chen if (event_bitmap & BITMASK_BCN_RSSI_LOW) {
126373b01e57SJeff Chen rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos;
126473b01e57SJeff Chen
126573b01e57SJeff Chen rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW);
126673b01e57SJeff Chen rssi_tlv->header.len =
126773b01e57SJeff Chen cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) -
126873b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
126973b01e57SJeff Chen rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value;
127073b01e57SJeff Chen rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq;
127173b01e57SJeff Chen
127273b01e57SJeff Chen nxpwifi_dbg(priv->adapter, EVENT,
127373b01e57SJeff Chen "Cfg Beacon Low Rssi event,\t"
127473b01e57SJeff Chen "RSSI:-%d dBm, Freq:%d\n",
127573b01e57SJeff Chen subsc_evt_cfg->bcn_l_rssi_cfg.abs_value,
127673b01e57SJeff Chen subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq);
127773b01e57SJeff Chen
127873b01e57SJeff Chen pos += sizeof(struct nxpwifi_ie_types_rssi_threshold);
127973b01e57SJeff Chen le16_unaligned_add_cpu
128073b01e57SJeff Chen (&cmd->size,
128173b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_rssi_threshold));
128273b01e57SJeff Chen }
128373b01e57SJeff Chen
128473b01e57SJeff Chen if (event_bitmap & BITMASK_BCN_RSSI_HIGH) {
128573b01e57SJeff Chen rssi_tlv = (struct nxpwifi_ie_types_rssi_threshold *)pos;
128673b01e57SJeff Chen
128773b01e57SJeff Chen rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
128873b01e57SJeff Chen rssi_tlv->header.len =
128973b01e57SJeff Chen cpu_to_le16(sizeof(struct nxpwifi_ie_types_rssi_threshold) -
129073b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
129173b01e57SJeff Chen rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value;
129273b01e57SJeff Chen rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq;
129373b01e57SJeff Chen
129473b01e57SJeff Chen nxpwifi_dbg(priv->adapter, EVENT,
129573b01e57SJeff Chen "Cfg Beacon High Rssi event,\t"
129673b01e57SJeff Chen "RSSI:-%d dBm, Freq:%d\n",
129773b01e57SJeff Chen subsc_evt_cfg->bcn_h_rssi_cfg.abs_value,
129873b01e57SJeff Chen subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq);
129973b01e57SJeff Chen
130073b01e57SJeff Chen pos += sizeof(struct nxpwifi_ie_types_rssi_threshold);
130173b01e57SJeff Chen le16_unaligned_add_cpu
130273b01e57SJeff Chen (&cmd->size,
130373b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_rssi_threshold));
130473b01e57SJeff Chen }
130573b01e57SJeff Chen
130673b01e57SJeff Chen return 0;
130773b01e57SJeff Chen }
130873b01e57SJeff Chen
130973b01e57SJeff Chen static int
nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)131073b01e57SJeff Chen nxpwifi_ret_sta_subsc_evt(struct nxpwifi_private *priv,
131173b01e57SJeff Chen struct host_cmd_ds_command *resp,
131273b01e57SJeff Chen u16 cmdresp_no,
131373b01e57SJeff Chen void *data_buf)
131473b01e57SJeff Chen {
131573b01e57SJeff Chen struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event =
131673b01e57SJeff Chen &resp->params.subsc_evt;
131773b01e57SJeff Chen
131873b01e57SJeff Chen /*
131973b01e57SJeff Chen * For every subscribe event command (Get/Set/Clear), FW reports the current
132073b01e57SJeff Chen * set of subscribed events
132173b01e57SJeff Chen */
132273b01e57SJeff Chen nxpwifi_dbg(priv->adapter, EVENT,
132373b01e57SJeff Chen "Bitmap of currently subscribed events: %16x\n",
132473b01e57SJeff Chen le16_to_cpu(cmd_sub_event->events));
132573b01e57SJeff Chen
132673b01e57SJeff Chen return 0;
132773b01e57SJeff Chen }
132873b01e57SJeff Chen
132973b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)133073b01e57SJeff Chen nxpwifi_cmd_sta_802_11_tx_rate_query(struct nxpwifi_private *priv,
133173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
133273b01e57SJeff Chen u16 cmd_no, void *data_buf,
133373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
133473b01e57SJeff Chen {
133573b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_TX_RATE_QUERY);
133673b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) +
133773b01e57SJeff Chen S_DS_GEN);
133873b01e57SJeff Chen priv->tx_rate = 0;
133973b01e57SJeff Chen
134073b01e57SJeff Chen return 0;
134173b01e57SJeff Chen }
134273b01e57SJeff Chen
134373b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)134473b01e57SJeff Chen nxpwifi_ret_sta_802_11_tx_rate_query(struct nxpwifi_private *priv,
134573b01e57SJeff Chen struct host_cmd_ds_command *resp,
134673b01e57SJeff Chen u16 cmdresp_no,
134773b01e57SJeff Chen void *data_buf)
134873b01e57SJeff Chen {
134973b01e57SJeff Chen priv->tx_rate = resp->params.tx_rate.tx_rate;
135073b01e57SJeff Chen priv->tx_htinfo = resp->params.tx_rate.ht_info;
135173b01e57SJeff Chen if (!priv->is_data_rate_auto)
135273b01e57SJeff Chen priv->data_rate =
135373b01e57SJeff Chen nxpwifi_index_to_data_rate(priv, priv->tx_rate,
135473b01e57SJeff Chen priv->tx_htinfo);
135573b01e57SJeff Chen
135673b01e57SJeff Chen return 0;
135773b01e57SJeff Chen }
135873b01e57SJeff Chen
135973b01e57SJeff Chen static int
nxpwifi_cmd_sta_mem_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)136073b01e57SJeff Chen nxpwifi_cmd_sta_mem_access(struct nxpwifi_private *priv,
136173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
136273b01e57SJeff Chen u16 cmd_no, void *data_buf,
136373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
136473b01e57SJeff Chen {
136573b01e57SJeff Chen struct nxpwifi_ds_mem_rw *mem_rw =
136673b01e57SJeff Chen (struct nxpwifi_ds_mem_rw *)data_buf;
136773b01e57SJeff Chen struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem;
136873b01e57SJeff Chen
136973b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_MEM_ACCESS);
137073b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) +
137173b01e57SJeff Chen S_DS_GEN);
137273b01e57SJeff Chen
137373b01e57SJeff Chen mem_access->action = cpu_to_le16(cmd_action);
137473b01e57SJeff Chen mem_access->addr = cpu_to_le32(mem_rw->addr);
137573b01e57SJeff Chen mem_access->value = cpu_to_le32(mem_rw->value);
137673b01e57SJeff Chen
137773b01e57SJeff Chen return 0;
137873b01e57SJeff Chen }
137973b01e57SJeff Chen
138073b01e57SJeff Chen static int
nxpwifi_ret_sta_mem_access(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)138173b01e57SJeff Chen nxpwifi_ret_sta_mem_access(struct nxpwifi_private *priv,
138273b01e57SJeff Chen struct host_cmd_ds_command *resp,
138373b01e57SJeff Chen u16 cmdresp_no,
138473b01e57SJeff Chen void *data_buf)
138573b01e57SJeff Chen {
138673b01e57SJeff Chen struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem;
138773b01e57SJeff Chen
138873b01e57SJeff Chen priv->mem_rw.addr = le32_to_cpu(mem->addr);
138973b01e57SJeff Chen priv->mem_rw.value = le32_to_cpu(mem->value);
139073b01e57SJeff Chen
139173b01e57SJeff Chen return 0;
139273b01e57SJeff Chen }
139373b01e57SJeff Chen
nxpwifi_parse_cal_cfg(u8 * src,size_t len,u8 * dst)139473b01e57SJeff Chen static u32 nxpwifi_parse_cal_cfg(u8 *src, size_t len, u8 *dst)
139573b01e57SJeff Chen {
139673b01e57SJeff Chen u8 *s = src, *d = dst;
139773b01e57SJeff Chen
139873b01e57SJeff Chen while (s - src < len) {
139973b01e57SJeff Chen if (*s && (isspace(*s) || *s == '\t')) {
140073b01e57SJeff Chen s++;
140173b01e57SJeff Chen continue;
140273b01e57SJeff Chen }
140373b01e57SJeff Chen if (isxdigit(*s)) {
140473b01e57SJeff Chen if (kstrtou8(s, 16, d))
140573b01e57SJeff Chen return 0;
140673b01e57SJeff Chen d++;
140773b01e57SJeff Chen s += 2;
140873b01e57SJeff Chen } else {
140973b01e57SJeff Chen s++;
141073b01e57SJeff Chen }
141173b01e57SJeff Chen }
141273b01e57SJeff Chen
141373b01e57SJeff Chen return d - dst;
141473b01e57SJeff Chen }
141573b01e57SJeff Chen
141673b01e57SJeff Chen static int
nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)141773b01e57SJeff Chen nxpwifi_cmd_sta_cfg_data(struct nxpwifi_private *priv,
141873b01e57SJeff Chen struct host_cmd_ds_command *cmd,
141973b01e57SJeff Chen u16 cmd_no, void *data_buf,
142073b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
142173b01e57SJeff Chen {
142273b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
142373b01e57SJeff Chen u32 len;
142473b01e57SJeff Chen u8 *data = (u8 *)cmd + S_DS_GEN;
142573b01e57SJeff Chen
142673b01e57SJeff Chen if (adapter->cal_data->data && adapter->cal_data->size > 0) {
142773b01e57SJeff Chen len = nxpwifi_parse_cal_cfg((u8 *)adapter->cal_data->data,
142873b01e57SJeff Chen adapter->cal_data->size, data);
142973b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
143073b01e57SJeff Chen "download cfg_data from config file\n");
143173b01e57SJeff Chen } else {
143273b01e57SJeff Chen return -EINVAL;
143373b01e57SJeff Chen }
143473b01e57SJeff Chen
143573b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_CFG_DATA);
143673b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN + len);
143773b01e57SJeff Chen
143873b01e57SJeff Chen return 0;
143973b01e57SJeff Chen }
144073b01e57SJeff Chen
144173b01e57SJeff Chen static int
nxpwifi_ret_sta_cfg_data(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)144273b01e57SJeff Chen nxpwifi_ret_sta_cfg_data(struct nxpwifi_private *priv,
144373b01e57SJeff Chen struct host_cmd_ds_command *resp,
144473b01e57SJeff Chen u16 cmdresp_no,
144573b01e57SJeff Chen void *data_buf)
144673b01e57SJeff Chen {
144773b01e57SJeff Chen if (resp->result != HOST_RESULT_OK) {
144873b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n");
144973b01e57SJeff Chen return -EINVAL;
145073b01e57SJeff Chen }
145173b01e57SJeff Chen
145273b01e57SJeff Chen return 0;
145373b01e57SJeff Chen }
145473b01e57SJeff Chen
145573b01e57SJeff Chen static int
nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)145673b01e57SJeff Chen nxpwifi_cmd_sta_ver_ext(struct nxpwifi_private *priv,
145773b01e57SJeff Chen struct host_cmd_ds_command *cmd,
145873b01e57SJeff Chen u16 cmd_no, void *data_buf,
145973b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
146073b01e57SJeff Chen {
146173b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
146273b01e57SJeff Chen cmd->params.verext.version_str_sel =
146373b01e57SJeff Chen (u8)(get_unaligned((u32 *)data_buf));
146473b01e57SJeff Chen memcpy(&cmd->params, data_buf, sizeof(struct host_cmd_ds_version_ext));
146573b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) +
146673b01e57SJeff Chen S_DS_GEN);
146773b01e57SJeff Chen
146873b01e57SJeff Chen return 0;
146973b01e57SJeff Chen }
147073b01e57SJeff Chen
147173b01e57SJeff Chen static int
nxpwifi_ret_sta_ver_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)147273b01e57SJeff Chen nxpwifi_ret_sta_ver_ext(struct nxpwifi_private *priv,
147373b01e57SJeff Chen struct host_cmd_ds_command *resp,
147473b01e57SJeff Chen u16 cmdresp_no,
147573b01e57SJeff Chen void *data_buf)
147673b01e57SJeff Chen {
147773b01e57SJeff Chen struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
147873b01e57SJeff Chen struct host_cmd_ds_version_ext *version_ext =
147973b01e57SJeff Chen (struct host_cmd_ds_version_ext *)data_buf;
148073b01e57SJeff Chen
148173b01e57SJeff Chen if (test_and_clear_bit(NXPWIFI_IS_REQUESTING_FW_VEREXT, &priv->adapter->work_flags)) {
148273b01e57SJeff Chen if (strncmp(ver_ext->version_str, "ChipRev:20, BB:9b(10.00), RF:40(21)",
148373b01e57SJeff Chen NXPWIFI_VERSION_STR_LENGTH) == 0) {
148473b01e57SJeff Chen struct nxpwifi_ds_auto_ds auto_ds = {
148573b01e57SJeff Chen .auto_ds = DEEP_SLEEP_OFF,
148673b01e57SJeff Chen };
148773b01e57SJeff Chen
148873b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
148973b01e57SJeff Chen "Bad HW revision detected, disabling deep sleep\n");
149073b01e57SJeff Chen
149173b01e57SJeff Chen if (nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH,
149273b01e57SJeff Chen DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, false)) {
149373b01e57SJeff Chen nxpwifi_dbg(priv->adapter, MSG,
149473b01e57SJeff Chen "Disabling deep sleep failed.\n");
149573b01e57SJeff Chen }
149673b01e57SJeff Chen }
149773b01e57SJeff Chen
149873b01e57SJeff Chen return 0;
149973b01e57SJeff Chen }
150073b01e57SJeff Chen
150173b01e57SJeff Chen if (version_ext) {
150273b01e57SJeff Chen version_ext->version_str_sel = ver_ext->version_str_sel;
150373b01e57SJeff Chen memcpy(version_ext->version_str, ver_ext->version_str,
150473b01e57SJeff Chen NXPWIFI_VERSION_STR_LENGTH);
150573b01e57SJeff Chen memcpy(priv->version_str, ver_ext->version_str,
150673b01e57SJeff Chen NXPWIFI_VERSION_STR_LENGTH);
150773b01e57SJeff Chen
150873b01e57SJeff Chen /* Ensure the version string from the firmware is 0-terminated */
150973b01e57SJeff Chen priv->version_str[NXPWIFI_VERSION_STR_LENGTH - 1] = '\0';
151073b01e57SJeff Chen }
151173b01e57SJeff Chen return 0;
151273b01e57SJeff Chen }
151373b01e57SJeff Chen
151473b01e57SJeff Chen static int
nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private * priv,struct nxpwifi_mef_entry * mef_entry,u8 ** buffer)151573b01e57SJeff Chen nxpwifi_cmd_append_rpn_expression(struct nxpwifi_private *priv,
151673b01e57SJeff Chen struct nxpwifi_mef_entry *mef_entry,
151773b01e57SJeff Chen u8 **buffer)
151873b01e57SJeff Chen {
151973b01e57SJeff Chen struct nxpwifi_mef_filter *filter = mef_entry->filter;
152073b01e57SJeff Chen int i, byte_len;
152173b01e57SJeff Chen u8 *stack_ptr = *buffer;
152273b01e57SJeff Chen
152373b01e57SJeff Chen for (i = 0; i < NXPWIFI_MEF_MAX_FILTERS; i++) {
152473b01e57SJeff Chen filter = &mef_entry->filter[i];
152573b01e57SJeff Chen if (!filter->filt_type)
152673b01e57SJeff Chen break;
152773b01e57SJeff Chen put_unaligned_le32((u32)filter->repeat, stack_ptr);
152873b01e57SJeff Chen stack_ptr += 4;
152973b01e57SJeff Chen *stack_ptr = TYPE_DNUM;
153073b01e57SJeff Chen stack_ptr += 1;
153173b01e57SJeff Chen
153273b01e57SJeff Chen byte_len = filter->byte_seq[NXPWIFI_MEF_MAX_BYTESEQ];
153373b01e57SJeff Chen memcpy(stack_ptr, filter->byte_seq, byte_len);
153473b01e57SJeff Chen stack_ptr += byte_len;
153573b01e57SJeff Chen *stack_ptr = byte_len;
153673b01e57SJeff Chen stack_ptr += 1;
153773b01e57SJeff Chen *stack_ptr = TYPE_BYTESEQ;
153873b01e57SJeff Chen stack_ptr += 1;
153973b01e57SJeff Chen put_unaligned_le32((u32)filter->offset, stack_ptr);
154073b01e57SJeff Chen stack_ptr += 4;
154173b01e57SJeff Chen *stack_ptr = TYPE_DNUM;
154273b01e57SJeff Chen stack_ptr += 1;
154373b01e57SJeff Chen
154473b01e57SJeff Chen *stack_ptr = filter->filt_type;
154573b01e57SJeff Chen stack_ptr += 1;
154673b01e57SJeff Chen
154773b01e57SJeff Chen if (filter->filt_action) {
154873b01e57SJeff Chen *stack_ptr = filter->filt_action;
154973b01e57SJeff Chen stack_ptr += 1;
155073b01e57SJeff Chen }
155173b01e57SJeff Chen
155273b01e57SJeff Chen if (stack_ptr - *buffer > STACK_NBYTES)
155373b01e57SJeff Chen return -ENOMEM;
155473b01e57SJeff Chen }
155573b01e57SJeff Chen
155673b01e57SJeff Chen *buffer = stack_ptr;
155773b01e57SJeff Chen return 0;
155873b01e57SJeff Chen }
155973b01e57SJeff Chen
156073b01e57SJeff Chen static int
nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)156173b01e57SJeff Chen nxpwifi_cmd_sta_mef_cfg(struct nxpwifi_private *priv,
156273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
156373b01e57SJeff Chen u16 cmd_no, void *data_buf,
156473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
156573b01e57SJeff Chen {
156673b01e57SJeff Chen struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg;
156773b01e57SJeff Chen struct nxpwifi_ds_mef_cfg *mef =
156873b01e57SJeff Chen (struct nxpwifi_ds_mef_cfg *)data_buf;
156973b01e57SJeff Chen struct nxpwifi_fw_mef_entry *mef_entry = NULL;
157073b01e57SJeff Chen u8 *pos = (u8 *)mef_cfg;
157173b01e57SJeff Chen u16 i;
157273b01e57SJeff Chen int ret = 0;
157373b01e57SJeff Chen
157473b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_MEF_CFG);
157573b01e57SJeff Chen
157673b01e57SJeff Chen mef_cfg->criteria = cpu_to_le32(mef->criteria);
157773b01e57SJeff Chen mef_cfg->num_entries = cpu_to_le16(mef->num_entries);
157873b01e57SJeff Chen pos += sizeof(*mef_cfg);
157973b01e57SJeff Chen
158073b01e57SJeff Chen for (i = 0; i < mef->num_entries; i++) {
158173b01e57SJeff Chen mef_entry = (struct nxpwifi_fw_mef_entry *)pos;
158273b01e57SJeff Chen mef_entry->mode = mef->mef_entry[i].mode;
158373b01e57SJeff Chen mef_entry->action = mef->mef_entry[i].action;
158473b01e57SJeff Chen pos += sizeof(*mef_entry);
158573b01e57SJeff Chen
158673b01e57SJeff Chen ret = nxpwifi_cmd_append_rpn_expression(priv,
158773b01e57SJeff Chen &mef->mef_entry[i],
158873b01e57SJeff Chen &pos);
158973b01e57SJeff Chen if (ret)
159073b01e57SJeff Chen return ret;
159173b01e57SJeff Chen
159273b01e57SJeff Chen mef_entry->exprsize =
159373b01e57SJeff Chen cpu_to_le16(pos - mef_entry->expr);
159473b01e57SJeff Chen }
159573b01e57SJeff Chen cmd->size = cpu_to_le16((u16)(pos - (u8 *)mef_cfg) + S_DS_GEN);
159673b01e57SJeff Chen
159773b01e57SJeff Chen return ret;
159873b01e57SJeff Chen }
159973b01e57SJeff Chen
160073b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)160173b01e57SJeff Chen nxpwifi_cmd_sta_802_11_rssi_info(struct nxpwifi_private *priv,
160273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
160373b01e57SJeff Chen u16 cmd_no, void *data_buf,
160473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
160573b01e57SJeff Chen {
160673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_RSSI_INFO);
160773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) +
160873b01e57SJeff Chen S_DS_GEN);
160973b01e57SJeff Chen cmd->params.rssi_info.action = cpu_to_le16(cmd_action);
161073b01e57SJeff Chen cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor);
161173b01e57SJeff Chen cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor);
161273b01e57SJeff Chen
161373b01e57SJeff Chen /* Reset SNR/NF/RSSI values in private structure */
161473b01e57SJeff Chen priv->data_rssi_last = 0;
161573b01e57SJeff Chen priv->data_nf_last = 0;
161673b01e57SJeff Chen priv->data_rssi_avg = 0;
161773b01e57SJeff Chen priv->data_nf_avg = 0;
161873b01e57SJeff Chen priv->bcn_rssi_last = 0;
161973b01e57SJeff Chen priv->bcn_nf_last = 0;
162073b01e57SJeff Chen priv->bcn_rssi_avg = 0;
162173b01e57SJeff Chen priv->bcn_nf_avg = 0;
162273b01e57SJeff Chen
162373b01e57SJeff Chen return 0;
162473b01e57SJeff Chen }
162573b01e57SJeff Chen
162673b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)162773b01e57SJeff Chen nxpwifi_ret_sta_802_11_rssi_info(struct nxpwifi_private *priv,
162873b01e57SJeff Chen struct host_cmd_ds_command *resp,
162973b01e57SJeff Chen u16 cmdresp_no,
163073b01e57SJeff Chen void *data_buf)
163173b01e57SJeff Chen {
163273b01e57SJeff Chen struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
163373b01e57SJeff Chen &resp->params.rssi_info_rsp;
163473b01e57SJeff Chen struct nxpwifi_ds_misc_subsc_evt *subsc_evt =
163573b01e57SJeff Chen &priv->async_subsc_evt_storage;
163673b01e57SJeff Chen
163773b01e57SJeff Chen priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
163873b01e57SJeff Chen priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
163973b01e57SJeff Chen
164073b01e57SJeff Chen priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg);
164173b01e57SJeff Chen priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg);
164273b01e57SJeff Chen
164373b01e57SJeff Chen priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last);
164473b01e57SJeff Chen priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last);
164573b01e57SJeff Chen
164673b01e57SJeff Chen priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg);
164773b01e57SJeff Chen priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
164873b01e57SJeff Chen
164973b01e57SJeff Chen if (priv->subsc_evt_rssi_state == EVENT_HANDLED)
165073b01e57SJeff Chen return 0;
165173b01e57SJeff Chen
165273b01e57SJeff Chen memset(subsc_evt, 0x00, sizeof(struct nxpwifi_ds_misc_subsc_evt));
165373b01e57SJeff Chen
165473b01e57SJeff Chen /* Resubscribe low and high rssi events with new thresholds */
165573b01e57SJeff Chen subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
165673b01e57SJeff Chen subsc_evt->action = HOST_ACT_BITWISE_SET;
165773b01e57SJeff Chen if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) {
165873b01e57SJeff Chen subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg -
165973b01e57SJeff Chen priv->cqm_rssi_hyst);
166073b01e57SJeff Chen subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
166173b01e57SJeff Chen } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) {
166273b01e57SJeff Chen subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold);
166373b01e57SJeff Chen subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg +
166473b01e57SJeff Chen priv->cqm_rssi_hyst);
166573b01e57SJeff Chen }
166673b01e57SJeff Chen subsc_evt->bcn_l_rssi_cfg.evt_freq = 1;
166773b01e57SJeff Chen subsc_evt->bcn_h_rssi_cfg.evt_freq = 1;
166873b01e57SJeff Chen
166973b01e57SJeff Chen priv->subsc_evt_rssi_state = EVENT_HANDLED;
167073b01e57SJeff Chen
167173b01e57SJeff Chen nxpwifi_send_cmd(priv, HOST_CMD_802_11_SUBSCRIBE_EVENT,
167273b01e57SJeff Chen 0, 0, subsc_evt, false);
167373b01e57SJeff Chen
167473b01e57SJeff Chen return 0;
167573b01e57SJeff Chen }
167673b01e57SJeff Chen
167773b01e57SJeff Chen static int
nxpwifi_cmd_sta_func_init(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)167873b01e57SJeff Chen nxpwifi_cmd_sta_func_init(struct nxpwifi_private *priv,
167973b01e57SJeff Chen struct host_cmd_ds_command *cmd,
168073b01e57SJeff Chen u16 cmd_no, void *data_buf,
168173b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
168273b01e57SJeff Chen {
168373b01e57SJeff Chen if (priv->adapter->hw_status == NXPWIFI_HW_STATUS_RESET)
168473b01e57SJeff Chen priv->adapter->hw_status = NXPWIFI_HW_STATUS_READY;
168573b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
168673b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN);
168773b01e57SJeff Chen
168873b01e57SJeff Chen return 0;
168973b01e57SJeff Chen }
169073b01e57SJeff Chen
169173b01e57SJeff Chen static int
nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)169273b01e57SJeff Chen nxpwifi_cmd_sta_func_shutdown(struct nxpwifi_private *priv,
169373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
169473b01e57SJeff Chen u16 cmd_no, void *data_buf,
169573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
169673b01e57SJeff Chen {
169773b01e57SJeff Chen priv->adapter->hw_status = NXPWIFI_HW_STATUS_RESET;
169873b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
169973b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN);
170073b01e57SJeff Chen
170173b01e57SJeff Chen return 0;
170273b01e57SJeff Chen }
170373b01e57SJeff Chen
170473b01e57SJeff Chen static int
nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)170573b01e57SJeff Chen nxpwifi_cmd_sta_11n_cfg(struct nxpwifi_private *priv,
170673b01e57SJeff Chen struct host_cmd_ds_command *cmd,
170773b01e57SJeff Chen u16 cmd_no, void *data_buf,
170873b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
170973b01e57SJeff Chen {
171073b01e57SJeff Chen return nxpwifi_cmd_11n_cfg(priv, cmd, cmd_action, data_buf);
171173b01e57SJeff Chen }
171273b01e57SJeff Chen
171373b01e57SJeff Chen static int
nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)171473b01e57SJeff Chen nxpwifi_cmd_sta_11n_addba_req(struct nxpwifi_private *priv,
171573b01e57SJeff Chen struct host_cmd_ds_command *cmd,
171673b01e57SJeff Chen u16 cmd_no, void *data_buf,
171773b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
171873b01e57SJeff Chen {
171973b01e57SJeff Chen return nxpwifi_cmd_11n_addba_req(cmd, data_buf);
172073b01e57SJeff Chen }
172173b01e57SJeff Chen
172273b01e57SJeff Chen static int
nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)172373b01e57SJeff Chen nxpwifi_ret_sta_11n_addba_req(struct nxpwifi_private *priv,
172473b01e57SJeff Chen struct host_cmd_ds_command *resp,
172573b01e57SJeff Chen u16 cmdresp_no,
172673b01e57SJeff Chen void *data_buf)
172773b01e57SJeff Chen {
172873b01e57SJeff Chen return nxpwifi_ret_11n_addba_req(priv, resp);
172973b01e57SJeff Chen }
173073b01e57SJeff Chen
173173b01e57SJeff Chen static int
nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)173273b01e57SJeff Chen nxpwifi_cmd_sta_11n_addba_rsp(struct nxpwifi_private *priv,
173373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
173473b01e57SJeff Chen u16 cmd_no, void *data_buf,
173573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
173673b01e57SJeff Chen {
173773b01e57SJeff Chen return nxpwifi_cmd_11n_addba_rsp_gen(priv, cmd, data_buf);
173873b01e57SJeff Chen }
173973b01e57SJeff Chen
174073b01e57SJeff Chen static int
nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)174173b01e57SJeff Chen nxpwifi_ret_sta_11n_addba_rsp(struct nxpwifi_private *priv,
174273b01e57SJeff Chen struct host_cmd_ds_command *resp,
174373b01e57SJeff Chen u16 cmdresp_no,
174473b01e57SJeff Chen void *data_buf)
174573b01e57SJeff Chen {
174673b01e57SJeff Chen return nxpwifi_ret_11n_addba_resp(priv, resp);
174773b01e57SJeff Chen }
174873b01e57SJeff Chen
174973b01e57SJeff Chen static int
nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)175073b01e57SJeff Chen nxpwifi_cmd_sta_11n_delba(struct nxpwifi_private *priv,
175173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
175273b01e57SJeff Chen u16 cmd_no, void *data_buf,
175373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
175473b01e57SJeff Chen {
175573b01e57SJeff Chen return nxpwifi_cmd_11n_delba(cmd, data_buf);
175673b01e57SJeff Chen }
175773b01e57SJeff Chen
175873b01e57SJeff Chen static int
nxpwifi_ret_sta_11n_delba(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)175973b01e57SJeff Chen nxpwifi_ret_sta_11n_delba(struct nxpwifi_private *priv,
176073b01e57SJeff Chen struct host_cmd_ds_command *resp,
176173b01e57SJeff Chen u16 cmdresp_no,
176273b01e57SJeff Chen void *data_buf)
176373b01e57SJeff Chen {
176473b01e57SJeff Chen return nxpwifi_ret_11n_delba(priv, resp);
176573b01e57SJeff Chen }
176673b01e57SJeff Chen
176773b01e57SJeff Chen static int
nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)176873b01e57SJeff Chen nxpwifi_cmd_sta_tx_power_cfg(struct nxpwifi_private *priv,
176973b01e57SJeff Chen struct host_cmd_ds_command *cmd,
177073b01e57SJeff Chen u16 cmd_no, void *data_buf,
177173b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
177273b01e57SJeff Chen {
177373b01e57SJeff Chen struct nxpwifi_types_power_group *pg_tlv;
177473b01e57SJeff Chen struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
177573b01e57SJeff Chen struct host_cmd_ds_txpwr_cfg *txp =
177673b01e57SJeff Chen (struct host_cmd_ds_txpwr_cfg *)data_buf;
177773b01e57SJeff Chen
177873b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_TXPWR_CFG);
177973b01e57SJeff Chen cmd->size =
178073b01e57SJeff Chen cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
178173b01e57SJeff Chen switch (cmd_action) {
178273b01e57SJeff Chen case HOST_ACT_GEN_SET:
178373b01e57SJeff Chen if (txp->mode) {
178473b01e57SJeff Chen pg_tlv = (struct nxpwifi_types_power_group
178573b01e57SJeff Chen *)((unsigned long)txp +
178673b01e57SJeff Chen sizeof(struct host_cmd_ds_txpwr_cfg));
178773b01e57SJeff Chen memmove(cmd_txp_cfg, txp,
178873b01e57SJeff Chen sizeof(struct host_cmd_ds_txpwr_cfg) +
178973b01e57SJeff Chen sizeof(struct nxpwifi_types_power_group) +
179073b01e57SJeff Chen le16_to_cpu(pg_tlv->length));
179173b01e57SJeff Chen
179273b01e57SJeff Chen pg_tlv = (struct nxpwifi_types_power_group *)((u8 *)
179373b01e57SJeff Chen cmd_txp_cfg +
179473b01e57SJeff Chen sizeof(struct host_cmd_ds_txpwr_cfg));
179573b01e57SJeff Chen cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) +
179673b01e57SJeff Chen sizeof(struct nxpwifi_types_power_group) +
179773b01e57SJeff Chen le16_to_cpu(pg_tlv->length));
179873b01e57SJeff Chen } else {
179973b01e57SJeff Chen memmove(cmd_txp_cfg, txp, sizeof(*txp));
180073b01e57SJeff Chen }
180173b01e57SJeff Chen cmd_txp_cfg->action = cpu_to_le16(cmd_action);
180273b01e57SJeff Chen break;
180373b01e57SJeff Chen case HOST_ACT_GEN_GET:
180473b01e57SJeff Chen cmd_txp_cfg->action = cpu_to_le16(cmd_action);
180573b01e57SJeff Chen break;
180673b01e57SJeff Chen }
180773b01e57SJeff Chen
180873b01e57SJeff Chen return 0;
180973b01e57SJeff Chen }
181073b01e57SJeff Chen
nxpwifi_get_power_level(struct nxpwifi_private * priv,void * data_buf)181173b01e57SJeff Chen static int nxpwifi_get_power_level(struct nxpwifi_private *priv, void *data_buf)
181273b01e57SJeff Chen {
181373b01e57SJeff Chen int length, max_power = -1, min_power = -1;
181473b01e57SJeff Chen struct nxpwifi_types_power_group *pg_tlv_hdr;
181573b01e57SJeff Chen struct nxpwifi_power_group *pg;
181673b01e57SJeff Chen
181773b01e57SJeff Chen if (!data_buf)
181873b01e57SJeff Chen return -ENOMEM;
181973b01e57SJeff Chen
182073b01e57SJeff Chen pg_tlv_hdr = (struct nxpwifi_types_power_group *)((u8 *)data_buf);
182173b01e57SJeff Chen pg = (struct nxpwifi_power_group *)
182273b01e57SJeff Chen ((u8 *)pg_tlv_hdr + sizeof(struct nxpwifi_types_power_group));
182373b01e57SJeff Chen length = le16_to_cpu(pg_tlv_hdr->length);
182473b01e57SJeff Chen
182573b01e57SJeff Chen /* At least one structure required to update power */
182673b01e57SJeff Chen if (length < sizeof(struct nxpwifi_power_group))
182773b01e57SJeff Chen return 0;
182873b01e57SJeff Chen
182973b01e57SJeff Chen max_power = pg->power_max;
183073b01e57SJeff Chen min_power = pg->power_min;
183173b01e57SJeff Chen length -= sizeof(struct nxpwifi_power_group);
183273b01e57SJeff Chen
183373b01e57SJeff Chen while (length >= sizeof(struct nxpwifi_power_group)) {
183473b01e57SJeff Chen pg++;
183573b01e57SJeff Chen if (max_power < pg->power_max)
183673b01e57SJeff Chen max_power = pg->power_max;
183773b01e57SJeff Chen
183873b01e57SJeff Chen if (min_power > pg->power_min)
183973b01e57SJeff Chen min_power = pg->power_min;
184073b01e57SJeff Chen
184173b01e57SJeff Chen length -= sizeof(struct nxpwifi_power_group);
184273b01e57SJeff Chen }
184373b01e57SJeff Chen priv->min_tx_power_level = (u8)min_power;
184473b01e57SJeff Chen priv->max_tx_power_level = (u8)max_power;
184573b01e57SJeff Chen
184673b01e57SJeff Chen return 0;
184773b01e57SJeff Chen }
184873b01e57SJeff Chen
184973b01e57SJeff Chen static int
nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)185073b01e57SJeff Chen nxpwifi_ret_sta_tx_power_cfg(struct nxpwifi_private *priv,
185173b01e57SJeff Chen struct host_cmd_ds_command *resp,
185273b01e57SJeff Chen u16 cmdresp_no,
185373b01e57SJeff Chen void *data_buf)
185473b01e57SJeff Chen {
185573b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
185673b01e57SJeff Chen struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
185773b01e57SJeff Chen struct nxpwifi_types_power_group *pg_tlv_hdr;
185873b01e57SJeff Chen struct nxpwifi_power_group *pg;
185973b01e57SJeff Chen u16 action = le16_to_cpu(txp_cfg->action);
186073b01e57SJeff Chen u16 tlv_buf_left;
186173b01e57SJeff Chen
186273b01e57SJeff Chen pg_tlv_hdr = (struct nxpwifi_types_power_group *)
186373b01e57SJeff Chen ((u8 *)txp_cfg +
186473b01e57SJeff Chen sizeof(struct host_cmd_ds_txpwr_cfg));
186573b01e57SJeff Chen
186673b01e57SJeff Chen pg = (struct nxpwifi_power_group *)
186773b01e57SJeff Chen ((u8 *)pg_tlv_hdr +
186873b01e57SJeff Chen sizeof(struct nxpwifi_types_power_group));
186973b01e57SJeff Chen
187073b01e57SJeff Chen tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg);
187173b01e57SJeff Chen if (tlv_buf_left <
187273b01e57SJeff Chen le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr))
187373b01e57SJeff Chen return 0;
187473b01e57SJeff Chen
187573b01e57SJeff Chen switch (action) {
187673b01e57SJeff Chen case HOST_ACT_GEN_GET:
187773b01e57SJeff Chen if (adapter->hw_status == NXPWIFI_HW_STATUS_INITIALIZING)
187873b01e57SJeff Chen nxpwifi_get_power_level(priv, pg_tlv_hdr);
187973b01e57SJeff Chen
188073b01e57SJeff Chen priv->tx_power_level = (u16)pg->power_min;
188173b01e57SJeff Chen break;
188273b01e57SJeff Chen
188373b01e57SJeff Chen case HOST_ACT_GEN_SET:
188473b01e57SJeff Chen if (!le32_to_cpu(txp_cfg->mode))
188573b01e57SJeff Chen break;
188673b01e57SJeff Chen
188773b01e57SJeff Chen if (pg->power_max == pg->power_min)
188873b01e57SJeff Chen priv->tx_power_level = (u16)pg->power_min;
188973b01e57SJeff Chen break;
189073b01e57SJeff Chen default:
189173b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
189273b01e57SJeff Chen "CMD_RESP: unknown cmd action %d\n",
189373b01e57SJeff Chen action);
189473b01e57SJeff Chen return 0;
189573b01e57SJeff Chen }
189673b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
189773b01e57SJeff Chen "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n",
189873b01e57SJeff Chen priv->tx_power_level, priv->max_tx_power_level,
189973b01e57SJeff Chen priv->min_tx_power_level);
190073b01e57SJeff Chen
190173b01e57SJeff Chen return 0;
190273b01e57SJeff Chen }
190373b01e57SJeff Chen
190473b01e57SJeff Chen static int
nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)190573b01e57SJeff Chen nxpwifi_cmd_sta_tx_rate_cfg(struct nxpwifi_private *priv,
190673b01e57SJeff Chen struct host_cmd_ds_command *cmd,
190773b01e57SJeff Chen u16 cmd_no, void *data_buf,
190873b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
190973b01e57SJeff Chen {
191073b01e57SJeff Chen struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
191173b01e57SJeff Chen u16 *pbitmap_rates = (u16 *)data_buf;
191273b01e57SJeff Chen struct nxpwifi_rate_scope *rate_scope;
191373b01e57SJeff Chen struct nxpwifi_rate_drop_pattern *rate_drop;
191473b01e57SJeff Chen u32 i;
191573b01e57SJeff Chen
191673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_TX_RATE_CFG);
191773b01e57SJeff Chen
191873b01e57SJeff Chen rate_cfg->action = cpu_to_le16(cmd_action);
191973b01e57SJeff Chen rate_cfg->cfg_index = 0;
192073b01e57SJeff Chen
192173b01e57SJeff Chen rate_scope = (struct nxpwifi_rate_scope *)((u8 *)rate_cfg +
192273b01e57SJeff Chen sizeof(struct host_cmd_ds_tx_rate_cfg));
192373b01e57SJeff Chen rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE);
192473b01e57SJeff Chen rate_scope->length = cpu_to_le16
192573b01e57SJeff Chen (sizeof(*rate_scope) - sizeof(struct nxpwifi_ie_types_header));
192673b01e57SJeff Chen if (pbitmap_rates) {
192773b01e57SJeff Chen rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]);
192873b01e57SJeff Chen rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]);
192973b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
193073b01e57SJeff Chen rate_scope->ht_mcs_rate_bitmap[i] =
193173b01e57SJeff Chen cpu_to_le16(pbitmap_rates[2 + i]);
193273b01e57SJeff Chen if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
193373b01e57SJeff Chen for (i = 0;
193473b01e57SJeff Chen i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
193573b01e57SJeff Chen i++)
193673b01e57SJeff Chen rate_scope->vht_mcs_rate_bitmap[i] =
193773b01e57SJeff Chen cpu_to_le16(pbitmap_rates[10 + i]);
193873b01e57SJeff Chen }
193973b01e57SJeff Chen } else {
194073b01e57SJeff Chen rate_scope->hr_dsss_rate_bitmap =
194173b01e57SJeff Chen cpu_to_le16(priv->bitmap_rates[0]);
194273b01e57SJeff Chen rate_scope->ofdm_rate_bitmap =
194373b01e57SJeff Chen cpu_to_le16(priv->bitmap_rates[1]);
194473b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
194573b01e57SJeff Chen rate_scope->ht_mcs_rate_bitmap[i] =
194673b01e57SJeff Chen cpu_to_le16(priv->bitmap_rates[2 + i]);
194773b01e57SJeff Chen if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
194873b01e57SJeff Chen for (i = 0;
194973b01e57SJeff Chen i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
195073b01e57SJeff Chen i++)
195173b01e57SJeff Chen rate_scope->vht_mcs_rate_bitmap[i] =
195273b01e57SJeff Chen cpu_to_le16(priv->bitmap_rates[10 + i]);
195373b01e57SJeff Chen }
195473b01e57SJeff Chen }
195573b01e57SJeff Chen
195673b01e57SJeff Chen rate_drop = (struct nxpwifi_rate_drop_pattern *)((u8 *)rate_scope +
195773b01e57SJeff Chen sizeof(struct nxpwifi_rate_scope));
195873b01e57SJeff Chen rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL);
195973b01e57SJeff Chen rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode));
196073b01e57SJeff Chen rate_drop->rate_drop_mode = 0;
196173b01e57SJeff Chen
196273b01e57SJeff Chen cmd->size =
196373b01e57SJeff Chen cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) +
196473b01e57SJeff Chen sizeof(struct nxpwifi_rate_scope) +
196573b01e57SJeff Chen sizeof(struct nxpwifi_rate_drop_pattern));
196673b01e57SJeff Chen
196773b01e57SJeff Chen return 0;
196873b01e57SJeff Chen }
196973b01e57SJeff Chen
nxpwifi_ret_rate_scope(struct nxpwifi_private * priv,u8 * tlv_buf)197073b01e57SJeff Chen static void nxpwifi_ret_rate_scope(struct nxpwifi_private *priv, u8 *tlv_buf)
197173b01e57SJeff Chen {
197273b01e57SJeff Chen struct nxpwifi_rate_scope *rate_scope;
197373b01e57SJeff Chen int i;
197473b01e57SJeff Chen
197573b01e57SJeff Chen rate_scope = (struct nxpwifi_rate_scope *)tlv_buf;
197673b01e57SJeff Chen priv->bitmap_rates[0] =
197773b01e57SJeff Chen le16_to_cpu(rate_scope->hr_dsss_rate_bitmap);
197873b01e57SJeff Chen priv->bitmap_rates[1] =
197973b01e57SJeff Chen le16_to_cpu(rate_scope->ofdm_rate_bitmap);
198073b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(rate_scope->ht_mcs_rate_bitmap); i++)
198173b01e57SJeff Chen priv->bitmap_rates[2 + i] =
198273b01e57SJeff Chen le16_to_cpu(rate_scope->ht_mcs_rate_bitmap[i]);
198373b01e57SJeff Chen
198473b01e57SJeff Chen if (priv->adapter->fw_api_ver == NXPWIFI_FW_V15) {
198573b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap);
198673b01e57SJeff Chen i++)
198773b01e57SJeff Chen priv->bitmap_rates[10 + i] =
198873b01e57SJeff Chen le16_to_cpu(rate_scope->vht_mcs_rate_bitmap[i]);
198973b01e57SJeff Chen }
199073b01e57SJeff Chen }
199173b01e57SJeff Chen
199273b01e57SJeff Chen static int
nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)199373b01e57SJeff Chen nxpwifi_ret_sta_tx_rate_cfg(struct nxpwifi_private *priv,
199473b01e57SJeff Chen struct host_cmd_ds_command *resp,
199573b01e57SJeff Chen u16 cmdresp_no,
199673b01e57SJeff Chen void *data_buf)
199773b01e57SJeff Chen {
199873b01e57SJeff Chen struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
199973b01e57SJeff Chen struct nxpwifi_ie_types_header *head;
200073b01e57SJeff Chen u16 tlv, tlv_buf_len, tlv_buf_left;
200173b01e57SJeff Chen u8 *tlv_buf;
200273b01e57SJeff Chen
200373b01e57SJeff Chen tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg);
200473b01e57SJeff Chen tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg);
200573b01e57SJeff Chen
200673b01e57SJeff Chen while (tlv_buf_left >= sizeof(*head)) {
200773b01e57SJeff Chen head = (struct nxpwifi_ie_types_header *)tlv_buf;
200873b01e57SJeff Chen tlv = le16_to_cpu(head->type);
200973b01e57SJeff Chen tlv_buf_len = le16_to_cpu(head->len);
201073b01e57SJeff Chen
201173b01e57SJeff Chen if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
201273b01e57SJeff Chen break;
201373b01e57SJeff Chen
201473b01e57SJeff Chen switch (tlv) {
201573b01e57SJeff Chen case TLV_TYPE_RATE_SCOPE:
201673b01e57SJeff Chen nxpwifi_ret_rate_scope(priv, tlv_buf);
201773b01e57SJeff Chen break;
201873b01e57SJeff Chen /* Add RATE_DROP tlv here */
201973b01e57SJeff Chen }
202073b01e57SJeff Chen
202173b01e57SJeff Chen tlv_buf += (sizeof(*head) + tlv_buf_len);
202273b01e57SJeff Chen tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
202373b01e57SJeff Chen }
202473b01e57SJeff Chen
202573b01e57SJeff Chen priv->is_data_rate_auto = nxpwifi_is_rate_auto(priv);
202673b01e57SJeff Chen
202773b01e57SJeff Chen if (priv->is_data_rate_auto)
202873b01e57SJeff Chen priv->data_rate = 0;
202973b01e57SJeff Chen else
203073b01e57SJeff Chen return nxpwifi_send_cmd(priv, HOST_CMD_802_11_TX_RATE_QUERY,
203173b01e57SJeff Chen HOST_ACT_GEN_GET, 0, NULL, false);
203273b01e57SJeff Chen
203373b01e57SJeff Chen return 0;
203473b01e57SJeff Chen }
203573b01e57SJeff Chen
203673b01e57SJeff Chen static int
nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)203773b01e57SJeff Chen nxpwifi_cmd_sta_reconfigure_rx_buff(struct nxpwifi_private *priv,
203873b01e57SJeff Chen struct host_cmd_ds_command *cmd,
203973b01e57SJeff Chen u16 cmd_no, void *data_buf,
204073b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
204173b01e57SJeff Chen {
204273b01e57SJeff Chen return nxpwifi_cmd_recfg_tx_buf(priv, cmd, cmd_action, data_buf);
204373b01e57SJeff Chen }
204473b01e57SJeff Chen
204573b01e57SJeff Chen static int
nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)204673b01e57SJeff Chen nxpwifi_ret_sta_reconfigure_rx_buff(struct nxpwifi_private *priv,
204773b01e57SJeff Chen struct host_cmd_ds_command *resp,
204873b01e57SJeff Chen u16 cmdresp_no,
204973b01e57SJeff Chen void *data_buf)
205073b01e57SJeff Chen {
205173b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
205273b01e57SJeff Chen
205373b01e57SJeff Chen if (0xffff != (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) {
205473b01e57SJeff Chen adapter->tx_buf_size =
205573b01e57SJeff Chen (u16)le16_to_cpu(resp->params.tx_buf.buff_size);
205673b01e57SJeff Chen adapter->tx_buf_size =
205773b01e57SJeff Chen (adapter->tx_buf_size / NXPWIFI_SDIO_BLOCK_SIZE) *
205873b01e57SJeff Chen NXPWIFI_SDIO_BLOCK_SIZE;
205973b01e57SJeff Chen adapter->curr_tx_buf_size = adapter->tx_buf_size;
206073b01e57SJeff Chen nxpwifi_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n",
206173b01e57SJeff Chen adapter->curr_tx_buf_size);
206273b01e57SJeff Chen
206373b01e57SJeff Chen if (adapter->if_ops.update_mp_end_port) {
206473b01e57SJeff Chen u16 mp_end_port;
206573b01e57SJeff Chen
206673b01e57SJeff Chen mp_end_port =
206773b01e57SJeff Chen le16_to_cpu(resp->params.tx_buf.mp_end_port);
206873b01e57SJeff Chen adapter->if_ops.update_mp_end_port(adapter,
206973b01e57SJeff Chen mp_end_port);
207073b01e57SJeff Chen }
207173b01e57SJeff Chen }
207273b01e57SJeff Chen
207373b01e57SJeff Chen return 0;
207473b01e57SJeff Chen }
207573b01e57SJeff Chen
207673b01e57SJeff Chen static int
nxpwifi_cmd_sta_chan_report_request(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)207773b01e57SJeff Chen nxpwifi_cmd_sta_chan_report_request(struct nxpwifi_private *priv,
207873b01e57SJeff Chen struct host_cmd_ds_command *cmd,
207973b01e57SJeff Chen u16 cmd_no, void *data_buf,
208073b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
208173b01e57SJeff Chen {
208273b01e57SJeff Chen return nxpwifi_cmd_issue_chan_report_request(priv, cmd, data_buf);
208373b01e57SJeff Chen }
208473b01e57SJeff Chen
208573b01e57SJeff Chen static int
nxpwifi_cmd_sta_amsdu_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)208673b01e57SJeff Chen nxpwifi_cmd_sta_amsdu_aggr_ctrl(struct nxpwifi_private *priv,
208773b01e57SJeff Chen struct host_cmd_ds_command *cmd,
208873b01e57SJeff Chen u16 cmd_no, void *data_buf,
208973b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
209073b01e57SJeff Chen {
209173b01e57SJeff Chen return nxpwifi_cmd_amsdu_aggr_ctrl(cmd, cmd_action, data_buf);
209273b01e57SJeff Chen }
209373b01e57SJeff Chen
209473b01e57SJeff Chen static int
nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)209573b01e57SJeff Chen nxpwifi_cmd_sta_robust_coex(struct nxpwifi_private *priv,
209673b01e57SJeff Chen struct host_cmd_ds_command *cmd,
209773b01e57SJeff Chen u16 cmd_no, void *data_buf,
209873b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
209973b01e57SJeff Chen {
210073b01e57SJeff Chen struct host_cmd_ds_robust_coex *coex = &cmd->params.coex;
210173b01e57SJeff Chen bool *is_timeshare = (bool *)data_buf;
210273b01e57SJeff Chen struct nxpwifi_ie_types_robust_coex *coex_tlv;
210373b01e57SJeff Chen
210473b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_ROBUST_COEX);
210573b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN);
210673b01e57SJeff Chen
210773b01e57SJeff Chen coex->action = cpu_to_le16(cmd_action);
210873b01e57SJeff Chen coex_tlv = (struct nxpwifi_ie_types_robust_coex *)
210973b01e57SJeff Chen ((u8 *)coex + sizeof(*coex));
211073b01e57SJeff Chen coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX);
211173b01e57SJeff Chen coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode));
211273b01e57SJeff Chen
211373b01e57SJeff Chen if (coex->action == HOST_ACT_GEN_GET)
211473b01e57SJeff Chen return 0;
211573b01e57SJeff Chen
211673b01e57SJeff Chen if (*is_timeshare)
211773b01e57SJeff Chen coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_TIMESHARE);
211873b01e57SJeff Chen else
211973b01e57SJeff Chen coex_tlv->mode = cpu_to_le32(NXPWIFI_COEX_MODE_SPATIAL);
212073b01e57SJeff Chen
212173b01e57SJeff Chen return 0;
212273b01e57SJeff Chen }
212373b01e57SJeff Chen
212473b01e57SJeff Chen static int
nxpwifi_ret_sta_robust_coex(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)212573b01e57SJeff Chen nxpwifi_ret_sta_robust_coex(struct nxpwifi_private *priv,
212673b01e57SJeff Chen struct host_cmd_ds_command *resp,
212773b01e57SJeff Chen u16 cmdresp_no,
212873b01e57SJeff Chen void *data_buf)
212973b01e57SJeff Chen {
213073b01e57SJeff Chen struct host_cmd_ds_robust_coex *coex = &resp->params.coex;
213173b01e57SJeff Chen bool *is_timeshare = (bool *)data_buf;
213273b01e57SJeff Chen struct nxpwifi_ie_types_robust_coex *coex_tlv;
213373b01e57SJeff Chen u16 action = le16_to_cpu(coex->action);
213473b01e57SJeff Chen u32 mode;
213573b01e57SJeff Chen
2136*068986fdSLinmao Li if (!is_timeshare)
2137*068986fdSLinmao Li return 0;
2138*068986fdSLinmao Li
213973b01e57SJeff Chen coex_tlv = (struct nxpwifi_ie_types_robust_coex
214073b01e57SJeff Chen *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex));
214173b01e57SJeff Chen if (action == HOST_ACT_GEN_GET) {
214273b01e57SJeff Chen mode = le32_to_cpu(coex_tlv->mode);
214373b01e57SJeff Chen if (mode == NXPWIFI_COEX_MODE_TIMESHARE)
214473b01e57SJeff Chen *is_timeshare = true;
214573b01e57SJeff Chen else
214673b01e57SJeff Chen *is_timeshare = false;
214773b01e57SJeff Chen }
214873b01e57SJeff Chen
214973b01e57SJeff Chen return 0;
215073b01e57SJeff Chen }
215173b01e57SJeff Chen
215273b01e57SJeff Chen static int
nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)215373b01e57SJeff Chen nxpwifi_cmd_sta_enh_power_mode(struct nxpwifi_private *priv,
215473b01e57SJeff Chen struct host_cmd_ds_command *cmd,
215573b01e57SJeff Chen u16 cmd_no, void *data_buf,
215673b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
215773b01e57SJeff Chen {
215873b01e57SJeff Chen struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
215973b01e57SJeff Chen &cmd->params.psmode_enh;
216073b01e57SJeff Chen u16 ps_bitmap = (u16)cmd_type;
216173b01e57SJeff Chen struct nxpwifi_ds_auto_ds *auto_ds =
216273b01e57SJeff Chen (struct nxpwifi_ds_auto_ds *)data_buf;
216373b01e57SJeff Chen u8 *tlv;
216473b01e57SJeff Chen u16 cmd_size = 0;
216573b01e57SJeff Chen
216673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_PS_MODE_ENH);
216773b01e57SJeff Chen if (cmd_action == DIS_AUTO_PS) {
216873b01e57SJeff Chen psmode_enh->action = cpu_to_le16(DIS_AUTO_PS);
216973b01e57SJeff Chen psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
217073b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
217173b01e57SJeff Chen sizeof(psmode_enh->params.ps_bitmap));
217273b01e57SJeff Chen } else if (cmd_action == GET_PS) {
217373b01e57SJeff Chen psmode_enh->action = cpu_to_le16(GET_PS);
217473b01e57SJeff Chen psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
217573b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) +
217673b01e57SJeff Chen sizeof(psmode_enh->params.ps_bitmap));
217773b01e57SJeff Chen } else if (cmd_action == EN_AUTO_PS) {
217873b01e57SJeff Chen psmode_enh->action = cpu_to_le16(EN_AUTO_PS);
217973b01e57SJeff Chen psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap);
218073b01e57SJeff Chen cmd_size = S_DS_GEN + sizeof(psmode_enh->action) +
218173b01e57SJeff Chen sizeof(psmode_enh->params.ps_bitmap);
218273b01e57SJeff Chen tlv = (u8 *)cmd + cmd_size;
218373b01e57SJeff Chen if (ps_bitmap & BITMAP_STA_PS) {
218473b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
218573b01e57SJeff Chen struct nxpwifi_ie_types_ps_param *ps_tlv =
218673b01e57SJeff Chen (struct nxpwifi_ie_types_ps_param *)tlv;
218773b01e57SJeff Chen struct nxpwifi_ps_param *ps_mode = &ps_tlv->param;
218873b01e57SJeff Chen
218973b01e57SJeff Chen ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM);
219073b01e57SJeff Chen ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) -
219173b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
219273b01e57SJeff Chen cmd_size += sizeof(*ps_tlv);
219373b01e57SJeff Chen tlv += sizeof(*ps_tlv);
219473b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
219573b01e57SJeff Chen "cmd: PS Command: Enter PS\n");
219673b01e57SJeff Chen ps_mode->null_pkt_interval =
219773b01e57SJeff Chen cpu_to_le16(adapter->null_pkt_interval);
219873b01e57SJeff Chen ps_mode->multiple_dtims =
219973b01e57SJeff Chen cpu_to_le16(adapter->multiple_dtim);
220073b01e57SJeff Chen ps_mode->bcn_miss_timeout =
220173b01e57SJeff Chen cpu_to_le16(adapter->bcn_miss_time_out);
220273b01e57SJeff Chen ps_mode->local_listen_interval =
220373b01e57SJeff Chen cpu_to_le16(adapter->local_listen_interval);
220473b01e57SJeff Chen ps_mode->delay_to_ps =
220573b01e57SJeff Chen cpu_to_le16(adapter->delay_to_ps);
220673b01e57SJeff Chen ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode);
220773b01e57SJeff Chen }
220873b01e57SJeff Chen if (ps_bitmap & BITMAP_AUTO_DS) {
220973b01e57SJeff Chen struct nxpwifi_ie_types_auto_ds_param *auto_ds_tlv =
221073b01e57SJeff Chen (struct nxpwifi_ie_types_auto_ds_param *)tlv;
221173b01e57SJeff Chen u16 idletime = 0;
221273b01e57SJeff Chen
221373b01e57SJeff Chen auto_ds_tlv->header.type =
221473b01e57SJeff Chen cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM);
221573b01e57SJeff Chen auto_ds_tlv->header.len =
221673b01e57SJeff Chen cpu_to_le16(sizeof(*auto_ds_tlv) -
221773b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
221873b01e57SJeff Chen cmd_size += sizeof(*auto_ds_tlv);
221973b01e57SJeff Chen tlv += sizeof(*auto_ds_tlv);
222073b01e57SJeff Chen if (auto_ds)
222173b01e57SJeff Chen idletime = auto_ds->idle_time;
222273b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
222373b01e57SJeff Chen "cmd: PS Command: Enter Auto Deep Sleep\n");
222473b01e57SJeff Chen auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
222573b01e57SJeff Chen }
222673b01e57SJeff Chen cmd->size = cpu_to_le16(cmd_size);
222773b01e57SJeff Chen }
222873b01e57SJeff Chen return 0;
222973b01e57SJeff Chen }
223073b01e57SJeff Chen
223173b01e57SJeff Chen static int
nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)223273b01e57SJeff Chen nxpwifi_ret_sta_enh_power_mode(struct nxpwifi_private *priv,
223373b01e57SJeff Chen struct host_cmd_ds_command *resp,
223473b01e57SJeff Chen u16 cmdresp_no,
223573b01e57SJeff Chen void *data_buf)
223673b01e57SJeff Chen {
223773b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
223873b01e57SJeff Chen struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
223973b01e57SJeff Chen &resp->params.psmode_enh;
224073b01e57SJeff Chen struct nxpwifi_ds_pm_cfg *pm_cfg =
224173b01e57SJeff Chen (struct nxpwifi_ds_pm_cfg *)data_buf;
224273b01e57SJeff Chen u16 action = le16_to_cpu(ps_mode->action);
224373b01e57SJeff Chen u16 ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap);
224473b01e57SJeff Chen u16 auto_ps_bitmap =
224573b01e57SJeff Chen le16_to_cpu(ps_mode->params.ps_bitmap);
224673b01e57SJeff Chen
224773b01e57SJeff Chen nxpwifi_dbg(adapter, INFO,
224873b01e57SJeff Chen "info: %s: PS_MODE cmd reply result=%#x action=%#X\n",
224973b01e57SJeff Chen __func__, resp->result, action);
225073b01e57SJeff Chen if (action == EN_AUTO_PS) {
225173b01e57SJeff Chen if (auto_ps_bitmap & BITMAP_AUTO_DS) {
225273b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
225373b01e57SJeff Chen "cmd: Enabled auto deep sleep\n");
225473b01e57SJeff Chen priv->adapter->is_deep_sleep = true;
225573b01e57SJeff Chen }
225673b01e57SJeff Chen if (auto_ps_bitmap & BITMAP_STA_PS) {
225773b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
225873b01e57SJeff Chen "cmd: Enabled STA power save\n");
225973b01e57SJeff Chen if (adapter->sleep_period.period)
226073b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
226173b01e57SJeff Chen "cmd: set to uapsd/pps mode\n");
226273b01e57SJeff Chen }
226373b01e57SJeff Chen } else if (action == DIS_AUTO_PS) {
226473b01e57SJeff Chen if (ps_bitmap & BITMAP_AUTO_DS) {
226573b01e57SJeff Chen priv->adapter->is_deep_sleep = false;
226673b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
226773b01e57SJeff Chen "cmd: Disabled auto deep sleep\n");
226873b01e57SJeff Chen }
226973b01e57SJeff Chen if (ps_bitmap & BITMAP_STA_PS) {
227073b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
227173b01e57SJeff Chen "cmd: Disabled STA power save\n");
227273b01e57SJeff Chen if (adapter->sleep_period.period) {
227373b01e57SJeff Chen adapter->delay_null_pkt = false;
227473b01e57SJeff Chen adapter->tx_lock_flag = false;
227573b01e57SJeff Chen adapter->pps_uapsd_mode = false;
227673b01e57SJeff Chen }
227773b01e57SJeff Chen }
227873b01e57SJeff Chen } else if (action == GET_PS) {
227973b01e57SJeff Chen if (ps_bitmap & BITMAP_STA_PS)
228073b01e57SJeff Chen adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP;
228173b01e57SJeff Chen else
228273b01e57SJeff Chen adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_CAM;
228373b01e57SJeff Chen
228473b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
228573b01e57SJeff Chen "cmd: ps_bitmap=%#x\n", ps_bitmap);
228673b01e57SJeff Chen
228773b01e57SJeff Chen if (pm_cfg) {
228873b01e57SJeff Chen /* This section is for get power save mode */
228973b01e57SJeff Chen if (ps_bitmap & BITMAP_STA_PS)
229073b01e57SJeff Chen pm_cfg->param.ps_mode = 1;
229173b01e57SJeff Chen else
229273b01e57SJeff Chen pm_cfg->param.ps_mode = 0;
229373b01e57SJeff Chen }
229473b01e57SJeff Chen }
229573b01e57SJeff Chen return 0;
229673b01e57SJeff Chen }
229773b01e57SJeff Chen
229873b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)229973b01e57SJeff Chen nxpwifi_cmd_sta_802_11_hs_cfg(struct nxpwifi_private *priv,
230073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
230173b01e57SJeff Chen u16 cmd_no, void *data_buf,
230273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
230373b01e57SJeff Chen {
230473b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
230573b01e57SJeff Chen struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
230673b01e57SJeff Chen struct nxpwifi_hs_config_param *hscfg_param =
230773b01e57SJeff Chen (struct nxpwifi_hs_config_param *)data_buf;
230873b01e57SJeff Chen u8 *tlv = (u8 *)hs_cfg + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
230973b01e57SJeff Chen struct nxpwifi_ps_param_in_hs *psparam_tlv = NULL;
231073b01e57SJeff Chen bool hs_activate = false;
231173b01e57SJeff Chen u16 size;
231273b01e57SJeff Chen
231373b01e57SJeff Chen if (!hscfg_param)
231473b01e57SJeff Chen /* New Activate command */
231573b01e57SJeff Chen hs_activate = true;
231673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_802_11_HS_CFG_ENH);
231773b01e57SJeff Chen
231873b01e57SJeff Chen if (!hs_activate &&
231973b01e57SJeff Chen hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL) &&
232073b01e57SJeff Chen (adapter->arp_filter_size > 0 &&
232173b01e57SJeff Chen adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE)) {
232273b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
232373b01e57SJeff Chen "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
232473b01e57SJeff Chen adapter->arp_filter_size);
232573b01e57SJeff Chen memcpy(((u8 *)hs_cfg) +
232673b01e57SJeff Chen sizeof(struct host_cmd_ds_802_11_hs_cfg_enh),
232773b01e57SJeff Chen adapter->arp_filter, adapter->arp_filter_size);
232873b01e57SJeff Chen size = adapter->arp_filter_size +
232973b01e57SJeff Chen sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
233073b01e57SJeff Chen + S_DS_GEN;
233173b01e57SJeff Chen tlv = (u8 *)hs_cfg
233273b01e57SJeff Chen + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh)
233373b01e57SJeff Chen + adapter->arp_filter_size;
233473b01e57SJeff Chen } else {
233573b01e57SJeff Chen size = S_DS_GEN + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh);
233673b01e57SJeff Chen }
233773b01e57SJeff Chen if (hs_activate) {
233873b01e57SJeff Chen hs_cfg->action = cpu_to_le16(HS_ACTIVATE);
233973b01e57SJeff Chen hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED);
234073b01e57SJeff Chen
234173b01e57SJeff Chen adapter->hs_activated_manually = true;
234273b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
234373b01e57SJeff Chen "cmd: Activating host sleep manually\n");
234473b01e57SJeff Chen } else {
234573b01e57SJeff Chen hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
234673b01e57SJeff Chen hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
234773b01e57SJeff Chen hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
234873b01e57SJeff Chen hs_cfg->params.hs_config.gap = hscfg_param->gap;
234973b01e57SJeff Chen
235073b01e57SJeff Chen size += sizeof(struct nxpwifi_ps_param_in_hs);
235173b01e57SJeff Chen psparam_tlv = (struct nxpwifi_ps_param_in_hs *)tlv;
235273b01e57SJeff Chen psparam_tlv->header.type =
235373b01e57SJeff Chen cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS);
235473b01e57SJeff Chen psparam_tlv->header.len =
235573b01e57SJeff Chen cpu_to_le16(sizeof(struct nxpwifi_ps_param_in_hs)
235673b01e57SJeff Chen - sizeof(struct nxpwifi_ie_types_header));
235773b01e57SJeff Chen psparam_tlv->hs_wake_int = cpu_to_le32(HS_DEF_WAKE_INTERVAL);
235873b01e57SJeff Chen psparam_tlv->hs_inact_timeout =
235973b01e57SJeff Chen cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT);
236073b01e57SJeff Chen
236173b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
236273b01e57SJeff Chen "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
236373b01e57SJeff Chen hs_cfg->params.hs_config.conditions,
236473b01e57SJeff Chen hs_cfg->params.hs_config.gpio,
236573b01e57SJeff Chen hs_cfg->params.hs_config.gap);
236673b01e57SJeff Chen }
236773b01e57SJeff Chen cmd->size = cpu_to_le16(size);
236873b01e57SJeff Chen
236973b01e57SJeff Chen return 0;
237073b01e57SJeff Chen }
237173b01e57SJeff Chen
237273b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)237373b01e57SJeff Chen nxpwifi_ret_sta_802_11_hs_cfg(struct nxpwifi_private *priv,
237473b01e57SJeff Chen struct host_cmd_ds_command *resp,
237573b01e57SJeff Chen u16 cmdresp_no,
237673b01e57SJeff Chen void *data_buf)
237773b01e57SJeff Chen {
237873b01e57SJeff Chen return nxpwifi_ret_802_11_hs_cfg(priv, resp);
237973b01e57SJeff Chen }
238073b01e57SJeff Chen
238173b01e57SJeff Chen static int
nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)238273b01e57SJeff Chen nxpwifi_cmd_sta_set_bss_mode(struct nxpwifi_private *priv,
238373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
238473b01e57SJeff Chen u16 cmd_no, void *data_buf,
238573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
238673b01e57SJeff Chen {
238773b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
238873b01e57SJeff Chen if (priv->bss_mode == NL80211_IFTYPE_STATION)
238973b01e57SJeff Chen cmd->params.bss_mode.con_type = CONNECTION_TYPE_INFRA;
239073b01e57SJeff Chen else if (priv->bss_mode == NL80211_IFTYPE_AP)
239173b01e57SJeff Chen cmd->params.bss_mode.con_type = CONNECTION_TYPE_AP;
239273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) +
239373b01e57SJeff Chen S_DS_GEN);
239473b01e57SJeff Chen
239573b01e57SJeff Chen return 0;
239673b01e57SJeff Chen }
239773b01e57SJeff Chen
239873b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_net_monitor(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)239973b01e57SJeff Chen nxpwifi_cmd_sta_802_11_net_monitor(struct nxpwifi_private *priv,
240073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
240173b01e57SJeff Chen u16 cmd_no, void *data_buf,
240273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
240373b01e57SJeff Chen {
240473b01e57SJeff Chen struct nxpwifi_802_11_net_monitor *net_mon;
240573b01e57SJeff Chen struct host_cmd_ds_802_11_net_monitor *cmd_net_mon =
240673b01e57SJeff Chen &cmd->params.net_mon;
240773b01e57SJeff Chen struct chan_band_param *chan_band = NULL;
240873b01e57SJeff Chen u8 sec_chan_offset = 0;
240973b01e57SJeff Chen u32 bw_offset = 0;
241073b01e57SJeff Chen
241173b01e57SJeff Chen net_mon = (struct nxpwifi_802_11_net_monitor *)data_buf;
241273b01e57SJeff Chen
241373b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN +
241473b01e57SJeff Chen sizeof(struct host_cmd_ds_802_11_net_monitor) +
241573b01e57SJeff Chen sizeof(struct chan_band_param));
241673b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
241773b01e57SJeff Chen cmd_net_mon->action = cpu_to_le16(cmd_action);
241873b01e57SJeff Chen
241973b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_SET) {
242073b01e57SJeff Chen if (net_mon->enable_net_mon) {
242173b01e57SJeff Chen cmd_net_mon->enable_net_mon = cpu_to_le16(0x1);
242273b01e57SJeff Chen cmd_net_mon->filter_flag = cpu_to_le16((u16)
242373b01e57SJeff Chen net_mon->filter_flag);
242473b01e57SJeff Chen }
242573b01e57SJeff Chen
242673b01e57SJeff Chen if (net_mon->enable_net_mon && net_mon->channel) {
242773b01e57SJeff Chen chan_band = &cmd_net_mon->monitor_chan.chan_band_param[0];
242873b01e57SJeff Chen cmd_net_mon->monitor_chan.header.type =
242973b01e57SJeff Chen cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
243073b01e57SJeff Chen cmd_net_mon->monitor_chan.header.len =
243173b01e57SJeff Chen cpu_to_le16(sizeof(struct chan_band_param));
243273b01e57SJeff Chen chan_band->chan_number = (u8)net_mon->channel;
243373b01e57SJeff Chen chan_band->band_cfg.chan_band =
243473b01e57SJeff Chen nxpwifi_band_to_radio_type((u16)net_mon->band);
243573b01e57SJeff Chen
243673b01e57SJeff Chen if (net_mon->band & BAND_GN ||
243773b01e57SJeff Chen net_mon->band & BAND_AN ||
243873b01e57SJeff Chen net_mon->band & BAND_GAC ||
243973b01e57SJeff Chen net_mon->band & BAND_AAC) {
244073b01e57SJeff Chen bw_offset = net_mon->chan_bandwidth;
244173b01e57SJeff Chen if (bw_offset == CHANNEL_BW_40MHZ_ABOVE) {
244273b01e57SJeff Chen chan_band->band_cfg.chan_2O_ffset =
244373b01e57SJeff Chen NXPWIFI_SEC_CHAN_ABOVE;
244473b01e57SJeff Chen chan_band->band_cfg.chan_width =
244573b01e57SJeff Chen CHAN_BW_40MHZ;
244673b01e57SJeff Chen } else if (bw_offset == CHANNEL_BW_40MHZ_BELOW) {
244773b01e57SJeff Chen chan_band->band_cfg.chan_2O_ffset =
244873b01e57SJeff Chen NXPWIFI_SEC_CHAN_BELOW;
244973b01e57SJeff Chen chan_band->band_cfg.chan_width =
245073b01e57SJeff Chen CHAN_BW_40MHZ;
245173b01e57SJeff Chen } else if (bw_offset == CHANNEL_BW_80MHZ) {
245273b01e57SJeff Chen sec_chan_offset =
245373b01e57SJeff Chen nxpwifi_get_sec_chan_offset(net_mon->channel);
245473b01e57SJeff Chen if (sec_chan_offset == NXPWIFI_SEC_CHAN_ABOVE)
245573b01e57SJeff Chen chan_band->band_cfg.chan_2O_ffset =
245673b01e57SJeff Chen NXPWIFI_SEC_CHAN_ABOVE;
245773b01e57SJeff Chen else if (sec_chan_offset == NXPWIFI_SEC_CHAN_BELOW)
245873b01e57SJeff Chen chan_band->band_cfg.chan_2O_ffset =
245973b01e57SJeff Chen NXPWIFI_SEC_CHAN_BELOW;
246073b01e57SJeff Chen chan_band->band_cfg.chan_width = CHAN_BW_80MHZ;
246173b01e57SJeff Chen }
246273b01e57SJeff Chen }
246373b01e57SJeff Chen }
246473b01e57SJeff Chen }
246573b01e57SJeff Chen return 0;
246673b01e57SJeff Chen }
246773b01e57SJeff Chen
246873b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_net_monitor(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)246973b01e57SJeff Chen nxpwifi_ret_sta_802_11_net_monitor(struct nxpwifi_private *priv,
247073b01e57SJeff Chen struct host_cmd_ds_command *resp,
247173b01e57SJeff Chen u16 cmdresp_no,
247273b01e57SJeff Chen void *data_buf)
247373b01e57SJeff Chen {
247473b01e57SJeff Chen struct host_cmd_ds_802_11_net_monitor *cmd_net_mon = &resp->params.net_mon;
247573b01e57SJeff Chen
247673b01e57SJeff Chen nxpwifi_dbg(priv->adapter, CMD,
247773b01e57SJeff Chen "cmd: NET_MONITOR_CMD: action: %d, enable: %d, flag: %d ch: %d band: %d bw: %d offset: %d\n",
247873b01e57SJeff Chen le16_to_cpu(cmd_net_mon->action),
247973b01e57SJeff Chen le16_to_cpu(cmd_net_mon->enable_net_mon),
248073b01e57SJeff Chen le16_to_cpu(cmd_net_mon->filter_flag),
248173b01e57SJeff Chen cmd_net_mon->monitor_chan.chan_band_param[0].chan_number,
248273b01e57SJeff Chen cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_band,
248373b01e57SJeff Chen cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_width,
248473b01e57SJeff Chen cmd_net_mon->monitor_chan.chan_band_param[0].band_cfg.chan_2O_ffset);
248573b01e57SJeff Chen priv->adapter->enable_net_mon = le16_to_cpu(cmd_net_mon->enable_net_mon);
248673b01e57SJeff Chen return 0;
248773b01e57SJeff Chen }
248873b01e57SJeff Chen
248973b01e57SJeff Chen static int
nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)249073b01e57SJeff Chen nxpwifi_cmd_sta_802_11_scan_ext(struct nxpwifi_private *priv,
249173b01e57SJeff Chen struct host_cmd_ds_command *cmd,
249273b01e57SJeff Chen u16 cmd_no, void *data_buf,
249373b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
249473b01e57SJeff Chen {
249573b01e57SJeff Chen return nxpwifi_cmd_802_11_scan_ext(priv, cmd, data_buf);
249673b01e57SJeff Chen }
249773b01e57SJeff Chen
249873b01e57SJeff Chen static int
nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)249973b01e57SJeff Chen nxpwifi_ret_sta_802_11_scan_ext(struct nxpwifi_private *priv,
250073b01e57SJeff Chen struct host_cmd_ds_command *resp,
250173b01e57SJeff Chen u16 cmdresp_no,
250273b01e57SJeff Chen void *data_buf)
250373b01e57SJeff Chen {
250473b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
250573b01e57SJeff Chen int ret;
250673b01e57SJeff Chen
250773b01e57SJeff Chen ret = nxpwifi_ret_802_11_scan_ext(priv, resp);
250873b01e57SJeff Chen adapter->curr_cmd->wait_q_enabled = false;
250973b01e57SJeff Chen
251073b01e57SJeff Chen return ret;
251173b01e57SJeff Chen }
251273b01e57SJeff Chen
251373b01e57SJeff Chen static int
nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)251473b01e57SJeff Chen nxpwifi_cmd_sta_coalesce_cfg(struct nxpwifi_private *priv,
251573b01e57SJeff Chen struct host_cmd_ds_command *cmd,
251673b01e57SJeff Chen u16 cmd_no, void *data_buf,
251773b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
251873b01e57SJeff Chen {
251973b01e57SJeff Chen struct host_cmd_ds_coalesce_cfg *coalesce_cfg =
252073b01e57SJeff Chen &cmd->params.coalesce_cfg;
252173b01e57SJeff Chen struct nxpwifi_ds_coalesce_cfg *cfg =
252273b01e57SJeff Chen (struct nxpwifi_ds_coalesce_cfg *)data_buf;
252373b01e57SJeff Chen struct coalesce_filt_field_param *param;
252473b01e57SJeff Chen u16 cnt, idx, length;
252573b01e57SJeff Chen struct coalesce_receive_filt_rule *rule;
252673b01e57SJeff Chen
252773b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_COALESCE_CFG);
252873b01e57SJeff Chen cmd->size = cpu_to_le16(S_DS_GEN);
252973b01e57SJeff Chen
253073b01e57SJeff Chen coalesce_cfg->action = cpu_to_le16(cmd_action);
253173b01e57SJeff Chen coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules);
253273b01e57SJeff Chen rule = (void *)coalesce_cfg->rule_data;
253373b01e57SJeff Chen
253473b01e57SJeff Chen for (cnt = 0; cnt < cfg->num_of_rules; cnt++) {
253573b01e57SJeff Chen rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE);
253673b01e57SJeff Chen rule->max_coalescing_delay =
253773b01e57SJeff Chen cpu_to_le16(cfg->rule[cnt].max_coalescing_delay);
253873b01e57SJeff Chen rule->pkt_type = cfg->rule[cnt].pkt_type;
253973b01e57SJeff Chen rule->num_of_fields = cfg->rule[cnt].num_of_fields;
254073b01e57SJeff Chen
254173b01e57SJeff Chen length = 0;
254273b01e57SJeff Chen
254373b01e57SJeff Chen param = rule->params;
254473b01e57SJeff Chen for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) {
254573b01e57SJeff Chen param->operation = cfg->rule[cnt].params[idx].operation;
254673b01e57SJeff Chen param->operand_len =
254773b01e57SJeff Chen cfg->rule[cnt].params[idx].operand_len;
254873b01e57SJeff Chen param->offset =
254973b01e57SJeff Chen cpu_to_le16(cfg->rule[cnt].params[idx].offset);
255073b01e57SJeff Chen memcpy(param->operand_byte_stream,
255173b01e57SJeff Chen cfg->rule[cnt].params[idx].operand_byte_stream,
255273b01e57SJeff Chen param->operand_len);
255373b01e57SJeff Chen
255473b01e57SJeff Chen length += sizeof(struct coalesce_filt_field_param);
255573b01e57SJeff Chen
255673b01e57SJeff Chen param++;
255773b01e57SJeff Chen }
255873b01e57SJeff Chen
255973b01e57SJeff Chen /*
256073b01e57SJeff Chen * Total rule length is sizeof max_coalescing_delay(u16),
256173b01e57SJeff Chen * num_of_fields(u8), pkt_type(u8) and total length of the all
256273b01e57SJeff Chen * params
256373b01e57SJeff Chen */
256473b01e57SJeff Chen rule->header.len = cpu_to_le16(length + sizeof(u16) +
256573b01e57SJeff Chen sizeof(u8) + sizeof(u8));
256673b01e57SJeff Chen
256773b01e57SJeff Chen /* Add the rule length to the command size */
256873b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size,
256973b01e57SJeff Chen le16_to_cpu(rule->header.len) +
257073b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
257173b01e57SJeff Chen
257273b01e57SJeff Chen rule = (void *)((u8 *)rule->params + length);
257373b01e57SJeff Chen }
257473b01e57SJeff Chen
257573b01e57SJeff Chen /* Add sizeof action, num_of_rules to total command length */
257673b01e57SJeff Chen le16_unaligned_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16));
257773b01e57SJeff Chen
257873b01e57SJeff Chen return 0;
257973b01e57SJeff Chen }
258073b01e57SJeff Chen
258173b01e57SJeff Chen static int
nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)258273b01e57SJeff Chen nxpwifi_cmd_sta_mgmt_frame_reg(struct nxpwifi_private *priv,
258373b01e57SJeff Chen struct host_cmd_ds_command *cmd,
258473b01e57SJeff Chen u16 cmd_no, void *data_buf,
258573b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
258673b01e57SJeff Chen {
258773b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
258873b01e57SJeff Chen cmd->params.reg_mask.action = cpu_to_le16(cmd_action);
258973b01e57SJeff Chen cmd->params.reg_mask.mask =
259073b01e57SJeff Chen cpu_to_le32(get_unaligned((u32 *)data_buf));
259173b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) +
259273b01e57SJeff Chen S_DS_GEN);
259373b01e57SJeff Chen
259473b01e57SJeff Chen return 0;
259573b01e57SJeff Chen }
259673b01e57SJeff Chen
259773b01e57SJeff Chen static int
nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)259873b01e57SJeff Chen nxpwifi_cmd_sta_remain_on_chan(struct nxpwifi_private *priv,
259973b01e57SJeff Chen struct host_cmd_ds_command *cmd,
260073b01e57SJeff Chen u16 cmd_no, void *data_buf,
260173b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
260273b01e57SJeff Chen {
260373b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
260473b01e57SJeff Chen memcpy(&cmd->params, data_buf,
260573b01e57SJeff Chen sizeof(struct host_cmd_ds_remain_on_chan));
260673b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) +
260773b01e57SJeff Chen S_DS_GEN);
260873b01e57SJeff Chen
260973b01e57SJeff Chen return 0;
261073b01e57SJeff Chen }
261173b01e57SJeff Chen
261273b01e57SJeff Chen static int
nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)261373b01e57SJeff Chen nxpwifi_ret_sta_remain_on_chan(struct nxpwifi_private *priv,
261473b01e57SJeff Chen struct host_cmd_ds_command *resp,
261573b01e57SJeff Chen u16 cmdresp_no,
261673b01e57SJeff Chen void *data_buf)
261773b01e57SJeff Chen {
261873b01e57SJeff Chen struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg;
261973b01e57SJeff Chen struct host_cmd_ds_remain_on_chan *roc_cfg =
262073b01e57SJeff Chen (struct host_cmd_ds_remain_on_chan *)data_buf;
262173b01e57SJeff Chen
262273b01e57SJeff Chen if (roc_cfg)
262373b01e57SJeff Chen memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg));
262473b01e57SJeff Chen
262573b01e57SJeff Chen return 0;
262673b01e57SJeff Chen }
262773b01e57SJeff Chen
262873b01e57SJeff Chen static int
nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)262973b01e57SJeff Chen nxpwifi_cmd_sta_gtk_rekey_offload(struct nxpwifi_private *priv,
263073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
263173b01e57SJeff Chen u16 cmd_no, void *data_buf,
263273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
263373b01e57SJeff Chen {
263473b01e57SJeff Chen struct host_cmd_ds_gtk_rekey_params *rekey = &cmd->params.rekey;
263573b01e57SJeff Chen struct cfg80211_gtk_rekey_data *data =
263673b01e57SJeff Chen (struct cfg80211_gtk_rekey_data *)data_buf;
263773b01e57SJeff Chen u64 rekey_ctr;
263873b01e57SJeff Chen
263973b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_GTK_REKEY_OFFLOAD_CFG);
264073b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*rekey) + S_DS_GEN);
264173b01e57SJeff Chen
264273b01e57SJeff Chen rekey->action = cpu_to_le16(cmd_action);
264373b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_SET) {
264473b01e57SJeff Chen memcpy(rekey->kek, data->kek, NL80211_KEK_LEN);
264573b01e57SJeff Chen memcpy(rekey->kck, data->kck, NL80211_KCK_LEN);
264673b01e57SJeff Chen rekey_ctr = be64_to_cpup((__be64 *)data->replay_ctr);
264773b01e57SJeff Chen rekey->replay_ctr_low = cpu_to_le32((u32)rekey_ctr);
264873b01e57SJeff Chen rekey->replay_ctr_high =
264973b01e57SJeff Chen cpu_to_le32((u32)((u64)rekey_ctr >> 32));
265073b01e57SJeff Chen }
265173b01e57SJeff Chen
265273b01e57SJeff Chen return 0;
265373b01e57SJeff Chen }
265473b01e57SJeff Chen
265573b01e57SJeff Chen static int
nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)265673b01e57SJeff Chen nxpwifi_cmd_sta_11ac_cfg(struct nxpwifi_private *priv,
265773b01e57SJeff Chen struct host_cmd_ds_command *cmd,
265873b01e57SJeff Chen u16 cmd_no, void *data_buf,
265973b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
266073b01e57SJeff Chen {
266173b01e57SJeff Chen return nxpwifi_cmd_11ac_cfg(priv, cmd, cmd_action, data_buf);
266273b01e57SJeff Chen }
266373b01e57SJeff Chen
266473b01e57SJeff Chen static int
nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)266573b01e57SJeff Chen nxpwifi_cmd_sta_hs_wakeup_reason(struct nxpwifi_private *priv,
266673b01e57SJeff Chen struct host_cmd_ds_command *cmd,
266773b01e57SJeff Chen u16 cmd_no, void *data_buf,
266873b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
266973b01e57SJeff Chen {
267073b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_HS_WAKEUP_REASON);
267173b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) +
267273b01e57SJeff Chen S_DS_GEN);
267373b01e57SJeff Chen
267473b01e57SJeff Chen return 0;
267573b01e57SJeff Chen }
267673b01e57SJeff Chen
267773b01e57SJeff Chen static int
nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)267873b01e57SJeff Chen nxpwifi_ret_sta_hs_wakeup_reason(struct nxpwifi_private *priv,
267973b01e57SJeff Chen struct host_cmd_ds_command *resp,
268073b01e57SJeff Chen u16 cmdresp_no,
268173b01e57SJeff Chen void *data_buf)
268273b01e57SJeff Chen {
268373b01e57SJeff Chen struct host_cmd_ds_wakeup_reason *wakeup_reason =
268473b01e57SJeff Chen (struct host_cmd_ds_wakeup_reason *)data_buf;
2685*068986fdSLinmao Li
2686*068986fdSLinmao Li if (!wakeup_reason)
2687*068986fdSLinmao Li return 0;
2688*068986fdSLinmao Li
268973b01e57SJeff Chen wakeup_reason->wakeup_reason =
269073b01e57SJeff Chen resp->params.hs_wakeup_reason.wakeup_reason;
269173b01e57SJeff Chen
269273b01e57SJeff Chen return 0;
269373b01e57SJeff Chen }
269473b01e57SJeff Chen
269573b01e57SJeff Chen static int
nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)269673b01e57SJeff Chen nxpwifi_cmd_sta_mc_policy(struct nxpwifi_private *priv,
269773b01e57SJeff Chen struct host_cmd_ds_command *cmd,
269873b01e57SJeff Chen u16 cmd_no, void *data_buf,
269973b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
270073b01e57SJeff Chen {
270173b01e57SJeff Chen struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy;
270273b01e57SJeff Chen const u16 *drcs_info = data_buf;
270373b01e57SJeff Chen
270473b01e57SJeff Chen mc_pol->action = cpu_to_le16(cmd_action);
270573b01e57SJeff Chen mc_pol->policy = cpu_to_le16(*drcs_info);
270673b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_MC_POLICY);
270773b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) +
270873b01e57SJeff Chen S_DS_GEN);
270973b01e57SJeff Chen return 0;
271073b01e57SJeff Chen }
271173b01e57SJeff Chen
271273b01e57SJeff Chen static int
nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)271373b01e57SJeff Chen nxpwifi_cmd_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv,
271473b01e57SJeff Chen struct host_cmd_ds_command *cmd,
271573b01e57SJeff Chen u16 cmd_no, void *data_buf,
271673b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
271773b01e57SJeff Chen {
271873b01e57SJeff Chen struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
271973b01e57SJeff Chen &cmd->params.sdio_rx_aggr_cfg;
272073b01e57SJeff Chen
272173b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_SDIO_SP_RX_AGGR_CFG);
272273b01e57SJeff Chen cmd->size =
272373b01e57SJeff Chen cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) +
272473b01e57SJeff Chen S_DS_GEN);
272573b01e57SJeff Chen cfg->action = cmd_action;
272673b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_SET)
272773b01e57SJeff Chen cfg->enable = *(u8 *)data_buf;
272873b01e57SJeff Chen
272973b01e57SJeff Chen return 0;
273073b01e57SJeff Chen }
273173b01e57SJeff Chen
273273b01e57SJeff Chen static int
nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)273373b01e57SJeff Chen nxpwifi_ret_sta_sdio_rx_aggr_cfg(struct nxpwifi_private *priv,
273473b01e57SJeff Chen struct host_cmd_ds_command *resp,
273573b01e57SJeff Chen u16 cmdresp_no,
273673b01e57SJeff Chen void *data_buf)
273773b01e57SJeff Chen {
273873b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
273973b01e57SJeff Chen struct host_cmd_sdio_sp_rx_aggr_cfg *cfg =
274073b01e57SJeff Chen &resp->params.sdio_rx_aggr_cfg;
274173b01e57SJeff Chen
274273b01e57SJeff Chen adapter->sdio_rx_aggr_enable = cfg->enable;
274373b01e57SJeff Chen adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size);
274473b01e57SJeff Chen
274573b01e57SJeff Chen return 0;
274673b01e57SJeff Chen }
274773b01e57SJeff Chen
274873b01e57SJeff Chen static int
nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)274973b01e57SJeff Chen nxpwifi_cmd_sta_get_chan_info(struct nxpwifi_private *priv,
275073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
275173b01e57SJeff Chen u16 cmd_no, void *data_buf,
275273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
275373b01e57SJeff Chen {
275473b01e57SJeff Chen struct host_cmd_ds_sta_configure *sta_cfg_cmd = &cmd->params.sta_cfg;
275573b01e57SJeff Chen struct host_cmd_tlv_channel_band *tlv_band_channel =
275673b01e57SJeff Chen (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
275773b01e57SJeff Chen
275873b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_STA_CONFIGURE);
275973b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*sta_cfg_cmd) +
276073b01e57SJeff Chen sizeof(*tlv_band_channel) + S_DS_GEN);
276173b01e57SJeff Chen sta_cfg_cmd->action = cpu_to_le16(cmd_action);
276273b01e57SJeff Chen memset(tlv_band_channel, 0, sizeof(*tlv_band_channel));
276373b01e57SJeff Chen tlv_band_channel->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST);
276473b01e57SJeff Chen tlv_band_channel->header.len = cpu_to_le16(sizeof(*tlv_band_channel) -
276573b01e57SJeff Chen sizeof(struct nxpwifi_ie_types_header));
276673b01e57SJeff Chen
276773b01e57SJeff Chen return 0;
276873b01e57SJeff Chen }
276973b01e57SJeff Chen
277073b01e57SJeff Chen static int
nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)277173b01e57SJeff Chen nxpwifi_ret_sta_get_chan_info(struct nxpwifi_private *priv,
277273b01e57SJeff Chen struct host_cmd_ds_command *resp,
277373b01e57SJeff Chen u16 cmdresp_no,
277473b01e57SJeff Chen void *data_buf)
277573b01e57SJeff Chen {
277673b01e57SJeff Chen struct host_cmd_ds_sta_configure *sta_cfg_cmd = &resp->params.sta_cfg;
277773b01e57SJeff Chen struct nxpwifi_channel_band *channel_band =
277873b01e57SJeff Chen (struct nxpwifi_channel_band *)data_buf;
277973b01e57SJeff Chen struct host_cmd_tlv_channel_band *tlv_band_channel;
278073b01e57SJeff Chen
2781*068986fdSLinmao Li if (!channel_band)
2782*068986fdSLinmao Li return 0;
2783*068986fdSLinmao Li
278473b01e57SJeff Chen tlv_band_channel =
278573b01e57SJeff Chen (struct host_cmd_tlv_channel_band *)sta_cfg_cmd->tlv_buffer;
278673b01e57SJeff Chen memcpy(&channel_band->band_config, &tlv_band_channel->band_config,
278773b01e57SJeff Chen sizeof(struct nxpwifi_band_config));
278873b01e57SJeff Chen channel_band->channel = tlv_band_channel->channel;
278973b01e57SJeff Chen
279073b01e57SJeff Chen return 0;
279173b01e57SJeff Chen }
279273b01e57SJeff Chen
279373b01e57SJeff Chen static int
nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)279473b01e57SJeff Chen nxpwifi_cmd_sta_chan_region_cfg(struct nxpwifi_private *priv,
279573b01e57SJeff Chen struct host_cmd_ds_command *cmd,
279673b01e57SJeff Chen u16 cmd_no, void *data_buf,
279773b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
279873b01e57SJeff Chen {
279973b01e57SJeff Chen struct host_cmd_ds_chan_region_cfg *reg = &cmd->params.reg_cfg;
280073b01e57SJeff Chen
280173b01e57SJeff Chen cmd->command = cpu_to_le16(HOST_CMD_CHAN_REGION_CFG);
280273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(*reg) + S_DS_GEN);
280373b01e57SJeff Chen
280473b01e57SJeff Chen if (cmd_action == HOST_ACT_GEN_GET)
280573b01e57SJeff Chen reg->action = cpu_to_le16(cmd_action);
280673b01e57SJeff Chen
280773b01e57SJeff Chen return 0;
280873b01e57SJeff Chen }
280973b01e57SJeff Chen
281073b01e57SJeff Chen static struct ieee80211_regdomain *
nxpwifi_create_custom_regdomain(struct nxpwifi_private * priv,u8 * buf,u16 buf_len)281173b01e57SJeff Chen nxpwifi_create_custom_regdomain(struct nxpwifi_private *priv,
281273b01e57SJeff Chen u8 *buf, u16 buf_len)
281373b01e57SJeff Chen {
281473b01e57SJeff Chen u16 num_chan = buf_len / 2;
281573b01e57SJeff Chen struct ieee80211_regdomain *regd;
281673b01e57SJeff Chen struct ieee80211_reg_rule *rule;
281773b01e57SJeff Chen bool new_rule;
281873b01e57SJeff Chen int idx, freq, prev_freq = 0;
281973b01e57SJeff Chen u32 bw, prev_bw = 0;
282073b01e57SJeff Chen u8 chflags, prev_chflags = 0, valid_rules = 0;
282173b01e57SJeff Chen
282273b01e57SJeff Chen if (WARN_ON_ONCE(num_chan > NL80211_MAX_SUPP_REG_RULES))
282373b01e57SJeff Chen return ERR_PTR(-EINVAL);
282473b01e57SJeff Chen
282573b01e57SJeff Chen regd = kzalloc_flex(*regd, reg_rules, num_chan, GFP_KERNEL);
282673b01e57SJeff Chen if (!regd)
282773b01e57SJeff Chen return ERR_PTR(-ENOMEM);
282873b01e57SJeff Chen
282973b01e57SJeff Chen for (idx = 0; idx < num_chan; idx++) {
283073b01e57SJeff Chen u8 chan;
283173b01e57SJeff Chen enum nl80211_band band;
283273b01e57SJeff Chen
283373b01e57SJeff Chen chan = *buf++;
283473b01e57SJeff Chen if (!chan) {
283573b01e57SJeff Chen kfree(regd);
283673b01e57SJeff Chen return NULL;
283773b01e57SJeff Chen }
283873b01e57SJeff Chen chflags = *buf++;
283973b01e57SJeff Chen band = (chan <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
284073b01e57SJeff Chen freq = ieee80211_channel_to_frequency(chan, band);
284173b01e57SJeff Chen new_rule = false;
284273b01e57SJeff Chen
284373b01e57SJeff Chen if (chflags & NXPWIFI_CHANNEL_DISABLED)
284473b01e57SJeff Chen continue;
284573b01e57SJeff Chen
284673b01e57SJeff Chen if (band == NL80211_BAND_5GHZ) {
284773b01e57SJeff Chen if (!(chflags & NXPWIFI_CHANNEL_NOHT80))
284873b01e57SJeff Chen bw = MHZ_TO_KHZ(80);
284973b01e57SJeff Chen else if (!(chflags & NXPWIFI_CHANNEL_NOHT40))
285073b01e57SJeff Chen bw = MHZ_TO_KHZ(40);
285173b01e57SJeff Chen else
285273b01e57SJeff Chen bw = MHZ_TO_KHZ(20);
285373b01e57SJeff Chen } else {
285473b01e57SJeff Chen if (!(chflags & NXPWIFI_CHANNEL_NOHT40))
285573b01e57SJeff Chen bw = MHZ_TO_KHZ(40);
285673b01e57SJeff Chen else
285773b01e57SJeff Chen bw = MHZ_TO_KHZ(20);
285873b01e57SJeff Chen }
285973b01e57SJeff Chen
286073b01e57SJeff Chen if (idx == 0 || prev_chflags != chflags || prev_bw != bw ||
286173b01e57SJeff Chen freq - prev_freq > 20) {
286273b01e57SJeff Chen valid_rules++;
286373b01e57SJeff Chen new_rule = true;
286473b01e57SJeff Chen }
286573b01e57SJeff Chen
286673b01e57SJeff Chen rule = ®d->reg_rules[valid_rules - 1];
286773b01e57SJeff Chen
286873b01e57SJeff Chen rule->freq_range.end_freq_khz = MHZ_TO_KHZ(freq + 10);
286973b01e57SJeff Chen
287073b01e57SJeff Chen prev_chflags = chflags;
287173b01e57SJeff Chen prev_freq = freq;
287273b01e57SJeff Chen prev_bw = bw;
287373b01e57SJeff Chen
287473b01e57SJeff Chen if (!new_rule)
287573b01e57SJeff Chen continue;
287673b01e57SJeff Chen
287773b01e57SJeff Chen rule->freq_range.start_freq_khz = MHZ_TO_KHZ(freq - 10);
287873b01e57SJeff Chen rule->power_rule.max_eirp = DBM_TO_MBM(19);
287973b01e57SJeff Chen
288073b01e57SJeff Chen if (chflags & NXPWIFI_CHANNEL_PASSIVE)
288173b01e57SJeff Chen rule->flags = NL80211_RRF_NO_IR;
288273b01e57SJeff Chen
288373b01e57SJeff Chen if (chflags & NXPWIFI_CHANNEL_DFS)
288473b01e57SJeff Chen rule->flags = NL80211_RRF_DFS;
288573b01e57SJeff Chen
288673b01e57SJeff Chen rule->freq_range.max_bandwidth_khz = bw;
288773b01e57SJeff Chen }
288873b01e57SJeff Chen
288973b01e57SJeff Chen regd->n_reg_rules = valid_rules;
289073b01e57SJeff Chen regd->alpha2[0] = '9';
289173b01e57SJeff Chen regd->alpha2[1] = '9';
289273b01e57SJeff Chen
289373b01e57SJeff Chen return regd;
289473b01e57SJeff Chen }
289573b01e57SJeff Chen
289673b01e57SJeff Chen static int
nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)289773b01e57SJeff Chen nxpwifi_ret_sta_chan_region_cfg(struct nxpwifi_private *priv,
289873b01e57SJeff Chen struct host_cmd_ds_command *resp,
289973b01e57SJeff Chen u16 cmdresp_no,
290073b01e57SJeff Chen void *data_buf)
290173b01e57SJeff Chen {
290273b01e57SJeff Chen struct host_cmd_ds_chan_region_cfg *reg = &resp->params.reg_cfg;
290373b01e57SJeff Chen u16 action = le16_to_cpu(reg->action);
290473b01e57SJeff Chen u16 tlv, tlv_buf_len, tlv_buf_left;
290573b01e57SJeff Chen struct nxpwifi_ie_types_header *head;
290673b01e57SJeff Chen struct ieee80211_regdomain *regd;
290773b01e57SJeff Chen u8 *tlv_buf;
290873b01e57SJeff Chen
290973b01e57SJeff Chen if (action != HOST_ACT_GEN_GET)
291073b01e57SJeff Chen return 0;
291173b01e57SJeff Chen
291273b01e57SJeff Chen tlv_buf = (u8 *)reg + sizeof(*reg);
291373b01e57SJeff Chen tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*reg);
291473b01e57SJeff Chen
291573b01e57SJeff Chen while (tlv_buf_left >= sizeof(*head)) {
291673b01e57SJeff Chen head = (struct nxpwifi_ie_types_header *)tlv_buf;
291773b01e57SJeff Chen tlv = le16_to_cpu(head->type);
291873b01e57SJeff Chen tlv_buf_len = le16_to_cpu(head->len);
291973b01e57SJeff Chen
292073b01e57SJeff Chen if (tlv_buf_left < (sizeof(*head) + tlv_buf_len))
292173b01e57SJeff Chen break;
292273b01e57SJeff Chen
292373b01e57SJeff Chen switch (tlv) {
292473b01e57SJeff Chen case TLV_TYPE_CHAN_ATTR_CFG:
292573b01e57SJeff Chen nxpwifi_dbg_dump(priv->adapter, CMD_D, "CHAN:",
292673b01e57SJeff Chen (u8 *)head + sizeof(*head),
292773b01e57SJeff Chen tlv_buf_len);
292873b01e57SJeff Chen regd = nxpwifi_create_custom_regdomain(priv, (u8 *)head
292973b01e57SJeff Chen + sizeof(*head),
293073b01e57SJeff Chen tlv_buf_len);
293173b01e57SJeff Chen if (!IS_ERR(regd))
293273b01e57SJeff Chen priv->adapter->regd = regd;
293373b01e57SJeff Chen break;
293473b01e57SJeff Chen }
293573b01e57SJeff Chen
293673b01e57SJeff Chen tlv_buf += (sizeof(*head) + tlv_buf_len);
293773b01e57SJeff Chen tlv_buf_left -= (sizeof(*head) + tlv_buf_len);
293873b01e57SJeff Chen }
293973b01e57SJeff Chen
294073b01e57SJeff Chen return 0;
294173b01e57SJeff Chen }
294273b01e57SJeff Chen
294373b01e57SJeff Chen static int
nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)294473b01e57SJeff Chen nxpwifi_cmd_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv,
294573b01e57SJeff Chen struct host_cmd_ds_command *cmd,
294673b01e57SJeff Chen u16 cmd_no, void *data_buf,
294773b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
294873b01e57SJeff Chen {
294973b01e57SJeff Chen cmd->command = cpu_to_le16(cmd_no);
295073b01e57SJeff Chen cmd->params.pkt_aggr_ctrl.action = cpu_to_le16(cmd_action);
295173b01e57SJeff Chen cmd->params.pkt_aggr_ctrl.enable = cpu_to_le16(*(u16 *)data_buf);
295273b01e57SJeff Chen cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl) +
295373b01e57SJeff Chen S_DS_GEN);
295473b01e57SJeff Chen
295573b01e57SJeff Chen return 0;
295673b01e57SJeff Chen }
295773b01e57SJeff Chen
295873b01e57SJeff Chen static int
nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)295973b01e57SJeff Chen nxpwifi_ret_sta_pkt_aggr_ctrl(struct nxpwifi_private *priv,
296073b01e57SJeff Chen struct host_cmd_ds_command *resp,
296173b01e57SJeff Chen u16 cmdresp_no,
296273b01e57SJeff Chen void *data_buf)
296373b01e57SJeff Chen {
296473b01e57SJeff Chen struct host_cmd_ds_pkt_aggr_ctrl *pkt_aggr_ctrl =
296573b01e57SJeff Chen &resp->params.pkt_aggr_ctrl;
296673b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
296773b01e57SJeff Chen
296873b01e57SJeff Chen adapter->bus_aggr.enable = le16_to_cpu(pkt_aggr_ctrl->enable);
296973b01e57SJeff Chen if (adapter->bus_aggr.enable)
297073b01e57SJeff Chen adapter->intf_hdr_len = INTF_HEADER_LEN;
297173b01e57SJeff Chen adapter->bus_aggr.mode = NXPWIFI_BUS_AGGR_MODE_LEN_V2;
297273b01e57SJeff Chen adapter->bus_aggr.tx_aggr_max_size =
297373b01e57SJeff Chen le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_size);
297473b01e57SJeff Chen adapter->bus_aggr.tx_aggr_max_num =
297573b01e57SJeff Chen le16_to_cpu(pkt_aggr_ctrl->tx_aggr_max_num);
297673b01e57SJeff Chen adapter->bus_aggr.tx_aggr_align =
297773b01e57SJeff Chen le16_to_cpu(pkt_aggr_ctrl->tx_aggr_align);
297873b01e57SJeff Chen
297973b01e57SJeff Chen return 0;
298073b01e57SJeff Chen }
298173b01e57SJeff Chen
298273b01e57SJeff Chen static int
nxpwifi_cmd_sta_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)298373b01e57SJeff Chen nxpwifi_cmd_sta_11ax_cfg(struct nxpwifi_private *priv,
298473b01e57SJeff Chen struct host_cmd_ds_command *cmd,
298573b01e57SJeff Chen u16 cmd_no, void *data_buf,
298673b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
298773b01e57SJeff Chen {
298873b01e57SJeff Chen return nxpwifi_cmd_11ax_cfg(priv, cmd, cmd_action, data_buf);
298973b01e57SJeff Chen }
299073b01e57SJeff Chen
299173b01e57SJeff Chen static int
nxpwifi_ret_sta_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)299273b01e57SJeff Chen nxpwifi_ret_sta_11ax_cfg(struct nxpwifi_private *priv,
299373b01e57SJeff Chen struct host_cmd_ds_command *resp,
299473b01e57SJeff Chen u16 cmdresp_no,
299573b01e57SJeff Chen void *data_buf)
299673b01e57SJeff Chen {
299773b01e57SJeff Chen return nxpwifi_ret_11ax_cfg(priv, resp, data_buf);
299873b01e57SJeff Chen }
299973b01e57SJeff Chen
300073b01e57SJeff Chen static int
nxpwifi_cmd_sta_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)300173b01e57SJeff Chen nxpwifi_cmd_sta_11ax_cmd(struct nxpwifi_private *priv,
300273b01e57SJeff Chen struct host_cmd_ds_command *cmd,
300373b01e57SJeff Chen u16 cmd_no, void *data_buf,
300473b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
300573b01e57SJeff Chen {
300673b01e57SJeff Chen return nxpwifi_cmd_11ax_cmd(priv, cmd, cmd_action, data_buf);
300773b01e57SJeff Chen }
300873b01e57SJeff Chen
300973b01e57SJeff Chen static int
nxpwifi_ret_sta_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)301073b01e57SJeff Chen nxpwifi_ret_sta_11ax_cmd(struct nxpwifi_private *priv,
301173b01e57SJeff Chen struct host_cmd_ds_command *resp,
301273b01e57SJeff Chen u16 cmdresp_no,
301373b01e57SJeff Chen void *data_buf)
301473b01e57SJeff Chen {
301573b01e57SJeff Chen return nxpwifi_ret_11ax_cmd(priv, resp, data_buf);
301673b01e57SJeff Chen }
301773b01e57SJeff Chen
301873b01e57SJeff Chen static int
nxpwifi_cmd_sta_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_no,void * data_buf,u16 cmd_action,u32 cmd_type)301973b01e57SJeff Chen nxpwifi_cmd_sta_twt_cfg(struct nxpwifi_private *priv,
302073b01e57SJeff Chen struct host_cmd_ds_command *cmd,
302173b01e57SJeff Chen u16 cmd_no, void *data_buf,
302273b01e57SJeff Chen u16 cmd_action, u32 cmd_type)
302373b01e57SJeff Chen {
302473b01e57SJeff Chen return nxpwifi_cmd_twt_cfg(priv, cmd, cmd_action, data_buf);
302573b01e57SJeff Chen }
302673b01e57SJeff Chen
302773b01e57SJeff Chen static int
nxpwifi_ret_sta_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,u16 cmdresp_no,void * data_buf)302873b01e57SJeff Chen nxpwifi_ret_sta_twt_cfg(struct nxpwifi_private *priv,
302973b01e57SJeff Chen struct host_cmd_ds_command *resp,
303073b01e57SJeff Chen u16 cmdresp_no,
303173b01e57SJeff Chen void *data_buf)
303273b01e57SJeff Chen {
303373b01e57SJeff Chen return nxpwifi_ret_twt_cfg(priv, resp, data_buf);
303473b01e57SJeff Chen }
303573b01e57SJeff Chen
303673b01e57SJeff Chen static const struct nxpwifi_cmd_entry cmd_table_sta[] = {
303773b01e57SJeff Chen {.cmd_no = HOST_CMD_GET_HW_SPEC,
303873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_get_hw_spec,
303973b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_get_hw_spec},
304073b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_SCAN,
304173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_scan,
304273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_scan},
304373b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_GET_LOG,
304473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_get_log,
304573b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_get_log},
304673b01e57SJeff Chen {.cmd_no = HOST_CMD_MAC_MULTICAST_ADR,
304773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mac_multicast_adr,
304873b01e57SJeff Chen .cmd_resp = NULL},
304973b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_ASSOCIATE,
305073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_associate,
305173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_associate},
305273b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_SNMP_MIB,
305373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_snmp_mib,
305473b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_snmp_mib},
305573b01e57SJeff Chen {.cmd_no = HOST_CMD_MAC_REG_ACCESS,
305673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
305773b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
305873b01e57SJeff Chen {.cmd_no = HOST_CMD_BBP_REG_ACCESS,
305973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
306073b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
306173b01e57SJeff Chen {.cmd_no = HOST_CMD_RF_REG_ACCESS,
306273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
306373b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
306473b01e57SJeff Chen {.cmd_no = HOST_CMD_RF_TX_PWR,
306573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_rf_tx_pwr,
306673b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_rf_tx_pwr},
306773b01e57SJeff Chen {.cmd_no = HOST_CMD_RF_ANTENNA,
306873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_rf_antenna,
306973b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_rf_antenna},
307073b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_DEAUTHENTICATE,
307173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_deauthenticate,
307273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_deauthenticate},
307373b01e57SJeff Chen {.cmd_no = HOST_CMD_MAC_CONTROL,
307473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mac_control,
307573b01e57SJeff Chen .cmd_resp = NULL},
307673b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_MAC_ADDRESS,
307773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_mac_address,
307873b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_mac_address},
307973b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_EEPROM_ACCESS,
308073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
308173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
308273b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11D_DOMAIN_INFO,
308373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11d_domain_info,
308473b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11d_domain_info},
308573b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_KEY_MATERIAL,
308673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_key_material,
308773b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_key_material},
308873b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_BG_SCAN_CONFIG,
308973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_config,
309073b01e57SJeff Chen .cmd_resp = NULL},
309173b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_BG_SCAN_QUERY,
309273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_bg_scan_query,
309373b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_bg_scan_query},
309473b01e57SJeff Chen {.cmd_no = HOST_CMD_WMM_GET_STATUS,
309573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_wmm_get_status,
309673b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_wmm_get_status},
309773b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_SUBSCRIBE_EVENT,
309873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_subsc_evt,
309973b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_subsc_evt},
310073b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_TX_RATE_QUERY,
310173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_tx_rate_query,
310273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_tx_rate_query},
310373b01e57SJeff Chen {.cmd_no = HOST_CMD_MEM_ACCESS,
310473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mem_access,
310573b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_mem_access},
310673b01e57SJeff Chen {.cmd_no = HOST_CMD_CFG_DATA,
310773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_cfg_data,
310873b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_cfg_data},
310973b01e57SJeff Chen {.cmd_no = HOST_CMD_VERSION_EXT,
311073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_ver_ext,
311173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_ver_ext},
311273b01e57SJeff Chen {.cmd_no = HOST_CMD_MEF_CFG,
311373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mef_cfg,
311473b01e57SJeff Chen .cmd_resp = NULL},
311573b01e57SJeff Chen {.cmd_no = HOST_CMD_RSSI_INFO,
311673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_rssi_info,
311773b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_rssi_info},
311873b01e57SJeff Chen {.cmd_no = HOST_CMD_FUNC_INIT,
311973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_func_init,
312073b01e57SJeff Chen .cmd_resp = NULL},
312173b01e57SJeff Chen {.cmd_no = HOST_CMD_FUNC_SHUTDOWN,
312273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_func_shutdown,
312373b01e57SJeff Chen .cmd_resp = NULL},
312473b01e57SJeff Chen {.cmd_no = HOST_CMD_PMIC_REG_ACCESS,
312573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
312673b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
312773b01e57SJeff Chen {.cmd_no = HOST_CMD_11N_CFG,
312873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11n_cfg,
312973b01e57SJeff Chen .cmd_resp = NULL},
313073b01e57SJeff Chen {.cmd_no = HOST_CMD_11N_ADDBA_REQ,
313173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11n_addba_req,
313273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_11n_addba_req},
313373b01e57SJeff Chen {.cmd_no = HOST_CMD_11N_ADDBA_RSP,
313473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11n_addba_rsp,
313573b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_11n_addba_rsp},
313673b01e57SJeff Chen {.cmd_no = HOST_CMD_11N_DELBA,
313773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11n_delba,
313873b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_11n_delba},
313973b01e57SJeff Chen {.cmd_no = HOST_CMD_TXPWR_CFG,
314073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_tx_power_cfg,
314173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_tx_power_cfg},
314273b01e57SJeff Chen {.cmd_no = HOST_CMD_TX_RATE_CFG,
314373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_tx_rate_cfg,
314473b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_tx_rate_cfg},
314573b01e57SJeff Chen {.cmd_no = HOST_CMD_RECONFIGURE_TX_BUFF,
314673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reconfigure_rx_buff,
314773b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reconfigure_rx_buff},
314873b01e57SJeff Chen {.cmd_no = HOST_CMD_CHAN_REPORT_REQUEST,
314973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_chan_report_request,
315073b01e57SJeff Chen .cmd_resp = NULL},
315173b01e57SJeff Chen {.cmd_no = HOST_CMD_AMSDU_AGGR_CTRL,
315273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_amsdu_aggr_ctrl,
315373b01e57SJeff Chen .cmd_resp = NULL},
315473b01e57SJeff Chen {.cmd_no = HOST_CMD_ROBUST_COEX,
315573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_robust_coex,
315673b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_robust_coex},
315773b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_PS_MODE_ENH,
315873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_enh_power_mode,
315973b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_enh_power_mode},
316073b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_HS_CFG_ENH,
316173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_hs_cfg,
316273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_hs_cfg},
316373b01e57SJeff Chen {.cmd_no = HOST_CMD_CAU_REG_ACCESS,
316473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_reg_access,
316573b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_reg_access},
316673b01e57SJeff Chen {.cmd_no = HOST_CMD_SET_BSS_MODE,
316773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_set_bss_mode,
316873b01e57SJeff Chen .cmd_resp = NULL},
316973b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_NET_MONITOR,
317073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_net_monitor,
317173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_net_monitor},
317273b01e57SJeff Chen {.cmd_no = HOST_CMD_802_11_SCAN_EXT,
317373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_802_11_scan_ext,
317473b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_802_11_scan_ext},
317573b01e57SJeff Chen {.cmd_no = HOST_CMD_COALESCE_CFG,
317673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_coalesce_cfg,
317773b01e57SJeff Chen .cmd_resp = NULL},
317873b01e57SJeff Chen {.cmd_no = HOST_CMD_MGMT_FRAME_REG,
317973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mgmt_frame_reg,
318073b01e57SJeff Chen .cmd_resp = NULL},
318173b01e57SJeff Chen {.cmd_no = HOST_CMD_REMAIN_ON_CHAN,
318273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_remain_on_chan,
318373b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_remain_on_chan},
318473b01e57SJeff Chen {.cmd_no = HOST_CMD_GTK_REKEY_OFFLOAD_CFG,
318573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_gtk_rekey_offload,
318673b01e57SJeff Chen .cmd_resp = NULL},
318773b01e57SJeff Chen {.cmd_no = HOST_CMD_11AC_CFG,
318873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11ac_cfg,
318973b01e57SJeff Chen .cmd_resp = NULL},
319073b01e57SJeff Chen {.cmd_no = HOST_CMD_HS_WAKEUP_REASON,
319173b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_hs_wakeup_reason,
319273b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_hs_wakeup_reason},
319373b01e57SJeff Chen {.cmd_no = HOST_CMD_MC_POLICY,
319473b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_mc_policy,
319573b01e57SJeff Chen .cmd_resp = NULL},
319673b01e57SJeff Chen {.cmd_no = HOST_CMD_FW_DUMP_EVENT,
319773b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_fill_head_only,
319873b01e57SJeff Chen .cmd_resp = NULL},
319973b01e57SJeff Chen {.cmd_no = HOST_CMD_SDIO_SP_RX_AGGR_CFG,
320073b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_sdio_rx_aggr_cfg,
320173b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_sdio_rx_aggr_cfg},
320273b01e57SJeff Chen {.cmd_no = HOST_CMD_STA_CONFIGURE,
320373b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_get_chan_info,
320473b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_get_chan_info},
320573b01e57SJeff Chen {.cmd_no = HOST_CMD_CHAN_REGION_CFG,
320673b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_chan_region_cfg,
320773b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_chan_region_cfg},
320873b01e57SJeff Chen {.cmd_no = HOST_CMD_PACKET_AGGR_CTRL,
320973b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_pkt_aggr_ctrl,
321073b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_pkt_aggr_ctrl},
321173b01e57SJeff Chen {.cmd_no = HOST_CMD_11AX_CFG,
321273b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11ax_cfg,
321373b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_11ax_cfg},
321473b01e57SJeff Chen {.cmd_no = HOST_CMD_11AX_CMD,
321573b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_11ax_cmd,
321673b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_11ax_cmd},
321773b01e57SJeff Chen {.cmd_no = HOST_CMD_TWT_CFG,
321873b01e57SJeff Chen .prepare_cmd = nxpwifi_cmd_sta_twt_cfg,
321973b01e57SJeff Chen .cmd_resp = nxpwifi_ret_sta_twt_cfg},
322073b01e57SJeff Chen };
322173b01e57SJeff Chen
322273b01e57SJeff Chen /*
322373b01e57SJeff Chen * Prepare a command before sending it to firmware by invoking the
322473b01e57SJeff Chen * appropriate handler based on the command ID.
322573b01e57SJeff Chen */
nxpwifi_sta_prepare_cmd(struct nxpwifi_private * priv,struct cmd_ctrl_node * cmd_node,u16 cmd_action,u32 cmd_oid)322673b01e57SJeff Chen int nxpwifi_sta_prepare_cmd(struct nxpwifi_private *priv,
322773b01e57SJeff Chen struct cmd_ctrl_node *cmd_node,
322873b01e57SJeff Chen u16 cmd_action, u32 cmd_oid)
322973b01e57SJeff Chen
323073b01e57SJeff Chen {
323173b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
323273b01e57SJeff Chen u16 cmd_no = cmd_node->cmd_no;
323373b01e57SJeff Chen struct host_cmd_ds_command *cmd =
323473b01e57SJeff Chen (struct host_cmd_ds_command *)cmd_node->skb->data;
323573b01e57SJeff Chen void *data_buf = cmd_node->data_buf;
323673b01e57SJeff Chen int i, ret = -EINVAL;
323773b01e57SJeff Chen
323873b01e57SJeff Chen for (i = 0; i < ARRAY_SIZE(cmd_table_sta); i++) {
323973b01e57SJeff Chen if (cmd_no == cmd_table_sta[i].cmd_no) {
324073b01e57SJeff Chen if (cmd_table_sta[i].prepare_cmd)
324173b01e57SJeff Chen ret = cmd_table_sta[i].prepare_cmd(priv, cmd,
324273b01e57SJeff Chen cmd_no,
324373b01e57SJeff Chen data_buf,
324473b01e57SJeff Chen cmd_action,
324573b01e57SJeff Chen cmd_oid);
324673b01e57SJeff Chen cmd_node->cmd_resp = cmd_table_sta[i].cmd_resp;
324773b01e57SJeff Chen break;
324873b01e57SJeff Chen }
324973b01e57SJeff Chen }
325073b01e57SJeff Chen
325173b01e57SJeff Chen if (i == ARRAY_SIZE(cmd_table_sta))
325273b01e57SJeff Chen nxpwifi_dbg(adapter, ERROR,
325373b01e57SJeff Chen "%s: unknown command: %#x\n",
325473b01e57SJeff Chen __func__, cmd_no);
325573b01e57SJeff Chen else
325673b01e57SJeff Chen nxpwifi_dbg(adapter, CMD,
325773b01e57SJeff Chen "%s: command: %#x\n",
325873b01e57SJeff Chen __func__, cmd_no);
325973b01e57SJeff Chen
326073b01e57SJeff Chen return ret;
326173b01e57SJeff Chen }
326273b01e57SJeff Chen
326373b01e57SJeff Chen /*
326473b01e57SJeff Chen * Initialize firmware after download or during virtual interface
326573b01e57SJeff Chen * reinitialization to bring the device to a working state.
326673b01e57SJeff Chen */
nxpwifi_sta_init_cmd(struct nxpwifi_private * priv,u8 first_sta,bool init)326773b01e57SJeff Chen int nxpwifi_sta_init_cmd(struct nxpwifi_private *priv, u8 first_sta, bool init)
326873b01e57SJeff Chen {
326973b01e57SJeff Chen struct nxpwifi_adapter *adapter = priv->adapter;
327073b01e57SJeff Chen int ret;
327173b01e57SJeff Chen struct nxpwifi_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;
327273b01e57SJeff Chen struct nxpwifi_ds_auto_ds auto_ds;
327373b01e57SJeff Chen enum state_11d_t state_11d;
327473b01e57SJeff Chen struct nxpwifi_ds_11n_tx_cfg tx_cfg;
327573b01e57SJeff Chen u8 sdio_sp_rx_aggr_enable;
327673b01e57SJeff Chen
327773b01e57SJeff Chen if (first_sta) {
327873b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_FUNC_INIT,
327973b01e57SJeff Chen HOST_ACT_GEN_SET, 0, NULL, true);
328073b01e57SJeff Chen if (ret)
328173b01e57SJeff Chen return ret;
328273b01e57SJeff Chen
328373b01e57SJeff Chen if (adapter->cal_data)
328473b01e57SJeff Chen nxpwifi_send_cmd(priv, HOST_CMD_CFG_DATA,
328573b01e57SJeff Chen HOST_ACT_GEN_SET, 0, NULL, true);
328673b01e57SJeff Chen
328773b01e57SJeff Chen /* Read MAC address from HW */
328873b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_GET_HW_SPEC,
328973b01e57SJeff Chen HOST_ACT_GEN_GET, 0, NULL, true);
329073b01e57SJeff Chen if (ret)
329173b01e57SJeff Chen return ret;
329273b01e57SJeff Chen
329373b01e57SJeff Chen /* * Set SDIO Single Port RX Aggr Info */
329473b01e57SJeff Chen if (priv->adapter->iface_type == NXPWIFI_SDIO &&
329573b01e57SJeff Chen ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) &&
329673b01e57SJeff Chen !priv->adapter->host_disable_sdio_rx_aggr) {
329773b01e57SJeff Chen sdio_sp_rx_aggr_enable = true;
329873b01e57SJeff Chen ret = nxpwifi_send_cmd(priv,
329973b01e57SJeff Chen HOST_CMD_SDIO_SP_RX_AGGR_CFG,
330073b01e57SJeff Chen HOST_ACT_GEN_SET, 0,
330173b01e57SJeff Chen &sdio_sp_rx_aggr_enable,
330273b01e57SJeff Chen true);
330373b01e57SJeff Chen if (ret) {
330473b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
330573b01e57SJeff Chen "error while enabling SP aggregation..disable it");
330673b01e57SJeff Chen adapter->sdio_rx_aggr_enable = false;
330773b01e57SJeff Chen }
330873b01e57SJeff Chen }
330973b01e57SJeff Chen
331073b01e57SJeff Chen /* Reconfigure tx buf size */
331173b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_RECONFIGURE_TX_BUFF,
331273b01e57SJeff Chen HOST_ACT_GEN_SET, 0,
331373b01e57SJeff Chen &priv->adapter->tx_buf_size, true);
331473b01e57SJeff Chen if (ret)
331573b01e57SJeff Chen return ret;
331673b01e57SJeff Chen
331773b01e57SJeff Chen if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
331873b01e57SJeff Chen /* Enable IEEE PS by default */
331973b01e57SJeff Chen priv->adapter->ps_mode = NXPWIFI_802_11_POWER_MODE_PSP;
332073b01e57SJeff Chen ret = nxpwifi_send_cmd(priv,
332173b01e57SJeff Chen HOST_CMD_802_11_PS_MODE_ENH,
332273b01e57SJeff Chen EN_AUTO_PS, BITMAP_STA_PS, NULL,
332373b01e57SJeff Chen true);
332473b01e57SJeff Chen if (ret)
332573b01e57SJeff Chen return ret;
332673b01e57SJeff Chen }
332773b01e57SJeff Chen
332873b01e57SJeff Chen nxpwifi_send_cmd(priv, HOST_CMD_CHAN_REGION_CFG,
332973b01e57SJeff Chen HOST_ACT_GEN_GET, 0, NULL, true);
333073b01e57SJeff Chen }
333173b01e57SJeff Chen
333273b01e57SJeff Chen /* get tx rate */
333373b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_TX_RATE_CFG,
333473b01e57SJeff Chen HOST_ACT_GEN_GET, 0, NULL, true);
333573b01e57SJeff Chen if (ret)
333673b01e57SJeff Chen return ret;
333773b01e57SJeff Chen priv->data_rate = 0;
333873b01e57SJeff Chen
333973b01e57SJeff Chen /* get tx power */
334073b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_RF_TX_PWR,
334173b01e57SJeff Chen HOST_ACT_GEN_GET, 0, NULL, true);
334273b01e57SJeff Chen if (ret)
334373b01e57SJeff Chen return ret;
334473b01e57SJeff Chen
334573b01e57SJeff Chen memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl));
334673b01e57SJeff Chen amsdu_aggr_ctrl.enable = true;
334773b01e57SJeff Chen /* Send request to firmware */
334873b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_AMSDU_AGGR_CTRL,
334973b01e57SJeff Chen HOST_ACT_GEN_SET, 0,
335073b01e57SJeff Chen &amsdu_aggr_ctrl, true);
335173b01e57SJeff Chen if (ret)
335273b01e57SJeff Chen return ret;
335373b01e57SJeff Chen /* MAC Control must be the last command in init_fw */
335473b01e57SJeff Chen /* set MAC Control */
335573b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_MAC_CONTROL,
335673b01e57SJeff Chen HOST_ACT_GEN_SET, 0,
335773b01e57SJeff Chen &priv->curr_pkt_filter, true);
335873b01e57SJeff Chen if (ret)
335973b01e57SJeff Chen return ret;
336073b01e57SJeff Chen
336173b01e57SJeff Chen if (!disable_auto_ds && first_sta &&
336273b01e57SJeff Chen priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
336373b01e57SJeff Chen /* Enable auto deep sleep */
336473b01e57SJeff Chen auto_ds.auto_ds = DEEP_SLEEP_ON;
336573b01e57SJeff Chen auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME;
336673b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_PS_MODE_ENH,
336773b01e57SJeff Chen EN_AUTO_PS, BITMAP_AUTO_DS,
336873b01e57SJeff Chen &auto_ds, true);
336973b01e57SJeff Chen if (ret)
337073b01e57SJeff Chen return ret;
337173b01e57SJeff Chen }
337273b01e57SJeff Chen
337373b01e57SJeff Chen if (priv->bss_type != NXPWIFI_BSS_TYPE_UAP) {
337473b01e57SJeff Chen /* Send cmd to FW to enable/disable 11D function */
337573b01e57SJeff Chen state_11d = ENABLE_11D;
337673b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_802_11_SNMP_MIB,
337773b01e57SJeff Chen HOST_ACT_GEN_SET, DOT11D_I,
337873b01e57SJeff Chen &state_11d, true);
337973b01e57SJeff Chen if (ret)
338073b01e57SJeff Chen nxpwifi_dbg(priv->adapter, ERROR,
338173b01e57SJeff Chen "11D: failed to enable 11D\n");
338273b01e57SJeff Chen }
338373b01e57SJeff Chen
338473b01e57SJeff Chen /*
338573b01e57SJeff Chen * Send cmd to FW to configure 11n specific configuration
338673b01e57SJeff Chen * (Short GI, Channel BW, Green field support etc.) for transmit
338773b01e57SJeff Chen */
338873b01e57SJeff Chen tx_cfg.tx_htcap = NXPWIFI_FW_DEF_HTTXCFG;
338973b01e57SJeff Chen ret = nxpwifi_send_cmd(priv, HOST_CMD_11N_CFG,
339073b01e57SJeff Chen HOST_ACT_GEN_SET, 0, &tx_cfg, true);
339173b01e57SJeff Chen
339273b01e57SJeff Chen return ret;
339373b01e57SJeff Chen }
3394