xref: /linux/drivers/net/wireless/nxp/nxpwifi/11ax.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
173b01e57SJeff Chen // SPDX-License-Identifier: GPL-2.0-only
273b01e57SJeff Chen /* nxpwifi: 802.11ax (HE) support
373b01e57SJeff Chen  * Copyright (C) 2011-2024 NXP
473b01e57SJeff Chen  */
573b01e57SJeff Chen 
673b01e57SJeff Chen #include "cfg.h"
773b01e57SJeff Chen #include "fw.h"
873b01e57SJeff Chen #include "main.h"
973b01e57SJeff Chen #include "11ax.h"
1073b01e57SJeff Chen 
nxpwifi_update_11ax_cap(struct nxpwifi_adapter * adapter,struct hw_spec_extension * hw_he_cap)1173b01e57SJeff Chen void nxpwifi_update_11ax_cap(struct nxpwifi_adapter *adapter,
1273b01e57SJeff Chen 			     struct hw_spec_extension *hw_he_cap)
1373b01e57SJeff Chen {
1473b01e57SJeff Chen 	struct nxpwifi_private *priv;
1573b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *he_cap = NULL;
1673b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *user_he_cap = NULL;
1773b01e57SJeff Chen 	u8 header_len = sizeof(struct nxpwifi_ie_types_header);
1873b01e57SJeff Chen 	u16 data_len = le16_to_cpu(hw_he_cap->header.len);
1973b01e57SJeff Chen 	bool he_cap_2g = false;
2073b01e57SJeff Chen 	int i;
2173b01e57SJeff Chen 
2273b01e57SJeff Chen 	if ((data_len + header_len) > sizeof(adapter->hw_he_cap)) {
2373b01e57SJeff Chen 		nxpwifi_dbg(adapter, ERROR,
2473b01e57SJeff Chen 			    "hw_he_cap too big, len=%d\n",
2573b01e57SJeff Chen 			    data_len);
2673b01e57SJeff Chen 		return;
2773b01e57SJeff Chen 	}
2873b01e57SJeff Chen 
2973b01e57SJeff Chen 	he_cap = (struct nxpwifi_ie_types_he_cap *)hw_he_cap;
3073b01e57SJeff Chen 
3173b01e57SJeff Chen 	if (he_cap->he_phy_cap[0] &
3273b01e57SJeff Chen 	    (AX_2G_40MHZ_SUPPORT | AX_2G_20MHZ_SUPPORT)) {
3373b01e57SJeff Chen 		adapter->hw_2g_he_cap_len = data_len + header_len;
3473b01e57SJeff Chen 		memcpy(adapter->hw_2g_he_cap, (u8 *)hw_he_cap,
3573b01e57SJeff Chen 		       adapter->hw_2g_he_cap_len);
3673b01e57SJeff Chen 		adapter->fw_bands |= BAND_GAX;
3773b01e57SJeff Chen 		he_cap_2g = true;
3873b01e57SJeff Chen 		nxpwifi_dbg_dump(adapter, CMD_D, "2.4G HE capability element ",
3973b01e57SJeff Chen 				 adapter->hw_2g_he_cap,
4073b01e57SJeff Chen 				 adapter->hw_2g_he_cap_len);
4173b01e57SJeff Chen 	} else {
4273b01e57SJeff Chen 		adapter->hw_he_cap_len = data_len + header_len;
4373b01e57SJeff Chen 		memcpy(adapter->hw_he_cap, (u8 *)hw_he_cap,
4473b01e57SJeff Chen 		       adapter->hw_he_cap_len);
4573b01e57SJeff Chen 		adapter->fw_bands |= BAND_AAX;
4673b01e57SJeff Chen 		nxpwifi_dbg_dump(adapter, CMD_D, "5G HE capability element ",
4773b01e57SJeff Chen 				 adapter->hw_he_cap,
4873b01e57SJeff Chen 				 adapter->hw_he_cap_len);
4973b01e57SJeff Chen 	}
5073b01e57SJeff Chen 
5173b01e57SJeff Chen 	for (i = 0; i < adapter->priv_num; i++) {
5273b01e57SJeff Chen 		priv = adapter->priv[i];
5373b01e57SJeff Chen 
5473b01e57SJeff Chen 		if (he_cap_2g) {
5573b01e57SJeff Chen 			priv->user_2g_he_cap_len = adapter->hw_2g_he_cap_len;
5673b01e57SJeff Chen 			memcpy(priv->user_2g_he_cap, adapter->hw_2g_he_cap,
5773b01e57SJeff Chen 			       sizeof(adapter->hw_2g_he_cap));
5873b01e57SJeff Chen 			user_he_cap = (struct nxpwifi_ie_types_he_cap *)
5973b01e57SJeff Chen 				priv->user_2g_he_cap;
6073b01e57SJeff Chen 		} else {
6173b01e57SJeff Chen 			priv->user_he_cap_len = adapter->hw_he_cap_len;
6273b01e57SJeff Chen 			memcpy(priv->user_he_cap, adapter->hw_he_cap,
6373b01e57SJeff Chen 			       sizeof(adapter->hw_he_cap));
6473b01e57SJeff Chen 			user_he_cap = (struct nxpwifi_ie_types_he_cap *)
6573b01e57SJeff Chen 				priv->user_he_cap;
6673b01e57SJeff Chen 		}
6773b01e57SJeff Chen 
6873b01e57SJeff Chen 		if (GET_BSS_ROLE(priv) == NXPWIFI_BSS_ROLE_STA)
6973b01e57SJeff Chen 			user_he_cap->he_mac_cap[0] &=
7073b01e57SJeff Chen 				~HE_MAC_CAP_TWT_RESP_SUPPORT;
7173b01e57SJeff Chen 		else
7273b01e57SJeff Chen 			user_he_cap->he_mac_cap[0] &=
7373b01e57SJeff Chen 				~HE_MAC_CAP_TWT_REQ_SUPPORT;
7473b01e57SJeff Chen 	}
7573b01e57SJeff Chen 
7673b01e57SJeff Chen 	adapter->is_hw_11ax_capable = true;
7773b01e57SJeff Chen }
7873b01e57SJeff Chen 
nxpwifi_11ax_bandconfig_allowed(struct nxpwifi_private * priv,struct nxpwifi_bssdescriptor * bss_desc)7973b01e57SJeff Chen bool nxpwifi_11ax_bandconfig_allowed(struct nxpwifi_private *priv,
8073b01e57SJeff Chen 				     struct nxpwifi_bssdescriptor *bss_desc)
8173b01e57SJeff Chen {
8273b01e57SJeff Chen 	u16 bss_band = bss_desc->bss_band;
8373b01e57SJeff Chen 
8473b01e57SJeff Chen 	if (bss_desc->disable_11n)
8573b01e57SJeff Chen 		return false;
8673b01e57SJeff Chen 
8773b01e57SJeff Chen 	if (bss_band & BAND_G)
8873b01e57SJeff Chen 		return (priv->config_bands & BAND_GAX);
8973b01e57SJeff Chen 	else if (bss_band & BAND_A)
9073b01e57SJeff Chen 		return (priv->config_bands & BAND_AAX);
9173b01e57SJeff Chen 
9273b01e57SJeff Chen 	return false;
9373b01e57SJeff Chen }
9473b01e57SJeff Chen 
nxpwifi_fill_he_cap_tlv(struct nxpwifi_private * priv,struct nxpwifi_ie_types_he_cap * he_cap,u16 bands)9573b01e57SJeff Chen int nxpwifi_fill_he_cap_tlv(struct nxpwifi_private *priv,
9673b01e57SJeff Chen 			    struct nxpwifi_ie_types_he_cap *he_cap,
9773b01e57SJeff Chen 			    u16 bands)
9873b01e57SJeff Chen {
9973b01e57SJeff Chen 	struct nxpwifi_adapter *adapter = priv->adapter;
10073b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *hw_he_cap = NULL;
10173b01e57SJeff Chen 	u16 rx_nss, tx_nss;
10273b01e57SJeff Chen 	u8 nss;
10373b01e57SJeff Chen 	u16 cfg_value;
10473b01e57SJeff Chen 	u16 hw_value;
10573b01e57SJeff Chen 	int ret_len;
10673b01e57SJeff Chen 
10773b01e57SJeff Chen 	if (bands & BAND_A) {
10873b01e57SJeff Chen 		memcpy(he_cap, priv->user_he_cap, priv->user_he_cap_len);
10973b01e57SJeff Chen 		hw_he_cap = (struct nxpwifi_ie_types_he_cap *)adapter->hw_he_cap;
11073b01e57SJeff Chen 		ret_len = priv->user_he_cap_len;
11173b01e57SJeff Chen 	} else {
11273b01e57SJeff Chen 		memcpy(he_cap, priv->user_2g_he_cap, priv->user_2g_he_cap_len);
11373b01e57SJeff Chen 		hw_he_cap = (struct nxpwifi_ie_types_he_cap *)adapter->hw_2g_he_cap;
11473b01e57SJeff Chen 		ret_len = priv->user_2g_he_cap_len;
11573b01e57SJeff Chen 	}
11673b01e57SJeff Chen 
11773b01e57SJeff Chen 	if (bands & BAND_A) {
11873b01e57SJeff Chen 		rx_nss = GET_RXMCSSUPP(adapter->user_htstream >> 8);
11973b01e57SJeff Chen 		tx_nss = GET_TXMCSSUPP(adapter->user_htstream >> 8) & 0x0f;
12073b01e57SJeff Chen 	} else {
12173b01e57SJeff Chen 		rx_nss = GET_RXMCSSUPP(adapter->user_htstream);
12273b01e57SJeff Chen 		tx_nss = GET_TXMCSSUPP(adapter->user_htstream) & 0x0f;
12373b01e57SJeff Chen 	}
12473b01e57SJeff Chen 
12573b01e57SJeff Chen 	for (nss = 1; nss <= 8; nss++) {
12673b01e57SJeff Chen 		cfg_value = nxpwifi_get_he_nss_mcs(he_cap->rx_mcs_80, nss);
12773b01e57SJeff Chen 		hw_value = nxpwifi_get_he_nss_mcs(hw_he_cap->rx_mcs_80, nss);
12873b01e57SJeff Chen 		if (rx_nss != 0 && nss > rx_nss)
12973b01e57SJeff Chen 			cfg_value = NO_NSS_SUPPORT;
13073b01e57SJeff Chen 		if (hw_value == NO_NSS_SUPPORT || cfg_value == NO_NSS_SUPPORT)
13173b01e57SJeff Chen 			nxpwifi_set_he_nss_mcs(&he_cap->rx_mcs_80, nss,
13273b01e57SJeff Chen 					       NO_NSS_SUPPORT);
13373b01e57SJeff Chen 		else
13473b01e57SJeff Chen 			nxpwifi_set_he_nss_mcs(&he_cap->rx_mcs_80, nss,
13573b01e57SJeff Chen 					       min(cfg_value, hw_value));
13673b01e57SJeff Chen 	}
13773b01e57SJeff Chen 
13873b01e57SJeff Chen 	for (nss = 1; nss <= 8; nss++) {
13973b01e57SJeff Chen 		cfg_value = nxpwifi_get_he_nss_mcs(he_cap->tx_mcs_80, nss);
14073b01e57SJeff Chen 		hw_value = nxpwifi_get_he_nss_mcs(hw_he_cap->tx_mcs_80, nss);
14173b01e57SJeff Chen 		if (tx_nss != 0 && nss > tx_nss)
14273b01e57SJeff Chen 			cfg_value = NO_NSS_SUPPORT;
14373b01e57SJeff Chen 		if (hw_value == NO_NSS_SUPPORT || cfg_value == NO_NSS_SUPPORT)
14473b01e57SJeff Chen 			nxpwifi_set_he_nss_mcs(&he_cap->tx_mcs_80, nss,
14573b01e57SJeff Chen 					       NO_NSS_SUPPORT);
14673b01e57SJeff Chen 		else
14773b01e57SJeff Chen 			nxpwifi_set_he_nss_mcs(&he_cap->tx_mcs_80, nss,
14873b01e57SJeff Chen 					       min(cfg_value, hw_value));
14973b01e57SJeff Chen 	}
15073b01e57SJeff Chen 
15173b01e57SJeff Chen 	return ret_len;
15273b01e57SJeff Chen }
15373b01e57SJeff Chen 
nxpwifi_cmd_append_11ax_tlv(struct nxpwifi_private * priv,struct nxpwifi_bssdescriptor * bss_desc,u8 ** buffer)15473b01e57SJeff Chen int nxpwifi_cmd_append_11ax_tlv(struct nxpwifi_private *priv,
15573b01e57SJeff Chen 				struct nxpwifi_bssdescriptor *bss_desc,
15673b01e57SJeff Chen 				u8 **buffer)
15773b01e57SJeff Chen {
15873b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *he_cap = NULL;
15973b01e57SJeff Chen 	int ret_len;
16073b01e57SJeff Chen 
16173b01e57SJeff Chen 	if (!bss_desc->bcn_he_cap)
16273b01e57SJeff Chen 		return -EOPNOTSUPP;
16373b01e57SJeff Chen 
16473b01e57SJeff Chen 	he_cap = (struct nxpwifi_ie_types_he_cap *)*buffer;
16573b01e57SJeff Chen 	ret_len = nxpwifi_fill_he_cap_tlv(priv, he_cap, bss_desc->bss_band);
16673b01e57SJeff Chen 	*buffer += ret_len;
16773b01e57SJeff Chen 
16873b01e57SJeff Chen 	return ret_len;
16973b01e57SJeff Chen }
17073b01e57SJeff Chen 
nxpwifi_cmd_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_action,struct nxpwifi_11ax_he_cfg * ax_cfg)17173b01e57SJeff Chen int nxpwifi_cmd_11ax_cfg(struct nxpwifi_private *priv,
17273b01e57SJeff Chen 			 struct host_cmd_ds_command *cmd, u16 cmd_action,
17373b01e57SJeff Chen 			 struct nxpwifi_11ax_he_cfg *ax_cfg)
17473b01e57SJeff Chen {
17573b01e57SJeff Chen 	struct host_cmd_11ax_cfg *he_cfg = &cmd->params.ax_cfg;
17673b01e57SJeff Chen 	u16 cmd_size;
17773b01e57SJeff Chen 	struct nxpwifi_ie_types_header *header;
17873b01e57SJeff Chen 
17973b01e57SJeff Chen 	cmd->command = cpu_to_le16(HOST_CMD_11AX_CFG);
18073b01e57SJeff Chen 	cmd_size = sizeof(struct host_cmd_11ax_cfg) + S_DS_GEN;
18173b01e57SJeff Chen 
18273b01e57SJeff Chen 	he_cfg->action = cpu_to_le16(cmd_action);
18373b01e57SJeff Chen 	he_cfg->band_config = ax_cfg->band;
18473b01e57SJeff Chen 
18573b01e57SJeff Chen 	if (ax_cfg->he_cap_cfg.len &&
18673b01e57SJeff Chen 	    ax_cfg->he_cap_cfg.ext_id == WLAN_EID_EXT_HE_CAPABILITY) {
18773b01e57SJeff Chen 		header = (struct nxpwifi_ie_types_header *)he_cfg->tlv;
18873b01e57SJeff Chen 		header->type = cpu_to_le16(ax_cfg->he_cap_cfg.id);
18973b01e57SJeff Chen 		header->len = cpu_to_le16(ax_cfg->he_cap_cfg.len);
19073b01e57SJeff Chen 		memcpy(he_cfg->tlv + sizeof(*header),
19173b01e57SJeff Chen 		       &ax_cfg->he_cap_cfg.ext_id,
19273b01e57SJeff Chen 		       ax_cfg->he_cap_cfg.len);
19373b01e57SJeff Chen 		cmd_size += (sizeof(*header) + ax_cfg->he_cap_cfg.len);
19473b01e57SJeff Chen 	}
19573b01e57SJeff Chen 
19673b01e57SJeff Chen 	cmd->size = cpu_to_le16(cmd_size);
19773b01e57SJeff Chen 
19873b01e57SJeff Chen 	return 0;
19973b01e57SJeff Chen }
20073b01e57SJeff Chen 
nxpwifi_ret_11ax_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,struct nxpwifi_11ax_he_cfg * ax_cfg)20173b01e57SJeff Chen int nxpwifi_ret_11ax_cfg(struct nxpwifi_private *priv,
20273b01e57SJeff Chen 			 struct host_cmd_ds_command *resp,
20373b01e57SJeff Chen 			 struct nxpwifi_11ax_he_cfg *ax_cfg)
20473b01e57SJeff Chen {
20573b01e57SJeff Chen 	struct host_cmd_11ax_cfg *he_cfg = &resp->params.ax_cfg;
20673b01e57SJeff Chen 	struct nxpwifi_ie_types_header *header;
20773b01e57SJeff Chen 	u16 left_len, tlv_type, tlv_len;
20873b01e57SJeff Chen 	u8 ext_id;
20973b01e57SJeff Chen 	struct nxpwifi_11ax_he_cap_cfg *he_cap = &ax_cfg->he_cap_cfg;
21073b01e57SJeff Chen 
21173b01e57SJeff Chen 	left_len = le16_to_cpu(resp->size) - sizeof(*he_cfg) - S_DS_GEN;
21273b01e57SJeff Chen 	header = (struct nxpwifi_ie_types_header *)he_cfg->tlv;
21373b01e57SJeff Chen 
21473b01e57SJeff Chen 	while (left_len > sizeof(*header)) {
21573b01e57SJeff Chen 		tlv_type = le16_to_cpu(header->type);
21673b01e57SJeff Chen 		tlv_len = le16_to_cpu(header->len);
21773b01e57SJeff Chen 
21873b01e57SJeff Chen 		if (tlv_type == TLV_TYPE_EXTENSION_ID) {
21973b01e57SJeff Chen 			ext_id = *((u8 *)header + sizeof(*header) + 1);
22073b01e57SJeff Chen 			if (ext_id == WLAN_EID_EXT_HE_CAPABILITY) {
22173b01e57SJeff Chen 				he_cap->id = tlv_type;
22273b01e57SJeff Chen 				he_cap->len = tlv_len;
22373b01e57SJeff Chen 				memcpy((u8 *)&he_cap->ext_id,
22473b01e57SJeff Chen 				       (u8 *)header + sizeof(*header) + 1,
22573b01e57SJeff Chen 				       tlv_len);
22673b01e57SJeff Chen 				if (he_cfg->band_config & BIT(1)) {
22773b01e57SJeff Chen 					memcpy(priv->user_he_cap,
22873b01e57SJeff Chen 					       (u8 *)header,
22973b01e57SJeff Chen 					       sizeof(*header) + tlv_len);
23073b01e57SJeff Chen 					priv->user_he_cap_len =
23173b01e57SJeff Chen 						sizeof(*header) + tlv_len;
23273b01e57SJeff Chen 				} else {
23373b01e57SJeff Chen 					memcpy(priv->user_2g_he_cap,
23473b01e57SJeff Chen 					       (u8 *)header,
23573b01e57SJeff Chen 					       sizeof(*header) + tlv_len);
23673b01e57SJeff Chen 					priv->user_2g_he_cap_len =
23773b01e57SJeff Chen 						sizeof(*header) + tlv_len;
23873b01e57SJeff Chen 				}
23973b01e57SJeff Chen 			}
24073b01e57SJeff Chen 		}
24173b01e57SJeff Chen 
24273b01e57SJeff Chen 		left_len -= (sizeof(*header) + tlv_len);
24373b01e57SJeff Chen 		header = (struct nxpwifi_ie_types_header *)((u8 *)header +
24473b01e57SJeff Chen 							    sizeof(*header) +
24573b01e57SJeff Chen 							    tlv_len);
24673b01e57SJeff Chen 	}
24773b01e57SJeff Chen 
24873b01e57SJeff Chen 	return 0;
24973b01e57SJeff Chen }
25073b01e57SJeff Chen 
nxpwifi_cmd_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_action,struct nxpwifi_11ax_cmd_cfg * ax_cmd)25173b01e57SJeff Chen int nxpwifi_cmd_11ax_cmd(struct nxpwifi_private *priv,
25273b01e57SJeff Chen 			 struct host_cmd_ds_command *cmd, u16 cmd_action,
25373b01e57SJeff Chen 			 struct nxpwifi_11ax_cmd_cfg *ax_cmd)
25473b01e57SJeff Chen {
25573b01e57SJeff Chen 	struct nxpwifi_adapter *adapter = priv->adapter;
25673b01e57SJeff Chen 	struct host_cmd_11ax_cmd *he_cmd = &cmd->params.ax_cmd;
25773b01e57SJeff Chen 	u16 cmd_size;
25873b01e57SJeff Chen 	struct nxpwifi_11ax_sr_cmd *sr_cmd;
25973b01e57SJeff Chen 	struct nxpwifi_ie_types_data *tlv;
26073b01e57SJeff Chen 	struct nxpwifi_11ax_beam_cmd *beam_cmd;
26173b01e57SJeff Chen 	struct nxpwifi_11ax_htc_cmd *htc_cmd;
26273b01e57SJeff Chen 	struct nxpwifi_11ax_txomi_cmd *txmoi_cmd;
26373b01e57SJeff Chen 	struct nxpwifi_11ax_toltime_cmd *toltime_cmd;
26473b01e57SJeff Chen 	struct nxpwifi_11ax_txop_cmd *txop_cmd;
26573b01e57SJeff Chen 	struct nxpwifi_11ax_set_bsrp_cmd *set_bsrp_cmd;
26673b01e57SJeff Chen 	struct nxpwifi_11ax_llde_cmd *llde_cmd;
26773b01e57SJeff Chen 
26873b01e57SJeff Chen 	cmd->command = cpu_to_le16(HOST_CMD_11AX_CMD);
26973b01e57SJeff Chen 	cmd_size = sizeof(struct host_cmd_11ax_cmd) + S_DS_GEN;
27073b01e57SJeff Chen 
27173b01e57SJeff Chen 	he_cmd->action = cpu_to_le16(cmd_action);
27273b01e57SJeff Chen 	he_cmd->sub_id = cpu_to_le16(ax_cmd->sub_id);
27373b01e57SJeff Chen 
27473b01e57SJeff Chen 	switch (ax_cmd->sub_command) {
27573b01e57SJeff Chen 	case NXPWIFI_11AXCMD_SR_SUBID:
27673b01e57SJeff Chen 		sr_cmd = (struct nxpwifi_11ax_sr_cmd *)&ax_cmd->param;
27773b01e57SJeff Chen 
27873b01e57SJeff Chen 		tlv = (struct nxpwifi_ie_types_data *)he_cmd->val;
27973b01e57SJeff Chen 		tlv->header.type = cpu_to_le16(sr_cmd->type);
28073b01e57SJeff Chen 		tlv->header.len = cpu_to_le16(sr_cmd->len);
28173b01e57SJeff Chen 		memcpy(tlv->data, sr_cmd->param.obss_pd_offset.offset,
28273b01e57SJeff Chen 		       sr_cmd->len);
28373b01e57SJeff Chen 		cmd_size += (sizeof(tlv->header) + sr_cmd->len);
28473b01e57SJeff Chen 		break;
28573b01e57SJeff Chen 	case NXPWIFI_11AXCMD_BEAM_SUBID:
28673b01e57SJeff Chen 		beam_cmd = (struct nxpwifi_11ax_beam_cmd *)&ax_cmd->param;
28773b01e57SJeff Chen 
28873b01e57SJeff Chen 		he_cmd->val[0] = beam_cmd->value;
28973b01e57SJeff Chen 		cmd_size += sizeof(*beam_cmd);
29073b01e57SJeff Chen 		break;
29173b01e57SJeff Chen 	case NXPWIFI_11AXCMD_HTC_SUBID:
29273b01e57SJeff Chen 		htc_cmd = (struct nxpwifi_11ax_htc_cmd *)&ax_cmd->param;
29373b01e57SJeff Chen 
29473b01e57SJeff Chen 		he_cmd->val[0] = htc_cmd->value;
29573b01e57SJeff Chen 		cmd_size += sizeof(*htc_cmd);
29673b01e57SJeff Chen 		break;
29773b01e57SJeff Chen 	case NXPWIFI_11AXCMD_TXOMI_SUBID:
29873b01e57SJeff Chen 		txmoi_cmd =	(struct nxpwifi_11ax_txomi_cmd *)&ax_cmd->param;
29973b01e57SJeff Chen 
30073b01e57SJeff Chen 		memcpy((void *)he_cmd->val, txmoi_cmd, sizeof(*txmoi_cmd));
30173b01e57SJeff Chen 		cmd_size += sizeof(*txmoi_cmd);
30273b01e57SJeff Chen 		break;
30373b01e57SJeff Chen 	case NXPWIFI_11AXCMD_OBSS_TOLTIME_SUBID:
30473b01e57SJeff Chen 		toltime_cmd = (struct nxpwifi_11ax_toltime_cmd *)&ax_cmd->param;
30573b01e57SJeff Chen 
30673b01e57SJeff Chen 		memcpy(he_cmd->val, &toltime_cmd->tol_time,
30773b01e57SJeff Chen 		       sizeof(toltime_cmd->tol_time));
30873b01e57SJeff Chen 		cmd_size += sizeof(*toltime_cmd);
30973b01e57SJeff Chen 		break;
31073b01e57SJeff Chen 	case NXPWIFI_11AXCMD_TXOPRTS_SUBID:
31173b01e57SJeff Chen 		txop_cmd = (struct nxpwifi_11ax_txop_cmd *)&ax_cmd->param;
31273b01e57SJeff Chen 
31373b01e57SJeff Chen 		memcpy(he_cmd->val, &txop_cmd->rts_thres,
31473b01e57SJeff Chen 		       sizeof(txop_cmd->rts_thres));
31573b01e57SJeff Chen 		cmd_size += sizeof(*txop_cmd);
31673b01e57SJeff Chen 		break;
31773b01e57SJeff Chen 	case NXPWIFI_11AXCMD_SET_BSRP_SUBID:
31873b01e57SJeff Chen 		set_bsrp_cmd = (struct nxpwifi_11ax_set_bsrp_cmd *)&ax_cmd->param;
31973b01e57SJeff Chen 
32073b01e57SJeff Chen 		he_cmd->val[0] = set_bsrp_cmd->value;
32173b01e57SJeff Chen 		cmd_size += sizeof(*set_bsrp_cmd);
32273b01e57SJeff Chen 		break;
32373b01e57SJeff Chen 	case NXPWIFI_11AXCMD_LLDE_SUBID:
32473b01e57SJeff Chen 		llde_cmd = (struct nxpwifi_11ax_llde_cmd *)&ax_cmd->param;
32573b01e57SJeff Chen 
32673b01e57SJeff Chen 		memcpy((void *)he_cmd->val, llde_cmd, sizeof(*llde_cmd));
32773b01e57SJeff Chen 		cmd_size += sizeof(*llde_cmd);
32873b01e57SJeff Chen 		break;
32973b01e57SJeff Chen 	default:
33073b01e57SJeff Chen 		nxpwifi_dbg(adapter, ERROR,
33173b01e57SJeff Chen 			    "%s: Unknown sub command: %d\n",
33273b01e57SJeff Chen 			    __func__, ax_cmd->sub_command);
33373b01e57SJeff Chen 		return -EINVAL;
33473b01e57SJeff Chen 	}
33573b01e57SJeff Chen 
33673b01e57SJeff Chen 	cmd->size = cpu_to_le16(cmd_size);
33773b01e57SJeff Chen 
33873b01e57SJeff Chen 	return 0;
33973b01e57SJeff Chen }
34073b01e57SJeff Chen 
nxpwifi_ret_11ax_cmd(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,struct nxpwifi_11ax_cmd_cfg * ax_cmd)34173b01e57SJeff Chen int nxpwifi_ret_11ax_cmd(struct nxpwifi_private *priv,
34273b01e57SJeff Chen 			 struct host_cmd_ds_command *resp,
34373b01e57SJeff Chen 			 struct nxpwifi_11ax_cmd_cfg *ax_cmd)
34473b01e57SJeff Chen {
34573b01e57SJeff Chen 	struct nxpwifi_adapter *adapter = priv->adapter;
34673b01e57SJeff Chen 	struct host_cmd_11ax_cmd *he_cmd = &resp->params.ax_cmd;
34773b01e57SJeff Chen 	struct nxpwifi_ie_types_data *tlv;
34873b01e57SJeff Chen 
34973b01e57SJeff Chen 	ax_cmd->sub_id = le16_to_cpu(he_cmd->sub_id);
35073b01e57SJeff Chen 
35173b01e57SJeff Chen 	switch (ax_cmd->sub_command) {
35273b01e57SJeff Chen 	case NXPWIFI_11AXCMD_SR_SUBID:
35373b01e57SJeff Chen 		tlv = (struct nxpwifi_ie_types_data *)he_cmd->val;
35473b01e57SJeff Chen 		memcpy(ax_cmd->param.sr_cfg.param.obss_pd_offset.offset,
35573b01e57SJeff Chen 		       tlv->data,
35673b01e57SJeff Chen 		       ax_cmd->param.sr_cfg.len);
35773b01e57SJeff Chen 		break;
35873b01e57SJeff Chen 	case NXPWIFI_11AXCMD_BEAM_SUBID:
35973b01e57SJeff Chen 		ax_cmd->param.beam_cfg.value = *he_cmd->val;
36073b01e57SJeff Chen 		break;
36173b01e57SJeff Chen 	case NXPWIFI_11AXCMD_HTC_SUBID:
36273b01e57SJeff Chen 		ax_cmd->param.htc_cfg.value = *he_cmd->val;
36373b01e57SJeff Chen 		break;
36473b01e57SJeff Chen 	case NXPWIFI_11AXCMD_TXOMI_SUBID:
36573b01e57SJeff Chen 		memcpy(&ax_cmd->param.txomi_cfg,
36673b01e57SJeff Chen 		       he_cmd->val, sizeof(ax_cmd->param.txomi_cfg));
36773b01e57SJeff Chen 		break;
36873b01e57SJeff Chen 	case NXPWIFI_11AXCMD_OBSS_TOLTIME_SUBID:
36973b01e57SJeff Chen 		memcpy(&ax_cmd->param.toltime_cfg.tol_time,
37073b01e57SJeff Chen 		       he_cmd->val, sizeof(ax_cmd->param.toltime_cfg));
37173b01e57SJeff Chen 		break;
37273b01e57SJeff Chen 	case NXPWIFI_11AXCMD_TXOPRTS_SUBID:
37373b01e57SJeff Chen 		memcpy(&ax_cmd->param.txop_cfg.rts_thres,
37473b01e57SJeff Chen 		       he_cmd->val, sizeof(ax_cmd->param.txop_cfg));
37573b01e57SJeff Chen 		break;
37673b01e57SJeff Chen 	case NXPWIFI_11AXCMD_SET_BSRP_SUBID:
37773b01e57SJeff Chen 		ax_cmd->param.setbsrp_cfg.value = *he_cmd->val;
37873b01e57SJeff Chen 		break;
37973b01e57SJeff Chen 	case NXPWIFI_11AXCMD_LLDE_SUBID:
38073b01e57SJeff Chen 		memcpy(&ax_cmd->param.llde_cfg,
38173b01e57SJeff Chen 		       he_cmd->val, sizeof(ax_cmd->param.llde_cfg));
38273b01e57SJeff Chen 		break;
38373b01e57SJeff Chen 	default:
38473b01e57SJeff Chen 		nxpwifi_dbg(adapter, ERROR,
38573b01e57SJeff Chen 			    "%s: Unknown sub command: %d\n",
38673b01e57SJeff Chen 			    __func__, ax_cmd->sub_command);
38773b01e57SJeff Chen 		return -EINVAL;
38873b01e57SJeff Chen 	}
38973b01e57SJeff Chen 
39073b01e57SJeff Chen 	return 0;
39173b01e57SJeff Chen }
39273b01e57SJeff Chen 
nxpwifi_is_ap_11ax_twt_supported(struct nxpwifi_bssdescriptor * bss_desc)39373b01e57SJeff Chen static u8 nxpwifi_is_ap_11ax_twt_supported(struct nxpwifi_bssdescriptor *bss_desc)
39473b01e57SJeff Chen {
39573b01e57SJeff Chen 	struct element *ext_cap;
39673b01e57SJeff Chen 
39773b01e57SJeff Chen 	if (!bss_desc->bcn_he_cap)
39873b01e57SJeff Chen 		return false;
39973b01e57SJeff Chen 	if (!(bss_desc->bcn_he_cap->mac_cap_info[0] & HE_MAC_CAP_TWT_RESP_SUPPORT))
40073b01e57SJeff Chen 		return false;
40173b01e57SJeff Chen 	if (!bss_desc->bcn_ext_cap)
40273b01e57SJeff Chen 		return false;
40373b01e57SJeff Chen 	ext_cap = (struct element *)bss_desc->bcn_ext_cap;
40473b01e57SJeff Chen 
40573b01e57SJeff Chen 	if (!(ext_cap->data[9] & WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT))
40673b01e57SJeff Chen 		return false;
40773b01e57SJeff Chen 	return true;
40873b01e57SJeff Chen }
40973b01e57SJeff Chen 
nxpwifi_is_11ax_twt_supported(struct nxpwifi_private * priv,struct nxpwifi_bssdescriptor * bss_desc)41073b01e57SJeff Chen bool nxpwifi_is_11ax_twt_supported(struct nxpwifi_private *priv,
41173b01e57SJeff Chen 				   struct nxpwifi_bssdescriptor *bss_desc)
41273b01e57SJeff Chen {
41373b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *user_he_cap;
41473b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *hw_he_cap;
41573b01e57SJeff Chen 
416*00c786a7SJeff Chen 	if (!bss_desc)
417*00c786a7SJeff Chen 		return false;
418*00c786a7SJeff Chen 
419*00c786a7SJeff Chen 	if (!nxpwifi_is_ap_11ax_twt_supported(bss_desc)) {
42073b01e57SJeff Chen 		nxpwifi_dbg(priv->adapter, MSG,
42173b01e57SJeff Chen 			    "AP don't support twt feature\n");
42273b01e57SJeff Chen 		return false;
42373b01e57SJeff Chen 	}
42473b01e57SJeff Chen 
42573b01e57SJeff Chen 	if (bss_desc->bss_band & BAND_A) {
42673b01e57SJeff Chen 		hw_he_cap = (struct nxpwifi_ie_types_he_cap *)
42773b01e57SJeff Chen 			priv->adapter->hw_he_cap;
42873b01e57SJeff Chen 		user_he_cap = (struct nxpwifi_ie_types_he_cap *)
42973b01e57SJeff Chen 			priv->user_he_cap;
43073b01e57SJeff Chen 	} else {
43173b01e57SJeff Chen 		hw_he_cap = (struct nxpwifi_ie_types_he_cap *)
43273b01e57SJeff Chen 			priv->adapter->hw_2g_he_cap;
43373b01e57SJeff Chen 		user_he_cap = (struct nxpwifi_ie_types_he_cap *)
43473b01e57SJeff Chen 			priv->user_2g_he_cap;
43573b01e57SJeff Chen 	}
43673b01e57SJeff Chen 
43773b01e57SJeff Chen 	if (!(hw_he_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)) {
43873b01e57SJeff Chen 		nxpwifi_dbg(priv->adapter, MSG,
43973b01e57SJeff Chen 			    "FW don't support TWT\n");
44073b01e57SJeff Chen 		return false;
44173b01e57SJeff Chen 	}
44273b01e57SJeff Chen 
44373b01e57SJeff Chen 	if (!(user_he_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT)) {
44473b01e57SJeff Chen 		nxpwifi_dbg(priv->adapter, MSG,
44573b01e57SJeff Chen 			    "USER HE_MAC_CAP don't support TWT\n");
44673b01e57SJeff Chen 		return false;
44773b01e57SJeff Chen 	}
44873b01e57SJeff Chen 
44973b01e57SJeff Chen 	return true;
45073b01e57SJeff Chen }
45173b01e57SJeff Chen 
nxpwifi_is_sta_11ax_twt_req_supported(struct nxpwifi_private * priv)45273b01e57SJeff Chen u8 nxpwifi_is_sta_11ax_twt_req_supported(struct nxpwifi_private *priv)
45373b01e57SJeff Chen {
45473b01e57SJeff Chen 	struct nxpwifi_ie_types_he_cap *user_he_cap;
45573b01e57SJeff Chen 	u8 ret = 0;
45673b01e57SJeff Chen 
45773b01e57SJeff Chen 	if (ISSUPP_11AXENABLED(priv->adapter->fw_cap_ext) &&
45873b01e57SJeff Chen 	    (priv->config_bands & BAND_GAX || priv->config_bands & BAND_AAX)) {
45973b01e57SJeff Chen 		if (priv->config_bands & BAND_AAX)
46073b01e57SJeff Chen 			user_he_cap = (struct nxpwifi_ie_types_he_cap *)priv->user_he_cap;
46173b01e57SJeff Chen 		else
46273b01e57SJeff Chen 			user_he_cap = (struct nxpwifi_ie_types_he_cap *)priv->user_2g_he_cap;
46373b01e57SJeff Chen 		ret = user_he_cap->he_mac_cap[0] & HE_MAC_CAP_TWT_REQ_SUPPORT;
46473b01e57SJeff Chen 	}
46573b01e57SJeff Chen 
46673b01e57SJeff Chen 	return ret;
46773b01e57SJeff Chen }
46873b01e57SJeff Chen 
nxpwifi_cmd_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * cmd,u16 cmd_action,struct nxpwifi_twt_cfg * twt_cfg)46973b01e57SJeff Chen int nxpwifi_cmd_twt_cfg(struct nxpwifi_private *priv,
47073b01e57SJeff Chen 			struct host_cmd_ds_command *cmd, u16 cmd_action,
47173b01e57SJeff Chen 			struct nxpwifi_twt_cfg *twt_cfg)
47273b01e57SJeff Chen {
47373b01e57SJeff Chen 	struct nxpwifi_adapter *adapter = priv->adapter;
47473b01e57SJeff Chen 	struct host_cmd_twt_cfg *twt_cfg_cmd = &cmd->params.twt_cfg;
47573b01e57SJeff Chen 	struct nxpwifi_twt_setup *twt_setup;
47673b01e57SJeff Chen 	struct nxpwifi_twt_teardown *twt_teardown;
47773b01e57SJeff Chen 	struct nxpwifi_twt_report *twt_report;
47873b01e57SJeff Chen 	struct nxpwifi_twt_information *twt_information;
47973b01e57SJeff Chen 	struct nxpwifi_btwt_ap_config *btwt_ap_config;
48073b01e57SJeff Chen 	u8 i;
48173b01e57SJeff Chen 	u16 cmd_size;
48273b01e57SJeff Chen 
48373b01e57SJeff Chen 	cmd->command = cpu_to_le16(HOST_CMD_TWT_CFG);
48473b01e57SJeff Chen 	cmd_size = sizeof(struct host_cmd_twt_cfg) + S_DS_GEN;
48573b01e57SJeff Chen 
48673b01e57SJeff Chen 	twt_cfg_cmd->action = cpu_to_le16(cmd_action);
48773b01e57SJeff Chen 	twt_cfg_cmd->sub_id = cpu_to_le16(twt_cfg->sub_id);
48873b01e57SJeff Chen 
48973b01e57SJeff Chen 	switch (twt_cfg->sub_id) {
49073b01e57SJeff Chen 	case NXPWIFI_11AX_TWT_SETUP_SUBID:
49173b01e57SJeff Chen 		twt_setup = (struct nxpwifi_twt_setup *)
49273b01e57SJeff Chen 			twt_cfg_cmd->val;
49373b01e57SJeff Chen 
49473b01e57SJeff Chen 		memset(twt_setup, 0x00, sizeof(struct nxpwifi_twt_setup));
49573b01e57SJeff Chen 		twt_setup->implicit = twt_cfg->param.twt_setup.implicit;
49673b01e57SJeff Chen 		twt_setup->announced = twt_cfg->param.twt_setup.announced;
49773b01e57SJeff Chen 		twt_setup->trigger_enabled = twt_cfg->param.twt_setup.trigger_enabled;
49873b01e57SJeff Chen 		twt_setup->twt_info_disabled = twt_cfg->param.twt_setup.twt_info_disabled;
49973b01e57SJeff Chen 		twt_setup->negotiation_type = twt_cfg->param.twt_setup.negotiation_type;
50073b01e57SJeff Chen 		twt_setup->twt_wakeup_duration =
50173b01e57SJeff Chen 			twt_cfg->param.twt_setup.twt_wakeup_duration;
50273b01e57SJeff Chen 		twt_setup->flow_identifier = twt_cfg->param.twt_setup.flow_identifier;
50373b01e57SJeff Chen 		twt_setup->hard_constraint = twt_cfg->param.twt_setup.hard_constraint;
50473b01e57SJeff Chen 		twt_setup->twt_exponent = twt_cfg->param.twt_setup.twt_exponent;
50573b01e57SJeff Chen 		twt_setup->twt_mantissa = twt_cfg->param.twt_setup.twt_mantissa;
50673b01e57SJeff Chen 		twt_setup->twt_request = twt_cfg->param.twt_setup.twt_request;
50773b01e57SJeff Chen 		twt_setup->bcn_miss_threshold = twt_cfg->param.twt_setup.bcn_miss_threshold;
50873b01e57SJeff Chen 		cmd_size += sizeof(struct nxpwifi_twt_setup);
50973b01e57SJeff Chen 		break;
51073b01e57SJeff Chen 	case NXPWIFI_11AX_TWT_TEARDOWN_SUBID:
51173b01e57SJeff Chen 		twt_teardown = (struct nxpwifi_twt_teardown *)
51273b01e57SJeff Chen 			twt_cfg_cmd->val;
51373b01e57SJeff Chen 		memset(twt_teardown, 0x00,
51473b01e57SJeff Chen 		       sizeof(struct nxpwifi_twt_teardown));
51573b01e57SJeff Chen 		twt_teardown->flow_identifier =
51673b01e57SJeff Chen 			twt_cfg->param.twt_teardown.flow_identifier;
51773b01e57SJeff Chen 		twt_teardown->negotiation_type =
51873b01e57SJeff Chen 			twt_cfg->param.twt_teardown.negotiation_type;
51973b01e57SJeff Chen 		twt_teardown->teardown_all_twt =
52073b01e57SJeff Chen 			twt_cfg->param.twt_teardown.teardown_all_twt;
52173b01e57SJeff Chen 		cmd_size += sizeof(struct nxpwifi_twt_teardown);
52273b01e57SJeff Chen 		break;
52373b01e57SJeff Chen 	case NXPWIFI_11AX_TWT_REPORT_SUBID:
52473b01e57SJeff Chen 		twt_report = (struct nxpwifi_twt_report *)
52573b01e57SJeff Chen 			twt_cfg_cmd->val;
52673b01e57SJeff Chen 		memset(twt_report, 0x00, sizeof(struct nxpwifi_twt_report));
52773b01e57SJeff Chen 		twt_report->type = twt_cfg->param.twt_report.type;
52873b01e57SJeff Chen 		cmd_size += sizeof(struct nxpwifi_twt_report);
52973b01e57SJeff Chen 		break;
53073b01e57SJeff Chen 	case NXPWIFI_11AX_TWT_INFORMATION_SUBID:
53173b01e57SJeff Chen 		twt_information = (struct nxpwifi_twt_information *)
53273b01e57SJeff Chen 			twt_cfg_cmd->val;
53373b01e57SJeff Chen 		memset(twt_information, 0x00,
53473b01e57SJeff Chen 		       sizeof(struct nxpwifi_twt_information));
53573b01e57SJeff Chen 		twt_information->flow_identifier =
53673b01e57SJeff Chen 			twt_cfg->param.twt_information.flow_identifier;
53773b01e57SJeff Chen 		twt_information->suspend_duration =
53873b01e57SJeff Chen 			twt_cfg->param.twt_information.suspend_duration;
53973b01e57SJeff Chen 		cmd_size += sizeof(struct nxpwifi_twt_information);
54073b01e57SJeff Chen 		break;
54173b01e57SJeff Chen 	case NXPWIFI_11AX_BTWT_AP_CONFIG_SUBID:
54273b01e57SJeff Chen 		btwt_ap_config = (struct nxpwifi_btwt_ap_config *)
54373b01e57SJeff Chen 				 twt_cfg_cmd->val;
54473b01e57SJeff Chen 		memset(btwt_ap_config, 0x00,
54573b01e57SJeff Chen 		       sizeof(struct nxpwifi_btwt_ap_config));
54673b01e57SJeff Chen 		btwt_ap_config->ap_bcast_bet_sta_wait =
54773b01e57SJeff Chen 			twt_cfg->param.btwt_ap_config.ap_bcast_bet_sta_wait;
54873b01e57SJeff Chen 		btwt_ap_config->ap_bcast_offset =
54973b01e57SJeff Chen 			twt_cfg->param.btwt_ap_config.ap_bcast_offset;
55073b01e57SJeff Chen 		btwt_ap_config->bcast_twtli =
55173b01e57SJeff Chen 			twt_cfg->param.btwt_ap_config.bcast_twtli;
55273b01e57SJeff Chen 		btwt_ap_config->count =
55373b01e57SJeff Chen 			twt_cfg->param.btwt_ap_config.count;
55473b01e57SJeff Chen 		for (i = 0; i < BTWT_AGREEMENT_MAX; i++) {
55573b01e57SJeff Chen 			btwt_ap_config->btwt_sets[i].btwt_id =
55673b01e57SJeff Chen 				twt_cfg->param.btwt_ap_config.btwt_sets[i].btwt_id;
55773b01e57SJeff Chen 			btwt_ap_config->btwt_sets[i].ap_bcast_mantissa =
55873b01e57SJeff Chen 				twt_cfg->param.btwt_ap_config.btwt_sets[i].ap_bcast_mantissa;
55973b01e57SJeff Chen 			btwt_ap_config->btwt_sets[i].ap_bcast_exponent =
56073b01e57SJeff Chen 				twt_cfg->param.btwt_ap_config.btwt_sets[i].ap_bcast_exponent;
56173b01e57SJeff Chen 			btwt_ap_config->btwt_sets[i].nominalwake =
56273b01e57SJeff Chen 				twt_cfg->param.btwt_ap_config.btwt_sets[i].nominalwake;
56373b01e57SJeff Chen 		}
56473b01e57SJeff Chen 
56573b01e57SJeff Chen 		cmd_size += sizeof(struct nxpwifi_btwt_ap_config);
56673b01e57SJeff Chen 		break;
56773b01e57SJeff Chen 	default:
56873b01e57SJeff Chen 		nxpwifi_dbg(adapter, ERROR,
56973b01e57SJeff Chen 			    "Unknown sub id: %d\n", twt_cfg->sub_id);
57073b01e57SJeff Chen 		return -EINVAL;
57173b01e57SJeff Chen 	}
57273b01e57SJeff Chen 
57373b01e57SJeff Chen 	cmd->size = cpu_to_le16(cmd_size);
57473b01e57SJeff Chen 
57573b01e57SJeff Chen 	return 0;
57673b01e57SJeff Chen }
57773b01e57SJeff Chen 
nxpwifi_ret_twt_cfg(struct nxpwifi_private * priv,struct host_cmd_ds_command * resp,struct nxpwifi_twt_cfg * twt_cfg)57873b01e57SJeff Chen int nxpwifi_ret_twt_cfg(struct nxpwifi_private *priv,
57973b01e57SJeff Chen 			struct host_cmd_ds_command *resp,
58073b01e57SJeff Chen 			struct nxpwifi_twt_cfg *twt_cfg)
58173b01e57SJeff Chen {
58273b01e57SJeff Chen 	struct host_cmd_twt_cfg *twt_cfg_cmd = &resp->params.twt_cfg;
58373b01e57SJeff Chen 	u16 action;
58473b01e57SJeff Chen 
58573b01e57SJeff Chen 	action = le16_to_cpu(twt_cfg_cmd->action);
58673b01e57SJeff Chen 	twt_cfg->sub_id = le16_to_cpu(twt_cfg_cmd->sub_id);
58773b01e57SJeff Chen 
58873b01e57SJeff Chen 	if (action == HOST_ACT_GEN_GET &&
58973b01e57SJeff Chen 	    twt_cfg->sub_id == NXPWIFI_11AX_TWT_REPORT_SUBID) {
59073b01e57SJeff Chen 		struct nxpwifi_twt_report *twt_report =
59173b01e57SJeff Chen 			(struct nxpwifi_twt_report *)twt_cfg_cmd->val;
59273b01e57SJeff Chen 
59373b01e57SJeff Chen 		memcpy(&twt_cfg->param.twt_report, twt_report, sizeof(struct nxpwifi_twt_report));
59473b01e57SJeff Chen 	}
59573b01e57SJeff Chen 
59673b01e57SJeff Chen 	return 0;
59773b01e57SJeff Chen }
598