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.
29 static bool disable_auto_ds
;
30 module_param(disable_auto_ds
, bool, 0);
31 MODULE_PARM_DESC(disable_auto_ds
,
32 "deepsleep enabled=0(default), deepsleep disabled=1");
34 * This function prepares command to set/get RSSI information.
36 * Preparation includes -
37 * - Setting command ID, action and proper size
38 * - Setting data/beacon average factors
39 * - Resetting SNR/NF/RSSI values in private structure
40 * - Ensuring correct endian-ness
43 mwifiex_cmd_802_11_rssi_info(struct mwifiex_private
*priv
,
44 struct host_cmd_ds_command
*cmd
, u16 cmd_action
)
46 cmd
->command
= cpu_to_le16(HostCmd_CMD_RSSI_INFO
);
47 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info
) +
49 cmd
->params
.rssi_info
.action
= cpu_to_le16(cmd_action
);
50 cmd
->params
.rssi_info
.ndata
= cpu_to_le16(priv
->data_avg_factor
);
51 cmd
->params
.rssi_info
.nbcn
= cpu_to_le16(priv
->bcn_avg_factor
);
53 /* Reset SNR/NF/RSSI values in private structure */
54 priv
->data_rssi_last
= 0;
55 priv
->data_nf_last
= 0;
56 priv
->data_rssi_avg
= 0;
57 priv
->data_nf_avg
= 0;
58 priv
->bcn_rssi_last
= 0;
59 priv
->bcn_nf_last
= 0;
60 priv
->bcn_rssi_avg
= 0;
67 * This function prepares command to set MAC control.
69 * Preparation includes -
70 * - Setting command ID, action and proper size
71 * - Ensuring correct endian-ness
73 static int mwifiex_cmd_mac_control(struct mwifiex_private
*priv
,
74 struct host_cmd_ds_command
*cmd
,
75 u16 cmd_action
, u16
*action
)
77 struct host_cmd_ds_mac_control
*mac_ctrl
= &cmd
->params
.mac_ctrl
;
79 if (cmd_action
!= HostCmd_ACT_GEN_SET
) {
80 dev_err(priv
->adapter
->dev
,
81 "mac_control: only support set cmd\n");
85 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_CONTROL
);
87 cpu_to_le16(sizeof(struct host_cmd_ds_mac_control
) + S_DS_GEN
);
88 mac_ctrl
->action
= cpu_to_le16(*action
);
94 * This function prepares command to set/get SNMP MIB.
96 * Preparation includes -
97 * - Setting command ID, action and proper size
98 * - Setting SNMP MIB OID number and value
100 * - Ensuring correct endian-ness
102 * The following SNMP MIB OIDs are supported -
103 * - FRAG_THRESH_I : Fragmentation threshold
104 * - RTS_THRESH_I : RTS threshold
105 * - SHORT_RETRY_LIM_I : Short retry limit
106 * - DOT11D_I : 11d support
108 static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private
*priv
,
109 struct host_cmd_ds_command
*cmd
,
110 u16 cmd_action
, u32 cmd_oid
,
113 struct host_cmd_ds_802_11_snmp_mib
*snmp_mib
= &cmd
->params
.smib
;
115 dev_dbg(priv
->adapter
->dev
, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid
);
116 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB
);
117 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib
)
120 snmp_mib
->oid
= cpu_to_le16((u16
)cmd_oid
);
121 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
122 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_GET
);
123 snmp_mib
->buf_size
= cpu_to_le16(MAX_SNMP_BUF_SIZE
);
124 le16_add_cpu(&cmd
->size
, MAX_SNMP_BUF_SIZE
);
125 } else if (cmd_action
== HostCmd_ACT_GEN_SET
) {
126 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
127 snmp_mib
->buf_size
= cpu_to_le16(sizeof(u16
));
128 *((__le16
*) (snmp_mib
->value
)) = cpu_to_le16(*ul_temp
);
129 le16_add_cpu(&cmd
->size
, sizeof(u16
));
132 dev_dbg(priv
->adapter
->dev
,
133 "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x,"
135 cmd_action
, cmd_oid
, le16_to_cpu(snmp_mib
->buf_size
),
136 le16_to_cpu(*(__le16
*) snmp_mib
->value
));
141 * This function prepares command to get log.
143 * Preparation includes -
144 * - Setting command ID and proper size
145 * - Ensuring correct endian-ness
148 mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command
*cmd
)
150 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_GET_LOG
);
151 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log
) +
157 * This function prepares command to set/get Tx data rate configuration.
159 * Preparation includes -
160 * - Setting command ID, action and proper size
161 * - Setting configuration index, rate scope and rate drop pattern
162 * parameters (as required)
163 * - Ensuring correct endian-ness
165 static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private
*priv
,
166 struct host_cmd_ds_command
*cmd
,
167 u16 cmd_action
, u16
*pbitmap_rates
)
169 struct host_cmd_ds_tx_rate_cfg
*rate_cfg
= &cmd
->params
.tx_rate_cfg
;
170 struct mwifiex_rate_scope
*rate_scope
;
171 struct mwifiex_rate_drop_pattern
*rate_drop
;
174 cmd
->command
= cpu_to_le16(HostCmd_CMD_TX_RATE_CFG
);
176 rate_cfg
->action
= cpu_to_le16(cmd_action
);
177 rate_cfg
->cfg_index
= 0;
179 rate_scope
= (struct mwifiex_rate_scope
*) ((u8
*) rate_cfg
+
180 sizeof(struct host_cmd_ds_tx_rate_cfg
));
181 rate_scope
->type
= cpu_to_le16(TLV_TYPE_RATE_SCOPE
);
182 rate_scope
->length
= cpu_to_le16
183 (sizeof(*rate_scope
) - sizeof(struct mwifiex_ie_types_header
));
184 if (pbitmap_rates
!= NULL
) {
185 rate_scope
->hr_dsss_rate_bitmap
= cpu_to_le16(pbitmap_rates
[0]);
186 rate_scope
->ofdm_rate_bitmap
= cpu_to_le16(pbitmap_rates
[1]);
188 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
190 rate_scope
->ht_mcs_rate_bitmap
[i
] =
191 cpu_to_le16(pbitmap_rates
[2 + i
]);
192 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
194 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
196 rate_scope
->vht_mcs_rate_bitmap
[i
] =
197 cpu_to_le16(pbitmap_rates
[10 + i
]);
200 rate_scope
->hr_dsss_rate_bitmap
=
201 cpu_to_le16(priv
->bitmap_rates
[0]);
202 rate_scope
->ofdm_rate_bitmap
=
203 cpu_to_le16(priv
->bitmap_rates
[1]);
205 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
207 rate_scope
->ht_mcs_rate_bitmap
[i
] =
208 cpu_to_le16(priv
->bitmap_rates
[2 + i
]);
209 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
211 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
213 rate_scope
->vht_mcs_rate_bitmap
[i
] =
214 cpu_to_le16(priv
->bitmap_rates
[10 + i
]);
218 rate_drop
= (struct mwifiex_rate_drop_pattern
*) ((u8
*) rate_scope
+
219 sizeof(struct mwifiex_rate_scope
));
220 rate_drop
->type
= cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL
);
221 rate_drop
->length
= cpu_to_le16(sizeof(rate_drop
->rate_drop_mode
));
222 rate_drop
->rate_drop_mode
= 0;
225 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_tx_rate_cfg
) +
226 sizeof(struct mwifiex_rate_scope
) +
227 sizeof(struct mwifiex_rate_drop_pattern
));
233 * This function prepares command to set/get Tx power configuration.
235 * Preparation includes -
236 * - Setting command ID, action and proper size
237 * - Setting Tx power mode, power group TLV
239 * - Ensuring correct endian-ness
241 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command
*cmd
,
243 struct host_cmd_ds_txpwr_cfg
*txp
)
245 struct mwifiex_types_power_group
*pg_tlv
;
246 struct host_cmd_ds_txpwr_cfg
*cmd_txp_cfg
= &cmd
->params
.txp_cfg
;
248 cmd
->command
= cpu_to_le16(HostCmd_CMD_TXPWR_CFG
);
250 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_txpwr_cfg
));
251 switch (cmd_action
) {
252 case HostCmd_ACT_GEN_SET
:
254 pg_tlv
= (struct mwifiex_types_power_group
255 *) ((unsigned long) txp
+
256 sizeof(struct host_cmd_ds_txpwr_cfg
));
257 memmove(cmd_txp_cfg
, txp
,
258 sizeof(struct host_cmd_ds_txpwr_cfg
) +
259 sizeof(struct mwifiex_types_power_group
) +
260 le16_to_cpu(pg_tlv
->length
));
262 pg_tlv
= (struct mwifiex_types_power_group
*) ((u8
*)
264 sizeof(struct host_cmd_ds_txpwr_cfg
));
265 cmd
->size
= cpu_to_le16(le16_to_cpu(cmd
->size
) +
266 sizeof(struct mwifiex_types_power_group
) +
267 le16_to_cpu(pg_tlv
->length
));
269 memmove(cmd_txp_cfg
, txp
, sizeof(*txp
));
271 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
273 case HostCmd_ACT_GEN_GET
:
274 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
282 * This function prepares command to get RF Tx power.
284 static int mwifiex_cmd_rf_tx_power(struct mwifiex_private
*priv
,
285 struct host_cmd_ds_command
*cmd
,
286 u16 cmd_action
, void *data_buf
)
288 struct host_cmd_ds_rf_tx_pwr
*txp
= &cmd
->params
.txp
;
290 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr
)
292 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_TX_PWR
);
293 txp
->action
= cpu_to_le16(cmd_action
);
299 * This function prepares command to set rf antenna.
301 static int mwifiex_cmd_rf_antenna(struct mwifiex_private
*priv
,
302 struct host_cmd_ds_command
*cmd
,
304 struct mwifiex_ds_ant_cfg
*ant_cfg
)
306 struct host_cmd_ds_rf_ant_mimo
*ant_mimo
= &cmd
->params
.ant_mimo
;
307 struct host_cmd_ds_rf_ant_siso
*ant_siso
= &cmd
->params
.ant_siso
;
309 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_ANTENNA
);
311 if (cmd_action
!= HostCmd_ACT_GEN_SET
)
314 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
315 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo
) +
317 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_SET_TX
);
318 ant_mimo
->tx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
319 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_SET_RX
);
320 ant_mimo
->rx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->rx_ant
);
322 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso
) +
324 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_SET_BOTH
);
325 ant_siso
->ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
332 * This function prepares command to set Host Sleep configuration.
334 * Preparation includes -
335 * - Setting command ID and proper size
336 * - Setting Host Sleep action, conditions, ARP filters
338 * - Ensuring correct endian-ness
341 mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private
*priv
,
342 struct host_cmd_ds_command
*cmd
,
344 struct mwifiex_hs_config_param
*hscfg_param
)
346 struct mwifiex_adapter
*adapter
= priv
->adapter
;
347 struct host_cmd_ds_802_11_hs_cfg_enh
*hs_cfg
= &cmd
->params
.opt_hs_cfg
;
348 bool hs_activate
= false;
351 /* New Activate command */
353 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH
);
356 (hscfg_param
->conditions
!= cpu_to_le32(HS_CFG_CANCEL
)) &&
357 ((adapter
->arp_filter_size
> 0) &&
358 (adapter
->arp_filter_size
<= ARP_FILTER_MAX_BUF_SIZE
))) {
359 dev_dbg(adapter
->dev
,
360 "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
361 adapter
->arp_filter_size
);
362 memcpy(((u8
*) hs_cfg
) +
363 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
),
364 adapter
->arp_filter
, adapter
->arp_filter_size
);
365 cmd
->size
= cpu_to_le16
366 (adapter
->arp_filter_size
+
367 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
)
370 cmd
->size
= cpu_to_le16(S_DS_GEN
+ sizeof(struct
371 host_cmd_ds_802_11_hs_cfg_enh
));
374 hs_cfg
->action
= cpu_to_le16(HS_ACTIVATE
);
375 hs_cfg
->params
.hs_activate
.resp_ctrl
= cpu_to_le16(RESP_NEEDED
);
377 hs_cfg
->action
= cpu_to_le16(HS_CONFIGURE
);
378 hs_cfg
->params
.hs_config
.conditions
= hscfg_param
->conditions
;
379 hs_cfg
->params
.hs_config
.gpio
= hscfg_param
->gpio
;
380 hs_cfg
->params
.hs_config
.gap
= hscfg_param
->gap
;
381 dev_dbg(adapter
->dev
,
382 "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
383 hs_cfg
->params
.hs_config
.conditions
,
384 hs_cfg
->params
.hs_config
.gpio
,
385 hs_cfg
->params
.hs_config
.gap
);
392 * This function prepares command to set/get MAC address.
394 * Preparation includes -
395 * - Setting command ID, action and proper size
396 * - Setting MAC address (for SET only)
397 * - Ensuring correct endian-ness
399 static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private
*priv
,
400 struct host_cmd_ds_command
*cmd
,
403 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS
);
404 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address
) +
408 cmd
->params
.mac_addr
.action
= cpu_to_le16(cmd_action
);
410 if (cmd_action
== HostCmd_ACT_GEN_SET
)
411 memcpy(cmd
->params
.mac_addr
.mac_addr
, priv
->curr_addr
,
417 * This function prepares command to set MAC multicast address.
419 * Preparation includes -
420 * - Setting command ID, action and proper size
421 * - Setting MAC multicast address
422 * - Ensuring correct endian-ness
425 mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command
*cmd
,
427 struct mwifiex_multicast_list
*mcast_list
)
429 struct host_cmd_ds_mac_multicast_adr
*mcast_addr
= &cmd
->params
.mc_addr
;
431 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr
) +
433 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR
);
435 mcast_addr
->action
= cpu_to_le16(cmd_action
);
436 mcast_addr
->num_of_adrs
=
437 cpu_to_le16((u16
) mcast_list
->num_multicast_addr
);
438 memcpy(mcast_addr
->mac_list
, mcast_list
->mac_list
,
439 mcast_list
->num_multicast_addr
* ETH_ALEN
);
445 * This function prepares command to deauthenticate.
447 * Preparation includes -
448 * - Setting command ID and proper size
449 * - Setting AP MAC address and reason code
450 * - Ensuring correct endian-ness
452 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private
*priv
,
453 struct host_cmd_ds_command
*cmd
,
456 struct host_cmd_ds_802_11_deauthenticate
*deauth
= &cmd
->params
.deauth
;
458 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE
);
459 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate
)
462 /* Set AP MAC address */
463 memcpy(deauth
->mac_addr
, mac
, ETH_ALEN
);
465 dev_dbg(priv
->adapter
->dev
, "cmd: Deauth: %pM\n", deauth
->mac_addr
);
467 deauth
->reason_code
= cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING
);
473 * This function prepares command to stop Ad-Hoc network.
475 * Preparation includes -
476 * - Setting command ID and proper size
477 * - Ensuring correct endian-ness
479 static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command
*cmd
)
481 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP
);
482 cmd
->size
= cpu_to_le16(S_DS_GEN
);
487 * This function sets WEP key(s) to key parameter TLV(s).
489 * Multi-key parameter TLVs are supported, so we can send multiple
490 * WEP keys in a single buffer.
493 mwifiex_set_keyparamset_wep(struct mwifiex_private
*priv
,
494 struct mwifiex_ie_type_key_param_set
*key_param_set
,
497 int cur_key_param_len
;
500 /* Multi-key_param_set TLV is supported */
501 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
502 if ((priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP40
) ||
503 (priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP104
)) {
504 key_param_set
->type
=
505 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
506 /* Key_param_set WEP fixed length */
507 #define KEYPARAMSET_WEP_FIXED_LEN 8
508 key_param_set
->length
= cpu_to_le16((u16
)
511 KEYPARAMSET_WEP_FIXED_LEN
));
512 key_param_set
->key_type_id
=
513 cpu_to_le16(KEY_TYPE_ID_WEP
);
514 key_param_set
->key_info
=
515 cpu_to_le16(KEY_ENABLED
| KEY_UNICAST
|
517 key_param_set
->key_len
=
518 cpu_to_le16(priv
->wep_key
[i
].key_length
);
519 /* Set WEP key index */
520 key_param_set
->key
[0] = i
;
521 /* Set default Tx key flag */
524 wep_key_curr_index
& HostCmd_WEP_KEY_INDEX_MASK
))
525 key_param_set
->key
[1] = 1;
527 key_param_set
->key
[1] = 0;
528 memmove(&key_param_set
->key
[2],
529 priv
->wep_key
[i
].key_material
,
530 priv
->wep_key
[i
].key_length
);
532 cur_key_param_len
= priv
->wep_key
[i
].key_length
+
533 KEYPARAMSET_WEP_FIXED_LEN
+
534 sizeof(struct mwifiex_ie_types_header
);
535 *key_param_len
+= (u16
) cur_key_param_len
;
537 (struct mwifiex_ie_type_key_param_set
*)
538 ((u8
*)key_param_set
+
540 } else if (!priv
->wep_key
[i
].key_length
) {
543 dev_err(priv
->adapter
->dev
,
544 "key%d Length = %d is incorrect\n",
545 (i
+ 1), priv
->wep_key
[i
].key_length
);
553 /* This function populates key material v2 command
554 * to set network key for AES & CMAC AES.
556 static int mwifiex_set_aes_key_v2(struct mwifiex_private
*priv
,
557 struct host_cmd_ds_command
*cmd
,
558 struct mwifiex_ds_encrypt_key
*enc_key
,
559 struct host_cmd_ds_802_11_key_material_v2
*km
)
561 struct mwifiex_adapter
*adapter
= priv
->adapter
;
562 u16 size
, len
= KEY_PARAMS_FIXED_LEN
;
564 if (enc_key
->is_igtk_key
) {
565 dev_dbg(adapter
->dev
, "%s: Set CMAC AES Key\n", __func__
);
566 if (enc_key
->is_rx_seq_valid
)
567 memcpy(km
->key_param_set
.key_params
.cmac_aes
.ipn
,
568 enc_key
->pn
, enc_key
->pn_len
);
569 km
->key_param_set
.key_info
&= cpu_to_le16(~KEY_MCAST
);
570 km
->key_param_set
.key_info
|= cpu_to_le16(KEY_IGTK
);
571 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES_CMAC
;
572 km
->key_param_set
.key_params
.cmac_aes
.key_len
=
573 cpu_to_le16(enc_key
->key_len
);
574 memcpy(km
->key_param_set
.key_params
.cmac_aes
.key
,
575 enc_key
->key_material
, enc_key
->key_len
);
576 len
+= sizeof(struct mwifiex_cmac_aes_param
);
578 dev_dbg(adapter
->dev
, "%s: Set AES Key\n", __func__
);
579 if (enc_key
->is_rx_seq_valid
)
580 memcpy(km
->key_param_set
.key_params
.aes
.pn
,
581 enc_key
->pn
, enc_key
->pn_len
);
582 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES
;
583 km
->key_param_set
.key_params
.aes
.key_len
=
584 cpu_to_le16(enc_key
->key_len
);
585 memcpy(km
->key_param_set
.key_params
.aes
.key
,
586 enc_key
->key_material
, enc_key
->key_len
);
587 len
+= sizeof(struct mwifiex_aes_param
);
590 km
->key_param_set
.len
= cpu_to_le16(len
);
591 size
= len
+ sizeof(struct mwifiex_ie_types_header
) +
592 sizeof(km
->action
) + S_DS_GEN
;
593 cmd
->size
= cpu_to_le16(size
);
598 /* This function prepares command to set/get/reset network key(s).
599 * This function prepares key material command for V2 format.
600 * Preparation includes -
601 * - Setting command ID, action and proper size
602 * - Setting WEP keys, WAPI keys or WPA keys along with required
603 * encryption (TKIP, AES) (as required)
604 * - Ensuring correct endian-ness
607 mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private
*priv
,
608 struct host_cmd_ds_command
*cmd
,
609 u16 cmd_action
, u32 cmd_oid
,
610 struct mwifiex_ds_encrypt_key
*enc_key
)
612 struct mwifiex_adapter
*adapter
= priv
->adapter
;
613 u8
*mac
= enc_key
->mac_addr
;
614 u16 key_info
, len
= KEY_PARAMS_FIXED_LEN
;
615 struct host_cmd_ds_802_11_key_material_v2
*km
=
616 &cmd
->params
.key_material_v2
;
618 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
619 km
->action
= cpu_to_le16(cmd_action
);
621 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
622 dev_dbg(adapter
->dev
, "%s: Get key\n", __func__
);
623 km
->key_param_set
.key_idx
=
624 enc_key
->key_index
& KEY_INDEX_MASK
;
625 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
626 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
627 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
629 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
630 key_info
= KEY_UNICAST
;
632 key_info
= KEY_MCAST
;
634 if (enc_key
->is_igtk_key
)
635 key_info
|= KEY_IGTK
;
637 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
639 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
640 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
645 memset(&km
->key_param_set
, 0,
646 sizeof(struct mwifiex_ie_type_key_param_set_v2
));
648 if (enc_key
->key_disable
) {
649 dev_dbg(adapter
->dev
, "%s: Remove key\n", __func__
);
650 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_REMOVE
);
651 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
652 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
653 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
654 key_info
= KEY_MCAST
| KEY_UNICAST
;
655 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
656 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
657 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
658 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
663 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
664 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
665 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
666 key_info
= KEY_ENABLED
;
667 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
669 if (enc_key
->key_len
<= WLAN_KEY_LEN_WEP104
) {
670 dev_dbg(adapter
->dev
, "%s: Set WEP Key\n", __func__
);
671 len
+= sizeof(struct mwifiex_wep_param
);
672 km
->key_param_set
.len
= cpu_to_le16(len
);
673 km
->key_param_set
.key_type
= KEY_TYPE_ID_WEP
;
675 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
676 key_info
|= KEY_MCAST
| KEY_UNICAST
;
678 if (enc_key
->is_current_wep_key
) {
679 key_info
|= KEY_MCAST
| KEY_UNICAST
;
680 if (km
->key_param_set
.key_idx
==
681 (priv
->wep_key_curr_index
& KEY_INDEX_MASK
))
682 key_info
|= KEY_DEFAULT
;
685 if (is_broadcast_ether_addr(mac
))
686 key_info
|= KEY_MCAST
;
688 key_info
|= KEY_UNICAST
|
691 key_info
|= KEY_MCAST
;
695 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
697 km
->key_param_set
.key_params
.wep
.key_len
=
698 cpu_to_le16(enc_key
->key_len
);
699 memcpy(km
->key_param_set
.key_params
.wep
.key
,
700 enc_key
->key_material
, enc_key
->key_len
);
702 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
703 len
+ sizeof(km
->action
) + S_DS_GEN
);
707 if (is_broadcast_ether_addr(mac
))
708 key_info
|= KEY_MCAST
| KEY_RX_KEY
;
710 key_info
|= KEY_UNICAST
| KEY_TX_KEY
| KEY_RX_KEY
;
712 if (enc_key
->is_wapi_key
) {
713 dev_dbg(adapter
->dev
, "%s: Set WAPI Key\n", __func__
);
714 km
->key_param_set
.key_type
= KEY_TYPE_ID_WAPI
;
715 memcpy(km
->key_param_set
.key_params
.wapi
.pn
, enc_key
->pn
,
717 km
->key_param_set
.key_params
.wapi
.key_len
=
718 cpu_to_le16(enc_key
->key_len
);
719 memcpy(km
->key_param_set
.key_params
.wapi
.key
,
720 enc_key
->key_material
, enc_key
->key_len
);
721 if (is_broadcast_ether_addr(mac
))
722 priv
->sec_info
.wapi_key_on
= true;
724 if (!priv
->sec_info
.wapi_key_on
)
725 key_info
|= KEY_DEFAULT
;
726 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
728 len
+= sizeof(struct mwifiex_wapi_param
);
729 km
->key_param_set
.len
= cpu_to_le16(len
);
730 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
731 len
+ sizeof(km
->action
) + S_DS_GEN
);
735 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
) {
736 key_info
|= KEY_DEFAULT
;
737 /* Enable unicast bit for WPA-NONE/ADHOC_AES */
738 if (!priv
->sec_info
.wpa2_enabled
&&
739 !is_broadcast_ether_addr(mac
))
740 key_info
|= KEY_UNICAST
;
742 /* Enable default key for WPA/WPA2 */
743 if (!priv
->wpa_is_gtk_set
)
744 key_info
|= KEY_DEFAULT
;
747 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
749 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
)
750 return mwifiex_set_aes_key_v2(priv
, cmd
, enc_key
, km
);
752 if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
753 dev_dbg(adapter
->dev
, "%s: Set TKIP Key\n", __func__
);
754 if (enc_key
->is_rx_seq_valid
)
755 memcpy(km
->key_param_set
.key_params
.tkip
.pn
,
756 enc_key
->pn
, enc_key
->pn_len
);
757 km
->key_param_set
.key_type
= KEY_TYPE_ID_TKIP
;
758 km
->key_param_set
.key_params
.tkip
.key_len
=
759 cpu_to_le16(enc_key
->key_len
);
760 memcpy(km
->key_param_set
.key_params
.tkip
.key
,
761 enc_key
->key_material
, enc_key
->key_len
);
763 len
+= sizeof(struct mwifiex_tkip_param
);
764 km
->key_param_set
.len
= cpu_to_le16(len
);
765 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
766 len
+ sizeof(km
->action
) + S_DS_GEN
);
773 * This function prepares command to set/get/reset network key(s).
774 * This function prepares key material command for V1 format.
776 * Preparation includes -
777 * - Setting command ID, action and proper size
778 * - Setting WEP keys, WAPI keys or WPA keys along with required
779 * encryption (TKIP, AES) (as required)
780 * - Ensuring correct endian-ness
783 mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private
*priv
,
784 struct host_cmd_ds_command
*cmd
,
785 u16 cmd_action
, u32 cmd_oid
,
786 struct mwifiex_ds_encrypt_key
*enc_key
)
788 struct host_cmd_ds_802_11_key_material
*key_material
=
789 &cmd
->params
.key_material
;
790 struct host_cmd_tlv_mac_addr
*tlv_mac
;
791 u16 key_param_len
= 0, cmd_size
;
794 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
795 key_material
->action
= cpu_to_le16(cmd_action
);
797 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
799 cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
);
804 memset(&key_material
->key_param_set
, 0,
806 sizeof(struct mwifiex_ie_type_key_param_set
)));
807 ret
= mwifiex_set_keyparamset_wep(priv
,
808 &key_material
->key_param_set
,
810 cmd
->size
= cpu_to_le16(key_param_len
+
811 sizeof(key_material
->action
) + S_DS_GEN
);
814 memset(&key_material
->key_param_set
, 0,
815 sizeof(struct mwifiex_ie_type_key_param_set
));
816 if (enc_key
->is_wapi_key
) {
817 dev_dbg(priv
->adapter
->dev
, "info: Set WAPI Key\n");
818 key_material
->key_param_set
.key_type_id
=
819 cpu_to_le16(KEY_TYPE_ID_WAPI
);
820 if (cmd_oid
== KEY_INFO_ENABLED
)
821 key_material
->key_param_set
.key_info
=
822 cpu_to_le16(KEY_ENABLED
);
824 key_material
->key_param_set
.key_info
=
825 cpu_to_le16(!KEY_ENABLED
);
827 key_material
->key_param_set
.key
[0] = enc_key
->key_index
;
828 if (!priv
->sec_info
.wapi_key_on
)
829 key_material
->key_param_set
.key
[1] = 1;
831 /* set 0 when re-key */
832 key_material
->key_param_set
.key
[1] = 0;
834 if (!is_broadcast_ether_addr(enc_key
->mac_addr
)) {
835 /* WAPI pairwise key: unicast */
836 key_material
->key_param_set
.key_info
|=
837 cpu_to_le16(KEY_UNICAST
);
838 } else { /* WAPI group key: multicast */
839 key_material
->key_param_set
.key_info
|=
840 cpu_to_le16(KEY_MCAST
);
841 priv
->sec_info
.wapi_key_on
= true;
844 key_material
->key_param_set
.type
=
845 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
846 key_material
->key_param_set
.key_len
=
847 cpu_to_le16(WAPI_KEY_LEN
);
848 memcpy(&key_material
->key_param_set
.key
[2],
849 enc_key
->key_material
, enc_key
->key_len
);
850 memcpy(&key_material
->key_param_set
.key
[2 + enc_key
->key_len
],
851 enc_key
->pn
, PN_LEN
);
852 key_material
->key_param_set
.length
=
853 cpu_to_le16(WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
);
855 key_param_len
= (WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
) +
856 sizeof(struct mwifiex_ie_types_header
);
857 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
)
858 + S_DS_GEN
+ key_param_len
);
861 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
) {
862 if (enc_key
->is_igtk_key
) {
863 dev_dbg(priv
->adapter
->dev
, "cmd: CMAC_AES\n");
864 key_material
->key_param_set
.key_type_id
=
865 cpu_to_le16(KEY_TYPE_ID_AES_CMAC
);
866 if (cmd_oid
== KEY_INFO_ENABLED
)
867 key_material
->key_param_set
.key_info
=
868 cpu_to_le16(KEY_ENABLED
);
870 key_material
->key_param_set
.key_info
=
871 cpu_to_le16(!KEY_ENABLED
);
873 key_material
->key_param_set
.key_info
|=
874 cpu_to_le16(KEY_IGTK
);
876 dev_dbg(priv
->adapter
->dev
, "cmd: WPA_AES\n");
877 key_material
->key_param_set
.key_type_id
=
878 cpu_to_le16(KEY_TYPE_ID_AES
);
879 if (cmd_oid
== KEY_INFO_ENABLED
)
880 key_material
->key_param_set
.key_info
=
881 cpu_to_le16(KEY_ENABLED
);
883 key_material
->key_param_set
.key_info
=
884 cpu_to_le16(!KEY_ENABLED
);
886 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
887 /* AES pairwise key: unicast */
888 key_material
->key_param_set
.key_info
|=
889 cpu_to_le16(KEY_UNICAST
);
890 else /* AES group key: multicast */
891 key_material
->key_param_set
.key_info
|=
892 cpu_to_le16(KEY_MCAST
);
894 } else if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
895 dev_dbg(priv
->adapter
->dev
, "cmd: WPA_TKIP\n");
896 key_material
->key_param_set
.key_type_id
=
897 cpu_to_le16(KEY_TYPE_ID_TKIP
);
898 key_material
->key_param_set
.key_info
=
899 cpu_to_le16(KEY_ENABLED
);
901 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
902 /* TKIP pairwise key: unicast */
903 key_material
->key_param_set
.key_info
|=
904 cpu_to_le16(KEY_UNICAST
);
905 else /* TKIP group key: multicast */
906 key_material
->key_param_set
.key_info
|=
907 cpu_to_le16(KEY_MCAST
);
910 if (key_material
->key_param_set
.key_type_id
) {
911 key_material
->key_param_set
.type
=
912 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
913 key_material
->key_param_set
.key_len
=
914 cpu_to_le16((u16
) enc_key
->key_len
);
915 memcpy(key_material
->key_param_set
.key
, enc_key
->key_material
,
917 key_material
->key_param_set
.length
=
918 cpu_to_le16((u16
) enc_key
->key_len
+
919 KEYPARAMSET_FIXED_LEN
);
921 key_param_len
= (u16
)(enc_key
->key_len
+ KEYPARAMSET_FIXED_LEN
)
922 + sizeof(struct mwifiex_ie_types_header
);
924 if (le16_to_cpu(key_material
->key_param_set
.key_type_id
) ==
925 KEY_TYPE_ID_AES_CMAC
) {
926 struct mwifiex_cmac_param
*param
=
927 (void *)key_material
->key_param_set
.key
;
929 memcpy(param
->ipn
, enc_key
->pn
, IGTK_PN_LEN
);
930 memcpy(param
->key
, enc_key
->key_material
,
931 WLAN_KEY_LEN_AES_CMAC
);
933 key_param_len
= sizeof(struct mwifiex_cmac_param
);
934 key_material
->key_param_set
.key_len
=
935 cpu_to_le16(key_param_len
);
936 key_param_len
+= KEYPARAMSET_FIXED_LEN
;
937 key_material
->key_param_set
.length
=
938 cpu_to_le16(key_param_len
);
939 key_param_len
+= sizeof(struct mwifiex_ie_types_header
);
942 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
945 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
946 tlv_mac
= (void *)((u8
*)&key_material
->key_param_set
+
948 tlv_mac
->header
.type
=
949 cpu_to_le16(TLV_TYPE_STA_MAC_ADDR
);
950 tlv_mac
->header
.len
= cpu_to_le16(ETH_ALEN
);
951 memcpy(tlv_mac
->mac_addr
, enc_key
->mac_addr
, ETH_ALEN
);
952 cmd_size
= key_param_len
+ S_DS_GEN
+
953 sizeof(key_material
->action
) +
954 sizeof(struct host_cmd_tlv_mac_addr
);
956 cmd_size
= key_param_len
+ S_DS_GEN
+
957 sizeof(key_material
->action
);
959 cmd
->size
= cpu_to_le16(cmd_size
);
965 /* Wrapper function for setting network key depending upon FW KEY API version */
967 mwifiex_cmd_802_11_key_material(struct mwifiex_private
*priv
,
968 struct host_cmd_ds_command
*cmd
,
969 u16 cmd_action
, u32 cmd_oid
,
970 struct mwifiex_ds_encrypt_key
*enc_key
)
972 if (priv
->adapter
->key_api_major_ver
== KEY_API_VER_MAJOR_V2
)
973 return mwifiex_cmd_802_11_key_material_v2(priv
, cmd
,
978 return mwifiex_cmd_802_11_key_material_v1(priv
, cmd
,
984 * This function prepares command to set/get 11d domain information.
986 * Preparation includes -
987 * - Setting command ID, action and proper size
988 * - Setting domain information fields (for SET only)
989 * - Ensuring correct endian-ness
991 static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private
*priv
,
992 struct host_cmd_ds_command
*cmd
,
995 struct mwifiex_adapter
*adapter
= priv
->adapter
;
996 struct host_cmd_ds_802_11d_domain_info
*domain_info
=
997 &cmd
->params
.domain_info
;
998 struct mwifiex_ietypes_domain_param_set
*domain
=
999 &domain_info
->domain
;
1000 u8 no_of_triplet
= adapter
->domain_reg
.no_of_triplet
;
1002 dev_dbg(adapter
->dev
, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet
);
1004 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO
);
1005 domain_info
->action
= cpu_to_le16(cmd_action
);
1006 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
1007 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1011 /* Set domain info fields */
1012 domain
->header
.type
= cpu_to_le16(WLAN_EID_COUNTRY
);
1013 memcpy(domain
->country_code
, adapter
->domain_reg
.country_code
,
1014 sizeof(domain
->country_code
));
1016 domain
->header
.len
=
1017 cpu_to_le16((no_of_triplet
*
1018 sizeof(struct ieee80211_country_ie_triplet
))
1019 + sizeof(domain
->country_code
));
1021 if (no_of_triplet
) {
1022 memcpy(domain
->triplet
, adapter
->domain_reg
.triplet
,
1023 no_of_triplet
* sizeof(struct
1024 ieee80211_country_ie_triplet
));
1026 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) +
1027 le16_to_cpu(domain
->header
.len
) +
1028 sizeof(struct mwifiex_ie_types_header
)
1031 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1038 * This function prepares command to set/get IBSS coalescing status.
1040 * Preparation includes -
1041 * - Setting command ID, action and proper size
1042 * - Setting status to enable or disable (for SET only)
1043 * - Ensuring correct endian-ness
1045 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command
*cmd
,
1046 u16 cmd_action
, u16
*enable
)
1048 struct host_cmd_ds_802_11_ibss_status
*ibss_coal
=
1049 &(cmd
->params
.ibss_coalescing
);
1051 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
);
1052 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status
) +
1055 ibss_coal
->action
= cpu_to_le16(cmd_action
);
1057 switch (cmd_action
) {
1058 case HostCmd_ACT_GEN_SET
:
1060 ibss_coal
->enable
= cpu_to_le16(*enable
);
1062 ibss_coal
->enable
= 0;
1065 /* In other case.. Nothing to do */
1066 case HostCmd_ACT_GEN_GET
:
1075 * This function prepares command to set/get register value.
1077 * Preparation includes -
1078 * - Setting command ID, action and proper size
1079 * - Setting register offset (for both GET and SET) and
1080 * register value (for SET only)
1081 * - Ensuring correct endian-ness
1083 * The following type of registers can be accessed with this function -
1091 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command
*cmd
,
1092 u16 cmd_action
, void *data_buf
)
1094 struct mwifiex_ds_reg_rw
*reg_rw
= data_buf
;
1096 switch (le16_to_cpu(cmd
->command
)) {
1097 case HostCmd_CMD_MAC_REG_ACCESS
:
1099 struct host_cmd_ds_mac_reg_access
*mac_reg
;
1101 cmd
->size
= cpu_to_le16(sizeof(*mac_reg
) + S_DS_GEN
);
1102 mac_reg
= &cmd
->params
.mac_reg
;
1103 mac_reg
->action
= cpu_to_le16(cmd_action
);
1105 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1106 mac_reg
->value
= reg_rw
->value
;
1109 case HostCmd_CMD_BBP_REG_ACCESS
:
1111 struct host_cmd_ds_bbp_reg_access
*bbp_reg
;
1113 cmd
->size
= cpu_to_le16(sizeof(*bbp_reg
) + S_DS_GEN
);
1114 bbp_reg
= &cmd
->params
.bbp_reg
;
1115 bbp_reg
->action
= cpu_to_le16(cmd_action
);
1117 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1118 bbp_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1121 case HostCmd_CMD_RF_REG_ACCESS
:
1123 struct host_cmd_ds_rf_reg_access
*rf_reg
;
1125 cmd
->size
= cpu_to_le16(sizeof(*rf_reg
) + S_DS_GEN
);
1126 rf_reg
= &cmd
->params
.rf_reg
;
1127 rf_reg
->action
= cpu_to_le16(cmd_action
);
1128 rf_reg
->offset
= cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1129 rf_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1132 case HostCmd_CMD_PMIC_REG_ACCESS
:
1134 struct host_cmd_ds_pmic_reg_access
*pmic_reg
;
1136 cmd
->size
= cpu_to_le16(sizeof(*pmic_reg
) + S_DS_GEN
);
1137 pmic_reg
= &cmd
->params
.pmic_reg
;
1138 pmic_reg
->action
= cpu_to_le16(cmd_action
);
1140 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1141 pmic_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1144 case HostCmd_CMD_CAU_REG_ACCESS
:
1146 struct host_cmd_ds_rf_reg_access
*cau_reg
;
1148 cmd
->size
= cpu_to_le16(sizeof(*cau_reg
) + S_DS_GEN
);
1149 cau_reg
= &cmd
->params
.rf_reg
;
1150 cau_reg
->action
= cpu_to_le16(cmd_action
);
1152 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1153 cau_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1156 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1158 struct mwifiex_ds_read_eeprom
*rd_eeprom
= data_buf
;
1159 struct host_cmd_ds_802_11_eeprom_access
*cmd_eeprom
=
1160 &cmd
->params
.eeprom
;
1162 cmd
->size
= cpu_to_le16(sizeof(*cmd_eeprom
) + S_DS_GEN
);
1163 cmd_eeprom
->action
= cpu_to_le16(cmd_action
);
1164 cmd_eeprom
->offset
= rd_eeprom
->offset
;
1165 cmd_eeprom
->byte_count
= rd_eeprom
->byte_count
;
1166 cmd_eeprom
->value
= 0;
1177 * This function prepares command to set PCI-Express
1178 * host buffer configuration
1180 * Preparation includes -
1181 * - Setting command ID, action and proper size
1182 * - Setting host buffer configuration
1183 * - Ensuring correct endian-ness
1186 mwifiex_cmd_pcie_host_spec(struct mwifiex_private
*priv
,
1187 struct host_cmd_ds_command
*cmd
, u16 action
)
1189 struct host_cmd_ds_pcie_details
*host_spec
=
1190 &cmd
->params
.pcie_host_spec
;
1191 struct pcie_service_card
*card
= priv
->adapter
->card
;
1193 cmd
->command
= cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS
);
1194 cmd
->size
= cpu_to_le16(sizeof(struct
1195 host_cmd_ds_pcie_details
) + S_DS_GEN
);
1198 memset(host_spec
, 0, sizeof(struct host_cmd_ds_pcie_details
));
1200 if (action
!= HostCmd_ACT_GEN_SET
)
1203 /* Send the ring base addresses and count to firmware */
1204 host_spec
->txbd_addr_lo
= (u32
)(card
->txbd_ring_pbase
);
1205 host_spec
->txbd_addr_hi
= (u32
)(((u64
)card
->txbd_ring_pbase
)>>32);
1206 host_spec
->txbd_count
= MWIFIEX_MAX_TXRX_BD
;
1207 host_spec
->rxbd_addr_lo
= (u32
)(card
->rxbd_ring_pbase
);
1208 host_spec
->rxbd_addr_hi
= (u32
)(((u64
)card
->rxbd_ring_pbase
)>>32);
1209 host_spec
->rxbd_count
= MWIFIEX_MAX_TXRX_BD
;
1210 host_spec
->evtbd_addr_lo
= (u32
)(card
->evtbd_ring_pbase
);
1211 host_spec
->evtbd_addr_hi
= (u32
)(((u64
)card
->evtbd_ring_pbase
)>>32);
1212 host_spec
->evtbd_count
= MWIFIEX_MAX_EVT_BD
;
1213 if (card
->sleep_cookie_vbase
) {
1214 host_spec
->sleep_cookie_addr_lo
=
1215 (u32
)(card
->sleep_cookie_pbase
);
1216 host_spec
->sleep_cookie_addr_hi
=
1217 (u32
)(((u64
)(card
->sleep_cookie_pbase
)) >> 32);
1218 dev_dbg(priv
->adapter
->dev
, "sleep_cook_lo phy addr: 0x%x\n",
1219 host_spec
->sleep_cookie_addr_lo
);
1226 * This function prepares command for event subscription, configuration
1227 * and query. Events can be subscribed or unsubscribed. Current subscribed
1228 * events can be queried. Also, current subscribed events are reported in
1229 * every FW response.
1232 mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private
*priv
,
1233 struct host_cmd_ds_command
*cmd
,
1234 struct mwifiex_ds_misc_subsc_evt
*subsc_evt_cfg
)
1236 struct host_cmd_ds_802_11_subsc_evt
*subsc_evt
= &cmd
->params
.subsc_evt
;
1237 struct mwifiex_ie_types_rssi_threshold
*rssi_tlv
;
1241 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT
);
1242 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt
) +
1245 subsc_evt
->action
= cpu_to_le16(subsc_evt_cfg
->action
);
1246 dev_dbg(priv
->adapter
->dev
, "cmd: action: %d\n", subsc_evt_cfg
->action
);
1248 /*For query requests, no configuration TLV structures are to be added.*/
1249 if (subsc_evt_cfg
->action
== HostCmd_ACT_GEN_GET
)
1252 subsc_evt
->events
= cpu_to_le16(subsc_evt_cfg
->events
);
1254 event_bitmap
= subsc_evt_cfg
->events
;
1255 dev_dbg(priv
->adapter
->dev
, "cmd: event bitmap : %16x\n",
1258 if (((subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
) ||
1259 (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_SET
)) &&
1260 (event_bitmap
== 0)) {
1261 dev_dbg(priv
->adapter
->dev
, "Error: No event specified "
1262 "for bitwise action type\n");
1267 * Append TLV structures for each of the specified events for
1268 * subscribing or re-configuring. This is not required for
1269 * bitwise unsubscribing request.
1271 if (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
)
1274 pos
= ((u8
*)subsc_evt
) +
1275 sizeof(struct host_cmd_ds_802_11_subsc_evt
);
1277 if (event_bitmap
& BITMASK_BCN_RSSI_LOW
) {
1278 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1280 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_LOW
);
1281 rssi_tlv
->header
.len
=
1282 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1283 sizeof(struct mwifiex_ie_types_header
));
1284 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
;
1285 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
;
1287 dev_dbg(priv
->adapter
->dev
, "Cfg Beacon Low Rssi event, "
1288 "RSSI:-%d dBm, Freq:%d\n",
1289 subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
,
1290 subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
);
1292 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1293 le16_add_cpu(&cmd
->size
,
1294 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1297 if (event_bitmap
& BITMASK_BCN_RSSI_HIGH
) {
1298 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1300 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_HIGH
);
1301 rssi_tlv
->header
.len
=
1302 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1303 sizeof(struct mwifiex_ie_types_header
));
1304 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
;
1305 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
;
1307 dev_dbg(priv
->adapter
->dev
, "Cfg Beacon High Rssi event, "
1308 "RSSI:-%d dBm, Freq:%d\n",
1309 subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
,
1310 subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
);
1312 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1313 le16_add_cpu(&cmd
->size
,
1314 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1321 mwifiex_cmd_append_rpn_expression(struct mwifiex_private
*priv
,
1322 struct mwifiex_mef_entry
*mef_entry
,
1325 struct mwifiex_mef_filter
*filter
= mef_entry
->filter
;
1327 u8
*stack_ptr
= *buffer
;
1329 for (i
= 0; i
< MWIFIEX_MEF_MAX_FILTERS
; i
++) {
1330 filter
= &mef_entry
->filter
[i
];
1331 if (!filter
->filt_type
)
1333 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->repeat
);
1335 *stack_ptr
= TYPE_DNUM
;
1338 byte_len
= filter
->byte_seq
[MWIFIEX_MEF_MAX_BYTESEQ
];
1339 memcpy(stack_ptr
, filter
->byte_seq
, byte_len
);
1340 stack_ptr
+= byte_len
;
1341 *stack_ptr
= byte_len
;
1343 *stack_ptr
= TYPE_BYTESEQ
;
1346 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->offset
);
1348 *stack_ptr
= TYPE_DNUM
;
1351 *stack_ptr
= filter
->filt_type
;
1354 if (filter
->filt_action
) {
1355 *stack_ptr
= filter
->filt_action
;
1359 if (stack_ptr
- *buffer
> STACK_NBYTES
)
1363 *buffer
= stack_ptr
;
1368 mwifiex_cmd_mef_cfg(struct mwifiex_private
*priv
,
1369 struct host_cmd_ds_command
*cmd
,
1370 struct mwifiex_ds_mef_cfg
*mef
)
1372 struct host_cmd_ds_mef_cfg
*mef_cfg
= &cmd
->params
.mef_cfg
;
1373 struct mwifiex_fw_mef_entry
*mef_entry
= NULL
;
1374 u8
*pos
= (u8
*)mef_cfg
;
1377 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEF_CFG
);
1379 mef_cfg
->criteria
= cpu_to_le32(mef
->criteria
);
1380 mef_cfg
->num_entries
= cpu_to_le16(mef
->num_entries
);
1381 pos
+= sizeof(*mef_cfg
);
1383 for (i
= 0; i
< mef
->num_entries
; i
++) {
1384 mef_entry
= (struct mwifiex_fw_mef_entry
*)pos
;
1385 mef_entry
->mode
= mef
->mef_entry
[i
].mode
;
1386 mef_entry
->action
= mef
->mef_entry
[i
].action
;
1387 pos
+= sizeof(*mef_cfg
->mef_entry
);
1389 if (mwifiex_cmd_append_rpn_expression(priv
,
1390 &mef
->mef_entry
[i
], &pos
))
1393 mef_entry
->exprsize
=
1394 cpu_to_le16(pos
- mef_entry
->expr
);
1396 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*)mef_cfg
) + S_DS_GEN
);
1401 /* This function parse cal data from ASCII to hex */
1402 static u32
mwifiex_parse_cal_cfg(u8
*src
, size_t len
, u8
*dst
)
1404 u8
*s
= src
, *d
= dst
;
1406 while (s
- src
< len
) {
1407 if (*s
&& (isspace(*s
) || *s
== '\t')) {
1412 *d
++ = simple_strtol(s
, NULL
, 16);
1422 int mwifiex_dnld_dt_cfgdata(struct mwifiex_private
*priv
,
1423 struct device_node
*node
, const char *prefix
)
1426 struct property
*prop
;
1427 size_t len
= strlen(prefix
);
1430 /* look for all matching property names */
1431 for_each_property_of_node(node
, prop
) {
1432 if (len
> strlen(prop
->name
) ||
1433 strncmp(prop
->name
, prefix
, len
))
1436 /* property header is 6 bytes, data must fit in cmd buffer */
1437 if (prop
&& prop
->value
&& prop
->length
> 6 &&
1438 prop
->length
<= MWIFIEX_SIZE_OF_CMD_BUFFER
- S_DS_GEN
) {
1439 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
1440 HostCmd_ACT_GEN_SET
, 0,
1450 /* This function prepares command of set_cfg_data. */
1451 static int mwifiex_cmd_cfg_data(struct mwifiex_private
*priv
,
1452 struct host_cmd_ds_command
*cmd
, void *data_buf
)
1454 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1455 struct property
*prop
= data_buf
;
1457 u8
*data
= (u8
*)cmd
+ S_DS_GEN
;
1462 ret
= of_property_read_u8_array(adapter
->dt_node
, prop
->name
,
1466 dev_dbg(adapter
->dev
,
1467 "download cfg_data from device tree: %s\n", prop
->name
);
1468 } else if (adapter
->cal_data
->data
&& adapter
->cal_data
->size
> 0) {
1469 len
= mwifiex_parse_cal_cfg((u8
*)adapter
->cal_data
->data
,
1470 adapter
->cal_data
->size
, data
);
1471 dev_dbg(adapter
->dev
, "download cfg_data from config file\n");
1476 cmd
->command
= cpu_to_le16(HostCmd_CMD_CFG_DATA
);
1477 cmd
->size
= cpu_to_le16(S_DS_GEN
+ len
);
1483 mwifiex_cmd_coalesce_cfg(struct mwifiex_private
*priv
,
1484 struct host_cmd_ds_command
*cmd
,
1485 u16 cmd_action
, void *data_buf
)
1487 struct host_cmd_ds_coalesce_cfg
*coalesce_cfg
=
1488 &cmd
->params
.coalesce_cfg
;
1489 struct mwifiex_ds_coalesce_cfg
*cfg
= data_buf
;
1490 struct coalesce_filt_field_param
*param
;
1491 u16 cnt
, idx
, length
;
1492 struct coalesce_receive_filt_rule
*rule
;
1494 cmd
->command
= cpu_to_le16(HostCmd_CMD_COALESCE_CFG
);
1495 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1497 coalesce_cfg
->action
= cpu_to_le16(cmd_action
);
1498 coalesce_cfg
->num_of_rules
= cpu_to_le16(cfg
->num_of_rules
);
1499 rule
= coalesce_cfg
->rule
;
1501 for (cnt
= 0; cnt
< cfg
->num_of_rules
; cnt
++) {
1502 rule
->header
.type
= cpu_to_le16(TLV_TYPE_COALESCE_RULE
);
1503 rule
->max_coalescing_delay
=
1504 cpu_to_le16(cfg
->rule
[cnt
].max_coalescing_delay
);
1505 rule
->pkt_type
= cfg
->rule
[cnt
].pkt_type
;
1506 rule
->num_of_fields
= cfg
->rule
[cnt
].num_of_fields
;
1510 param
= rule
->params
;
1511 for (idx
= 0; idx
< cfg
->rule
[cnt
].num_of_fields
; idx
++) {
1512 param
->operation
= cfg
->rule
[cnt
].params
[idx
].operation
;
1513 param
->operand_len
=
1514 cfg
->rule
[cnt
].params
[idx
].operand_len
;
1516 cpu_to_le16(cfg
->rule
[cnt
].params
[idx
].offset
);
1517 memcpy(param
->operand_byte_stream
,
1518 cfg
->rule
[cnt
].params
[idx
].operand_byte_stream
,
1519 param
->operand_len
);
1521 length
+= sizeof(struct coalesce_filt_field_param
);
1526 /* Total rule length is sizeof max_coalescing_delay(u16),
1527 * num_of_fields(u8), pkt_type(u8) and total length of the all
1530 rule
->header
.len
= cpu_to_le16(length
+ sizeof(u16
) +
1531 sizeof(u8
) + sizeof(u8
));
1533 /* Add the rule length to the command size*/
1534 le16_add_cpu(&cmd
->size
, le16_to_cpu(rule
->header
.len
) +
1535 sizeof(struct mwifiex_ie_types_header
));
1537 rule
= (void *)((u8
*)rule
->params
+ length
);
1540 /* Add sizeof action, num_of_rules to total command length */
1541 le16_add_cpu(&cmd
->size
, sizeof(u16
) + sizeof(u16
));
1547 mwifiex_cmd_tdls_oper(struct mwifiex_private
*priv
,
1548 struct host_cmd_ds_command
*cmd
,
1551 struct host_cmd_ds_tdls_oper
*tdls_oper
= &cmd
->params
.tdls_oper
;
1552 struct mwifiex_ds_tdls_oper
*oper
= data_buf
;
1553 struct mwifiex_sta_node
*sta_ptr
;
1554 struct host_cmd_tlv_rates
*tlv_rates
;
1555 struct mwifiex_ie_types_htcap
*ht_capab
;
1556 struct mwifiex_ie_types_qos_info
*wmm_qos_info
;
1557 struct mwifiex_ie_types_extcap
*extcap
;
1558 struct mwifiex_ie_types_vhtcap
*vht_capab
;
1559 struct mwifiex_ie_types_aid
*aid
;
1560 struct mwifiex_ie_types_tdls_idle_timeout
*timeout
;
1563 struct station_parameters
*params
= priv
->sta_params
;
1565 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_OPER
);
1566 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1567 le16_add_cpu(&cmd
->size
, sizeof(struct host_cmd_ds_tdls_oper
));
1569 tdls_oper
->reason
= 0;
1570 memcpy(tdls_oper
->peer_mac
, oper
->peer_mac
, ETH_ALEN
);
1571 sta_ptr
= mwifiex_get_sta_entry(priv
, oper
->peer_mac
);
1573 pos
= (u8
*)tdls_oper
+ sizeof(struct host_cmd_ds_tdls_oper
);
1575 switch (oper
->tdls_action
) {
1576 case MWIFIEX_TDLS_DISABLE_LINK
:
1577 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_DELETE
);
1579 case MWIFIEX_TDLS_CREATE_LINK
:
1580 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CREATE
);
1582 case MWIFIEX_TDLS_CONFIG_LINK
:
1583 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CONFIG
);
1586 dev_err(priv
->adapter
->dev
,
1587 "TDLS config params not available for %pM\n",
1592 *(__le16
*)pos
= cpu_to_le16(params
->capability
);
1593 config_len
+= sizeof(params
->capability
);
1595 qos_info
= params
->uapsd_queues
| (params
->max_sp
<< 5);
1596 wmm_qos_info
= (struct mwifiex_ie_types_qos_info
*)(pos
+
1598 wmm_qos_info
->header
.type
= cpu_to_le16(WLAN_EID_QOS_CAPA
);
1599 wmm_qos_info
->header
.len
= cpu_to_le16(sizeof(qos_info
));
1600 wmm_qos_info
->qos_info
= qos_info
;
1601 config_len
+= sizeof(struct mwifiex_ie_types_qos_info
);
1603 if (params
->ht_capa
) {
1604 ht_capab
= (struct mwifiex_ie_types_htcap
*)(pos
+
1606 ht_capab
->header
.type
=
1607 cpu_to_le16(WLAN_EID_HT_CAPABILITY
);
1608 ht_capab
->header
.len
=
1609 cpu_to_le16(sizeof(struct ieee80211_ht_cap
));
1610 memcpy(&ht_capab
->ht_cap
, params
->ht_capa
,
1611 sizeof(struct ieee80211_ht_cap
));
1612 config_len
+= sizeof(struct mwifiex_ie_types_htcap
);
1615 if (params
->supported_rates
&& params
->supported_rates_len
) {
1616 tlv_rates
= (struct host_cmd_tlv_rates
*)(pos
+
1618 tlv_rates
->header
.type
=
1619 cpu_to_le16(WLAN_EID_SUPP_RATES
);
1620 tlv_rates
->header
.len
=
1621 cpu_to_le16(params
->supported_rates_len
);
1622 memcpy(tlv_rates
->rates
, params
->supported_rates
,
1623 params
->supported_rates_len
);
1624 config_len
+= sizeof(struct host_cmd_tlv_rates
) +
1625 params
->supported_rates_len
;
1628 if (params
->ext_capab
&& params
->ext_capab_len
) {
1629 extcap
= (struct mwifiex_ie_types_extcap
*)(pos
+
1631 extcap
->header
.type
=
1632 cpu_to_le16(WLAN_EID_EXT_CAPABILITY
);
1633 extcap
->header
.len
= cpu_to_le16(params
->ext_capab_len
);
1634 memcpy(extcap
->ext_capab
, params
->ext_capab
,
1635 params
->ext_capab_len
);
1636 config_len
+= sizeof(struct mwifiex_ie_types_extcap
) +
1637 params
->ext_capab_len
;
1639 if (params
->vht_capa
) {
1640 vht_capab
= (struct mwifiex_ie_types_vhtcap
*)(pos
+
1642 vht_capab
->header
.type
=
1643 cpu_to_le16(WLAN_EID_VHT_CAPABILITY
);
1644 vht_capab
->header
.len
=
1645 cpu_to_le16(sizeof(struct ieee80211_vht_cap
));
1646 memcpy(&vht_capab
->vht_cap
, params
->vht_capa
,
1647 sizeof(struct ieee80211_vht_cap
));
1648 config_len
+= sizeof(struct mwifiex_ie_types_vhtcap
);
1651 aid
= (struct mwifiex_ie_types_aid
*)(pos
+ config_len
);
1652 aid
->header
.type
= cpu_to_le16(WLAN_EID_AID
);
1653 aid
->header
.len
= cpu_to_le16(sizeof(params
->aid
));
1654 aid
->aid
= cpu_to_le16(params
->aid
);
1655 config_len
+= sizeof(struct mwifiex_ie_types_aid
);
1658 timeout
= (void *)(pos
+ config_len
);
1659 timeout
->header
.type
= cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT
);
1660 timeout
->header
.len
= cpu_to_le16(sizeof(timeout
->value
));
1661 timeout
->value
= cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC
);
1662 config_len
+= sizeof(struct mwifiex_ie_types_tdls_idle_timeout
);
1666 dev_err(priv
->adapter
->dev
, "Unknown TDLS operation\n");
1670 le16_add_cpu(&cmd
->size
, config_len
);
1675 /* This function prepares command of sdio rx aggr info. */
1676 static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command
*cmd
,
1677 u16 cmd_action
, void *data_buf
)
1679 struct host_cmd_sdio_sp_rx_aggr_cfg
*cfg
=
1680 &cmd
->params
.sdio_rx_aggr_cfg
;
1682 cmd
->command
= cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
);
1684 cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg
) +
1686 cfg
->action
= cmd_action
;
1687 if (cmd_action
== HostCmd_ACT_GEN_SET
)
1688 cfg
->enable
= *(u8
*)data_buf
;
1694 * This function prepares the commands before sending them to the firmware.
1696 * This is a generic function which calls specific command preparation
1697 * routines based upon the command number.
1699 int mwifiex_sta_prepare_cmd(struct mwifiex_private
*priv
, uint16_t cmd_no
,
1700 u16 cmd_action
, u32 cmd_oid
,
1701 void *data_buf
, void *cmd_buf
)
1703 struct host_cmd_ds_command
*cmd_ptr
= cmd_buf
;
1706 /* Prepare command */
1708 case HostCmd_CMD_GET_HW_SPEC
:
1709 ret
= mwifiex_cmd_get_hw_spec(priv
, cmd_ptr
);
1711 case HostCmd_CMD_CFG_DATA
:
1712 ret
= mwifiex_cmd_cfg_data(priv
, cmd_ptr
, data_buf
);
1714 case HostCmd_CMD_MAC_CONTROL
:
1715 ret
= mwifiex_cmd_mac_control(priv
, cmd_ptr
, cmd_action
,
1718 case HostCmd_CMD_802_11_MAC_ADDRESS
:
1719 ret
= mwifiex_cmd_802_11_mac_address(priv
, cmd_ptr
,
1722 case HostCmd_CMD_MAC_MULTICAST_ADR
:
1723 ret
= mwifiex_cmd_mac_multicast_adr(cmd_ptr
, cmd_action
,
1726 case HostCmd_CMD_TX_RATE_CFG
:
1727 ret
= mwifiex_cmd_tx_rate_cfg(priv
, cmd_ptr
, cmd_action
,
1730 case HostCmd_CMD_TXPWR_CFG
:
1731 ret
= mwifiex_cmd_tx_power_cfg(cmd_ptr
, cmd_action
,
1734 case HostCmd_CMD_RF_TX_PWR
:
1735 ret
= mwifiex_cmd_rf_tx_power(priv
, cmd_ptr
, cmd_action
,
1738 case HostCmd_CMD_RF_ANTENNA
:
1739 ret
= mwifiex_cmd_rf_antenna(priv
, cmd_ptr
, cmd_action
,
1742 case HostCmd_CMD_802_11_PS_MODE_ENH
:
1743 ret
= mwifiex_cmd_enh_power_mode(priv
, cmd_ptr
, cmd_action
,
1744 (uint16_t)cmd_oid
, data_buf
);
1746 case HostCmd_CMD_802_11_HS_CFG_ENH
:
1747 ret
= mwifiex_cmd_802_11_hs_cfg(priv
, cmd_ptr
, cmd_action
,
1748 (struct mwifiex_hs_config_param
*) data_buf
);
1750 case HostCmd_CMD_802_11_SCAN
:
1751 ret
= mwifiex_cmd_802_11_scan(cmd_ptr
, data_buf
);
1753 case HostCmd_CMD_802_11_BG_SCAN_QUERY
:
1754 ret
= mwifiex_cmd_802_11_bg_scan_query(cmd_ptr
);
1756 case HostCmd_CMD_802_11_ASSOCIATE
:
1757 ret
= mwifiex_cmd_802_11_associate(priv
, cmd_ptr
, data_buf
);
1759 case HostCmd_CMD_802_11_DEAUTHENTICATE
:
1760 ret
= mwifiex_cmd_802_11_deauthenticate(priv
, cmd_ptr
,
1763 case HostCmd_CMD_802_11_AD_HOC_START
:
1764 ret
= mwifiex_cmd_802_11_ad_hoc_start(priv
, cmd_ptr
,
1767 case HostCmd_CMD_802_11_GET_LOG
:
1768 ret
= mwifiex_cmd_802_11_get_log(cmd_ptr
);
1770 case HostCmd_CMD_802_11_AD_HOC_JOIN
:
1771 ret
= mwifiex_cmd_802_11_ad_hoc_join(priv
, cmd_ptr
,
1774 case HostCmd_CMD_802_11_AD_HOC_STOP
:
1775 ret
= mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr
);
1777 case HostCmd_CMD_RSSI_INFO
:
1778 ret
= mwifiex_cmd_802_11_rssi_info(priv
, cmd_ptr
, cmd_action
);
1780 case HostCmd_CMD_802_11_SNMP_MIB
:
1781 ret
= mwifiex_cmd_802_11_snmp_mib(priv
, cmd_ptr
, cmd_action
,
1784 case HostCmd_CMD_802_11_TX_RATE_QUERY
:
1786 cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY
);
1788 cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query
) +
1793 case HostCmd_CMD_VERSION_EXT
:
1794 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1795 cmd_ptr
->params
.verext
.version_str_sel
=
1796 (u8
) (*((u32
*) data_buf
));
1797 memcpy(&cmd_ptr
->params
, data_buf
,
1798 sizeof(struct host_cmd_ds_version_ext
));
1800 cpu_to_le16(sizeof(struct host_cmd_ds_version_ext
) +
1804 case HostCmd_CMD_MGMT_FRAME_REG
:
1805 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1806 cmd_ptr
->params
.reg_mask
.action
= cpu_to_le16(cmd_action
);
1807 cmd_ptr
->params
.reg_mask
.mask
= cpu_to_le32(*(u32
*)data_buf
);
1809 cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg
) +
1813 case HostCmd_CMD_REMAIN_ON_CHAN
:
1814 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1815 memcpy(&cmd_ptr
->params
, data_buf
,
1816 sizeof(struct host_cmd_ds_remain_on_chan
));
1818 cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan
) +
1821 case HostCmd_CMD_11AC_CFG
:
1822 ret
= mwifiex_cmd_11ac_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
1824 case HostCmd_CMD_P2P_MODE_CFG
:
1825 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1826 cmd_ptr
->params
.mode_cfg
.action
= cpu_to_le16(cmd_action
);
1827 cmd_ptr
->params
.mode_cfg
.mode
= cpu_to_le16(*(u16
*)data_buf
);
1829 cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg
) +
1832 case HostCmd_CMD_FUNC_INIT
:
1833 if (priv
->adapter
->hw_status
== MWIFIEX_HW_STATUS_RESET
)
1834 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_READY
;
1835 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1836 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
1838 case HostCmd_CMD_FUNC_SHUTDOWN
:
1839 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_RESET
;
1840 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1841 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
1843 case HostCmd_CMD_11N_ADDBA_REQ
:
1844 ret
= mwifiex_cmd_11n_addba_req(cmd_ptr
, data_buf
);
1846 case HostCmd_CMD_11N_DELBA
:
1847 ret
= mwifiex_cmd_11n_delba(cmd_ptr
, data_buf
);
1849 case HostCmd_CMD_11N_ADDBA_RSP
:
1850 ret
= mwifiex_cmd_11n_addba_rsp_gen(priv
, cmd_ptr
, data_buf
);
1852 case HostCmd_CMD_802_11_KEY_MATERIAL
:
1853 ret
= mwifiex_cmd_802_11_key_material(priv
, cmd_ptr
,
1854 cmd_action
, cmd_oid
,
1857 case HostCmd_CMD_802_11D_DOMAIN_INFO
:
1858 ret
= mwifiex_cmd_802_11d_domain_info(priv
, cmd_ptr
,
1861 case HostCmd_CMD_RECONFIGURE_TX_BUFF
:
1862 ret
= mwifiex_cmd_recfg_tx_buf(priv
, cmd_ptr
, cmd_action
,
1865 case HostCmd_CMD_AMSDU_AGGR_CTRL
:
1866 ret
= mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr
, cmd_action
,
1869 case HostCmd_CMD_11N_CFG
:
1870 ret
= mwifiex_cmd_11n_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
1872 case HostCmd_CMD_WMM_GET_STATUS
:
1873 dev_dbg(priv
->adapter
->dev
,
1874 "cmd: WMM: WMM_GET_STATUS cmd sent\n");
1875 cmd_ptr
->command
= cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS
);
1877 cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status
) +
1881 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
:
1882 ret
= mwifiex_cmd_ibss_coalescing_status(cmd_ptr
, cmd_action
,
1885 case HostCmd_CMD_802_11_SCAN_EXT
:
1886 ret
= mwifiex_cmd_802_11_scan_ext(priv
, cmd_ptr
, data_buf
);
1888 case HostCmd_CMD_MAC_REG_ACCESS
:
1889 case HostCmd_CMD_BBP_REG_ACCESS
:
1890 case HostCmd_CMD_RF_REG_ACCESS
:
1891 case HostCmd_CMD_PMIC_REG_ACCESS
:
1892 case HostCmd_CMD_CAU_REG_ACCESS
:
1893 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1894 ret
= mwifiex_cmd_reg_access(cmd_ptr
, cmd_action
, data_buf
);
1896 case HostCmd_CMD_SET_BSS_MODE
:
1897 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1898 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
)
1899 cmd_ptr
->params
.bss_mode
.con_type
=
1900 CONNECTION_TYPE_ADHOC
;
1901 else if (priv
->bss_mode
== NL80211_IFTYPE_STATION
)
1902 cmd_ptr
->params
.bss_mode
.con_type
=
1903 CONNECTION_TYPE_INFRA
;
1904 else if (priv
->bss_mode
== NL80211_IFTYPE_AP
)
1905 cmd_ptr
->params
.bss_mode
.con_type
= CONNECTION_TYPE_AP
;
1906 cmd_ptr
->size
= cpu_to_le16(sizeof(struct
1907 host_cmd_ds_set_bss_mode
) + S_DS_GEN
);
1910 case HostCmd_CMD_PCIE_DESC_DETAILS
:
1911 ret
= mwifiex_cmd_pcie_host_spec(priv
, cmd_ptr
, cmd_action
);
1913 case HostCmd_CMD_802_11_SUBSCRIBE_EVENT
:
1914 ret
= mwifiex_cmd_802_11_subsc_evt(priv
, cmd_ptr
, data_buf
);
1916 case HostCmd_CMD_MEF_CFG
:
1917 ret
= mwifiex_cmd_mef_cfg(priv
, cmd_ptr
, data_buf
);
1919 case HostCmd_CMD_COALESCE_CFG
:
1920 ret
= mwifiex_cmd_coalesce_cfg(priv
, cmd_ptr
, cmd_action
,
1923 case HostCmd_CMD_TDLS_OPER
:
1924 ret
= mwifiex_cmd_tdls_oper(priv
, cmd_ptr
, data_buf
);
1926 case HostCmd_CMD_CHAN_REPORT_REQUEST
:
1927 ret
= mwifiex_cmd_issue_chan_report_request(priv
, cmd_ptr
,
1930 case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
:
1931 ret
= mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr
, cmd_action
,
1935 dev_err(priv
->adapter
->dev
,
1936 "PREP_CMD: unknown cmd- %#x\n", cmd_no
);
1944 * This function issues commands to initialize firmware.
1946 * This is called after firmware download to bring the card to
1948 * Function is also called during reinitialization of virtual
1951 * The following commands are issued sequentially -
1952 * - Set PCI-Express host buffer configuration (PCIE only)
1953 * - Function init (for first interface only)
1954 * - Read MAC address (for first interface only)
1955 * - Reconfigure Tx buffer size (for first interface only)
1956 * - Enable auto deep sleep (for first interface only)
1959 * - Set IBSS coalescing status
1960 * - Set AMSDU aggregation control
1962 * - Set MAC control (this must be the last command to initialize firmware)
1964 int mwifiex_sta_init_cmd(struct mwifiex_private
*priv
, u8 first_sta
, bool init
)
1966 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1969 struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl
;
1970 struct mwifiex_ds_auto_ds auto_ds
;
1971 enum state_11d_t state_11d
;
1972 struct mwifiex_ds_11n_tx_cfg tx_cfg
;
1973 u8 sdio_sp_rx_aggr_enable
;
1976 if (priv
->adapter
->iface_type
== MWIFIEX_PCIE
) {
1977 ret
= mwifiex_send_cmd(priv
,
1978 HostCmd_CMD_PCIE_DESC_DETAILS
,
1979 HostCmd_ACT_GEN_SET
, 0, NULL
,
1985 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_FUNC_INIT
,
1986 HostCmd_ACT_GEN_SET
, 0, NULL
, true);
1990 /* Download calibration data to firmware.
1991 * The cal-data can be read from device tree and/or
1992 * a configuration file and downloaded to firmware.
1995 of_find_node_by_name(NULL
, "marvell_cfgdata");
1996 if (adapter
->dt_node
) {
1997 ret
= mwifiex_dnld_dt_cfgdata(priv
, adapter
->dt_node
,
2003 if (adapter
->cal_data
) {
2004 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
2005 HostCmd_ACT_GEN_SET
, 0, NULL
,
2011 /* Read MAC address from HW */
2012 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_GET_HW_SPEC
,
2013 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2017 /** Set SDIO Single Port RX Aggr Info */
2018 if (priv
->adapter
->iface_type
== MWIFIEX_SDIO
&&
2019 ISSUPP_SDIO_SPA_ENABLED(priv
->adapter
->fw_cap_info
)) {
2020 sdio_sp_rx_aggr_enable
= true;
2021 ret
= mwifiex_send_cmd(priv
,
2022 HostCmd_CMD_SDIO_SP_RX_AGGR_CFG
,
2023 HostCmd_ACT_GEN_SET
, 0,
2024 &sdio_sp_rx_aggr_enable
,
2027 dev_err(priv
->adapter
->dev
,
2028 "error while enabling SP aggregation..disable it");
2029 adapter
->sdio_rx_aggr_enable
= false;
2033 /* Reconfigure tx buf size */
2034 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RECONFIGURE_TX_BUFF
,
2035 HostCmd_ACT_GEN_SET
, 0,
2036 &priv
->adapter
->tx_buf_size
, true);
2040 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2041 /* Enable IEEE PS by default */
2042 priv
->adapter
->ps_mode
= MWIFIEX_802_11_POWER_MODE_PSP
;
2043 ret
= mwifiex_send_cmd(priv
,
2044 HostCmd_CMD_802_11_PS_MODE_ENH
,
2045 EN_AUTO_PS
, BITMAP_STA_PS
, NULL
,
2053 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_TX_RATE_CFG
,
2054 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2057 priv
->data_rate
= 0;
2060 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RF_TX_PWR
,
2061 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2065 if (priv
->bss_type
== MWIFIEX_BSS_TYPE_STA
) {
2066 /* set ibss coalescing_status */
2067 ret
= mwifiex_send_cmd(
2069 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
,
2070 HostCmd_ACT_GEN_SET
, 0, &enable
, true);
2075 memset(&amsdu_aggr_ctrl
, 0, sizeof(amsdu_aggr_ctrl
));
2076 amsdu_aggr_ctrl
.enable
= true;
2077 /* Send request to firmware */
2078 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_AMSDU_AGGR_CTRL
,
2079 HostCmd_ACT_GEN_SET
, 0,
2080 &amsdu_aggr_ctrl
, true);
2083 /* MAC Control must be the last command in init_fw */
2084 /* set MAC Control */
2085 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_MAC_CONTROL
,
2086 HostCmd_ACT_GEN_SET
, 0,
2087 &priv
->curr_pkt_filter
, true);
2091 if (!disable_auto_ds
&&
2092 first_sta
&& priv
->adapter
->iface_type
!= MWIFIEX_USB
&&
2093 priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2094 /* Enable auto deep sleep */
2095 auto_ds
.auto_ds
= DEEP_SLEEP_ON
;
2096 auto_ds
.idle_time
= DEEP_SLEEP_IDLE_TIME
;
2097 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_PS_MODE_ENH
,
2098 EN_AUTO_PS
, BITMAP_AUTO_DS
,
2104 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2105 /* Send cmd to FW to enable/disable 11D function */
2106 state_11d
= ENABLE_11D
;
2107 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_SNMP_MIB
,
2108 HostCmd_ACT_GEN_SET
, DOT11D_I
,
2111 dev_err(priv
->adapter
->dev
,
2112 "11D: failed to enable 11D\n");
2115 /* Send cmd to FW to configure 11n specific configuration
2116 * (Short GI, Channel BW, Green field support etc.) for transmit
2118 tx_cfg
.tx_htcap
= MWIFIEX_FW_DEF_HTTXCFG
;
2119 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_11N_CFG
,
2120 HostCmd_ACT_GEN_SET
, 0, &tx_cfg
, true);
2123 /* set last_init_cmd before sending the command */
2124 priv
->adapter
->last_init_cmd
= HostCmd_CMD_11N_CFG
;