1 /*****************************************************************************
3 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved
5 *****************************************************************************/
6 #include <net/cfg80211.h>
7 #include <linux/etherdevice.h>
18 static void slsi_fw_test_save_frame(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*saved_skbs
[CONFIG_SCSC_WLAN_MAX_INTERFACES
+ 1], struct sk_buff
*skb
, bool udi_header
)
22 skb
= slsi_skb_copy(skb
, GFP_KERNEL
);
25 skb_pull(skb
, sizeof(struct udi_msg_t
));
27 vif
= fapi_get_vif(skb
);
29 SLSI_DBG3(sdev
, SLSI_FW_TEST
, "sig:0x%.4X, vif:%d\n", fapi_get_sigid(skb
), vif
);
30 slsi_debug_frame(sdev
, NULL
, skb
, "SAVE");
32 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
33 slsi_kfree_skb(saved_skbs
[vif
]);
34 saved_skbs
[vif
] = skb
;
35 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
38 static void slsi_fw_test_process_frame(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
, bool udi_header
)
42 skb
= slsi_skb_copy(skb
, GFP_KERNEL
);
45 skb_pull(skb
, sizeof(struct udi_msg_t
));
47 vif
= fapi_get_vif(skb
);
49 SLSI_DBG3(sdev
, SLSI_FW_TEST
, "sig:0x%.4X, vif:%d\n", fapi_get_sigid(skb
), vif
);
50 slsi_debug_frame(sdev
, NULL
, skb
, "PROCESS");
52 slsi_skb_work_enqueue(&fwtest
->fw_test_work
, skb
);
55 int slsi_fw_test_signal(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
57 u16 vif
= fapi_get_vif(skb
);
59 /* Atleast one write to via the UDI interface */
60 fwtest
->fw_test_enabled
= true;
61 SLSI_DBG3(sdev
, SLSI_FW_TEST
, "0x%p: sig:0x%.4X, vif:%d\n", skb
, fapi_get_sigid(skb
), vif
);
63 if (WARN(vif
> CONFIG_SCSC_WLAN_MAX_INTERFACES
, "vif(%d) > CONFIG_SCSC_WLAN_MAX_INTERFACES", vif
))
66 switch (fapi_get_sigid(skb
)) {
67 case MLME_ADD_VIF_REQ
:
68 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Save MLME_ADD_VIF_REQ(0x%.4X, vif:%d)\n", skb
, fapi_get_sigid(skb
), vif
);
69 slsi_fw_test_save_frame(sdev
, fwtest
, fwtest
->mlme_add_vif_req
, skb
, false);
70 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, false);
72 case MLME_CONNECT_REQ
:
73 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Save MLME_CONNECT_REQ(0x%.4X, vif:%d)\n", skb
, fapi_get_sigid(skb
), vif
);
74 slsi_fw_test_save_frame(sdev
, fwtest
, fwtest
->mlme_connect_req
, skb
, false);
76 case MLME_DEL_VIF_REQ
:
77 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Save MLME_DEL_VIF_REQ(0x%.4X, vif:%d)\n", skb
, fapi_get_sigid(skb
), vif
);
78 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, false);
87 int slsi_fw_test_signal_with_udi_header(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
89 struct udi_msg_t
*udi_msg
= (struct udi_msg_t
*)skb
->data
;
90 struct fapi_vif_signal_header
*fapi_header
= (struct fapi_vif_signal_header
*)(skb
->data
+ sizeof(struct udi_msg_t
));
92 if (!fwtest
->fw_test_enabled
)
95 SLSI_DBG3(sdev
, SLSI_FW_TEST
, "0x%p: sig:0x%.4X, vif:%d\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
97 if (udi_msg
->direction
== SLSI_LOG_DIRECTION_TO_HOST
) {
98 switch (le16_to_cpu(fapi_header
->id
)) {
99 case MLME_DISCONNECT_IND
:
100 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_DISCONNECT_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
101 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
103 case MLME_DISCONNECTED_IND
:
104 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_DISCONNECTED_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
105 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
107 case MLME_CONNECT_IND
:
108 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_CONNECT_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
109 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
111 case MLME_CONNECTED_IND
:
112 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_CONNECTED_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
113 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
115 case MLME_ROAMED_IND
:
116 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_ROAMED_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
117 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
119 case MLME_TDLS_PEER_IND
:
120 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_TDLS_PEER_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
121 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
123 case MLME_CONNECT_CFM
:
124 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Save MLME_CONNECT_CFM(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
125 slsi_fw_test_save_frame(sdev
, fwtest
, fwtest
->mlme_connect_cfm
, skb
, true);
127 case MLME_PROCEDURE_STARTED_IND
:
128 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Save MLME_PROCEDURE_STARTED_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
129 slsi_fw_test_save_frame(sdev
, fwtest
, fwtest
->mlme_procedure_started_ind
, skb
, true);
130 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_PROCEDURE_STARTED_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
131 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
134 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MLME_START_CFM(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
135 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
136 sdev
->device_config
.ap_disconnect_ind_timeout
= SLSI_DEFAULT_AP_DISCONNECT_IND_TIMEOUT
;
138 case MA_BLOCKACK_IND
:
139 SLSI_DBG2(sdev
, SLSI_FW_TEST
, "0x%p: Process MA_BLOCKACK_IND(0x%.4X, vif:%d)\n", skb
, le16_to_cpu(fapi_header
->id
), le16_to_cpu(fapi_header
->vif
));
140 slsi_fw_test_process_frame(sdev
, fwtest
, skb
, true);
150 static void slsi_fw_test_connect_station_roam(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
152 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
153 struct slsi_peer
*peer
= slsi_get_peer_from_qs(sdev
, dev
, SLSI_STA_PEER_QUEUESET
);
154 struct ieee80211_mgmt
*mgmt
= fapi_get_mgmt(skb
);
155 struct sk_buff
*mlme_procedure_started_ind
;
157 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
159 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Station Connect(vif:%d) Roam\n", ndev_vif
->ifnum
);
161 if (WARN(!ndev_vif
->is_fw_test
, "!is_fw_test"))
164 if (WARN(!ndev_vif
->activated
, "Not Activated"))
167 if (WARN(ndev_vif
->vif_type
!= FAPI_VIFTYPE_STATION
, "Not Station Vif"))
170 if (WARN(!peer
, "peer not found"))
173 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
174 mlme_procedure_started_ind
= fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
];
175 fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
] = NULL
;
176 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
178 if (WARN(!mlme_procedure_started_ind
, "mlme_procedure_started_ind not found"))
181 slsi_rx_ba_stop_all(dev
, peer
);
183 SLSI_ETHER_COPY(peer
->address
, mgmt
->bssid
);
184 slsi_peer_update_assoc_req(sdev
, dev
, peer
, mlme_procedure_started_ind
);
185 slsi_peer_update_assoc_rsp(sdev
, dev
, peer
, slsi_skb_copy(skb
, GFP_KERNEL
));
188 static void slsi_fw_test_connect_start_station(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
190 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
194 struct slsi_peer
*peer
;
197 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
199 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Station Connect Start(vif:%d)\n", ndev_vif
->ifnum
);
201 if (WARN(!ndev_vif
->is_fw_test
, "!is_fw_test"))
203 if (WARN(ndev_vif
->activated
, "Already Activated"))
206 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
207 req
= fwtest
->mlme_connect_req
[ndev_vif
->ifnum
];
208 cfm
= fwtest
->mlme_connect_cfm
[ndev_vif
->ifnum
];
209 ind
= fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
];
211 SLSI_ETHER_COPY(bssid
, fapi_get_buff(req
, u
.mlme_connect_req
.bssid
));
212 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
214 if (WARN(!req
, "mlme_connect_req Not found"))
216 if (WARN(!cfm
, "mlme_connect_cfm Not found"))
219 ndev_vif
->iftype
= NL80211_IFTYPE_STATION
;
220 dev
->ieee80211_ptr
->iftype
= NL80211_IFTYPE_STATION
;
221 ndev_vif
->vif_type
= FAPI_VIFTYPE_STATION
;
223 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d slsi_vif_activated\n", ndev_vif
->ifnum
);
224 if (WARN(slsi_vif_activated(sdev
, dev
) != 0, "slsi_vif_activated() Failed"))
227 peer
= slsi_peer_add(sdev
, dev
, bssid
, SLSI_STA_PEER_QUEUESET
+ 1);
228 if (WARN(!peer
, "slsi_peer_add(%pM) Failed", bssid
)) {
229 slsi_vif_deactivated(sdev
, dev
);
233 slsi_peer_update_assoc_req(sdev
, dev
, peer
, slsi_skb_copy(skb
, GFP_KERNEL
));
236 static void slsi_fw_test_connect_station(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
238 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
242 struct slsi_peer
*peer
;
245 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
247 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Station Connect(vif:%d)\n", ndev_vif
->ifnum
);
249 if (WARN(!ndev_vif
->is_fw_test
, "!is_fw_test"))
252 result
= fapi_get_u16(skb
, u
.mlme_connect_ind
.result_code
);
254 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
255 req
= fwtest
->mlme_connect_req
[ndev_vif
->ifnum
];
256 cfm
= fwtest
->mlme_connect_cfm
[ndev_vif
->ifnum
];
257 ind
= fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
];
258 fwtest
->mlme_connect_req
[ndev_vif
->ifnum
] = NULL
;
259 fwtest
->mlme_connect_cfm
[ndev_vif
->ifnum
] = NULL
;
260 fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
] = NULL
;
261 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
263 if (WARN(!req
, "mlme_connect_req Not found"))
265 if (WARN(!cfm
, "mlme_connect_cfm Not found"))
267 if (FAPI_RESULTCODE_SUCCESS
== result
&&
268 WARN(!ind
, "mlme_procedure_started_ind Not found"))
270 if (FAPI_RESULTCODE_SUCCESS
!= result
)
273 if (WARN(!ndev_vif
->activated
, "Not Activated"))
276 peer
= slsi_get_peer_from_mac(sdev
, dev
, fapi_get_buff(req
, u
.mlme_connect_req
.bssid
));
277 if (WARN(!peer
, "slsi_get_peer_from_mac(%pM) Failed", fapi_get_buff(req
, u
.mlme_connect_req
.bssid
)))
280 slsi_ps_port_control(sdev
, dev
, peer
, SLSI_STA_CONN_STATE_CONNECTED
);
281 netif_carrier_on(dev
);
289 static void slsi_fw_test_started_network(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
291 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
292 u16 result
= fapi_get_u16(skb
, u
.mlme_start_cfm
.result_code
);
294 SLSI_UNUSED_PARAMETER(fwtest
);
296 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
298 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Start Network(vif:%d)\n", ndev_vif
->ifnum
);
300 if (WARN(!ndev_vif
->is_fw_test
, "!is_fw_test"))
302 if (WARN(ndev_vif
->activated
, "Already Activated"))
305 ndev_vif
->iftype
= NL80211_IFTYPE_AP
;
306 dev
->ieee80211_ptr
->iftype
= NL80211_IFTYPE_AP
;
307 ndev_vif
->vif_type
= FAPI_VIFTYPE_AP
;
309 if (WARN(slsi_vif_activated(sdev
, dev
) != 0, "slsi_vif_activated() Failed"))
312 if (FAPI_RESULTCODE_SUCCESS
== result
)
313 netif_carrier_on(dev
);
316 static void slsi_fw_test_stop_network(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
318 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
320 SLSI_UNUSED_PARAMETER(fwtest
);
321 SLSI_UNUSED_PARAMETER(skb
);
323 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
325 if (!ndev_vif
->is_fw_test
)
328 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Stopping Network(vif:%d)\n", ndev_vif
->ifnum
);
330 if (WARN(!ndev_vif
->activated
, "Not Activated"))
333 netif_carrier_off(dev
);
334 slsi_vif_deactivated(sdev
, dev
);
337 static void slsi_fw_test_connect_start_ap(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
339 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
340 struct slsi_peer
*peer
= NULL
;
341 struct ieee80211_mgmt
*mgmt
= fapi_get_mgmt(skb
);
344 SLSI_UNUSED_PARAMETER(fwtest
);
346 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
348 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Network Peer Connect Start(vif:%d)\n", ndev_vif
->ifnum
);
349 WARN(!ndev_vif
->is_fw_test
, "!is_fw_test");
351 if (WARN(!ndev_vif
->activated
, "Not Activated"))
354 if (WARN_ON(!ieee80211_is_assoc_req(mgmt
->frame_control
) &&
355 !ieee80211_is_reassoc_req(mgmt
->frame_control
)))
357 peer_index
= fapi_get_u16(skb
, u
.mlme_procedure_started_ind
.association_identifier
);
359 peer
= slsi_peer_add(sdev
, dev
, mgmt
->sa
, peer_index
);
363 slsi_peer_update_assoc_req(sdev
, dev
, peer
, slsi_skb_copy(skb
, GFP_KERNEL
));
364 peer
->connected_state
= SLSI_STA_CONN_STATE_CONNECTING
;
367 static void slsi_fw_test_connected_network(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
369 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
370 struct slsi_peer
*peer
= NULL
;
371 u16 aid
= fapi_get_u16(skb
, u
.mlme_connected_ind
.association_identifier
);
373 SLSI_UNUSED_PARAMETER(fwtest
);
375 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
377 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Network Peer Connect(vif:%d, aid:%d)\n", ndev_vif
->ifnum
, aid
);
378 WARN(!ndev_vif
->is_fw_test
, "!is_fw_test");
380 if (WARN(!ndev_vif
->activated
, "Not Activated"))
383 if (WARN_ON(aid
> SLSI_PEER_INDEX_MAX
))
386 peer
= slsi_get_peer_from_qs(sdev
, dev
, aid
- 1);
387 if (WARN(!peer
, "Peer(aid:%d) Not Found", aid
))
390 slsi_ps_port_control(sdev
, dev
, peer
, SLSI_STA_CONN_STATE_CONNECTED
);
391 peer
->connected_state
= SLSI_STA_CONN_STATE_CONNECTED
;
393 slsi_rx_buffered_frames(sdev
, dev
, peer
);
396 /* Setup the NetDev / Peers based on the saved frames */
397 static void slsi_fw_test_procedure_started_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
399 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
400 struct sk_buff
*add_vif_req
;
401 u16 viftype
= FAPI_VIFTYPE_STATION
;
403 if (!ndev_vif
->is_fw_test
) {
408 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "ProceedureStarted(vif:%d)\n", ndev_vif
->ifnum
);
410 if (fapi_get_u16(skb
, u
.mlme_procedure_started_ind
.procedure_type
) != FAPI_PROCEDURETYPE_CONNECTION_STARTED
) {
415 /* Set up the VIF and Data plane ready to go BUT do not open the control port */
416 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
417 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
419 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
420 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
422 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Start UDI test NetDevice(vif:%d)\n", ndev_vif
->ifnum
);
423 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
426 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
429 case FAPI_VIFTYPE_STATION
:
430 slsi_fw_test_connect_start_station(sdev
, dev
, fwtest
, skb
);
432 case FAPI_VIFTYPE_AP
:
433 slsi_fw_test_connect_start_ap(sdev
, dev
, fwtest
, skb
);
436 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
440 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
446 /* Setup the NetDev / Peers based on the saved frames */
447 static void slsi_fw_test_connect_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
449 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
450 struct sk_buff
*add_vif_req
;
451 u16 viftype
= FAPI_VIFTYPE_STATION
;
453 if (!ndev_vif
->is_fw_test
) {
458 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Network Peer Connect(vif:%d)\n", ndev_vif
->ifnum
);
460 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
461 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
463 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
464 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
466 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Start UDI test NetDevice(vif:%d)\n", ndev_vif
->ifnum
);
467 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
470 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
473 case FAPI_VIFTYPE_STATION
:
474 slsi_fw_test_connect_station(sdev
, dev
, fwtest
, skb
);
477 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
481 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
487 static void slsi_fw_test_connected_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
489 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
490 struct sk_buff
*add_vif_req
;
491 u16 viftype
= FAPI_VIFTYPE_STATION
;
493 if (!ndev_vif
->is_fw_test
) {
498 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Connected(vif:%d)\n", ndev_vif
->ifnum
);
500 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
501 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
503 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
504 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
506 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
509 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
512 case FAPI_VIFTYPE_AP
:
513 slsi_fw_test_connected_network(sdev
, dev
, fwtest
, skb
);
516 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
520 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
526 static void slsi_fw_test_roamed_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
528 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
529 struct sk_buff
*add_vif_req
;
530 u16 viftype
= FAPI_VIFTYPE_STATION
;
532 if (!ndev_vif
->is_fw_test
) {
537 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Roamed(vif:%d)\n", ndev_vif
->ifnum
);
539 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
540 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
542 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
543 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
545 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
548 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
551 case FAPI_VIFTYPE_STATION
:
552 slsi_fw_test_connect_station_roam(sdev
, dev
, fwtest
, skb
);
555 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
559 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
565 static void slsi_fw_test_disconnect_station(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
567 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
568 struct slsi_peer
*peer
= slsi_get_peer_from_qs(sdev
, dev
, SLSI_STA_PEER_QUEUESET
);
570 SLSI_UNUSED_PARAMETER(fwtest
);
571 SLSI_UNUSED_PARAMETER(skb
);
573 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
575 if (!ndev_vif
->is_fw_test
)
578 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Station Disconnect(vif:%d)\n", ndev_vif
->ifnum
);
580 if (WARN(!ndev_vif
->activated
, "Not Activated"))
583 netif_carrier_off(dev
);
585 slsi_spinlock_lock(&ndev_vif
->peer_lock
);
586 slsi_peer_remove(sdev
, dev
, peer
);
587 slsi_spinlock_unlock(&ndev_vif
->peer_lock
);
589 slsi_vif_deactivated(sdev
, dev
);
592 static void slsi_fw_test_disconnect_network(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
594 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
595 /* Find the peer based on MAC address, mlme-disconnect-ind and mlme-disconnected-ind
596 * both have the MAC address in the same position.
598 struct slsi_peer
*peer
= slsi_get_peer_from_mac(sdev
, dev
, fapi_get_buff(skb
, u
.mlme_disconnect_ind
.peer_sta_address
));
600 SLSI_UNUSED_PARAMETER(fwtest
);
602 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif
->vif_mutex
));
604 if (!ndev_vif
->is_fw_test
)
607 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Network Peer Disconnect(vif:%d)\n", ndev_vif
->ifnum
);
610 slsi_spinlock_lock(&ndev_vif
->peer_lock
);
611 slsi_peer_remove(sdev
, dev
, peer
);
612 slsi_spinlock_unlock(&ndev_vif
->peer_lock
);
616 static void slsi_fw_test_disconnected_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
618 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
619 struct sk_buff
*add_vif_req
;
620 u16 viftype
= FAPI_VIFTYPE_STATION
;
622 if (!ndev_vif
->is_fw_test
) {
627 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
628 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
630 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
631 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
633 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
636 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
639 case FAPI_VIFTYPE_STATION
:
640 slsi_fw_test_disconnect_station(sdev
, dev
, fwtest
, skb
);
642 case FAPI_VIFTYPE_AP
:
643 slsi_fw_test_disconnect_network(sdev
, dev
, fwtest
, skb
);
646 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
649 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
655 static void slsi_fw_test_tdls_event_connected(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
)
657 struct slsi_peer
*peer
= NULL
;
658 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
659 u16 peer_index
= fapi_get_u16(skb
, u
.mlme_tdls_peer_ind
.peer_index
);
661 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
662 ndev_vif
->sta
.tdls_enabled
= true;
663 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "TDLS connect (vif:%d, peer_index:%d, mac:%pM)\n", fapi_get_vif(skb
), peer_index
, fapi_get_buff(skb
, u
.mlme_tdls_peer_ind
.peer_sta_address
));
665 if ((ndev_vif
->sta
.tdls_peer_sta_records
) + 1 > SLSI_TDLS_PEER_CONNECTIONS_MAX
) {
666 SLSI_NET_ERR(dev
, "max TDLS limit reached (peer_index:%d)\n", peer_index
);
670 if (peer_index
< SLSI_TDLS_PEER_INDEX_MIN
|| peer_index
> SLSI_TDLS_PEER_INDEX_MAX
) {
671 SLSI_NET_ERR(dev
, "incorrect index (peer_index:%d)\n", peer_index
);
675 peer
= slsi_peer_add(sdev
, dev
, fapi_get_buff(skb
, u
.mlme_tdls_peer_ind
.peer_sta_address
), peer_index
);
677 SLSI_NET_ERR(dev
, "peer add failed\n");
681 /* QoS is mandatory for TDLS - enable QoS for TDLS peer by default */
682 peer
->qos_enabled
= true;
683 slsi_ps_port_control(sdev
, dev
, peer
, SLSI_STA_CONN_STATE_CONNECTED
);
685 /* move TDLS packets from STA Q to TDLS Q */
686 slsi_tdls_move_packets(sdev
, dev
, ndev_vif
->peer_sta_record
[SLSI_STA_PEER_QUEUESET
], peer
, true);
689 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
692 static void slsi_fw_test_tdls_event_disconnected(struct slsi_dev
*sdev
, struct net_device
*dev
, struct sk_buff
*skb
)
694 struct slsi_peer
*peer
= NULL
;
695 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
697 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
698 SLSI_NET_DBG1(dev
, SLSI_MLME
, "TDLS dis-connect (vif:%d, mac:%pM)\n", ndev_vif
->ifnum
, fapi_get_buff(skb
, u
.mlme_tdls_peer_ind
.peer_sta_address
));
700 slsi_spinlock_lock(&ndev_vif
->peer_lock
);
701 peer
= slsi_get_peer_from_mac(sdev
, dev
, fapi_get_buff(skb
, u
.mlme_tdls_peer_ind
.peer_sta_address
));
702 if (!peer
|| (peer
->aid
== 0)) {
703 WARN_ON(!peer
|| (peer
->aid
== 0));
704 SLSI_NET_DBG1(dev
, SLSI_MLME
, "can't find peer by MAC address\n");
708 slsi_ps_port_control(sdev
, dev
, peer
, SLSI_STA_CONN_STATE_DISCONNECTED
);
710 /* move TDLS packets from TDLS Q to STA Q */
711 slsi_tdls_move_packets(sdev
, dev
, ndev_vif
->peer_sta_record
[SLSI_STA_PEER_QUEUESET
], peer
, false);
712 slsi_peer_remove(sdev
, dev
, peer
);
714 slsi_spinlock_unlock(&ndev_vif
->peer_lock
);
715 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
718 static void slsi_fw_test_tdls_peer_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
720 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
721 struct sk_buff
*add_vif_req
;
725 if (!ndev_vif
->is_fw_test
) {
729 if (WARN(!ndev_vif
->activated
, "Not Activated")) {
733 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
734 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
736 vif_type
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
737 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
739 if (WARN(vif_type
!= FAPI_VIFTYPE_STATION
, "Not STA VIF")) {
744 tdls_event
= fapi_get_u16(skb
, u
.mlme_tdls_peer_ind
.tdls_event
);
745 SLSI_NET_DBG1(dev
, SLSI_MLME
, "TDLS peer(vif:%d tdls_event:%d)\n", ndev_vif
->ifnum
, tdls_event
);
746 switch (tdls_event
) {
747 case FAPI_TDLSEVENT_CONNECTED
:
748 slsi_fw_test_tdls_event_connected(sdev
, dev
, skb
);
750 case FAPI_TDLSEVENT_DISCONNECTED
:
751 slsi_fw_test_tdls_event_disconnected(sdev
, dev
, skb
);
753 case FAPI_TDLSEVENT_DISCOVERED
:
757 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d tdls_event:%d not supported\n", ndev_vif
->ifnum
, tdls_event
);
763 /* Setup the NetDev */
764 static void slsi_fw_test_start_cfm(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
766 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
767 struct sk_buff
*add_vif_req
;
768 u16 viftype
= FAPI_VIFTYPE_UNSYNCHRONISED
;
770 if (!ndev_vif
->is_fw_test
) {
775 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Network Start(vif:%d)\n", ndev_vif
->ifnum
);
777 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
778 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
780 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
781 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
783 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "Start UDI test NetDevice(vif:%d)\n", ndev_vif
->ifnum
);
784 if (WARN(!add_vif_req
, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
787 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
790 case FAPI_VIFTYPE_AP
:
791 slsi_fw_test_started_network(sdev
, dev
, fwtest
, skb
);
794 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif
->ifnum
, viftype
);
798 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
804 static void slsi_fw_test_add_vif_req(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
806 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
808 SLSI_UNUSED_PARAMETER(sdev
);
809 SLSI_UNUSED_PARAMETER(fwtest
);
811 SLSI_DBG1(sdev
, SLSI_FW_TEST
, "Mark UDI test NetDevice(vif:%d)\n", fapi_get_vif(skb
));
812 ndev_vif
->is_fw_test
= true;
816 static void slsi_fw_test_del_vif_req(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
818 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
819 struct sk_buff
*add_vif_req
;
820 u16 viftype
= FAPI_VIFTYPE_UNSYNCHRONISED
;
822 SLSI_DBG1(sdev
, SLSI_FW_TEST
, "Unmark UDI test NetDevice(vif:%d)\n", fapi_get_vif(skb
));
824 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
825 add_vif_req
= fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
];
827 viftype
= fapi_get_u16(add_vif_req
, u
.mlme_add_vif_req
.virtual_interface_type
);
828 slsi_kfree_skb(fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
]);
829 slsi_kfree_skb(fwtest
->mlme_connect_req
[ndev_vif
->ifnum
]);
830 slsi_kfree_skb(fwtest
->mlme_connect_cfm
[ndev_vif
->ifnum
]);
831 slsi_kfree_skb(fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
]);
833 fwtest
->mlme_add_vif_req
[ndev_vif
->ifnum
] = NULL
;
834 fwtest
->mlme_connect_req
[ndev_vif
->ifnum
] = NULL
;
835 fwtest
->mlme_connect_cfm
[ndev_vif
->ifnum
] = NULL
;
836 fwtest
->mlme_procedure_started_ind
[ndev_vif
->ifnum
] = NULL
;
837 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
839 SLSI_MUTEX_LOCK(ndev_vif
->vif_mutex
);
842 /* As there is no specific MLME primitive for shutting down the network
843 * perform an actions on the MLME-DEL-VIF.
845 case FAPI_VIFTYPE_AP
:
846 slsi_fw_test_stop_network(sdev
, dev
, fwtest
, skb
);
849 if (ndev_vif
->is_fw_test
&& ndev_vif
->activated
) {
850 netif_carrier_off(dev
);
851 slsi_vif_deactivated(sdev
, dev
);
855 ndev_vif
->is_fw_test
= false;
857 SLSI_MUTEX_UNLOCK(ndev_vif
->vif_mutex
);
862 static void slsi_fw_test_ma_blockack_ind(struct slsi_dev
*sdev
, struct net_device
*dev
, struct slsi_fw_test
*fwtest
, struct sk_buff
*skb
)
864 struct netdev_vif
*ndev_vif
= netdev_priv(dev
);
866 if (!ndev_vif
->is_fw_test
) {
871 SLSI_NET_DBG1(dev
, SLSI_FW_TEST
, "MA Block Ack Indication(vif:%d)\n", ndev_vif
->ifnum
);
872 slsi_rx_blockack_ind(sdev
, dev
, skb
);
875 void slsi_fw_test_work(struct work_struct
*work
)
877 struct slsi_fw_test
*fw_test
= container_of(work
, struct slsi_fw_test
, fw_test_work
.work
);
878 struct slsi_dev
*sdev
= fw_test
->sdev
;
879 struct sk_buff
*skb
= slsi_skb_work_dequeue(&fw_test
->fw_test_work
);
880 struct net_device
*dev
;
883 u16 vif
= fapi_get_vif(skb
);
885 SLSI_DBG3(sdev
, SLSI_FW_TEST
, "0x%p: Signal:0x%.4X, vif:%d\n", skb
, fapi_get_sigid(skb
), vif
);
887 if (WARN(!vif
, "!vif")) {
889 skb
= slsi_skb_work_dequeue(&fw_test
->fw_test_work
);
893 SLSI_MUTEX_LOCK(sdev
->netdev_add_remove_mutex
);
894 dev
= slsi_get_netdev_locked(sdev
, vif
);
896 /* Just ignore the signal. This is valid in some error testing scenarios*/
897 SLSI_MUTEX_UNLOCK(sdev
->netdev_add_remove_mutex
);
899 skb
= slsi_skb_work_dequeue(&fw_test
->fw_test_work
);
903 switch (fapi_get_sigid(skb
)) {
904 case MLME_PROCEDURE_STARTED_IND
:
905 slsi_fw_test_procedure_started_ind(sdev
, dev
, fw_test
, skb
);
907 case MLME_CONNECT_IND
:
908 slsi_fw_test_connect_ind(sdev
, dev
, fw_test
, skb
);
910 case MLME_ROAMED_IND
:
911 slsi_fw_test_roamed_ind(sdev
, dev
, fw_test
, skb
);
913 case MLME_CONNECTED_IND
:
914 slsi_fw_test_connected_ind(sdev
, dev
, fw_test
, skb
);
916 case MLME_DISCONNECT_IND
:
917 case MLME_DISCONNECTED_IND
:
918 slsi_fw_test_disconnected_ind(sdev
, dev
, fw_test
, skb
);
920 case MLME_TDLS_PEER_IND
:
921 slsi_fw_test_tdls_peer_ind(sdev
, dev
, fw_test
, skb
);
924 slsi_fw_test_start_cfm(sdev
, dev
, fw_test
, skb
);
926 case MLME_ADD_VIF_REQ
:
927 slsi_fw_test_add_vif_req(sdev
, dev
, fw_test
, skb
);
929 case MLME_DEL_VIF_REQ
:
930 slsi_fw_test_del_vif_req(sdev
, dev
, fw_test
, skb
);
932 case MA_BLOCKACK_IND
:
933 slsi_fw_test_ma_blockack_ind(sdev
, dev
, fw_test
, skb
);
936 WARN(1, "Unhandled Signal");
940 SLSI_MUTEX_UNLOCK(sdev
->netdev_add_remove_mutex
);
942 skb
= slsi_skb_work_dequeue(&fw_test
->fw_test_work
);
946 void slsi_fw_test_init(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
)
948 SLSI_DBG1(sdev
, SLSI_FW_TEST
, "\n");
949 memset(fwtest
, 0x00, sizeof(struct slsi_fw_test
));
951 slsi_spinlock_create(&fwtest
->fw_test_lock
);
952 slsi_skb_work_init(sdev
, NULL
, &fwtest
->fw_test_work
, "slsi_wlan_fw_test", slsi_fw_test_work
);
955 void slsi_fw_test_deinit(struct slsi_dev
*sdev
, struct slsi_fw_test
*fwtest
)
959 SLSI_UNUSED_PARAMETER(sdev
);
961 SLSI_DBG1(sdev
, SLSI_FW_TEST
, "\n");
962 fwtest
->fw_test_enabled
= false;
963 slsi_skb_work_deinit(&fwtest
->fw_test_work
);
964 slsi_spinlock_lock(&fwtest
->fw_test_lock
);
965 for (i
= 1; i
<= CONFIG_SCSC_WLAN_MAX_INTERFACES
; i
++) {
966 slsi_kfree_skb(fwtest
->mlme_add_vif_req
[i
]);
967 slsi_kfree_skb(fwtest
->mlme_connect_req
[i
]);
968 slsi_kfree_skb(fwtest
->mlme_connect_cfm
[i
]);
969 slsi_kfree_skb(fwtest
->mlme_procedure_started_ind
[i
]);
971 fwtest
->mlme_add_vif_req
[i
] = NULL
;
972 fwtest
->mlme_connect_req
[i
] = NULL
;
973 fwtest
->mlme_connect_cfm
[i
] = NULL
;
974 fwtest
->mlme_procedure_started_ind
[i
] = NULL
;
976 slsi_spinlock_unlock(&fwtest
->fw_test_lock
);
977 memset(fwtest
, 0x00, sizeof(struct slsi_fw_test
));