1 /****************************************************************************
3 * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd. All rights reserved
5 ****************************************************************************/
6 #include <linux/types.h>
15 #include "scsc_wifilogger_rings.h"
17 #include "nl80211_vendor.h"
20 #define SUPPORTED_OLD_VERSION 0
22 static int sap_mlme_version_supported(u16 version
);
23 static int sap_mlme_rx_handler(struct slsi_dev
*sdev
, struct sk_buff
*skb
);
25 static int sap_mlme_notifier(struct slsi_dev
*sdev
, unsigned long event
);
27 static struct sap_api sap_mlme
= {
28 .sap_class
= SAP_MLME
,
29 .sap_version_supported
= sap_mlme_version_supported
,
30 .sap_handler
= sap_mlme_rx_handler
,
31 .sap_versions
= { FAPI_CONTROL_SAP_VERSION
, SUPPORTED_OLD_VERSION
},
32 .sap_notifier
= sap_mlme_notifier
,
35 static int sap_mlme_notifier(struct slsi_dev
*sdev
, unsigned long event
)
38 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
39 struct net_device
*dev
;
41 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
42 bool vif_type_ap
= false;
45 struct netdev_vif
*ndev_vif
;
47 SLSI_INFO_NODEV("Notifier event received: %lu\n", event
);
48 if (event
>= SCSC_MAX_NOTIFIER
)
53 /* Stop sending signals down*/
54 sdev
->mlme_blocked
= true;
55 /* cleanup all the VIFs and scan data */
56 SLSI_MUTEX_LOCK(sdev
->netdev_add_remove_mutex
);
57 level
= atomic_read(&sdev
->cm_if
.reset_level
);
58 SLSI_INFO_NODEV("MLME BLOCKED system error level:%d\n", level
);
59 complete_all(&sdev
->sig_wait
.completion
);
60 /*WLAN system down actions*/
61 for (i
= 1; i
<= CONFIG_SCSC_WLAN_MAX_INTERFACES
; i
++)
62 if (sdev
->netdev
[i
]) {
63 ndev_vif
= netdev_priv(sdev
->netdev
[i
]);
64 slsi_scan_cleanup(sdev
, sdev
->netdev
[i
]);
65 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
66 /* For level7 use the older panic flow */
67 if (level
< SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
&& ndev_vif
->vif_type
== FAPI_VIFTYPE_AP
) {
68 slsi_ap_cleanup(sdev
, sdev
->netdev
[i
]);
72 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
73 slsi_vif_cleanup(sdev
, sdev
->netdev
[i
], 0);
74 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
75 if (level
< SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
&& vif_type_ap
)
76 ndev_vif
->vif_type
= FAPI_VIFTYPE_AP
;
78 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
80 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
81 if (level
< SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
)
82 sdev
->device_state
= SLSI_DEVICE_STATE_STOPPING
;
84 SLSI_MUTEX_UNLOCK(sdev
->netdev_add_remove_mutex
);
85 SLSI_INFO_NODEV("Force cleaned all VIFs\n");
88 case SCSC_WIFI_FAILURE_RESET
:
89 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
90 level
= atomic_read(&sdev
->cm_if
.reset_level
);
91 if (level
< SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
)
92 slsi_failure_reset(sdev
);
96 case SCSC_WIFI_SUSPEND
:
99 case SCSC_WIFI_RESUME
:
100 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
101 dev
= slsi_get_netdev(sdev
, SLSI_NET_INDEX_WLAN
);
102 ndev_vif
= netdev_priv(dev
);
103 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
105 if ((ndev_vif
->is_wips_running
) && (ndev_vif
->activated
) &&
106 (ndev_vif
->vif_type
== FAPI_VIFTYPE_STATION
) &&
107 (ndev_vif
->sta
.vif_status
== SLSI_VIF_STATUS_CONNECTED
)) {
108 ndev_vif
->is_wips_running
= false;
110 slsi_send_forward_beacon_abort_vendor_event(sdev
, SLSI_FORWARD_BEACON_ABORT_REASON_SUSPENDED
);
111 SLSI_INFO_NODEV("FORWARD_BEACON: SUSPEND_RESUMED!! send abort event\n");
114 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
117 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
118 case SCSC_WIFI_SUBSYSTEM_RESET
:
119 /*wlan system down actions*/
120 queue_work(sdev
->device_wq
, &sdev
->recovery_work
);
122 case SCSC_WIFI_CHIP_READY
:
123 level
= atomic_read(&sdev
->cm_if
.reset_level
);
124 if (level
< SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
)
125 slsi_chip_recovery(sdev
);
129 SLSI_INFO_NODEV("Unknown event code %lu\n", event
);
136 static int sap_mlme_version_supported(u16 version
)
138 unsigned int major
= SAP_MAJOR(version
);
139 unsigned int minor
= SAP_MINOR(version
);
142 SLSI_INFO_NODEV("Reported version: %d.%d\n", major
, minor
);
144 for (i
= 0; i
< SAP_MAX_VER
; i
++)
145 if (SAP_MAJOR(sap_mlme
.sap_versions
[i
]) == major
)
148 SLSI_ERR_NODEV("Version %d.%d Not supported\n", major
, minor
);
153 static int slsi_rx_netdev_mlme(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
)
155 u16 id
= fapi_get_u16(skb
, id
);
157 /* The skb is consumed by the functions called.
161 slsi_rx_scan_ind(sdev
, dev
, skb
);
163 case MLME_SCAN_DONE_IND
:
164 slsi_rx_scan_done_ind(sdev
, dev
, skb
);
166 case MLME_CONNECT_IND
:
167 slsi_rx_connect_ind(sdev
, dev
, skb
);
169 case MLME_CONNECTED_IND
:
170 slsi_rx_connected_ind(sdev
, dev
, skb
);
172 case MLME_RECEIVED_FRAME_IND
:
173 slsi_rx_received_frame_ind(sdev
, dev
, skb
);
175 case MLME_DISCONNECT_IND
:
176 slsi_rx_disconnect_ind(sdev
, dev
, skb
);
178 case MLME_DISCONNECTED_IND
:
179 slsi_rx_disconnected_ind(sdev
, dev
, skb
);
181 case MLME_PROCEDURE_STARTED_IND
:
182 slsi_rx_procedure_started_ind(sdev
, dev
, skb
);
184 case MLME_FRAME_TRANSMISSION_IND
:
185 slsi_rx_frame_transmission_ind(sdev
, dev
, skb
);
187 case MA_BLOCKACK_IND
:
188 slsi_rx_blockack_ind(sdev
, dev
, skb
);
190 case MLME_ROAMED_IND
:
191 slsi_rx_roamed_ind(sdev
, dev
, skb
);
194 slsi_rx_roam_ind(sdev
, dev
, skb
);
196 case MLME_MIC_FAILURE_IND
:
197 slsi_rx_mic_failure_ind(sdev
, dev
, skb
);
199 case MLME_REASSOCIATE_IND
:
200 slsi_rx_reassoc_ind(sdev
, dev
, skb
);
202 case MLME_TDLS_PEER_IND
:
203 slsi_tdls_peer_ind(sdev
, dev
, skb
);
205 case MLME_LISTEN_END_IND
:
206 slsi_rx_listen_end_ind(dev
, skb
);
208 case MLME_CHANNEL_SWITCHED_IND
:
209 slsi_rx_channel_switched_ind(sdev
, dev
, skb
);
211 case MLME_AC_PRIORITY_UPDATE_IND
:
212 SLSI_DBG1(sdev
, SLSI_MLME
, "Unexpected MLME_AC_PRIORITY_UPDATE_IND\n");
215 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
216 case MLME_RSSI_REPORT_IND
:
217 slsi_rx_rssi_report_ind(sdev
, dev
, skb
);
220 slsi_rx_range_ind(sdev
, dev
, skb
);
222 case MLME_RANGE_DONE_IND
:
223 slsi_rx_range_done_ind(sdev
, dev
, skb
);
225 case MLME_EVENT_LOG_IND
:
226 slsi_rx_event_log_indication(sdev
, dev
, skb
);
229 #ifdef CONFIG_SCSC_WIFI_NAN_ENABLE
230 case MLME_NAN_EVENT_IND
:
231 slsi_nan_event(sdev
, dev
, skb
);
234 case MLME_NAN_FOLLOWUP_IND
:
235 slsi_nan_followup_ind(sdev
, dev
, skb
);
238 case MLME_NAN_SERVICE_IND
:
239 slsi_nan_service_ind(sdev
, dev
, skb
);
243 #ifdef CONFIG_SCSC_WLAN_SAE_CONFIG
244 case MLME_SYNCHRONISED_IND
:
245 slsi_rx_synchronised_ind(sdev
, dev
, skb
);
249 #ifdef CONFIG_SLSI_WLAN_STA_FWD_BEACON
250 case MLME_BEACON_REPORTING_EVENT_IND
:
251 slsi_rx_beacon_reporting_event_ind(sdev
, dev
, skb
);
256 SLSI_NET_ERR(dev
, "Unhandled Ind: 0x%.4x\n", id
);
262 void slsi_rx_netdev_mlme_work(struct work_struct
*work
)
264 struct slsi_skb_work
*w
= container_of(work
, struct slsi_skb_work
, work
);
265 struct slsi_dev
*sdev
= w
->sdev
;
266 struct net_device
*dev
= w
->dev
;
267 struct sk_buff
*skb
= slsi_skb_work_dequeue(w
);
272 slsi_wakelock(&sdev
->wlan_wl
);
274 slsi_debug_frame(sdev
, dev
, skb
, "RX");
275 slsi_rx_netdev_mlme(sdev
, dev
, skb
);
276 skb
= slsi_skb_work_dequeue(w
);
278 slsi_wakeunlock(&sdev
->wlan_wl
);
281 int slsi_rx_enqueue_netdev_mlme(struct slsi_dev
*sdev
, struct sk_buff
*skb
, u16 vif
)
283 struct net_device
*dev
;
284 struct netdev_vif
*ndev_vif
;
287 dev
= slsi_get_netdev_rcu(sdev
, vif
);
290 /* Calling function should free the skb */
294 ndev_vif
= netdev_priv(dev
);
296 if (unlikely(ndev_vif
->is_fw_test
)) {
302 slsi_skb_work_enqueue(&ndev_vif
->rx_mlme
, skb
);
307 static int slsi_rx_action_enqueue_netdev_mlme(struct slsi_dev
*sdev
, struct sk_buff
*skb
, u16 vif
)
309 struct net_device
*dev
;
310 struct netdev_vif
*ndev_vif
;
313 dev
= slsi_get_netdev_rcu(sdev
, vif
);
319 ndev_vif
= netdev_priv(dev
);
321 if (unlikely(ndev_vif
->is_fw_test
)) {
326 if (ndev_vif
->iftype
== NL80211_IFTYPE_P2P_GO
|| ndev_vif
->iftype
== NL80211_IFTYPE_P2P_CLIENT
) {
327 struct ieee80211_mgmt
*mgmt
= fapi_get_mgmt(skb
);
328 /* Check the DA of received action frame with the GO interface address */
329 if (memcmp(mgmt
->da
, dev
->dev_addr
, ETH_ALEN
) != 0) {
330 /* If not equal, compare DA of received action frame with the P2P DEV address*/
331 struct net_device
*p2pdev
= slsi_get_netdev_rcu(sdev
, SLSI_NET_INDEX_P2P
);
333 if (WARN_ON(!p2pdev
)) {
337 if (memcmp(mgmt
->da
, p2pdev
->dev_addr
, ETH_ALEN
) == 0) {
338 /* If destination address is equal to P2P DEV ADDR, then action frame is received on
339 * GO interface. Hence indicate action frames on P2P DEV
341 ndev_vif
= netdev_priv(p2pdev
);
343 if (unlikely(ndev_vif
->is_fw_test
)) {
352 slsi_skb_work_enqueue(&ndev_vif
->rx_mlme
, skb
);
358 static int sap_mlme_rx_handler(struct slsi_dev
*sdev
, struct sk_buff
*skb
)
361 u16 vif
= fapi_get_vif(skb
);
363 if (slsi_rx_blocking_signals(sdev
, skb
) == 0)
366 if (fapi_is_ind(skb
)) {
367 #ifdef CONFIG_SCSC_WIFILOGGER
368 SCSC_WLOG_PKTFATE_LOG_RX_CTRL_FRAME(fapi_get_data(skb
), fapi_get_datalen(skb
));
371 switch (fapi_get_sigid(skb
)) {
372 case MLME_SCAN_DONE_IND
:
373 scan_id
= fapi_get_u16(skb
, u
.mlme_scan_done_ind
.scan_id
);
374 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
375 if (slsi_is_gscan_id(scan_id
))
376 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, SLSI_NET_INDEX_WLAN
);
378 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, (scan_id
>> 8));
381 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, vif
);
382 scan_id
= fapi_get_u16(skb
, u
.mlme_scan_ind
.scan_id
);
383 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
384 if (slsi_is_gscan_id(scan_id
))
385 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, SLSI_NET_INDEX_WLAN
);
387 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, (scan_id
>> 8));
388 case MLME_RECEIVED_FRAME_IND
:
390 SLSI_WARN(sdev
, "Received MLME_RECEIVED_FRAME_IND on VIF 0\n");
393 return slsi_rx_action_enqueue_netdev_mlme(sdev
, skb
, vif
);
394 #ifdef CONFIG_SCSC_WLAN_GSCAN_ENABLE
395 case MLME_NAN_EVENT_IND
:
396 case MLME_NAN_FOLLOWUP_IND
:
397 case MLME_NAN_SERVICE_IND
:
398 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, vif
);
400 case MLME_RANGE_DONE_IND
:
402 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, SLSI_NET_INDEX_WLAN
);
404 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, vif
);
406 #ifdef CONFIG_SCSC_WLAN_ENHANCED_LOGGING
407 case MLME_EVENT_LOG_IND
:
408 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, SLSI_NET_INDEX_WLAN
);
410 case MLME_ROAMED_IND
:
412 SLSI_WARN(sdev
, "Received MLME_ROAMED_IND on VIF 0, return error\n");
415 struct net_device
*dev
;
416 struct netdev_vif
*ndev_vif
;
419 dev
= slsi_get_netdev_rcu(sdev
, vif
);
424 ndev_vif
= netdev_priv(dev
);
425 if (atomic_read(&ndev_vif
->sta
.drop_roamed_ind
)) {
426 /* If roam cfm is not received for the req, ignore this roamed indication. */
432 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, vif
);
436 SLSI_WARN(sdev
, "Received signal 0x%04x on VIF 0, return error\n", fapi_get_sigid(skb
));
439 return slsi_rx_enqueue_netdev_mlme(sdev
, skb
, vif
);
443 if (WARN_ON(fapi_is_req(skb
)))
446 if (slsi_is_test_mode_enabled()) {
457 int sap_mlme_init(void)
459 SLSI_INFO_NODEV("Registering SAP\n");
460 slsi_hip_sap_register(&sap_mlme
);
464 int sap_mlme_deinit(void)
466 SLSI_INFO_NODEV("Unregistering SAP\n");
467 slsi_hip_sap_unregister(&sap_mlme
);