2 * NXP Wireless LAN device driver: station command handling
4 * Copyright 2011-2020 NXP
6 * This software file (the "File") is distributed by NXP
7 * under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
30 module_param(drcs
, bool, 0644);
31 MODULE_PARM_DESC(drcs
, "multi-channel operation:1, single-channel operation:0");
33 static bool disable_auto_ds
;
34 module_param(disable_auto_ds
, bool, 0);
35 MODULE_PARM_DESC(disable_auto_ds
,
36 "deepsleep enabled=0(default), deepsleep disabled=1");
38 * This function prepares command to set/get RSSI information.
40 * Preparation includes -
41 * - Setting command ID, action and proper size
42 * - Setting data/beacon average factors
43 * - Resetting SNR/NF/RSSI values in private structure
44 * - Ensuring correct endian-ness
47 mwifiex_cmd_802_11_rssi_info(struct mwifiex_private
*priv
,
48 struct host_cmd_ds_command
*cmd
, u16 cmd_action
)
50 cmd
->command
= cpu_to_le16(HostCmd_CMD_RSSI_INFO
);
51 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info
) +
53 cmd
->params
.rssi_info
.action
= cpu_to_le16(cmd_action
);
54 cmd
->params
.rssi_info
.ndata
= cpu_to_le16(priv
->data_avg_factor
);
55 cmd
->params
.rssi_info
.nbcn
= cpu_to_le16(priv
->bcn_avg_factor
);
57 /* Reset SNR/NF/RSSI values in private structure */
58 priv
->data_rssi_last
= 0;
59 priv
->data_nf_last
= 0;
60 priv
->data_rssi_avg
= 0;
61 priv
->data_nf_avg
= 0;
62 priv
->bcn_rssi_last
= 0;
63 priv
->bcn_nf_last
= 0;
64 priv
->bcn_rssi_avg
= 0;
71 * This function prepares command to set MAC control.
73 * Preparation includes -
74 * - Setting command ID, action and proper size
75 * - Ensuring correct endian-ness
77 static int mwifiex_cmd_mac_control(struct mwifiex_private
*priv
,
78 struct host_cmd_ds_command
*cmd
,
79 u16 cmd_action
, u32
*action
)
81 struct host_cmd_ds_mac_control
*mac_ctrl
= &cmd
->params
.mac_ctrl
;
83 if (cmd_action
!= HostCmd_ACT_GEN_SET
) {
84 mwifiex_dbg(priv
->adapter
, ERROR
,
85 "mac_control: only support set cmd\n");
89 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_CONTROL
);
91 cpu_to_le16(sizeof(struct host_cmd_ds_mac_control
) + S_DS_GEN
);
92 mac_ctrl
->action
= cpu_to_le32(*action
);
98 * This function prepares command to set/get SNMP MIB.
100 * Preparation includes -
101 * - Setting command ID, action and proper size
102 * - Setting SNMP MIB OID number and value
104 * - Ensuring correct endian-ness
106 * The following SNMP MIB OIDs are supported -
107 * - FRAG_THRESH_I : Fragmentation threshold
108 * - RTS_THRESH_I : RTS threshold
109 * - SHORT_RETRY_LIM_I : Short retry limit
110 * - DOT11D_I : 11d support
112 static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private
*priv
,
113 struct host_cmd_ds_command
*cmd
,
114 u16 cmd_action
, u32 cmd_oid
,
117 struct host_cmd_ds_802_11_snmp_mib
*snmp_mib
= &cmd
->params
.smib
;
119 mwifiex_dbg(priv
->adapter
, CMD
,
120 "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid
);
121 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB
);
122 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib
)
125 snmp_mib
->oid
= cpu_to_le16((u16
)cmd_oid
);
126 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
127 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_GET
);
128 snmp_mib
->buf_size
= cpu_to_le16(MAX_SNMP_BUF_SIZE
);
129 le16_unaligned_add_cpu(&cmd
->size
, MAX_SNMP_BUF_SIZE
);
130 } else if (cmd_action
== HostCmd_ACT_GEN_SET
) {
131 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
132 snmp_mib
->buf_size
= cpu_to_le16(sizeof(u16
));
133 put_unaligned_le16(*ul_temp
, snmp_mib
->value
);
134 le16_unaligned_add_cpu(&cmd
->size
, sizeof(u16
));
137 mwifiex_dbg(priv
->adapter
, CMD
,
138 "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t"
139 "OIDSize=0x%x, Value=0x%x\n",
140 cmd_action
, cmd_oid
, le16_to_cpu(snmp_mib
->buf_size
),
141 get_unaligned_le16(snmp_mib
->value
));
146 * This function prepares command to get log.
148 * Preparation includes -
149 * - Setting command ID and proper size
150 * - Ensuring correct endian-ness
153 mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command
*cmd
)
155 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_GET_LOG
);
156 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log
) +
162 * This function prepares command to set/get Tx data rate configuration.
164 * Preparation includes -
165 * - Setting command ID, action and proper size
166 * - Setting configuration index, rate scope and rate drop pattern
167 * parameters (as required)
168 * - Ensuring correct endian-ness
170 static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private
*priv
,
171 struct host_cmd_ds_command
*cmd
,
172 u16 cmd_action
, u16
*pbitmap_rates
)
174 struct host_cmd_ds_tx_rate_cfg
*rate_cfg
= &cmd
->params
.tx_rate_cfg
;
175 struct mwifiex_rate_scope
*rate_scope
;
176 struct mwifiex_rate_drop_pattern
*rate_drop
;
179 cmd
->command
= cpu_to_le16(HostCmd_CMD_TX_RATE_CFG
);
181 rate_cfg
->action
= cpu_to_le16(cmd_action
);
182 rate_cfg
->cfg_index
= 0;
184 rate_scope
= (struct mwifiex_rate_scope
*) ((u8
*) rate_cfg
+
185 sizeof(struct host_cmd_ds_tx_rate_cfg
));
186 rate_scope
->type
= cpu_to_le16(TLV_TYPE_RATE_SCOPE
);
187 rate_scope
->length
= cpu_to_le16
188 (sizeof(*rate_scope
) - sizeof(struct mwifiex_ie_types_header
));
189 if (pbitmap_rates
!= NULL
) {
190 rate_scope
->hr_dsss_rate_bitmap
= cpu_to_le16(pbitmap_rates
[0]);
191 rate_scope
->ofdm_rate_bitmap
= cpu_to_le16(pbitmap_rates
[1]);
192 for (i
= 0; i
< ARRAY_SIZE(rate_scope
->ht_mcs_rate_bitmap
); i
++)
193 rate_scope
->ht_mcs_rate_bitmap
[i
] =
194 cpu_to_le16(pbitmap_rates
[2 + i
]);
195 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
197 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
199 rate_scope
->vht_mcs_rate_bitmap
[i
] =
200 cpu_to_le16(pbitmap_rates
[10 + i
]);
203 rate_scope
->hr_dsss_rate_bitmap
=
204 cpu_to_le16(priv
->bitmap_rates
[0]);
205 rate_scope
->ofdm_rate_bitmap
=
206 cpu_to_le16(priv
->bitmap_rates
[1]);
207 for (i
= 0; i
< ARRAY_SIZE(rate_scope
->ht_mcs_rate_bitmap
); i
++)
208 rate_scope
->ht_mcs_rate_bitmap
[i
] =
209 cpu_to_le16(priv
->bitmap_rates
[2 + i
]);
210 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
212 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
214 rate_scope
->vht_mcs_rate_bitmap
[i
] =
215 cpu_to_le16(priv
->bitmap_rates
[10 + i
]);
219 rate_drop
= (struct mwifiex_rate_drop_pattern
*) ((u8
*) rate_scope
+
220 sizeof(struct mwifiex_rate_scope
));
221 rate_drop
->type
= cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL
);
222 rate_drop
->length
= cpu_to_le16(sizeof(rate_drop
->rate_drop_mode
));
223 rate_drop
->rate_drop_mode
= 0;
226 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_tx_rate_cfg
) +
227 sizeof(struct mwifiex_rate_scope
) +
228 sizeof(struct mwifiex_rate_drop_pattern
));
234 * This function prepares command to set/get Tx power configuration.
236 * Preparation includes -
237 * - Setting command ID, action and proper size
238 * - Setting Tx power mode, power group TLV
240 * - Ensuring correct endian-ness
242 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command
*cmd
,
244 struct host_cmd_ds_txpwr_cfg
*txp
)
246 struct mwifiex_types_power_group
*pg_tlv
;
247 struct host_cmd_ds_txpwr_cfg
*cmd_txp_cfg
= &cmd
->params
.txp_cfg
;
249 cmd
->command
= cpu_to_le16(HostCmd_CMD_TXPWR_CFG
);
251 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_txpwr_cfg
));
252 switch (cmd_action
) {
253 case HostCmd_ACT_GEN_SET
:
255 pg_tlv
= (struct mwifiex_types_power_group
256 *) ((unsigned long) txp
+
257 sizeof(struct host_cmd_ds_txpwr_cfg
));
258 memmove(cmd_txp_cfg
, txp
,
259 sizeof(struct host_cmd_ds_txpwr_cfg
) +
260 sizeof(struct mwifiex_types_power_group
) +
261 le16_to_cpu(pg_tlv
->length
));
263 pg_tlv
= (struct mwifiex_types_power_group
*) ((u8
*)
265 sizeof(struct host_cmd_ds_txpwr_cfg
));
266 cmd
->size
= cpu_to_le16(le16_to_cpu(cmd
->size
) +
267 sizeof(struct mwifiex_types_power_group
) +
268 le16_to_cpu(pg_tlv
->length
));
270 memmove(cmd_txp_cfg
, txp
, sizeof(*txp
));
272 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
274 case HostCmd_ACT_GEN_GET
:
275 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
283 * This function prepares command to get RF Tx power.
285 static int mwifiex_cmd_rf_tx_power(struct mwifiex_private
*priv
,
286 struct host_cmd_ds_command
*cmd
,
287 u16 cmd_action
, void *data_buf
)
289 struct host_cmd_ds_rf_tx_pwr
*txp
= &cmd
->params
.txp
;
291 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr
)
293 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_TX_PWR
);
294 txp
->action
= cpu_to_le16(cmd_action
);
300 * This function prepares command to set rf antenna.
302 static int mwifiex_cmd_rf_antenna(struct mwifiex_private
*priv
,
303 struct host_cmd_ds_command
*cmd
,
305 struct mwifiex_ds_ant_cfg
*ant_cfg
)
307 struct host_cmd_ds_rf_ant_mimo
*ant_mimo
= &cmd
->params
.ant_mimo
;
308 struct host_cmd_ds_rf_ant_siso
*ant_siso
= &cmd
->params
.ant_siso
;
310 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_ANTENNA
);
312 switch (cmd_action
) {
313 case HostCmd_ACT_GEN_SET
:
314 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
315 cmd
->size
= cpu_to_le16(sizeof(struct
316 host_cmd_ds_rf_ant_mimo
)
318 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_SET_TX
);
319 ant_mimo
->tx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->
321 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_SET_RX
);
322 ant_mimo
->rx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->
325 cmd
->size
= cpu_to_le16(sizeof(struct
326 host_cmd_ds_rf_ant_siso
) +
328 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_SET_BOTH
);
329 ant_siso
->ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
332 case HostCmd_ACT_GEN_GET
:
333 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
334 cmd
->size
= cpu_to_le16(sizeof(struct
335 host_cmd_ds_rf_ant_mimo
) +
337 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_GET_TX
);
338 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_GET_RX
);
340 cmd
->size
= cpu_to_le16(sizeof(struct
341 host_cmd_ds_rf_ant_siso
) +
343 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_GET_BOTH
);
351 * This function prepares command to set Host Sleep configuration.
353 * Preparation includes -
354 * - Setting command ID and proper size
355 * - Setting Host Sleep action, conditions, ARP filters
357 * - Ensuring correct endian-ness
360 mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private
*priv
,
361 struct host_cmd_ds_command
*cmd
,
363 struct mwifiex_hs_config_param
*hscfg_param
)
365 struct mwifiex_adapter
*adapter
= priv
->adapter
;
366 struct host_cmd_ds_802_11_hs_cfg_enh
*hs_cfg
= &cmd
->params
.opt_hs_cfg
;
367 u8
*tlv
= (u8
*)hs_cfg
+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
);
368 struct mwifiex_ps_param_in_hs
*psparam_tlv
= NULL
;
369 bool hs_activate
= false;
373 /* New Activate command */
375 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH
);
378 (hscfg_param
->conditions
!= cpu_to_le32(HS_CFG_CANCEL
)) &&
379 ((adapter
->arp_filter_size
> 0) &&
380 (adapter
->arp_filter_size
<= ARP_FILTER_MAX_BUF_SIZE
))) {
381 mwifiex_dbg(adapter
, CMD
,
382 "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
383 adapter
->arp_filter_size
);
384 memcpy(((u8
*) hs_cfg
) +
385 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
),
386 adapter
->arp_filter
, adapter
->arp_filter_size
);
387 size
= adapter
->arp_filter_size
+
388 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
)
391 + sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
)
392 + adapter
->arp_filter_size
;
394 size
= S_DS_GEN
+ sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
);
397 hs_cfg
->action
= cpu_to_le16(HS_ACTIVATE
);
398 hs_cfg
->params
.hs_activate
.resp_ctrl
= cpu_to_le16(RESP_NEEDED
);
400 hs_cfg
->action
= cpu_to_le16(HS_CONFIGURE
);
401 hs_cfg
->params
.hs_config
.conditions
= hscfg_param
->conditions
;
402 hs_cfg
->params
.hs_config
.gpio
= hscfg_param
->gpio
;
403 hs_cfg
->params
.hs_config
.gap
= hscfg_param
->gap
;
405 size
+= sizeof(struct mwifiex_ps_param_in_hs
);
406 psparam_tlv
= (struct mwifiex_ps_param_in_hs
*)tlv
;
407 psparam_tlv
->header
.type
=
408 cpu_to_le16(TLV_TYPE_PS_PARAMS_IN_HS
);
409 psparam_tlv
->header
.len
=
410 cpu_to_le16(sizeof(struct mwifiex_ps_param_in_hs
)
411 - sizeof(struct mwifiex_ie_types_header
));
412 psparam_tlv
->hs_wake_int
= cpu_to_le32(HS_DEF_WAKE_INTERVAL
);
413 psparam_tlv
->hs_inact_timeout
=
414 cpu_to_le32(HS_DEF_INACTIVITY_TIMEOUT
);
416 mwifiex_dbg(adapter
, CMD
,
417 "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
418 hs_cfg
->params
.hs_config
.conditions
,
419 hs_cfg
->params
.hs_config
.gpio
,
420 hs_cfg
->params
.hs_config
.gap
);
422 cmd
->size
= cpu_to_le16(size
);
428 * This function prepares command to set/get MAC address.
430 * Preparation includes -
431 * - Setting command ID, action and proper size
432 * - Setting MAC address (for SET only)
433 * - Ensuring correct endian-ness
435 static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private
*priv
,
436 struct host_cmd_ds_command
*cmd
,
439 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS
);
440 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address
) +
444 cmd
->params
.mac_addr
.action
= cpu_to_le16(cmd_action
);
446 if (cmd_action
== HostCmd_ACT_GEN_SET
)
447 memcpy(cmd
->params
.mac_addr
.mac_addr
, priv
->curr_addr
,
453 * This function prepares command to set MAC multicast address.
455 * Preparation includes -
456 * - Setting command ID, action and proper size
457 * - Setting MAC multicast address
458 * - Ensuring correct endian-ness
461 mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command
*cmd
,
463 struct mwifiex_multicast_list
*mcast_list
)
465 struct host_cmd_ds_mac_multicast_adr
*mcast_addr
= &cmd
->params
.mc_addr
;
467 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr
) +
469 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR
);
471 mcast_addr
->action
= cpu_to_le16(cmd_action
);
472 mcast_addr
->num_of_adrs
=
473 cpu_to_le16((u16
) mcast_list
->num_multicast_addr
);
474 memcpy(mcast_addr
->mac_list
, mcast_list
->mac_list
,
475 mcast_list
->num_multicast_addr
* ETH_ALEN
);
481 * This function prepares command to deauthenticate.
483 * Preparation includes -
484 * - Setting command ID and proper size
485 * - Setting AP MAC address and reason code
486 * - Ensuring correct endian-ness
488 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private
*priv
,
489 struct host_cmd_ds_command
*cmd
,
492 struct host_cmd_ds_802_11_deauthenticate
*deauth
= &cmd
->params
.deauth
;
494 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE
);
495 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate
)
498 /* Set AP MAC address */
499 memcpy(deauth
->mac_addr
, mac
, ETH_ALEN
);
501 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: Deauth: %pM\n", deauth
->mac_addr
);
503 deauth
->reason_code
= cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING
);
509 * This function prepares command to stop Ad-Hoc network.
511 * Preparation includes -
512 * - Setting command ID and proper size
513 * - Ensuring correct endian-ness
515 static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command
*cmd
)
517 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP
);
518 cmd
->size
= cpu_to_le16(S_DS_GEN
);
523 * This function sets WEP key(s) to key parameter TLV(s).
525 * Multi-key parameter TLVs are supported, so we can send multiple
526 * WEP keys in a single buffer.
529 mwifiex_set_keyparamset_wep(struct mwifiex_private
*priv
,
530 struct mwifiex_ie_type_key_param_set
*key_param_set
,
533 int cur_key_param_len
;
536 /* Multi-key_param_set TLV is supported */
537 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
538 if ((priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP40
) ||
539 (priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP104
)) {
540 key_param_set
->type
=
541 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
542 /* Key_param_set WEP fixed length */
543 #define KEYPARAMSET_WEP_FIXED_LEN 8
544 key_param_set
->length
= cpu_to_le16((u16
)
547 KEYPARAMSET_WEP_FIXED_LEN
));
548 key_param_set
->key_type_id
=
549 cpu_to_le16(KEY_TYPE_ID_WEP
);
550 key_param_set
->key_info
=
551 cpu_to_le16(KEY_ENABLED
| KEY_UNICAST
|
553 key_param_set
->key_len
=
554 cpu_to_le16(priv
->wep_key
[i
].key_length
);
555 /* Set WEP key index */
556 key_param_set
->key
[0] = i
;
557 /* Set default Tx key flag */
560 wep_key_curr_index
& HostCmd_WEP_KEY_INDEX_MASK
))
561 key_param_set
->key
[1] = 1;
563 key_param_set
->key
[1] = 0;
564 memmove(&key_param_set
->key
[2],
565 priv
->wep_key
[i
].key_material
,
566 priv
->wep_key
[i
].key_length
);
568 cur_key_param_len
= priv
->wep_key
[i
].key_length
+
569 KEYPARAMSET_WEP_FIXED_LEN
+
570 sizeof(struct mwifiex_ie_types_header
);
571 *key_param_len
+= (u16
) cur_key_param_len
;
573 (struct mwifiex_ie_type_key_param_set
*)
574 ((u8
*)key_param_set
+
576 } else if (!priv
->wep_key
[i
].key_length
) {
579 mwifiex_dbg(priv
->adapter
, ERROR
,
580 "key%d Length = %d is incorrect\n",
581 (i
+ 1), priv
->wep_key
[i
].key_length
);
589 /* This function populates key material v2 command
590 * to set network key for AES & CMAC AES.
592 static int mwifiex_set_aes_key_v2(struct mwifiex_private
*priv
,
593 struct host_cmd_ds_command
*cmd
,
594 struct mwifiex_ds_encrypt_key
*enc_key
,
595 struct host_cmd_ds_802_11_key_material_v2
*km
)
597 struct mwifiex_adapter
*adapter
= priv
->adapter
;
598 u16 size
, len
= KEY_PARAMS_FIXED_LEN
;
600 if (enc_key
->is_igtk_key
) {
601 mwifiex_dbg(adapter
, INFO
,
602 "%s: Set CMAC AES Key\n", __func__
);
603 if (enc_key
->is_rx_seq_valid
)
604 memcpy(km
->key_param_set
.key_params
.cmac_aes
.ipn
,
605 enc_key
->pn
, enc_key
->pn_len
);
606 km
->key_param_set
.key_info
&= cpu_to_le16(~KEY_MCAST
);
607 km
->key_param_set
.key_info
|= cpu_to_le16(KEY_IGTK
);
608 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES_CMAC
;
609 km
->key_param_set
.key_params
.cmac_aes
.key_len
=
610 cpu_to_le16(enc_key
->key_len
);
611 memcpy(km
->key_param_set
.key_params
.cmac_aes
.key
,
612 enc_key
->key_material
, enc_key
->key_len
);
613 len
+= sizeof(struct mwifiex_cmac_aes_param
);
614 } else if (enc_key
->is_igtk_def_key
) {
615 mwifiex_dbg(adapter
, INFO
,
616 "%s: Set CMAC default Key index\n", __func__
);
617 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES_CMAC_DEF
;
618 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
620 mwifiex_dbg(adapter
, INFO
,
621 "%s: Set AES Key\n", __func__
);
622 if (enc_key
->is_rx_seq_valid
)
623 memcpy(km
->key_param_set
.key_params
.aes
.pn
,
624 enc_key
->pn
, enc_key
->pn_len
);
625 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES
;
626 km
->key_param_set
.key_params
.aes
.key_len
=
627 cpu_to_le16(enc_key
->key_len
);
628 memcpy(km
->key_param_set
.key_params
.aes
.key
,
629 enc_key
->key_material
, enc_key
->key_len
);
630 len
+= sizeof(struct mwifiex_aes_param
);
633 km
->key_param_set
.len
= cpu_to_le16(len
);
634 size
= len
+ sizeof(struct mwifiex_ie_types_header
) +
635 sizeof(km
->action
) + S_DS_GEN
;
636 cmd
->size
= cpu_to_le16(size
);
641 /* This function prepares command to set/get/reset network key(s).
642 * This function prepares key material command for V2 format.
643 * Preparation includes -
644 * - Setting command ID, action and proper size
645 * - Setting WEP keys, WAPI keys or WPA keys along with required
646 * encryption (TKIP, AES) (as required)
647 * - Ensuring correct endian-ness
650 mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private
*priv
,
651 struct host_cmd_ds_command
*cmd
,
652 u16 cmd_action
, u32 cmd_oid
,
653 struct mwifiex_ds_encrypt_key
*enc_key
)
655 struct mwifiex_adapter
*adapter
= priv
->adapter
;
656 u8
*mac
= enc_key
->mac_addr
;
657 u16 key_info
, len
= KEY_PARAMS_FIXED_LEN
;
658 struct host_cmd_ds_802_11_key_material_v2
*km
=
659 &cmd
->params
.key_material_v2
;
661 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
662 km
->action
= cpu_to_le16(cmd_action
);
664 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
665 mwifiex_dbg(adapter
, INFO
, "%s: Get key\n", __func__
);
666 km
->key_param_set
.key_idx
=
667 enc_key
->key_index
& KEY_INDEX_MASK
;
668 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
669 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
670 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
672 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
673 key_info
= KEY_UNICAST
;
675 key_info
= KEY_MCAST
;
677 if (enc_key
->is_igtk_key
)
678 key_info
|= KEY_IGTK
;
680 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
682 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
683 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
688 memset(&km
->key_param_set
, 0,
689 sizeof(struct mwifiex_ie_type_key_param_set_v2
));
691 if (enc_key
->key_disable
) {
692 mwifiex_dbg(adapter
, INFO
, "%s: Remove key\n", __func__
);
693 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_REMOVE
);
694 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
695 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
696 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
697 key_info
= KEY_MCAST
| KEY_UNICAST
;
698 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
699 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
700 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
701 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
706 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
707 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
708 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
709 key_info
= KEY_ENABLED
;
710 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
712 if (enc_key
->key_len
<= WLAN_KEY_LEN_WEP104
) {
713 mwifiex_dbg(adapter
, INFO
, "%s: Set WEP Key\n", __func__
);
714 len
+= sizeof(struct mwifiex_wep_param
);
715 km
->key_param_set
.len
= cpu_to_le16(len
);
716 km
->key_param_set
.key_type
= KEY_TYPE_ID_WEP
;
718 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
719 key_info
|= KEY_MCAST
| KEY_UNICAST
;
721 if (enc_key
->is_current_wep_key
) {
722 key_info
|= KEY_MCAST
| KEY_UNICAST
;
723 if (km
->key_param_set
.key_idx
==
724 (priv
->wep_key_curr_index
& KEY_INDEX_MASK
))
725 key_info
|= KEY_DEFAULT
;
727 if (is_broadcast_ether_addr(mac
))
728 key_info
|= KEY_MCAST
;
730 key_info
|= KEY_UNICAST
| KEY_DEFAULT
;
733 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
735 km
->key_param_set
.key_params
.wep
.key_len
=
736 cpu_to_le16(enc_key
->key_len
);
737 memcpy(km
->key_param_set
.key_params
.wep
.key
,
738 enc_key
->key_material
, enc_key
->key_len
);
740 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
741 len
+ sizeof(km
->action
) + S_DS_GEN
);
745 if (is_broadcast_ether_addr(mac
))
746 key_info
|= KEY_MCAST
| KEY_RX_KEY
;
748 key_info
|= KEY_UNICAST
| KEY_TX_KEY
| KEY_RX_KEY
;
750 if (enc_key
->is_wapi_key
) {
751 mwifiex_dbg(adapter
, INFO
, "%s: Set WAPI Key\n", __func__
);
752 km
->key_param_set
.key_type
= KEY_TYPE_ID_WAPI
;
753 memcpy(km
->key_param_set
.key_params
.wapi
.pn
, enc_key
->pn
,
755 km
->key_param_set
.key_params
.wapi
.key_len
=
756 cpu_to_le16(enc_key
->key_len
);
757 memcpy(km
->key_param_set
.key_params
.wapi
.key
,
758 enc_key
->key_material
, enc_key
->key_len
);
759 if (is_broadcast_ether_addr(mac
))
760 priv
->sec_info
.wapi_key_on
= true;
762 if (!priv
->sec_info
.wapi_key_on
)
763 key_info
|= KEY_DEFAULT
;
764 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
766 len
+= sizeof(struct mwifiex_wapi_param
);
767 km
->key_param_set
.len
= cpu_to_le16(len
);
768 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
769 len
+ sizeof(km
->action
) + S_DS_GEN
);
773 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
) {
774 key_info
|= KEY_DEFAULT
;
775 /* Enable unicast bit for WPA-NONE/ADHOC_AES */
776 if (!priv
->sec_info
.wpa2_enabled
&&
777 !is_broadcast_ether_addr(mac
))
778 key_info
|= KEY_UNICAST
;
780 /* Enable default key for WPA/WPA2 */
781 if (!priv
->wpa_is_gtk_set
)
782 key_info
|= KEY_DEFAULT
;
785 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
787 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
)
788 return mwifiex_set_aes_key_v2(priv
, cmd
, enc_key
, km
);
790 if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
791 mwifiex_dbg(adapter
, INFO
,
792 "%s: Set TKIP Key\n", __func__
);
793 if (enc_key
->is_rx_seq_valid
)
794 memcpy(km
->key_param_set
.key_params
.tkip
.pn
,
795 enc_key
->pn
, enc_key
->pn_len
);
796 km
->key_param_set
.key_type
= KEY_TYPE_ID_TKIP
;
797 km
->key_param_set
.key_params
.tkip
.key_len
=
798 cpu_to_le16(enc_key
->key_len
);
799 memcpy(km
->key_param_set
.key_params
.tkip
.key
,
800 enc_key
->key_material
, enc_key
->key_len
);
802 len
+= sizeof(struct mwifiex_tkip_param
);
803 km
->key_param_set
.len
= cpu_to_le16(len
);
804 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
805 len
+ sizeof(km
->action
) + S_DS_GEN
);
812 * This function prepares command to set/get/reset network key(s).
813 * This function prepares key material command for V1 format.
815 * Preparation includes -
816 * - Setting command ID, action and proper size
817 * - Setting WEP keys, WAPI keys or WPA keys along with required
818 * encryption (TKIP, AES) (as required)
819 * - Ensuring correct endian-ness
822 mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private
*priv
,
823 struct host_cmd_ds_command
*cmd
,
824 u16 cmd_action
, u32 cmd_oid
,
825 struct mwifiex_ds_encrypt_key
*enc_key
)
827 struct host_cmd_ds_802_11_key_material
*key_material
=
828 &cmd
->params
.key_material
;
829 struct host_cmd_tlv_mac_addr
*tlv_mac
;
830 u16 key_param_len
= 0, cmd_size
;
833 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
834 key_material
->action
= cpu_to_le16(cmd_action
);
836 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
838 cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
);
843 memset(&key_material
->key_param_set
, 0,
845 sizeof(struct mwifiex_ie_type_key_param_set
)));
846 ret
= mwifiex_set_keyparamset_wep(priv
,
847 &key_material
->key_param_set
,
849 cmd
->size
= cpu_to_le16(key_param_len
+
850 sizeof(key_material
->action
) + S_DS_GEN
);
853 memset(&key_material
->key_param_set
, 0,
854 sizeof(struct mwifiex_ie_type_key_param_set
));
855 if (enc_key
->is_wapi_key
) {
856 struct mwifiex_ie_type_key_param_set
*set
;
858 mwifiex_dbg(priv
->adapter
, INFO
, "info: Set WAPI Key\n");
859 set
= &key_material
->key_param_set
;
860 set
->key_type_id
= cpu_to_le16(KEY_TYPE_ID_WAPI
);
861 if (cmd_oid
== KEY_INFO_ENABLED
)
862 set
->key_info
= cpu_to_le16(KEY_ENABLED
);
864 set
->key_info
= cpu_to_le16(!KEY_ENABLED
);
866 set
->key
[0] = enc_key
->key_index
;
867 if (!priv
->sec_info
.wapi_key_on
)
870 /* set 0 when re-key */
873 if (!is_broadcast_ether_addr(enc_key
->mac_addr
)) {
874 /* WAPI pairwise key: unicast */
875 set
->key_info
|= cpu_to_le16(KEY_UNICAST
);
876 } else { /* WAPI group key: multicast */
877 set
->key_info
|= cpu_to_le16(KEY_MCAST
);
878 priv
->sec_info
.wapi_key_on
= true;
881 set
->type
= cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
882 set
->key_len
= cpu_to_le16(WAPI_KEY_LEN
);
883 memcpy(&set
->key
[2], enc_key
->key_material
, enc_key
->key_len
);
884 memcpy(&set
->key
[2 + enc_key
->key_len
], enc_key
->pn
, PN_LEN
);
885 set
->length
= cpu_to_le16(WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
);
887 key_param_len
= (WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
) +
888 sizeof(struct mwifiex_ie_types_header
);
889 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
)
890 + S_DS_GEN
+ key_param_len
);
893 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
) {
894 if (enc_key
->is_igtk_key
) {
895 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: CMAC_AES\n");
896 key_material
->key_param_set
.key_type_id
=
897 cpu_to_le16(KEY_TYPE_ID_AES_CMAC
);
898 if (cmd_oid
== KEY_INFO_ENABLED
)
899 key_material
->key_param_set
.key_info
=
900 cpu_to_le16(KEY_ENABLED
);
902 key_material
->key_param_set
.key_info
=
903 cpu_to_le16(!KEY_ENABLED
);
905 key_material
->key_param_set
.key_info
|=
906 cpu_to_le16(KEY_IGTK
);
908 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: WPA_AES\n");
909 key_material
->key_param_set
.key_type_id
=
910 cpu_to_le16(KEY_TYPE_ID_AES
);
911 if (cmd_oid
== KEY_INFO_ENABLED
)
912 key_material
->key_param_set
.key_info
=
913 cpu_to_le16(KEY_ENABLED
);
915 key_material
->key_param_set
.key_info
=
916 cpu_to_le16(!KEY_ENABLED
);
918 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
919 /* AES pairwise key: unicast */
920 key_material
->key_param_set
.key_info
|=
921 cpu_to_le16(KEY_UNICAST
);
922 else /* AES group key: multicast */
923 key_material
->key_param_set
.key_info
|=
924 cpu_to_le16(KEY_MCAST
);
926 } else if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
927 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: WPA_TKIP\n");
928 key_material
->key_param_set
.key_type_id
=
929 cpu_to_le16(KEY_TYPE_ID_TKIP
);
930 key_material
->key_param_set
.key_info
=
931 cpu_to_le16(KEY_ENABLED
);
933 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
934 /* TKIP pairwise key: unicast */
935 key_material
->key_param_set
.key_info
|=
936 cpu_to_le16(KEY_UNICAST
);
937 else /* TKIP group key: multicast */
938 key_material
->key_param_set
.key_info
|=
939 cpu_to_le16(KEY_MCAST
);
942 if (key_material
->key_param_set
.key_type_id
) {
943 key_material
->key_param_set
.type
=
944 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
945 key_material
->key_param_set
.key_len
=
946 cpu_to_le16((u16
) enc_key
->key_len
);
947 memcpy(key_material
->key_param_set
.key
, enc_key
->key_material
,
949 key_material
->key_param_set
.length
=
950 cpu_to_le16((u16
) enc_key
->key_len
+
951 KEYPARAMSET_FIXED_LEN
);
953 key_param_len
= (u16
)(enc_key
->key_len
+ KEYPARAMSET_FIXED_LEN
)
954 + sizeof(struct mwifiex_ie_types_header
);
956 if (le16_to_cpu(key_material
->key_param_set
.key_type_id
) ==
957 KEY_TYPE_ID_AES_CMAC
) {
958 struct mwifiex_cmac_param
*param
=
959 (void *)key_material
->key_param_set
.key
;
961 memcpy(param
->ipn
, enc_key
->pn
, IGTK_PN_LEN
);
962 memcpy(param
->key
, enc_key
->key_material
,
963 WLAN_KEY_LEN_AES_CMAC
);
965 key_param_len
= sizeof(struct mwifiex_cmac_param
);
966 key_material
->key_param_set
.key_len
=
967 cpu_to_le16(key_param_len
);
968 key_param_len
+= KEYPARAMSET_FIXED_LEN
;
969 key_material
->key_param_set
.length
=
970 cpu_to_le16(key_param_len
);
971 key_param_len
+= sizeof(struct mwifiex_ie_types_header
);
974 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
977 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
978 tlv_mac
= (void *)((u8
*)&key_material
->key_param_set
+
980 tlv_mac
->header
.type
=
981 cpu_to_le16(TLV_TYPE_STA_MAC_ADDR
);
982 tlv_mac
->header
.len
= cpu_to_le16(ETH_ALEN
);
983 memcpy(tlv_mac
->mac_addr
, enc_key
->mac_addr
, ETH_ALEN
);
984 cmd_size
= key_param_len
+ S_DS_GEN
+
985 sizeof(key_material
->action
) +
986 sizeof(struct host_cmd_tlv_mac_addr
);
988 cmd_size
= key_param_len
+ S_DS_GEN
+
989 sizeof(key_material
->action
);
991 cmd
->size
= cpu_to_le16(cmd_size
);
997 /* Wrapper function for setting network key depending upon FW KEY API version */
999 mwifiex_cmd_802_11_key_material(struct mwifiex_private
*priv
,
1000 struct host_cmd_ds_command
*cmd
,
1001 u16 cmd_action
, u32 cmd_oid
,
1002 struct mwifiex_ds_encrypt_key
*enc_key
)
1004 if (priv
->adapter
->key_api_major_ver
== KEY_API_VER_MAJOR_V2
)
1005 return mwifiex_cmd_802_11_key_material_v2(priv
, cmd
,
1006 cmd_action
, cmd_oid
,
1010 return mwifiex_cmd_802_11_key_material_v1(priv
, cmd
,
1011 cmd_action
, cmd_oid
,
1016 * This function prepares command to set/get 11d domain information.
1018 * Preparation includes -
1019 * - Setting command ID, action and proper size
1020 * - Setting domain information fields (for SET only)
1021 * - Ensuring correct endian-ness
1023 static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private
*priv
,
1024 struct host_cmd_ds_command
*cmd
,
1027 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1028 struct host_cmd_ds_802_11d_domain_info
*domain_info
=
1029 &cmd
->params
.domain_info
;
1030 struct mwifiex_ietypes_domain_param_set
*domain
=
1031 &domain_info
->domain
;
1032 u8 no_of_triplet
= adapter
->domain_reg
.no_of_triplet
;
1034 mwifiex_dbg(adapter
, INFO
,
1035 "info: 11D: no_of_triplet=0x%x\n", no_of_triplet
);
1037 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO
);
1038 domain_info
->action
= cpu_to_le16(cmd_action
);
1039 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
1040 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1044 /* Set domain info fields */
1045 domain
->header
.type
= cpu_to_le16(WLAN_EID_COUNTRY
);
1046 memcpy(domain
->country_code
, adapter
->domain_reg
.country_code
,
1047 sizeof(domain
->country_code
));
1049 domain
->header
.len
=
1050 cpu_to_le16((no_of_triplet
*
1051 sizeof(struct ieee80211_country_ie_triplet
))
1052 + sizeof(domain
->country_code
));
1054 if (no_of_triplet
) {
1055 memcpy(domain
->triplet
, adapter
->domain_reg
.triplet
,
1056 no_of_triplet
* sizeof(struct
1057 ieee80211_country_ie_triplet
));
1059 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) +
1060 le16_to_cpu(domain
->header
.len
) +
1061 sizeof(struct mwifiex_ie_types_header
)
1064 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1071 * This function prepares command to set/get IBSS coalescing status.
1073 * Preparation includes -
1074 * - Setting command ID, action and proper size
1075 * - Setting status to enable or disable (for SET only)
1076 * - Ensuring correct endian-ness
1078 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command
*cmd
,
1079 u16 cmd_action
, u16
*enable
)
1081 struct host_cmd_ds_802_11_ibss_status
*ibss_coal
=
1082 &(cmd
->params
.ibss_coalescing
);
1084 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
);
1085 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status
) +
1088 ibss_coal
->action
= cpu_to_le16(cmd_action
);
1090 switch (cmd_action
) {
1091 case HostCmd_ACT_GEN_SET
:
1093 ibss_coal
->enable
= cpu_to_le16(*enable
);
1095 ibss_coal
->enable
= 0;
1098 /* In other case.. Nothing to do */
1099 case HostCmd_ACT_GEN_GET
:
1107 /* This function prepares command buffer to get/set memory location value.
1110 mwifiex_cmd_mem_access(struct host_cmd_ds_command
*cmd
, u16 cmd_action
,
1113 struct mwifiex_ds_mem_rw
*mem_rw
= (void *)pdata_buf
;
1114 struct host_cmd_ds_mem_access
*mem_access
= (void *)&cmd
->params
.mem
;
1116 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEM_ACCESS
);
1117 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mem_access
) +
1120 mem_access
->action
= cpu_to_le16(cmd_action
);
1121 mem_access
->addr
= cpu_to_le32(mem_rw
->addr
);
1122 mem_access
->value
= cpu_to_le32(mem_rw
->value
);
1128 * This function prepares command to set/get register value.
1130 * Preparation includes -
1131 * - Setting command ID, action and proper size
1132 * - Setting register offset (for both GET and SET) and
1133 * register value (for SET only)
1134 * - Ensuring correct endian-ness
1136 * The following type of registers can be accessed with this function -
1144 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command
*cmd
,
1145 u16 cmd_action
, void *data_buf
)
1147 struct mwifiex_ds_reg_rw
*reg_rw
= data_buf
;
1149 switch (le16_to_cpu(cmd
->command
)) {
1150 case HostCmd_CMD_MAC_REG_ACCESS
:
1152 struct host_cmd_ds_mac_reg_access
*mac_reg
;
1154 cmd
->size
= cpu_to_le16(sizeof(*mac_reg
) + S_DS_GEN
);
1155 mac_reg
= &cmd
->params
.mac_reg
;
1156 mac_reg
->action
= cpu_to_le16(cmd_action
);
1157 mac_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1158 mac_reg
->value
= cpu_to_le32(reg_rw
->value
);
1161 case HostCmd_CMD_BBP_REG_ACCESS
:
1163 struct host_cmd_ds_bbp_reg_access
*bbp_reg
;
1165 cmd
->size
= cpu_to_le16(sizeof(*bbp_reg
) + S_DS_GEN
);
1166 bbp_reg
= &cmd
->params
.bbp_reg
;
1167 bbp_reg
->action
= cpu_to_le16(cmd_action
);
1168 bbp_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1169 bbp_reg
->value
= (u8
) reg_rw
->value
;
1172 case HostCmd_CMD_RF_REG_ACCESS
:
1174 struct host_cmd_ds_rf_reg_access
*rf_reg
;
1176 cmd
->size
= cpu_to_le16(sizeof(*rf_reg
) + S_DS_GEN
);
1177 rf_reg
= &cmd
->params
.rf_reg
;
1178 rf_reg
->action
= cpu_to_le16(cmd_action
);
1179 rf_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1180 rf_reg
->value
= (u8
) reg_rw
->value
;
1183 case HostCmd_CMD_PMIC_REG_ACCESS
:
1185 struct host_cmd_ds_pmic_reg_access
*pmic_reg
;
1187 cmd
->size
= cpu_to_le16(sizeof(*pmic_reg
) + S_DS_GEN
);
1188 pmic_reg
= &cmd
->params
.pmic_reg
;
1189 pmic_reg
->action
= cpu_to_le16(cmd_action
);
1190 pmic_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1191 pmic_reg
->value
= (u8
) reg_rw
->value
;
1194 case HostCmd_CMD_CAU_REG_ACCESS
:
1196 struct host_cmd_ds_rf_reg_access
*cau_reg
;
1198 cmd
->size
= cpu_to_le16(sizeof(*cau_reg
) + S_DS_GEN
);
1199 cau_reg
= &cmd
->params
.rf_reg
;
1200 cau_reg
->action
= cpu_to_le16(cmd_action
);
1201 cau_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1202 cau_reg
->value
= (u8
) reg_rw
->value
;
1205 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1207 struct mwifiex_ds_read_eeprom
*rd_eeprom
= data_buf
;
1208 struct host_cmd_ds_802_11_eeprom_access
*cmd_eeprom
=
1209 &cmd
->params
.eeprom
;
1211 cmd
->size
= cpu_to_le16(sizeof(*cmd_eeprom
) + S_DS_GEN
);
1212 cmd_eeprom
->action
= cpu_to_le16(cmd_action
);
1213 cmd_eeprom
->offset
= cpu_to_le16(rd_eeprom
->offset
);
1214 cmd_eeprom
->byte_count
= cpu_to_le16(rd_eeprom
->byte_count
);
1215 cmd_eeprom
->value
= 0;
1226 * This function prepares command to set PCI-Express
1227 * host buffer configuration
1229 * Preparation includes -
1230 * - Setting command ID, action and proper size
1231 * - Setting host buffer configuration
1232 * - Ensuring correct endian-ness
1235 mwifiex_cmd_pcie_host_spec(struct mwifiex_private
*priv
,
1236 struct host_cmd_ds_command
*cmd
, u16 action
)
1238 struct host_cmd_ds_pcie_details
*host_spec
=
1239 &cmd
->params
.pcie_host_spec
;
1240 struct pcie_service_card
*card
= priv
->adapter
->card
;
1242 cmd
->command
= cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS
);
1243 cmd
->size
= cpu_to_le16(sizeof(struct
1244 host_cmd_ds_pcie_details
) + S_DS_GEN
);
1247 memset(host_spec
, 0, sizeof(struct host_cmd_ds_pcie_details
));
1249 if (action
!= HostCmd_ACT_GEN_SET
)
1252 /* Send the ring base addresses and count to firmware */
1253 host_spec
->txbd_addr_lo
= cpu_to_le32((u32
)(card
->txbd_ring_pbase
));
1254 host_spec
->txbd_addr_hi
=
1255 cpu_to_le32((u32
)(((u64
)card
->txbd_ring_pbase
) >> 32));
1256 host_spec
->txbd_count
= cpu_to_le32(MWIFIEX_MAX_TXRX_BD
);
1257 host_spec
->rxbd_addr_lo
= cpu_to_le32((u32
)(card
->rxbd_ring_pbase
));
1258 host_spec
->rxbd_addr_hi
=
1259 cpu_to_le32((u32
)(((u64
)card
->rxbd_ring_pbase
) >> 32));
1260 host_spec
->rxbd_count
= cpu_to_le32(MWIFIEX_MAX_TXRX_BD
);
1261 host_spec
->evtbd_addr_lo
= cpu_to_le32((u32
)(card
->evtbd_ring_pbase
));
1262 host_spec
->evtbd_addr_hi
=
1263 cpu_to_le32((u32
)(((u64
)card
->evtbd_ring_pbase
) >> 32));
1264 host_spec
->evtbd_count
= cpu_to_le32(MWIFIEX_MAX_EVT_BD
);
1265 if (card
->sleep_cookie_vbase
) {
1266 host_spec
->sleep_cookie_addr_lo
=
1267 cpu_to_le32((u32
)(card
->sleep_cookie_pbase
));
1268 host_spec
->sleep_cookie_addr_hi
= cpu_to_le32((u32
)(((u64
)
1269 (card
->sleep_cookie_pbase
)) >> 32));
1270 mwifiex_dbg(priv
->adapter
, INFO
,
1271 "sleep_cook_lo phy addr: 0x%x\n",
1272 host_spec
->sleep_cookie_addr_lo
);
1279 * This function prepares command for event subscription, configuration
1280 * and query. Events can be subscribed or unsubscribed. Current subscribed
1281 * events can be queried. Also, current subscribed events are reported in
1282 * every FW response.
1285 mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private
*priv
,
1286 struct host_cmd_ds_command
*cmd
,
1287 struct mwifiex_ds_misc_subsc_evt
*subsc_evt_cfg
)
1289 struct host_cmd_ds_802_11_subsc_evt
*subsc_evt
= &cmd
->params
.subsc_evt
;
1290 struct mwifiex_ie_types_rssi_threshold
*rssi_tlv
;
1294 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT
);
1295 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt
) +
1298 subsc_evt
->action
= cpu_to_le16(subsc_evt_cfg
->action
);
1299 mwifiex_dbg(priv
->adapter
, CMD
,
1300 "cmd: action: %d\n", subsc_evt_cfg
->action
);
1302 /*For query requests, no configuration TLV structures are to be added.*/
1303 if (subsc_evt_cfg
->action
== HostCmd_ACT_GEN_GET
)
1306 subsc_evt
->events
= cpu_to_le16(subsc_evt_cfg
->events
);
1308 event_bitmap
= subsc_evt_cfg
->events
;
1309 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: event bitmap : %16x\n",
1312 if (((subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
) ||
1313 (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_SET
)) &&
1314 (event_bitmap
== 0)) {
1315 mwifiex_dbg(priv
->adapter
, ERROR
,
1316 "Error: No event specified\t"
1317 "for bitwise action type\n");
1322 * Append TLV structures for each of the specified events for
1323 * subscribing or re-configuring. This is not required for
1324 * bitwise unsubscribing request.
1326 if (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
)
1329 pos
= ((u8
*)subsc_evt
) +
1330 sizeof(struct host_cmd_ds_802_11_subsc_evt
);
1332 if (event_bitmap
& BITMASK_BCN_RSSI_LOW
) {
1333 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1335 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_LOW
);
1336 rssi_tlv
->header
.len
=
1337 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1338 sizeof(struct mwifiex_ie_types_header
));
1339 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
;
1340 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
;
1342 mwifiex_dbg(priv
->adapter
, EVENT
,
1343 "Cfg Beacon Low Rssi event,\t"
1344 "RSSI:-%d dBm, Freq:%d\n",
1345 subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
,
1346 subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
);
1348 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1349 le16_unaligned_add_cpu(&cmd
->size
,
1351 struct mwifiex_ie_types_rssi_threshold
));
1354 if (event_bitmap
& BITMASK_BCN_RSSI_HIGH
) {
1355 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1357 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_HIGH
);
1358 rssi_tlv
->header
.len
=
1359 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1360 sizeof(struct mwifiex_ie_types_header
));
1361 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
;
1362 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
;
1364 mwifiex_dbg(priv
->adapter
, EVENT
,
1365 "Cfg Beacon High Rssi event,\t"
1366 "RSSI:-%d dBm, Freq:%d\n",
1367 subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
,
1368 subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
);
1370 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1371 le16_unaligned_add_cpu(&cmd
->size
,
1373 struct mwifiex_ie_types_rssi_threshold
));
1380 mwifiex_cmd_append_rpn_expression(struct mwifiex_private
*priv
,
1381 struct mwifiex_mef_entry
*mef_entry
,
1384 struct mwifiex_mef_filter
*filter
= mef_entry
->filter
;
1386 u8
*stack_ptr
= *buffer
;
1388 for (i
= 0; i
< MWIFIEX_MEF_MAX_FILTERS
; i
++) {
1389 filter
= &mef_entry
->filter
[i
];
1390 if (!filter
->filt_type
)
1392 put_unaligned_le32((u32
)filter
->repeat
, stack_ptr
);
1394 *stack_ptr
= TYPE_DNUM
;
1397 byte_len
= filter
->byte_seq
[MWIFIEX_MEF_MAX_BYTESEQ
];
1398 memcpy(stack_ptr
, filter
->byte_seq
, byte_len
);
1399 stack_ptr
+= byte_len
;
1400 *stack_ptr
= byte_len
;
1402 *stack_ptr
= TYPE_BYTESEQ
;
1404 put_unaligned_le32((u32
)filter
->offset
, stack_ptr
);
1406 *stack_ptr
= TYPE_DNUM
;
1409 *stack_ptr
= filter
->filt_type
;
1412 if (filter
->filt_action
) {
1413 *stack_ptr
= filter
->filt_action
;
1417 if (stack_ptr
- *buffer
> STACK_NBYTES
)
1421 *buffer
= stack_ptr
;
1426 mwifiex_cmd_mef_cfg(struct mwifiex_private
*priv
,
1427 struct host_cmd_ds_command
*cmd
,
1428 struct mwifiex_ds_mef_cfg
*mef
)
1430 struct host_cmd_ds_mef_cfg
*mef_cfg
= &cmd
->params
.mef_cfg
;
1431 struct mwifiex_fw_mef_entry
*mef_entry
= NULL
;
1432 u8
*pos
= (u8
*)mef_cfg
;
1435 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEF_CFG
);
1437 mef_cfg
->criteria
= cpu_to_le32(mef
->criteria
);
1438 mef_cfg
->num_entries
= cpu_to_le16(mef
->num_entries
);
1439 pos
+= sizeof(*mef_cfg
);
1441 for (i
= 0; i
< mef
->num_entries
; i
++) {
1442 mef_entry
= (struct mwifiex_fw_mef_entry
*)pos
;
1443 mef_entry
->mode
= mef
->mef_entry
[i
].mode
;
1444 mef_entry
->action
= mef
->mef_entry
[i
].action
;
1445 pos
+= sizeof(*mef_cfg
->mef_entry
);
1447 if (mwifiex_cmd_append_rpn_expression(priv
,
1448 &mef
->mef_entry
[i
], &pos
))
1451 mef_entry
->exprsize
=
1452 cpu_to_le16(pos
- mef_entry
->expr
);
1454 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*)mef_cfg
) + S_DS_GEN
);
1459 /* This function parse cal data from ASCII to hex */
1460 static u32
mwifiex_parse_cal_cfg(u8
*src
, size_t len
, u8
*dst
)
1462 u8
*s
= src
, *d
= dst
;
1464 while (s
- src
< len
) {
1465 if (*s
&& (isspace(*s
) || *s
== '\t')) {
1470 *d
++ = simple_strtol(s
, NULL
, 16);
1480 int mwifiex_dnld_dt_cfgdata(struct mwifiex_private
*priv
,
1481 struct device_node
*node
, const char *prefix
)
1484 struct property
*prop
;
1485 size_t len
= strlen(prefix
);
1488 /* look for all matching property names */
1489 for_each_property_of_node(node
, prop
) {
1490 if (len
> strlen(prop
->name
) ||
1491 strncmp(prop
->name
, prefix
, len
))
1494 /* property header is 6 bytes, data must fit in cmd buffer */
1495 if (prop
->value
&& prop
->length
> 6 &&
1496 prop
->length
<= MWIFIEX_SIZE_OF_CMD_BUFFER
- S_DS_GEN
) {
1497 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
1498 HostCmd_ACT_GEN_SET
, 0,
1508 /* This function prepares command of set_cfg_data. */
1509 static int mwifiex_cmd_cfg_data(struct mwifiex_private
*priv
,
1510 struct host_cmd_ds_command
*cmd
, void *data_buf
)
1512 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1513 struct property
*prop
= data_buf
;
1515 u8
*data
= (u8
*)cmd
+ S_DS_GEN
;
1520 ret
= of_property_read_u8_array(adapter
->dt_node
, prop
->name
,
1524 mwifiex_dbg(adapter
, INFO
,
1525 "download cfg_data from device tree: %s\n",
1527 } else if (adapter
->cal_data
->data
&& adapter
->cal_data
->size
> 0) {
1528 len
= mwifiex_parse_cal_cfg((u8
*)adapter
->cal_data
->data
,
1529 adapter
->cal_data
->size
, data
);
1530 mwifiex_dbg(adapter
, INFO
,
1531 "download cfg_data from config file\n");
1536 cmd
->command
= cpu_to_le16(HostCmd_CMD_CFG_DATA
);
1537 cmd
->size
= cpu_to_le16(S_DS_GEN
+ len
);
1543 mwifiex_cmd_set_mc_policy(struct mwifiex_private
*priv
,
1544 struct host_cmd_ds_command
*cmd
,
1545 u16 cmd_action
, void *data_buf
)
1547 struct host_cmd_ds_multi_chan_policy
*mc_pol
= &cmd
->params
.mc_policy
;
1548 const u16
*drcs_info
= data_buf
;
1550 mc_pol
->action
= cpu_to_le16(cmd_action
);
1551 mc_pol
->policy
= cpu_to_le16(*drcs_info
);
1552 cmd
->command
= cpu_to_le16(HostCmd_CMD_MC_POLICY
);
1553 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy
) +
1558 static int mwifiex_cmd_robust_coex(struct mwifiex_private
*priv
,
1559 struct host_cmd_ds_command
*cmd
,
1560 u16 cmd_action
, bool *is_timeshare
)
1562 struct host_cmd_ds_robust_coex
*coex
= &cmd
->params
.coex
;
1563 struct mwifiex_ie_types_robust_coex
*coex_tlv
;
1565 cmd
->command
= cpu_to_le16(HostCmd_CMD_ROBUST_COEX
);
1566 cmd
->size
= cpu_to_le16(sizeof(*coex
) + sizeof(*coex_tlv
) + S_DS_GEN
);
1568 coex
->action
= cpu_to_le16(cmd_action
);
1569 coex_tlv
= (struct mwifiex_ie_types_robust_coex
*)
1570 ((u8
*)coex
+ sizeof(*coex
));
1571 coex_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_ROBUST_COEX
);
1572 coex_tlv
->header
.len
= cpu_to_le16(sizeof(coex_tlv
->mode
));
1574 if (coex
->action
== HostCmd_ACT_GEN_GET
)
1578 coex_tlv
->mode
= cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE
);
1580 coex_tlv
->mode
= cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL
);
1585 static int mwifiex_cmd_gtk_rekey_offload(struct mwifiex_private
*priv
,
1586 struct host_cmd_ds_command
*cmd
,
1588 struct cfg80211_gtk_rekey_data
*data
)
1590 struct host_cmd_ds_gtk_rekey_params
*rekey
= &cmd
->params
.rekey
;
1593 cmd
->command
= cpu_to_le16(HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG
);
1594 cmd
->size
= cpu_to_le16(sizeof(*rekey
) + S_DS_GEN
);
1596 rekey
->action
= cpu_to_le16(cmd_action
);
1597 if (cmd_action
== HostCmd_ACT_GEN_SET
) {
1598 memcpy(rekey
->kek
, data
->kek
, NL80211_KEK_LEN
);
1599 memcpy(rekey
->kck
, data
->kck
, NL80211_KCK_LEN
);
1600 rekey_ctr
= be64_to_cpup((__be64
*)data
->replay_ctr
);
1601 rekey
->replay_ctr_low
= cpu_to_le32((u32
)rekey_ctr
);
1602 rekey
->replay_ctr_high
=
1603 cpu_to_le32((u32
)((u64
)rekey_ctr
>> 32));
1609 static int mwifiex_cmd_chan_region_cfg(struct mwifiex_private
*priv
,
1610 struct host_cmd_ds_command
*cmd
,
1613 struct host_cmd_ds_chan_region_cfg
*reg
= &cmd
->params
.reg_cfg
;
1615 cmd
->command
= cpu_to_le16(HostCmd_CMD_CHAN_REGION_CFG
);
1616 cmd
->size
= cpu_to_le16(sizeof(*reg
) + S_DS_GEN
);
1618 if (cmd_action
== HostCmd_ACT_GEN_GET
)
1619 reg
->action
= cpu_to_le16(cmd_action
);
1625 mwifiex_cmd_coalesce_cfg(struct mwifiex_private
*priv
,
1626 struct host_cmd_ds_command
*cmd
,
1627 u16 cmd_action
, void *data_buf
)
1629 struct host_cmd_ds_coalesce_cfg
*coalesce_cfg
=
1630 &cmd
->params
.coalesce_cfg
;
1631 struct mwifiex_ds_coalesce_cfg
*cfg
= data_buf
;
1632 struct coalesce_filt_field_param
*param
;
1633 u16 cnt
, idx
, length
;
1634 struct coalesce_receive_filt_rule
*rule
;
1636 cmd
->command
= cpu_to_le16(HostCmd_CMD_COALESCE_CFG
);
1637 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1639 coalesce_cfg
->action
= cpu_to_le16(cmd_action
);
1640 coalesce_cfg
->num_of_rules
= cpu_to_le16(cfg
->num_of_rules
);
1641 rule
= coalesce_cfg
->rule
;
1643 for (cnt
= 0; cnt
< cfg
->num_of_rules
; cnt
++) {
1644 rule
->header
.type
= cpu_to_le16(TLV_TYPE_COALESCE_RULE
);
1645 rule
->max_coalescing_delay
=
1646 cpu_to_le16(cfg
->rule
[cnt
].max_coalescing_delay
);
1647 rule
->pkt_type
= cfg
->rule
[cnt
].pkt_type
;
1648 rule
->num_of_fields
= cfg
->rule
[cnt
].num_of_fields
;
1652 param
= rule
->params
;
1653 for (idx
= 0; idx
< cfg
->rule
[cnt
].num_of_fields
; idx
++) {
1654 param
->operation
= cfg
->rule
[cnt
].params
[idx
].operation
;
1655 param
->operand_len
=
1656 cfg
->rule
[cnt
].params
[idx
].operand_len
;
1658 cpu_to_le16(cfg
->rule
[cnt
].params
[idx
].offset
);
1659 memcpy(param
->operand_byte_stream
,
1660 cfg
->rule
[cnt
].params
[idx
].operand_byte_stream
,
1661 param
->operand_len
);
1663 length
+= sizeof(struct coalesce_filt_field_param
);
1668 /* Total rule length is sizeof max_coalescing_delay(u16),
1669 * num_of_fields(u8), pkt_type(u8) and total length of the all
1672 rule
->header
.len
= cpu_to_le16(length
+ sizeof(u16
) +
1673 sizeof(u8
) + sizeof(u8
));
1675 /* Add the rule length to the command size*/
1676 le16_unaligned_add_cpu(&cmd
->size
,
1677 le16_to_cpu(rule
->header
.len
) +
1678 sizeof(struct mwifiex_ie_types_header
));
1680 rule
= (void *)((u8
*)rule
->params
+ length
);
1683 /* Add sizeof action, num_of_rules to total command length */
1684 le16_unaligned_add_cpu(&cmd
->size
, sizeof(u16
) + sizeof(u16
));
1690 mwifiex_cmd_tdls_config(struct mwifiex_private
*priv
,
1691 struct host_cmd_ds_command
*cmd
,
1692 u16 cmd_action
, void *data_buf
)
1694 struct host_cmd_ds_tdls_config
*tdls_config
= &cmd
->params
.tdls_config
;
1695 struct mwifiex_tdls_init_cs_params
*config
;
1696 struct mwifiex_tdls_config
*init_config
;
1699 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_CONFIG
);
1700 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1701 tdls_config
->tdls_action
= cpu_to_le16(cmd_action
);
1702 le16_unaligned_add_cpu(&cmd
->size
, sizeof(tdls_config
->tdls_action
));
1704 switch (cmd_action
) {
1705 case ACT_TDLS_CS_ENABLE_CONFIG
:
1706 init_config
= data_buf
;
1707 len
= sizeof(*init_config
);
1708 memcpy(tdls_config
->tdls_data
, init_config
, len
);
1710 case ACT_TDLS_CS_INIT
:
1712 len
= sizeof(*config
);
1713 memcpy(tdls_config
->tdls_data
, config
, len
);
1715 case ACT_TDLS_CS_STOP
:
1716 len
= sizeof(struct mwifiex_tdls_stop_cs_params
);
1717 memcpy(tdls_config
->tdls_data
, data_buf
, len
);
1719 case ACT_TDLS_CS_PARAMS
:
1720 len
= sizeof(struct mwifiex_tdls_config_cs_params
);
1721 memcpy(tdls_config
->tdls_data
, data_buf
, len
);
1724 mwifiex_dbg(priv
->adapter
, ERROR
,
1725 "Unknown TDLS configuration\n");
1729 le16_unaligned_add_cpu(&cmd
->size
, len
);
1734 mwifiex_cmd_tdls_oper(struct mwifiex_private
*priv
,
1735 struct host_cmd_ds_command
*cmd
,
1738 struct host_cmd_ds_tdls_oper
*tdls_oper
= &cmd
->params
.tdls_oper
;
1739 struct mwifiex_ds_tdls_oper
*oper
= data_buf
;
1740 struct host_cmd_tlv_rates
*tlv_rates
;
1741 struct mwifiex_ie_types_htcap
*ht_capab
;
1742 struct mwifiex_ie_types_qos_info
*wmm_qos_info
;
1743 struct mwifiex_ie_types_extcap
*extcap
;
1744 struct mwifiex_ie_types_vhtcap
*vht_capab
;
1745 struct mwifiex_ie_types_aid
*aid
;
1746 struct mwifiex_ie_types_tdls_idle_timeout
*timeout
;
1749 struct station_parameters
*params
= priv
->sta_params
;
1751 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_OPER
);
1752 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1753 le16_unaligned_add_cpu(&cmd
->size
,
1754 sizeof(struct host_cmd_ds_tdls_oper
));
1756 tdls_oper
->reason
= 0;
1757 memcpy(tdls_oper
->peer_mac
, oper
->peer_mac
, ETH_ALEN
);
1759 pos
= (u8
*)tdls_oper
+ sizeof(struct host_cmd_ds_tdls_oper
);
1761 switch (oper
->tdls_action
) {
1762 case MWIFIEX_TDLS_DISABLE_LINK
:
1763 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_DELETE
);
1765 case MWIFIEX_TDLS_CREATE_LINK
:
1766 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CREATE
);
1768 case MWIFIEX_TDLS_CONFIG_LINK
:
1769 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CONFIG
);
1772 mwifiex_dbg(priv
->adapter
, ERROR
,
1773 "TDLS config params not available for %pM\n",
1778 put_unaligned_le16(params
->capability
, pos
);
1779 config_len
+= sizeof(params
->capability
);
1781 wmm_qos_info
= (void *)(pos
+ config_len
);
1782 wmm_qos_info
->header
.type
= cpu_to_le16(WLAN_EID_QOS_CAPA
);
1783 wmm_qos_info
->header
.len
=
1784 cpu_to_le16(sizeof(wmm_qos_info
->qos_info
));
1785 wmm_qos_info
->qos_info
= 0;
1786 config_len
+= sizeof(struct mwifiex_ie_types_qos_info
);
1788 if (params
->ht_capa
) {
1789 ht_capab
= (struct mwifiex_ie_types_htcap
*)(pos
+
1791 ht_capab
->header
.type
=
1792 cpu_to_le16(WLAN_EID_HT_CAPABILITY
);
1793 ht_capab
->header
.len
=
1794 cpu_to_le16(sizeof(struct ieee80211_ht_cap
));
1795 memcpy(&ht_capab
->ht_cap
, params
->ht_capa
,
1796 sizeof(struct ieee80211_ht_cap
));
1797 config_len
+= sizeof(struct mwifiex_ie_types_htcap
);
1800 if (params
->supported_rates
&& params
->supported_rates_len
) {
1801 tlv_rates
= (struct host_cmd_tlv_rates
*)(pos
+
1803 tlv_rates
->header
.type
=
1804 cpu_to_le16(WLAN_EID_SUPP_RATES
);
1805 tlv_rates
->header
.len
=
1806 cpu_to_le16(params
->supported_rates_len
);
1807 memcpy(tlv_rates
->rates
, params
->supported_rates
,
1808 params
->supported_rates_len
);
1809 config_len
+= sizeof(struct host_cmd_tlv_rates
) +
1810 params
->supported_rates_len
;
1813 if (params
->ext_capab
&& params
->ext_capab_len
) {
1814 extcap
= (struct mwifiex_ie_types_extcap
*)(pos
+
1816 extcap
->header
.type
=
1817 cpu_to_le16(WLAN_EID_EXT_CAPABILITY
);
1818 extcap
->header
.len
= cpu_to_le16(params
->ext_capab_len
);
1819 memcpy(extcap
->ext_capab
, params
->ext_capab
,
1820 params
->ext_capab_len
);
1821 config_len
+= sizeof(struct mwifiex_ie_types_extcap
) +
1822 params
->ext_capab_len
;
1824 if (params
->vht_capa
) {
1825 vht_capab
= (struct mwifiex_ie_types_vhtcap
*)(pos
+
1827 vht_capab
->header
.type
=
1828 cpu_to_le16(WLAN_EID_VHT_CAPABILITY
);
1829 vht_capab
->header
.len
=
1830 cpu_to_le16(sizeof(struct ieee80211_vht_cap
));
1831 memcpy(&vht_capab
->vht_cap
, params
->vht_capa
,
1832 sizeof(struct ieee80211_vht_cap
));
1833 config_len
+= sizeof(struct mwifiex_ie_types_vhtcap
);
1836 aid
= (struct mwifiex_ie_types_aid
*)(pos
+ config_len
);
1837 aid
->header
.type
= cpu_to_le16(WLAN_EID_AID
);
1838 aid
->header
.len
= cpu_to_le16(sizeof(params
->aid
));
1839 aid
->aid
= cpu_to_le16(params
->aid
);
1840 config_len
+= sizeof(struct mwifiex_ie_types_aid
);
1843 timeout
= (void *)(pos
+ config_len
);
1844 timeout
->header
.type
= cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT
);
1845 timeout
->header
.len
= cpu_to_le16(sizeof(timeout
->value
));
1846 timeout
->value
= cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC
);
1847 config_len
+= sizeof(struct mwifiex_ie_types_tdls_idle_timeout
);
1851 mwifiex_dbg(priv
->adapter
, ERROR
, "Unknown TDLS operation\n");
1855 le16_unaligned_add_cpu(&cmd
->size
, config_len
);
1860 /* This function prepares command of sdio rx aggr info. */
1861 static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command
*cmd
,
1862 u16 cmd_action
, void *data_buf
)
1864 struct host_cmd_sdio_sp_rx_aggr_cfg
*cfg
=
1865 &cmd
->params
.sdio_rx_aggr_cfg
;
1867 cmd
->command
= cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
);
1869 cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg
) +
1871 cfg
->action
= cmd_action
;
1872 if (cmd_action
== HostCmd_ACT_GEN_SET
)
1873 cfg
->enable
= *(u8
*)data_buf
;
1878 /* This function prepares command to get HS wakeup reason.
1880 * Preparation includes -
1881 * - Setting command ID, action and proper size
1882 * - Ensuring correct endian-ness
1884 static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private
*priv
,
1885 struct host_cmd_ds_command
*cmd
)
1887 cmd
->command
= cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON
);
1888 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason
) +
1894 static int mwifiex_cmd_get_chan_info(struct host_cmd_ds_command
*cmd
,
1897 struct host_cmd_ds_sta_configure
*sta_cfg_cmd
= &cmd
->params
.sta_cfg
;
1898 struct host_cmd_tlv_channel_band
*tlv_band_channel
=
1899 (struct host_cmd_tlv_channel_band
*)sta_cfg_cmd
->tlv_buffer
;
1901 cmd
->command
= cpu_to_le16(HostCmd_CMD_STA_CONFIGURE
);
1902 cmd
->size
= cpu_to_le16(sizeof(*sta_cfg_cmd
) +
1903 sizeof(*tlv_band_channel
) + S_DS_GEN
);
1904 sta_cfg_cmd
->action
= cpu_to_le16(cmd_action
);
1905 memset(tlv_band_channel
, 0, sizeof(*tlv_band_channel
));
1906 tlv_band_channel
->header
.type
= cpu_to_le16(TLV_TYPE_CHANNELBANDLIST
);
1907 tlv_band_channel
->header
.len
= cpu_to_le16(sizeof(*tlv_band_channel
) -
1908 sizeof(struct mwifiex_ie_types_header
));
1913 /* This function check if the command is supported by firmware */
1914 static int mwifiex_is_cmd_supported(struct mwifiex_private
*priv
, u16 cmd_no
)
1916 if (!ISSUPP_ADHOC_ENABLED(priv
->adapter
->fw_cap_info
)) {
1918 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
:
1919 case HostCmd_CMD_802_11_AD_HOC_START
:
1920 case HostCmd_CMD_802_11_AD_HOC_JOIN
:
1921 case HostCmd_CMD_802_11_AD_HOC_STOP
:
1932 * This function prepares the commands before sending them to the firmware.
1934 * This is a generic function which calls specific command preparation
1935 * routines based upon the command number.
1937 int mwifiex_sta_prepare_cmd(struct mwifiex_private
*priv
, uint16_t cmd_no
,
1938 u16 cmd_action
, u32 cmd_oid
,
1939 void *data_buf
, void *cmd_buf
)
1941 struct host_cmd_ds_command
*cmd_ptr
= cmd_buf
;
1944 if (mwifiex_is_cmd_supported(priv
, cmd_no
)) {
1945 mwifiex_dbg(priv
->adapter
, ERROR
,
1946 "0x%x command not supported by firmware\n",
1951 /* Prepare command */
1953 case HostCmd_CMD_GET_HW_SPEC
:
1954 ret
= mwifiex_cmd_get_hw_spec(priv
, cmd_ptr
);
1956 case HostCmd_CMD_CFG_DATA
:
1957 ret
= mwifiex_cmd_cfg_data(priv
, cmd_ptr
, data_buf
);
1959 case HostCmd_CMD_MAC_CONTROL
:
1960 ret
= mwifiex_cmd_mac_control(priv
, cmd_ptr
, cmd_action
,
1963 case HostCmd_CMD_802_11_MAC_ADDRESS
:
1964 ret
= mwifiex_cmd_802_11_mac_address(priv
, cmd_ptr
,
1967 case HostCmd_CMD_MAC_MULTICAST_ADR
:
1968 ret
= mwifiex_cmd_mac_multicast_adr(cmd_ptr
, cmd_action
,
1971 case HostCmd_CMD_TX_RATE_CFG
:
1972 ret
= mwifiex_cmd_tx_rate_cfg(priv
, cmd_ptr
, cmd_action
,
1975 case HostCmd_CMD_TXPWR_CFG
:
1976 ret
= mwifiex_cmd_tx_power_cfg(cmd_ptr
, cmd_action
,
1979 case HostCmd_CMD_RF_TX_PWR
:
1980 ret
= mwifiex_cmd_rf_tx_power(priv
, cmd_ptr
, cmd_action
,
1983 case HostCmd_CMD_RF_ANTENNA
:
1984 ret
= mwifiex_cmd_rf_antenna(priv
, cmd_ptr
, cmd_action
,
1987 case HostCmd_CMD_802_11_PS_MODE_ENH
:
1988 ret
= mwifiex_cmd_enh_power_mode(priv
, cmd_ptr
, cmd_action
,
1989 (uint16_t)cmd_oid
, data_buf
);
1991 case HostCmd_CMD_802_11_HS_CFG_ENH
:
1992 ret
= mwifiex_cmd_802_11_hs_cfg(priv
, cmd_ptr
, cmd_action
,
1993 (struct mwifiex_hs_config_param
*) data_buf
);
1995 case HostCmd_CMD_802_11_SCAN
:
1996 ret
= mwifiex_cmd_802_11_scan(cmd_ptr
, data_buf
);
1998 case HostCmd_CMD_802_11_BG_SCAN_CONFIG
:
1999 ret
= mwifiex_cmd_802_11_bg_scan_config(priv
, cmd_ptr
,
2002 case HostCmd_CMD_802_11_BG_SCAN_QUERY
:
2003 ret
= mwifiex_cmd_802_11_bg_scan_query(cmd_ptr
);
2005 case HostCmd_CMD_802_11_ASSOCIATE
:
2006 ret
= mwifiex_cmd_802_11_associate(priv
, cmd_ptr
, data_buf
);
2008 case HostCmd_CMD_802_11_DEAUTHENTICATE
:
2009 ret
= mwifiex_cmd_802_11_deauthenticate(priv
, cmd_ptr
,
2012 case HostCmd_CMD_802_11_AD_HOC_START
:
2013 ret
= mwifiex_cmd_802_11_ad_hoc_start(priv
, cmd_ptr
,
2016 case HostCmd_CMD_802_11_GET_LOG
:
2017 ret
= mwifiex_cmd_802_11_get_log(cmd_ptr
);
2019 case HostCmd_CMD_802_11_AD_HOC_JOIN
:
2020 ret
= mwifiex_cmd_802_11_ad_hoc_join(priv
, cmd_ptr
,
2023 case HostCmd_CMD_802_11_AD_HOC_STOP
:
2024 ret
= mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr
);
2026 case HostCmd_CMD_RSSI_INFO
:
2027 ret
= mwifiex_cmd_802_11_rssi_info(priv
, cmd_ptr
, cmd_action
);
2029 case HostCmd_CMD_802_11_SNMP_MIB
:
2030 ret
= mwifiex_cmd_802_11_snmp_mib(priv
, cmd_ptr
, cmd_action
,
2033 case HostCmd_CMD_802_11_TX_RATE_QUERY
:
2035 cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY
);
2037 cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query
) +
2042 case HostCmd_CMD_VERSION_EXT
:
2043 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2044 cmd_ptr
->params
.verext
.version_str_sel
=
2045 (u8
)(get_unaligned((u32
*)data_buf
));
2046 memcpy(&cmd_ptr
->params
, data_buf
,
2047 sizeof(struct host_cmd_ds_version_ext
));
2049 cpu_to_le16(sizeof(struct host_cmd_ds_version_ext
) +
2053 case HostCmd_CMD_MGMT_FRAME_REG
:
2054 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2055 cmd_ptr
->params
.reg_mask
.action
= cpu_to_le16(cmd_action
);
2056 cmd_ptr
->params
.reg_mask
.mask
= cpu_to_le32(
2057 get_unaligned((u32
*)data_buf
));
2059 cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg
) +
2063 case HostCmd_CMD_REMAIN_ON_CHAN
:
2064 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2065 memcpy(&cmd_ptr
->params
, data_buf
,
2066 sizeof(struct host_cmd_ds_remain_on_chan
));
2068 cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan
) +
2071 case HostCmd_CMD_11AC_CFG
:
2072 ret
= mwifiex_cmd_11ac_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
2074 case HostCmd_CMD_PACKET_AGGR_CTRL
:
2075 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2076 cmd_ptr
->params
.pkt_aggr_ctrl
.action
= cpu_to_le16(cmd_action
);
2077 cmd_ptr
->params
.pkt_aggr_ctrl
.enable
=
2078 cpu_to_le16(*(u16
*)data_buf
);
2080 cpu_to_le16(sizeof(struct host_cmd_ds_pkt_aggr_ctrl
) +
2083 case HostCmd_CMD_P2P_MODE_CFG
:
2084 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2085 cmd_ptr
->params
.mode_cfg
.action
= cpu_to_le16(cmd_action
);
2086 cmd_ptr
->params
.mode_cfg
.mode
= cpu_to_le16(
2087 get_unaligned((u16
*)data_buf
));
2089 cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg
) +
2092 case HostCmd_CMD_FUNC_INIT
:
2093 if (priv
->adapter
->hw_status
== MWIFIEX_HW_STATUS_RESET
)
2094 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_READY
;
2095 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2096 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
2098 case HostCmd_CMD_FUNC_SHUTDOWN
:
2099 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_RESET
;
2100 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2101 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
2103 case HostCmd_CMD_11N_ADDBA_REQ
:
2104 ret
= mwifiex_cmd_11n_addba_req(cmd_ptr
, data_buf
);
2106 case HostCmd_CMD_11N_DELBA
:
2107 ret
= mwifiex_cmd_11n_delba(cmd_ptr
, data_buf
);
2109 case HostCmd_CMD_11N_ADDBA_RSP
:
2110 ret
= mwifiex_cmd_11n_addba_rsp_gen(priv
, cmd_ptr
, data_buf
);
2112 case HostCmd_CMD_802_11_KEY_MATERIAL
:
2113 ret
= mwifiex_cmd_802_11_key_material(priv
, cmd_ptr
,
2114 cmd_action
, cmd_oid
,
2117 case HostCmd_CMD_802_11D_DOMAIN_INFO
:
2118 ret
= mwifiex_cmd_802_11d_domain_info(priv
, cmd_ptr
,
2121 case HostCmd_CMD_RECONFIGURE_TX_BUFF
:
2122 ret
= mwifiex_cmd_recfg_tx_buf(priv
, cmd_ptr
, cmd_action
,
2125 case HostCmd_CMD_AMSDU_AGGR_CTRL
:
2126 ret
= mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr
, cmd_action
,
2129 case HostCmd_CMD_11N_CFG
:
2130 ret
= mwifiex_cmd_11n_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
2132 case HostCmd_CMD_WMM_GET_STATUS
:
2133 mwifiex_dbg(priv
->adapter
, CMD
,
2134 "cmd: WMM: WMM_GET_STATUS cmd sent\n");
2135 cmd_ptr
->command
= cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS
);
2137 cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status
) +
2141 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
:
2142 ret
= mwifiex_cmd_ibss_coalescing_status(cmd_ptr
, cmd_action
,
2145 case HostCmd_CMD_802_11_SCAN_EXT
:
2146 ret
= mwifiex_cmd_802_11_scan_ext(priv
, cmd_ptr
, data_buf
);
2148 case HostCmd_CMD_MEM_ACCESS
:
2149 ret
= mwifiex_cmd_mem_access(cmd_ptr
, cmd_action
, data_buf
);
2151 case HostCmd_CMD_MAC_REG_ACCESS
:
2152 case HostCmd_CMD_BBP_REG_ACCESS
:
2153 case HostCmd_CMD_RF_REG_ACCESS
:
2154 case HostCmd_CMD_PMIC_REG_ACCESS
:
2155 case HostCmd_CMD_CAU_REG_ACCESS
:
2156 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
2157 ret
= mwifiex_cmd_reg_access(cmd_ptr
, cmd_action
, data_buf
);
2159 case HostCmd_CMD_SET_BSS_MODE
:
2160 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2161 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
)
2162 cmd_ptr
->params
.bss_mode
.con_type
=
2163 CONNECTION_TYPE_ADHOC
;
2164 else if (priv
->bss_mode
== NL80211_IFTYPE_STATION
||
2165 priv
->bss_mode
== NL80211_IFTYPE_P2P_CLIENT
)
2166 cmd_ptr
->params
.bss_mode
.con_type
=
2167 CONNECTION_TYPE_INFRA
;
2168 else if (priv
->bss_mode
== NL80211_IFTYPE_AP
||
2169 priv
->bss_mode
== NL80211_IFTYPE_P2P_GO
)
2170 cmd_ptr
->params
.bss_mode
.con_type
= CONNECTION_TYPE_AP
;
2171 cmd_ptr
->size
= cpu_to_le16(sizeof(struct
2172 host_cmd_ds_set_bss_mode
) + S_DS_GEN
);
2175 case HostCmd_CMD_PCIE_DESC_DETAILS
:
2176 ret
= mwifiex_cmd_pcie_host_spec(priv
, cmd_ptr
, cmd_action
);
2178 case HostCmd_CMD_802_11_SUBSCRIBE_EVENT
:
2179 ret
= mwifiex_cmd_802_11_subsc_evt(priv
, cmd_ptr
, data_buf
);
2181 case HostCmd_CMD_MEF_CFG
:
2182 ret
= mwifiex_cmd_mef_cfg(priv
, cmd_ptr
, data_buf
);
2184 case HostCmd_CMD_COALESCE_CFG
:
2185 ret
= mwifiex_cmd_coalesce_cfg(priv
, cmd_ptr
, cmd_action
,
2188 case HostCmd_CMD_TDLS_OPER
:
2189 ret
= mwifiex_cmd_tdls_oper(priv
, cmd_ptr
, data_buf
);
2191 case HostCmd_CMD_TDLS_CONFIG
:
2192 ret
= mwifiex_cmd_tdls_config(priv
, cmd_ptr
, cmd_action
,
2195 case HostCmd_CMD_CHAN_REPORT_REQUEST
:
2196 ret
= mwifiex_cmd_issue_chan_report_request(priv
, cmd_ptr
,
2199 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
:
2200 ret
= mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr
, cmd_action
,
2203 case HostCmd_CMD_HS_WAKEUP_REASON
:
2204 ret
= mwifiex_cmd_get_wakeup_reason(priv
, cmd_ptr
);
2206 case HostCmd_CMD_MC_POLICY
:
2207 ret
= mwifiex_cmd_set_mc_policy(priv
, cmd_ptr
, cmd_action
,
2210 case HostCmd_CMD_ROBUST_COEX
:
2211 ret
= mwifiex_cmd_robust_coex(priv
, cmd_ptr
, cmd_action
,
2214 case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG
:
2215 ret
= mwifiex_cmd_gtk_rekey_offload(priv
, cmd_ptr
, cmd_action
,
2218 case HostCmd_CMD_CHAN_REGION_CFG
:
2219 ret
= mwifiex_cmd_chan_region_cfg(priv
, cmd_ptr
, cmd_action
);
2221 case HostCmd_CMD_FW_DUMP_EVENT
:
2222 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2223 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
2225 case HostCmd_CMD_STA_CONFIGURE
:
2226 ret
= mwifiex_cmd_get_chan_info(cmd_ptr
, cmd_action
);
2229 mwifiex_dbg(priv
->adapter
, ERROR
,
2230 "PREP_CMD: unknown cmd- %#x\n", cmd_no
);
2238 * This function issues commands to initialize firmware.
2240 * This is called after firmware download to bring the card to
2242 * Function is also called during reinitialization of virtual
2245 * The following commands are issued sequentially -
2246 * - Set PCI-Express host buffer configuration (PCIE only)
2247 * - Function init (for first interface only)
2248 * - Read MAC address (for first interface only)
2249 * - Reconfigure Tx buffer size (for first interface only)
2250 * - Enable auto deep sleep (for first interface only)
2253 * - Set IBSS coalescing status
2254 * - Set AMSDU aggregation control
2256 * - Set MAC control (this must be the last command to initialize firmware)
2258 int mwifiex_sta_init_cmd(struct mwifiex_private
*priv
, u8 first_sta
, bool init
)
2260 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2262 struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl
;
2263 struct mwifiex_ds_auto_ds auto_ds
;
2264 enum state_11d_t state_11d
;
2265 struct mwifiex_ds_11n_tx_cfg tx_cfg
;
2266 u8 sdio_sp_rx_aggr_enable
;
2267 u16 packet_aggr_enable
;
2271 if (priv
->adapter
->iface_type
== MWIFIEX_PCIE
) {
2272 ret
= mwifiex_send_cmd(priv
,
2273 HostCmd_CMD_PCIE_DESC_DETAILS
,
2274 HostCmd_ACT_GEN_SET
, 0, NULL
,
2280 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_FUNC_INIT
,
2281 HostCmd_ACT_GEN_SET
, 0, NULL
, true);
2285 /* Download calibration data to firmware.
2286 * The cal-data can be read from device tree and/or
2287 * a configuration file and downloaded to firmware.
2289 if (adapter
->dt_node
) {
2290 if (of_property_read_u32(adapter
->dt_node
,
2291 "marvell,wakeup-pin",
2293 pr_debug("Wakeup pin = 0x%x\n", data
);
2294 adapter
->hs_cfg
.gpio
= data
;
2297 mwifiex_dnld_dt_cfgdata(priv
, adapter
->dt_node
,
2301 if (adapter
->cal_data
)
2302 mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
2303 HostCmd_ACT_GEN_SET
, 0, NULL
, true);
2305 /* Read MAC address from HW */
2306 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_GET_HW_SPEC
,
2307 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2311 /** Set SDIO Single Port RX Aggr Info */
2312 if (priv
->adapter
->iface_type
== MWIFIEX_SDIO
&&
2313 ISSUPP_SDIO_SPA_ENABLED(priv
->adapter
->fw_cap_info
) &&
2314 !priv
->adapter
->host_disable_sdio_rx_aggr
) {
2315 sdio_sp_rx_aggr_enable
= true;
2316 ret
= mwifiex_send_cmd(priv
,
2317 HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
,
2318 HostCmd_ACT_GEN_SET
, 0,
2319 &sdio_sp_rx_aggr_enable
,
2322 mwifiex_dbg(priv
->adapter
, ERROR
,
2323 "error while enabling SP aggregation..disable it");
2324 adapter
->sdio_rx_aggr_enable
= false;
2328 /* Reconfigure tx buf size */
2329 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RECONFIGURE_TX_BUFF
,
2330 HostCmd_ACT_GEN_SET
, 0,
2331 &priv
->adapter
->tx_buf_size
, true);
2335 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2336 /* Enable IEEE PS by default */
2337 priv
->adapter
->ps_mode
= MWIFIEX_802_11_POWER_MODE_PSP
;
2338 ret
= mwifiex_send_cmd(priv
,
2339 HostCmd_CMD_802_11_PS_MODE_ENH
,
2340 EN_AUTO_PS
, BITMAP_STA_PS
, NULL
,
2347 adapter
->drcs_enabled
= true;
2348 if (ISSUPP_DRCS_ENABLED(adapter
->fw_cap_info
))
2349 ret
= mwifiex_send_cmd(priv
,
2350 HostCmd_CMD_MC_POLICY
,
2351 HostCmd_ACT_GEN_SET
, 0,
2352 &adapter
->drcs_enabled
,
2358 mwifiex_send_cmd(priv
, HostCmd_CMD_CHAN_REGION_CFG
,
2359 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2363 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_TX_RATE_CFG
,
2364 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2367 priv
->data_rate
= 0;
2370 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RF_TX_PWR
,
2371 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2375 memset(&amsdu_aggr_ctrl
, 0, sizeof(amsdu_aggr_ctrl
));
2376 amsdu_aggr_ctrl
.enable
= true;
2377 /* Send request to firmware */
2378 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_AMSDU_AGGR_CTRL
,
2379 HostCmd_ACT_GEN_SET
, 0,
2380 &amsdu_aggr_ctrl
, true);
2383 /* MAC Control must be the last command in init_fw */
2384 /* set MAC Control */
2385 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_MAC_CONTROL
,
2386 HostCmd_ACT_GEN_SET
, 0,
2387 &priv
->curr_pkt_filter
, true);
2391 if (!disable_auto_ds
&& first_sta
&&
2392 priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2393 /* Enable auto deep sleep */
2394 auto_ds
.auto_ds
= DEEP_SLEEP_ON
;
2395 auto_ds
.idle_time
= DEEP_SLEEP_IDLE_TIME
;
2396 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_PS_MODE_ENH
,
2397 EN_AUTO_PS
, BITMAP_AUTO_DS
,
2403 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2404 /* Send cmd to FW to enable/disable 11D function */
2405 state_11d
= ENABLE_11D
;
2406 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_SNMP_MIB
,
2407 HostCmd_ACT_GEN_SET
, DOT11D_I
,
2410 mwifiex_dbg(priv
->adapter
, ERROR
,
2411 "11D: failed to enable 11D\n");
2414 /* Pacekt aggregation handshake with firmware */
2416 packet_aggr_enable
= true;
2417 mwifiex_send_cmd(priv
, HostCmd_CMD_PACKET_AGGR_CTRL
,
2418 HostCmd_ACT_GEN_SET
, 0,
2419 &packet_aggr_enable
, true);
2422 /* Send cmd to FW to configure 11n specific configuration
2423 * (Short GI, Channel BW, Green field support etc.) for transmit
2425 tx_cfg
.tx_htcap
= MWIFIEX_FW_DEF_HTTXCFG
;
2426 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_11N_CFG
,
2427 HostCmd_ACT_GEN_SET
, 0, &tx_cfg
, true);
2430 /* set last_init_cmd before sending the command */
2431 priv
->adapter
->last_init_cmd
= HostCmd_CMD_11N_CFG
;