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 * This function prepares command to set/get RSSI information.
32 * Preparation includes -
33 * - Setting command ID, action and proper size
34 * - Setting data/beacon average factors
35 * - Resetting SNR/NF/RSSI values in private structure
36 * - Ensuring correct endian-ness
39 mwifiex_cmd_802_11_rssi_info(struct mwifiex_private
*priv
,
40 struct host_cmd_ds_command
*cmd
, u16 cmd_action
)
42 cmd
->command
= cpu_to_le16(HostCmd_CMD_RSSI_INFO
);
43 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info
) +
45 cmd
->params
.rssi_info
.action
= cpu_to_le16(cmd_action
);
46 cmd
->params
.rssi_info
.ndata
= cpu_to_le16(priv
->data_avg_factor
);
47 cmd
->params
.rssi_info
.nbcn
= cpu_to_le16(priv
->bcn_avg_factor
);
49 /* Reset SNR/NF/RSSI values in private structure */
50 priv
->data_rssi_last
= 0;
51 priv
->data_nf_last
= 0;
52 priv
->data_rssi_avg
= 0;
53 priv
->data_nf_avg
= 0;
54 priv
->bcn_rssi_last
= 0;
55 priv
->bcn_nf_last
= 0;
56 priv
->bcn_rssi_avg
= 0;
63 * This function prepares command to set MAC control.
65 * Preparation includes -
66 * - Setting command ID, action and proper size
67 * - Ensuring correct endian-ness
69 static int mwifiex_cmd_mac_control(struct mwifiex_private
*priv
,
70 struct host_cmd_ds_command
*cmd
,
71 u16 cmd_action
, u16
*action
)
73 struct host_cmd_ds_mac_control
*mac_ctrl
= &cmd
->params
.mac_ctrl
;
75 if (cmd_action
!= HostCmd_ACT_GEN_SET
) {
76 dev_err(priv
->adapter
->dev
,
77 "mac_control: only support set cmd\n");
81 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_CONTROL
);
83 cpu_to_le16(sizeof(struct host_cmd_ds_mac_control
) + S_DS_GEN
);
84 mac_ctrl
->action
= cpu_to_le16(*action
);
90 * This function prepares command to set/get SNMP MIB.
92 * Preparation includes -
93 * - Setting command ID, action and proper size
94 * - Setting SNMP MIB OID number and value
96 * - Ensuring correct endian-ness
98 * The following SNMP MIB OIDs are supported -
99 * - FRAG_THRESH_I : Fragmentation threshold
100 * - RTS_THRESH_I : RTS threshold
101 * - SHORT_RETRY_LIM_I : Short retry limit
102 * - DOT11D_I : 11d support
104 static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private
*priv
,
105 struct host_cmd_ds_command
*cmd
,
106 u16 cmd_action
, u32 cmd_oid
,
109 struct host_cmd_ds_802_11_snmp_mib
*snmp_mib
= &cmd
->params
.smib
;
111 dev_dbg(priv
->adapter
->dev
, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid
);
112 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB
);
113 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib
)
116 snmp_mib
->oid
= cpu_to_le16((u16
)cmd_oid
);
117 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
118 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_GET
);
119 snmp_mib
->buf_size
= cpu_to_le16(MAX_SNMP_BUF_SIZE
);
120 le16_add_cpu(&cmd
->size
, MAX_SNMP_BUF_SIZE
);
121 } else if (cmd_action
== HostCmd_ACT_GEN_SET
) {
122 snmp_mib
->query_type
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
123 snmp_mib
->buf_size
= cpu_to_le16(sizeof(u16
));
124 *((__le16
*) (snmp_mib
->value
)) = cpu_to_le16(*ul_temp
);
125 le16_add_cpu(&cmd
->size
, sizeof(u16
));
128 dev_dbg(priv
->adapter
->dev
,
129 "cmd: SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x,"
131 cmd_action
, cmd_oid
, le16_to_cpu(snmp_mib
->buf_size
),
132 le16_to_cpu(*(__le16
*) snmp_mib
->value
));
137 * This function prepares command to get log.
139 * Preparation includes -
140 * - Setting command ID and proper size
141 * - Ensuring correct endian-ness
144 mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command
*cmd
)
146 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_GET_LOG
);
147 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log
) +
153 * This function prepares command to set/get Tx data rate configuration.
155 * Preparation includes -
156 * - Setting command ID, action and proper size
157 * - Setting configuration index, rate scope and rate drop pattern
158 * parameters (as required)
159 * - Ensuring correct endian-ness
161 static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private
*priv
,
162 struct host_cmd_ds_command
*cmd
,
163 u16 cmd_action
, u16
*pbitmap_rates
)
165 struct host_cmd_ds_tx_rate_cfg
*rate_cfg
= &cmd
->params
.tx_rate_cfg
;
166 struct mwifiex_rate_scope
*rate_scope
;
167 struct mwifiex_rate_drop_pattern
*rate_drop
;
170 cmd
->command
= cpu_to_le16(HostCmd_CMD_TX_RATE_CFG
);
172 rate_cfg
->action
= cpu_to_le16(cmd_action
);
173 rate_cfg
->cfg_index
= 0;
175 rate_scope
= (struct mwifiex_rate_scope
*) ((u8
*) rate_cfg
+
176 sizeof(struct host_cmd_ds_tx_rate_cfg
));
177 rate_scope
->type
= cpu_to_le16(TLV_TYPE_RATE_SCOPE
);
178 rate_scope
->length
= cpu_to_le16
179 (sizeof(*rate_scope
) - sizeof(struct mwifiex_ie_types_header
));
180 if (pbitmap_rates
!= NULL
) {
181 rate_scope
->hr_dsss_rate_bitmap
= cpu_to_le16(pbitmap_rates
[0]);
182 rate_scope
->ofdm_rate_bitmap
= cpu_to_le16(pbitmap_rates
[1]);
184 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
186 rate_scope
->ht_mcs_rate_bitmap
[i
] =
187 cpu_to_le16(pbitmap_rates
[2 + i
]);
188 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
190 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
192 rate_scope
->vht_mcs_rate_bitmap
[i
] =
193 cpu_to_le16(pbitmap_rates
[10 + i
]);
196 rate_scope
->hr_dsss_rate_bitmap
=
197 cpu_to_le16(priv
->bitmap_rates
[0]);
198 rate_scope
->ofdm_rate_bitmap
=
199 cpu_to_le16(priv
->bitmap_rates
[1]);
201 i
< sizeof(rate_scope
->ht_mcs_rate_bitmap
) / sizeof(u16
);
203 rate_scope
->ht_mcs_rate_bitmap
[i
] =
204 cpu_to_le16(priv
->bitmap_rates
[2 + i
]);
205 if (priv
->adapter
->fw_api_ver
== MWIFIEX_FW_V15
) {
207 i
< ARRAY_SIZE(rate_scope
->vht_mcs_rate_bitmap
);
209 rate_scope
->vht_mcs_rate_bitmap
[i
] =
210 cpu_to_le16(priv
->bitmap_rates
[10 + i
]);
214 rate_drop
= (struct mwifiex_rate_drop_pattern
*) ((u8
*) rate_scope
+
215 sizeof(struct mwifiex_rate_scope
));
216 rate_drop
->type
= cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL
);
217 rate_drop
->length
= cpu_to_le16(sizeof(rate_drop
->rate_drop_mode
));
218 rate_drop
->rate_drop_mode
= 0;
221 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_tx_rate_cfg
) +
222 sizeof(struct mwifiex_rate_scope
) +
223 sizeof(struct mwifiex_rate_drop_pattern
));
229 * This function prepares command to set/get Tx power configuration.
231 * Preparation includes -
232 * - Setting command ID, action and proper size
233 * - Setting Tx power mode, power group TLV
235 * - Ensuring correct endian-ness
237 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command
*cmd
,
239 struct host_cmd_ds_txpwr_cfg
*txp
)
241 struct mwifiex_types_power_group
*pg_tlv
;
242 struct host_cmd_ds_txpwr_cfg
*cmd_txp_cfg
= &cmd
->params
.txp_cfg
;
244 cmd
->command
= cpu_to_le16(HostCmd_CMD_TXPWR_CFG
);
246 cpu_to_le16(S_DS_GEN
+ sizeof(struct host_cmd_ds_txpwr_cfg
));
247 switch (cmd_action
) {
248 case HostCmd_ACT_GEN_SET
:
250 pg_tlv
= (struct mwifiex_types_power_group
251 *) ((unsigned long) txp
+
252 sizeof(struct host_cmd_ds_txpwr_cfg
));
253 memmove(cmd_txp_cfg
, txp
,
254 sizeof(struct host_cmd_ds_txpwr_cfg
) +
255 sizeof(struct mwifiex_types_power_group
) +
256 le16_to_cpu(pg_tlv
->length
));
258 pg_tlv
= (struct mwifiex_types_power_group
*) ((u8
*)
260 sizeof(struct host_cmd_ds_txpwr_cfg
));
261 cmd
->size
= cpu_to_le16(le16_to_cpu(cmd
->size
) +
262 sizeof(struct mwifiex_types_power_group
) +
263 le16_to_cpu(pg_tlv
->length
));
265 memmove(cmd_txp_cfg
, txp
, sizeof(*txp
));
267 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
269 case HostCmd_ACT_GEN_GET
:
270 cmd_txp_cfg
->action
= cpu_to_le16(cmd_action
);
278 * This function prepares command to get RF Tx power.
280 static int mwifiex_cmd_rf_tx_power(struct mwifiex_private
*priv
,
281 struct host_cmd_ds_command
*cmd
,
282 u16 cmd_action
, void *data_buf
)
284 struct host_cmd_ds_rf_tx_pwr
*txp
= &cmd
->params
.txp
;
286 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr
)
288 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_TX_PWR
);
289 txp
->action
= cpu_to_le16(cmd_action
);
295 * This function prepares command to set rf antenna.
297 static int mwifiex_cmd_rf_antenna(struct mwifiex_private
*priv
,
298 struct host_cmd_ds_command
*cmd
,
300 struct mwifiex_ds_ant_cfg
*ant_cfg
)
302 struct host_cmd_ds_rf_ant_mimo
*ant_mimo
= &cmd
->params
.ant_mimo
;
303 struct host_cmd_ds_rf_ant_siso
*ant_siso
= &cmd
->params
.ant_siso
;
305 cmd
->command
= cpu_to_le16(HostCmd_CMD_RF_ANTENNA
);
307 if (cmd_action
!= HostCmd_ACT_GEN_SET
)
310 if (priv
->adapter
->hw_dev_mcs_support
== HT_STREAM_2X2
) {
311 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo
) +
313 ant_mimo
->action_tx
= cpu_to_le16(HostCmd_ACT_SET_TX
);
314 ant_mimo
->tx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
315 ant_mimo
->action_rx
= cpu_to_le16(HostCmd_ACT_SET_RX
);
316 ant_mimo
->rx_ant_mode
= cpu_to_le16((u16
)ant_cfg
->rx_ant
);
318 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso
) +
320 ant_siso
->action
= cpu_to_le16(HostCmd_ACT_SET_BOTH
);
321 ant_siso
->ant_mode
= cpu_to_le16((u16
)ant_cfg
->tx_ant
);
328 * This function prepares command to set Host Sleep configuration.
330 * Preparation includes -
331 * - Setting command ID and proper size
332 * - Setting Host Sleep action, conditions, ARP filters
334 * - Ensuring correct endian-ness
337 mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private
*priv
,
338 struct host_cmd_ds_command
*cmd
,
340 struct mwifiex_hs_config_param
*hscfg_param
)
342 struct mwifiex_adapter
*adapter
= priv
->adapter
;
343 struct host_cmd_ds_802_11_hs_cfg_enh
*hs_cfg
= &cmd
->params
.opt_hs_cfg
;
344 bool hs_activate
= false;
347 /* New Activate command */
349 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH
);
352 (hscfg_param
->conditions
!= cpu_to_le32(HS_CFG_CANCEL
)) &&
353 ((adapter
->arp_filter_size
> 0) &&
354 (adapter
->arp_filter_size
<= ARP_FILTER_MAX_BUF_SIZE
))) {
355 dev_dbg(adapter
->dev
,
356 "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n",
357 adapter
->arp_filter_size
);
358 memcpy(((u8
*) hs_cfg
) +
359 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
),
360 adapter
->arp_filter
, adapter
->arp_filter_size
);
361 cmd
->size
= cpu_to_le16
362 (adapter
->arp_filter_size
+
363 sizeof(struct host_cmd_ds_802_11_hs_cfg_enh
)
366 cmd
->size
= cpu_to_le16(S_DS_GEN
+ sizeof(struct
367 host_cmd_ds_802_11_hs_cfg_enh
));
370 hs_cfg
->action
= cpu_to_le16(HS_ACTIVATE
);
371 hs_cfg
->params
.hs_activate
.resp_ctrl
= cpu_to_le16(RESP_NEEDED
);
373 hs_cfg
->action
= cpu_to_le16(HS_CONFIGURE
);
374 hs_cfg
->params
.hs_config
.conditions
= hscfg_param
->conditions
;
375 hs_cfg
->params
.hs_config
.gpio
= hscfg_param
->gpio
;
376 hs_cfg
->params
.hs_config
.gap
= hscfg_param
->gap
;
377 dev_dbg(adapter
->dev
,
378 "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
379 hs_cfg
->params
.hs_config
.conditions
,
380 hs_cfg
->params
.hs_config
.gpio
,
381 hs_cfg
->params
.hs_config
.gap
);
388 * This function prepares command to set/get MAC address.
390 * Preparation includes -
391 * - Setting command ID, action and proper size
392 * - Setting MAC address (for SET only)
393 * - Ensuring correct endian-ness
395 static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private
*priv
,
396 struct host_cmd_ds_command
*cmd
,
399 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS
);
400 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address
) +
404 cmd
->params
.mac_addr
.action
= cpu_to_le16(cmd_action
);
406 if (cmd_action
== HostCmd_ACT_GEN_SET
)
407 memcpy(cmd
->params
.mac_addr
.mac_addr
, priv
->curr_addr
,
413 * This function prepares command to set MAC multicast address.
415 * Preparation includes -
416 * - Setting command ID, action and proper size
417 * - Setting MAC multicast address
418 * - Ensuring correct endian-ness
421 mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command
*cmd
,
423 struct mwifiex_multicast_list
*mcast_list
)
425 struct host_cmd_ds_mac_multicast_adr
*mcast_addr
= &cmd
->params
.mc_addr
;
427 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr
) +
429 cmd
->command
= cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR
);
431 mcast_addr
->action
= cpu_to_le16(cmd_action
);
432 mcast_addr
->num_of_adrs
=
433 cpu_to_le16((u16
) mcast_list
->num_multicast_addr
);
434 memcpy(mcast_addr
->mac_list
, mcast_list
->mac_list
,
435 mcast_list
->num_multicast_addr
* ETH_ALEN
);
441 * This function prepares command to deauthenticate.
443 * Preparation includes -
444 * - Setting command ID and proper size
445 * - Setting AP MAC address and reason code
446 * - Ensuring correct endian-ness
448 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private
*priv
,
449 struct host_cmd_ds_command
*cmd
,
452 struct host_cmd_ds_802_11_deauthenticate
*deauth
= &cmd
->params
.deauth
;
454 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE
);
455 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate
)
458 /* Set AP MAC address */
459 memcpy(deauth
->mac_addr
, mac
, ETH_ALEN
);
461 dev_dbg(priv
->adapter
->dev
, "cmd: Deauth: %pM\n", deauth
->mac_addr
);
463 deauth
->reason_code
= cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING
);
469 * This function prepares command to stop Ad-Hoc network.
471 * Preparation includes -
472 * - Setting command ID and proper size
473 * - Ensuring correct endian-ness
475 static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command
*cmd
)
477 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP
);
478 cmd
->size
= cpu_to_le16(S_DS_GEN
);
483 * This function sets WEP key(s) to key parameter TLV(s).
485 * Multi-key parameter TLVs are supported, so we can send multiple
486 * WEP keys in a single buffer.
489 mwifiex_set_keyparamset_wep(struct mwifiex_private
*priv
,
490 struct mwifiex_ie_type_key_param_set
*key_param_set
,
493 int cur_key_param_len
;
496 /* Multi-key_param_set TLV is supported */
497 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
498 if ((priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP40
) ||
499 (priv
->wep_key
[i
].key_length
== WLAN_KEY_LEN_WEP104
)) {
500 key_param_set
->type
=
501 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
502 /* Key_param_set WEP fixed length */
503 #define KEYPARAMSET_WEP_FIXED_LEN 8
504 key_param_set
->length
= cpu_to_le16((u16
)
507 KEYPARAMSET_WEP_FIXED_LEN
));
508 key_param_set
->key_type_id
=
509 cpu_to_le16(KEY_TYPE_ID_WEP
);
510 key_param_set
->key_info
=
511 cpu_to_le16(KEY_ENABLED
| KEY_UNICAST
|
513 key_param_set
->key_len
=
514 cpu_to_le16(priv
->wep_key
[i
].key_length
);
515 /* Set WEP key index */
516 key_param_set
->key
[0] = i
;
517 /* Set default Tx key flag */
520 wep_key_curr_index
& HostCmd_WEP_KEY_INDEX_MASK
))
521 key_param_set
->key
[1] = 1;
523 key_param_set
->key
[1] = 0;
524 memmove(&key_param_set
->key
[2],
525 priv
->wep_key
[i
].key_material
,
526 priv
->wep_key
[i
].key_length
);
528 cur_key_param_len
= priv
->wep_key
[i
].key_length
+
529 KEYPARAMSET_WEP_FIXED_LEN
+
530 sizeof(struct mwifiex_ie_types_header
);
531 *key_param_len
+= (u16
) cur_key_param_len
;
533 (struct mwifiex_ie_type_key_param_set
*)
534 ((u8
*)key_param_set
+
536 } else if (!priv
->wep_key
[i
].key_length
) {
539 dev_err(priv
->adapter
->dev
,
540 "key%d Length = %d is incorrect\n",
541 (i
+ 1), priv
->wep_key
[i
].key_length
);
549 /* This function populates key material v2 command
550 * to set network key for AES & CMAC AES.
552 static int mwifiex_set_aes_key_v2(struct mwifiex_private
*priv
,
553 struct host_cmd_ds_command
*cmd
,
554 struct mwifiex_ds_encrypt_key
*enc_key
,
555 struct host_cmd_ds_802_11_key_material_v2
*km
)
557 struct mwifiex_adapter
*adapter
= priv
->adapter
;
558 u16 size
, len
= KEY_PARAMS_FIXED_LEN
;
560 if (enc_key
->is_igtk_key
) {
561 dev_dbg(adapter
->dev
, "%s: Set CMAC AES Key\n", __func__
);
562 if (enc_key
->is_rx_seq_valid
)
563 memcpy(km
->key_param_set
.key_params
.cmac_aes
.ipn
,
564 enc_key
->pn
, enc_key
->pn_len
);
565 km
->key_param_set
.key_info
&= cpu_to_le16(~KEY_MCAST
);
566 km
->key_param_set
.key_info
|= cpu_to_le16(KEY_IGTK
);
567 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES_CMAC
;
568 km
->key_param_set
.key_params
.cmac_aes
.key_len
=
569 cpu_to_le16(enc_key
->key_len
);
570 memcpy(km
->key_param_set
.key_params
.cmac_aes
.key
,
571 enc_key
->key_material
, enc_key
->key_len
);
572 len
+= sizeof(struct mwifiex_cmac_aes_param
);
574 dev_dbg(adapter
->dev
, "%s: Set AES Key\n", __func__
);
575 if (enc_key
->is_rx_seq_valid
)
576 memcpy(km
->key_param_set
.key_params
.aes
.pn
,
577 enc_key
->pn
, enc_key
->pn_len
);
578 km
->key_param_set
.key_type
= KEY_TYPE_ID_AES
;
579 km
->key_param_set
.key_params
.aes
.key_len
=
580 cpu_to_le16(enc_key
->key_len
);
581 memcpy(km
->key_param_set
.key_params
.aes
.key
,
582 enc_key
->key_material
, enc_key
->key_len
);
583 len
+= sizeof(struct mwifiex_aes_param
);
586 km
->key_param_set
.len
= cpu_to_le16(len
);
587 size
= len
+ sizeof(struct mwifiex_ie_types_header
) +
588 sizeof(km
->action
) + S_DS_GEN
;
589 cmd
->size
= cpu_to_le16(size
);
594 /* This function prepares command to set/get/reset network key(s).
595 * This function prepares key material command for V2 format.
596 * Preparation includes -
597 * - Setting command ID, action and proper size
598 * - Setting WEP keys, WAPI keys or WPA keys along with required
599 * encryption (TKIP, AES) (as required)
600 * - Ensuring correct endian-ness
603 mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private
*priv
,
604 struct host_cmd_ds_command
*cmd
,
605 u16 cmd_action
, u32 cmd_oid
,
606 struct mwifiex_ds_encrypt_key
*enc_key
)
608 struct mwifiex_adapter
*adapter
= priv
->adapter
;
609 u8
*mac
= enc_key
->mac_addr
;
610 u16 key_info
, len
= KEY_PARAMS_FIXED_LEN
;
611 struct host_cmd_ds_802_11_key_material_v2
*km
=
612 &cmd
->params
.key_material_v2
;
614 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
615 km
->action
= cpu_to_le16(cmd_action
);
617 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
618 dev_dbg(adapter
->dev
, "%s: Get key\n", __func__
);
619 km
->key_param_set
.key_idx
=
620 enc_key
->key_index
& KEY_INDEX_MASK
;
621 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
622 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
623 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
625 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
626 key_info
= KEY_UNICAST
;
628 key_info
= KEY_MCAST
;
630 if (enc_key
->is_igtk_key
)
631 key_info
|= KEY_IGTK
;
633 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
635 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
636 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
641 memset(&km
->key_param_set
, 0,
642 sizeof(struct mwifiex_ie_type_key_param_set_v2
));
644 if (enc_key
->key_disable
) {
645 dev_dbg(adapter
->dev
, "%s: Remove key\n", __func__
);
646 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_REMOVE
);
647 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
648 km
->key_param_set
.len
= cpu_to_le16(KEY_PARAMS_FIXED_LEN
);
649 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
650 key_info
= KEY_MCAST
| KEY_UNICAST
;
651 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
652 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
653 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
654 S_DS_GEN
+ KEY_PARAMS_FIXED_LEN
+
659 km
->action
= cpu_to_le16(HostCmd_ACT_GEN_SET
);
660 km
->key_param_set
.key_idx
= enc_key
->key_index
& KEY_INDEX_MASK
;
661 km
->key_param_set
.type
= cpu_to_le16(TLV_TYPE_KEY_PARAM_V2
);
662 key_info
= KEY_ENABLED
;
663 memcpy(km
->key_param_set
.mac_addr
, mac
, ETH_ALEN
);
665 if (enc_key
->key_len
<= WLAN_KEY_LEN_WEP104
) {
666 dev_dbg(adapter
->dev
, "%s: Set WEP Key\n", __func__
);
667 len
+= sizeof(struct mwifiex_wep_param
);
668 km
->key_param_set
.len
= cpu_to_le16(len
);
669 km
->key_param_set
.key_type
= KEY_TYPE_ID_WEP
;
671 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
672 key_info
|= KEY_MCAST
| KEY_UNICAST
;
674 if (enc_key
->is_current_wep_key
) {
675 key_info
|= KEY_MCAST
| KEY_UNICAST
;
676 if (km
->key_param_set
.key_idx
==
677 (priv
->wep_key_curr_index
& KEY_INDEX_MASK
))
678 key_info
|= KEY_DEFAULT
;
681 if (is_broadcast_ether_addr(mac
))
682 key_info
|= KEY_MCAST
;
684 key_info
|= KEY_UNICAST
|
687 key_info
|= KEY_MCAST
;
691 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
693 km
->key_param_set
.key_params
.wep
.key_len
=
694 cpu_to_le16(enc_key
->key_len
);
695 memcpy(km
->key_param_set
.key_params
.wep
.key
,
696 enc_key
->key_material
, enc_key
->key_len
);
698 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
699 len
+ sizeof(km
->action
) + S_DS_GEN
);
703 if (is_broadcast_ether_addr(mac
))
704 key_info
|= KEY_MCAST
| KEY_RX_KEY
;
706 key_info
|= KEY_UNICAST
| KEY_TX_KEY
| KEY_RX_KEY
;
708 if (enc_key
->is_wapi_key
) {
709 dev_dbg(adapter
->dev
, "%s: Set WAPI Key\n", __func__
);
710 km
->key_param_set
.key_type
= KEY_TYPE_ID_WAPI
;
711 memcpy(km
->key_param_set
.key_params
.wapi
.pn
, enc_key
->pn
,
713 km
->key_param_set
.key_params
.wapi
.key_len
=
714 cpu_to_le16(enc_key
->key_len
);
715 memcpy(km
->key_param_set
.key_params
.wapi
.key
,
716 enc_key
->key_material
, enc_key
->key_len
);
717 if (is_broadcast_ether_addr(mac
))
718 priv
->sec_info
.wapi_key_on
= true;
720 if (!priv
->sec_info
.wapi_key_on
)
721 key_info
|= KEY_DEFAULT
;
722 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
724 len
+= sizeof(struct mwifiex_wapi_param
);
725 km
->key_param_set
.len
= cpu_to_le16(len
);
726 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
727 len
+ sizeof(km
->action
) + S_DS_GEN
);
731 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
) {
732 key_info
|= KEY_DEFAULT
;
733 /* Enable unicast bit for WPA-NONE/ADHOC_AES */
734 if (!priv
->sec_info
.wpa2_enabled
&&
735 !is_broadcast_ether_addr(mac
))
736 key_info
|= KEY_UNICAST
;
738 /* Enable default key for WPA/WPA2 */
739 if (!priv
->wpa_is_gtk_set
)
740 key_info
|= KEY_DEFAULT
;
743 km
->key_param_set
.key_info
= cpu_to_le16(key_info
);
745 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
)
746 return mwifiex_set_aes_key_v2(priv
, cmd
, enc_key
, km
);
748 if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
749 dev_dbg(adapter
->dev
, "%s: Set TKIP Key\n", __func__
);
750 if (enc_key
->is_rx_seq_valid
)
751 memcpy(km
->key_param_set
.key_params
.tkip
.pn
,
752 enc_key
->pn
, enc_key
->pn_len
);
753 km
->key_param_set
.key_type
= KEY_TYPE_ID_TKIP
;
754 km
->key_param_set
.key_params
.tkip
.key_len
=
755 cpu_to_le16(enc_key
->key_len
);
756 memcpy(km
->key_param_set
.key_params
.tkip
.key
,
757 enc_key
->key_material
, enc_key
->key_len
);
759 len
+= sizeof(struct mwifiex_tkip_param
);
760 km
->key_param_set
.len
= cpu_to_le16(len
);
761 cmd
->size
= cpu_to_le16(sizeof(struct mwifiex_ie_types_header
) +
762 len
+ sizeof(km
->action
) + S_DS_GEN
);
769 * This function prepares command to set/get/reset network key(s).
770 * This function prepares key material command for V1 format.
772 * Preparation includes -
773 * - Setting command ID, action and proper size
774 * - Setting WEP keys, WAPI keys or WPA keys along with required
775 * encryption (TKIP, AES) (as required)
776 * - Ensuring correct endian-ness
779 mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private
*priv
,
780 struct host_cmd_ds_command
*cmd
,
781 u16 cmd_action
, u32 cmd_oid
,
782 struct mwifiex_ds_encrypt_key
*enc_key
)
784 struct host_cmd_ds_802_11_key_material
*key_material
=
785 &cmd
->params
.key_material
;
786 struct host_cmd_tlv_mac_addr
*tlv_mac
;
787 u16 key_param_len
= 0, cmd_size
;
790 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL
);
791 key_material
->action
= cpu_to_le16(cmd_action
);
793 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
795 cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
);
800 memset(&key_material
->key_param_set
, 0,
802 sizeof(struct mwifiex_ie_type_key_param_set
)));
803 ret
= mwifiex_set_keyparamset_wep(priv
,
804 &key_material
->key_param_set
,
806 cmd
->size
= cpu_to_le16(key_param_len
+
807 sizeof(key_material
->action
) + S_DS_GEN
);
810 memset(&key_material
->key_param_set
, 0,
811 sizeof(struct mwifiex_ie_type_key_param_set
));
812 if (enc_key
->is_wapi_key
) {
813 dev_dbg(priv
->adapter
->dev
, "info: Set WAPI Key\n");
814 key_material
->key_param_set
.key_type_id
=
815 cpu_to_le16(KEY_TYPE_ID_WAPI
);
816 if (cmd_oid
== KEY_INFO_ENABLED
)
817 key_material
->key_param_set
.key_info
=
818 cpu_to_le16(KEY_ENABLED
);
820 key_material
->key_param_set
.key_info
=
821 cpu_to_le16(!KEY_ENABLED
);
823 key_material
->key_param_set
.key
[0] = enc_key
->key_index
;
824 if (!priv
->sec_info
.wapi_key_on
)
825 key_material
->key_param_set
.key
[1] = 1;
827 /* set 0 when re-key */
828 key_material
->key_param_set
.key
[1] = 0;
830 if (!is_broadcast_ether_addr(enc_key
->mac_addr
)) {
831 /* WAPI pairwise key: unicast */
832 key_material
->key_param_set
.key_info
|=
833 cpu_to_le16(KEY_UNICAST
);
834 } else { /* WAPI group key: multicast */
835 key_material
->key_param_set
.key_info
|=
836 cpu_to_le16(KEY_MCAST
);
837 priv
->sec_info
.wapi_key_on
= true;
840 key_material
->key_param_set
.type
=
841 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
842 key_material
->key_param_set
.key_len
=
843 cpu_to_le16(WAPI_KEY_LEN
);
844 memcpy(&key_material
->key_param_set
.key
[2],
845 enc_key
->key_material
, enc_key
->key_len
);
846 memcpy(&key_material
->key_param_set
.key
[2 + enc_key
->key_len
],
847 enc_key
->pn
, PN_LEN
);
848 key_material
->key_param_set
.length
=
849 cpu_to_le16(WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
);
851 key_param_len
= (WAPI_KEY_LEN
+ KEYPARAMSET_FIXED_LEN
) +
852 sizeof(struct mwifiex_ie_types_header
);
853 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
)
854 + S_DS_GEN
+ key_param_len
);
857 if (enc_key
->key_len
== WLAN_KEY_LEN_CCMP
) {
858 if (enc_key
->is_igtk_key
) {
859 dev_dbg(priv
->adapter
->dev
, "cmd: CMAC_AES\n");
860 key_material
->key_param_set
.key_type_id
=
861 cpu_to_le16(KEY_TYPE_ID_AES_CMAC
);
862 if (cmd_oid
== KEY_INFO_ENABLED
)
863 key_material
->key_param_set
.key_info
=
864 cpu_to_le16(KEY_ENABLED
);
866 key_material
->key_param_set
.key_info
=
867 cpu_to_le16(!KEY_ENABLED
);
869 key_material
->key_param_set
.key_info
|=
870 cpu_to_le16(KEY_IGTK
);
872 dev_dbg(priv
->adapter
->dev
, "cmd: WPA_AES\n");
873 key_material
->key_param_set
.key_type_id
=
874 cpu_to_le16(KEY_TYPE_ID_AES
);
875 if (cmd_oid
== KEY_INFO_ENABLED
)
876 key_material
->key_param_set
.key_info
=
877 cpu_to_le16(KEY_ENABLED
);
879 key_material
->key_param_set
.key_info
=
880 cpu_to_le16(!KEY_ENABLED
);
882 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
883 /* AES pairwise key: unicast */
884 key_material
->key_param_set
.key_info
|=
885 cpu_to_le16(KEY_UNICAST
);
886 else /* AES group key: multicast */
887 key_material
->key_param_set
.key_info
|=
888 cpu_to_le16(KEY_MCAST
);
890 } else if (enc_key
->key_len
== WLAN_KEY_LEN_TKIP
) {
891 dev_dbg(priv
->adapter
->dev
, "cmd: WPA_TKIP\n");
892 key_material
->key_param_set
.key_type_id
=
893 cpu_to_le16(KEY_TYPE_ID_TKIP
);
894 key_material
->key_param_set
.key_info
=
895 cpu_to_le16(KEY_ENABLED
);
897 if (enc_key
->key_index
& MWIFIEX_KEY_INDEX_UNICAST
)
898 /* TKIP pairwise key: unicast */
899 key_material
->key_param_set
.key_info
|=
900 cpu_to_le16(KEY_UNICAST
);
901 else /* TKIP group key: multicast */
902 key_material
->key_param_set
.key_info
|=
903 cpu_to_le16(KEY_MCAST
);
906 if (key_material
->key_param_set
.key_type_id
) {
907 key_material
->key_param_set
.type
=
908 cpu_to_le16(TLV_TYPE_KEY_MATERIAL
);
909 key_material
->key_param_set
.key_len
=
910 cpu_to_le16((u16
) enc_key
->key_len
);
911 memcpy(key_material
->key_param_set
.key
, enc_key
->key_material
,
913 key_material
->key_param_set
.length
=
914 cpu_to_le16((u16
) enc_key
->key_len
+
915 KEYPARAMSET_FIXED_LEN
);
917 key_param_len
= (u16
)(enc_key
->key_len
+ KEYPARAMSET_FIXED_LEN
)
918 + sizeof(struct mwifiex_ie_types_header
);
920 if (le16_to_cpu(key_material
->key_param_set
.key_type_id
) ==
921 KEY_TYPE_ID_AES_CMAC
) {
922 struct mwifiex_cmac_param
*param
=
923 (void *)key_material
->key_param_set
.key
;
925 memcpy(param
->ipn
, enc_key
->pn
, IGTK_PN_LEN
);
926 memcpy(param
->key
, enc_key
->key_material
,
927 WLAN_KEY_LEN_AES_CMAC
);
929 key_param_len
= sizeof(struct mwifiex_cmac_param
);
930 key_material
->key_param_set
.key_len
=
931 cpu_to_le16(key_param_len
);
932 key_param_len
+= KEYPARAMSET_FIXED_LEN
;
933 key_material
->key_param_set
.length
=
934 cpu_to_le16(key_param_len
);
935 key_param_len
+= sizeof(struct mwifiex_ie_types_header
);
938 cmd
->size
= cpu_to_le16(sizeof(key_material
->action
) + S_DS_GEN
941 if (GET_BSS_ROLE(priv
) == MWIFIEX_BSS_ROLE_UAP
) {
942 tlv_mac
= (void *)((u8
*)&key_material
->key_param_set
+
944 tlv_mac
->header
.type
=
945 cpu_to_le16(TLV_TYPE_STA_MAC_ADDR
);
946 tlv_mac
->header
.len
= cpu_to_le16(ETH_ALEN
);
947 memcpy(tlv_mac
->mac_addr
, enc_key
->mac_addr
, ETH_ALEN
);
948 cmd_size
= key_param_len
+ S_DS_GEN
+
949 sizeof(key_material
->action
) +
950 sizeof(struct host_cmd_tlv_mac_addr
);
952 cmd_size
= key_param_len
+ S_DS_GEN
+
953 sizeof(key_material
->action
);
955 cmd
->size
= cpu_to_le16(cmd_size
);
961 /* Wrapper function for setting network key depending upon FW KEY API version */
963 mwifiex_cmd_802_11_key_material(struct mwifiex_private
*priv
,
964 struct host_cmd_ds_command
*cmd
,
965 u16 cmd_action
, u32 cmd_oid
,
966 struct mwifiex_ds_encrypt_key
*enc_key
)
968 if (priv
->adapter
->key_api_major_ver
== KEY_API_VER_MAJOR_V2
)
969 return mwifiex_cmd_802_11_key_material_v2(priv
, cmd
,
974 return mwifiex_cmd_802_11_key_material_v1(priv
, cmd
,
980 * This function prepares command to set/get 11d domain information.
982 * Preparation includes -
983 * - Setting command ID, action and proper size
984 * - Setting domain information fields (for SET only)
985 * - Ensuring correct endian-ness
987 static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private
*priv
,
988 struct host_cmd_ds_command
*cmd
,
991 struct mwifiex_adapter
*adapter
= priv
->adapter
;
992 struct host_cmd_ds_802_11d_domain_info
*domain_info
=
993 &cmd
->params
.domain_info
;
994 struct mwifiex_ietypes_domain_param_set
*domain
=
995 &domain_info
->domain
;
996 u8 no_of_triplet
= adapter
->domain_reg
.no_of_triplet
;
998 dev_dbg(adapter
->dev
, "info: 11D: no_of_triplet=0x%x\n", no_of_triplet
);
1000 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO
);
1001 domain_info
->action
= cpu_to_le16(cmd_action
);
1002 if (cmd_action
== HostCmd_ACT_GEN_GET
) {
1003 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1007 /* Set domain info fields */
1008 domain
->header
.type
= cpu_to_le16(WLAN_EID_COUNTRY
);
1009 memcpy(domain
->country_code
, adapter
->domain_reg
.country_code
,
1010 sizeof(domain
->country_code
));
1012 domain
->header
.len
=
1013 cpu_to_le16((no_of_triplet
*
1014 sizeof(struct ieee80211_country_ie_triplet
))
1015 + sizeof(domain
->country_code
));
1017 if (no_of_triplet
) {
1018 memcpy(domain
->triplet
, adapter
->domain_reg
.triplet
,
1019 no_of_triplet
* sizeof(struct
1020 ieee80211_country_ie_triplet
));
1022 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) +
1023 le16_to_cpu(domain
->header
.len
) +
1024 sizeof(struct mwifiex_ie_types_header
)
1027 cmd
->size
= cpu_to_le16(sizeof(domain_info
->action
) + S_DS_GEN
);
1034 * This function prepares command to set/get IBSS coalescing status.
1036 * Preparation includes -
1037 * - Setting command ID, action and proper size
1038 * - Setting status to enable or disable (for SET only)
1039 * - Ensuring correct endian-ness
1041 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command
*cmd
,
1042 u16 cmd_action
, u16
*enable
)
1044 struct host_cmd_ds_802_11_ibss_status
*ibss_coal
=
1045 &(cmd
->params
.ibss_coalescing
);
1047 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
);
1048 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status
) +
1051 ibss_coal
->action
= cpu_to_le16(cmd_action
);
1053 switch (cmd_action
) {
1054 case HostCmd_ACT_GEN_SET
:
1056 ibss_coal
->enable
= cpu_to_le16(*enable
);
1058 ibss_coal
->enable
= 0;
1061 /* In other case.. Nothing to do */
1062 case HostCmd_ACT_GEN_GET
:
1071 * This function prepares command to set/get register value.
1073 * Preparation includes -
1074 * - Setting command ID, action and proper size
1075 * - Setting register offset (for both GET and SET) and
1076 * register value (for SET only)
1077 * - Ensuring correct endian-ness
1079 * The following type of registers can be accessed with this function -
1087 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command
*cmd
,
1088 u16 cmd_action
, void *data_buf
)
1090 struct mwifiex_ds_reg_rw
*reg_rw
= data_buf
;
1092 switch (le16_to_cpu(cmd
->command
)) {
1093 case HostCmd_CMD_MAC_REG_ACCESS
:
1095 struct host_cmd_ds_mac_reg_access
*mac_reg
;
1097 cmd
->size
= cpu_to_le16(sizeof(*mac_reg
) + S_DS_GEN
);
1098 mac_reg
= &cmd
->params
.mac_reg
;
1099 mac_reg
->action
= cpu_to_le16(cmd_action
);
1101 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1102 mac_reg
->value
= reg_rw
->value
;
1105 case HostCmd_CMD_BBP_REG_ACCESS
:
1107 struct host_cmd_ds_bbp_reg_access
*bbp_reg
;
1109 cmd
->size
= cpu_to_le16(sizeof(*bbp_reg
) + S_DS_GEN
);
1110 bbp_reg
= &cmd
->params
.bbp_reg
;
1111 bbp_reg
->action
= cpu_to_le16(cmd_action
);
1113 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1114 bbp_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1117 case HostCmd_CMD_RF_REG_ACCESS
:
1119 struct host_cmd_ds_rf_reg_access
*rf_reg
;
1121 cmd
->size
= cpu_to_le16(sizeof(*rf_reg
) + S_DS_GEN
);
1122 rf_reg
= &cmd
->params
.rf_reg
;
1123 rf_reg
->action
= cpu_to_le16(cmd_action
);
1124 rf_reg
->offset
= cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1125 rf_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1128 case HostCmd_CMD_PMIC_REG_ACCESS
:
1130 struct host_cmd_ds_pmic_reg_access
*pmic_reg
;
1132 cmd
->size
= cpu_to_le16(sizeof(*pmic_reg
) + S_DS_GEN
);
1133 pmic_reg
= &cmd
->params
.pmic_reg
;
1134 pmic_reg
->action
= cpu_to_le16(cmd_action
);
1136 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1137 pmic_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1140 case HostCmd_CMD_CAU_REG_ACCESS
:
1142 struct host_cmd_ds_rf_reg_access
*cau_reg
;
1144 cmd
->size
= cpu_to_le16(sizeof(*cau_reg
) + S_DS_GEN
);
1145 cau_reg
= &cmd
->params
.rf_reg
;
1146 cau_reg
->action
= cpu_to_le16(cmd_action
);
1148 cpu_to_le16((u16
) le32_to_cpu(reg_rw
->offset
));
1149 cau_reg
->value
= (u8
) le32_to_cpu(reg_rw
->value
);
1152 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1154 struct mwifiex_ds_read_eeprom
*rd_eeprom
= data_buf
;
1155 struct host_cmd_ds_802_11_eeprom_access
*cmd_eeprom
=
1156 &cmd
->params
.eeprom
;
1158 cmd
->size
= cpu_to_le16(sizeof(*cmd_eeprom
) + S_DS_GEN
);
1159 cmd_eeprom
->action
= cpu_to_le16(cmd_action
);
1160 cmd_eeprom
->offset
= rd_eeprom
->offset
;
1161 cmd_eeprom
->byte_count
= rd_eeprom
->byte_count
;
1162 cmd_eeprom
->value
= 0;
1173 * This function prepares command to set PCI-Express
1174 * host buffer configuration
1176 * Preparation includes -
1177 * - Setting command ID, action and proper size
1178 * - Setting host buffer configuration
1179 * - Ensuring correct endian-ness
1182 mwifiex_cmd_pcie_host_spec(struct mwifiex_private
*priv
,
1183 struct host_cmd_ds_command
*cmd
, u16 action
)
1185 struct host_cmd_ds_pcie_details
*host_spec
=
1186 &cmd
->params
.pcie_host_spec
;
1187 struct pcie_service_card
*card
= priv
->adapter
->card
;
1189 cmd
->command
= cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS
);
1190 cmd
->size
= cpu_to_le16(sizeof(struct
1191 host_cmd_ds_pcie_details
) + S_DS_GEN
);
1194 memset(host_spec
, 0, sizeof(struct host_cmd_ds_pcie_details
));
1196 if (action
!= HostCmd_ACT_GEN_SET
)
1199 /* Send the ring base addresses and count to firmware */
1200 host_spec
->txbd_addr_lo
= (u32
)(card
->txbd_ring_pbase
);
1201 host_spec
->txbd_addr_hi
= (u32
)(((u64
)card
->txbd_ring_pbase
)>>32);
1202 host_spec
->txbd_count
= MWIFIEX_MAX_TXRX_BD
;
1203 host_spec
->rxbd_addr_lo
= (u32
)(card
->rxbd_ring_pbase
);
1204 host_spec
->rxbd_addr_hi
= (u32
)(((u64
)card
->rxbd_ring_pbase
)>>32);
1205 host_spec
->rxbd_count
= MWIFIEX_MAX_TXRX_BD
;
1206 host_spec
->evtbd_addr_lo
= (u32
)(card
->evtbd_ring_pbase
);
1207 host_spec
->evtbd_addr_hi
= (u32
)(((u64
)card
->evtbd_ring_pbase
)>>32);
1208 host_spec
->evtbd_count
= MWIFIEX_MAX_EVT_BD
;
1209 if (card
->sleep_cookie_vbase
) {
1210 host_spec
->sleep_cookie_addr_lo
=
1211 (u32
)(card
->sleep_cookie_pbase
);
1212 host_spec
->sleep_cookie_addr_hi
=
1213 (u32
)(((u64
)(card
->sleep_cookie_pbase
)) >> 32);
1214 dev_dbg(priv
->adapter
->dev
, "sleep_cook_lo phy addr: 0x%x\n",
1215 host_spec
->sleep_cookie_addr_lo
);
1222 * This function prepares command for event subscription, configuration
1223 * and query. Events can be subscribed or unsubscribed. Current subscribed
1224 * events can be queried. Also, current subscribed events are reported in
1225 * every FW response.
1228 mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private
*priv
,
1229 struct host_cmd_ds_command
*cmd
,
1230 struct mwifiex_ds_misc_subsc_evt
*subsc_evt_cfg
)
1232 struct host_cmd_ds_802_11_subsc_evt
*subsc_evt
= &cmd
->params
.subsc_evt
;
1233 struct mwifiex_ie_types_rssi_threshold
*rssi_tlv
;
1237 cmd
->command
= cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT
);
1238 cmd
->size
= cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt
) +
1241 subsc_evt
->action
= cpu_to_le16(subsc_evt_cfg
->action
);
1242 dev_dbg(priv
->adapter
->dev
, "cmd: action: %d\n", subsc_evt_cfg
->action
);
1244 /*For query requests, no configuration TLV structures are to be added.*/
1245 if (subsc_evt_cfg
->action
== HostCmd_ACT_GEN_GET
)
1248 subsc_evt
->events
= cpu_to_le16(subsc_evt_cfg
->events
);
1250 event_bitmap
= subsc_evt_cfg
->events
;
1251 dev_dbg(priv
->adapter
->dev
, "cmd: event bitmap : %16x\n",
1254 if (((subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
) ||
1255 (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_SET
)) &&
1256 (event_bitmap
== 0)) {
1257 dev_dbg(priv
->adapter
->dev
, "Error: No event specified "
1258 "for bitwise action type\n");
1263 * Append TLV structures for each of the specified events for
1264 * subscribing or re-configuring. This is not required for
1265 * bitwise unsubscribing request.
1267 if (subsc_evt_cfg
->action
== HostCmd_ACT_BITWISE_CLR
)
1270 pos
= ((u8
*)subsc_evt
) +
1271 sizeof(struct host_cmd_ds_802_11_subsc_evt
);
1273 if (event_bitmap
& BITMASK_BCN_RSSI_LOW
) {
1274 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1276 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_LOW
);
1277 rssi_tlv
->header
.len
=
1278 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1279 sizeof(struct mwifiex_ie_types_header
));
1280 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
;
1281 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
;
1283 dev_dbg(priv
->adapter
->dev
, "Cfg Beacon Low Rssi event, "
1284 "RSSI:-%d dBm, Freq:%d\n",
1285 subsc_evt_cfg
->bcn_l_rssi_cfg
.abs_value
,
1286 subsc_evt_cfg
->bcn_l_rssi_cfg
.evt_freq
);
1288 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1289 le16_add_cpu(&cmd
->size
,
1290 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1293 if (event_bitmap
& BITMASK_BCN_RSSI_HIGH
) {
1294 rssi_tlv
= (struct mwifiex_ie_types_rssi_threshold
*) pos
;
1296 rssi_tlv
->header
.type
= cpu_to_le16(TLV_TYPE_RSSI_HIGH
);
1297 rssi_tlv
->header
.len
=
1298 cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold
) -
1299 sizeof(struct mwifiex_ie_types_header
));
1300 rssi_tlv
->abs_value
= subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
;
1301 rssi_tlv
->evt_freq
= subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
;
1303 dev_dbg(priv
->adapter
->dev
, "Cfg Beacon High Rssi event, "
1304 "RSSI:-%d dBm, Freq:%d\n",
1305 subsc_evt_cfg
->bcn_h_rssi_cfg
.abs_value
,
1306 subsc_evt_cfg
->bcn_h_rssi_cfg
.evt_freq
);
1308 pos
+= sizeof(struct mwifiex_ie_types_rssi_threshold
);
1309 le16_add_cpu(&cmd
->size
,
1310 sizeof(struct mwifiex_ie_types_rssi_threshold
));
1317 mwifiex_cmd_append_rpn_expression(struct mwifiex_private
*priv
,
1318 struct mwifiex_mef_entry
*mef_entry
,
1321 struct mwifiex_mef_filter
*filter
= mef_entry
->filter
;
1323 u8
*stack_ptr
= *buffer
;
1325 for (i
= 0; i
< MWIFIEX_MEF_MAX_FILTERS
; i
++) {
1326 filter
= &mef_entry
->filter
[i
];
1327 if (!filter
->filt_type
)
1329 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->repeat
);
1331 *stack_ptr
= TYPE_DNUM
;
1334 byte_len
= filter
->byte_seq
[MWIFIEX_MEF_MAX_BYTESEQ
];
1335 memcpy(stack_ptr
, filter
->byte_seq
, byte_len
);
1336 stack_ptr
+= byte_len
;
1337 *stack_ptr
= byte_len
;
1339 *stack_ptr
= TYPE_BYTESEQ
;
1342 *(__le32
*)stack_ptr
= cpu_to_le32((u32
)filter
->offset
);
1344 *stack_ptr
= TYPE_DNUM
;
1347 *stack_ptr
= filter
->filt_type
;
1350 if (filter
->filt_action
) {
1351 *stack_ptr
= filter
->filt_action
;
1355 if (stack_ptr
- *buffer
> STACK_NBYTES
)
1359 *buffer
= stack_ptr
;
1364 mwifiex_cmd_mef_cfg(struct mwifiex_private
*priv
,
1365 struct host_cmd_ds_command
*cmd
,
1366 struct mwifiex_ds_mef_cfg
*mef
)
1368 struct host_cmd_ds_mef_cfg
*mef_cfg
= &cmd
->params
.mef_cfg
;
1369 u8
*pos
= (u8
*)mef_cfg
;
1371 cmd
->command
= cpu_to_le16(HostCmd_CMD_MEF_CFG
);
1373 mef_cfg
->criteria
= cpu_to_le32(mef
->criteria
);
1374 mef_cfg
->num_entries
= cpu_to_le16(mef
->num_entries
);
1375 pos
+= sizeof(*mef_cfg
);
1376 mef_cfg
->mef_entry
->mode
= mef
->mef_entry
->mode
;
1377 mef_cfg
->mef_entry
->action
= mef
->mef_entry
->action
;
1378 pos
+= sizeof(*(mef_cfg
->mef_entry
));
1380 if (mwifiex_cmd_append_rpn_expression(priv
, mef
->mef_entry
, &pos
))
1383 mef_cfg
->mef_entry
->exprsize
=
1384 cpu_to_le16(pos
- mef_cfg
->mef_entry
->expr
);
1385 cmd
->size
= cpu_to_le16((u16
) (pos
- (u8
*)mef_cfg
) + S_DS_GEN
);
1390 /* This function parse cal data from ASCII to hex */
1391 static u32
mwifiex_parse_cal_cfg(u8
*src
, size_t len
, u8
*dst
)
1393 u8
*s
= src
, *d
= dst
;
1395 while (s
- src
< len
) {
1396 if (*s
&& (isspace(*s
) || *s
== '\t')) {
1401 *d
++ = simple_strtol(s
, NULL
, 16);
1411 int mwifiex_dnld_dt_cfgdata(struct mwifiex_private
*priv
,
1412 struct device_node
*node
, const char *prefix
)
1415 struct property
*prop
;
1416 size_t len
= strlen(prefix
);
1419 /* look for all matching property names */
1420 for_each_property_of_node(node
, prop
) {
1421 if (len
> strlen(prop
->name
) ||
1422 strncmp(prop
->name
, prefix
, len
))
1425 /* property header is 6 bytes, data must fit in cmd buffer */
1426 if (prop
&& prop
->value
&& prop
->length
> 6 &&
1427 prop
->length
<= MWIFIEX_SIZE_OF_CMD_BUFFER
- S_DS_GEN
) {
1428 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
1429 HostCmd_ACT_GEN_SET
, 0,
1439 /* This function prepares command of set_cfg_data. */
1440 static int mwifiex_cmd_cfg_data(struct mwifiex_private
*priv
,
1441 struct host_cmd_ds_command
*cmd
, void *data_buf
)
1443 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1444 struct property
*prop
= data_buf
;
1446 u8
*data
= (u8
*)cmd
+ S_DS_GEN
;
1451 ret
= of_property_read_u8_array(adapter
->dt_node
, prop
->name
,
1455 dev_dbg(adapter
->dev
,
1456 "download cfg_data from device tree: %s\n", prop
->name
);
1457 } else if (adapter
->cal_data
->data
&& adapter
->cal_data
->size
> 0) {
1458 len
= mwifiex_parse_cal_cfg((u8
*)adapter
->cal_data
->data
,
1459 adapter
->cal_data
->size
, data
);
1460 dev_dbg(adapter
->dev
, "download cfg_data from config file\n");
1465 cmd
->command
= cpu_to_le16(HostCmd_CMD_CFG_DATA
);
1466 cmd
->size
= cpu_to_le16(S_DS_GEN
+ len
);
1472 mwifiex_cmd_coalesce_cfg(struct mwifiex_private
*priv
,
1473 struct host_cmd_ds_command
*cmd
,
1474 u16 cmd_action
, void *data_buf
)
1476 struct host_cmd_ds_coalesce_cfg
*coalesce_cfg
=
1477 &cmd
->params
.coalesce_cfg
;
1478 struct mwifiex_ds_coalesce_cfg
*cfg
= data_buf
;
1479 struct coalesce_filt_field_param
*param
;
1480 u16 cnt
, idx
, length
;
1481 struct coalesce_receive_filt_rule
*rule
;
1483 cmd
->command
= cpu_to_le16(HostCmd_CMD_COALESCE_CFG
);
1484 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1486 coalesce_cfg
->action
= cpu_to_le16(cmd_action
);
1487 coalesce_cfg
->num_of_rules
= cpu_to_le16(cfg
->num_of_rules
);
1488 rule
= coalesce_cfg
->rule
;
1490 for (cnt
= 0; cnt
< cfg
->num_of_rules
; cnt
++) {
1491 rule
->header
.type
= cpu_to_le16(TLV_TYPE_COALESCE_RULE
);
1492 rule
->max_coalescing_delay
=
1493 cpu_to_le16(cfg
->rule
[cnt
].max_coalescing_delay
);
1494 rule
->pkt_type
= cfg
->rule
[cnt
].pkt_type
;
1495 rule
->num_of_fields
= cfg
->rule
[cnt
].num_of_fields
;
1499 param
= rule
->params
;
1500 for (idx
= 0; idx
< cfg
->rule
[cnt
].num_of_fields
; idx
++) {
1501 param
->operation
= cfg
->rule
[cnt
].params
[idx
].operation
;
1502 param
->operand_len
=
1503 cfg
->rule
[cnt
].params
[idx
].operand_len
;
1505 cpu_to_le16(cfg
->rule
[cnt
].params
[idx
].offset
);
1506 memcpy(param
->operand_byte_stream
,
1507 cfg
->rule
[cnt
].params
[idx
].operand_byte_stream
,
1508 param
->operand_len
);
1510 length
+= sizeof(struct coalesce_filt_field_param
);
1515 /* Total rule length is sizeof max_coalescing_delay(u16),
1516 * num_of_fields(u8), pkt_type(u8) and total length of the all
1519 rule
->header
.len
= cpu_to_le16(length
+ sizeof(u16
) +
1520 sizeof(u8
) + sizeof(u8
));
1522 /* Add the rule length to the command size*/
1523 le16_add_cpu(&cmd
->size
, le16_to_cpu(rule
->header
.len
) +
1524 sizeof(struct mwifiex_ie_types_header
));
1526 rule
= (void *)((u8
*)rule
->params
+ length
);
1529 /* Add sizeof action, num_of_rules to total command length */
1530 le16_add_cpu(&cmd
->size
, sizeof(u16
) + sizeof(u16
));
1536 mwifiex_cmd_tdls_oper(struct mwifiex_private
*priv
,
1537 struct host_cmd_ds_command
*cmd
,
1540 struct host_cmd_ds_tdls_oper
*tdls_oper
= &cmd
->params
.tdls_oper
;
1541 struct mwifiex_ds_tdls_oper
*oper
= data_buf
;
1542 struct mwifiex_sta_node
*sta_ptr
;
1543 struct host_cmd_tlv_rates
*tlv_rates
;
1544 struct mwifiex_ie_types_htcap
*ht_capab
;
1545 struct mwifiex_ie_types_qos_info
*wmm_qos_info
;
1546 struct mwifiex_ie_types_extcap
*extcap
;
1547 struct mwifiex_ie_types_vhtcap
*vht_capab
;
1548 struct mwifiex_ie_types_aid
*aid
;
1549 struct mwifiex_ie_types_tdls_idle_timeout
*timeout
;
1552 struct station_parameters
*params
= priv
->sta_params
;
1554 cmd
->command
= cpu_to_le16(HostCmd_CMD_TDLS_OPER
);
1555 cmd
->size
= cpu_to_le16(S_DS_GEN
);
1556 le16_add_cpu(&cmd
->size
, sizeof(struct host_cmd_ds_tdls_oper
));
1558 tdls_oper
->reason
= 0;
1559 memcpy(tdls_oper
->peer_mac
, oper
->peer_mac
, ETH_ALEN
);
1560 sta_ptr
= mwifiex_get_sta_entry(priv
, oper
->peer_mac
);
1562 pos
= (u8
*)tdls_oper
+ sizeof(struct host_cmd_ds_tdls_oper
);
1564 switch (oper
->tdls_action
) {
1565 case MWIFIEX_TDLS_DISABLE_LINK
:
1566 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_DELETE
);
1568 case MWIFIEX_TDLS_CREATE_LINK
:
1569 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CREATE
);
1571 case MWIFIEX_TDLS_CONFIG_LINK
:
1572 tdls_oper
->tdls_action
= cpu_to_le16(ACT_TDLS_CONFIG
);
1575 dev_err(priv
->adapter
->dev
,
1576 "TDLS config params not available for %pM\n",
1581 *(__le16
*)pos
= cpu_to_le16(params
->capability
);
1582 config_len
+= sizeof(params
->capability
);
1584 qos_info
= params
->uapsd_queues
| (params
->max_sp
<< 5);
1585 wmm_qos_info
= (struct mwifiex_ie_types_qos_info
*)(pos
+
1587 wmm_qos_info
->header
.type
= cpu_to_le16(WLAN_EID_QOS_CAPA
);
1588 wmm_qos_info
->header
.len
= cpu_to_le16(sizeof(qos_info
));
1589 wmm_qos_info
->qos_info
= qos_info
;
1590 config_len
+= sizeof(struct mwifiex_ie_types_qos_info
);
1592 if (params
->ht_capa
) {
1593 ht_capab
= (struct mwifiex_ie_types_htcap
*)(pos
+
1595 ht_capab
->header
.type
=
1596 cpu_to_le16(WLAN_EID_HT_CAPABILITY
);
1597 ht_capab
->header
.len
=
1598 cpu_to_le16(sizeof(struct ieee80211_ht_cap
));
1599 memcpy(&ht_capab
->ht_cap
, params
->ht_capa
,
1600 sizeof(struct ieee80211_ht_cap
));
1601 config_len
+= sizeof(struct mwifiex_ie_types_htcap
);
1604 if (params
->supported_rates
&& params
->supported_rates_len
) {
1605 tlv_rates
= (struct host_cmd_tlv_rates
*)(pos
+
1607 tlv_rates
->header
.type
=
1608 cpu_to_le16(WLAN_EID_SUPP_RATES
);
1609 tlv_rates
->header
.len
=
1610 cpu_to_le16(params
->supported_rates_len
);
1611 memcpy(tlv_rates
->rates
, params
->supported_rates
,
1612 params
->supported_rates_len
);
1613 config_len
+= sizeof(struct host_cmd_tlv_rates
) +
1614 params
->supported_rates_len
;
1617 if (params
->ext_capab
&& params
->ext_capab_len
) {
1618 extcap
= (struct mwifiex_ie_types_extcap
*)(pos
+
1620 extcap
->header
.type
=
1621 cpu_to_le16(WLAN_EID_EXT_CAPABILITY
);
1622 extcap
->header
.len
= cpu_to_le16(params
->ext_capab_len
);
1623 memcpy(extcap
->ext_capab
, params
->ext_capab
,
1624 params
->ext_capab_len
);
1625 config_len
+= sizeof(struct mwifiex_ie_types_extcap
) +
1626 params
->ext_capab_len
;
1628 if (params
->vht_capa
) {
1629 vht_capab
= (struct mwifiex_ie_types_vhtcap
*)(pos
+
1631 vht_capab
->header
.type
=
1632 cpu_to_le16(WLAN_EID_VHT_CAPABILITY
);
1633 vht_capab
->header
.len
=
1634 cpu_to_le16(sizeof(struct ieee80211_vht_cap
));
1635 memcpy(&vht_capab
->vht_cap
, params
->vht_capa
,
1636 sizeof(struct ieee80211_vht_cap
));
1637 config_len
+= sizeof(struct mwifiex_ie_types_vhtcap
);
1640 aid
= (struct mwifiex_ie_types_aid
*)(pos
+ config_len
);
1641 aid
->header
.type
= cpu_to_le16(WLAN_EID_AID
);
1642 aid
->header
.len
= cpu_to_le16(sizeof(params
->aid
));
1643 aid
->aid
= cpu_to_le16(params
->aid
);
1644 config_len
+= sizeof(struct mwifiex_ie_types_aid
);
1647 timeout
= (void *)(pos
+ config_len
);
1648 timeout
->header
.type
= cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT
);
1649 timeout
->header
.len
= cpu_to_le16(sizeof(timeout
->value
));
1650 timeout
->value
= cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC
);
1651 config_len
+= sizeof(struct mwifiex_ie_types_tdls_idle_timeout
);
1655 dev_err(priv
->adapter
->dev
, "Unknown TDLS operation\n");
1659 le16_add_cpu(&cmd
->size
, config_len
);
1664 * This function prepares the commands before sending them to the firmware.
1666 * This is a generic function which calls specific command preparation
1667 * routines based upon the command number.
1669 int mwifiex_sta_prepare_cmd(struct mwifiex_private
*priv
, uint16_t cmd_no
,
1670 u16 cmd_action
, u32 cmd_oid
,
1671 void *data_buf
, void *cmd_buf
)
1673 struct host_cmd_ds_command
*cmd_ptr
= cmd_buf
;
1676 /* Prepare command */
1678 case HostCmd_CMD_GET_HW_SPEC
:
1679 ret
= mwifiex_cmd_get_hw_spec(priv
, cmd_ptr
);
1681 case HostCmd_CMD_CFG_DATA
:
1682 ret
= mwifiex_cmd_cfg_data(priv
, cmd_ptr
, data_buf
);
1684 case HostCmd_CMD_MAC_CONTROL
:
1685 ret
= mwifiex_cmd_mac_control(priv
, cmd_ptr
, cmd_action
,
1688 case HostCmd_CMD_802_11_MAC_ADDRESS
:
1689 ret
= mwifiex_cmd_802_11_mac_address(priv
, cmd_ptr
,
1692 case HostCmd_CMD_MAC_MULTICAST_ADR
:
1693 ret
= mwifiex_cmd_mac_multicast_adr(cmd_ptr
, cmd_action
,
1696 case HostCmd_CMD_TX_RATE_CFG
:
1697 ret
= mwifiex_cmd_tx_rate_cfg(priv
, cmd_ptr
, cmd_action
,
1700 case HostCmd_CMD_TXPWR_CFG
:
1701 ret
= mwifiex_cmd_tx_power_cfg(cmd_ptr
, cmd_action
,
1704 case HostCmd_CMD_RF_TX_PWR
:
1705 ret
= mwifiex_cmd_rf_tx_power(priv
, cmd_ptr
, cmd_action
,
1708 case HostCmd_CMD_RF_ANTENNA
:
1709 ret
= mwifiex_cmd_rf_antenna(priv
, cmd_ptr
, cmd_action
,
1712 case HostCmd_CMD_802_11_PS_MODE_ENH
:
1713 ret
= mwifiex_cmd_enh_power_mode(priv
, cmd_ptr
, cmd_action
,
1714 (uint16_t)cmd_oid
, data_buf
);
1716 case HostCmd_CMD_802_11_HS_CFG_ENH
:
1717 ret
= mwifiex_cmd_802_11_hs_cfg(priv
, cmd_ptr
, cmd_action
,
1718 (struct mwifiex_hs_config_param
*) data_buf
);
1720 case HostCmd_CMD_802_11_SCAN
:
1721 ret
= mwifiex_cmd_802_11_scan(cmd_ptr
, data_buf
);
1723 case HostCmd_CMD_802_11_BG_SCAN_QUERY
:
1724 ret
= mwifiex_cmd_802_11_bg_scan_query(cmd_ptr
);
1726 case HostCmd_CMD_802_11_ASSOCIATE
:
1727 ret
= mwifiex_cmd_802_11_associate(priv
, cmd_ptr
, data_buf
);
1729 case HostCmd_CMD_802_11_DEAUTHENTICATE
:
1730 ret
= mwifiex_cmd_802_11_deauthenticate(priv
, cmd_ptr
,
1733 case HostCmd_CMD_802_11_AD_HOC_START
:
1734 ret
= mwifiex_cmd_802_11_ad_hoc_start(priv
, cmd_ptr
,
1737 case HostCmd_CMD_802_11_GET_LOG
:
1738 ret
= mwifiex_cmd_802_11_get_log(cmd_ptr
);
1740 case HostCmd_CMD_802_11_AD_HOC_JOIN
:
1741 ret
= mwifiex_cmd_802_11_ad_hoc_join(priv
, cmd_ptr
,
1744 case HostCmd_CMD_802_11_AD_HOC_STOP
:
1745 ret
= mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr
);
1747 case HostCmd_CMD_RSSI_INFO
:
1748 ret
= mwifiex_cmd_802_11_rssi_info(priv
, cmd_ptr
, cmd_action
);
1750 case HostCmd_CMD_802_11_SNMP_MIB
:
1751 ret
= mwifiex_cmd_802_11_snmp_mib(priv
, cmd_ptr
, cmd_action
,
1754 case HostCmd_CMD_802_11_TX_RATE_QUERY
:
1756 cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY
);
1758 cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query
) +
1763 case HostCmd_CMD_VERSION_EXT
:
1764 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1765 cmd_ptr
->params
.verext
.version_str_sel
=
1766 (u8
) (*((u32
*) data_buf
));
1767 memcpy(&cmd_ptr
->params
, data_buf
,
1768 sizeof(struct host_cmd_ds_version_ext
));
1770 cpu_to_le16(sizeof(struct host_cmd_ds_version_ext
) +
1774 case HostCmd_CMD_MGMT_FRAME_REG
:
1775 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1776 cmd_ptr
->params
.reg_mask
.action
= cpu_to_le16(cmd_action
);
1777 cmd_ptr
->params
.reg_mask
.mask
= cpu_to_le32(*(u32
*)data_buf
);
1779 cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg
) +
1783 case HostCmd_CMD_REMAIN_ON_CHAN
:
1784 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1785 memcpy(&cmd_ptr
->params
, data_buf
,
1786 sizeof(struct host_cmd_ds_remain_on_chan
));
1788 cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan
) +
1791 case HostCmd_CMD_11AC_CFG
:
1792 ret
= mwifiex_cmd_11ac_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
1794 case HostCmd_CMD_P2P_MODE_CFG
:
1795 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1796 cmd_ptr
->params
.mode_cfg
.action
= cpu_to_le16(cmd_action
);
1797 cmd_ptr
->params
.mode_cfg
.mode
= cpu_to_le16(*(u16
*)data_buf
);
1799 cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg
) +
1802 case HostCmd_CMD_FUNC_INIT
:
1803 if (priv
->adapter
->hw_status
== MWIFIEX_HW_STATUS_RESET
)
1804 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_READY
;
1805 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1806 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
1808 case HostCmd_CMD_FUNC_SHUTDOWN
:
1809 priv
->adapter
->hw_status
= MWIFIEX_HW_STATUS_RESET
;
1810 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1811 cmd_ptr
->size
= cpu_to_le16(S_DS_GEN
);
1813 case HostCmd_CMD_11N_ADDBA_REQ
:
1814 ret
= mwifiex_cmd_11n_addba_req(cmd_ptr
, data_buf
);
1816 case HostCmd_CMD_11N_DELBA
:
1817 ret
= mwifiex_cmd_11n_delba(cmd_ptr
, data_buf
);
1819 case HostCmd_CMD_11N_ADDBA_RSP
:
1820 ret
= mwifiex_cmd_11n_addba_rsp_gen(priv
, cmd_ptr
, data_buf
);
1822 case HostCmd_CMD_802_11_KEY_MATERIAL
:
1823 ret
= mwifiex_cmd_802_11_key_material(priv
, cmd_ptr
,
1824 cmd_action
, cmd_oid
,
1827 case HostCmd_CMD_802_11D_DOMAIN_INFO
:
1828 ret
= mwifiex_cmd_802_11d_domain_info(priv
, cmd_ptr
,
1831 case HostCmd_CMD_RECONFIGURE_TX_BUFF
:
1832 ret
= mwifiex_cmd_recfg_tx_buf(priv
, cmd_ptr
, cmd_action
,
1835 case HostCmd_CMD_AMSDU_AGGR_CTRL
:
1836 ret
= mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr
, cmd_action
,
1839 case HostCmd_CMD_11N_CFG
:
1840 ret
= mwifiex_cmd_11n_cfg(priv
, cmd_ptr
, cmd_action
, data_buf
);
1842 case HostCmd_CMD_WMM_GET_STATUS
:
1843 dev_dbg(priv
->adapter
->dev
,
1844 "cmd: WMM: WMM_GET_STATUS cmd sent\n");
1845 cmd_ptr
->command
= cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS
);
1847 cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status
) +
1851 case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
:
1852 ret
= mwifiex_cmd_ibss_coalescing_status(cmd_ptr
, cmd_action
,
1855 case HostCmd_CMD_802_11_SCAN_EXT
:
1856 ret
= mwifiex_cmd_802_11_scan_ext(priv
, cmd_ptr
, data_buf
);
1858 case HostCmd_CMD_MAC_REG_ACCESS
:
1859 case HostCmd_CMD_BBP_REG_ACCESS
:
1860 case HostCmd_CMD_RF_REG_ACCESS
:
1861 case HostCmd_CMD_PMIC_REG_ACCESS
:
1862 case HostCmd_CMD_CAU_REG_ACCESS
:
1863 case HostCmd_CMD_802_11_EEPROM_ACCESS
:
1864 ret
= mwifiex_cmd_reg_access(cmd_ptr
, cmd_action
, data_buf
);
1866 case HostCmd_CMD_SET_BSS_MODE
:
1867 cmd_ptr
->command
= cpu_to_le16(cmd_no
);
1868 if (priv
->bss_mode
== NL80211_IFTYPE_ADHOC
)
1869 cmd_ptr
->params
.bss_mode
.con_type
=
1870 CONNECTION_TYPE_ADHOC
;
1871 else if (priv
->bss_mode
== NL80211_IFTYPE_STATION
)
1872 cmd_ptr
->params
.bss_mode
.con_type
=
1873 CONNECTION_TYPE_INFRA
;
1874 else if (priv
->bss_mode
== NL80211_IFTYPE_AP
)
1875 cmd_ptr
->params
.bss_mode
.con_type
= CONNECTION_TYPE_AP
;
1876 cmd_ptr
->size
= cpu_to_le16(sizeof(struct
1877 host_cmd_ds_set_bss_mode
) + S_DS_GEN
);
1880 case HostCmd_CMD_PCIE_DESC_DETAILS
:
1881 ret
= mwifiex_cmd_pcie_host_spec(priv
, cmd_ptr
, cmd_action
);
1883 case HostCmd_CMD_802_11_SUBSCRIBE_EVENT
:
1884 ret
= mwifiex_cmd_802_11_subsc_evt(priv
, cmd_ptr
, data_buf
);
1886 case HostCmd_CMD_MEF_CFG
:
1887 ret
= mwifiex_cmd_mef_cfg(priv
, cmd_ptr
, data_buf
);
1889 case HostCmd_CMD_COALESCE_CFG
:
1890 ret
= mwifiex_cmd_coalesce_cfg(priv
, cmd_ptr
, cmd_action
,
1893 case HostCmd_CMD_TDLS_OPER
:
1894 ret
= mwifiex_cmd_tdls_oper(priv
, cmd_ptr
, data_buf
);
1897 dev_err(priv
->adapter
->dev
,
1898 "PREP_CMD: unknown cmd- %#x\n", cmd_no
);
1906 * This function issues commands to initialize firmware.
1908 * This is called after firmware download to bring the card to
1911 * The following commands are issued sequentially -
1912 * - Set PCI-Express host buffer configuration (PCIE only)
1913 * - Function init (for first interface only)
1914 * - Read MAC address (for first interface only)
1915 * - Reconfigure Tx buffer size (for first interface only)
1916 * - Enable auto deep sleep (for first interface only)
1919 * - Set IBSS coalescing status
1920 * - Set AMSDU aggregation control
1922 * - Set MAC control (this must be the last command to initialize firmware)
1924 int mwifiex_sta_init_cmd(struct mwifiex_private
*priv
, u8 first_sta
)
1926 struct mwifiex_adapter
*adapter
= priv
->adapter
;
1929 struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl
;
1930 struct mwifiex_ds_auto_ds auto_ds
;
1931 enum state_11d_t state_11d
;
1932 struct mwifiex_ds_11n_tx_cfg tx_cfg
;
1935 if (priv
->adapter
->iface_type
== MWIFIEX_PCIE
) {
1936 ret
= mwifiex_send_cmd(priv
,
1937 HostCmd_CMD_PCIE_DESC_DETAILS
,
1938 HostCmd_ACT_GEN_SET
, 0, NULL
,
1944 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_FUNC_INIT
,
1945 HostCmd_ACT_GEN_SET
, 0, NULL
, true);
1949 /* Download calibration data to firmware.
1950 * The cal-data can be read from device tree and/or
1951 * a configuration file and downloaded to firmware.
1954 of_find_node_by_name(NULL
, "marvell_cfgdata");
1955 if (adapter
->dt_node
) {
1956 ret
= mwifiex_dnld_dt_cfgdata(priv
, adapter
->dt_node
,
1962 if (adapter
->cal_data
) {
1963 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_CFG_DATA
,
1964 HostCmd_ACT_GEN_SET
, 0, NULL
,
1970 /* Read MAC address from HW */
1971 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_GET_HW_SPEC
,
1972 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
1976 /* Reconfigure tx buf size */
1977 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RECONFIGURE_TX_BUFF
,
1978 HostCmd_ACT_GEN_SET
, 0,
1979 &priv
->adapter
->tx_buf_size
, true);
1983 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
1984 /* Enable IEEE PS by default */
1985 priv
->adapter
->ps_mode
= MWIFIEX_802_11_POWER_MODE_PSP
;
1986 ret
= mwifiex_send_cmd(priv
,
1987 HostCmd_CMD_802_11_PS_MODE_ENH
,
1988 EN_AUTO_PS
, BITMAP_STA_PS
, NULL
,
1996 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_TX_RATE_CFG
,
1997 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2000 priv
->data_rate
= 0;
2003 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_RF_TX_PWR
,
2004 HostCmd_ACT_GEN_GET
, 0, NULL
, true);
2008 if (priv
->bss_type
== MWIFIEX_BSS_TYPE_STA
) {
2009 /* set ibss coalescing_status */
2010 ret
= mwifiex_send_cmd(
2012 HostCmd_CMD_802_11_IBSS_COALESCING_STATUS
,
2013 HostCmd_ACT_GEN_SET
, 0, &enable
, true);
2018 memset(&amsdu_aggr_ctrl
, 0, sizeof(amsdu_aggr_ctrl
));
2019 amsdu_aggr_ctrl
.enable
= true;
2020 /* Send request to firmware */
2021 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_AMSDU_AGGR_CTRL
,
2022 HostCmd_ACT_GEN_SET
, 0,
2023 &amsdu_aggr_ctrl
, true);
2026 /* MAC Control must be the last command in init_fw */
2027 /* set MAC Control */
2028 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_MAC_CONTROL
,
2029 HostCmd_ACT_GEN_SET
, 0,
2030 &priv
->curr_pkt_filter
, true);
2034 if (first_sta
&& priv
->adapter
->iface_type
!= MWIFIEX_USB
&&
2035 priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2036 /* Enable auto deep sleep */
2037 auto_ds
.auto_ds
= DEEP_SLEEP_ON
;
2038 auto_ds
.idle_time
= DEEP_SLEEP_IDLE_TIME
;
2039 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_PS_MODE_ENH
,
2040 EN_AUTO_PS
, BITMAP_AUTO_DS
,
2046 if (priv
->bss_type
!= MWIFIEX_BSS_TYPE_UAP
) {
2047 /* Send cmd to FW to enable/disable 11D function */
2048 state_11d
= ENABLE_11D
;
2049 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_802_11_SNMP_MIB
,
2050 HostCmd_ACT_GEN_SET
, DOT11D_I
,
2053 dev_err(priv
->adapter
->dev
,
2054 "11D: failed to enable 11D\n");
2057 /* set last_init_cmd before sending the command */
2058 priv
->adapter
->last_init_cmd
= HostCmd_CMD_11N_CFG
;
2060 /* Send cmd to FW to configure 11n specific configuration
2061 * (Short GI, Channel BW, Green field support etc.) for transmit
2063 tx_cfg
.tx_htcap
= MWIFIEX_FW_DEF_HTTXCFG
;
2064 ret
= mwifiex_send_cmd(priv
, HostCmd_CMD_11N_CFG
,
2065 HostCmd_ACT_GEN_SET
, 0, &tx_cfg
, true);