2 * Marvell Wireless LAN device driver: station command handling
4 * Copyright (C) 2011-2014, Marvell International Ltd.
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. 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
, u16
*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_le16(*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_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 *((__le16
*) (snmp_mib
->value
)) = cpu_to_le16(*ul_temp
);
134 le16_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 le16_to_cpu(*(__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]);
193 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
195 rate_scope
->ht_mcs_rate_bitmap
[i
] =
196 cpu_to_le16(pbitmap_rates
[2 + i
]);
197 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
199 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
201 rate_scope
->vht_mcs_rate_bitmap
[i
] =
202 cpu_to_le16(pbitmap_rates
[10 + i
]);
205 rate_scope
->hr_dsss_rate_bitmap
=
206 cpu_to_le16(priv
->bitmap_rates
[0]);
207 rate_scope
->ofdm_rate_bitmap
=
208 cpu_to_le16(priv
->bitmap_rates
[1]);
210 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
212 rate_scope
->ht_mcs_rate_bitmap
[i
] =
213 cpu_to_le16(priv
->bitmap_rates
[2 + i
]);
214 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
216 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
218 rate_scope
->vht_mcs_rate_bitmap
[i
] =
219 cpu_to_le16(priv
->bitmap_rates
[10 + i
]);
223 rate_drop
= (struct mwifiex_rate_drop_pattern
*) ((u8
*) rate_scope
+
224 sizeof(struct mwifiex_rate_scope
));
225 rate_drop
->type
= cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL
);
226 rate_drop
->length
= cpu_to_le16(sizeof(rate_drop
->rate_drop_mode
));
227 rate_drop
->rate_drop_mode
= 0;
230 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_tx_rate_cfg
) +
231 sizeof(struct mwifiex_rate_scope
) +
232 sizeof(struct mwifiex_rate_drop_pattern
));
238 * This function prepares command to set/get Tx power configuration.
240 * Preparation includes -
241 * - Setting command ID, action and proper size
242 * - Setting Tx power mode, power group TLV
244 * - Ensuring correct endian-ness
246 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command
*cmd
,
248 struct host_cmd_ds_txpwr_cfg
*txp
)
250 struct mwifiex_types_power_group
*pg_tlv
;
251 struct host_cmd_ds_txpwr_cfg
*cmd_txp_cfg
= &cmd
->params
.txp_cfg
;
253 cmd
->command
= cpu_to_le16(HostCmd_CMD_TXPWR_CFG
);
255 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_txpwr_cfg
));
256 switch (cmd_action
) {
257 case HostCmd_ACT_GEN_SET
:
259 pg_tlv
= (struct mwifiex_types_power_group
260 *) ((unsigned long) txp
+
261 sizeof(struct host_cmd_ds_txpwr_cfg
));
262 memmove(cmd_txp_cfg
, txp
,
263 sizeof(struct host_cmd_ds_txpwr_cfg
) +
264 sizeof(struct mwifiex_types_power_group
) +
265 le16_to_cpu(pg_tlv
->length
));
267 pg_tlv
= (struct mwifiex_types_power_group
*) ((u8
*)
269 sizeof(struct host_cmd_ds_txpwr_cfg
));
270 cmd
->size
= cpu_to_le16(le16_to_cpu(cmd
->size
) +
271 sizeof(struct mwifiex_types_power_group
) +
272 le16_to_cpu(pg_tlv
->length
));
274 memmove(cmd_txp_cfg
, txp
, sizeof(*txp
));
276 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
278 case HostCmd_ACT_GEN_GET
:
279 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
287 * This function prepares command to get RF Tx power.
289 static int mwifiex_cmd_rf_tx_power(struct mwifiex_private
*priv
,
290 struct host_cmd_ds_command
*cmd
,
291 u16 cmd_action
, void *data_buf
)
293 struct host_cmd_ds_rf_tx_pwr
*txp
= &cmd
->params
.txp
;
295 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr
)
297 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_TX_PWR
);
298 txp
->action
= cpu_to_le16(cmd_action
);
304 * This function prepares command to set rf antenna.
306 static int mwifiex_cmd_rf_antenna(struct mwifiex_private
*priv
,
307 struct host_cmd_ds_command
*cmd
,
309 struct mwifiex_ds_ant_cfg
*ant_cfg
)
311 struct host_cmd_ds_rf_ant_mimo
*ant_mimo
= &cmd
->params
.ant_mimo
;
312 struct host_cmd_ds_rf_ant_siso
*ant_siso
= &cmd
->params
.ant_siso
;
314 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_ANTENNA
);
316 switch (cmd_action
) {
317 case HostCmd_ACT_GEN_SET
:
318 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
319 cmd
->size
= cpu_to_le16(sizeof(struct
320 host_cmd_ds_rf_ant_mimo
)
322 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_SET_TX
);
323 ant_mimo
->tx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->
325 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_SET_RX
);
326 ant_mimo
->rx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->
329 cmd
->size
= cpu_to_le16(sizeof(struct
330 host_cmd_ds_rf_ant_siso
) +
332 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_SET_BOTH
);
333 ant_siso
->ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
336 case HostCmd_ACT_GEN_GET
:
337 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
338 cmd
->size
= cpu_to_le16(sizeof(struct
339 host_cmd_ds_rf_ant_mimo
) +
341 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_GET_TX
);
342 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_GET_RX
);
344 cmd
->size
= cpu_to_le16(sizeof(struct
345 host_cmd_ds_rf_ant_siso
) +
347 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_GET_BOTH
);
355 * This function prepares command to set Host Sleep configuration.
357 * Preparation includes -
358 * - Setting command ID and proper size
359 * - Setting Host Sleep action, conditions, ARP filters
361 * - Ensuring correct endian-ness
364 mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private
*priv
,
365 struct host_cmd_ds_command
*cmd
,
367 struct mwifiex_hs_config_param
*hscfg_param
)
369 struct mwifiex_adapter
*adapter
= priv
->adapter
;
370 struct host_cmd_ds_802_11_hs_cfg_enh
*hs_cfg
= &cmd
->params
.opt_hs_cfg
;
371 bool hs_activate
= false;
374 /* New Activate command */
376 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH
);
379 (hscfg_param
->conditions
!= cpu_to_le32(HS_CFG_CANCEL
)) &&
380 ((adapter
->arp_filter_size
> 0) &&
381 (adapter
->arp_filter_size
<= ARP_FILTER_MAX_BUF_SIZE
))) {
382 mwifiex_dbg(adapter
, CMD
,
383 "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
384 adapter
->arp_filter_size
);
385 memcpy(((u8
*) hs_cfg
) +
386 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
),
387 adapter
->arp_filter
, adapter
->arp_filter_size
);
388 cmd
->size
= cpu_to_le16
389 (adapter
->arp_filter_size
+
390 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
)
393 cmd
->size
= cpu_to_le16(S_DS_GEN
+ sizeof(struct
394 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
;
404 mwifiex_dbg(adapter
, CMD
,
405 "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
406 hs_cfg
->params
.hs_config
.conditions
,
407 hs_cfg
->params
.hs_config
.gpio
,
408 hs_cfg
->params
.hs_config
.gap
);
415 * This function prepares command to set/get MAC address.
417 * Preparation includes -
418 * - Setting command ID, action and proper size
419 * - Setting MAC address (for SET only)
420 * - Ensuring correct endian-ness
422 static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private
*priv
,
423 struct host_cmd_ds_command
*cmd
,
426 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS
);
427 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address
) +
431 cmd
->params
.mac_addr
.action
= cpu_to_le16(cmd_action
);
433 if (cmd_action
== HostCmd_ACT_GEN_SET
)
434 memcpy(cmd
->params
.mac_addr
.mac_addr
, priv
->curr_addr
,
440 * This function prepares command to set MAC multicast address.
442 * Preparation includes -
443 * - Setting command ID, action and proper size
444 * - Setting MAC multicast address
445 * - Ensuring correct endian-ness
448 mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command
*cmd
,
450 struct mwifiex_multicast_list
*mcast_list
)
452 struct host_cmd_ds_mac_multicast_adr
*mcast_addr
= &cmd
->params
.mc_addr
;
454 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr
) +
456 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR
);
458 mcast_addr
->action
= cpu_to_le16(cmd_action
);
459 mcast_addr
->num_of_adrs
=
460 cpu_to_le16((u16
) mcast_list
->num_multicast_addr
);
461 memcpy(mcast_addr
->mac_list
, mcast_list
->mac_list
,
462 mcast_list
->num_multicast_addr
* ETH_ALEN
);
468 * This function prepares command to deauthenticate.
470 * Preparation includes -
471 * - Setting command ID and proper size
472 * - Setting AP MAC address and reason code
473 * - Ensuring correct endian-ness
475 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private
*priv
,
476 struct host_cmd_ds_command
*cmd
,
479 struct host_cmd_ds_802_11_deauthenticate
*deauth
= &cmd
->params
.deauth
;
481 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE
);
482 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate
)
485 /* Set AP MAC address */
486 memcpy(deauth
->mac_addr
, mac
, ETH_ALEN
);
488 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: Deauth: %pM\n", deauth
->mac_addr
);
490 deauth
->reason_code
= cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING
);
496 * This function prepares command to stop Ad-Hoc network.
498 * Preparation includes -
499 * - Setting command ID and proper size
500 * - Ensuring correct endian-ness
502 static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command
*cmd
)
504 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP
);
505 cmd
->size
= cpu_to_le16(S_DS_GEN
);
510 * This function sets WEP key(s) to key parameter TLV(s).
512 * Multi-key parameter TLVs are supported, so we can send multiple
513 * WEP keys in a single buffer.
516 mwifiex_set_keyparamset_wep(struct mwifiex_private
*priv
,
517 struct mwifiex_ie_type_key_param_set
*key_param_set
,
520 int cur_key_param_len
;
523 /* Multi-key_param_set TLV is supported */
524 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
525 if ((priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP40
) ||
526 (priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP104
)) {
527 key_param_set
->type
=
528 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
529 /* Key_param_set WEP fixed length */
530 #define KEYPARAMSET_WEP_FIXED_LEN 8
531 key_param_set
->length
= cpu_to_le16((u16
)
534 KEYPARAMSET_WEP_FIXED_LEN
));
535 key_param_set
->key_type_id
=
536 cpu_to_le16(KEY_TYPE_ID_WEP
);
537 key_param_set
->key_info
=
538 cpu_to_le16(KEY_ENABLED
| KEY_UNICAST
|
540 key_param_set
->key_len
=
541 cpu_to_le16(priv
->wep_key
[i
].key_length
);
542 /* Set WEP key index */
543 key_param_set
->key
[0] = i
;
544 /* Set default Tx key flag */
547 wep_key_curr_index
& HostCmd_WEP_KEY_INDEX_MASK
))
548 key_param_set
->key
[1] = 1;
550 key_param_set
->key
[1] = 0;
551 memmove(&key_param_set
->key
[2],
552 priv
->wep_key
[i
].key_material
,
553 priv
->wep_key
[i
].key_length
);
555 cur_key_param_len
= priv
->wep_key
[i
].key_length
+
556 KEYPARAMSET_WEP_FIXED_LEN
+
557 sizeof(struct mwifiex_ie_types_header
);
558 *key_param_len
+= (u16
) cur_key_param_len
;
560 (struct mwifiex_ie_type_key_param_set
*)
561 ((u8
*)key_param_set
+
563 } else if (!priv
->wep_key
[i
].key_length
) {
566 mwifiex_dbg(priv
->adapter
, ERROR
,
567 "key%d Length = %d is incorrect\n",
568 (i
+ 1), priv
->wep_key
[i
].key_length
);
576 /* This function populates key material v2 command
577 * to set network key for AES & CMAC AES.
579 static int mwifiex_set_aes_key_v2(struct mwifiex_private
*priv
,
580 struct host_cmd_ds_command
*cmd
,
581 struct mwifiex_ds_encrypt_key
*enc_key
,
582 struct host_cmd_ds_802_11_key_material_v2
*km
)
584 struct mwifiex_adapter
*adapter
= priv
->adapter
;
585 u16 size
, len
= KEY_PARAMS_FIXED_LEN
;
587 if (enc_key
->is_igtk_key
) {
588 mwifiex_dbg(adapter
, INFO
,
589 "%s: Set CMAC AES Key\n", __func__
);
590 if (enc_key
->is_rx_seq_valid
)
591 memcpy(km
->key_param_set
.key_params
.cmac_aes
.ipn
,
592 enc_key
->pn
, enc_key
->pn_len
);
593 km
->key_param_set
.key_info
&= cpu_to_le16(~KEY_MCAST
);
594 km
->key_param_set
.key_info
|= cpu_to_le16(KEY_IGTK
);
595 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES_CMAC
;
596 km
->key_param_set
.key_params
.cmac_aes
.key_len
=
597 cpu_to_le16(enc_key
->key_len
);
598 memcpy(km
->key_param_set
.key_params
.cmac_aes
.key
,
599 enc_key
->key_material
, enc_key
->key_len
);
600 len
+= sizeof(struct mwifiex_cmac_aes_param
);
602 mwifiex_dbg(adapter
, INFO
,
603 "%s: Set AES Key\n", __func__
);
604 if (enc_key
->is_rx_seq_valid
)
605 memcpy(km
->key_param_set
.key_params
.aes
.pn
,
606 enc_key
->pn
, enc_key
->pn_len
);
607 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES
;
608 km
->key_param_set
.key_params
.aes
.key_len
=
609 cpu_to_le16(enc_key
->key_len
);
610 memcpy(km
->key_param_set
.key_params
.aes
.key
,
611 enc_key
->key_material
, enc_key
->key_len
);
612 len
+= sizeof(struct mwifiex_aes_param
);
615 km
->key_param_set
.len
= cpu_to_le16(len
);
616 size
= len
+ sizeof(struct mwifiex_ie_types_header
) +
617 sizeof(km
->action
) + S_DS_GEN
;
618 cmd
->size
= cpu_to_le16(size
);
623 /* This function prepares command to set/get/reset network key(s).
624 * This function prepares key material command for V2 format.
625 * Preparation includes -
626 * - Setting command ID, action and proper size
627 * - Setting WEP keys, WAPI keys or WPA keys along with required
628 * encryption (TKIP, AES) (as required)
629 * - Ensuring correct endian-ness
632 mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private
*priv
,
633 struct host_cmd_ds_command
*cmd
,
634 u16 cmd_action
, u32 cmd_oid
,
635 struct mwifiex_ds_encrypt_key
*enc_key
)
637 struct mwifiex_adapter
*adapter
= priv
->adapter
;
638 u8
*mac
= enc_key
->mac_addr
;
639 u16 key_info
, len
= KEY_PARAMS_FIXED_LEN
;
640 struct host_cmd_ds_802_11_key_material_v2
*km
=
641 &cmd
->params
.key_material_v2
;
643 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
644 km
->action
= cpu_to_le16(cmd_action
);
646 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
647 mwifiex_dbg(adapter
, INFO
, "%s: Get key\n", __func__
);
648 km
->key_param_set
.key_idx
=
649 enc_key
->key_index
& KEY_INDEX_MASK
;
650 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
651 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
652 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
654 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
655 key_info
= KEY_UNICAST
;
657 key_info
= KEY_MCAST
;
659 if (enc_key
->is_igtk_key
)
660 key_info
|= KEY_IGTK
;
662 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
664 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
665 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
670 memset(&km
->key_param_set
, 0,
671 sizeof(struct mwifiex_ie_type_key_param_set_v2
));
673 if (enc_key
->key_disable
) {
674 mwifiex_dbg(adapter
, INFO
, "%s: Remove key\n", __func__
);
675 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_REMOVE
);
676 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
677 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
678 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
679 key_info
= KEY_MCAST
| KEY_UNICAST
;
680 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
681 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
682 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
683 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
688 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
689 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
690 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
691 key_info
= KEY_ENABLED
;
692 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
694 if (enc_key
->key_len
<= WLAN_KEY_LEN_WEP104
) {
695 mwifiex_dbg(adapter
, INFO
, "%s: Set WEP Key\n", __func__
);
696 len
+= sizeof(struct mwifiex_wep_param
);
697 km
->key_param_set
.len
= cpu_to_le16(len
);
698 km
->key_param_set
.key_type
= KEY_TYPE_ID_WEP
;
700 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
701 key_info
|= KEY_MCAST
| KEY_UNICAST
;
703 if (enc_key
->is_current_wep_key
) {
704 key_info
|= KEY_MCAST
| KEY_UNICAST
;
705 if (km
->key_param_set
.key_idx
==
706 (priv
->wep_key_curr_index
& KEY_INDEX_MASK
))
707 key_info
|= KEY_DEFAULT
;
710 if (is_broadcast_ether_addr(mac
))
711 key_info
|= KEY_MCAST
;
713 key_info
|= KEY_UNICAST
|
716 key_info
|= KEY_MCAST
;
720 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
722 km
->key_param_set
.key_params
.wep
.key_len
=
723 cpu_to_le16(enc_key
->key_len
);
724 memcpy(km
->key_param_set
.key_params
.wep
.key
,
725 enc_key
->key_material
, enc_key
->key_len
);
727 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
728 len
+ sizeof(km
->action
) + S_DS_GEN
);
732 if (is_broadcast_ether_addr(mac
))
733 key_info
|= KEY_MCAST
| KEY_RX_KEY
;
735 key_info
|= KEY_UNICAST
| KEY_TX_KEY
| KEY_RX_KEY
;
737 if (enc_key
->is_wapi_key
) {
738 mwifiex_dbg(adapter
, INFO
, "%s: Set WAPI Key\n", __func__
);
739 km
->key_param_set
.key_type
= KEY_TYPE_ID_WAPI
;
740 memcpy(km
->key_param_set
.key_params
.wapi
.pn
, enc_key
->pn
,
742 km
->key_param_set
.key_params
.wapi
.key_len
=
743 cpu_to_le16(enc_key
->key_len
);
744 memcpy(km
->key_param_set
.key_params
.wapi
.key
,
745 enc_key
->key_material
, enc_key
->key_len
);
746 if (is_broadcast_ether_addr(mac
))
747 priv
->sec_info
.wapi_key_on
= true;
749 if (!priv
->sec_info
.wapi_key_on
)
750 key_info
|= KEY_DEFAULT
;
751 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
753 len
+= sizeof(struct mwifiex_wapi_param
);
754 km
->key_param_set
.len
= cpu_to_le16(len
);
755 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
756 len
+ sizeof(km
->action
) + S_DS_GEN
);
760 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
) {
761 key_info
|= KEY_DEFAULT
;
762 /* Enable unicast bit for WPA-NONE/ADHOC_AES */
763 if (!priv
->sec_info
.wpa2_enabled
&&
764 !is_broadcast_ether_addr(mac
))
765 key_info
|= KEY_UNICAST
;
767 /* Enable default key for WPA/WPA2 */
768 if (!priv
->wpa_is_gtk_set
)
769 key_info
|= KEY_DEFAULT
;
772 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
774 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
)
775 return mwifiex_set_aes_key_v2(priv
, cmd
, enc_key
, km
);
777 if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
778 mwifiex_dbg(adapter
, INFO
,
779 "%s: Set TKIP Key\n", __func__
);
780 if (enc_key
->is_rx_seq_valid
)
781 memcpy(km
->key_param_set
.key_params
.tkip
.pn
,
782 enc_key
->pn
, enc_key
->pn_len
);
783 km
->key_param_set
.key_type
= KEY_TYPE_ID_TKIP
;
784 km
->key_param_set
.key_params
.tkip
.key_len
=
785 cpu_to_le16(enc_key
->key_len
);
786 memcpy(km
->key_param_set
.key_params
.tkip
.key
,
787 enc_key
->key_material
, enc_key
->key_len
);
789 len
+= sizeof(struct mwifiex_tkip_param
);
790 km
->key_param_set
.len
= cpu_to_le16(len
);
791 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
792 len
+ sizeof(km
->action
) + S_DS_GEN
);
799 * This function prepares command to set/get/reset network key(s).
800 * This function prepares key material command for V1 format.
802 * Preparation includes -
803 * - Setting command ID, action and proper size
804 * - Setting WEP keys, WAPI keys or WPA keys along with required
805 * encryption (TKIP, AES) (as required)
806 * - Ensuring correct endian-ness
809 mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private
*priv
,
810 struct host_cmd_ds_command
*cmd
,
811 u16 cmd_action
, u32 cmd_oid
,
812 struct mwifiex_ds_encrypt_key
*enc_key
)
814 struct host_cmd_ds_802_11_key_material
*key_material
=
815 &cmd
->params
.key_material
;
816 struct host_cmd_tlv_mac_addr
*tlv_mac
;
817 u16 key_param_len
= 0, cmd_size
;
820 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
821 key_material
->action
= cpu_to_le16(cmd_action
);
823 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
825 cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
);
830 memset(&key_material
->key_param_set
, 0,
832 sizeof(struct mwifiex_ie_type_key_param_set
)));
833 ret
= mwifiex_set_keyparamset_wep(priv
,
834 &key_material
->key_param_set
,
836 cmd
->size
= cpu_to_le16(key_param_len
+
837 sizeof(key_material
->action
) + S_DS_GEN
);
840 memset(&key_material
->key_param_set
, 0,
841 sizeof(struct mwifiex_ie_type_key_param_set
));
842 if (enc_key
->is_wapi_key
) {
843 mwifiex_dbg(priv
->adapter
, INFO
, "info: Set WAPI Key\n");
844 key_material
->key_param_set
.key_type_id
=
845 cpu_to_le16(KEY_TYPE_ID_WAPI
);
846 if (cmd_oid
== KEY_INFO_ENABLED
)
847 key_material
->key_param_set
.key_info
=
848 cpu_to_le16(KEY_ENABLED
);
850 key_material
->key_param_set
.key_info
=
851 cpu_to_le16(!KEY_ENABLED
);
853 key_material
->key_param_set
.key
[0] = enc_key
->key_index
;
854 if (!priv
->sec_info
.wapi_key_on
)
855 key_material
->key_param_set
.key
[1] = 1;
857 /* set 0 when re-key */
858 key_material
->key_param_set
.key
[1] = 0;
860 if (!is_broadcast_ether_addr(enc_key
->mac_addr
)) {
861 /* WAPI pairwise key: unicast */
862 key_material
->key_param_set
.key_info
|=
863 cpu_to_le16(KEY_UNICAST
);
864 } else { /* WAPI group key: multicast */
865 key_material
->key_param_set
.key_info
|=
866 cpu_to_le16(KEY_MCAST
);
867 priv
->sec_info
.wapi_key_on
= true;
870 key_material
->key_param_set
.type
=
871 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
872 key_material
->key_param_set
.key_len
=
873 cpu_to_le16(WAPI_KEY_LEN
);
874 memcpy(&key_material
->key_param_set
.key
[2],
875 enc_key
->key_material
, enc_key
->key_len
);
876 memcpy(&key_material
->key_param_set
.key
[2 + enc_key
->key_len
],
877 enc_key
->pn
, PN_LEN
);
878 key_material
->key_param_set
.length
=
879 cpu_to_le16(WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
);
881 key_param_len
= (WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
) +
882 sizeof(struct mwifiex_ie_types_header
);
883 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
)
884 + S_DS_GEN
+ key_param_len
);
887 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
) {
888 if (enc_key
->is_igtk_key
) {
889 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: CMAC_AES\n");
890 key_material
->key_param_set
.key_type_id
=
891 cpu_to_le16(KEY_TYPE_ID_AES_CMAC
);
892 if (cmd_oid
== KEY_INFO_ENABLED
)
893 key_material
->key_param_set
.key_info
=
894 cpu_to_le16(KEY_ENABLED
);
896 key_material
->key_param_set
.key_info
=
897 cpu_to_le16(!KEY_ENABLED
);
899 key_material
->key_param_set
.key_info
|=
900 cpu_to_le16(KEY_IGTK
);
902 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: WPA_AES\n");
903 key_material
->key_param_set
.key_type_id
=
904 cpu_to_le16(KEY_TYPE_ID_AES
);
905 if (cmd_oid
== KEY_INFO_ENABLED
)
906 key_material
->key_param_set
.key_info
=
907 cpu_to_le16(KEY_ENABLED
);
909 key_material
->key_param_set
.key_info
=
910 cpu_to_le16(!KEY_ENABLED
);
912 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
913 /* AES pairwise key: unicast */
914 key_material
->key_param_set
.key_info
|=
915 cpu_to_le16(KEY_UNICAST
);
916 else /* AES group key: multicast */
917 key_material
->key_param_set
.key_info
|=
918 cpu_to_le16(KEY_MCAST
);
920 } else if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
921 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: WPA_TKIP\n");
922 key_material
->key_param_set
.key_type_id
=
923 cpu_to_le16(KEY_TYPE_ID_TKIP
);
924 key_material
->key_param_set
.key_info
=
925 cpu_to_le16(KEY_ENABLED
);
927 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
928 /* TKIP pairwise key: unicast */
929 key_material
->key_param_set
.key_info
|=
930 cpu_to_le16(KEY_UNICAST
);
931 else /* TKIP group key: multicast */
932 key_material
->key_param_set
.key_info
|=
933 cpu_to_le16(KEY_MCAST
);
936 if (key_material
->key_param_set
.key_type_id
) {
937 key_material
->key_param_set
.type
=
938 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
939 key_material
->key_param_set
.key_len
=
940 cpu_to_le16((u16
) enc_key
->key_len
);
941 memcpy(key_material
->key_param_set
.key
, enc_key
->key_material
,
943 key_material
->key_param_set
.length
=
944 cpu_to_le16((u16
) enc_key
->key_len
+
945 KEYPARAMSET_FIXED_LEN
);
947 key_param_len
= (u16
)(enc_key
->key_len
+ KEYPARAMSET_FIXED_LEN
)
948 + sizeof(struct mwifiex_ie_types_header
);
950 if (le16_to_cpu(key_material
->key_param_set
.key_type_id
) ==
951 KEY_TYPE_ID_AES_CMAC
) {
952 struct mwifiex_cmac_param
*param
=
953 (void *)key_material
->key_param_set
.key
;
955 memcpy(param
->ipn
, enc_key
->pn
, IGTK_PN_LEN
);
956 memcpy(param
->key
, enc_key
->key_material
,
957 WLAN_KEY_LEN_AES_CMAC
);
959 key_param_len
= sizeof(struct mwifiex_cmac_param
);
960 key_material
->key_param_set
.key_len
=
961 cpu_to_le16(key_param_len
);
962 key_param_len
+= KEYPARAMSET_FIXED_LEN
;
963 key_material
->key_param_set
.length
=
964 cpu_to_le16(key_param_len
);
965 key_param_len
+= sizeof(struct mwifiex_ie_types_header
);
968 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
971 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
972 tlv_mac
= (void *)((u8
*)&key_material
->key_param_set
+
974 tlv_mac
->header
.type
=
975 cpu_to_le16(TLV_TYPE_STA_MAC_ADDR
);
976 tlv_mac
->header
.len
= cpu_to_le16(ETH_ALEN
);
977 memcpy(tlv_mac
->mac_addr
, enc_key
->mac_addr
, ETH_ALEN
);
978 cmd_size
= key_param_len
+ S_DS_GEN
+
979 sizeof(key_material
->action
) +
980 sizeof(struct host_cmd_tlv_mac_addr
);
982 cmd_size
= key_param_len
+ S_DS_GEN
+
983 sizeof(key_material
->action
);
985 cmd
->size
= cpu_to_le16(cmd_size
);
991 /* Wrapper function for setting network key depending upon FW KEY API version */
993 mwifiex_cmd_802_11_key_material(struct mwifiex_private
*priv
,
994 struct host_cmd_ds_command
*cmd
,
995 u16 cmd_action
, u32 cmd_oid
,
996 struct mwifiex_ds_encrypt_key
*enc_key
)
998 if (priv
->adapter
->key_api_major_ver
== KEY_API_VER_MAJOR_V2
)
999 return mwifiex_cmd_802_11_key_material_v2(priv
, cmd
,
1000 cmd_action
, cmd_oid
,
1004 return mwifiex_cmd_802_11_key_material_v1(priv
, cmd
,
1005 cmd_action
, cmd_oid
,
1010 * This function prepares command to set/get 11d domain information.
1012 * Preparation includes -
1013 * - Setting command ID, action and proper size
1014 * - Setting domain information fields (for SET only)
1015 * - Ensuring correct endian-ness
1017 static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private
*priv
,
1018 struct host_cmd_ds_command
*cmd
,
1021 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1022 struct host_cmd_ds_802_11d_domain_info
*domain_info
=
1023 &cmd
->params
.domain_info
;
1024 struct mwifiex_ietypes_domain_param_set
*domain
=
1025 &domain_info
->domain
;
1026 u8 no_of_triplet
= adapter
->domain_reg
.no_of_triplet
;
1028 mwifiex_dbg(adapter
, INFO
,
1029 "info: 11D: no_of_triplet=0x%x\n", no_of_triplet
);
1031 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO
);
1032 domain_info
->action
= cpu_to_le16(cmd_action
);
1033 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
1034 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1038 /* Set domain info fields */
1039 domain
->header
.type
= cpu_to_le16(WLAN_EID_COUNTRY
);
1040 memcpy(domain
->country_code
, adapter
->domain_reg
.country_code
,
1041 sizeof(domain
->country_code
));
1043 domain
->header
.len
=
1044 cpu_to_le16((no_of_triplet
*
1045 sizeof(struct ieee80211_country_ie_triplet
))
1046 + sizeof(domain
->country_code
));
1048 if (no_of_triplet
) {
1049 memcpy(domain
->triplet
, adapter
->domain_reg
.triplet
,
1050 no_of_triplet
* sizeof(struct
1051 ieee80211_country_ie_triplet
));
1053 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) +
1054 le16_to_cpu(domain
->header
.len
) +
1055 sizeof(struct mwifiex_ie_types_header
)
1058 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1065 * This function prepares command to set/get IBSS coalescing status.
1067 * Preparation includes -
1068 * - Setting command ID, action and proper size
1069 * - Setting status to enable or disable (for SET only)
1070 * - Ensuring correct endian-ness
1072 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command
*cmd
,
1073 u16 cmd_action
, u16
*enable
)
1075 struct host_cmd_ds_802_11_ibss_status
*ibss_coal
=
1076 &(cmd
->params
.ibss_coalescing
);
1078 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
);
1079 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status
) +
1082 ibss_coal
->action
= cpu_to_le16(cmd_action
);
1084 switch (cmd_action
) {
1085 case HostCmd_ACT_GEN_SET
:
1087 ibss_coal
->enable
= cpu_to_le16(*enable
);
1089 ibss_coal
->enable
= 0;
1092 /* In other case.. Nothing to do */
1093 case HostCmd_ACT_GEN_GET
:
1101 /* This function prepares command buffer to get/set memory location value.
1104 mwifiex_cmd_mem_access(struct host_cmd_ds_command
*cmd
, u16 cmd_action
,
1107 struct mwifiex_ds_mem_rw
*mem_rw
= (void *)pdata_buf
;
1108 struct host_cmd_ds_mem_access
*mem_access
= (void *)&cmd
->params
.mem
;
1110 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEM_ACCESS
);
1111 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mem_access
) +
1114 mem_access
->action
= cpu_to_le16(cmd_action
);
1115 mem_access
->addr
= cpu_to_le32(mem_rw
->addr
);
1116 mem_access
->value
= cpu_to_le32(mem_rw
->value
);
1122 * This function prepares command to set/get register value.
1124 * Preparation includes -
1125 * - Setting command ID, action and proper size
1126 * - Setting register offset (for both GET and SET) and
1127 * register value (for SET only)
1128 * - Ensuring correct endian-ness
1130 * The following type of registers can be accessed with this function -
1138 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command
*cmd
,
1139 u16 cmd_action
, void *data_buf
)
1141 struct mwifiex_ds_reg_rw
*reg_rw
= data_buf
;
1143 switch (le16_to_cpu(cmd
->command
)) {
1144 case HostCmd_CMD_MAC_REG_ACCESS
:
1146 struct host_cmd_ds_mac_reg_access
*mac_reg
;
1148 cmd
->size
= cpu_to_le16(sizeof(*mac_reg
) + S_DS_GEN
);
1149 mac_reg
= &cmd
->params
.mac_reg
;
1150 mac_reg
->action
= cpu_to_le16(cmd_action
);
1151 mac_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1152 mac_reg
->value
= cpu_to_le32(reg_rw
->value
);
1155 case HostCmd_CMD_BBP_REG_ACCESS
:
1157 struct host_cmd_ds_bbp_reg_access
*bbp_reg
;
1159 cmd
->size
= cpu_to_le16(sizeof(*bbp_reg
) + S_DS_GEN
);
1160 bbp_reg
= &cmd
->params
.bbp_reg
;
1161 bbp_reg
->action
= cpu_to_le16(cmd_action
);
1162 bbp_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1163 bbp_reg
->value
= (u8
) reg_rw
->value
;
1166 case HostCmd_CMD_RF_REG_ACCESS
:
1168 struct host_cmd_ds_rf_reg_access
*rf_reg
;
1170 cmd
->size
= cpu_to_le16(sizeof(*rf_reg
) + S_DS_GEN
);
1171 rf_reg
= &cmd
->params
.rf_reg
;
1172 rf_reg
->action
= cpu_to_le16(cmd_action
);
1173 rf_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1174 rf_reg
->value
= (u8
) reg_rw
->value
;
1177 case HostCmd_CMD_PMIC_REG_ACCESS
:
1179 struct host_cmd_ds_pmic_reg_access
*pmic_reg
;
1181 cmd
->size
= cpu_to_le16(sizeof(*pmic_reg
) + S_DS_GEN
);
1182 pmic_reg
= &cmd
->params
.pmic_reg
;
1183 pmic_reg
->action
= cpu_to_le16(cmd_action
);
1184 pmic_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1185 pmic_reg
->value
= (u8
) reg_rw
->value
;
1188 case HostCmd_CMD_CAU_REG_ACCESS
:
1190 struct host_cmd_ds_rf_reg_access
*cau_reg
;
1192 cmd
->size
= cpu_to_le16(sizeof(*cau_reg
) + S_DS_GEN
);
1193 cau_reg
= &cmd
->params
.rf_reg
;
1194 cau_reg
->action
= cpu_to_le16(cmd_action
);
1195 cau_reg
->offset
= cpu_to_le16((u16
) reg_rw
->offset
);
1196 cau_reg
->value
= (u8
) reg_rw
->value
;
1199 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1201 struct mwifiex_ds_read_eeprom
*rd_eeprom
= data_buf
;
1202 struct host_cmd_ds_802_11_eeprom_access
*cmd_eeprom
=
1203 &cmd
->params
.eeprom
;
1205 cmd
->size
= cpu_to_le16(sizeof(*cmd_eeprom
) + S_DS_GEN
);
1206 cmd_eeprom
->action
= cpu_to_le16(cmd_action
);
1207 cmd_eeprom
->offset
= cpu_to_le16(rd_eeprom
->offset
);
1208 cmd_eeprom
->byte_count
= cpu_to_le16(rd_eeprom
->byte_count
);
1209 cmd_eeprom
->value
= 0;
1220 * This function prepares command to set PCI-Express
1221 * host buffer configuration
1223 * Preparation includes -
1224 * - Setting command ID, action and proper size
1225 * - Setting host buffer configuration
1226 * - Ensuring correct endian-ness
1229 mwifiex_cmd_pcie_host_spec(struct mwifiex_private
*priv
,
1230 struct host_cmd_ds_command
*cmd
, u16 action
)
1232 struct host_cmd_ds_pcie_details
*host_spec
=
1233 &cmd
->params
.pcie_host_spec
;
1234 struct pcie_service_card
*card
= priv
->adapter
->card
;
1236 cmd
->command
= cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS
);
1237 cmd
->size
= cpu_to_le16(sizeof(struct
1238 host_cmd_ds_pcie_details
) + S_DS_GEN
);
1241 memset(host_spec
, 0, sizeof(struct host_cmd_ds_pcie_details
));
1243 if (action
!= HostCmd_ACT_GEN_SET
)
1246 /* Send the ring base addresses and count to firmware */
1247 host_spec
->txbd_addr_lo
= (u32
)(card
->txbd_ring_pbase
);
1248 host_spec
->txbd_addr_hi
= (u32
)(((u64
)card
->txbd_ring_pbase
)>>32);
1249 host_spec
->txbd_count
= MWIFIEX_MAX_TXRX_BD
;
1250 host_spec
->rxbd_addr_lo
= (u32
)(card
->rxbd_ring_pbase
);
1251 host_spec
->rxbd_addr_hi
= (u32
)(((u64
)card
->rxbd_ring_pbase
)>>32);
1252 host_spec
->rxbd_count
= MWIFIEX_MAX_TXRX_BD
;
1253 host_spec
->evtbd_addr_lo
= (u32
)(card
->evtbd_ring_pbase
);
1254 host_spec
->evtbd_addr_hi
= (u32
)(((u64
)card
->evtbd_ring_pbase
)>>32);
1255 host_spec
->evtbd_count
= MWIFIEX_MAX_EVT_BD
;
1256 if (card
->sleep_cookie_vbase
) {
1257 host_spec
->sleep_cookie_addr_lo
=
1258 (u32
)(card
->sleep_cookie_pbase
);
1259 host_spec
->sleep_cookie_addr_hi
=
1260 (u32
)(((u64
)(card
->sleep_cookie_pbase
)) >> 32);
1261 mwifiex_dbg(priv
->adapter
, INFO
,
1262 "sleep_cook_lo phy addr: 0x%x\n",
1263 host_spec
->sleep_cookie_addr_lo
);
1270 * This function prepares command for event subscription, configuration
1271 * and query. Events can be subscribed or unsubscribed. Current subscribed
1272 * events can be queried. Also, current subscribed events are reported in
1273 * every FW response.
1276 mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private
*priv
,
1277 struct host_cmd_ds_command
*cmd
,
1278 struct mwifiex_ds_misc_subsc_evt
*subsc_evt_cfg
)
1280 struct host_cmd_ds_802_11_subsc_evt
*subsc_evt
= &cmd
->params
.subsc_evt
;
1281 struct mwifiex_ie_types_rssi_threshold
*rssi_tlv
;
1285 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT
);
1286 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt
) +
1289 subsc_evt
->action
= cpu_to_le16(subsc_evt_cfg
->action
);
1290 mwifiex_dbg(priv
->adapter
, CMD
,
1291 "cmd: action: %d\n", subsc_evt_cfg
->action
);
1293 /*For query requests, no configuration TLV structures are to be added.*/
1294 if (subsc_evt_cfg
->action
== HostCmd_ACT_GEN_GET
)
1297 subsc_evt
->events
= cpu_to_le16(subsc_evt_cfg
->events
);
1299 event_bitmap
= subsc_evt_cfg
->events
;
1300 mwifiex_dbg(priv
->adapter
, CMD
, "cmd: event bitmap : %16x\n",
1303 if (((subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
) ||
1304 (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_SET
)) &&
1305 (event_bitmap
== 0)) {
1306 mwifiex_dbg(priv
->adapter
, ERROR
,
1307 "Error: No event specified\t"
1308 "for bitwise action type\n");
1313 * Append TLV structures for each of the specified events for
1314 * subscribing or re-configuring. This is not required for
1315 * bitwise unsubscribing request.
1317 if (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
)
1320 pos
= ((u8
*)subsc_evt
) +
1321 sizeof(struct host_cmd_ds_802_11_subsc_evt
);
1323 if (event_bitmap
& BITMASK_BCN_RSSI_LOW
) {
1324 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1326 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_LOW
);
1327 rssi_tlv
->header
.len
=
1328 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1329 sizeof(struct mwifiex_ie_types_header
));
1330 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
;
1331 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
;
1333 mwifiex_dbg(priv
->adapter
, EVENT
,
1334 "Cfg Beacon Low Rssi event,\t"
1335 "RSSI:-%d dBm, Freq:%d\n",
1336 subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
,
1337 subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
);
1339 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1340 le16_add_cpu(&cmd
->size
,
1341 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1344 if (event_bitmap
& BITMASK_BCN_RSSI_HIGH
) {
1345 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1347 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_HIGH
);
1348 rssi_tlv
->header
.len
=
1349 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1350 sizeof(struct mwifiex_ie_types_header
));
1351 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
;
1352 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
;
1354 mwifiex_dbg(priv
->adapter
, EVENT
,
1355 "Cfg Beacon High Rssi event,\t"
1356 "RSSI:-%d dBm, Freq:%d\n",
1357 subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
,
1358 subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
);
1360 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1361 le16_add_cpu(&cmd
->size
,
1362 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1369 mwifiex_cmd_append_rpn_expression(struct mwifiex_private
*priv
,
1370 struct mwifiex_mef_entry
*mef_entry
,
1373 struct mwifiex_mef_filter
*filter
= mef_entry
->filter
;
1375 u8
*stack_ptr
= *buffer
;
1377 for (i
= 0; i
< MWIFIEX_MEF_MAX_FILTERS
; i
++) {
1378 filter
= &mef_entry
->filter
[i
];
1379 if (!filter
->filt_type
)
1381 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->repeat
);
1383 *stack_ptr
= TYPE_DNUM
;
1386 byte_len
= filter
->byte_seq
[MWIFIEX_MEF_MAX_BYTESEQ
];
1387 memcpy(stack_ptr
, filter
->byte_seq
, byte_len
);
1388 stack_ptr
+= byte_len
;
1389 *stack_ptr
= byte_len
;
1391 *stack_ptr
= TYPE_BYTESEQ
;
1394 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->offset
);
1396 *stack_ptr
= TYPE_DNUM
;
1399 *stack_ptr
= filter
->filt_type
;
1402 if (filter
->filt_action
) {
1403 *stack_ptr
= filter
->filt_action
;
1407 if (stack_ptr
- *buffer
> STACK_NBYTES
)
1411 *buffer
= stack_ptr
;
1416 mwifiex_cmd_mef_cfg(struct mwifiex_private
*priv
,
1417 struct host_cmd_ds_command
*cmd
,
1418 struct mwifiex_ds_mef_cfg
*mef
)
1420 struct host_cmd_ds_mef_cfg
*mef_cfg
= &cmd
->params
.mef_cfg
;
1421 struct mwifiex_fw_mef_entry
*mef_entry
= NULL
;
1422 u8
*pos
= (u8
*)mef_cfg
;
1425 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEF_CFG
);
1427 mef_cfg
->criteria
= cpu_to_le32(mef
->criteria
);
1428 mef_cfg
->num_entries
= cpu_to_le16(mef
->num_entries
);
1429 pos
+= sizeof(*mef_cfg
);
1431 for (i
= 0; i
< mef
->num_entries
; i
++) {
1432 mef_entry
= (struct mwifiex_fw_mef_entry
*)pos
;
1433 mef_entry
->mode
= mef
->mef_entry
[i
].mode
;
1434 mef_entry
->action
= mef
->mef_entry
[i
].action
;
1435 pos
+= sizeof(*mef_cfg
->mef_entry
);
1437 if (mwifiex_cmd_append_rpn_expression(priv
,
1438 &mef
->mef_entry
[i
], &pos
))
1441 mef_entry
->exprsize
=
1442 cpu_to_le16(pos
- mef_entry
->expr
);
1444 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*)mef_cfg
) + S_DS_GEN
);
1449 /* This function parse cal data from ASCII to hex */
1450 static u32
mwifiex_parse_cal_cfg(u8
*src
, size_t len
, u8
*dst
)
1452 u8
*s
= src
, *d
= dst
;
1454 while (s
- src
< len
) {
1455 if (*s
&& (isspace(*s
) || *s
== '\t')) {
1460 *d
++ = simple_strtol(s
, NULL
, 16);
1470 int mwifiex_dnld_dt_cfgdata(struct mwifiex_private
*priv
,
1471 struct device_node
*node
, const char *prefix
)
1474 struct property
*prop
;
1475 size_t len
= strlen(prefix
);
1478 /* look for all matching property names */
1479 for_each_property_of_node(node
, prop
) {
1480 if (len
> strlen(prop
->name
) ||
1481 strncmp(prop
->name
, prefix
, len
))
1484 /* property header is 6 bytes, data must fit in cmd buffer */
1485 if (prop
&& prop
->value
&& prop
->length
> 6 &&
1486 prop
->length
<= MWIFIEX_SIZE_OF_CMD_BUFFER
- S_DS_GEN
) {
1487 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
1488 HostCmd_ACT_GEN_SET
, 0,
1498 /* This function prepares command of set_cfg_data. */
1499 static int mwifiex_cmd_cfg_data(struct mwifiex_private
*priv
,
1500 struct host_cmd_ds_command
*cmd
, void *data_buf
)
1502 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1503 struct property
*prop
= data_buf
;
1505 u8
*data
= (u8
*)cmd
+ S_DS_GEN
;
1510 ret
= of_property_read_u8_array(adapter
->dt_node
, prop
->name
,
1514 mwifiex_dbg(adapter
, INFO
,
1515 "download cfg_data from device tree: %s\n",
1517 } else if (adapter
->cal_data
->data
&& adapter
->cal_data
->size
> 0) {
1518 len
= mwifiex_parse_cal_cfg((u8
*)adapter
->cal_data
->data
,
1519 adapter
->cal_data
->size
, data
);
1520 mwifiex_dbg(adapter
, INFO
,
1521 "download cfg_data from config file\n");
1526 cmd
->command
= cpu_to_le16(HostCmd_CMD_CFG_DATA
);
1527 cmd
->size
= cpu_to_le16(S_DS_GEN
+ len
);
1533 mwifiex_cmd_set_mc_policy(struct mwifiex_private
*priv
,
1534 struct host_cmd_ds_command
*cmd
,
1535 u16 cmd_action
, void *data_buf
)
1537 struct host_cmd_ds_multi_chan_policy
*mc_pol
= &cmd
->params
.mc_policy
;
1538 const u16
*drcs_info
= data_buf
;
1540 mc_pol
->action
= cpu_to_le16(cmd_action
);
1541 mc_pol
->policy
= cpu_to_le16(*drcs_info
);
1542 cmd
->command
= cpu_to_le16(HostCmd_CMD_MC_POLICY
);
1543 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy
) +
1548 static int mwifiex_cmd_robust_coex(struct mwifiex_private
*priv
,
1549 struct host_cmd_ds_command
*cmd
,
1550 u16 cmd_action
, bool *is_timeshare
)
1552 struct host_cmd_ds_robust_coex
*coex
= &cmd
->params
.coex
;
1553 struct mwifiex_ie_types_robust_coex
*coex_tlv
;
1555 cmd
->command
= cpu_to_le16(HostCmd_CMD_ROBUST_COEX
);
1556 cmd
->size
= cpu_to_le16(sizeof(*coex
) + sizeof(*coex_tlv
) + S_DS_GEN
);
1558 coex
->action
= cpu_to_le16(cmd_action
);
1559 coex_tlv
= (struct mwifiex_ie_types_robust_coex
*)
1560 ((u8
*)coex
+ sizeof(*coex
));
1561 coex_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_ROBUST_COEX
);
1562 coex_tlv
->header
.len
= cpu_to_le16(sizeof(coex_tlv
->mode
));
1564 if (coex
->action
== HostCmd_ACT_GEN_GET
)
1568 coex_tlv
->mode
= cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE
);
1570 coex_tlv
->mode
= cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL
);
1575 static int mwifiex_cmd_gtk_rekey_offload(struct mwifiex_private
*priv
,
1576 struct host_cmd_ds_command
*cmd
,
1578 struct cfg80211_gtk_rekey_data
*data
)
1580 struct host_cmd_ds_gtk_rekey_params
*rekey
= &cmd
->params
.rekey
;
1583 cmd
->command
= cpu_to_le16(HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG
);
1584 cmd
->size
= cpu_to_le16(sizeof(*rekey
) + S_DS_GEN
);
1586 rekey
->action
= cpu_to_le16(cmd_action
);
1587 if (cmd_action
== HostCmd_ACT_GEN_SET
) {
1588 memcpy(rekey
->kek
, data
->kek
, NL80211_KEK_LEN
);
1589 memcpy(rekey
->kck
, data
->kck
, NL80211_KCK_LEN
);
1590 rekey_ctr
= be64_to_cpup((__be64
*)data
->replay_ctr
);
1591 rekey
->replay_ctr_low
= cpu_to_le32((u32
)rekey_ctr
);
1592 rekey
->replay_ctr_high
=
1593 cpu_to_le32((u32
)((u64
)rekey_ctr
>> 32));
1600 mwifiex_cmd_coalesce_cfg(struct mwifiex_private
*priv
,
1601 struct host_cmd_ds_command
*cmd
,
1602 u16 cmd_action
, void *data_buf
)
1604 struct host_cmd_ds_coalesce_cfg
*coalesce_cfg
=
1605 &cmd
->params
.coalesce_cfg
;
1606 struct mwifiex_ds_coalesce_cfg
*cfg
= data_buf
;
1607 struct coalesce_filt_field_param
*param
;
1608 u16 cnt
, idx
, length
;
1609 struct coalesce_receive_filt_rule
*rule
;
1611 cmd
->command
= cpu_to_le16(HostCmd_CMD_COALESCE_CFG
);
1612 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1614 coalesce_cfg
->action
= cpu_to_le16(cmd_action
);
1615 coalesce_cfg
->num_of_rules
= cpu_to_le16(cfg
->num_of_rules
);
1616 rule
= coalesce_cfg
->rule
;
1618 for (cnt
= 0; cnt
< cfg
->num_of_rules
; cnt
++) {
1619 rule
->header
.type
= cpu_to_le16(TLV_TYPE_COALESCE_RULE
);
1620 rule
->max_coalescing_delay
=
1621 cpu_to_le16(cfg
->rule
[cnt
].max_coalescing_delay
);
1622 rule
->pkt_type
= cfg
->rule
[cnt
].pkt_type
;
1623 rule
->num_of_fields
= cfg
->rule
[cnt
].num_of_fields
;
1627 param
= rule
->params
;
1628 for (idx
= 0; idx
< cfg
->rule
[cnt
].num_of_fields
; idx
++) {
1629 param
->operation
= cfg
->rule
[cnt
].params
[idx
].operation
;
1630 param
->operand_len
=
1631 cfg
->rule
[cnt
].params
[idx
].operand_len
;
1633 cpu_to_le16(cfg
->rule
[cnt
].params
[idx
].offset
);
1634 memcpy(param
->operand_byte_stream
,
1635 cfg
->rule
[cnt
].params
[idx
].operand_byte_stream
,
1636 param
->operand_len
);
1638 length
+= sizeof(struct coalesce_filt_field_param
);
1643 /* Total rule length is sizeof max_coalescing_delay(u16),
1644 * num_of_fields(u8), pkt_type(u8) and total length of the all
1647 rule
->header
.len
= cpu_to_le16(length
+ sizeof(u16
) +
1648 sizeof(u8
) + sizeof(u8
));
1650 /* Add the rule length to the command size*/
1651 le16_add_cpu(&cmd
->size
, le16_to_cpu(rule
->header
.len
) +
1652 sizeof(struct mwifiex_ie_types_header
));
1654 rule
= (void *)((u8
*)rule
->params
+ length
);
1657 /* Add sizeof action, num_of_rules to total command length */
1658 le16_add_cpu(&cmd
->size
, sizeof(u16
) + sizeof(u16
));
1664 mwifiex_cmd_tdls_config(struct mwifiex_private
*priv
,
1665 struct host_cmd_ds_command
*cmd
,
1666 u16 cmd_action
, void *data_buf
)
1668 struct host_cmd_ds_tdls_config
*tdls_config
= &cmd
->params
.tdls_config
;
1669 struct mwifiex_tdls_init_cs_params
*config
;
1670 struct mwifiex_tdls_config
*init_config
;
1673 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_CONFIG
);
1674 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1675 tdls_config
->tdls_action
= cpu_to_le16(cmd_action
);
1676 le16_add_cpu(&cmd
->size
, sizeof(tdls_config
->tdls_action
));
1678 switch (cmd_action
) {
1679 case ACT_TDLS_CS_ENABLE_CONFIG
:
1680 init_config
= data_buf
;
1681 len
= sizeof(*init_config
);
1682 memcpy(tdls_config
->tdls_data
, init_config
, len
);
1684 case ACT_TDLS_CS_INIT
:
1686 len
= sizeof(*config
);
1687 memcpy(tdls_config
->tdls_data
, config
, len
);
1689 case ACT_TDLS_CS_STOP
:
1690 len
= sizeof(struct mwifiex_tdls_stop_cs_params
);
1691 memcpy(tdls_config
->tdls_data
, data_buf
, len
);
1693 case ACT_TDLS_CS_PARAMS
:
1694 len
= sizeof(struct mwifiex_tdls_config_cs_params
);
1695 memcpy(tdls_config
->tdls_data
, data_buf
, len
);
1698 mwifiex_dbg(priv
->adapter
, ERROR
,
1699 "Unknown TDLS configuration\n");
1703 le16_add_cpu(&cmd
->size
, len
);
1708 mwifiex_cmd_tdls_oper(struct mwifiex_private
*priv
,
1709 struct host_cmd_ds_command
*cmd
,
1712 struct host_cmd_ds_tdls_oper
*tdls_oper
= &cmd
->params
.tdls_oper
;
1713 struct mwifiex_ds_tdls_oper
*oper
= data_buf
;
1714 struct mwifiex_sta_node
*sta_ptr
;
1715 struct host_cmd_tlv_rates
*tlv_rates
;
1716 struct mwifiex_ie_types_htcap
*ht_capab
;
1717 struct mwifiex_ie_types_qos_info
*wmm_qos_info
;
1718 struct mwifiex_ie_types_extcap
*extcap
;
1719 struct mwifiex_ie_types_vhtcap
*vht_capab
;
1720 struct mwifiex_ie_types_aid
*aid
;
1721 struct mwifiex_ie_types_tdls_idle_timeout
*timeout
;
1724 struct station_parameters
*params
= priv
->sta_params
;
1726 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_OPER
);
1727 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1728 le16_add_cpu(&cmd
->size
, sizeof(struct host_cmd_ds_tdls_oper
));
1730 tdls_oper
->reason
= 0;
1731 memcpy(tdls_oper
->peer_mac
, oper
->peer_mac
, ETH_ALEN
);
1732 sta_ptr
= mwifiex_get_sta_entry(priv
, oper
->peer_mac
);
1734 pos
= (u8
*)tdls_oper
+ sizeof(struct host_cmd_ds_tdls_oper
);
1736 switch (oper
->tdls_action
) {
1737 case MWIFIEX_TDLS_DISABLE_LINK
:
1738 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_DELETE
);
1740 case MWIFIEX_TDLS_CREATE_LINK
:
1741 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CREATE
);
1743 case MWIFIEX_TDLS_CONFIG_LINK
:
1744 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CONFIG
);
1747 mwifiex_dbg(priv
->adapter
, ERROR
,
1748 "TDLS config params not available for %pM\n",
1753 *(__le16
*)pos
= cpu_to_le16(params
->capability
);
1754 config_len
+= sizeof(params
->capability
);
1756 qos_info
= params
->uapsd_queues
| (params
->max_sp
<< 5);
1757 wmm_qos_info
= (struct mwifiex_ie_types_qos_info
*)(pos
+
1759 wmm_qos_info
->header
.type
= cpu_to_le16(WLAN_EID_QOS_CAPA
);
1760 wmm_qos_info
->header
.len
= cpu_to_le16(sizeof(qos_info
));
1761 wmm_qos_info
->qos_info
= qos_info
;
1762 config_len
+= sizeof(struct mwifiex_ie_types_qos_info
);
1764 if (params
->ht_capa
) {
1765 ht_capab
= (struct mwifiex_ie_types_htcap
*)(pos
+
1767 ht_capab
->header
.type
=
1768 cpu_to_le16(WLAN_EID_HT_CAPABILITY
);
1769 ht_capab
->header
.len
=
1770 cpu_to_le16(sizeof(struct ieee80211_ht_cap
));
1771 memcpy(&ht_capab
->ht_cap
, params
->ht_capa
,
1772 sizeof(struct ieee80211_ht_cap
));
1773 config_len
+= sizeof(struct mwifiex_ie_types_htcap
);
1776 if (params
->supported_rates
&& params
->supported_rates_len
) {
1777 tlv_rates
= (struct host_cmd_tlv_rates
*)(pos
+
1779 tlv_rates
->header
.type
=
1780 cpu_to_le16(WLAN_EID_SUPP_RATES
);
1781 tlv_rates
->header
.len
=
1782 cpu_to_le16(params
->supported_rates_len
);
1783 memcpy(tlv_rates
->rates
, params
->supported_rates
,
1784 params
->supported_rates_len
);
1785 config_len
+= sizeof(struct host_cmd_tlv_rates
) +
1786 params
->supported_rates_len
;
1789 if (params
->ext_capab
&& params
->ext_capab_len
) {
1790 extcap
= (struct mwifiex_ie_types_extcap
*)(pos
+
1792 extcap
->header
.type
=
1793 cpu_to_le16(WLAN_EID_EXT_CAPABILITY
);
1794 extcap
->header
.len
= cpu_to_le16(params
->ext_capab_len
);
1795 memcpy(extcap
->ext_capab
, params
->ext_capab
,
1796 params
->ext_capab_len
);
1797 config_len
+= sizeof(struct mwifiex_ie_types_extcap
) +
1798 params
->ext_capab_len
;
1800 if (params
->vht_capa
) {
1801 vht_capab
= (struct mwifiex_ie_types_vhtcap
*)(pos
+
1803 vht_capab
->header
.type
=
1804 cpu_to_le16(WLAN_EID_VHT_CAPABILITY
);
1805 vht_capab
->header
.len
=
1806 cpu_to_le16(sizeof(struct ieee80211_vht_cap
));
1807 memcpy(&vht_capab
->vht_cap
, params
->vht_capa
,
1808 sizeof(struct ieee80211_vht_cap
));
1809 config_len
+= sizeof(struct mwifiex_ie_types_vhtcap
);
1812 aid
= (struct mwifiex_ie_types_aid
*)(pos
+ config_len
);
1813 aid
->header
.type
= cpu_to_le16(WLAN_EID_AID
);
1814 aid
->header
.len
= cpu_to_le16(sizeof(params
->aid
));
1815 aid
->aid
= cpu_to_le16(params
->aid
);
1816 config_len
+= sizeof(struct mwifiex_ie_types_aid
);
1819 timeout
= (void *)(pos
+ config_len
);
1820 timeout
->header
.type
= cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT
);
1821 timeout
->header
.len
= cpu_to_le16(sizeof(timeout
->value
));
1822 timeout
->value
= cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC
);
1823 config_len
+= sizeof(struct mwifiex_ie_types_tdls_idle_timeout
);
1827 mwifiex_dbg(priv
->adapter
, ERROR
, "Unknown TDLS operation\n");
1831 le16_add_cpu(&cmd
->size
, config_len
);
1836 /* This function prepares command of sdio rx aggr info. */
1837 static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command
*cmd
,
1838 u16 cmd_action
, void *data_buf
)
1840 struct host_cmd_sdio_sp_rx_aggr_cfg
*cfg
=
1841 &cmd
->params
.sdio_rx_aggr_cfg
;
1843 cmd
->command
= cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
);
1845 cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg
) +
1847 cfg
->action
= cmd_action
;
1848 if (cmd_action
== HostCmd_ACT_GEN_SET
)
1849 cfg
->enable
= *(u8
*)data_buf
;
1854 /* This function prepares command to get HS wakeup reason.
1856 * Preparation includes -
1857 * - Setting command ID, action and proper size
1858 * - Ensuring correct endian-ness
1860 static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private
*priv
,
1861 struct host_cmd_ds_command
*cmd
)
1863 cmd
->command
= cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON
);
1864 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason
) +
1871 * This function prepares the commands before sending them to the firmware.
1873 * This is a generic function which calls specific command preparation
1874 * routines based upon the command number.
1876 int mwifiex_sta_prepare_cmd(struct mwifiex_private
*priv
, uint16_t cmd_no
,
1877 u16 cmd_action
, u32 cmd_oid
,
1878 void *data_buf
, void *cmd_buf
)
1880 struct host_cmd_ds_command
*cmd_ptr
= cmd_buf
;
1883 /* Prepare command */
1885 case HostCmd_CMD_GET_HW_SPEC
:
1886 ret
= mwifiex_cmd_get_hw_spec(priv
, cmd_ptr
);
1888 case HostCmd_CMD_CFG_DATA
:
1889 ret
= mwifiex_cmd_cfg_data(priv
, cmd_ptr
, data_buf
);
1891 case HostCmd_CMD_MAC_CONTROL
:
1892 ret
= mwifiex_cmd_mac_control(priv
, cmd_ptr
, cmd_action
,
1895 case HostCmd_CMD_802_11_MAC_ADDRESS
:
1896 ret
= mwifiex_cmd_802_11_mac_address(priv
, cmd_ptr
,
1899 case HostCmd_CMD_MAC_MULTICAST_ADR
:
1900 ret
= mwifiex_cmd_mac_multicast_adr(cmd_ptr
, cmd_action
,
1903 case HostCmd_CMD_TX_RATE_CFG
:
1904 ret
= mwifiex_cmd_tx_rate_cfg(priv
, cmd_ptr
, cmd_action
,
1907 case HostCmd_CMD_TXPWR_CFG
:
1908 ret
= mwifiex_cmd_tx_power_cfg(cmd_ptr
, cmd_action
,
1911 case HostCmd_CMD_RF_TX_PWR
:
1912 ret
= mwifiex_cmd_rf_tx_power(priv
, cmd_ptr
, cmd_action
,
1915 case HostCmd_CMD_RF_ANTENNA
:
1916 ret
= mwifiex_cmd_rf_antenna(priv
, cmd_ptr
, cmd_action
,
1919 case HostCmd_CMD_802_11_PS_MODE_ENH
:
1920 ret
= mwifiex_cmd_enh_power_mode(priv
, cmd_ptr
, cmd_action
,
1921 (uint16_t)cmd_oid
, data_buf
);
1923 case HostCmd_CMD_802_11_HS_CFG_ENH
:
1924 ret
= mwifiex_cmd_802_11_hs_cfg(priv
, cmd_ptr
, cmd_action
,
1925 (struct mwifiex_hs_config_param
*) data_buf
);
1927 case HostCmd_CMD_802_11_SCAN
:
1928 ret
= mwifiex_cmd_802_11_scan(cmd_ptr
, data_buf
);
1930 case HostCmd_CMD_802_11_BG_SCAN_CONFIG
:
1931 ret
= mwifiex_cmd_802_11_bg_scan_config(priv
, cmd_ptr
,
1934 case HostCmd_CMD_802_11_BG_SCAN_QUERY
:
1935 ret
= mwifiex_cmd_802_11_bg_scan_query(cmd_ptr
);
1937 case HostCmd_CMD_802_11_ASSOCIATE
:
1938 ret
= mwifiex_cmd_802_11_associate(priv
, cmd_ptr
, data_buf
);
1940 case HostCmd_CMD_802_11_DEAUTHENTICATE
:
1941 ret
= mwifiex_cmd_802_11_deauthenticate(priv
, cmd_ptr
,
1944 case HostCmd_CMD_802_11_AD_HOC_START
:
1945 ret
= mwifiex_cmd_802_11_ad_hoc_start(priv
, cmd_ptr
,
1948 case HostCmd_CMD_802_11_GET_LOG
:
1949 ret
= mwifiex_cmd_802_11_get_log(cmd_ptr
);
1951 case HostCmd_CMD_802_11_AD_HOC_JOIN
:
1952 ret
= mwifiex_cmd_802_11_ad_hoc_join(priv
, cmd_ptr
,
1955 case HostCmd_CMD_802_11_AD_HOC_STOP
:
1956 ret
= mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr
);
1958 case HostCmd_CMD_RSSI_INFO
:
1959 ret
= mwifiex_cmd_802_11_rssi_info(priv
, cmd_ptr
, cmd_action
);
1961 case HostCmd_CMD_802_11_SNMP_MIB
:
1962 ret
= mwifiex_cmd_802_11_snmp_mib(priv
, cmd_ptr
, cmd_action
,
1965 case HostCmd_CMD_802_11_TX_RATE_QUERY
:
1967 cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY
);
1969 cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query
) +
1974 case HostCmd_CMD_VERSION_EXT
:
1975 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1976 cmd_ptr
->params
.verext
.version_str_sel
=
1977 (u8
) (*((u32
*) data_buf
));
1978 memcpy(&cmd_ptr
->params
, data_buf
,
1979 sizeof(struct host_cmd_ds_version_ext
));
1981 cpu_to_le16(sizeof(struct host_cmd_ds_version_ext
) +
1985 case HostCmd_CMD_MGMT_FRAME_REG
:
1986 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1987 cmd_ptr
->params
.reg_mask
.action
= cpu_to_le16(cmd_action
);
1988 cmd_ptr
->params
.reg_mask
.mask
= cpu_to_le32(*(u32
*)data_buf
);
1990 cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg
) +
1994 case HostCmd_CMD_REMAIN_ON_CHAN
:
1995 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1996 memcpy(&cmd_ptr
->params
, data_buf
,
1997 sizeof(struct host_cmd_ds_remain_on_chan
));
1999 cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan
) +
2002 case HostCmd_CMD_11AC_CFG
:
2003 ret
= mwifiex_cmd_11ac_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
2005 case HostCmd_CMD_P2P_MODE_CFG
:
2006 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2007 cmd_ptr
->params
.mode_cfg
.action
= cpu_to_le16(cmd_action
);
2008 cmd_ptr
->params
.mode_cfg
.mode
= cpu_to_le16(*(u16
*)data_buf
);
2010 cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg
) +
2013 case HostCmd_CMD_FUNC_INIT
:
2014 if (priv
->adapter
->hw_status
== MWIFIEX_HW_STATUS_RESET
)
2015 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_READY
;
2016 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2017 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
2019 case HostCmd_CMD_FUNC_SHUTDOWN
:
2020 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_RESET
;
2021 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2022 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
2024 case HostCmd_CMD_11N_ADDBA_REQ
:
2025 ret
= mwifiex_cmd_11n_addba_req(cmd_ptr
, data_buf
);
2027 case HostCmd_CMD_11N_DELBA
:
2028 ret
= mwifiex_cmd_11n_delba(cmd_ptr
, data_buf
);
2030 case HostCmd_CMD_11N_ADDBA_RSP
:
2031 ret
= mwifiex_cmd_11n_addba_rsp_gen(priv
, cmd_ptr
, data_buf
);
2033 case HostCmd_CMD_802_11_KEY_MATERIAL
:
2034 ret
= mwifiex_cmd_802_11_key_material(priv
, cmd_ptr
,
2035 cmd_action
, cmd_oid
,
2038 case HostCmd_CMD_802_11D_DOMAIN_INFO
:
2039 ret
= mwifiex_cmd_802_11d_domain_info(priv
, cmd_ptr
,
2042 case HostCmd_CMD_RECONFIGURE_TX_BUFF
:
2043 ret
= mwifiex_cmd_recfg_tx_buf(priv
, cmd_ptr
, cmd_action
,
2046 case HostCmd_CMD_AMSDU_AGGR_CTRL
:
2047 ret
= mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr
, cmd_action
,
2050 case HostCmd_CMD_11N_CFG
:
2051 ret
= mwifiex_cmd_11n_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
2053 case HostCmd_CMD_WMM_GET_STATUS
:
2054 mwifiex_dbg(priv
->adapter
, CMD
,
2055 "cmd: WMM: WMM_GET_STATUS cmd sent\n");
2056 cmd_ptr
->command
= cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS
);
2058 cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status
) +
2062 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
:
2063 ret
= mwifiex_cmd_ibss_coalescing_status(cmd_ptr
, cmd_action
,
2066 case HostCmd_CMD_802_11_SCAN_EXT
:
2067 ret
= mwifiex_cmd_802_11_scan_ext(priv
, cmd_ptr
, data_buf
);
2069 case HostCmd_CMD_MEM_ACCESS
:
2070 ret
= mwifiex_cmd_mem_access(cmd_ptr
, cmd_action
, data_buf
);
2072 case HostCmd_CMD_MAC_REG_ACCESS
:
2073 case HostCmd_CMD_BBP_REG_ACCESS
:
2074 case HostCmd_CMD_RF_REG_ACCESS
:
2075 case HostCmd_CMD_PMIC_REG_ACCESS
:
2076 case HostCmd_CMD_CAU_REG_ACCESS
:
2077 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
2078 ret
= mwifiex_cmd_reg_access(cmd_ptr
, cmd_action
, data_buf
);
2080 case HostCmd_CMD_SET_BSS_MODE
:
2081 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
2082 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
)
2083 cmd_ptr
->params
.bss_mode
.con_type
=
2084 CONNECTION_TYPE_ADHOC
;
2085 else if (priv
->bss_mode
== NL80211_IFTYPE_STATION
||
2086 priv
->bss_mode
== NL80211_IFTYPE_P2P_CLIENT
)
2087 cmd_ptr
->params
.bss_mode
.con_type
=
2088 CONNECTION_TYPE_INFRA
;
2089 else if (priv
->bss_mode
== NL80211_IFTYPE_AP
||
2090 priv
->bss_mode
== NL80211_IFTYPE_P2P_GO
)
2091 cmd_ptr
->params
.bss_mode
.con_type
= CONNECTION_TYPE_AP
;
2092 cmd_ptr
->size
= cpu_to_le16(sizeof(struct
2093 host_cmd_ds_set_bss_mode
) + S_DS_GEN
);
2096 case HostCmd_CMD_PCIE_DESC_DETAILS
:
2097 ret
= mwifiex_cmd_pcie_host_spec(priv
, cmd_ptr
, cmd_action
);
2099 case HostCmd_CMD_802_11_SUBSCRIBE_EVENT
:
2100 ret
= mwifiex_cmd_802_11_subsc_evt(priv
, cmd_ptr
, data_buf
);
2102 case HostCmd_CMD_MEF_CFG
:
2103 ret
= mwifiex_cmd_mef_cfg(priv
, cmd_ptr
, data_buf
);
2105 case HostCmd_CMD_COALESCE_CFG
:
2106 ret
= mwifiex_cmd_coalesce_cfg(priv
, cmd_ptr
, cmd_action
,
2109 case HostCmd_CMD_TDLS_OPER
:
2110 ret
= mwifiex_cmd_tdls_oper(priv
, cmd_ptr
, data_buf
);
2112 case HostCmd_CMD_TDLS_CONFIG
:
2113 ret
= mwifiex_cmd_tdls_config(priv
, cmd_ptr
, cmd_action
,
2116 case HostCmd_CMD_CHAN_REPORT_REQUEST
:
2117 ret
= mwifiex_cmd_issue_chan_report_request(priv
, cmd_ptr
,
2120 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
:
2121 ret
= mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr
, cmd_action
,
2124 case HostCmd_CMD_HS_WAKEUP_REASON
:
2125 ret
= mwifiex_cmd_get_wakeup_reason(priv
, cmd_ptr
);
2127 case HostCmd_CMD_MC_POLICY
:
2128 ret
= mwifiex_cmd_set_mc_policy(priv
, cmd_ptr
, cmd_action
,
2131 case HostCmd_CMD_ROBUST_COEX
:
2132 ret
= mwifiex_cmd_robust_coex(priv
, cmd_ptr
, cmd_action
,
2135 case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG
:
2136 ret
= mwifiex_cmd_gtk_rekey_offload(priv
, cmd_ptr
, cmd_action
,
2140 mwifiex_dbg(priv
->adapter
, ERROR
,
2141 "PREP_CMD: unknown cmd- %#x\n", cmd_no
);
2149 * This function issues commands to initialize firmware.
2151 * This is called after firmware download to bring the card to
2153 * Function is also called during reinitialization of virtual
2156 * The following commands are issued sequentially -
2157 * - Set PCI-Express host buffer configuration (PCIE only)
2158 * - Function init (for first interface only)
2159 * - Read MAC address (for first interface only)
2160 * - Reconfigure Tx buffer size (for first interface only)
2161 * - Enable auto deep sleep (for first interface only)
2164 * - Set IBSS coalescing status
2165 * - Set AMSDU aggregation control
2167 * - Set MAC control (this must be the last command to initialize firmware)
2169 int mwifiex_sta_init_cmd(struct mwifiex_private
*priv
, u8 first_sta
, bool init
)
2171 struct mwifiex_adapter
*adapter
= priv
->adapter
;
2174 struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl
;
2175 struct mwifiex_ds_auto_ds auto_ds
;
2176 enum state_11d_t state_11d
;
2177 struct mwifiex_ds_11n_tx_cfg tx_cfg
;
2178 u8 sdio_sp_rx_aggr_enable
;
2182 if (priv
->adapter
->iface_type
== MWIFIEX_PCIE
) {
2183 ret
= mwifiex_send_cmd(priv
,
2184 HostCmd_CMD_PCIE_DESC_DETAILS
,
2185 HostCmd_ACT_GEN_SET
, 0, NULL
,
2191 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_FUNC_INIT
,
2192 HostCmd_ACT_GEN_SET
, 0, NULL
, true);
2196 /* Download calibration data to firmware.
2197 * The cal-data can be read from device tree and/or
2198 * a configuration file and downloaded to firmware.
2200 if (priv
->adapter
->iface_type
== MWIFIEX_SDIO
&&
2201 adapter
->dev
->of_node
) {
2202 adapter
->dt_node
= adapter
->dev
->of_node
;
2203 if (of_property_read_u32(adapter
->dt_node
,
2204 "marvell,wakeup-pin",
2206 pr_debug("Wakeup pin = 0x%x\n", data
);
2207 adapter
->hs_cfg
.gpio
= data
;
2210 ret
= mwifiex_dnld_dt_cfgdata(priv
, adapter
->dt_node
,
2216 if (adapter
->cal_data
) {
2217 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
2218 HostCmd_ACT_GEN_SET
, 0, NULL
,
2224 /* Read MAC address from HW */
2225 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_GET_HW_SPEC
,
2226 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2230 /** Set SDIO Single Port RX Aggr Info */
2231 if (priv
->adapter
->iface_type
== MWIFIEX_SDIO
&&
2232 ISSUPP_SDIO_SPA_ENABLED(priv
->adapter
->fw_cap_info
) &&
2233 !priv
->adapter
->host_disable_sdio_rx_aggr
) {
2234 sdio_sp_rx_aggr_enable
= true;
2235 ret
= mwifiex_send_cmd(priv
,
2236 HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
,
2237 HostCmd_ACT_GEN_SET
, 0,
2238 &sdio_sp_rx_aggr_enable
,
2241 mwifiex_dbg(priv
->adapter
, ERROR
,
2242 "error while enabling SP aggregation..disable it");
2243 adapter
->sdio_rx_aggr_enable
= false;
2247 /* Reconfigure tx buf size */
2248 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RECONFIGURE_TX_BUFF
,
2249 HostCmd_ACT_GEN_SET
, 0,
2250 &priv
->adapter
->tx_buf_size
, true);
2254 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2255 /* Enable IEEE PS by default */
2256 priv
->adapter
->ps_mode
= MWIFIEX_802_11_POWER_MODE_PSP
;
2257 ret
= mwifiex_send_cmd(priv
,
2258 HostCmd_CMD_802_11_PS_MODE_ENH
,
2259 EN_AUTO_PS
, BITMAP_STA_PS
, NULL
,
2266 adapter
->drcs_enabled
= true;
2267 if (ISSUPP_DRCS_ENABLED(adapter
->fw_cap_info
))
2268 ret
= mwifiex_send_cmd(priv
,
2269 HostCmd_CMD_MC_POLICY
,
2270 HostCmd_ACT_GEN_SET
, 0,
2271 &adapter
->drcs_enabled
,
2279 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_TX_RATE_CFG
,
2280 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2283 priv
->data_rate
= 0;
2286 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RF_TX_PWR
,
2287 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2291 if (priv
->bss_type
== MWIFIEX_BSS_TYPE_STA
) {
2292 /* set ibss coalescing_status */
2293 ret
= mwifiex_send_cmd(
2295 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
,
2296 HostCmd_ACT_GEN_SET
, 0, &enable
, true);
2301 memset(&amsdu_aggr_ctrl
, 0, sizeof(amsdu_aggr_ctrl
));
2302 amsdu_aggr_ctrl
.enable
= true;
2303 /* Send request to firmware */
2304 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_AMSDU_AGGR_CTRL
,
2305 HostCmd_ACT_GEN_SET
, 0,
2306 &amsdu_aggr_ctrl
, true);
2309 /* MAC Control must be the last command in init_fw */
2310 /* set MAC Control */
2311 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_MAC_CONTROL
,
2312 HostCmd_ACT_GEN_SET
, 0,
2313 &priv
->curr_pkt_filter
, true);
2317 if (!disable_auto_ds
&&
2318 first_sta
&& priv
->adapter
->iface_type
!= MWIFIEX_USB
&&
2319 priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2320 /* Enable auto deep sleep */
2321 auto_ds
.auto_ds
= DEEP_SLEEP_ON
;
2322 auto_ds
.idle_time
= DEEP_SLEEP_IDLE_TIME
;
2323 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_PS_MODE_ENH
,
2324 EN_AUTO_PS
, BITMAP_AUTO_DS
,
2330 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2331 /* Send cmd to FW to enable/disable 11D function */
2332 state_11d
= ENABLE_11D
;
2333 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_SNMP_MIB
,
2334 HostCmd_ACT_GEN_SET
, DOT11D_I
,
2337 mwifiex_dbg(priv
->adapter
, ERROR
,
2338 "11D: failed to enable 11D\n");
2341 /* Send cmd to FW to configure 11n specific configuration
2342 * (Short GI, Channel BW, Green field support etc.) for transmit
2344 tx_cfg
.tx_htcap
= MWIFIEX_FW_DEF_HTTXCFG
;
2345 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_11N_CFG
,
2346 HostCmd_ACT_GEN_SET
, 0, &tx_cfg
, true);
2349 /* set last_init_cmd before sending the command */
2350 priv
->adapter
->last_init_cmd
= HostCmd_CMD_11N_CFG
;