1 /*****************************************************************************
3 * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
5 ****************************************************************************/
7 #include <linux/delay.h>
8 #include <net/cfg80211.h>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <scsc/scsc_log_collector.h>
20 #define SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN 7
21 #define SLSI_SCAN_PRIVATE_IE_SSID_FILTER_HEADER_LEN 7
22 #define SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE 3
23 #define SLSI_CHANN_INFO_HT_SCB 0x0100
25 #define SLSI_NOA_CONFIG_REQUEST_ID (1)
26 #define SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT 16
28 static bool missing_cfm_ind_panic
= true;
29 module_param(missing_cfm_ind_panic
, bool, S_IRUGO
| S_IWUSR
);
30 MODULE_PARM_DESC(missing_cfm_ind_panic
, "Panic on missing confirm or indication from the chip");
32 struct slsi_mlme_rsse
{
36 const u8
*pairwise_cs
;
41 const u8
*group_mgmt_cs
; /* used for PMF*/
44 static struct sk_buff
*slsi_mlme_wait_for_cfm(struct slsi_dev
*sdev
, struct slsi_sig_send
*sig_wait
)
46 struct sk_buff
*cfm
= NULL
;
49 tm
= wait_for_completion_timeout(&sig_wait
->completion
, msecs_to_jiffies(*sdev
->sig_wait_cfm_timeout
));
50 spin_lock_bh(&sig_wait
->send_signal_lock
);
52 /* Confirm timed out? */
54 SLSI_ERR(sdev
, "No cfm(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait
->cfm_id
, sig_wait
->req_id
, sig_wait
->process_id
);
58 WARN(1, "Timeout - confirm 0x%04x not received from chip\n", sig_wait
->cfm_id
);
59 if (missing_cfm_ind_panic
) {
60 snprintf(reason
, sizeof(reason
), "Timed out while waiting for the cfm(0x%.4x) for req(0x%04x)",
61 sig_wait
->cfm_id
, sig_wait
->req_id
);
63 spin_unlock_bh(&sig_wait
->send_signal_lock
);
64 slsi_sm_service_failed(sdev
, reason
);
65 spin_lock_bh(&sig_wait
->send_signal_lock
);
68 WARN(1, "Confirm 0x%04x lost\n", sig_wait
->cfm_id
);
71 WARN_ON(fapi_get_u16(sig_wait
->cfm
, receiver_pid
) != sig_wait
->process_id
);
72 WARN_ON(fapi_get_u16(sig_wait
->cfm
, id
) != sig_wait
->cfm_id
);
81 spin_unlock_bh(&sig_wait
->send_signal_lock
);
86 static int panic_on_lost_ind(u16 ind_id
)
88 if (ind_id
== MLME_SCAN_DONE_IND
)
93 static struct sk_buff
*slsi_mlme_wait_for_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_sig_send
*sig_wait
, u16 ind_id
)
95 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
96 struct sk_buff
*ind
= NULL
;
99 /* The indication and confirm may have been received in the same HIP read.
100 * The HIP receive buffer processes all received signals in one thread whilst the
101 * waiting process may not be scheduled even if the "complete" call is made.
102 * In this scenario, the complete() call has already been made for this object
103 * and the wait will return immediately.
105 if (ind_id
== MLME_SCAN_DONE_IND
)
106 /* To handle the coex scenario where BTscan has high priority increasing the wait time to 40 secs */
107 tm
= wait_for_completion_timeout(&sig_wait
->completion
, msecs_to_jiffies(SLSI_SCAN_DONE_IND_WAIT_TIMEOUT
));
108 else if ((ind_id
== MLME_DISCONNECT_IND
) && (ndev_vif
->vif_type
== FAPI_VIFTYPE_AP
))
109 tm
= wait_for_completion_timeout(&sig_wait
->completion
, msecs_to_jiffies(sdev
->device_config
.ap_disconnect_ind_timeout
));
111 tm
= wait_for_completion_timeout(&sig_wait
->completion
, msecs_to_jiffies(*sdev
->sig_wait_cfm_timeout
));
113 spin_lock_bh(&sig_wait
->send_signal_lock
);
115 /* Indication timed out? */
116 if (!sig_wait
->ind
) {
117 SLSI_ERR(sdev
, "No ind(0x%.4X) for req(0x%04X) senderid=0x%x\n", sig_wait
->ind_id
, sig_wait
->req_id
, sig_wait
->process_id
);
121 WARN(1, "Timeout - indication 0x%04x not received from chip\n", sig_wait
->ind_id
);
122 if (missing_cfm_ind_panic
&& panic_on_lost_ind(ind_id
)) {
123 snprintf(reason
, sizeof(reason
), "Timed out while waiting for the ind(0x%.4x) for req(0x%04x)",
124 sig_wait
->ind_id
, sig_wait
->req_id
);
126 spin_unlock_bh(&sig_wait
->send_signal_lock
);
127 slsi_sm_service_failed(sdev
, reason
);
128 spin_lock_bh(&sig_wait
->send_signal_lock
);
131 WARN(1, "Indication 0x%04x lost\n", sig_wait
->ind_id
);
134 WARN_ON(fapi_get_u16(sig_wait
->ind
, receiver_pid
) != sig_wait
->process_id
);
135 WARN_ON(fapi_get_u16(sig_wait
->ind
, id
) != sig_wait
->ind_id
);
138 sig_wait
->ind_id
= 0;
140 sig_wait
->ind
= NULL
;
142 spin_unlock_bh(&sig_wait
->send_signal_lock
);
147 /* mib_error: NULL when not required
148 * ind: 0 when not required, if used validate_cfm_wait_ind MUST be supplied
149 * validate_cfm_wait_ind: NULL when not required, if used ind MUS not be 0
150 * NOTE: dev can be NULL!
152 static struct sk_buff
*slsi_mlme_tx_rx(struct slsi_dev
*sdev
,
153 struct net_device
*dev
,
156 struct sk_buff
**mib_error
,
158 bool (*validate_cfm_wait_ind
)(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*cfm
))
160 struct sk_buff
*rx
= NULL
;
162 u16 req_id
= fapi_get_u16(skb
, id
);
163 struct slsi_sig_send
*sig_wait
= &sdev
->sig_wait
;
166 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
168 sig_wait
= &ndev_vif
->sig_wait
;
170 if (sdev
->mlme_blocked
) {
171 SLSI_DBG3(sdev
, SLSI_TX
, "Rejected. mlme_blocked=%d\n", sdev
->mlme_blocked
);
176 slsi_wakelock(&sdev
->wlan_wl
);
177 SLSI_MUTEX_LOCK(sig_wait
->mutex
);
179 spin_lock_bh(&sig_wait
->send_signal_lock
);
180 if (++sig_wait
->process_id
> SLSI_TX_PROCESS_ID_MAX
)
181 sig_wait
->process_id
= SLSI_TX_PROCESS_ID_MIN
;
183 WARN_ON(sig_wait
->cfm
);
184 WARN_ON(sig_wait
->ind
);
185 slsi_kfree_skb(sig_wait
->cfm
);
186 slsi_kfree_skb(sig_wait
->ind
);
187 slsi_kfree_skb(sig_wait
->mib_error
);
188 sig_wait
->cfm
= NULL
;
189 sig_wait
->ind
= NULL
;
190 sig_wait
->mib_error
= NULL
;
191 sig_wait
->req_id
= req_id
;
192 sig_wait
->cfm_id
= cfm_id
;
193 sig_wait
->ind_id
= ind_id
;
195 fapi_set_u16(skb
, sender_pid
, sig_wait
->process_id
);
196 spin_unlock_bh(&sig_wait
->send_signal_lock
);
198 err
= slsi_tx_control(sdev
, dev
, skb
);
200 SLSI_ERR(sdev
, "Failed to send mlme signal:0x%.4X, err=%d\n", req_id
, err
);
206 rx
= slsi_mlme_wait_for_cfm(sdev
, sig_wait
);
208 /* The cfm skb is owned by the validate_cfm_wait_ind() function and MUST be freed or saved there */
209 if (validate_cfm_wait_ind(sdev
, dev
, rx
)) {
210 rx
= slsi_mlme_wait_for_ind(sdev
, dev
, sig_wait
, ind_id
);
212 sig_wait
->ind_id
= 0; /* Reset as there is no wait for indication */
217 rx
= slsi_mlme_wait_for_ind(sdev
, dev
, sig_wait
, ind_id
);
220 /* The cfm_id and ind_id should ALWAYS be 0 at this point */
221 WARN_ON(sig_wait
->cfm_id
);
222 WARN_ON(sig_wait
->ind_id
);
223 WARN_ON(sig_wait
->cfm
);
224 WARN_ON(sig_wait
->ind
);
227 spin_lock_bh(&sig_wait
->send_signal_lock
);
229 sig_wait
->req_id
= 0;
230 sig_wait
->cfm_id
= 0;
231 sig_wait
->ind_id
= 0;
232 slsi_kfree_skb(sig_wait
->cfm
);
233 slsi_kfree_skb(sig_wait
->ind
);
234 sig_wait
->cfm
= NULL
;
235 sig_wait
->ind
= NULL
;
238 *mib_error
= sig_wait
->mib_error
;
240 slsi_kfree_skb(sig_wait
->mib_error
);
241 sig_wait
->mib_error
= NULL
;
242 spin_unlock_bh(&sig_wait
->send_signal_lock
);
244 SLSI_MUTEX_UNLOCK(sig_wait
->mutex
);
246 slsi_wakeunlock(&sdev
->wlan_wl
);
251 * NOTE: dev can be NULL!
253 int slsi_mlme_req(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
)
256 struct slsi_sig_send
*sig_wait
= &sdev
->sig_wait
;
259 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
261 sig_wait
= &ndev_vif
->sig_wait
;
263 spin_lock_bh(&sig_wait
->send_signal_lock
);
264 if (++sig_wait
->process_id
> SLSI_TX_PROCESS_ID_MAX
)
265 sig_wait
->process_id
= SLSI_TX_PROCESS_ID_MIN
;
266 fapi_set_u16(skb
, sender_pid
, sig_wait
->process_id
);
267 spin_unlock_bh(&sig_wait
->send_signal_lock
);
269 ret
= slsi_tx_control(sdev
, dev
, skb
);
275 struct sk_buff
*slsi_mlme_req_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
, u16 ind_id
)
277 if (WARN_ON(!ind_id
))
279 return slsi_mlme_tx_rx(sdev
, dev
, skb
, 0, NULL
, ind_id
, NULL
);
285 struct sk_buff
*slsi_mlme_req_no_cfm(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
)
287 return slsi_mlme_tx_rx(sdev
, dev
, skb
, 0, NULL
, 0, NULL
);
290 struct sk_buff
*slsi_mlme_req_cfm(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
, u16 cfm_id
)
292 if (WARN_ON(!cfm_id
))
294 return slsi_mlme_tx_rx(sdev
, dev
, skb
, cfm_id
, NULL
, 0, NULL
);
300 /* NOTE: dev can be NULL! */
301 static inline struct sk_buff
*slsi_mlme_req_cfm_mib(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
, u16 cfm_id
, struct sk_buff
**mib_error
)
303 if (WARN_ON(!cfm_id
))
305 if (WARN_ON(!mib_error
))
307 return slsi_mlme_tx_rx(sdev
, dev
, skb
, cfm_id
, mib_error
, 0, NULL
);
313 /* NOTE: dev can be NULL! */
314 static inline struct sk_buff
*slsi_mlme_req_cfm_ind(struct slsi_dev
*sdev
,
315 struct net_device
*dev
,
319 bool (*validate_cfm_wait_ind
)(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*cfm
))
321 if (WARN_ON(!cfm_id
))
323 if (WARN_ON(!ind_id
))
325 if (WARN_ON(!validate_cfm_wait_ind
))
328 return slsi_mlme_tx_rx(sdev
, dev
, skb
, cfm_id
, NULL
, ind_id
, validate_cfm_wait_ind
);
335 static struct ieee80211_reg_rule
*slsi_get_reg_rule(u32 center_freq
, struct slsi_802_11d_reg_domain
*domain_info
)
337 struct ieee80211_reg_rule
*rule
;
340 for (i
= 0; i
< domain_info
->regdomain
->n_reg_rules
; i
++) {
341 rule
= &domain_info
->regdomain
->reg_rules
[i
];
343 /* Consider 10Mhz on both side from the center frequency */
344 if (((center_freq
- MHZ_TO_KHZ(10)) >= rule
->freq_range
.start_freq_khz
) &&
345 ((center_freq
+ MHZ_TO_KHZ(10)) <= rule
->freq_range
.end_freq_khz
))
352 u16
slsi_compute_chann_info(struct slsi_dev
*sdev
, u16 width
, u16 center_freq0
, u16 channel_freq
)
355 u16 prim_chan_pos
= 0;
357 SLSI_DBG3(sdev
, SLSI_MLME
, "compute channel info\n");
359 case NL80211_CHAN_WIDTH_20
:
362 case NL80211_CHAN_WIDTH_40
:
365 if (center_freq0
< channel_freq
)
366 chann_info
|= SLSI_CHANN_INFO_HT_SCB
;
368 case NL80211_CHAN_WIDTH_80
:
369 /* F = { F1-30, ... F1+30 } => { 0x0000, ... 0x0300} */
370 prim_chan_pos
= ((30 + channel_freq
- center_freq0
) / 20);
371 if (prim_chan_pos
> 3) {
372 SLSI_ERR(sdev
, "Invalid center_freq0 in chandef : %u, primary channel = %u,"
373 "primary chan pos calculated = %d\n", center_freq0
, channel_freq
, prim_chan_pos
);
376 prim_chan_pos
= 0xFFFF & (prim_chan_pos
<< 8);
377 chann_info
= 80 | prim_chan_pos
;
380 SLSI_WARN(sdev
, "Invalid chandef.width(0x%x)\n", width
);
385 SLSI_DBG3(sdev
, SLSI_MLME
, "channel_width:%u, chann_info:0x%x\n", width
, chann_info
);
389 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
390 u16
slsi_get_chann_info(struct slsi_dev
*sdev
, struct cfg80211_chan_def
*chandef
)
394 SLSI_UNUSED_PARAMETER(sdev
);
396 if (chandef
->width
== NL80211_CHAN_WIDTH_20
|| chandef
->width
== NL80211_CHAN_WIDTH_20_NOHT
) {
398 SLSI_DBG3(sdev
, SLSI_MLME
, "channel_width:%u, chann_info:0x%x\n", chandef
->width
, chann_info
);
399 } else if (chandef
->chan
) {
400 chann_info
= slsi_compute_chann_info(sdev
, chandef
->width
, chandef
->center_freq1
,
401 chandef
->chan
->center_freq
);
406 int slsi_check_channelization(struct slsi_dev
*sdev
, struct cfg80211_chan_def
*chandef
,
407 int wifi_sharing_channel_switched
)
410 struct ieee80211_reg_rule
*rule
= NULL
;
411 struct ieee80211_channel
*channel
= NULL
;
414 switch (chandef
->width
) {
415 case NL80211_CHAN_WIDTH_20
:
416 case NL80211_CHAN_WIDTH_20_NOHT
:
419 case NL80211_CHAN_WIDTH_40
:
422 case NL80211_CHAN_WIDTH_80
:
426 SLSI_ERR(sdev
, "Invalid chandef.width(0x%x)\n", chandef
->width
);
430 channel
= ieee80211_get_channel(sdev
->wiphy
, chandef
->chan
->center_freq
);
432 SLSI_ERR(sdev
, "Invalid channel %d used to start AP. Channel not found\n", chandef
->chan
->center_freq
);
436 if (wifi_sharing_channel_switched
== 1) {
437 ref_flags
= IEEE80211_CHAN_DISABLED
438 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13)
439 | IEEE80211_CHAN_PASSIVE_SCAN
443 ref_flags
= IEEE80211_CHAN_DISABLED
|
445 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 10, 13)
446 | IEEE80211_CHAN_PASSIVE_SCAN
451 if (channel
->flags
& ref_flags
) {
452 SLSI_ERR(sdev
, "Invalid channel %d used to start AP\n", chandef
->chan
->center_freq
);
455 rule
= slsi_get_reg_rule(MHZ_TO_KHZ(chandef
->center_freq1
), &sdev
->device_config
.domain_info
);
457 SLSI_ERR(sdev
, "Invalid channel %d used to start AP. No reg rule found for this channel\n", chandef
->chan
->center_freq
);
461 if (MHZ_TO_KHZ(width
) <= rule
->freq_range
.max_bandwidth_khz
) {
462 u32 width_boundary1
, width_boundary2
;
464 width_boundary1
= MHZ_TO_KHZ(chandef
->center_freq1
- width
/ 2);
465 width_boundary2
= MHZ_TO_KHZ(chandef
->center_freq1
+ width
/ 2);
466 if ((width_boundary1
>= rule
->freq_range
.start_freq_khz
) && (width_boundary2
<= rule
->freq_range
.end_freq_khz
))
468 SLSI_ERR(sdev
, "Invalid channel %d used to start AP. Channel not within frequency range of the reg rule\n", chandef
->chan
->center_freq
);
475 u16
slsi_get_chann_info(struct slsi_dev
*sdev
, enum nl80211_channel_type channel_type
)
479 SLSI_UNUSED_PARAMETER(sdev
);
482 * bits 0 ~ 7 : Channel Width (5, 10, 20, 40)
483 * bit 8 : Set to 1 if primary channel is greater than secondary channel (HT Minus)
485 switch (channel_type
) {
486 case NL80211_CHAN_NO_HT
:
487 case NL80211_CHAN_HT20
:
490 case NL80211_CHAN_HT40MINUS
:
491 chann_info
= 40 | SLSI_CHANN_INFO_HT_SCB
;
493 case NL80211_CHAN_HT40PLUS
:
497 SLSI_WARN(sdev
, "Unknown channel_type: %d\n", channel_type
);
502 SLSI_DBG3(sdev
, SLSI_MLME
, "channel_type:%d, chann_info:0x%x\n", channel_type
, chann_info
);
506 int slsi_check_channelization(struct slsi_dev
*sdev
, enum nl80211_channel_type channel_type
)
513 /* Called in the case of MIB SET errors.
514 * Decode and print a MIB buffer to the log for debug purposes.
516 static void mib_buffer_dump_to_log(struct slsi_dev
*sdev
, u8
*mib_buffer
, unsigned int mib_buffer_len
)
518 size_t mib_decode_result
;
520 struct slsi_mib_entry decoded_mib_value
;
521 struct slsi_mib_data mibdata
;
522 int error_out_len
= mib_buffer_len
* 3;
523 int error_out_pos
= 0;
526 SLSI_UNUSED_PARAMETER(sdev
);
529 SLSI_ERR(sdev
, "MIB buffer length: %u. MIB Error (decoded):", mib_buffer_len
);
532 SLSI_ERR(sdev
, "MIB buffer pointer is NULL - can not decode MIB keys\n");
535 error_out
= kmalloc(error_out_len
, GFP_KERNEL
);
537 while (offset
< mib_buffer_len
) {
539 mibdata
.data
= &mib_buffer
[offset
];
540 mibdata
.dataLength
= mib_buffer_len
- offset
;
542 mib_decode_result
= slsi_mib_decode(&mibdata
, &decoded_mib_value
);
543 if (!mib_decode_result
) {
544 SLSI_ERR_HEX(sdev
, mibdata
.data
, mibdata
.dataLength
, "slsi_mib_decode() Failed to Decode:\n");
548 offset
+= mib_decode_result
;
549 /* Time for some eye candy - output the decoded MIB key at error level in the log */
550 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "%d", (int)(decoded_mib_value
.psid
));
551 if (decoded_mib_value
.index
[0]) {
552 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, ".%d", (int)(decoded_mib_value
.index
[0]));
553 if (decoded_mib_value
.index
[1])
554 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, ".%d", (int)(decoded_mib_value
.index
[1]));
557 switch (decoded_mib_value
.value
.type
) {
558 case SLSI_MIB_TYPE_BOOL
:
559 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "=%s\n", decoded_mib_value
.value
.u
.boolValue
? "TRUE" : "FALSE");
561 case SLSI_MIB_TYPE_UINT
:
562 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "=%d\n", (int)decoded_mib_value
.value
.u
.uintValue
);
564 case SLSI_MIB_TYPE_INT
:
565 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "=%d\n", (int)decoded_mib_value
.value
.u
.intValue
);
567 case SLSI_MIB_TYPE_OCTET
:
571 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "=[");
572 for (i
= 0; i
< decoded_mib_value
.value
.u
.octetValue
.dataLength
; i
++)
573 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "%.2X", (int)decoded_mib_value
.value
.u
.octetValue
.data
[i
]);
574 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "]\n");
578 error_out_pos
+= snprintf(error_out
+ error_out_pos
, error_out_len
- error_out_pos
, "=Can not decode MIB key type\n");
582 SLSI_INFO_NODEV("%s", error_out
);
588 int slsi_mlme_set_ip_address(struct slsi_dev
*sdev
, struct net_device
*dev
)
591 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
595 u8 multicast_add
[ETH_ALEN
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
597 if (slsi_is_test_mode_enabled()) {
598 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n");
602 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
604 req
= fapi_alloc(mlme_set_ip_address_req
, MLME_SET_IP_ADDRESS_REQ
, ndev_vif
->ifnum
, sizeof(ndev_vif
->ipaddress
));
608 fapi_set_u16(req
, u
.mlme_set_ip_address_req
.ip_version
, 4);
609 fapi_set_memcpy(req
, u
.mlme_set_ip_address_req
.multicast_address
, multicast_add
);
611 ipaddr
= htonl(be32_to_cpu(ndev_vif
->ipaddress
));
612 fapi_append_data(req
, (const u8
*)(&ipaddr
), sizeof(ipaddr
));
614 SLSI_DBG2(sdev
, SLSI_MLME
, "slsi_mlme_set_ip_address(vif: %d, IP: %pI4)\n", ndev_vif
->ifnum
, &ndev_vif
->ipaddress
);
615 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_IP_ADDRESS_CFM
);
619 if (fapi_get_u16(cfm
, u
.mlme_set_ip_address_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
620 SLSI_NET_ERR(dev
, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm
, u
.mlme_set_ip_address_cfm
.result_code
));
628 #ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6
630 int slsi_mlme_set_ipv6_address(struct slsi_dev
*sdev
, struct net_device
*dev
)
633 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
636 u8 solicited_node_addr
[ETH_ALEN
] = { 0x33, 0x33, 0xff, 0x00, 0x00, 0x00 };
638 if (slsi_is_test_mode_enabled()) {
639 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_SET_IP_ADDRESS.request\n");
643 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
645 req
= fapi_alloc(mlme_set_ip_address_req
, MLME_SET_IP_ADDRESS_REQ
, ndev_vif
->ifnum
, 16);
649 fapi_set_u16(req
, u
.mlme_set_ip_address_req
.ip_version
, 6);
651 if (ndev_vif
->sta
.nd_offload_enabled
== 1) {
652 slsi_spinlock_lock(&ndev_vif
->ipv6addr_lock
);
653 memcpy(&solicited_node_addr
[3], &ndev_vif
->ipv6address
.s6_addr
[13], 3);
654 slsi_spinlock_unlock(&ndev_vif
->ipv6addr_lock
);
656 fapi_set_memcpy(req
, u
.mlme_set_ip_address_req
.multicast_address
, solicited_node_addr
);
657 fapi_append_data(req
, ndev_vif
->ipv6address
.s6_addr
, 16);
658 SLSI_DBG2(sdev
, SLSI_MLME
, "mlme_set_ip_address_req(vif: %d, IP: %pI6)\n", ndev_vif
->ifnum
,
659 &ndev_vif
->ipv6address
);
661 u8 node_addr_nd_disable
[16];
663 memset(&node_addr_nd_disable
, 0, sizeof(node_addr_nd_disable
));
664 fapi_append_data(req
, node_addr_nd_disable
, 16);
665 SLSI_DBG2(sdev
, SLSI_MLME
, "mlme_set_ip_address_req(vif: %d, IP-setting ip address to all zeros)\n",
669 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_IP_ADDRESS_CFM
);
673 if (fapi_get_u16(cfm
, u
.mlme_set_ip_address_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
674 SLSI_NET_ERR(dev
, "mlme_set_ip_address_cfm(result:0x%04x) ERROR\n",
675 fapi_get_u16(cfm
, u
.mlme_set_ip_address_cfm
.result_code
));
683 int slsi_mlme_set(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
*mib
, int mib_len
)
691 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
693 ifnum
= ndev_vif
->ifnum
;
696 req
= fapi_alloc(mlme_set_req
, MLME_SET_REQ
, ifnum
, mib_len
);
700 fapi_append_data(req
, mib
, mib_len
);
702 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_CFM
);
706 if (fapi_get_datalen(cfm
)) {
707 mib_buffer_dump_to_log(sdev
, fapi_get_data(cfm
), fapi_get_datalen(cfm
));
716 int slsi_mlme_get(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
*mib
, int mib_len
, u8
*resp
,
717 int resp_buf_len
, int *resp_len
)
720 struct sk_buff
*err
= NULL
;
728 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
730 ifnum
= ndev_vif
->ifnum
;
732 req
= fapi_alloc(mlme_get_req
, MLME_GET_REQ
, ifnum
, mib_len
);
735 fapi_append_data(req
, mib
, mib_len
);
737 cfm
= slsi_mlme_req_cfm_mib(sdev
, dev
, req
, MLME_GET_CFM
, &err
);
742 SLSI_DBG1(sdev
, SLSI_MLME
, "ERROR: mlme_get_cfm with mib error\n");
743 mib_buffer_dump_to_log(sdev
, fapi_get_data(err
), fapi_get_datalen(err
));
744 LOG_CONDITIONALLY(fapi_get_datalen(cfm
) > resp_buf_len
,
745 SLSI_ERR(sdev
, "Insufficient resp_buf_len(%d). mlme_get_cfm(%d)\n",
746 resp_buf_len
, fapi_get_datalen(cfm
)));
750 /* if host has requested for multiple PSIDs in same request, we can get a
751 * combination of error and success
753 if (fapi_get_datalen(cfm
) <= resp_buf_len
) {
754 *resp_len
= fapi_get_datalen(cfm
);
755 memcpy(resp
, fapi_get_data(cfm
), fapi_get_datalen(cfm
));
758 SLSI_WARN(sdev
, "Insufficient length (%d) to read MIB values, expected =%d\n", resp_buf_len
, fapi_get_datalen(cfm
));
768 int slsi_mlme_add_vif(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
*interface_address
, u8
*device_address
)
770 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
775 if (slsi_is_test_mode_enabled()) {
776 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_ADD_VIF.request\n");
780 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
782 /* reset host stats */
783 for (i
= 0; i
< SLSI_LLS_AC_MAX
; i
++) {
784 ndev_vif
->tx_no_ack
[i
] = 0;
785 ndev_vif
->tx_packets
[i
] = 0;
786 ndev_vif
->rx_packets
[i
] = 0;
788 req
= fapi_alloc(mlme_add_vif_req
, MLME_ADD_VIF_REQ
, ndev_vif
->ifnum
, 0);
791 fapi_set_u16(req
, u
.mlme_add_vif_req
.virtual_interface_type
, ndev_vif
->vif_type
);
792 fapi_set_memcpy(req
, u
.mlme_add_vif_req
.interface_address
, interface_address
);
793 fapi_set_memcpy(req
, u
.mlme_add_vif_req
.device_address
, device_address
);
794 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_add_vif_req(vif:%d)\n", ndev_vif
->ifnum
);
795 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_ADD_VIF_CFM
);
799 if (fapi_get_u16(cfm
, u
.mlme_add_vif_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
800 SLSI_NET_ERR(dev
, "mlme_add_vif_cfm(result:0x%04x) ERROR\n",
801 fapi_get_u16(cfm
, u
.mlme_add_vif_cfm
.result_code
));
805 /* By default firmware vif will be in active mode */
806 ndev_vif
->power_mode
= FAPI_POWERMANAGEMENTMODE_ACTIVE_MODE
;
812 void slsi_mlme_del_vif(struct slsi_dev
*sdev
, struct net_device
*dev
)
814 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
818 if (slsi_is_test_mode_enabled()) {
819 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_DEL_VIF.request\n");
823 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
825 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_del_vif_req(vif:%d)\n", ndev_vif
->ifnum
);
826 req
= fapi_alloc(mlme_del_vif_req
, MLME_DEL_VIF_REQ
, ndev_vif
->ifnum
, 0);
830 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_DEL_VIF_CFM
);
834 if (fapi_get_u16(cfm
, u
.mlme_del_vif_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
)
835 SLSI_NET_ERR(dev
, "mlme_del_vif_cfm(result:0x%04x) ERROR\n",
836 fapi_get_u16(cfm
, u
.mlme_del_vif_cfm
.result_code
));
838 if (((ndev_vif
->iftype
== NL80211_IFTYPE_P2P_CLIENT
) || (ndev_vif
->iftype
== NL80211_IFTYPE_STATION
)) &&
839 (ndev_vif
->delete_probe_req_ies
)) {
840 kfree(ndev_vif
->probe_req_ies
);
841 ndev_vif
->probe_req_ies
= NULL
;
842 ndev_vif
->probe_req_ie_len
= 0;
843 ndev_vif
->delete_probe_req_ies
= false;
845 if (SLSI_IS_VIF_INDEX_P2P(ndev_vif
))
846 ndev_vif
->drv_in_p2p_procedure
= false;
851 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
852 int slsi_mlme_set_forward_beacon(struct slsi_dev
*sdev
, struct net_device
*dev
, int action
)
854 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
858 if (slsi_is_test_mode_enabled()) {
859 SLSI_NET_INFO(dev
, "wlanlite does not support mlme_forward_bacon_req\n");
863 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_forward_beacon_req(action = %s(%d))\n", action
? "start" : "stop", action
);
865 req
= fapi_alloc(mlme_forward_beacon_req
, MLME_FORWARD_BEACON_REQ
, ndev_vif
->ifnum
, 0);
867 SLSI_NET_ERR(dev
, "fapi alloc for mlme_forward_beacon_req is failed\n");
871 fapi_set_u16(req
, u
.mlme_forward_beacon_req
.wips_action
, action
);
873 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_FORWARD_BEACON_CFM
);
875 SLSI_NET_ERR(dev
, "receiving mlme_forward_beacon_cfm is failed\n");
879 if (fapi_get_u16(cfm
, u
.mlme_forward_beacon_cfm
.result_code
) != FAPI_RESULTCODE_HOST_REQUEST_SUCCESS
) {
880 SLSI_NET_ERR(dev
, "mlme_forward_beacon_cfm(result:0x%04x) ERROR\n",
881 fapi_get_u16(cfm
, u
.mlme_forward_beacon_cfm
.result_code
));
885 ndev_vif
->is_wips_running
= (action
? true : false);
892 int slsi_mlme_set_channel(struct slsi_dev
*sdev
, struct net_device
*dev
, struct ieee80211_channel
*chan
, u16 duration
, u16 interval
, u16 count
)
894 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
899 if (slsi_is_test_mode_enabled()) {
900 SLSI_NET_INFO(dev
, "wlanlite does not support MLME_SET_CHANNEL.request\n");
904 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
906 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_channel_req(freq:%u, duration:%u, interval:%u, count:%u)\n", chan
->center_freq
, duration
, interval
, count
);
908 req
= fapi_alloc(mlme_set_channel_req
, MLME_SET_CHANNEL_REQ
, ndev_vif
->ifnum
, 0);
912 fapi_set_u16(req
, u
.mlme_set_channel_req
.availability_duration
, duration
);
913 fapi_set_u16(req
, u
.mlme_set_channel_req
.availability_interval
, interval
);
914 fapi_set_u16(req
, u
.mlme_set_channel_req
.count
, count
);
915 fapi_set_u16(req
, u
.mlme_set_channel_req
.channel_frequency
, SLSI_FREQ_HOST_TO_FW(chan
->center_freq
));
917 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_CHANNEL_CFM
);
921 if (fapi_get_u16(cfm
, u
.mlme_set_channel_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
922 SLSI_NET_ERR(dev
, "mlme_set_channel_cfm(result:0x%04x) ERROR\n",
923 fapi_get_u16(cfm
, u
.mlme_set_channel_cfm
.result_code
));
931 int slsi_mlme_unset_channel_req(struct slsi_dev
*sdev
, struct net_device
*dev
)
933 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
938 SLSI_NET_DBG3(dev
, SLSI_MLME
, "slsi_mlme_unset_channel_req\n");
940 req
= fapi_alloc(mlme_unset_channel_req
, MLME_UNSET_CHANNEL_REQ
, ndev_vif
->ifnum
, 0);
945 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_UNSET_CHANNEL_CFM
);
950 if (fapi_get_u16(cfm
, u
.mlme_unset_channel_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
951 SLSI_NET_ERR(dev
, "mlme_unset_channel_cfm(result:0x%04x) ERROR\n",
952 fapi_get_u16(cfm
, u
.mlme_unset_channel_cfm
.result_code
));
960 void slsi_ap_obss_scan_done_ind(struct net_device
*dev
, struct netdev_vif
*ndev_vif
)
962 struct sk_buff
*scan_res
;
963 u16 scan_id
= SLSI_SCAN_HW_ID
;
965 SLSI_UNUSED_PARAMETER(dev
);
967 SLSI_NET_DBG1(dev
, SLSI_MLME
, "Scan before AP start completed\n");
969 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
970 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->scan_mutex
));
971 SLSI_MUTEX_LOCK(ndev_vif
->scan_result_mutex
);
973 scan_res
= slsi_dequeue_cached_scan_result(&ndev_vif
->scan
[scan_id
], NULL
);
975 struct ieee80211_mgmt
*mgmt
= fapi_get_mgmt(scan_res
);
976 size_t mgmt_len
= fapi_get_mgmtlen(scan_res
);
977 size_t ie_len
= mgmt_len
- offsetof(struct ieee80211_mgmt
, u
.beacon
.variable
); /* ieee80211_mgmt structure is similar for Probe Response and Beacons */
979 SLSI_NET_DBG4(dev
, SLSI_MLME
, "OBSS scan result (scan_id:%d, %pM, freq:%d, rssi:%d, ie_len = %zu)\n",
980 fapi_get_u16(scan_res
, u
.mlme_scan_ind
.scan_id
),
981 fapi_get_mgmt(scan_res
)->bssid
,
982 fapi_get_u16(scan_res
, u
.mlme_scan_ind
.channel_frequency
) / 2,
983 fapi_get_s16(scan_res
, u
.mlme_scan_ind
.rssi
),
986 if (!cfg80211_find_ie(WLAN_EID_HT_CAPABILITY
, mgmt
->u
.beacon
.variable
, ie_len
)) {
987 SLSI_NET_DBG1(dev
, SLSI_MLME
, "Non HT BSS detected on primary channel\n");
988 ndev_vif
->ap
.non_ht_bss_present
= true;
991 slsi_kfree_skb(scan_res
);
992 scan_res
= slsi_dequeue_cached_scan_result(&ndev_vif
->scan
[scan_id
], NULL
);
994 SLSI_MUTEX_UNLOCK(ndev_vif
->scan_result_mutex
);
997 /* Null check for cfm done in caller function */
998 static bool slsi_scan_cfm_validate(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*cfm
)
1002 if (fapi_get_u16(cfm
, u
.mlme_add_scan_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
1003 SLSI_ERR_NODEV("mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1004 fapi_get_u16(cfm
, u
.mlme_add_scan_cfm
.result_code
));
1008 slsi_kfree_skb(cfm
);
1012 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
1013 int slsi_mlme_append_gscan_channel_list(struct slsi_dev
*sdev
,
1014 struct net_device
*dev
,
1015 struct sk_buff
*req
,
1016 struct slsi_nl_bucket_param
*nl_bucket
)
1021 const u8 channels_list_ie_header
[] = {
1022 0xDD, /* Element ID: Vendor Specific */
1023 0x05, /* Length: actual length will be updated later */
1024 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1025 0x01, /* OUI Type: Scan parameters */
1026 0x02 /* OUI Subtype: channel list */
1028 u8
*channels_list_ie
= fapi_append_data(req
, channels_list_ie_header
, sizeof(channels_list_ie_header
));
1030 if (!channels_list_ie
) {
1031 SLSI_WARN(sdev
, "channel list IE append failed\n");
1032 slsi_kfree_skb(req
);
1036 if (nl_bucket
->band
== WIFI_BAND_UNSPECIFIED
)
1037 /* channel list is added only if band is UNSPECIFIED */
1038 for (i
= 0; i
< nl_bucket
->num_channels
; i
++) {
1039 p
= fapi_append_data(req
, NULL
, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
1041 SLSI_ERR(sdev
, "chan desc[%d] append failed\n", i
);
1042 slsi_kfree_skb(req
);
1045 channel_freq
= SLSI_FREQ_HOST_TO_FW(nl_bucket
->channels
[i
].channel
);
1046 channel_freq
= cpu_to_le16(channel_freq
);
1047 memcpy(p
, &channel_freq
, sizeof(channel_freq
));
1048 p
[2] = FAPI_SCANPOLICY_ANY_RA
;
1049 channels_list_ie
[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
; /* Length */
1052 p
= fapi_append_data(req
, NULL
, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
1054 SLSI_ERR(sdev
, "chan desc(band specific)append failed\n");
1055 slsi_kfree_skb(req
);
1058 /* Channel frequency set to 0 for all channels allowed by the corresponding regulatory domain and scan policy */
1060 memcpy(p
, &channel_freq
, sizeof(channel_freq
));
1061 p
[2] = slsi_gscan_get_scan_policy(nl_bucket
->band
);
1062 channels_list_ie
[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
;
1069 static int slsi_mlme_append_channel_list(struct slsi_dev
*sdev
,
1070 struct net_device
*dev
,
1071 struct sk_buff
*req
,
1073 struct ieee80211_channel
*channels
[],
1080 int n_valid_channels
= 0;
1083 const u8 channels_list_ie_header
[] = {
1084 0xDD, /* Element ID: vendor specific */
1085 0x05, /* Length: actual length will be updated later */
1086 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1087 0x01, /* OUI Type: scan parameters */
1088 0x02 /* OUI Subtype: channel list */
1091 u8
*channels_list_ie
= fapi_append_data(req
, channels_list_ie_header
, sizeof(channels_list_ie_header
));
1093 if (!channels_list_ie
) {
1094 SLSI_WARN(sdev
, "channel list IE append failed\n");
1095 slsi_kfree_skb(req
);
1099 /* For P2P Full Scan, Setting Channel Frequency = 0x0000, Scan Policy = 2.4GHz, 5GHz and Non-Dfs. */
1100 if (scan_type
== FAPI_SCANTYPE_P2P_SCAN_FULL
) {
1101 p
= fapi_append_data(req
, NULL
, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
1103 SLSI_WARN(sdev
, "scan channel descriptor append failed\n");
1104 slsi_kfree_skb(req
);
1109 p
[2] = FAPI_SCANPOLICY_2_4GHZ
| FAPI_SCANPOLICY_5GHZ
| FAPI_SCANPOLICY_NON_DFS
;
1110 channels_list_ie
[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
;
1114 for (i
= 0; i
< num_channels
; i
++) {
1115 chann
= channels
[i
]->hw_value
& 0xFF;
1117 if (sdev
->device_config
.supported_band
) {
1118 if (channels
[i
]->band
== NL80211_BAND_2GHZ
&& sdev
->device_config
.supported_band
!= SLSI_FREQ_BAND_2GHZ
)
1120 if (channels
[i
]->band
== NL80211_BAND_5GHZ
&& sdev
->device_config
.supported_band
!= SLSI_FREQ_BAND_5GHZ
)
1125 p
= fapi_append_data(req
, NULL
, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
1127 SLSI_WARN(sdev
, "scan channel descriptor append failed\n");
1128 slsi_kfree_skb(req
);
1131 freq_fw_unit
= 2 * ieee80211_channel_to_frequency(chann
, (chann
<= 14) ?
1132 NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ
);
1133 freq_fw_unit
= cpu_to_le16(freq_fw_unit
);
1134 memcpy(p
, &freq_fw_unit
, sizeof(freq_fw_unit
));
1136 if (passive_scan
&& (scan_type
!= FAPI_SCANTYPE_AP_AUTO_CHANNEL_SELECTION
))
1137 p
[2] = FAPI_SCANPOLICY_PASSIVE
;
1141 channels_list_ie
[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
;
1143 if (n_valid_channels
== 0) {
1144 SLSI_NET_ERR(dev
, "no valid channels to Scan\n");
1145 slsi_kfree_skb(req
);
1151 static inline int slsi_set_scan_params(
1152 struct net_device
*dev
,
1157 struct cfg80211_ssid
*ssids
,
1158 struct sk_buff
*req
)
1162 struct cfg80211_ssid
*pssid
= ssids
;
1163 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1164 struct netdev_vif
*netdev_vif
= netdev_priv(dev
);
1165 struct slsi_dev
*sdev
= netdev_vif
->sdev
;
1168 fapi_set_u16(req
, u
.mlme_add_scan_req
.scan_id
, scan_id
);
1169 fapi_set_u16(req
, u
.mlme_add_scan_req
.scan_type
, scan_type
);
1170 fapi_set_u16(req
, u
.mlme_add_scan_req
.report_mode_bitmap
, report_mode
);
1173 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1174 if (sdev
->scan_addr_set
&& slsi_dev_mac_randomisation_support()) //IKSAMP-1972
1175 fapi_set_memcpy(req
, u
.mlme_add_scan_req
.device_address
, sdev
->scan_mac_addr
);
1178 fapi_set_memcpy(req
, u
.mlme_add_scan_req
.device_address
, dev
->dev_addr
);
1180 for (i
= 0; i
< num_ssids
; i
++, pssid
++) {
1181 p
= fapi_append_data(req
, NULL
, 2 + pssid
->ssid_len
);
1183 slsi_kfree_skb(req
);
1184 SLSI_NET_WARN(dev
, "fail to append SSID element to scan request\n");
1188 *p
++ = WLAN_EID_SSID
;
1189 *p
++ = pssid
->ssid_len
;
1191 if (pssid
->ssid_len
)
1192 memcpy(p
, pssid
->ssid
, pssid
->ssid_len
);
1197 #define SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM 7
1198 int slsi_mlme_add_sched_scan(struct slsi_dev
*sdev
,
1199 struct net_device
*dev
,
1200 struct cfg80211_sched_scan_request
*request
,
1204 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
1205 struct sk_buff
*req
;
1208 size_t alloc_data_size
= 0;
1210 u32 num_ssid_filter_elements
= 0;
1212 /* Scan Timing IE: default values */
1213 u8 scan_timing_ie
[] = {
1214 0xdd, /* Element ID: Vendor Specific */
1216 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1217 0x01, /* OUI Type: Scan parameters */
1218 0x01, /* OUI Subtype: Scan timing */
1219 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */
1220 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */
1221 /* BEGIN IKSAMP-7392, optimize pno scanning interval */
1222 0x0a, /* Exponent */
1223 0x07, /* Step count */
1224 /* END IKSAMP-7392 */
1225 0x00, 0x01 /* Skip first period: true for scheduled scans*/
1228 u8 ssid_filter_ie_hdr
[] = {
1229 0xdd, /* Element ID: Vendor Specific */
1231 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1232 0x01, /* OUI Type: Scan parameters */
1233 0x04 /* OUI Subtype: SSID Filter */
1236 if (slsi_is_test_mode_enabled()) {
1237 SLSI_NET_WARN(dev
, "not supported in WlanLite mode\n");
1241 if (WARN_ON(!(dev
->dev_addr
)))
1244 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->scan_mutex
));
1246 #ifdef CONFIG_SCSC_WLAN_ENABLE_MAC_RANDOMISATION
1247 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
1248 if (request
->flags
& NL80211_SCAN_FLAG_RANDOM_ADDR
) {
1249 if (sdev
->fw_mac_randomization_enabled
) {
1250 memcpy(sdev
->scan_mac_addr
, request
->mac_addr
, ETH_ALEN
);
1251 r
= slsi_set_mac_randomisation_mask(sdev
, request
->mac_addr_mask
);
1253 sdev
->scan_addr_set
= 1;
1255 SLSI_NET_INFO(dev
, "Mac Randomization is not enabled in Firmware\n");
1256 sdev
->scan_addr_set
= 0;
1262 alloc_data_size
+= sizeof(scan_timing_ie
) + ies_len
+ SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN
+
1263 (request
->n_channels
* SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
1265 for (i
= 0; i
< request
->n_ssids
; i
++) {
1266 /* 2 bytes for SSID EID and length field + variable length SSID */
1267 alloc_data_size
+= (2 + request
->ssids
[i
].ssid_len
);
1270 if (request
->n_match_sets
) {
1271 num_ssid_filter_elements
= (request
->n_match_sets
/ SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM
) + 1;
1272 /* EID(1) + len(1) + oui(3) + type/subtype(2) + 7 ssid descriptors(7 * 33) */
1273 alloc_data_size
+= 238 * num_ssid_filter_elements
;
1276 req
= fapi_alloc(mlme_add_scan_req
, MLME_ADD_SCAN_REQ
, 0, alloc_data_size
);
1280 r
= slsi_set_scan_params(dev
, (ndev_vif
->ifnum
<< 8 | SLSI_SCAN_SCHED_ID
),
1281 FAPI_SCANTYPE_SCHEDULED_SCAN
,
1282 FAPI_REPORTMODE_REAL_TIME
,
1289 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
1290 // BEGIN IKSAMP-7392, optimize pno scanning interval
1291 SLSI_U32_TO_BUFF_LE(48 * 1000 * 1000, &scan_timing_ie
[7]);
1292 SLSI_U32_TO_BUFF_LE(500 * 1000 * 1000, &scan_timing_ie
[11]);
1295 SLSI_U32_TO_BUFF_LE(request
->interval
* 1000, &scan_timing_ie
[7]);
1296 SLSI_U32_TO_BUFF_LE(request
->interval
* 1000, &scan_timing_ie
[11]);
1299 fapi_append_data(req
, scan_timing_ie
, sizeof(scan_timing_ie
));
1300 fapi_append_data(req
, ies
, ies_len
);
1302 if (request
->n_match_sets
) {
1303 struct cfg80211_match_set
*match_sets
= request
->match_sets
;
1306 for (j
= 0; j
< num_ssid_filter_elements
; j
++) {
1307 ssid_filter_ie
= fapi_append_data(req
, ssid_filter_ie_hdr
, sizeof(ssid_filter_ie_hdr
));
1308 if (!ssid_filter_ie
) {
1309 slsi_kfree_skb(req
);
1310 SLSI_ERR(sdev
, "ssid_filter_ie append failed\n");
1313 for (i
= 0; i
< SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM
; i
++, match_sets
++) {
1314 if ((j
* SLSI_MAX_SSID_DESC_IN_SSID_FILTER_ELEM
) + i
>= request
->n_match_sets
)
1316 SLSI_NET_DBG2(dev
, SLSI_MLME
, "SSID: %.*s",
1317 match_sets
->ssid
.ssid_len
, match_sets
->ssid
.ssid
);
1318 ssid_filter_ie
[1] += (1 + match_sets
->ssid
.ssid_len
);
1319 fapi_append_data(req
, &match_sets
->ssid
.ssid_len
, 1);
1320 fapi_append_data(req
, match_sets
->ssid
.ssid
, match_sets
->ssid
.ssid_len
);
1325 if (request
->n_channels
) {
1326 r
= slsi_mlme_append_channel_list(sdev
, dev
, req
, request
->n_channels
, request
->channels
,
1327 FAPI_SCANTYPE_SCHEDULED_SCAN
, request
->n_ssids
== 0);
1332 rx
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_ADD_SCAN_CFM
);
1336 if (fapi_get_u16(rx
, u
.mlme_add_scan_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
1337 SLSI_NET_ERR(dev
, "mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1338 fapi_get_u16(rx
, u
.mlme_add_scan_cfm
.result_code
));
1346 int slsi_mlme_add_scan(
1347 struct slsi_dev
*sdev
,
1348 struct net_device
*dev
,
1352 struct cfg80211_ssid
*ssids
,
1354 struct ieee80211_channel
*channels
[],
1360 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
1361 struct sk_buff
*req
;
1364 size_t alloc_data_size
= 0;
1367 /* Scan Timing IE: default values */
1368 u8 scan_timing_ie
[] = {
1369 0xdd, /* Element ID: Vendor Specific */
1371 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
1372 0x01, /* OUI Type: Scan parameters */
1373 0x01, /* OUI Subtype: Scan timing */
1374 0x00, 0x00, 0x00, 0x00, /* Min_Period: filled later in the function */
1375 0x00, 0x00, 0x00, 0x00, /* Max_Period: filled later in the function */
1376 0x00, /* Exponent */
1377 0x00, /* Step count */
1378 0x00, 0x00 /* Skip first period: false */
1381 if (slsi_is_test_mode_enabled()) {
1382 SLSI_NET_WARN(dev
, "not supported in WlanLite mode\n");
1386 if (WARN_ON(!(dev
->dev_addr
)))
1389 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->scan_mutex
));
1390 SLSI_INFO(sdev
, "scan started for id:0x%x, n_channels:%d, n_ssids:%d, scan_type:%d\n",
1391 (ndev_vif
->ifnum
<< 8 | SLSI_SCAN_HW_ID
), n_channels
, n_ssids
, scan_type
);
1393 alloc_data_size
+= sizeof(scan_timing_ie
) +
1395 (SLSI_SCAN_PRIVATE_IE_CHANNEL_LIST_HEADER_LEN
+ (n_channels
* SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
));
1397 for (i
= 0; i
< n_ssids
; i
++)
1398 alloc_data_size
+= 2 + ssids
[i
].ssid_len
; /* 2: SSID EID + len */
1400 req
= fapi_alloc(mlme_add_scan_req
, MLME_ADD_SCAN_REQ
, 0, alloc_data_size
);
1405 r
= slsi_set_scan_params(
1407 (ndev_vif
->ifnum
<< 8 | SLSI_SCAN_HW_ID
),
1416 fapi_append_data(req
, scan_timing_ie
, sizeof(scan_timing_ie
));
1417 fapi_append_data(req
, ies
, ies_len
);
1420 r
= slsi_mlme_append_channel_list(sdev
, dev
, req
, n_channels
, channels
, scan_type
,
1426 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
1428 struct slsi_gscan_param
*gscan_param
= (struct slsi_gscan_param
*)gscan
;
1430 r
= slsi_set_scan_params(
1432 gscan_param
->bucket
->scan_id
,
1441 SLSI_U32_TO_BUFF_LE((gscan_param
->nl_bucket
->period
* 1000), &scan_timing_ie
[7]);
1442 if (gscan_param
->nl_bucket
->exponent
) {
1443 SLSI_U32_TO_BUFF_LE((gscan_param
->nl_bucket
->max_period
* 1000), &scan_timing_ie
[11]);
1444 scan_timing_ie
[15] = (u8
)gscan_param
->nl_bucket
->exponent
;
1445 scan_timing_ie
[16] = (u8
)gscan_param
->nl_bucket
->step_count
;
1447 fapi_append_data(req
, scan_timing_ie
, sizeof(scan_timing_ie
));
1449 r
= slsi_mlme_append_gscan_channel_list(sdev
, dev
, req
, gscan_param
->nl_bucket
);
1455 /* Use the Global sig_wait not the Interface specific for Scan Req */
1456 rx
= slsi_mlme_req_cfm_ind(sdev
, NULL
, req
, MLME_ADD_SCAN_CFM
, MLME_SCAN_DONE_IND
, slsi_scan_cfm_validate
);
1459 SLSI_NET_DBG3(dev
, SLSI_MLME
, "mlme_scan_done_ind()\n");
1461 /* slsi_mlme_add_scan is a generic definition for multiple handlers
1462 * Any added functionality, if not generic, should not be defined here.
1463 * It should be a part of calling function.
1466 /* Use the Global sig_wait not the Interface specific for Scan Req */
1467 rx
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_ADD_SCAN_CFM
);
1470 if (fapi_get_u16(rx
, u
.mlme_add_scan_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
1471 SLSI_NET_ERR(dev
, "mlme_add_scan_cfm(result:0x%04x) ERROR\n",
1472 fapi_get_u16(rx
, u
.mlme_add_scan_cfm
.result_code
));
1480 int slsi_mlme_del_scan(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 scan_id
, bool scan_timed_out
)
1482 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
1483 struct sk_buff
*req
;
1484 struct sk_buff
*cfm
;
1487 if (slsi_is_test_mode_enabled()) {
1488 SLSI_NET_WARN(dev
, "not supported in WlanLite mode\n");
1492 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_del_scan_req(scan_id:%d)\n", scan_id
);
1494 if ((scan_id
& 0xFF) == SLSI_SCAN_HW_ID
&& ndev_vif
->scan
[SLSI_SCAN_HW_ID
].scan_req
&& !scan_timed_out
)
1495 cancel_delayed_work(&ndev_vif
->scan_timeout_work
);
1497 req
= fapi_alloc(mlme_del_scan_req
, MLME_DEL_SCAN_REQ
, 0, 0);
1500 fapi_set_u16(req
, u
.mlme_del_scan_req
.scan_id
, scan_id
);
1502 /* Use the Global sig_wait not the Interface specific for Scan Req */
1503 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_DEL_SCAN_CFM
);
1507 if (fapi_get_u16(cfm
, u
.mlme_del_scan_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
1508 SLSI_NET_ERR(dev
, "mlme_del_scan_cfm(result:0x%04x) ERROR\n",
1509 fapi_get_u16(cfm
, u
.mlme_del_scan_cfm
.result_code
));
1513 slsi_kfree_skb(cfm
);
1517 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1518 static void slsi_ap_add_ext_capab_ie(struct sk_buff
*req
, struct netdev_vif
*ndev_vif
, const u8
*prev_ext
)
1520 u8 ext_capa_ie
[SLSI_AP_EXT_CAPAB_IE_LEN_MAX
];
1524 ext_capa_ie
[0] = WLAN_EID_EXT_CAPABILITY
;
1525 ext_capa_ie
[1] = SLSI_AP_EXT_CAPAB_IE_LEN_MAX
- 1 - 1;
1527 prev_len
= prev_ext
[1];
1528 for (i
= 2; i
< prev_len
+ 2; i
++)
1529 ext_capa_ie
[i
] = prev_ext
[i
];
1531 for (i
= prev_len
+ 2; i
< SLSI_AP_EXT_CAPAB_IE_LEN_MAX
; i
++)
1532 ext_capa_ie
[i
] = 0x00;
1533 SLSI_DBG3(ndev_vif
->sdev
, SLSI_MLME
, "New Ext capab Added\n");
1534 /* For VHT, set the Operating Mode Notification field - Bit 62 (8th Octet) */
1535 ext_capa_ie
[9] |= 0x40;
1537 fapi_append_data(req
, &ext_capa_ie
[0], SLSI_AP_EXT_CAPAB_IE_LEN_MAX
);
1541 static int slsi_prepare_country_ie(struct slsi_dev
*sdev
, u16 center_freq
, u8
*country_ie
, u8
**new_country_ie
)
1543 struct ieee80211_supported_band band
;
1544 struct ieee80211_reg_rule
*rule
;
1545 struct ieee80211_channel
*channels
;
1550 /* Select frequency band */
1551 if (center_freq
< 5180)
1552 band
= slsi_band_2ghz
;
1554 band
= slsi_band_5ghz
;
1556 /* Allocate memory for the new country IE - EID(1) + Len(1) + CountryString(3) + ChannelInfo (n * 3) */
1557 ie
= kmalloc(5 + (band
.n_channels
* 3), GFP_KERNEL
);
1559 SLSI_ERR(sdev
, "Failed to allocate memory\n");
1563 /* Preapre the new country IE */
1564 ie
[offset
++] = country_ie
[0]; /* Element IE */
1565 ie
[offset
++] = 0; /* IE Length - initialized at the end of this function */
1566 ie
[offset
++] = sdev
->device_config
.domain_info
.regdomain
->alpha2
[0]; /* Country code */
1567 ie
[offset
++] = sdev
->device_config
.domain_info
.regdomain
->alpha2
[1]; /* Country code */
1568 ie
[offset
++] = country_ie
[4]; /* CountryString: 3rd octet */
1570 channels
= band
.channels
;
1571 for (i
= 0; i
< band
.n_channels
; i
++, channels
++) {
1572 /* Get the regulatory rule for the channel */
1573 rule
= slsi_get_reg_rule(MHZ_TO_KHZ(channels
->center_freq
), &sdev
->device_config
.domain_info
);
1575 ie
[offset
++] = channels
->hw_value
; /* Channel number */
1576 ie
[offset
++] = 1; /* Number of channels */
1577 ie
[offset
++] = MBM_TO_DBM(rule
->power_rule
.max_eirp
); /* Max TX power */
1581 ie
[1] = offset
- 2; /* Length of IE */
1582 *new_country_ie
= ie
;
1587 int slsi_modify_ies(struct net_device
*dev
, u8 eid
, u8
*ies
, int ies_len
, u8 ie_index
, u8 ie_value
)
1591 SLSI_NET_DBG1(dev
, SLSI_MLME
, "eid: %d, ie_value = 0x%x\n", eid
, ie_value
);
1593 ie
= (u8
*)cfg80211_find_ie(eid
, ies
, ies_len
);
1596 case WLAN_EID_HT_CAPABILITY
:
1597 case WLAN_EID_VHT_CAPABILITY
:
1598 ie
[ie_index
] |= ie_value
;
1600 case WLAN_EID_DS_PARAMS
:
1601 case WLAN_EID_HT_OPERATION
:
1603 ie
[ie_index
] = ie_value
;
1605 ie
[ie_index
] |= ie_value
;
1608 SLSI_NET_WARN(dev
, "slsi_modify_ies: IE type mismatch : %d\n", eid
);
1613 SLSI_NET_WARN(dev
, "slsi_modify_ies: IE not found : %d\n", eid
);
1617 static void slsi_mlme_start_prepare_ies(struct sk_buff
*req
, struct netdev_vif
*ndev_vif
, struct cfg80211_ap_settings
*settings
, const u8
*wpa_ie_pos
, const u8
*wmm_ie_pos
)
1619 const u8
*wps_ie
, *vht_capab_ie
, *tail_pos
= NULL
, *ext_capab_ie
;
1620 size_t beacon_ie_len
= 0, tail_length
= 0;
1622 const u8
*beacon_tail
= settings
->beacon
.tail
;
1623 size_t beacon_tail_len
= settings
->beacon
.tail_len
;
1626 * Channel list of Country IE prepared by hostapd is wrong, so driver needs remove the existing country IE and prepare correct one.
1627 * Hostapd adds country IE at the beginning of the tail, beacon_tail is moved to the next IE to avoid the default county IE.
1629 country_ie
= (u8
*)cfg80211_find_ie(WLAN_EID_COUNTRY
, beacon_tail
, beacon_tail_len
);
1631 u8
*new_country_ie
= NULL
;
1633 SLSI_DBG3(ndev_vif
->sdev
, SLSI_MLME
, "Country IE found, length = %d", country_ie
[1]);
1635 /* Prepare the new country IE */
1636 if (slsi_prepare_country_ie(ndev_vif
->sdev
, ndev_vif
->chan
->center_freq
, country_ie
, &new_country_ie
) != 0)
1637 SLSI_ERR(ndev_vif
->sdev
, "Failed to prepare country IE");
1639 /* Add the new country IE */
1640 if (new_country_ie
) {
1641 /* new_country_ie[1] ontains the length of IE */
1642 fapi_append_data(req
, new_country_ie
, (new_country_ie
[1] + 2));
1644 /* Free the memory allocated for the new country IE */
1645 kfree(new_country_ie
);
1647 /* Remove the default country IE from the beacon_tail */
1648 beacon_tail
+= (country_ie
[1] + 2);
1649 beacon_tail_len
-= (country_ie
[1] + 2);
1653 /* Modify HT IE based on OBSS scan data */
1654 if (ndev_vif
->ap
.non_ht_bss_present
) {
1657 SLSI_NET_DBG1(ndev_vif
->wdev
.netdev
, SLSI_MLME
, "Modify Operating mode of BSS in HT IE\n");
1658 slsi_modify_ies(ndev_vif
->wdev
.netdev
, WLAN_EID_HT_OPERATION
, (u8
*)settings
->beacon
.tail
, settings
->beacon
.tail_len
, 4, op_mode
);
1659 ndev_vif
->ap
.non_ht_bss_present
= false;
1662 /* Vendor IEs are excluded from start_req. Currently WPA IE, WMM IE, WPS IE and P2P IE need to be excluded.
1663 * From hostapd, order of IEs are - WPA, WMM, WPS and P2P
1664 * Of these the WMM, WPS and P2P IE are usually at the end.
1665 * Note: There can be "eid_p2p_manage" and "eid_hs20" after WPS and P2P IE. Both of these are currently not supported.
1668 /* Exclude WMM or WPS IE */
1669 if (wmm_ie_pos
) /* WMM IE is present. Remove from this position onwards, i.e. copy only till this data. WPS and P2P IE will also get removed. */
1670 beacon_ie_len
= wmm_ie_pos
- beacon_tail
;
1672 /* WMM IE is not present. Check for WPS IE (and thereby P2P IE) and exclude it */
1673 wps_ie
= cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
, WLAN_OUI_TYPE_MICROSOFT_WPS
, beacon_tail
, beacon_tail_len
);
1675 beacon_ie_len
= wps_ie
- beacon_tail
;
1677 beacon_ie_len
= beacon_tail_len
;
1680 /* Exclude WPA IE if present */
1682 size_t len_before
, len
;
1684 len_before
= wpa_ie_pos
- beacon_tail
;
1685 fapi_append_data(req
, beacon_tail
, len_before
);
1687 len
= len_before
+ ndev_vif
->ap
.wpa_ie_len
;
1689 if (beacon_ie_len
> len
) { /* More IEs to go */
1690 tail_length
= beacon_ie_len
- len
;
1691 tail_pos
= (beacon_tail
+ len
);
1692 } else /* No more IEs, don't add Ext Capab IE as no HT/VHT */
1695 tail_length
= beacon_ie_len
;
1696 tail_pos
= beacon_tail
;
1699 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1700 /* Add Ext Capab IE only for VHT mode for now */
1701 if (ndev_vif
->chandef
->width
== NL80211_CHAN_WIDTH_80
) {
1702 /* Ext Capab should be before VHT IEs */
1703 vht_capab_ie
= (cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY
, tail_pos
, tail_length
));
1704 ext_capab_ie
= cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY
, tail_pos
, tail_length
);
1705 while (tail_length
> 2) {
1706 if (tail_pos
[0] == WLAN_EID_VHT_CAPABILITY
)
1707 slsi_ap_add_ext_capab_ie(req
, ndev_vif
, ext_capab_ie
);
1708 else if (tail_pos
[0] != WLAN_EID_EXT_CAPABILITY
&& tail_pos
[0] != WLAN_EID_VHT_OPERATION
)
1709 fapi_append_data(req
, tail_pos
, tail_pos
[1] + 2);
1711 tail_length
-= tail_pos
[1] + 2;
1712 tail_pos
+= tail_pos
[1] + 2;
1715 slsi_ap_add_ext_capab_ie(req
, ndev_vif
, ext_capab_ie
);
1717 fapi_append_data(req
, tail_pos
, tail_length
);
1720 fapi_append_data(req
, tail_pos
, tail_length
);
1724 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1725 /*EID + LEN + CAPABILITIES + MCS */
1727 #define SLSI_VHT_CAPABILITIES_IE_LEN 14
1729 /* EID + LEN + WIDTH + SEG0 + SEG1 + MCS */
1731 #define SLSI_VHT_OPERATION_IE_LEN 7
1733 static int slsi_prepare_vht_ies(struct net_device
*dev
, u8
**vht_ie_capab
, u8
**vht_ie_operation
)
1738 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
1740 *vht_ie_capab
= kmalloc(SLSI_VHT_CAPABILITIES_IE_LEN
, GFP_KERNEL
);
1741 if (!(*vht_ie_capab
))
1743 *vht_ie_operation
= kmalloc(SLSI_VHT_OPERATION_IE_LEN
, GFP_KERNEL
);
1744 if (!(*vht_ie_operation
)) {
1745 kfree(*vht_ie_capab
);
1749 p_cap
= *vht_ie_capab
;
1750 p_oper
= *vht_ie_operation
;
1752 *p_cap
++ = WLAN_EID_VHT_CAPABILITY
;
1753 *p_cap
++ = SLSI_VHT_CAPABILITIES_IE_LEN
- 1 - 1;
1754 capabs
= cpu_to_le32(slsi_vht_cap
.cap
);
1755 memcpy(p_cap
, &capabs
, sizeof(capabs
));
1756 p_cap
+= sizeof(capabs
);
1757 memcpy(p_cap
, &slsi_vht_cap
.vht_mcs
, sizeof(slsi_vht_cap
.vht_mcs
));
1759 *p_oper
++ = WLAN_EID_VHT_OPERATION
;
1760 *p_oper
++ = SLSI_VHT_OPERATION_IE_LEN
- 1 - 1;
1761 *p_oper
++ = IEEE80211_VHT_CHANWIDTH_80MHZ
;
1762 *p_oper
++ = ieee80211_frequency_to_channel(ndev_vif
->chandef
->center_freq1
);
1764 mcs
= cpu_to_le16(0xfffc);
1765 memcpy(p_oper
, &mcs
, sizeof(mcs
));
1771 int slsi_mlme_start(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
*bssid
, struct cfg80211_ap_settings
*settings
, const u8
*wpa_ie_pos
, const u8
*wmm_ie_pos
, bool append_vht_ies
)
1773 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
1774 struct sk_buff
*req
;
1775 struct sk_buff
*cfm
;
1776 struct ieee80211_mgmt
*mgmt
;
1779 enum nl80211_auth_type auth_type
= settings
->auth_type
;
1780 u16 beacon_ie_head_len
;
1783 u16 vht_ies_len
= 0;
1784 u8 ext_capab_len
= 0;
1785 const u8
*recv_vht_capab_ie
, *recv_vht_operation_ie
;
1787 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1788 u8
*vht_ie_capab
, *vht_ie_operation
;
1790 SLSI_UNUSED_PARAMETER(bssid
);
1792 if (slsi_is_test_mode_enabled()) {
1793 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_START.request\n");
1797 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
1799 mgmt
= (struct ieee80211_mgmt
*)settings
->beacon
.head
;
1800 beacon_ie_head_len
= settings
->beacon
.head_len
- ((u8
*)mgmt
->u
.beacon
.variable
- (u8
*)mgmt
);
1802 /* For port enabling, save the privacy bit used in assoc response or beacon */
1803 ndev_vif
->ap
.privacy
= (mgmt
->u
.beacon
.capab_info
& WLAN_CAPABILITY_PRIVACY
);
1804 ndev_vif
->ap
.qos_enabled
= (mgmt
->u
.beacon
.capab_info
& WLAN_CAPABILITY_QOS
);
1806 switch (auth_type
) {
1807 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
1808 case NL80211_AUTHTYPE_SHARED_KEY
:
1810 case NL80211_AUTHTYPE_AUTOMATIC
:
1811 auth_type
= NL80211_AUTHTYPE_OPEN_SYSTEM
;
1812 if (settings
->privacy
&& settings
->crypto
.cipher_group
== 0)
1813 auth_type
= NL80211_AUTHTYPE_SHARED_KEY
;
1816 SLSI_NET_ERR(dev
, "Unsupported auth_type: %d\n", auth_type
);
1820 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_start_req(vif:%u, bssid:%pM, ssid:%.*s, hidden:%d)\n", ndev_vif
->ifnum
, bssid
, (int)settings
->ssid_len
, settings
->ssid
, settings
->hidden_ssid
);
1822 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1824 vht_ies_len
= SLSI_VHT_CAPABILITIES_IE_LEN
+ SLSI_VHT_OPERATION_IE_LEN
;
1826 recv_vht_capab_ie
= cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY
, settings
->beacon
.tail
,
1827 settings
->beacon
.tail_len
);
1828 if (recv_vht_capab_ie
)
1829 vht_ies_len
-= (recv_vht_capab_ie
[1] + 2);
1831 recv_vht_operation_ie
= cfg80211_find_ie(WLAN_EID_VHT_OPERATION
, settings
->beacon
.tail
,
1832 settings
->beacon
.tail_len
);
1833 if (recv_vht_operation_ie
)
1834 vht_ies_len
-= (recv_vht_operation_ie
[1] + 2);
1836 if (ndev_vif
->chandef
->width
== NL80211_CHAN_WIDTH_80
) {
1837 /* Ext Capab are not advertised by driver and so the IE would not be sent by hostapd.
1838 * Frame the IE in driver and set the required bit(s).
1840 SLSI_NET_DBG1(dev
, SLSI_MLME
, "VHT - Ext Capab IE to be included\n");
1841 ext_capab_len
= SLSI_AP_EXT_CAPAB_IE_LEN_MAX
;
1845 if (settings
->hidden_ssid
== 1)
1846 req
= fapi_alloc(mlme_start_req
, MLME_START_REQ
, ndev_vif
->ifnum
, settings
->ssid_len
+ beacon_ie_head_len
+ settings
->beacon
.tail_len
+ vht_ies_len
+ ext_capab_len
);
1848 req
= fapi_alloc(mlme_start_req
, MLME_START_REQ
, ndev_vif
->ifnum
, beacon_ie_head_len
+ settings
->beacon
.tail_len
+ vht_ies_len
+ ext_capab_len
);
1852 fapi_set_memcpy(req
, u
.mlme_start_req
.bssid
, dev
->dev_addr
);
1853 fapi_set_u16(req
, u
.mlme_start_req
.beacon_period
, settings
->beacon_interval
);
1854 fapi_set_u16(req
, u
.mlme_start_req
.dtim_period
, settings
->dtim_period
);
1855 fapi_set_u16(req
, u
.mlme_start_req
.capability_information
, le16_to_cpu(mgmt
->u
.beacon
.capab_info
));
1856 fapi_set_u16(req
, u
.mlme_start_req
.authentication_type
, auth_type
);
1857 fapi_set_u16(req
, u
.mlme_start_req
.hidden_ssid
, settings
->hidden_ssid
< 3 ? settings
->hidden_ssid
: NL80211_HIDDEN_SSID_ZERO_LEN
);
1859 fw_freq
= ndev_vif
->chan
->center_freq
;
1860 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1861 chan_info
= slsi_get_chann_info(sdev
, ndev_vif
->chandef
);
1863 chan_info
= slsi_get_chann_info(sdev
, ndev_vif
->channel_type
);
1865 if ((chan_info
& 20) != 20)
1866 fw_freq
= slsi_get_center_freq1(sdev
, chan_info
, fw_freq
);
1868 fapi_set_u16(req
, u
.mlme_start_req
.channel_frequency
, (2 * fw_freq
));
1869 fapi_set_u16(req
, u
.mlme_start_req
.channel_information
, chan_info
);
1870 ndev_vif
->ap
.channel_freq
= fw_freq
;
1872 /* Addition of SSID IE in mlme_start_req for hiddenSSID case */
1873 if (settings
->hidden_ssid
!= 0) {
1874 p
= fapi_append_data(req
, NULL
, 2 + settings
->ssid_len
);
1876 slsi_kfree_skb(req
);
1879 *p
++ = WLAN_EID_SSID
;
1880 *p
++ = settings
->ssid_len
;
1881 memcpy(p
, settings
->ssid
, settings
->ssid_len
);
1884 if (beacon_ie_head_len
&& settings
->hidden_ssid
== 0)
1885 fapi_append_data(req
, mgmt
->u
.beacon
.variable
, beacon_ie_head_len
);
1886 else if (beacon_ie_head_len
&& settings
->hidden_ssid
== 1)
1887 fapi_append_data(req
, mgmt
->u
.beacon
.variable
+ 2, beacon_ie_head_len
- 2);
1888 else if (beacon_ie_head_len
&& settings
->hidden_ssid
== 2)
1889 fapi_append_data(req
, mgmt
->u
.beacon
.variable
+ 2 + settings
->ssid_len
, beacon_ie_head_len
- (2 + settings
->ssid_len
));
1891 if (settings
->beacon
.tail_len
)
1892 slsi_mlme_start_prepare_ies(req
, ndev_vif
, settings
, wpa_ie_pos
, wmm_ie_pos
);
1894 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
1895 if ((append_vht_ies
) && !slsi_prepare_vht_ies(dev
, &vht_ie_capab
, &vht_ie_operation
)) {
1896 fapi_append_data(req
, vht_ie_capab
, SLSI_VHT_CAPABILITIES_IE_LEN
);
1897 fapi_append_data(req
, vht_ie_operation
, SLSI_VHT_OPERATION_IE_LEN
);
1898 kfree(vht_ie_capab
);
1899 kfree(vht_ie_operation
);
1903 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_START_CFM
);
1906 if (fapi_get_u16(cfm
, u
.mlme_start_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
1907 SLSI_NET_ERR(dev
, "mlme_start_cfm(result:0x%04x) ERROR\n",
1908 fapi_get_u16(cfm
, u
.mlme_start_cfm
.result_code
));
1912 slsi_kfree_skb(cfm
);
1916 static const u8
*slsi_mlme_connect_get_sec_ie(struct cfg80211_connect_params
*sme
, int *sec_ie_len
)
1919 const u8
*ptr
= NULL
;
1921 if (sme
->crypto
.wpa_versions
== 0) {
1923 ptr
= cfg80211_find_ie(SLSI_WLAN_EID_WAPI
, sme
->ie
, sme
->ie_len
);
1925 version
= ptr
[3] << 8 | ptr
[2];
1927 SLSI_ERR_NODEV("Unexpected version (%d) in WAPI ie\n", version
);
1931 } else if (sme
->crypto
.wpa_versions
== 2) {
1933 ptr
= cfg80211_find_ie(WLAN_EID_RSN
, sme
->ie
, sme
->ie_len
);
1936 /* version index is 2 for RSN */
1937 version
= ptr
[2 + 1] << 8 | ptr
[2];
1939 SLSI_ERR_NODEV("Unexpected version (%d) in rsn ie\n", version
);
1944 *sec_ie_len
= ptr
? ptr
[1] + 2 : 0;
1948 /* If is_copy is true copy the required IEs from connect_ie to ie_dest. else
1949 * calculate the required ie length
1951 static int slsi_mlme_connect_info_elems_ie_prep(struct slsi_dev
*sdev
, const u8
*connect_ie
,
1952 const size_t connect_ie_len
, bool is_copy
, u8
*ie_dest
, int ie_dest_len
)
1954 const u8
*ie_pos
= NULL
;
1955 int info_elem_length
= 0;
1958 u8 ie_eid
[] = {SLSI_WLAN_EID_INTERWORKING
,
1959 SLSI_WLAN_EID_EXTENSION
,
1960 WLAN_EID_VENDOR_SPECIFIC
}; /*Vendor IE has to be the last element */
1962 if (is_copy
&& (!ie_dest
|| ie_dest_len
== 0))
1965 for (i
= 0; i
< sizeof(ie_eid
) / sizeof(u8
); i
++) {
1966 ie_pos
= cfg80211_find_ie(ie_eid
[i
], connect_ie
, connect_ie_len
);
1968 if (ie_eid
[i
] == WLAN_EID_VENDOR_SPECIFIC
) /*Vendor IE will be the last element */
1969 curr_ie_len
= connect_ie_len
- (ie_pos
- connect_ie
);
1971 curr_ie_len
= *(ie_pos
+ 1) + 2;
1972 SLSI_DBG2(sdev
, SLSI_MLME
, "IE[%d] is present having length:%d\n", ie_eid
[i
], curr_ie_len
);
1974 if (ie_dest_len
>= curr_ie_len
) {
1975 memcpy(ie_dest
, ie_pos
, curr_ie_len
);
1976 ie_dest
+= curr_ie_len
;
1977 /* free space avail in ie_dest for next ie*/
1978 ie_dest_len
-= curr_ie_len
;
1980 SLSI_ERR_NODEV("IE[%d] extract error (ie_copy_l:%d, c_ie_l:%d):\n", ie_eid
[i
],
1981 ie_dest_len
, curr_ie_len
);
1985 info_elem_length
+= curr_ie_len
;
1990 if (sdev
->device_config
.qos_info
!= -1) {
1992 if (ie_dest_len
>= 9) {
1995 ie_dest
[pos
++] = SLSI_WLAN_EID_VENDOR_SPECIFIC
;
1996 ie_dest
[pos
++] = 0x07;
1997 ie_dest
[pos
++] = 0x00;
1998 ie_dest
[pos
++] = 0x50;
1999 ie_dest
[pos
++] = 0xf2;
2000 ie_dest
[pos
++] = WLAN_OUI_TYPE_MICROSOFT_WMM
;
2001 ie_dest
[pos
++] = WMM_OUI_SUBTYPE_INFORMATION_ELEMENT
;
2002 ie_dest
[pos
++] = WMM_VERSION
;
2003 ie_dest
[pos
++] = sdev
->device_config
.qos_info
& 0x0F;
2007 SLSI_ERR_NODEV("Required 9bytes but left:%d\n", ie_dest_len
);
2011 info_elem_length
+= 9;
2014 return info_elem_length
;
2017 static int slsi_mlme_connect_info_elements(struct slsi_dev
*sdev
, struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
2019 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2020 int info_elem_length
= 0;
2021 struct sk_buff
*req
;
2022 struct sk_buff
*cfm
;
2026 info_elem_length
= slsi_mlme_connect_info_elems_ie_prep(sdev
, sme
->ie
, sme
->ie_len
, false, NULL
, 0);
2028 /* NO IE required in MLME-ADD-INFO-ELEMENTS */
2029 if (info_elem_length
<= 0)
2030 return info_elem_length
;
2032 req
= fapi_alloc(mlme_add_info_elements_req
, MLME_ADD_INFO_ELEMENTS_REQ
,
2033 ndev_vif
->ifnum
, info_elem_length
);
2037 fapi_set_u16(req
, u
.mlme_add_info_elements_req
.purpose
, FAPI_PURPOSE_ASSOCIATION_REQUEST
);
2039 p
= fapi_append_data(req
, NULL
, info_elem_length
);
2041 slsi_kfree_skb(req
);
2045 (void)slsi_mlme_connect_info_elems_ie_prep(sdev
, sme
->ie
, sme
->ie_len
, true, p
, info_elem_length
);
2048 if (SLSI_IS_VIF_INDEX_WLAN(ndev_vif
)) {
2049 if (ndev_vif
->sta
.assoc_req_add_info_elem_len
)
2050 kfree(ndev_vif
->sta
.assoc_req_add_info_elem
);
2051 ndev_vif
->sta
.assoc_req_add_info_elem_len
= 0;
2053 ndev_vif
->sta
.assoc_req_add_info_elem
= kmalloc(info_elem_length
, GFP_KERNEL
);
2054 if (ndev_vif
->sta
.assoc_req_add_info_elem
) {
2055 memcpy(ndev_vif
->sta
.assoc_req_add_info_elem
, p
, info_elem_length
);
2056 ndev_vif
->sta
.assoc_req_add_info_elem_len
= info_elem_length
;
2058 SLSI_WARN(sdev
, "No mem for ndev_vif->sta.assoc_req_add_info_elem size %d\n", info_elem_length
);
2062 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_add_info_elements_req(vif:%u)\n", ndev_vif
->ifnum
);
2063 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_ADD_INFO_ELEMENTS_CFM
);
2067 if (fapi_get_u16(cfm
, u
.mlme_add_info_elements_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2068 SLSI_NET_ERR(dev
, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n",
2069 fapi_get_u16(cfm
, u
.mlme_connect_cfm
.result_code
));
2073 if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT
, WLAN_OUI_TYPE_MICROSOFT_WPS
, sme
->ie
, sme
->ie_len
))
2074 ndev_vif
->sta
.is_wps
= true;
2076 slsi_kfree_skb(cfm
);
2080 int slsi_mlme_connect(struct slsi_dev
*sdev
, struct net_device
*dev
, struct cfg80211_connect_params
*sme
, struct ieee80211_channel
*channel
, const u8
*bssid
)
2082 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2083 struct sk_buff
*req
;
2084 struct sk_buff
*cfm
;
2087 enum nl80211_auth_type auth_type
= sme
->auth_type
;
2088 u8 mac_addr
[ETH_ALEN
] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
2089 struct key_params slsi_key
;
2090 const u8
*sec_ie
= NULL
;
2093 memset(&slsi_key
, 0, sizeof(slsi_key
));
2095 if (slsi_is_test_mode_enabled()) {
2096 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_CONNECT.request\n");
2100 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2102 if (WARN(!bssid
, "BSSID is Null"))
2105 if (WARN(!sme
->ssid_len
, "SSID is Null"))
2108 switch (auth_type
) {
2109 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
2110 case NL80211_AUTHTYPE_SHARED_KEY
:
2112 case NL80211_AUTHTYPE_SAE
:
2113 auth_type
= NL80211_AUTHTYPE_NETWORK_EAP
;
2115 case NL80211_AUTHTYPE_AUTOMATIC
:
2116 /* In case of WEP, need to try both open and shared.
2117 * FW does this if auth is shared_key. So set it to shared.
2120 (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP40
||
2121 sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP104
))
2122 auth_type
= NL80211_AUTHTYPE_SHARED_KEY
;
2124 auth_type
= NL80211_AUTHTYPE_OPEN_SYSTEM
;
2127 SLSI_NET_ERR(dev
, "Unsupported auth_type: %d\n", auth_type
);
2131 /* We save the WEP key for shared authentication. */
2132 if ((auth_type
== NL80211_AUTHTYPE_SHARED_KEY
) &&
2133 ((sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP40
) ||
2134 (sme
->crypto
.cipher_group
== WLAN_CIPHER_SUITE_WEP104
)) &&
2135 (ndev_vif
->vif_type
== FAPI_VIFTYPE_STATION
)) {
2136 SLSI_NET_DBG3(dev
, SLSI_MLME
, "key len (%d)\n", sme
->key_len
);
2137 slsi_key
.key
= (u8
*)sme
->key
;
2140 slsi_key
.key_len
= sme
->key_len
;
2141 slsi_key
.seq_len
= 0;
2142 if (sme
->crypto
.n_ciphers_pairwise
)
2143 slsi_key
.cipher
= sme
->crypto
.ciphers_pairwise
[0];
2145 r
= slsi_mlme_set_key(sdev
, dev
, sme
->key_idx
, FAPI_KEYTYPE_WEP
, mac_addr
, &slsi_key
);
2147 SLSI_NET_ERR(dev
, "Error Setting Shared key (%d)", r
);
2152 /*Do not check sme->ie as wpa_supplicant sends some invalid value in it even if ie_len is zero .*/
2154 r
= slsi_mlme_connect_info_elements(sdev
, dev
, sme
);
2158 sec_ie
= slsi_mlme_connect_get_sec_ie(sme
, &sec_ie_len
);
2159 if (sec_ie_len
< 0) {
2160 SLSI_NET_ERR(dev
, "ERROR preparing Security IEs\n");
2165 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_connect_req(vif:%u, bssid:%pM, ssid:%.*s)\n", ndev_vif
->ifnum
, bssid
, (int)sme
->ssid_len
, sme
->ssid
);
2166 req
= fapi_alloc(mlme_connect_req
, MLME_CONNECT_REQ
, ndev_vif
->ifnum
,
2167 2 + sme
->ssid_len
+ /*SSID IE*/
2168 sec_ie_len
); /*WPA/WPA2/WAPI/OSEN*/
2172 fapi_set_memcpy(req
, u
.mlme_connect_req
.bssid
, bssid
);
2173 fapi_set_u16(req
, u
.mlme_connect_req
.authentication_type
, auth_type
);
2174 /* Need to double the freq for the firmware */
2175 fapi_set_u16(req
, u
.mlme_connect_req
.channel_frequency
, (2 * channel
->center_freq
));
2177 p
= fapi_append_data(req
, NULL
, 2 + sme
->ssid_len
+ sec_ie_len
);
2179 slsi_kfree_skb(req
);
2182 *p
++ = WLAN_EID_SSID
;
2183 *p
++ = sme
->ssid_len
;
2184 memcpy(p
, sme
->ssid
, sme
->ssid_len
);
2188 memcpy(p
, sec_ie
, sec_ie_len
);
2189 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_CONNECT_CFM
);
2193 if (fapi_get_u16(cfm
, u
.mlme_connect_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2194 SLSI_NET_ERR(dev
, "mlme_connect_cfm(result:0x%04x) ERROR\n",
2195 fapi_get_u16(cfm
, u
.mlme_connect_cfm
.result_code
));
2199 slsi_kfree_skb(cfm
);
2203 void slsi_mlme_connect_resp(struct slsi_dev
*sdev
, struct net_device
*dev
)
2205 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2206 struct sk_buff
*req
;
2207 struct sk_buff
*cfm
;
2209 if (slsi_is_test_mode_enabled()) {
2210 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n");
2214 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_connect_resp(vif:%u)\n", ndev_vif
->ifnum
);
2215 req
= fapi_alloc(mlme_connect_res
, MLME_CONNECT_RES
, ndev_vif
->ifnum
, 0);
2219 cfm
= slsi_mlme_req_no_cfm(sdev
, dev
, req
);
2223 void slsi_mlme_connected_resp(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 peer_index
)
2225 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2226 struct sk_buff
*req
;
2228 if (slsi_is_test_mode_enabled()) {
2229 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_CONNECT_RESP\n");
2233 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_connected_resp(vif:%u, peer_index:%d)\n", ndev_vif
->ifnum
, peer_index
);
2234 req
= fapi_alloc(mlme_connected_res
, MLME_CONNECTED_RES
, ndev_vif
->ifnum
, 0);
2236 SLSI_NET_ERR(dev
, "mlme-connected-response :: memory allocation failed\n");
2240 fapi_set_u16(req
, u
.mlme_connected_res
.association_identifier
, peer_index
);
2241 slsi_mlme_req_no_cfm(sdev
, dev
, req
);
2244 void slsi_mlme_roamed_resp(struct slsi_dev
*sdev
, struct net_device
*dev
)
2246 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2247 struct sk_buff
*req
;
2248 struct sk_buff
*cfm
;
2250 if (slsi_is_test_mode_enabled()) {
2251 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_ROAMED_RESP\n");
2255 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_roamed_resp\n");
2256 req
= fapi_alloc(mlme_roamed_res
, MLME_ROAMED_RES
, ndev_vif
->ifnum
, 0);
2260 cfm
= slsi_mlme_req_no_cfm(sdev
, dev
, req
);
2264 /* Null check for cfm done in caller function */
2265 bool slsi_disconnect_cfm_validate(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*cfm
)
2267 int result
= fapi_get_u16(cfm
, u
.mlme_disconnect_cfm
.result_code
);
2270 SLSI_UNUSED_PARAMETER(sdev
);
2275 if (result
== FAPI_RESULTCODE_SUCCESS
)
2277 /* Not present code would mean peer is already disconnected and hence no ind (could be race scenario), don't log as error */
2278 else if (result
!= FAPI_RESULTCODE_NOT_PRESENT
)
2279 SLSI_NET_ERR(dev
, "mlme_disconnect_cfm(result:0x%04x) ERROR\n",
2280 fapi_get_u16(cfm
, u
.mlme_disconnect_cfm
.result_code
));
2283 slsi_kfree_skb(cfm
);
2287 int slsi_mlme_disconnect(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
*mac
, u16 reason_code
, bool wait_ind
)
2289 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2290 struct sk_buff
*req
;
2294 if (slsi_is_test_mode_enabled()) {
2295 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_DISCONNECT.request\n");
2299 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2301 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_disconnect_req(vif:%u, bssid:%pM, reason:%d)\n", ndev_vif
->ifnum
, mac
, reason_code
);
2303 req
= fapi_alloc(mlme_disconnect_req
, MLME_DISCONNECT_REQ
, ndev_vif
->ifnum
,
2304 ndev_vif
->sta
.vendor_disconnect_ies_len
);
2308 SLSI_INFO(sdev
, "Send DEAUTH, reason = %d\n", reason_code
);
2309 fapi_set_u16(req
, u
.mlme_disconnect_req
.reason_code
, reason_code
);
2310 if (ndev_vif
->sta
.vendor_disconnect_ies_len
> 0)
2311 fapi_append_data(req
, ndev_vif
->sta
.vendor_disconnect_ies
, ndev_vif
->sta
.vendor_disconnect_ies_len
);
2312 kfree(ndev_vif
->sta
.vendor_disconnect_ies
);
2313 ndev_vif
->sta
.vendor_disconnect_ies
= NULL
;
2314 ndev_vif
->sta
.vendor_disconnect_ies_len
= 0;
2317 fapi_set_memcpy(req
, u
.mlme_disconnect_req
.peer_sta_address
, mac
);
2319 fapi_set_memset(req
, u
.mlme_disconnect_req
.peer_sta_address
, 0);
2321 rx
= slsi_mlme_req_cfm_ind(sdev
, dev
, req
, MLME_DISCONNECT_CFM
, MLME_DISCONNECT_IND
, slsi_disconnect_cfm_validate
);
2323 SLSI_NET_ERR(dev
, "mlme_disconnect_cfm() ERROR\n");
2327 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_DISCONNECT_CFM
);
2329 if (fapi_get_u16(rx
, u
.mlme_disconnect_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2330 SLSI_NET_ERR(dev
, "mlme_disconnect_cfm(result:0x%04x) ERROR\n",
2331 fapi_get_u16(rx
, u
.mlme_disconnect_cfm
.result_code
));
2343 int slsi_mlme_set_key(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 key_id
, u16 key_type
, const u8
*address
, struct key_params
*key
)
2345 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2346 struct sk_buff
*req
;
2347 struct sk_buff
*cfm
;
2350 if (slsi_is_test_mode_enabled()) {
2351 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_SETKEYS.request\n");
2355 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2357 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_setkeys_req(key_id:%d, key_type:%d, address:%pM, length:%d, cipher:0x%.8X)\n", key_id
, key_type
, address
, key
->key_len
, key
->cipher
);
2358 req
= fapi_alloc(mlme_setkeys_req
, MLME_SETKEYS_REQ
, ndev_vif
->ifnum
, key
->key_len
+ 1); /* + 1 for the wep key index */
2361 fapi_set_u16(req
, u
.mlme_setkeys_req
.length
, key
->key_len
* 8);
2362 fapi_set_u16(req
, u
.mlme_setkeys_req
.key_id
, key_id
);
2363 fapi_set_u16(req
, u
.mlme_setkeys_req
.key_type
, key_type
);
2364 fapi_set_memcpy(req
, u
.mlme_setkeys_req
.address
, address
);
2365 fapi_set_memset(req
, u
.mlme_setkeys_req
.sequence_number
, 0x00);
2367 if (key
->seq_len
&& key
->seq
) {
2371 SLSI_NET_DBG3(dev
, SLSI_MLME
, "mlme_setkeys_req(key->seq_len:%d)\n", key
->seq_len
);
2373 /* Sequence would be in little endian format
2374 * If sequence is say key->seq is
2375 * 04 03 02 01 00 00 00 00, it would be encoded as :
2376 * 0x0304 0x0102 0x0000 0x0000 for firmware
2378 for (i
= 0; i
< key
->seq_len
; i
+= 2) {
2379 temp_seq
= (u16
)(key
->seq
[i
+ 1] << 8) | (u16
)(key
->seq
[i
]);
2380 fapi_set_u16(req
, u
.mlme_setkeys_req
.sequence_number
[i
/ 2], temp_seq
);
2384 fapi_set_u32(req
, u
.mlme_setkeys_req
.cipher_suite_selector
, key
->cipher
);
2386 if (key
->cipher
== WLAN_CIPHER_SUITE_WEP40
|| key
->cipher
== WLAN_CIPHER_SUITE_WEP104
) {
2387 u8 wep_key_id
= (u8
)key_id
;
2390 SLSI_NET_WARN(dev
, "Key ID is greater than 3");
2391 /* Incase of WEP key index is appended before key.
2392 * So increment length by one
2394 fapi_set_u16(req
, u
.mlme_setkeys_req
.length
, (key
->key_len
+ 1) * 8);
2395 fapi_append_data(req
, &wep_key_id
, 1);
2397 fapi_append_data(req
, key
->key
, key
->key_len
);
2399 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SETKEYS_CFM
);
2403 if (fapi_get_u16(cfm
, u
.mlme_setkeys_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2404 SLSI_NET_ERR(dev
, "mlme_setkeys_cfm(result:0x%04x) ERROR\n",
2405 fapi_get_u16(cfm
, u
.mlme_setkeys_cfm
.result_code
));
2408 slsi_kfree_skb(cfm
);
2412 int slsi_mlme_get_key(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 key_id
, u16 key_type
, u8
*seq
, int *seq_len
)
2414 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2415 struct sk_buff
*req
;
2416 struct sk_buff
*cfm
;
2419 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2421 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_get_key_sequence_req(key_id:%d, key_type:%d)\n", key_id
, key_type
);
2422 req
= fapi_alloc(mlme_get_key_sequence_req
, MLME_GET_KEY_SEQUENCE_REQ
, ndev_vif
->ifnum
, 0);
2425 fapi_set_u16(req
, u
.mlme_get_key_sequence_req
.key_id
, key_id
);
2426 fapi_set_u16(req
, u
.mlme_get_key_sequence_req
.key_type
, key_type
);
2428 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_GET_KEY_SEQUENCE_CFM
);
2432 if (fapi_get_u16(cfm
, u
.mlme_get_key_sequence_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2433 SLSI_NET_ERR(dev
, "mlme_get_key_sequence_cfm(result:0x%04x) ERROR\n",
2434 fapi_get_u16(cfm
, u
.mlme_get_key_sequence_cfm
.result_code
));
2440 /* For WPA2 Key RSC - 8 octets. For WPAI, it would be 16 octets (code would need to be updated)
2441 * Length is not available in cfm but even if max length 8 is assigned, it should be ok as other octets
2442 * would be padded with 0s
2446 /* Sequence from firmware is of a[8] type u16 (16 octets) and only 8 octets are required for WPA/WPA2.
2447 * If sequence is say 0x01 0x02 0x03 0x04 with 0x01 as MSB and 0x04 as LSB then
2448 * it would be encoded as: 0x0304 0x0102 by firmware.
2449 * Sequence is expected to be returned in little endian
2452 for (i
= 0; i
< *seq_len
/ 2; i
++) {
2453 temp_seq
= fapi_get_u16(cfm
, u
.mlme_get_key_sequence_cfm
.sequence_number
[i
]);
2454 *seq
= (u8
)(temp_seq
& 0xFF);
2455 *(seq
+ 1) = (u8
)((temp_seq
>> 8) & 0xFF);
2461 slsi_kfree_skb(cfm
);
2465 void slsi_calc_max_data_rate(struct net_device
*dev
, u8 bandwidth
, u8 antenna_mode
)
2467 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2468 u8 bandwidth_index
, sta_mode
, mcs_index
;
2470 if (bandwidth
== 0 || antenna_mode
> 3) {
2471 SLSI_NET_ERR(dev
, "MIB value is wrong.");
2475 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2477 /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */
2478 bandwidth_index
= bandwidth
/ 40;
2479 sta_mode
= slsi_sta_ieee80211_mode(dev
, ndev_vif
->sta
.sta_bss
->channel
->center_freq
);
2481 if (sta_mode
== SLSI_80211_MODE_11B
) {
2482 ndev_vif
->sta
.max_rate_mbps
= 11;
2483 } else if (sta_mode
== SLSI_80211_MODE_11G
|| sta_mode
== SLSI_80211_MODE_11A
) {
2484 ndev_vif
->sta
.max_rate_mbps
= 54;
2485 } else if (sta_mode
== SLSI_80211_MODE_11N
) { /* max mcs index = 7 */
2486 ndev_vif
->sta
.max_rate_mbps
= (unsigned long)(slsi_rates_table
[bandwidth_index
][1][7] * (antenna_mode
+ 1)) / 10;
2487 } else if (sta_mode
== SLSI_80211_MODE_11AC
) {
2488 if (bandwidth_index
== 0)
2492 ndev_vif
->sta
.max_rate_mbps
= (unsigned long)(slsi_rates_table
[bandwidth_index
][1][mcs_index
] * (antenna_mode
+ 1)) / 10;
2496 void slsi_decode_fw_rate(u16 fw_rate
, struct rate_info
*rate
, unsigned long *data_rate_mbps
)
2498 const int fw_rate_idx_to_80211_rate
[] = { 0, 10, 20, 55, 60, 90, 110, 120, 180, 240, 360, 480, 540 };
2503 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2508 if ((fw_rate
& SLSI_FW_API_RATE_HT_SELECTOR_FIELD
) == SLSI_FW_API_RATE_NON_HT_SELECTED
) {
2509 u16 fw_rate_idx
= fw_rate
& SLSI_FW_API_RATE_INDEX_FIELD
;
2511 if (fw_rate
> 0 && fw_rate_idx
< ARRAY_SIZE(fw_rate_idx_to_80211_rate
)) {
2513 rate
->legacy
= fw_rate_idx_to_80211_rate
[fw_rate_idx
];
2515 *data_rate_mbps
= fw_rate_idx_to_80211_rate
[fw_rate_idx
] / 10;
2517 } else if ((fw_rate
& SLSI_FW_API_RATE_HT_SELECTOR_FIELD
) == SLSI_FW_API_RATE_HT_SELECTED
) {
2518 u8 mcs_idx
= SLSI_FW_API_RATE_HT_MCS_FIELD
& fw_rate
;
2519 u8 nss
= ((SLSI_FW_API_RATE_HT_NSS_FIELD
& fw_rate
) >> 6) + 1;
2522 rate
->flags
|= RATE_INFO_FLAGS_MCS
;
2523 rate
->mcs
= mcs_idx
;
2525 if ((fw_rate
& SLSI_FW_API_RATE_BW_FIELD
) == SLSI_FW_API_RATE_BW_40MHZ
)
2526 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2527 rate
->bw
|= RATE_INFO_BW_40
;
2529 rate
->flags
|= RATE_INFO_FLAGS_40_MHZ_WIDTH
;
2531 if (fw_rate
& SLSI_FW_API_RATE_SGI
)
2532 rate
->flags
|= RATE_INFO_FLAGS_SHORT_GI
;
2535 if (data_rate_mbps
) {
2539 chan_bw_idx
= (fw_rate
& SLSI_FW_API_RATE_BW_FIELD
) >> 9;
2540 gi_idx
= ((fw_rate
& SLSI_FW_API_RATE_SGI
) == SLSI_FW_API_RATE_SGI
) ? 1 : 0;
2542 /* nss will be 1 when mcs_idx <= 7 or mcs == 32 */
2543 if (chan_bw_idx
< 2) {
2545 *data_rate_mbps
= slsi_rates_table
[chan_bw_idx
][gi_idx
][mcs_idx
] / 10;
2546 } else if (mcs_idx
<= 15) {
2547 *data_rate_mbps
= (unsigned long)(nss
* slsi_rates_table
[chan_bw_idx
][gi_idx
][mcs_idx
- 8]) / 10;
2548 } else if (mcs_idx
== 32 && chan_bw_idx
== 1) {
2549 /* TODO: Fix this : unsigned long will not hold decimal values */
2551 *data_rate_mbps
= (unsigned long) 6.7;
2553 *data_rate_mbps
= 6;
2556 SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x, nss : %d\n",
2557 fw_rate
, chan_bw_idx
, mcs_idx
, nss
);
2560 } else if ((fw_rate
& SLSI_FW_API_RATE_HT_SELECTOR_FIELD
) == SLSI_FW_API_RATE_VHT_SELECTED
) {
2566 /* report vht rate in legacy units and not as mcs index. reason: upper layers may still be not
2567 * updated with vht msc table.
2569 chan_bw_idx
= (fw_rate
& SLSI_FW_API_RATE_BW_FIELD
) >> 9;
2570 gi_idx
= ((fw_rate
& SLSI_FW_API_RATE_SGI
) == SLSI_FW_API_RATE_SGI
) ? 1 : 0;
2571 /* Calculate NSS --> bits 6 to 4*/
2572 nss
= ((SLSI_FW_API_RATE_VHT_NSS_FIELD
& fw_rate
) >> 4) + 1;
2573 mcs_idx
= SLSI_FW_API_RATE_VHT_MCS_FIELD
& fw_rate
;
2574 /* Bandwidth (BW): 0x0= 20 MHz, 0x1= 40 MHz, 0x2= 80 MHz, 0x3= 160/ 80+80 MHz. 0x3 is not supported */
2575 if ((chan_bw_idx
<= 2) && (mcs_idx
<= 9)) {
2577 rate
->legacy
= nss
* slsi_rates_table
[chan_bw_idx
][gi_idx
][mcs_idx
];
2579 *data_rate_mbps
= (unsigned long)(nss
* slsi_rates_table
[chan_bw_idx
][gi_idx
][mcs_idx
]) / 10;
2581 SLSI_WARN_NODEV("FW DATA RATE decode error fw_rate:%x, bw:%x, mcs_idx:%x,nss : %d\n", fw_rate
, chan_bw_idx
, mcs_idx
, nss
);
2586 int slsi_mlme_get_sinfo_mib(struct slsi_dev
*sdev
, struct net_device
*dev
,
2587 struct slsi_peer
*peer
)
2589 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2590 struct slsi_mib_data mibreq
= { 0, NULL
};
2591 struct slsi_mib_data mibrsp
= { 0, NULL
};
2592 struct slsi_mib_value
*values
= NULL
;
2593 u8 bandwidth
= 0, antenna_mode
= 4;
2594 int data_length
= 0;
2597 static const struct slsi_mib_get_entry get_values
[] = {
2598 { SLSI_PSID_UNIFI_TX_DATA_RATE
, { 0, 0 } }, /* to get STATION_INFO_TX_BITRATE*/
2599 { SLSI_PSID_UNIFI_RX_DATA_RATE
, { 0, 0 } }, /* to get STATION_INFO_RX_BITRATE*/
2600 { SLSI_PSID_UNIFI_RSSI
, { 0, 0 } }, /* to get STATION_INFO_SIGNAL_AVG*/
2601 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG
, { 3, 0 } }, /* bad_fcs_count*/
2602 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG
, { 25, 0 } }, /* mac_bad_sig_count*/
2603 { SLSI_PSID_UNIFI_THROUGHPUT_DEBUG
, { 30, 0 } }, /* rx_error_count*/
2604 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS
, { 1, 0 } }, /*tx good count*/
2605 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS
, { 2, 0 } }, /*tx bad count*/
2606 { SLSI_PSID_UNIFI_FRAME_RX_COUNTERS
, { 1, 0 } }, /*rx good count*/
2607 { SLSI_PSID_UNIFI_CURRENT_BSS_BANDWIDTH
, { 0, 0 } }, /* bss bandwidth */
2608 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2609 { SLSI_PSID_UNIFI_FRAME_TX_COUNTERS
, { 3, 0 } }, /*tx retry count*/
2611 { SLSI_PSID_UNIFI_STA_VIF_LINK_NSS
, { 0, 0 } } /* current nss */
2615 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2618 SLSI_WARN(sdev
, "Peer Not available\n");
2622 /*check if function is called within given period*/
2623 if (__ratelimit(&peer
->sinfo_mib_get_rs
))
2626 r
= slsi_mib_encode_get_list(&mibreq
, (sizeof(get_values
) / sizeof(struct slsi_mib_get_entry
)),
2628 if (r
!= SLSI_MIB_STATUS_SUCCESS
)
2631 /* Fixed fields len (5) : 2 bytes(PSID) + 2 bytes (Len) + 1 byte (VLDATA header ) [10 for 2 PSIDs]
2632 * Data : 3*2 bytes for SLSI_PSID_UNIFI_TX_DATA_RATE & SLSI_PSID_UNIFI_RX_DATA_RATE, 1 byte for SLSI_PSID_UNIFI_RSSI
2633 * 10*7 bytes for 3 Throughput Mib's and 4 counter Mib's
2635 mibrsp
.dataLength
= 114;
2636 mibrsp
.data
= kmalloc(mibrsp
.dataLength
, GFP_KERNEL
);
2639 SLSI_NET_DBG1(dev
, SLSI_MLME
, "failed to allocate memory\n");
2644 r
= slsi_mlme_get(sdev
, dev
, mibreq
.data
, mibreq
.dataLength
, mibrsp
.data
,
2645 mibrsp
.dataLength
, &data_length
);
2649 mibrsp
.dataLength
= (u32
)data_length
;
2650 values
= slsi_mib_decode_get_list(&mibrsp
,
2651 (sizeof(get_values
) / sizeof(struct slsi_mib_get_entry
)), get_values
);
2653 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mib decode list failed\n");
2658 if (values
[mib_index
].type
!= SLSI_MIB_TYPE_NONE
) {
2659 SLSI_CHECK_TYPE(sdev
, values
[mib_index
].type
, SLSI_MIB_TYPE_UINT
);
2660 slsi_decode_fw_rate((u16
)values
[mib_index
].u
.uintValue
, &peer
->sinfo
.txrate
, &ndev_vif
->sta
.data_rate_mbps
);
2661 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2662 peer
->sinfo
.filled
|= BIT(NL80211_STA_INFO_TX_BITRATE
);
2664 peer
->sinfo
.filled
|= STATION_INFO_TX_BITRATE
;
2666 SLSI_DBG3(sdev
, SLSI_MLME
, "SLSI_PSID_UNIFI_TX_DATA_RATE = 0x%x\n",
2667 values
[mib_index
].u
.uintValue
);
2670 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2672 if (values
[++mib_index
].type
!= SLSI_MIB_TYPE_NONE
) {
2673 SLSI_CHECK_TYPE(sdev
, values
[mib_index
].type
, SLSI_MIB_TYPE_UINT
);
2674 slsi_decode_fw_rate((u16
)values
[mib_index
].u
.uintValue
, &peer
->sinfo
.rxrate
, NULL
);
2675 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2676 peer
->sinfo
.filled
|= BIT(NL80211_STA_INFO_RX_BITRATE
);
2678 peer
->sinfo
.filled
|= STATION_INFO_RX_BITRATE
;
2680 SLSI_DBG3(sdev
, SLSI_MLME
, "SLSI_PSID_UNIFI_RX_DATA_RATE = 0x%x\n",
2681 values
[mib_index
].u
.uintValue
);
2684 SLSI_DBG3(sdev
, SLSI_MLME
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2686 if (values
[++mib_index
].type
!= SLSI_MIB_TYPE_NONE
) {
2687 SLSI_CHECK_TYPE(sdev
, values
[mib_index
].type
, SLSI_MIB_TYPE_INT
);
2688 if (values
[mib_index
].u
.intValue
>= 0)
2689 peer
->sinfo
.signal
= -1;
2691 peer
->sinfo
.signal
= (s8
)values
[mib_index
].u
.intValue
;
2692 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2693 peer
->sinfo
.filled
|= BIT(NL80211_STA_INFO_SIGNAL
);
2695 peer
->sinfo
.filled
|= STATION_INFO_SIGNAL
;
2697 SLSI_DBG3(sdev
, SLSI_MLME
, "SLSI_PSID_UNIFI_RSSI = %d\n",
2698 values
[mib_index
].u
.intValue
);
2701 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2703 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2704 rx_counter
+= values
[mib_index
].u
.uintValue
; /*bad_fcs_count*/
2706 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2707 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2708 rx_counter
+= values
[mib_index
].u
.uintValue
; /*mac_bad_sig_count*/
2710 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2711 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2712 rx_counter
+= values
[mib_index
].u
.uintValue
; /*rx_error_count*/
2714 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2715 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2716 peer
->sinfo
.tx_packets
= values
[mib_index
].u
.uintValue
; /*tx good count*/
2718 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2719 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2720 peer
->sinfo
.tx_failed
= values
[mib_index
].u
.uintValue
; /*tx bad count*/
2722 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2723 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2724 peer
->sinfo
.rx_packets
= values
[mib_index
].u
.uintValue
; /*rx good count*/
2726 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2727 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2728 bandwidth
= values
[mib_index
].u
.uintValue
; /* bss bandwidth */
2730 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2731 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2732 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
)
2733 peer
->sinfo
.tx_retries
= values
[mib_index
].u
.uintValue
; /*tx retry count*/
2735 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2737 if (values
[++mib_index
].type
== SLSI_MIB_TYPE_UINT
) {
2738 antenna_mode
= values
[mib_index
].u
.uintValue
; /* current nss */
2739 slsi_calc_max_data_rate(dev
, bandwidth
, antenna_mode
);
2741 SLSI_ERR(sdev
, "Invalid type: PSID = 0x%x\n", get_values
[mib_index
].psid
);
2744 peer
->sinfo
.rx_dropped_misc
= rx_counter
;
2746 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2747 peer
->sinfo
.filled
|= BIT(NL80211_STA_INFO_TX_FAILED
) | BIT(NL80211_STA_INFO_RX_DROP_MISC
) |
2748 BIT(NL80211_STA_INFO_TX_PACKETS
) | BIT(NL80211_STA_INFO_RX_PACKETS
);
2749 #ifdef CONFIG_SCSC_ENHANCED_PACKET_STATS
2750 peer
->sinfo
.filled
|= BIT(NL80211_STA_INFO_TX_RETRIES
);
2754 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_get_req failed(result:0x%4x)\n", r
);
2762 int slsi_mlme_connect_scan(struct slsi_dev
*sdev
, struct net_device
*dev
,
2763 u32 n_ssids
, struct cfg80211_ssid
*ssids
, struct ieee80211_channel
*channel
)
2765 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2767 struct ieee80211_channel
**scan_channels
= NULL
;
2768 struct ieee80211_channel
**add_scan_channels
;
2770 struct sk_buff
*scan
;
2771 struct cfg80211_scan_info info
= {.aborted
= true};
2773 SLSI_MUTEX_LOCK(ndev_vif
->scan_mutex
);
2775 if (ndev_vif
->scan
[SLSI_SCAN_HW_ID
].scan_req
) {
2776 SLSI_NET_DBG3(dev
, SLSI_MLME
, "stop on-going Scan\n");
2777 (void)slsi_mlme_del_scan(sdev
, dev
, ndev_vif
->ifnum
<< 8 | SLSI_SCAN_HW_ID
, false);
2778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2779 cfg80211_scan_done(ndev_vif
->scan
[SLSI_SCAN_HW_ID
].scan_req
, &info
);
2781 cfg80211_scan_done(ndev_vif
->scan
[SLSI_SCAN_HW_ID
].scan_req
, true);
2784 ndev_vif
->scan
[SLSI_SCAN_HW_ID
].scan_req
= NULL
;
2788 enum nl80211_band band
;
2789 struct wiphy
*wiphy
= sdev
->wiphy
;
2790 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2791 for (band
= 0; band
< NUM_NL80211_BANDS
; band
++) {
2793 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
2795 if (!wiphy
->bands
[band
])
2797 n_channels
+= wiphy
->bands
[band
]->n_channels
;
2800 WARN_ON(n_channels
== 0);
2801 scan_channels
= kmalloc_array((size_t)n_channels
, sizeof(*scan_channels
), GFP_KERNEL
);
2802 if (!scan_channels
) {
2803 SLSI_MUTEX_UNLOCK(ndev_vif
->scan_mutex
);
2807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
2808 for (band
= 0; band
< NUM_NL80211_BANDS
; band
++) {
2810 for (band
= 0; band
< IEEE80211_NUM_BANDS
; band
++) {
2814 if (!wiphy
->bands
[band
])
2816 for (j
= 0; j
< wiphy
->bands
[band
]->n_channels
; j
++)
2817 if (!(wiphy
->bands
[band
]->channels
[j
].flags
& IEEE80211_CHAN_DISABLED
)) {
2818 scan_channels
[n_channels
] = &wiphy
->bands
[band
]->channels
[j
];
2822 add_scan_channels
= scan_channels
;
2825 add_scan_channels
= &channel
;
2827 ndev_vif
->scan
[SLSI_SCAN_HW_ID
].is_blocking_scan
= true;
2828 r
= slsi_mlme_add_scan(sdev
,
2830 FAPI_SCANTYPE_FULL_SCAN
,
2831 FAPI_REPORTMODE_REAL_TIME
,
2837 ndev_vif
->probe_req_ies
,
2838 ndev_vif
->probe_req_ie_len
,
2839 ndev_vif
->scan
[SLSI_SCAN_HW_ID
].is_blocking_scan
);
2841 SLSI_MUTEX_LOCK(ndev_vif
->scan_result_mutex
);
2842 scan
= slsi_dequeue_cached_scan_result(&ndev_vif
->scan
[SLSI_SCAN_HW_ID
], NULL
);
2844 slsi_rx_scan_pass_to_cfg80211(sdev
, dev
, scan
);
2845 scan
= slsi_dequeue_cached_scan_result(&ndev_vif
->scan
[SLSI_SCAN_HW_ID
], NULL
);
2847 SLSI_MUTEX_UNLOCK(ndev_vif
->scan_result_mutex
);
2849 kfree(scan_channels
);
2850 ndev_vif
->scan
[SLSI_SCAN_HW_ID
].is_blocking_scan
= false;
2852 SLSI_MUTEX_UNLOCK(ndev_vif
->scan_mutex
);
2857 * The powermgt_lock mutex is to ensure atomic update of the power management state.
2859 DEFINE_MUTEX(powermgt_lock
);
2861 * The slsi_mlme_powermgt_unlocked() must be called from a context that is synchronised
2862 * with ndev_vif. if called without the ndev_vif mutex already taken, other mechanisms
2863 * must ensure that ndev_vif will exist for the duration of the function.
2865 int slsi_mlme_powermgt_unlocked(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 power_mode
)
2867 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2868 struct sk_buff
*req
;
2872 mutex_lock(&powermgt_lock
);
2874 if (WARN_ON(!ndev_vif
->activated
)) {
2875 mutex_unlock(&powermgt_lock
);
2879 if (ndev_vif
->power_mode
== power_mode
) {
2880 mutex_unlock(&powermgt_lock
);
2881 SLSI_NET_DBG3(dev
, SLSI_MLME
, "power management mode is same as requested. No changes done\n");
2885 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_powermgt_req(vif:%d, power_management_mode:%d)\n", ndev_vif
->ifnum
, power_mode
);
2886 req
= fapi_alloc(mlme_powermgt_req
, MLME_POWERMGT_REQ
, ndev_vif
->ifnum
, 0);
2888 mutex_unlock(&powermgt_lock
);
2891 fapi_set_u16(req
, u
.mlme_powermgt_req
.power_management_mode
, power_mode
);
2893 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_POWERMGT_CFM
);
2895 mutex_unlock(&powermgt_lock
);
2899 if (fapi_get_u16(rx
, u
.mlme_powermgt_cfm
.result_code
) == FAPI_RESULTCODE_SUCCESS
) {
2900 ndev_vif
->power_mode
= power_mode
;
2902 SLSI_NET_ERR(dev
, "mlme_powermgt_cfm(result:0x%04x) ERROR\n",
2903 fapi_get_u16(rx
, u
.mlme_powermgt_cfm
.result_code
));
2908 mutex_unlock(&powermgt_lock
);
2912 int slsi_mlme_powermgt(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 power_mode
)
2914 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2916 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2918 return slsi_mlme_powermgt_unlocked(sdev
, dev
, power_mode
);
2921 #ifdef CONFIG_SCSC_WLAN_SAE_CONFIG
2922 int slsi_mlme_synchronised_response(struct slsi_dev
*sdev
, struct net_device
*dev
,
2923 struct cfg80211_external_auth_params
*params
)
2925 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2926 struct sk_buff
*req
;
2927 struct sk_buff
*cfm
;
2928 if (ndev_vif
->activated
) {
2929 SLSI_NET_DBG3(dev
, SLSI_MLME
, "MLME_SYNCHRONISED_RES\n");
2931 req
= fapi_alloc(mlme_synchronised_res
, MLME_SYNCHRONISED_RES
, ndev_vif
->ifnum
, 0);
2935 fapi_set_u16(req
, u
.mlme_synchronised_res
.result_code
, params
->status
);
2936 fapi_set_memcpy(req
, u
.mlme_synchronised_res
.bssid
, params
->bssid
);
2938 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_synchronised_response(vif:%d) status:%d\n",
2939 ndev_vif
->ifnum
, params
->status
);
2940 cfm
= slsi_mlme_req_no_cfm(sdev
, dev
, req
);
2942 SLSI_NET_ERR(dev
, "Received cfm for MLME_SYNCHRONISED_RES\n");
2944 SLSI_NET_DBG1(dev
, SLSI_MLME
, "vif is not active");
2950 int slsi_mlme_register_action_frame(struct slsi_dev
*sdev
, struct net_device
*dev
, u32 af_bitmap_active
, u32 af_bitmap_suspended
)
2952 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2953 struct sk_buff
*req
;
2954 struct sk_buff
*cfm
;
2957 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2959 req
= fapi_alloc(mlme_register_action_frame_req
, MLME_REGISTER_ACTION_FRAME_REQ
, ndev_vif
->ifnum
, 0);
2963 fapi_set_u32(req
, u
.mlme_register_action_frame_req
.action_frame_category_bitmap_active
, af_bitmap_active
);
2964 fapi_set_u32(req
, u
.mlme_register_action_frame_req
.action_frame_category_bitmap_suspended
, af_bitmap_suspended
);
2966 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_register_action_frame(vif:%d, active:%d, suspended:%d)\n", ndev_vif
->ifnum
, af_bitmap_active
, af_bitmap_suspended
);
2967 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_REGISTER_ACTION_FRAME_CFM
);
2971 if (fapi_get_u16(cfm
, u
.mlme_register_action_frame_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
2972 SLSI_NET_ERR(dev
, "mlme_register_action_frame_cfm(result:0x%04x) ERROR\n",
2973 fapi_get_u16(cfm
, u
.mlme_register_action_frame_cfm
.result_code
));
2977 slsi_kfree_skb(cfm
);
2981 int slsi_mlme_channel_switch(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 center_freq
, u16 chan_info
)
2983 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
2984 struct sk_buff
*req
;
2985 struct sk_buff
*cfm
;
2988 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
2990 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_channel_switch_req(vif:%d, freq: %d, channel info: 0x%x)\n", ndev_vif
->ifnum
, center_freq
, chan_info
);
2991 req
= fapi_alloc(mlme_channel_switch_req
, MLME_CHANNEL_SWITCH_REQ
, ndev_vif
->ifnum
, 0);
2995 fapi_set_u16(req
, u
.mlme_channel_switch_req
.channel_frequency
, SLSI_FREQ_HOST_TO_FW(center_freq
));
2996 fapi_set_u16(req
, u
.mlme_channel_switch_req
.channel_information
, chan_info
);
2998 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_CHANNEL_SWITCH_CFM
);
3002 if (fapi_get_u16(cfm
, u
.mlme_channel_switch_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3003 SLSI_NET_ERR(dev
, "mlme_channel_switch_cfm(result:0x%04x) ERROR\n",
3004 fapi_get_u16(cfm
, u
.mlme_channel_switch_cfm
.result_code
));
3008 slsi_kfree_skb(cfm
);
3012 int slsi_mlme_add_info_elements(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 purpose
, const u8
*ies
, const u16 ies_len
)
3014 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3015 struct sk_buff
*req
;
3016 struct sk_buff
*cfm
;
3020 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3022 req
= fapi_alloc(mlme_add_info_elements_req
, MLME_ADD_INFO_ELEMENTS_REQ
, ndev_vif
->ifnum
, ies_len
);
3026 fapi_set_u16(req
, u
.mlme_add_info_elements_req
.purpose
, purpose
);
3029 p
= fapi_append_data(req
, ies
, ies_len
);
3031 slsi_kfree_skb(req
);
3036 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_add_info_elements_req(vif:%d, ies_len:%d)\n", ndev_vif
->ifnum
, ies_len
);
3037 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_ADD_INFO_ELEMENTS_CFM
);
3041 if (fapi_get_u16(cfm
, u
.mlme_add_info_elements_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3042 SLSI_NET_ERR(dev
, "mlme_add_info_elements_cfm(result:0x%04x) ERROR\n",
3043 fapi_get_u16(cfm
, u
.mlme_add_info_elements_cfm
.result_code
));
3047 slsi_kfree_skb(cfm
);
3051 int slsi_mlme_send_frame_data(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
, u16 msg_type
,
3052 u16 host_tag
, u32 dwell_time
, u32 period
)
3054 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3056 struct sk_buff
*original_skb
= 0;
3058 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3059 int is_enhanced_arp_request_frame
= 0;
3062 /* don't let ARP frames exhaust all the control slots */
3063 if (msg_type
== FAPI_MESSAGETYPE_ARP
) {
3066 free_slots
= hip4_free_ctrl_slots_count(&sdev
->hip4_inst
);
3068 if (free_slots
< 0) {
3069 SLSI_DBG1(sdev
, SLSI_MLME
, "drop ARP (error in getting free slot count)\n");
3073 if (free_slots
< SLSI_MLME_ARP_DROP_FREE_SLOTS_COUNT
) {
3074 SLSI_DBG1(sdev
, SLSI_MLME
, "drop ARP (running out of Control slots:%d)\n", free_slots
);
3075 slsi_kfree_skb(skb
);
3076 return NETDEV_TX_OK
;
3079 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3080 if (ndev_vif
->enhanced_arp_detect_enabled
&& (msg_type
== FAPI_MESSAGETYPE_ARP
)) {
3081 u8
*frame
= skb
->data
+ sizeof(struct ethhdr
);
3082 u16 arp_opcode
= frame
[SLSI_ARP_OPCODE_OFFSET
] << 8 | frame
[SLSI_ARP_OPCODE_OFFSET
+ 1];
3084 if ((arp_opcode
== SLSI_ARP_REQUEST_OPCODE
) &&
3085 !SLSI_IS_GRATUITOUS_ARP(frame
) &&
3086 !memcmp(&frame
[SLSI_ARP_DEST_IP_ADDR_OFFSET
], &ndev_vif
->target_ip_addr
, 4))
3087 is_enhanced_arp_request_frame
= 1;
3092 /* check for headroom to push signal header; if not available, re-alloc headroom */
3093 if (skb_headroom(skb
) < (fapi_sig_size(mlme_send_frame_req
))) {
3094 struct sk_buff
*skb2
= NULL
;
3096 skb2
= slsi_skb_realloc_headroom(skb
, fapi_sig_size(mlme_send_frame_req
));
3103 (void)skb_push(skb
, (fapi_sig_size(mlme_send_frame_req
)));
3105 /* fill the signal header */
3106 fapi_set_u16(skb
, id
, MLME_SEND_FRAME_REQ
);
3107 fapi_set_u16(skb
, receiver_pid
, 0);
3108 fapi_set_u16(skb
, sender_pid
, SLSI_TX_PROCESS_ID_MIN
);
3109 fapi_set_u16(skb
, fw_reference
, 0);
3111 /* fill in signal parameters */
3112 fapi_set_u16(skb
, u
.mlme_send_frame_req
.vif
, ndev_vif
->ifnum
);
3115 host_tag
= slsi_tx_mgmt_host_tag(sdev
);
3117 fapi_set_u16(skb
, u
.mlme_send_frame_req
.host_tag
, host_tag
);
3118 fapi_set_u16(skb
, u
.mlme_send_frame_req
.data_unit_descriptor
, FAPI_DATAUNITDESCRIPTOR_IEEE802_3_FRAME
);
3119 fapi_set_u16(skb
, u
.mlme_send_frame_req
.message_type
, msg_type
);
3120 fapi_set_u16(skb
, u
.mlme_send_frame_req
.channel_frequency
, 0);
3121 fapi_set_u32(skb
, u
.mlme_send_frame_req
.dwell_time
, dwell_time
);
3122 fapi_set_u32(skb
, u
.mlme_send_frame_req
.period
, period
);
3124 SLSI_DBG2(sdev
, SLSI_MLME
, "mlme_send_frame_req(vif:%d, message_type:%d, host_tag:%d)\n", ndev_vif
->ifnum
, msg_type
, host_tag
);
3125 /* slsi_tx_control frees the skb. Do not use it after this call. */
3126 ret
= slsi_tx_control(sdev
, dev
, skb
);
3128 SLSI_WARN(sdev
, "failed to send MLME signal(err=%d)\n", ret
);
3132 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
3133 if (is_enhanced_arp_request_frame
) {
3136 ndev_vif
->enhanced_arp_stats
.arp_req_count_to_lower_mac
++;
3137 for (i
= 0; i
< SLSI_MAX_ARP_SEND_FRAME
; i
++) {
3138 if (!ndev_vif
->enhanced_arp_host_tag
[i
]) {
3139 ndev_vif
->enhanced_arp_host_tag
[i
] = host_tag
;
3147 slsi_kfree_skb(original_skb
);
3149 /* as the frame is queued to HIP for transmission, store the host tag of the frames
3150 * to validate the transmission status in MLME-Frame-Transmission.indication.
3151 * Take necessary action based on the type of frame and status of it's transmission
3153 if (msg_type
== FAPI_MESSAGETYPE_EAPOL_KEY_M4
) {
3154 ndev_vif
->sta
.m4_host_tag
= host_tag
;
3155 SLSI_NET_DBG1(dev
, SLSI_MLME
, "EAPOL-Key M4 frame (host_tag:%d)\n", ndev_vif
->sta
.m4_host_tag
);
3156 } else if (msg_type
== FAPI_MESSAGETYPE_EAP_MESSAGE
) {
3157 if (!ndev_vif
->sta
.is_wps
&& (ndev_vif
->iftype
== NL80211_IFTYPE_STATION
)) {
3158 /* In case of non-P2P station and Enterprise security store the host_tag.
3159 * If transmission of such frame fails, inform supplicant to disconnect.
3161 ndev_vif
->sta
.eap_hosttag
= host_tag
;
3162 SLSI_NET_DBG1(dev
, SLSI_MLME
, "EAP frame (host_tag:%d)\n", ndev_vif
->sta
.eap_hosttag
);
3168 int slsi_mlme_send_frame_mgmt(struct slsi_dev
*sdev
, struct net_device
*dev
, const u8
*frame
, int frame_len
,
3169 u16 data_desc
, u16 msg_type
, u16 host_tag
, u16 freq
, u32 dwell_time
, u32 period
)
3171 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3172 struct sk_buff
*req
;
3173 struct sk_buff
*cfm
;
3177 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3179 req
= fapi_alloc(mlme_send_frame_req
, MLME_SEND_FRAME_REQ
, ndev_vif
->ifnum
, frame_len
);
3181 SLSI_WARN(sdev
, "failed to alloc memory\n");
3185 fapi_set_u16(req
, u
.mlme_send_frame_req
.host_tag
, host_tag
);
3186 fapi_set_u16(req
, u
.mlme_send_frame_req
.data_unit_descriptor
, data_desc
);
3187 fapi_set_u16(req
, u
.mlme_send_frame_req
.message_type
, msg_type
);
3188 fapi_set_u16(req
, u
.mlme_send_frame_req
.channel_frequency
, freq
);
3189 fapi_set_u32(req
, u
.mlme_send_frame_req
.dwell_time
, dwell_time
);
3190 fapi_set_u32(req
, u
.mlme_send_frame_req
.period
, period
);
3192 p
= fapi_append_data(req
, frame
, frame_len
);
3194 slsi_kfree_skb(req
);
3195 SLSI_WARN(sdev
, "failed to append data\n");
3199 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_send_frame_req(vif:%d, message_type:%d,host_tag:%d)\n", ndev_vif
->ifnum
, msg_type
, host_tag
);
3200 slsi_debug_frame(sdev
, dev
, req
, "TX");
3201 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SEND_FRAME_CFM
);
3205 if (fapi_get_u16(cfm
, u
.mlme_send_frame_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3206 SLSI_NET_ERR(dev
, "mlme_send_frame_cfm(result:0x%04x) ERROR\n",
3207 fapi_get_u16(cfm
, u
.mlme_send_frame_cfm
.result_code
));
3211 slsi_kfree_skb(cfm
);
3215 int slsi_mlme_reset_dwell_time(struct slsi_dev
*sdev
, struct net_device
*dev
)
3217 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3218 struct sk_buff
*req
;
3219 struct sk_buff
*cfm
;
3222 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3224 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_reset_dwell_time_req (vif:%d)\n", ndev_vif
->ifnum
);
3226 req
= fapi_alloc(mlme_reset_dwell_time_req
, MLME_RESET_DWELL_TIME_REQ
, ndev_vif
->ifnum
, 0);
3231 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_RESET_DWELL_TIME_CFM
);
3235 if (fapi_get_u16(cfm
, u
.mlme_reset_dwell_time_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3236 SLSI_NET_ERR(dev
, "mlme_reset_dwell_time_cfm(result:0x%04x) ERROR\n",
3237 fapi_get_u16(cfm
, u
.mlme_reset_dwell_time_cfm
.result_code
));
3241 slsi_kfree_skb(cfm
);
3245 int slsi_mlme_set_packet_filter(struct slsi_dev
*sdev
, struct net_device
*dev
,
3248 struct slsi_mlme_pkt_filter_elem
*pkt_filter_elems
)
3250 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3251 struct sk_buff
*req
;
3252 struct sk_buff
*cfm
;
3253 int r
= 0, i
= 0, j
= 0;
3257 if (WARN_ON(!ndev_vif
->activated
))
3260 if (WARN_ON(!num_filters
))
3263 req
= fapi_alloc(mlme_set_packet_filter_req
, MLME_SET_PACKET_FILTER_REQ
, ndev_vif
->ifnum
, pkt_filter_len
);
3267 p
= fapi_append_data(req
, NULL
, pkt_filter_len
);
3269 slsi_kfree_skb(req
);
3273 for (i
= 0; i
< num_filters
; i
++) {
3274 struct slsi_mlme_pkt_filter_elem pkt_filter_elem
= pkt_filter_elems
[i
];
3276 memcpy(&p
[index
], pkt_filter_elem
.header
, SLSI_PKT_FILTER_ELEM_HDR_LEN
);
3277 index
+= SLSI_PKT_FILTER_ELEM_HDR_LEN
;
3279 for (j
= 0; j
< pkt_filter_elem
.num_pattern_desc
; j
++) {
3280 p
[index
++] = pkt_filter_elem
.pattern_desc
[j
].offset
;
3281 p
[index
++] = pkt_filter_elem
.pattern_desc
[j
].mask_length
;
3282 memcpy(&p
[index
], pkt_filter_elem
.pattern_desc
[j
].mask
, pkt_filter_elem
.pattern_desc
[j
].mask_length
);
3283 index
+= pkt_filter_elem
.pattern_desc
[j
].mask_length
;
3284 memcpy(&p
[index
], pkt_filter_elem
.pattern_desc
[j
].pattern
, pkt_filter_elem
.pattern_desc
[j
].mask_length
);
3285 index
+= pkt_filter_elem
.pattern_desc
[j
].mask_length
;
3289 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_packet_filter_req(vif:%d, num_filters:%d)\n", ndev_vif
->ifnum
, num_filters
);
3290 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_PACKET_FILTER_CFM
);
3294 slsi_kfree_skb(cfm
);
3298 int slsi_mlme_set_pmk(struct slsi_dev
*sdev
, struct net_device
*dev
, const u8
*pmk
, u16 pmklen
)
3300 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3301 struct sk_buff
*req
;
3302 struct sk_buff
*cfm
;
3305 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3307 if (WARN_ON(!ndev_vif
->activated
))
3310 req
= fapi_alloc(mlme_set_pmk_req
, MLME_SET_PMK_REQ
, ndev_vif
->ifnum
, pmklen
);
3312 req
= fapi_alloc(mlme_set_pmk_req
, MLME_SET_PMK_REQ
, ndev_vif
->ifnum
, 0);
3317 fapi_append_data(req
, pmk
, pmklen
);
3319 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_pmk_req(vif:%u, pmklen:%d)\n", ndev_vif
->ifnum
, pmklen
);
3320 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_PMK_CFM
);
3324 if (fapi_get_u16(cfm
, u
.mlme_set_pmk_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3325 SLSI_NET_ERR(dev
, "mlme_set_pmk_cfm(result:0x%04x) ERROR\n",
3326 fapi_get_u16(cfm
, u
.mlme_set_pmk_cfm
.result_code
));
3329 slsi_kfree_skb(cfm
);
3333 int slsi_mlme_roam(struct slsi_dev
*sdev
, struct net_device
*dev
, const u8
*bssid
, u16 freq
)
3335 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3336 struct sk_buff
*req
;
3337 struct sk_buff
*cfm
;
3340 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3341 if (WARN_ON(!ndev_vif
->activated
))
3344 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_roam_req(vif:%u, bssid:%pM, freq:%d)\n", ndev_vif
->ifnum
, bssid
, freq
);
3345 req
= fapi_alloc(mlme_roam_req
, MLME_ROAM_REQ
, ndev_vif
->ifnum
, 0);
3348 fapi_set_memcpy(req
, u
.mlme_roam_req
.bssid
, bssid
);
3349 fapi_set_u16(req
, u
.mlme_roam_req
.channel_frequency
, SLSI_FREQ_HOST_TO_FW(freq
));
3350 atomic_set(&ndev_vif
->sta
.drop_roamed_ind
, 1);
3351 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_ROAM_CFM
);
3352 atomic_set(&ndev_vif
->sta
.drop_roamed_ind
, 0);
3355 if (fapi_get_u16(cfm
, u
.mlme_roam_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3356 SLSI_NET_ERR(dev
, "mlme_roam_cfm(result:0x%04x) ERROR\n",
3357 fapi_get_u16(cfm
, u
.mlme_roam_cfm
.result_code
));
3360 slsi_kfree_skb(cfm
);
3361 ndev_vif
->sta
.roam_in_progress
= true;
3365 int slsi_mlme_set_cached_channels(struct slsi_dev
*sdev
, struct net_device
*dev
, u32 channels_count
, u8
*channels
)
3367 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3368 struct sk_buff
*req
;
3369 struct sk_buff
*cfm
;
3372 size_t channel_ie
= 0;
3374 const u8 channels_list_ie_header
[] = {
3375 0xDD, /* Element ID: Vendor Specific */
3376 0x05, /* Length: actual length will be updated later */
3377 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
3378 0x01, /* OUI Type: Scan parameters */
3379 0x02 /* OUI Subtype: channel list */
3382 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3383 if (WARN_ON(!ndev_vif
->activated
))
3386 if (channels_count
) {
3387 channel_ie
+= 6 + (channels_count
* SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
3388 req
= fapi_alloc(mlme_set_cached_channels_req
, MLME_SET_CACHED_CHANNELS_REQ
, ndev_vif
->ifnum
, channel_ie
);
3390 req
= fapi_alloc(mlme_set_cached_channels_req
, MLME_SET_CACHED_CHANNELS_REQ
, ndev_vif
->ifnum
, 0);
3395 if (channels_count
) {
3397 u8
*channels_list_ie
= fapi_append_data(req
, channels_list_ie_header
, sizeof(channels_list_ie_header
));
3399 if (!channels_list_ie
) {
3400 SLSI_WARN(sdev
, "channel list IE append failed\n");
3401 slsi_kfree_skb(req
);
3405 for (i
= 0; i
< channels_count
; i
++) {
3406 SLSI_NET_DBG3(dev
, SLSI_MLME
, "request for channels %d\n", channels
[i
]);
3407 p
= fapi_append_data(req
, NULL
, SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
);
3409 slsi_kfree_skb(req
);
3412 freq_fw_unit
= 2 * ieee80211_channel_to_frequency(channels
[i
], (channels
[i
] <= 14) ? NL80211_BAND_2GHZ
: NL80211_BAND_5GHZ
);
3413 freq_fw_unit
= cpu_to_le16(freq_fw_unit
);
3414 memcpy(p
, &freq_fw_unit
, sizeof(freq_fw_unit
));
3416 p
[2] = FAPI_SCANPOLICY_2_4GHZ
| FAPI_SCANPOLICY_5GHZ
;
3418 channels_list_ie
[1] += SLSI_SCAN_CHANNEL_DESCRIPTOR_SIZE
;
3422 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_cached_channels_req(vif:%d)\n", ndev_vif
->ifnum
);
3423 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_CACHED_CHANNELS_CFM
);
3427 if (fapi_get_u16(cfm
, u
.mlme_set_cached_channels_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3428 SLSI_NET_ERR(dev
, "mlme_set_cached_channels_cfm(result:0x%04x) ERROR\n",
3429 fapi_get_u16(cfm
, u
.mlme_set_cached_channels_cfm
.result_code
));
3433 slsi_kfree_skb(cfm
);
3437 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 9))
3438 int slsi_mlme_set_acl(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 ifnum
, const struct cfg80211_acl_data
*params
)
3440 struct sk_buff
*req
;
3441 struct sk_buff
*cfm
;
3442 size_t mac_acl_size
= 0;
3445 mac_acl_size
= sizeof((params
->mac_addrs
[0])) * (params
->n_acl_entries
);
3446 req
= fapi_alloc(mlme_set_acl_req
, MLME_SET_ACL_REQ
, ifnum
, mac_acl_size
);
3448 SLSI_NET_ERR(dev
, "fapi alloc failure\n");
3451 fapi_set_u16(req
, u
.mlme_set_acl_req
.entries
, params
->n_acl_entries
);
3452 fapi_set_u16(req
, u
.mlme_set_acl_req
.acl_policy
, params
->acl_policy
);
3454 for (i
= 0; i
< params
->n_acl_entries
; i
++)
3455 fapi_append_data(req
, params
->mac_addrs
[i
].addr
, sizeof((params
->mac_addrs
[i
])));
3457 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_acl_req(vif:%u, n_acl_entries:%d)\n", ifnum
, params
->n_acl_entries
);
3460 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_ACL_CFM
);
3462 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_SET_ACL_CFM
);
3466 if (fapi_get_u16(cfm
, u
.mlme_set_acl_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3467 SLSI_NET_ERR(dev
, "mlme_set_acl_cfm(result:0x%04x) ERROR\n",
3468 fapi_get_u16(cfm
, u
.mlme_set_acl_cfm
.result_code
));
3472 slsi_kfree_skb(cfm
);
3477 int slsi_mlme_set_traffic_parameters(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 user_priority
, u16 medium_time
, u16 minimun_data_rate
, u8
*mac
)
3479 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3480 struct sk_buff
*req
;
3484 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3486 if (WARN_ON(!ndev_vif
->activated
))
3489 if (WARN_ON(ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
&& ndev_vif
->iftype
== NL80211_IFTYPE_STATION
))
3492 req
= fapi_alloc(mlme_set_traffic_parameters_req
, MLME_SET_TRAFFIC_PARAMETERS_REQ
, ndev_vif
->ifnum
, 0);
3496 fapi_set_u16(req
, u
.mlme_set_traffic_parameters_req
.user_priority
, user_priority
);
3497 fapi_set_u16(req
, u
.mlme_set_traffic_parameters_req
.medium_time
, medium_time
);
3498 fapi_set_u16(req
, u
.mlme_set_traffic_parameters_req
.minimum_data_rate
, minimun_data_rate
);
3501 fapi_set_memcpy(req
, u
.mlme_set_traffic_parameters_req
.peer_address
, mac
);
3503 fapi_set_memset(req
, u
.mlme_set_traffic_parameters_req
.peer_address
, 0);
3505 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_set_traffic_parameters_req(vif:%u, user_priority:%d, medium_time:%d)\n", ndev_vif
->ifnum
, user_priority
, medium_time
);
3506 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_TRAFFIC_PARAMETERS_CFM
);
3510 if (fapi_get_u16(rx
, u
.mlme_set_traffic_parameters_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3511 SLSI_NET_ERR(dev
, "mlme_set_traffic_parameters_cfm(result:0x%04x) ERROR\n",
3512 fapi_get_u16(rx
, u
.mlme_set_traffic_parameters_cfm
.result_code
));
3519 int slsi_mlme_del_traffic_parameters(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 user_priority
)
3521 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3522 struct sk_buff
*req
;
3526 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3528 if (WARN_ON(!ndev_vif
->activated
))
3531 if (WARN_ON(ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
&& ndev_vif
->iftype
== NL80211_IFTYPE_STATION
))
3534 req
= fapi_alloc(mlme_del_traffic_parameters_req
, MLME_DEL_TRAFFIC_PARAMETERS_REQ
, ndev_vif
->ifnum
, 0);
3538 fapi_set_u16(req
, u
.mlme_del_traffic_parameters_req
.user_priority
, user_priority
);
3540 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_del_traffic_parameters_req(vif:%u, user_priority:%d)\n", ndev_vif
->ifnum
, user_priority
);
3541 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_DEL_TRAFFIC_PARAMETERS_CFM
);
3545 if (fapi_get_u16(rx
, u
.mlme_del_traffic_parameters_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3546 SLSI_NET_ERR(dev
, "mlme_del_traffic_parameters_cfm(result:0x%04x) ERROR\n",
3547 fapi_get_u16(rx
, u
.mlme_del_traffic_parameters_cfm
.result_code
));
3554 int slsi_mlme_set_ext_capab(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_mib_value
*mib_val
)
3556 struct slsi_mib_data mib_data
= { 0, NULL
};
3559 error
= slsi_mib_encode_octet(&mib_data
, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES
, mib_val
->u
.octetValue
.dataLength
, mib_val
->u
.octetValue
.data
, 0);
3560 if (error
!= SLSI_MIB_STATUS_SUCCESS
) {
3565 if (WARN_ON(mib_data
.dataLength
== 0)) {
3570 error
= slsi_mlme_set(sdev
, NULL
, mib_data
.data
, mib_data
.dataLength
);
3571 kfree(mib_data
.data
);
3577 SLSI_ERR(sdev
, "Error in setting ext capab. error = %d\n", error
);
3581 int slsi_mlme_set_hs2_ext_cap(struct slsi_dev
*sdev
, struct net_device
*dev
, const u8
*ies
, int ie_len
)
3583 struct slsi_mib_entry mib_entry
;
3584 struct slsi_mib_data mibreq
= { 0, NULL
};
3585 struct slsi_mib_data mibrsp
= { 0, NULL
};
3586 const u8
*ext_capab_ie
;
3591 slsi_mib_encode_get(&mibreq
, SLSI_PSID_UNIFI_EXTENDED_CAPABILITIES
, 0);
3593 /* 5 (header) + 9 (data) + 2 (mlme expects 16 (??))*/
3594 mibrsp
.dataLength
= 16;
3595 mibrsp
.data
= kmalloc(mibrsp
.dataLength
, GFP_KERNEL
);
3598 SLSI_ERR(sdev
, "Failed to alloc for Mib response\n");
3603 r
= slsi_mlme_get(sdev
, NULL
, mibreq
.data
, mibreq
.dataLength
,
3604 mibrsp
.data
, mibrsp
.dataLength
, &rx_length
);
3608 mibrsp
.dataLength
= rx_length
;
3609 len
= slsi_mib_decode(&mibrsp
, &mib_entry
);
3611 SLSI_ERR(sdev
, "Mib decode error\n");
3616 SLSI_NET_DBG1(dev
, SLSI_MLME
, "Mib read failed (error: %d)\n", r
);
3620 ext_capab_ie
= cfg80211_find_ie(WLAN_EID_EXT_CAPABILITY
, ies
, ie_len
);
3623 u8 ext_capab_ie_len
= ext_capab_ie
[1];
3625 ext_capab_ie
+= 2; /* skip the EID and length*/
3627 /*BSS Transition bit is bit 19 ,ie length must be >= 3 */
3628 if ((ext_capab_ie_len
>= 3) && (ext_capab_ie
[2] & SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED
))
3629 mib_entry
.value
.u
.octetValue
.data
[2] |= SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED
;
3631 mib_entry
.value
.u
.octetValue
.data
[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED
;
3633 /*interworking bit is bit 31 ,ie length must be >= 4 */
3634 if ((ext_capab_ie_len
>= 4) && (ext_capab_ie
[3] & SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED
))
3635 mib_entry
.value
.u
.octetValue
.data
[3] |= SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED
;
3637 mib_entry
.value
.u
.octetValue
.data
[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED
;
3639 /*QoS MAP is bit 32 ,ie length must be >= 5 */
3640 if ((ext_capab_ie_len
>= 5) && (ext_capab_ie
[4] & SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED
))
3641 mib_entry
.value
.u
.octetValue
.data
[4] |= SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED
;
3643 mib_entry
.value
.u
.octetValue
.data
[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED
;
3645 /*WNM- Notification bit is bit 46 ,ie length must be >= 6 */
3646 if ((ext_capab_ie_len
>= 6) && (ext_capab_ie
[5] & SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED
))
3647 mib_entry
.value
.u
.octetValue
.data
[5] |= SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED
;
3649 mib_entry
.value
.u
.octetValue
.data
[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED
;
3651 mib_entry
.value
.u
.octetValue
.data
[2] &= ~SLSI_WLAN_EXT_CAPA2_BSS_TRANSISITION_ENABLED
;
3652 mib_entry
.value
.u
.octetValue
.data
[3] &= ~SLSI_WLAN_EXT_CAPA3_INTERWORKING_ENABLED
;
3653 mib_entry
.value
.u
.octetValue
.data
[4] &= ~SLSI_WLAN_EXT_CAPA4_QOS_MAP_ENABLED
;
3654 mib_entry
.value
.u
.octetValue
.data
[5] &= ~SLSI_WLAN_EXT_CAPA5_WNM_NOTIF_ENABLED
;
3657 r
= slsi_mlme_set_ext_capab(sdev
, dev
, &mib_entry
.value
);
3663 int slsi_mlme_tdls_peer_resp(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 pid
, u16 tdls_event
)
3665 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3666 struct sk_buff
*req
;
3667 struct sk_buff
*cfm
;
3669 req
= fapi_alloc(mlme_tdls_peer_res
, MLME_TDLS_PEER_RES
, ndev_vif
->ifnum
, 0);
3673 fapi_set_u16(req
, u
.mlme_tdls_peer_res
.peer_index
, pid
);
3674 fapi_set_u16(req
, u
.mlme_tdls_peer_res
.tdls_event
, tdls_event
);
3676 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_tdls_peer_res(vif:%d)\n", ndev_vif
->ifnum
);
3677 cfm
= slsi_mlme_req_no_cfm(sdev
, dev
, req
);
3683 int slsi_mlme_tdls_action(struct slsi_dev
*sdev
, struct net_device
*dev
, const u8
*peer
, int action
, u16 center_freq
, u16 chan_info
)
3685 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3686 struct sk_buff
*req
;
3687 struct sk_buff
*cfm
;
3690 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_tdls_action_req(action:%u)\n", action
);
3691 req
= fapi_alloc(mlme_tdls_action_req
, MLME_TDLS_ACTION_REQ
, ndev_vif
->ifnum
, 0);
3695 center_freq
= SLSI_FREQ_HOST_TO_FW(center_freq
);
3697 fapi_set_memcpy(req
, u
.mlme_tdls_action_req
.peer_sta_address
, peer
);
3698 fapi_set_u16(req
, u
.mlme_tdls_action_req
.tdls_action
, action
);
3699 fapi_set_u16(req
, u
.mlme_tdls_action_req
.channel_frequency
, center_freq
);
3700 fapi_set_u16(req
, u
.mlme_tdls_action_req
.channel_information
, chan_info
);
3702 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_TDLS_ACTION_CFM
);
3706 if (fapi_get_u16(cfm
, u
.mlme_tdls_action_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3707 SLSI_NET_ERR(dev
, "mlme_tdls_action_cfm(result:0x%04x) ERROR\n",
3708 fapi_get_u16(cfm
, u
.mlme_tdls_action_cfm
.result_code
));
3712 slsi_kfree_skb(cfm
);
3717 int slsi_mlme_reassociate(struct slsi_dev
*sdev
, struct net_device
*dev
)
3719 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3720 struct sk_buff
*req
;
3721 struct sk_buff
*cfm
;
3724 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
3725 if (WARN_ON(!ndev_vif
->activated
))
3728 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_reassoc_req(vif:%u)\n", ndev_vif
->ifnum
);
3729 req
= fapi_alloc(mlme_reassociate_req
, MLME_REASSOCIATE_REQ
, ndev_vif
->ifnum
, 0);
3733 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_REASSOCIATE_CFM
);
3737 if (fapi_get_u16(cfm
, u
.mlme_reassociate_cfm
.result_code
) == FAPI_RESULTCODE_HOST_REQUEST_SUCCESS
) {
3738 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_reassoc_cfm(result:0x%04x)\n",
3739 fapi_get_u16(cfm
, u
.mlme_reassociate_cfm
.result_code
));
3741 SLSI_NET_ERR(dev
, "mlme_reassoc_cfm(result:0x%04x) ERROR\n",
3742 fapi_get_u16(cfm
, u
.mlme_reassociate_cfm
.result_code
));
3745 slsi_kfree_skb(cfm
);
3749 void slsi_mlme_reassociate_resp(struct slsi_dev
*sdev
, struct net_device
*dev
)
3751 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
3752 struct sk_buff
*req
;
3753 struct sk_buff
*cfm
;
3755 if (slsi_is_test_mode_enabled()) {
3756 SLSI_NET_INFO(dev
, "Skip sending signal, WlanLite FW does not support MLME_REASSOCIATE_RESP\n");
3760 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_reassociate_resp(vif:%d)\n", ndev_vif
->ifnum
);
3761 req
= fapi_alloc(mlme_reassociate_res
, MLME_REASSOCIATE_RES
, ndev_vif
->ifnum
, 0);
3765 cfm
= slsi_mlme_req_no_cfm(sdev
, dev
, req
);
3769 int slsi_mlme_add_range_req(struct slsi_dev
*sdev
, u8 count
,
3770 struct slsi_rtt_config
*nl_rtt_params
, u16 rtt_id
, u16 vif_idx
, u8
*source_addr
)
3772 struct sk_buff
*req
;
3775 size_t alloc_data_size
= 0;
3776 u8 fapi_ie_generic
[] = { 0xdd, 0x1c, 0x00, 0x16, 0x32, 0x0a, 0x01 };
3777 /* calculate data size */
3778 alloc_data_size
+= count
* (fapi_ie_generic
[1] + 2);
3780 req
= fapi_alloc(mlme_add_range_req
, MLME_ADD_RANGE_REQ
, 0, alloc_data_size
);
3782 SLSI_ERR(sdev
, "failed to alloc %zd\n", alloc_data_size
);
3785 SLSI_DBG2(sdev
, SLSI_MLME
, "count:%d allocated data size: %d, source_addr:%pM\n",
3786 count
, alloc_data_size
, source_addr
);
3788 fapi_set_u16(req
, u
.mlme_add_range_req
.vif
, vif_idx
);
3789 fapi_set_u16(req
, u
.mlme_add_range_req
.rtt_id
, rtt_id
);
3790 fapi_set_memcpy(req
, u
.mlme_add_range_req
.device_address
, source_addr
);
3791 for (i
= 0; i
< count
; i
++) {
3792 fapi_append_data(req
, fapi_ie_generic
, sizeof(fapi_ie_generic
));
3793 fapi_append_data(req
, nl_rtt_params
[i
].peer_addr
, ETH_ALEN
);
3794 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].type
, 2);
3795 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].channel_freq
, 2);
3796 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].burst_period
, 1);
3797 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].num_burst
, 1);
3798 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].num_frames_per_burst
, 1);
3799 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].num_retries_per_ftmr
, 1);
3800 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].burst_duration
, 1);
3801 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].preamble
, 2);
3802 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].bw
, 2);
3803 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].LCI_request
, 2);
3804 fapi_append_data(req
, (u8
*)&nl_rtt_params
[i
].LCR_request
, 2);
3806 rx
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_ADD_RANGE_CFM
);
3807 SLSI_DBG2(sdev
, SLSI_MLME
, "(After mlme req cfm for rtt config)\n");
3810 if (fapi_get_u16(rx
, u
.mlme_add_range_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3811 SLSI_ERR(sdev
, "mlme_add_range_cfm(ERROR:0x%04x)",
3812 fapi_get_u16(rx
, u
.mlme_add_range_cfm
.result_code
));
3820 bool slsi_del_range_cfm_validate(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*cfm
)
3822 int result
= fapi_get_u16(cfm
, u
.mlme_del_range_cfm
.result_code
);
3825 SLSI_UNUSED_PARAMETER(sdev
);
3830 if (result
== FAPI_RESULTCODE_SUCCESS
)
3833 SLSI_NET_ERR(dev
, "mlme_del_range_cfm(result:0x%04x) ERROR\n", result
);
3836 slsi_kfree_skb(cfm
);
3840 int slsi_mlme_del_range_req(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 count
,
3841 u8
*addr
, u16 rtt_id
)
3843 struct sk_buff
*req
;
3845 u16
*rtt_vif_idx
= sdev
->rtt_vif
;
3847 size_t alloc_data_size
= 0;
3849 /* calculate data size-->2 bytes for vif */
3850 alloc_data_size
+= count
* sizeof(ETH_ALEN
);
3851 /* Alloc data size */
3852 req
= fapi_alloc(mlme_del_range_req
, MLME_DEL_RANGE_REQ
, 0, alloc_data_size
);
3854 SLSI_ERR(sdev
, "failed to alloc %zd\n", alloc_data_size
);
3858 fapi_set_u16(req
, u
.mlme_del_range_req
.vif
, rtt_vif_idx
[rtt_id
]);
3859 fapi_set_u16(req
, u
.mlme_del_range_req
.rtt_id
, rtt_id
);
3860 fapi_set_u16(req
, u
.mlme_del_range_req
.entries
, count
);
3861 for (i
= 0; i
< count
; i
++)
3862 fapi_append_data(req
, &addr
[i
* ETH_ALEN
], ETH_ALEN
);
3864 rx
= slsi_mlme_req_cfm_ind(sdev
, dev
, req
, MLME_DEL_RANGE_CFM
, MLME_RANGE_IND
, slsi_del_range_cfm_validate
);
3865 sdev
->rtt_vif
[rtt_id
] = -1;
3867 SLSI_NET_ERR(dev
, "mlme_del_range_cfm() ERROR\n");
3875 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
3876 #define SLSI_FAPI_EPNO_NETWORK_MIN_SIZE (3)
3877 int slsi_mlme_set_pno_list(struct slsi_dev
*sdev
, int count
,
3878 struct slsi_epno_param
*epno_param
, struct slsi_epno_hs2_param
*epno_hs2_param
)
3880 struct sk_buff
*req
;
3883 size_t alloc_data_size
= 0;
3885 u8 fapi_ie_generic
[] = { 0xdd, 0, 0x00, 0x16, 0x32, 0x01, 0x00 };
3886 u8
*buff_ptr
, *ie_start_pos
;
3889 /* calculate data size */
3891 alloc_data_size
+= sizeof(fapi_ie_generic
) + SLSI_FAPI_EPNO_NETWORK_MIN_SIZE
* count
+ 11;
3892 for (i
= 0; i
< count
; i
++)
3893 alloc_data_size
+= epno_param
->epno_ssid
[i
].ssid_len
;
3894 } else if (epno_hs2_param
) {
3895 for (i
= 0; i
< count
; i
++) {
3896 /* fapi_ie_generic + Network_block_ID(1) + Realm_length(1) + realm_data(x)
3897 * + Roaming_Consortium_Count(1) + Roaming Consortium data(16 * 8) +
3898 * PLMN length(1) + PLMN data(6)
3900 if (strlen(epno_hs2_param
->realm
))
3901 alloc_data_size
+= sizeof(fapi_ie_generic
) + 1 + 1 + (strlen(epno_hs2_param
->realm
) + 1)
3902 + 1 + 16 * 8 + 1 + 6;
3904 alloc_data_size
+= sizeof(fapi_ie_generic
) + 1 + 1 + 0
3905 + 1 + 16 * 8 + 1 + 6;
3910 /* Alloc data size */
3911 req
= fapi_alloc(mlme_set_pno_list_req
, MLME_SET_PNO_LIST_REQ
, 0, alloc_data_size
);
3913 SLSI_ERR(sdev
, "failed to alloc %zd\n", alloc_data_size
);
3919 fapi_ie_generic
[1] = alloc_data_size
- 2;
3920 fapi_ie_generic
[6] = 9; /* OUI */
3921 fapi_append_data(req
, fapi_ie_generic
, sizeof(fapi_ie_generic
));
3922 fapi_append_data(req
, (u8
*)epno_param
, (sizeof(*epno_param
) - 1));
3923 for (i
= 0; i
< count
; i
++) {
3924 fapi_append_data(req
, (u8
*)&epno_param
->epno_ssid
[i
].flags
, 2);
3925 fapi_append_data(req
, (u8
*)&epno_param
->epno_ssid
[i
].ssid_len
, 1);
3926 fapi_append_data(req
, (u8
*)epno_param
->epno_ssid
[i
].ssid
,
3927 epno_param
->epno_ssid
[i
].ssid_len
);
3929 } else if (epno_hs2_param
) {
3931 u8 roaming_consortium_count
= 16;
3935 fapi_ie_generic
[6] = 0x10; /* OUI subtype = Passpoint Network */
3936 for (i
= 0; i
< count
; i
++) {
3937 buff_ptr
= fapi_append_data(req
, fapi_ie_generic
, sizeof(fapi_ie_generic
));
3939 SLSI_ERR(sdev
, "failed append data\n");
3940 slsi_kfree_skb(req
);
3943 ie_start_pos
= buff_ptr
;
3945 fapi_append_data(req
, (u8
*)&epno_hs2_param
[i
].id
, 1);
3947 realm_length
= strlen(epno_hs2_param
[i
].realm
);
3950 fapi_append_data(req
, &realm_length
, 1);
3951 fapi_append_data(req
, epno_hs2_param
[i
].realm
, realm_length
);
3953 fapi_append_data(req
, &realm_length
, 1);
3956 fapi_append_data(req
, &roaming_consortium_count
, 1);
3957 fapi_append_data(req
, (u8
*)&epno_hs2_param
[i
].roaming_consortium_ids
, 16 * 8);
3959 fapi_append_data(req
, &plmn_length
, 1);
3960 for (j
= 0; j
< 3; j
++) {
3961 plmn_digit
[j
* 2] = epno_hs2_param
[i
].plmn
[i
] & 0x0F;
3962 plmn_digit
[(j
* 2) + 1] = epno_hs2_param
[i
].plmn
[i
] & 0xF0 >> 4;
3964 buff_ptr
= fapi_append_data(req
, plmn_digit
, sizeof(plmn_digit
));
3966 SLSI_ERR(sdev
, "failed append data\n");
3967 slsi_kfree_skb(req
);
3971 buff_ptr
+= sizeof(plmn_digit
);
3972 ie_start_pos
[1] = buff_ptr
- ie_start_pos
- 2; /* fill ie length field */
3978 /* Use the Global sig_wait not the Interface specific for mlme-set-pno.list */
3979 rx
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_SET_PNO_LIST_CFM
);
3982 if (fapi_get_u16(rx
, u
.mlme_set_pno_list_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
3983 SLSI_ERR(sdev
, "mlme_set_pno_list_cfm(ERROR:0x%04x)",
3984 fapi_get_u16(rx
, u
.mlme_set_pno_list_cfm
.result_code
));
3991 int slsi_mlme_start_link_stats_req(struct slsi_dev
*sdev
, u16 mpdu_size_threshold
, bool aggressive_stats_enabled
)
3993 struct sk_buff
*req
;
3994 struct sk_buff
*cfm
;
3997 req
= fapi_alloc(mlme_start_link_statistics_req
, MLME_START_LINK_STATISTICS_REQ
, 0, 0);
3999 SLSI_ERR(sdev
, "memory allocation failed for signal\n");
4003 fapi_set_u16(req
, u
.mlme_start_link_statistics_req
.mpdu_size_threshold
, mpdu_size_threshold
);
4004 fapi_set_u16(req
, u
.mlme_start_link_statistics_req
.aggressive_statistics_gathering_enabled
,
4005 aggressive_stats_enabled
);
4007 SLSI_DBG2(sdev
, SLSI_MLME
, "(mpdu_size_threshold:%d, aggressive_stats_enabled:%d)\n",
4008 mpdu_size_threshold
, aggressive_stats_enabled
);
4009 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_START_LINK_STATISTICS_CFM
);
4013 if (fapi_get_u16(cfm
, u
.mlme_start_link_statistics_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4014 SLSI_ERR(sdev
, "mlme_start_link_statistics_cfm (result:0x%04x) ERROR\n",
4015 fapi_get_u16(cfm
, u
.mlme_start_link_statistics_cfm
.result_code
));
4019 slsi_kfree_skb(cfm
);
4023 int slsi_mlme_stop_link_stats_req(struct slsi_dev
*sdev
, u16 stats_stop_mask
)
4025 struct sk_buff
*req
;
4026 struct sk_buff
*cfm
;
4029 req
= fapi_alloc(mlme_stop_link_statistics_req
, MLME_STOP_LINK_STATISTICS_REQ
, 0, 0);
4031 SLSI_ERR(sdev
, "memory allocation failed for signal\n");
4035 fapi_set_u16(req
, u
.mlme_stop_link_statistics_req
.statistics_stop_bitmap
, stats_stop_mask
);
4037 SLSI_DBG2(sdev
, SLSI_MLME
, "statistics_stop_bitmap:%d\n", stats_stop_mask
);
4038 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_STOP_LINK_STATISTICS_CFM
);
4042 if (fapi_get_u16(cfm
, u
.mlme_stop_link_statistics_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4043 SLSI_ERR(sdev
, "mlme_stop_link_statistics_cfm (result:0x%04x) ERROR\n",
4044 fapi_get_u16(cfm
, u
.mlme_stop_link_statistics_cfm
.result_code
));
4047 slsi_kfree_skb(cfm
);
4052 int slsi_mlme_set_rssi_monitor(struct slsi_dev
*sdev
, struct net_device
*dev
, u8 enable
, s8 low_rssi_threshold
, s8 high_rssi_threshold
)
4054 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
4055 struct sk_buff
*req
;
4056 struct sk_buff
*cfm
;
4059 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_set_rssi_monitor(vif:%u), enable =%d, low_rssi_threshold = %d,high_rssi_threshold =%d\n",
4060 ndev_vif
->ifnum
, enable
, low_rssi_threshold
, high_rssi_threshold
);
4062 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
4063 req
= fapi_alloc(mlme_monitor_rssi_req
, MLME_MONITOR_RSSI_REQ
, ndev_vif
->ifnum
, 0);
4065 SLSI_NET_ERR(dev
, "fapi alloc failure\n");
4069 fapi_set_u16(req
, u
.mlme_monitor_rssi_req
.rssi_monitoring_enabled
, enable
);
4070 fapi_set_u16(req
, u
.mlme_monitor_rssi_req
.low_rssi_threshold
, low_rssi_threshold
);
4071 fapi_set_u16(req
, u
.mlme_monitor_rssi_req
.high_rssi_threshold
, high_rssi_threshold
);
4073 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_MONITOR_RSSI_CFM
);
4077 if (fapi_get_u16(cfm
, u
.mlme_monitor_rssi_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4078 SLSI_NET_ERR(dev
, "mlme_monitor_rssi_cfm(result:0x%04x) ERROR\n", fapi_get_u16(cfm
, u
.mlme_monitor_rssi_cfm
.result_code
));
4082 slsi_kfree_skb(cfm
);
4086 struct slsi_mib_value
*slsi_read_mibs(struct slsi_dev
*sdev
, struct net_device
*dev
,
4087 struct slsi_mib_get_entry
*mib_entries
, int mib_count
, struct slsi_mib_data
*mibrsp
)
4089 struct slsi_mib_data mibreq
= { 0, NULL
};
4090 struct slsi_mib_value
*values
;
4093 r
= slsi_mib_encode_get_list(&mibreq
, mib_count
, mib_entries
);
4094 if (r
!= SLSI_MIB_STATUS_SUCCESS
) {
4095 SLSI_WARN(sdev
, "slsi_mib_encode_get_list fail %d\n", r
);
4099 r
= slsi_mlme_get(sdev
, dev
, mibreq
.data
, mibreq
.dataLength
, mibrsp
->data
, mibrsp
->dataLength
, &rx_length
);
4103 SLSI_ERR(sdev
, "Mib (err:%d)\n", r
);
4107 mibrsp
->dataLength
= (u32
)rx_length
;
4108 values
= slsi_mib_decode_get_list(mibrsp
, mib_count
, mib_entries
);
4110 SLSI_WARN(sdev
, "decode error\n");
4114 int slsi_mlme_set_ctwindow(struct slsi_dev
*sdev
, struct net_device
*dev
, unsigned int ct_param
)
4116 struct netdev_vif
*ndev_vif
;
4117 struct sk_buff
*req
;
4118 struct sk_buff
*cfm
;
4121 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_set_ctwindow(ct_param = %d)\n", ct_param
);
4123 ndev_vif
= netdev_priv(dev
);
4125 req
= fapi_alloc(mlme_set_ctwindow_req
, MLME_SET_CTWINDOW_REQ
, ndev_vif
->ifnum
, 0);
4129 fapi_set_u16(req
, u
.mlme_set_ctwindow_req
.ctwindow
, ct_param
);
4131 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_CTWINDOW_CFM
);
4135 if (fapi_get_u16(cfm
, u
.mlme_set_ctwindow_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4136 SLSI_NET_ERR(dev
, "mlme_set_ctwindow_cfm(result:0x%04x) ERROR\n",
4137 fapi_get_u16(cfm
, u
.mlme_set_ctwindow_cfm
.result_code
));
4140 slsi_kfree_skb(cfm
);
4144 int slsi_mlme_set_p2p_noa(struct slsi_dev
*sdev
, struct net_device
*dev
, unsigned int noa_count
,
4145 unsigned int interval
, unsigned int duration
)
4147 struct netdev_vif
*ndev_vif
;
4148 struct sk_buff
*req
;
4149 struct sk_buff
*cfm
;
4152 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_set_noa_req(noa_count = %d, interval = %d, duration = %d)\n",
4153 noa_count
, interval
, duration
);
4155 ndev_vif
= netdev_priv(dev
);
4157 req
= fapi_alloc(mlme_set_noa_req
, MLME_SET_NOA_REQ
, ndev_vif
->ifnum
, 0);
4161 fapi_set_u16(req
, u
.mlme_set_noa_req
.request_id
, SLSI_NOA_CONFIG_REQUEST_ID
);
4162 fapi_set_u16(req
, u
.mlme_set_noa_req
.noa_count
, noa_count
);
4164 fapi_set_u32(req
, u
.mlme_set_noa_req
.interval
, (1 * 1024 * ndev_vif
->ap
.beacon_interval
));
4166 fapi_set_u32(req
, u
.mlme_set_noa_req
.interval
, interval
* 1000);
4167 fapi_set_u32(req
, u
.mlme_set_noa_req
.duration
, duration
* 1000);
4169 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_SET_NOA_CFM
);
4173 if (fapi_get_u16(cfm
, u
.mlme_set_noa_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4174 SLSI_NET_ERR(dev
, "mlme_set_noa_cfm(result:0x%04x) ERROR\n",
4175 fapi_get_u16(cfm
, u
.mlme_set_noa_cfm
.result_code
));
4178 slsi_kfree_skb(cfm
);
4182 int slsi_mlme_set_host_state(struct slsi_dev
*sdev
, struct net_device
*dev
, u8 host_state
)
4184 struct sk_buff
*req
;
4185 struct sk_buff
*cfm
;
4188 if (slsi_is_test_mode_enabled()) {
4189 SLSI_NET_INFO(dev
, "Skip MLME_HOST_STATE_REQ in wlanlite mode\n");
4193 SLSI_NET_DBG1(dev
, SLSI_MLME
, "mlme_set_host_state(state =%d)\n", host_state
);
4195 req
= fapi_alloc(mlme_host_state_req
, MLME_HOST_STATE_REQ
, 0, 0);
4197 SLSI_NET_ERR(dev
, "fapi alloc failure\n");
4201 fapi_set_u16(req
, u
.mlme_host_state_req
.host_state
, host_state
);
4203 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_HOST_STATE_CFM
);
4207 if (fapi_get_u16(cfm
, u
.mlme_host_state_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4208 SLSI_NET_ERR(dev
, "mlme_host_state_cfm(result:0x%04x) ERROR\n",
4209 fapi_get_u16(cfm
, u
.mlme_host_state_cfm
.result_code
));
4213 slsi_kfree_skb(cfm
);
4217 int slsi_mlme_read_apf_request(struct slsi_dev
*sdev
, struct net_device
*dev
, u8
**host_dst
, int *datalen
)
4219 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
4220 struct sk_buff
*req
;
4224 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
4226 if (!ndev_vif
->activated
) {
4227 SLSI_ERR(sdev
, "ndev_vif is not activated\n");
4232 if (ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
) {
4233 SLSI_ERR(sdev
, "vif_type is not FAPI_VIFTYPE_STATION\n");
4238 req
= fapi_alloc(mlme_read_apf_req
, MLME_READ_APF_REQ
, ndev_vif
->ifnum
, 0);
4244 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_read_apf_req(vif:%u)\n", ndev_vif
->ifnum
);
4245 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_READ_APF_CFM
);
4251 if (fapi_get_u16(rx
, u
.mlme_read_apf_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4252 SLSI_NET_ERR(dev
, "mlme_read_apf_cfm(result:0x%04x) ERROR\n",
4253 fapi_get_u16(rx
, u
.mlme_read_apf_cfm
.result_code
));
4257 *datalen
= fapi_get_datalen(rx
);
4258 *host_dst
= fapi_get_data(rx
);
4261 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
4265 int slsi_mlme_install_apf_request(struct slsi_dev
*sdev
, struct net_device
*dev
,
4266 u8
*program
, u32 program_len
)
4268 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
4269 struct sk_buff
*req
;
4273 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
4275 if (!ndev_vif
->activated
) {
4276 SLSI_ERR(sdev
, "ndev_vif is not activated\n");
4281 if (ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
) {
4282 SLSI_ERR(sdev
, "vif_type is not FAPI_VIFTYPE_STATION\n");
4287 req
= fapi_alloc(mlme_install_apf_req
, MLME_INSTALL_APF_REQ
, ndev_vif
->ifnum
, program_len
);
4293 /* filter_mode will be "don't care" for FW */
4294 fapi_set_u16(req
, u
.mlme_install_apf_req
.filter_mode
, FAPI_APFFILTERMODE_SUSPEND
);
4295 fapi_append_data(req
, program
, program_len
);
4297 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_install_apf_req(vif:%u, filter_mode:%d)\n",
4298 ndev_vif
->ifnum
, FAPI_APFFILTERMODE_SUSPEND
);
4299 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_INSTALL_APF_CFM
);
4305 if (fapi_get_u16(rx
, u
.mlme_install_apf_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4306 SLSI_NET_ERR(dev
, "mlme_install_apf_cfm(result:0x%04x) ERROR\n",
4307 fapi_get_u16(rx
, u
.mlme_install_apf_cfm
.result_code
));
4312 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
4316 #ifdef CONFIG_SCSC_WLAN_STA_ENHANCED_ARP_DETECT
4317 int slsi_mlme_arp_detect_request(struct slsi_dev
*sdev
, struct net_device
*dev
, u16 action
, u8
*target_ipaddr
)
4319 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
4320 struct sk_buff
*req
;
4323 u32 ipaddress
= 0x0;
4326 if (!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
)) {
4327 SLSI_ERR(sdev
, "ndev_vif mutex is not locked\n");
4332 if (!ndev_vif
->activated
) {
4333 SLSI_ERR(sdev
, "ndev_vif is not activated\n");
4338 if ((ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
) && (ndev_vif
->iftype
== NL80211_IFTYPE_STATION
)) {
4339 SLSI_ERR(sdev
, "vif_type is not FAPI_VIFTYPE_STATION\n");
4344 req
= fapi_alloc(mlme_arp_detect_req
, MLME_ARP_DETECT_REQ
, ndev_vif
->ifnum
, 0);
4350 for (i
= 0; i
< 4; i
++)
4351 ipaddress
= (ipaddress
<< 8) | ((unsigned char)target_ipaddr
[i
]);
4352 ipaddress
= htonl(ipaddress
);
4354 fapi_set_u16(req
, u
.mlme_arp_detect_req
.arp_detect_action
, action
);
4355 fapi_append_data(req
, (const u8
*)&ipaddress
, 4);
4357 SLSI_NET_DBG2(dev
, SLSI_MLME
, "mlme_arp_detect_req(vif:%u, action:%d IP Address:%d.%d.%d.%d)\n",
4358 ndev_vif
->ifnum
, action
, ndev_vif
->target_ip_addr
[0], ndev_vif
->target_ip_addr
[1],
4359 ndev_vif
->target_ip_addr
[2], ndev_vif
->target_ip_addr
[3]);
4360 rx
= slsi_mlme_req_cfm(sdev
, dev
, req
, MLME_ARP_DETECT_CFM
);
4366 if (fapi_get_u16(rx
, u
.mlme_arp_detect_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4367 SLSI_NET_ERR(dev
, "mlme_arp_detect_cfm(result:0x%04x) ERROR\n",
4368 fapi_get_u16(rx
, u
.mlme_arp_detect_cfm
.result_code
));
4377 #ifdef CONFIG_SCSC_WLAN_DEBUG
4378 #define SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE (12)
4379 int slsi_test_sap_configure_monitor_mode(struct slsi_dev
*sdev
, struct net_device
*dev
, struct cfg80211_chan_def
*chandef
)
4381 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
4382 struct sk_buff
*req
;
4383 struct sk_buff
*cfm
;
4385 size_t alloc_data_size
= 0;
4391 const u8 monitor_config_ie_header
[] = {
4392 0xDD, /* Element ID: Vendor Specific */
4394 0x00, 0x16, 0x32, /* OUI: Samsung Electronics Co. */
4395 0x10, /* OUI Type: Monitor mode parameters */
4396 0x01 /* OUI Subtype: configuration */
4399 if (slsi_is_test_mode_enabled()) {
4400 SLSI_NET_WARN(dev
, "WlanLite: NOT supported\n");
4404 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
4406 chan_info
= slsi_get_chann_info(sdev
, chandef
);
4407 SLSI_NET_DBG2(dev
, SLSI_MLME
, "test_configure_monitor_mode_req(center_freq1:%u, chan_info:%u, center_freq2:%u)\n",
4408 chandef
->center_freq1
,
4410 chandef
->center_freq2
);
4412 center_freq1
= SLSI_FREQ_HOST_TO_FW(chandef
->center_freq1
);
4413 center_freq1
= cpu_to_le16(center_freq1
);
4414 center_freq2
= SLSI_FREQ_HOST_TO_FW(chandef
->center_freq2
);
4415 center_freq2
= cpu_to_le16(center_freq2
);
4417 alloc_data_size
= sizeof(monitor_config_ie_header
) + SLSI_TEST_CONFIG_MONITOR_MODE_DESCRIPTOR_SIZE
;
4419 req
= fapi_alloc(test_configure_monitor_mode_req
, TEST_CONFIGURE_MONITOR_MODE_REQ
, ndev_vif
->ifnum
, alloc_data_size
);
4421 SLSI_NET_ERR(dev
, "failed to alloc Monitor mode request (len:%d)\n", alloc_data_size
);
4425 fapi_append_data(req
, monitor_config_ie_header
, sizeof(monitor_config_ie_header
));
4426 fapi_append_data(req
, (const u8
*)¢er_freq1
, 2);
4427 fapi_append_data(req
, (const u8
*)&chan_info
, 2);
4428 p
= fapi_append_data(req
, (const u8
*)¢er_freq2
, 2);
4430 /* MAC address filtering is not supported yet; so fill in zeros */
4433 cfm
= slsi_mlme_req_cfm(sdev
, dev
, req
, TEST_CONFIGURE_MONITOR_MODE_CFM
);
4435 SLSI_NET_ERR(dev
, "failed to receive Confirm\n");
4439 if (fapi_get_u16(cfm
, u
.mlme_set_channel_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4440 SLSI_NET_ERR(dev
, "test_configure_monitor_mode_cfm(result:0x%04x) ERROR\n",
4441 fapi_get_u16(cfm
, u
.test_configure_monitor_mode_cfm
.result_code
));
4445 slsi_kfree_skb(cfm
);
4450 int slsi_mlme_set_country(struct slsi_dev
*sdev
, char *alpha2
)
4452 struct slsi_mib_data mib_data
= { 0, NULL
};
4453 struct sk_buff
*req
;
4454 struct sk_buff
*cfm
;
4455 int country_index
= 0;
4457 u16 country_code
= 0;
4463 if (sdev
->regdb
.regdb_state
== SLSI_REG_DB_SET
) {
4464 for (i
= 0; i
< sdev
->regdb
.num_countries
; i
++) {
4465 if ((sdev
->regdb
.country
[i
].alpha2
[0] == alpha2
[0]) && (sdev
->regdb
.country
[i
].alpha2
[1] == alpha2
[1])) {
4471 /* 7 octets for each rule */
4472 rules_len
= 7 * sdev
->regdb
.country
[country_index
].collection
->reg_rule_num
;
4473 dfs_region
= sdev
->regdb
.country
[country_index
].dfs_region
;
4476 /* last parameter should be length of bulk data */
4477 req
= fapi_alloc(mlme_set_country_req
, MLME_SET_COUNTRY_REQ
, 0, rules_len
);
4481 country_code
= (((u16
)alpha2
[0] << 8) | (u16
)alpha2
[1]);
4482 fapi_set_u16(req
, u
.mlme_set_country_req
.country_code
, country_code
);
4483 fapi_set_u16(req
, u
.mlme_set_country_req
.dfs_regulatory_domain
, dfs_region
);
4485 for (i
= 0; i
< sdev
->regdb
.country
[country_index
].collection
->reg_rule_num
; i
++) {
4486 append_byte
= (sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->freq_range
->start_freq
* 2) & 0xFF;
4487 fapi_append_data(req
, &append_byte
, 1);
4488 append_byte
= ((sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->freq_range
->start_freq
* 2) >> 8) & 0xFF;
4489 fapi_append_data(req
, &append_byte
, 1);
4490 append_byte
= (sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->freq_range
->end_freq
* 2) & 0xFF;
4491 fapi_append_data(req
, &append_byte
, 1);
4492 append_byte
= ((sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->freq_range
->end_freq
* 2) >> 8) & 0xFF;
4493 fapi_append_data(req
, &append_byte
, 1);
4494 append_byte
= sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->freq_range
->max_bandwidth
& 0xFF;
4495 fapi_append_data(req
, &append_byte
, 1);
4496 append_byte
= sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->max_eirp
& 0xFF;
4497 fapi_append_data(req
, &append_byte
, 1);
4498 append_byte
= sdev
->regdb
.country
[country_index
].collection
->reg_rule
[i
]->flags
& 0xFF;
4499 fapi_append_data(req
, &append_byte
, 1);
4503 SLSI_DBG2(sdev
, SLSI_MLME
, "mlme_set_country_req(country:%c%c, dfs_regulatory_domain:%x)\n", alpha2
[0], alpha2
[1], dfs_region
);
4504 cfm
= slsi_mlme_req_cfm(sdev
, NULL
, req
, MLME_SET_COUNTRY_CFM
);
4508 if (fapi_get_u16(cfm
, u
.mlme_set_country_cfm
.result_code
) != FAPI_RESULTCODE_SUCCESS
) {
4509 SLSI_ERR(sdev
, "mlme_set_country_cfm(result:0x%04x) ERROR\n",
4510 fapi_get_u16(cfm
, u
.mlme_set_country_cfm
.result_code
));
4511 slsi_kfree_skb(cfm
);
4512 error
= slsi_mib_encode_octet(&mib_data
, SLSI_PSID_UNIFI_DEFAULT_COUNTRY
, 3, alpha2
, 0);
4513 if (error
!= SLSI_MIB_STATUS_SUCCESS
)
4516 if (WARN_ON(mib_data
.dataLength
== 0))
4519 error
= slsi_mlme_set(sdev
, NULL
, mib_data
.data
, mib_data
.dataLength
);
4523 kfree(mib_data
.data
);
4527 slsi_kfree_skb(cfm
);
4531 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
4532 void slsi_mlme_set_country_for_recovery(struct slsi_dev
*sdev
)
4535 struct slsi_mib_data mib_data
= { 0, NULL
};
4537 SLSI_MUTEX_LOCK(sdev
->device_config_mutex
);
4538 ret
= slsi_mib_encode_octet(&mib_data
, SLSI_PSID_UNIFI_DEFAULT_COUNTRY
, 3, sdev
->device_config
.domain_info
.regdomain
->alpha2
, 0);
4539 if (ret
!= SLSI_MIB_STATUS_SUCCESS
) {
4541 SLSI_ERR(sdev
, "Err setting country error = %d\n", ret
);
4542 SLSI_MUTEX_UNLOCK(sdev
->device_config_mutex
);
4546 if (mib_data
.dataLength
== 0) {
4548 SLSI_ERR(sdev
, "Err setting country error = %d\n", ret
);
4549 SLSI_MUTEX_UNLOCK(sdev
->device_config_mutex
);
4553 ret
= slsi_mlme_set(sdev
, NULL
, mib_data
.data
, mib_data
.dataLength
);
4554 kfree(mib_data
.data
);
4557 SLSI_ERR(sdev
, "Err setting country error = %d\n", ret
);
4558 SLSI_MUTEX_UNLOCK(sdev
->device_config_mutex
);