[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / net / wireless / scsc / fw_test.c
1 /*****************************************************************************
2 *
3 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 *****************************************************************************/
6 #include <net/cfg80211.h>
7 #include <linux/etherdevice.h>
8 #include "dev.h"
9 #include "fapi.h"
10 #include "fw_test.h"
11 #include "debug.h"
12 #include "mgt.h"
13 #include "mlme.h"
14 #include "netif.h"
15 #include "ba.h"
16 #include "sap_mlme.h"
17
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)
19 {
20 u16 vif;
21
22 skb = slsi_skb_copy(skb, GFP_KERNEL);
23
24 if (udi_header)
25 skb_pull(skb, sizeof(struct udi_msg_t));
26
27 vif = fapi_get_vif(skb);
28
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");
31
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);
36 }
37
38 static void slsi_fw_test_process_frame(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb, bool udi_header)
39 {
40 u16 vif;
41
42 skb = slsi_skb_copy(skb, GFP_KERNEL);
43
44 if (udi_header)
45 skb_pull(skb, sizeof(struct udi_msg_t));
46
47 vif = fapi_get_vif(skb);
48
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");
51
52 slsi_skb_work_enqueue(&fwtest->fw_test_work, skb);
53 }
54
55 int slsi_fw_test_signal(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb)
56 {
57 u16 vif = fapi_get_vif(skb);
58
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);
62
63 if (WARN(vif > CONFIG_SCSC_WLAN_MAX_INTERFACES, "vif(%d) > CONFIG_SCSC_WLAN_MAX_INTERFACES", vif))
64 return -EINVAL;
65
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);
71 break;
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);
75 break;
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);
79 break;
80 default:
81 return 0;
82 }
83
84 return 0;
85 }
86
87 int slsi_fw_test_signal_with_udi_header(struct slsi_dev *sdev, struct slsi_fw_test *fwtest, struct sk_buff *skb)
88 {
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));
91
92 if (!fwtest->fw_test_enabled)
93 return 0;
94
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));
96
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);
102 break;
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);
106 break;
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);
110 break;
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);
114 break;
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);
118 break;
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);
122 break;
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);
126 break;
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);
132 break;
133 case MLME_START_CFM:
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;
137 break;
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);
141 break;
142 default:
143 break;
144 }
145 }
146
147 return 0;
148 }
149
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)
151 {
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;
156
157 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
158
159 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect(vif:%d) Roam\n", ndev_vif->ifnum);
160
161 if (WARN(!ndev_vif->is_fw_test, "!is_fw_test"))
162 return;
163
164 if (WARN(!ndev_vif->activated, "Not Activated"))
165 return;
166
167 if (WARN(ndev_vif->vif_type != FAPI_VIFTYPE_STATION, "Not Station Vif"))
168 return;
169
170 if (WARN(!peer, "peer not found"))
171 return;
172
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);
177
178 if (WARN(!mlme_procedure_started_ind, "mlme_procedure_started_ind not found"))
179 return;
180
181 slsi_rx_ba_stop_all(dev, peer);
182
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));
186 }
187
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)
189 {
190 struct netdev_vif *ndev_vif = netdev_priv(dev);
191 struct sk_buff *req;
192 struct sk_buff *cfm;
193 struct sk_buff *ind;
194 struct slsi_peer *peer;
195 u8 bssid[ETH_ALEN];
196
197 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
198
199 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect Start(vif:%d)\n", ndev_vif->ifnum);
200
201 if (WARN(!ndev_vif->is_fw_test, "!is_fw_test"))
202 return;
203 if (WARN(ndev_vif->activated, "Already Activated"))
204 return;
205
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];
210 if (req)
211 SLSI_ETHER_COPY(bssid, fapi_get_buff(req, u.mlme_connect_req.bssid));
212 slsi_spinlock_unlock(&fwtest->fw_test_lock);
213
214 if (WARN(!req, "mlme_connect_req Not found"))
215 return;
216 if (WARN(!cfm, "mlme_connect_cfm Not found"))
217 return;
218
219 ndev_vif->iftype = NL80211_IFTYPE_STATION;
220 dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
221 ndev_vif->vif_type = FAPI_VIFTYPE_STATION;
222
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"))
225 return;
226
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);
230 return;
231 }
232
233 slsi_peer_update_assoc_req(sdev, dev, peer, slsi_skb_copy(skb, GFP_KERNEL));
234 }
235
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)
237 {
238 struct netdev_vif *ndev_vif = netdev_priv(dev);
239 struct sk_buff *req;
240 struct sk_buff *cfm;
241 struct sk_buff *ind;
242 struct slsi_peer *peer;
243 u16 result;
244
245 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
246
247 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Connect(vif:%d)\n", ndev_vif->ifnum);
248
249 if (WARN(!ndev_vif->is_fw_test, "!is_fw_test"))
250 return;
251
252 result = fapi_get_u16(skb, u.mlme_connect_ind.result_code);
253
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);
262
263 if (WARN(!req, "mlme_connect_req Not found"))
264 goto exit;
265 if (WARN(!cfm, "mlme_connect_cfm Not found"))
266 goto exit;
267 if (FAPI_RESULTCODE_SUCCESS == result &&
268 WARN(!ind, "mlme_procedure_started_ind Not found"))
269 goto exit;
270 if (FAPI_RESULTCODE_SUCCESS != result)
271 goto exit;
272
273 if (WARN(!ndev_vif->activated, "Not Activated"))
274 return;
275
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)))
278 goto exit;
279
280 slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED);
281 netif_carrier_on(dev);
282
283 exit:
284 slsi_kfree_skb(req);
285 slsi_kfree_skb(cfm);
286 slsi_kfree_skb(ind);
287 }
288
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)
290 {
291 struct netdev_vif *ndev_vif = netdev_priv(dev);
292 u16 result = fapi_get_u16(skb, u.mlme_start_cfm.result_code);
293
294 SLSI_UNUSED_PARAMETER(fwtest);
295
296 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
297
298 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Start Network(vif:%d)\n", ndev_vif->ifnum);
299
300 if (WARN(!ndev_vif->is_fw_test, "!is_fw_test"))
301 return;
302 if (WARN(ndev_vif->activated, "Already Activated"))
303 return;
304
305 ndev_vif->iftype = NL80211_IFTYPE_AP;
306 dev->ieee80211_ptr->iftype = NL80211_IFTYPE_AP;
307 ndev_vif->vif_type = FAPI_VIFTYPE_AP;
308
309 if (WARN(slsi_vif_activated(sdev, dev) != 0, "slsi_vif_activated() Failed"))
310 return;
311
312 if (FAPI_RESULTCODE_SUCCESS == result)
313 netif_carrier_on(dev);
314 }
315
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)
317 {
318 struct netdev_vif *ndev_vif = netdev_priv(dev);
319
320 SLSI_UNUSED_PARAMETER(fwtest);
321 SLSI_UNUSED_PARAMETER(skb);
322
323 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
324
325 if (!ndev_vif->is_fw_test)
326 return;
327
328 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Stopping Network(vif:%d)\n", ndev_vif->ifnum);
329
330 if (WARN(!ndev_vif->activated, "Not Activated"))
331 return;
332
333 netif_carrier_off(dev);
334 slsi_vif_deactivated(sdev, dev);
335 }
336
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)
338 {
339 struct netdev_vif *ndev_vif = netdev_priv(dev);
340 struct slsi_peer *peer = NULL;
341 struct ieee80211_mgmt *mgmt = fapi_get_mgmt(skb);
342 u16 peer_index;
343
344 SLSI_UNUSED_PARAMETER(fwtest);
345
346 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
347
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");
350
351 if (WARN(!ndev_vif->activated, "Not Activated"))
352 return;
353
354 if (WARN_ON(!ieee80211_is_assoc_req(mgmt->frame_control) &&
355 !ieee80211_is_reassoc_req(mgmt->frame_control)))
356 return;
357 peer_index = fapi_get_u16(skb, u.mlme_procedure_started_ind.association_identifier);
358
359 peer = slsi_peer_add(sdev, dev, mgmt->sa, peer_index);
360 if (WARN_ON(!peer))
361 return;
362
363 slsi_peer_update_assoc_req(sdev, dev, peer, slsi_skb_copy(skb, GFP_KERNEL));
364 peer->connected_state = SLSI_STA_CONN_STATE_CONNECTING;
365 }
366
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)
368 {
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);
372
373 SLSI_UNUSED_PARAMETER(fwtest);
374
375 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
376
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");
379
380 if (WARN(!ndev_vif->activated, "Not Activated"))
381 return;
382
383 if (WARN_ON(aid > SLSI_PEER_INDEX_MAX))
384 return;
385
386 peer = slsi_get_peer_from_qs(sdev, dev, aid - 1);
387 if (WARN(!peer, "Peer(aid:%d) Not Found", aid))
388 return;
389
390 slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_CONNECTED);
391 peer->connected_state = SLSI_STA_CONN_STATE_CONNECTED;
392
393 slsi_rx_buffered_frames(sdev, dev, peer);
394 }
395
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)
398 {
399 struct netdev_vif *ndev_vif = netdev_priv(dev);
400 struct sk_buff *add_vif_req;
401 u16 viftype = FAPI_VIFTYPE_STATION;
402
403 if (!ndev_vif->is_fw_test) {
404 slsi_kfree_skb(skb);
405 return;
406 }
407
408 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "ProceedureStarted(vif:%d)\n", ndev_vif->ifnum);
409
410 if (fapi_get_u16(skb, u.mlme_procedure_started_ind.procedure_type) != FAPI_PROCEDURETYPE_CONNECTION_STARTED) {
411 slsi_kfree_skb(skb);
412 return;
413 }
414
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];
418 if (add_vif_req)
419 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
420 slsi_spinlock_unlock(&fwtest->fw_test_lock);
421
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"))
424 goto out;
425
426 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
427
428 switch (viftype) {
429 case FAPI_VIFTYPE_STATION:
430 slsi_fw_test_connect_start_station(sdev, dev, fwtest, skb);
431 break;
432 case FAPI_VIFTYPE_AP:
433 slsi_fw_test_connect_start_ap(sdev, dev, fwtest, skb);
434 break;
435 default:
436 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
437 break;
438 }
439
440 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
441
442 out:
443 slsi_kfree_skb(skb);
444 }
445
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)
448 {
449 struct netdev_vif *ndev_vif = netdev_priv(dev);
450 struct sk_buff *add_vif_req;
451 u16 viftype = FAPI_VIFTYPE_STATION;
452
453 if (!ndev_vif->is_fw_test) {
454 slsi_kfree_skb(skb);
455 return;
456 }
457
458 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Connect(vif:%d)\n", ndev_vif->ifnum);
459
460 slsi_spinlock_lock(&fwtest->fw_test_lock);
461 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
462 if (add_vif_req)
463 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
464 slsi_spinlock_unlock(&fwtest->fw_test_lock);
465
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"))
468 goto out;
469
470 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
471
472 switch (viftype) {
473 case FAPI_VIFTYPE_STATION:
474 slsi_fw_test_connect_station(sdev, dev, fwtest, skb);
475 break;
476 default:
477 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
478 break;
479 }
480
481 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
482
483 out:
484 slsi_kfree_skb(skb);
485 }
486
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)
488 {
489 struct netdev_vif *ndev_vif = netdev_priv(dev);
490 struct sk_buff *add_vif_req;
491 u16 viftype = FAPI_VIFTYPE_STATION;
492
493 if (!ndev_vif->is_fw_test) {
494 slsi_kfree_skb(skb);
495 return;
496 }
497
498 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Connected(vif:%d)\n", ndev_vif->ifnum);
499
500 slsi_spinlock_lock(&fwtest->fw_test_lock);
501 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
502 if (add_vif_req)
503 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
504 slsi_spinlock_unlock(&fwtest->fw_test_lock);
505
506 if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
507 goto out;
508
509 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
510
511 switch (viftype) {
512 case FAPI_VIFTYPE_AP:
513 slsi_fw_test_connected_network(sdev, dev, fwtest, skb);
514 break;
515 default:
516 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
517 break;
518 }
519
520 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
521
522 out:
523 slsi_kfree_skb(skb);
524 }
525
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)
527 {
528 struct netdev_vif *ndev_vif = netdev_priv(dev);
529 struct sk_buff *add_vif_req;
530 u16 viftype = FAPI_VIFTYPE_STATION;
531
532 if (!ndev_vif->is_fw_test) {
533 slsi_kfree_skb(skb);
534 return;
535 }
536
537 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Roamed(vif:%d)\n", ndev_vif->ifnum);
538
539 slsi_spinlock_lock(&fwtest->fw_test_lock);
540 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
541 if (add_vif_req)
542 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
543 slsi_spinlock_unlock(&fwtest->fw_test_lock);
544
545 if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
546 goto out;
547
548 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
549
550 switch (viftype) {
551 case FAPI_VIFTYPE_STATION:
552 slsi_fw_test_connect_station_roam(sdev, dev, fwtest, skb);
553 break;
554 default:
555 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
556 break;
557 }
558
559 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
560
561 out:
562 slsi_kfree_skb(skb);
563 }
564
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)
566 {
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);
569
570 SLSI_UNUSED_PARAMETER(fwtest);
571 SLSI_UNUSED_PARAMETER(skb);
572
573 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
574
575 if (!ndev_vif->is_fw_test)
576 return;
577
578 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Station Disconnect(vif:%d)\n", ndev_vif->ifnum);
579
580 if (WARN(!ndev_vif->activated, "Not Activated"))
581 return;
582
583 netif_carrier_off(dev);
584 if (peer) {
585 slsi_spinlock_lock(&ndev_vif->peer_lock);
586 slsi_peer_remove(sdev, dev, peer);
587 slsi_spinlock_unlock(&ndev_vif->peer_lock);
588 }
589 slsi_vif_deactivated(sdev, dev);
590 }
591
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)
593 {
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.
597 */
598 struct slsi_peer *peer = slsi_get_peer_from_mac(sdev, dev, fapi_get_buff(skb, u.mlme_disconnect_ind.peer_sta_address));
599
600 SLSI_UNUSED_PARAMETER(fwtest);
601
602 WARN_ON(!SLSI_MUTEX_IS_LOCKED(ndev_vif->vif_mutex));
603
604 if (!ndev_vif->is_fw_test)
605 return;
606
607 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Peer Disconnect(vif:%d)\n", ndev_vif->ifnum);
608
609 if (peer) {
610 slsi_spinlock_lock(&ndev_vif->peer_lock);
611 slsi_peer_remove(sdev, dev, peer);
612 slsi_spinlock_unlock(&ndev_vif->peer_lock);
613 }
614 }
615
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)
617 {
618 struct netdev_vif *ndev_vif = netdev_priv(dev);
619 struct sk_buff *add_vif_req;
620 u16 viftype = FAPI_VIFTYPE_STATION;
621
622 if (!ndev_vif->is_fw_test) {
623 slsi_kfree_skb(skb);
624 return;
625 }
626
627 slsi_spinlock_lock(&fwtest->fw_test_lock);
628 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
629 if (add_vif_req)
630 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
631 slsi_spinlock_unlock(&fwtest->fw_test_lock);
632
633 if (WARN(!add_vif_req, "fwtest->mlme_add_vif_req[ndev_vif->ifnum] == NULL"))
634 goto out;
635
636 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
637
638 switch (viftype) {
639 case FAPI_VIFTYPE_STATION:
640 slsi_fw_test_disconnect_station(sdev, dev, fwtest, skb);
641 break;
642 case FAPI_VIFTYPE_AP:
643 slsi_fw_test_disconnect_network(sdev, dev, fwtest, skb);
644 break;
645 default:
646 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
647 break;
648 }
649 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
650
651 out:
652 slsi_kfree_skb(skb);
653 }
654
655 static void slsi_fw_test_tdls_event_connected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
656 {
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);
660
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));
664
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);
667 goto out;
668 }
669
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);
672 goto out;
673 }
674
675 peer = slsi_peer_add(sdev, dev, fapi_get_buff(skb, u.mlme_tdls_peer_ind.peer_sta_address), peer_index);
676 if (!peer) {
677 SLSI_NET_ERR(dev, "peer add failed\n");
678 goto out;
679 }
680
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);
684
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);
687
688 out:
689 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
690 }
691
692 static void slsi_fw_test_tdls_event_disconnected(struct slsi_dev *sdev, struct net_device *dev, struct sk_buff *skb)
693 {
694 struct slsi_peer *peer = NULL;
695 struct netdev_vif *ndev_vif = netdev_priv(dev);
696
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));
699
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");
705 goto out;
706 }
707
708 slsi_ps_port_control(sdev, dev, peer, SLSI_STA_CONN_STATE_DISCONNECTED);
709
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);
713 out:
714 slsi_spinlock_unlock(&ndev_vif->peer_lock);
715 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
716 }
717
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)
719 {
720 struct netdev_vif *ndev_vif = netdev_priv(dev);
721 struct sk_buff *add_vif_req;
722 u16 vif_type = 0;
723 u16 tdls_event;
724
725 if (!ndev_vif->is_fw_test) {
726 slsi_kfree_skb(skb);
727 return;
728 }
729 if (WARN(!ndev_vif->activated, "Not Activated")) {
730 slsi_kfree_skb(skb);
731 return;
732 }
733 slsi_spinlock_lock(&fwtest->fw_test_lock);
734 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
735 if (add_vif_req)
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);
738
739 if (WARN(vif_type != FAPI_VIFTYPE_STATION, "Not STA VIF")) {
740 slsi_kfree_skb(skb);
741 return;
742 }
743
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);
749 break;
750 case FAPI_TDLSEVENT_DISCONNECTED:
751 slsi_fw_test_tdls_event_disconnected(sdev, dev, skb);
752 break;
753 case FAPI_TDLSEVENT_DISCOVERED:
754 /* nothing to do */
755 break;
756 default:
757 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d tdls_event:%d not supported\n", ndev_vif->ifnum, tdls_event);
758 break;
759 }
760 slsi_kfree_skb(skb);
761 }
762
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)
765 {
766 struct netdev_vif *ndev_vif = netdev_priv(dev);
767 struct sk_buff *add_vif_req;
768 u16 viftype = FAPI_VIFTYPE_UNSYNCHRONISED;
769
770 if (!ndev_vif->is_fw_test) {
771 slsi_kfree_skb(skb);
772 return;
773 }
774
775 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "Network Start(vif:%d)\n", ndev_vif->ifnum);
776
777 slsi_spinlock_lock(&fwtest->fw_test_lock);
778 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
779 if (add_vif_req)
780 viftype = fapi_get_u16(add_vif_req, u.mlme_add_vif_req.virtual_interface_type);
781 slsi_spinlock_unlock(&fwtest->fw_test_lock);
782
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"))
785 goto out;
786
787 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
788
789 switch (viftype) {
790 case FAPI_VIFTYPE_AP:
791 slsi_fw_test_started_network(sdev, dev, fwtest, skb);
792 break;
793 default:
794 SLSI_NET_DBG1(dev, SLSI_FW_TEST, "vif:%d virtual_interface_type:%d NOT SUPPORTED\n", ndev_vif->ifnum, viftype);
795 break;
796 }
797
798 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
799
800 out:
801 slsi_kfree_skb(skb);
802 }
803
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)
805 {
806 struct netdev_vif *ndev_vif = netdev_priv(dev);
807
808 SLSI_UNUSED_PARAMETER(sdev);
809 SLSI_UNUSED_PARAMETER(fwtest);
810
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;
813 slsi_kfree_skb(skb);
814 }
815
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)
817 {
818 struct netdev_vif *ndev_vif = netdev_priv(dev);
819 struct sk_buff *add_vif_req;
820 u16 viftype = FAPI_VIFTYPE_UNSYNCHRONISED;
821
822 SLSI_DBG1(sdev, SLSI_FW_TEST, "Unmark UDI test NetDevice(vif:%d)\n", fapi_get_vif(skb));
823
824 slsi_spinlock_lock(&fwtest->fw_test_lock);
825 add_vif_req = fwtest->mlme_add_vif_req[ndev_vif->ifnum];
826 if (add_vif_req)
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]);
832
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);
838
839 SLSI_MUTEX_LOCK(ndev_vif->vif_mutex);
840
841 switch (viftype) {
842 /* As there is no specific MLME primitive for shutting down the network
843 * perform an actions on the MLME-DEL-VIF.
844 */
845 case FAPI_VIFTYPE_AP:
846 slsi_fw_test_stop_network(sdev, dev, fwtest, skb);
847 break;
848 default:
849 if (ndev_vif->is_fw_test && ndev_vif->activated) {
850 netif_carrier_off(dev);
851 slsi_vif_deactivated(sdev, dev);
852 }
853 break;
854 }
855 ndev_vif->is_fw_test = false;
856
857 SLSI_MUTEX_UNLOCK(ndev_vif->vif_mutex);
858
859 slsi_kfree_skb(skb);
860 }
861
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)
863 {
864 struct netdev_vif *ndev_vif = netdev_priv(dev);
865
866 if (!ndev_vif->is_fw_test) {
867 slsi_kfree_skb(skb);
868 return;
869 }
870
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);
873 }
874
875 void slsi_fw_test_work(struct work_struct *work)
876 {
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;
881
882 while (skb) {
883 u16 vif = fapi_get_vif(skb);
884
885 SLSI_DBG3(sdev, SLSI_FW_TEST, "0x%p: Signal:0x%.4X, vif:%d\n", skb, fapi_get_sigid(skb), vif);
886
887 if (WARN(!vif, "!vif")) {
888 slsi_kfree_skb(skb);
889 skb = slsi_skb_work_dequeue(&fw_test->fw_test_work);
890 continue;
891 }
892
893 SLSI_MUTEX_LOCK(sdev->netdev_add_remove_mutex);
894 dev = slsi_get_netdev_locked(sdev, vif);
895 if (!dev) {
896 /* Just ignore the signal. This is valid in some error testing scenarios*/
897 SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
898 slsi_kfree_skb(skb);
899 skb = slsi_skb_work_dequeue(&fw_test->fw_test_work);
900 continue;
901 }
902
903 switch (fapi_get_sigid(skb)) {
904 case MLME_PROCEDURE_STARTED_IND:
905 slsi_fw_test_procedure_started_ind(sdev, dev, fw_test, skb);
906 break;
907 case MLME_CONNECT_IND:
908 slsi_fw_test_connect_ind(sdev, dev, fw_test, skb);
909 break;
910 case MLME_ROAMED_IND:
911 slsi_fw_test_roamed_ind(sdev, dev, fw_test, skb);
912 break;
913 case MLME_CONNECTED_IND:
914 slsi_fw_test_connected_ind(sdev, dev, fw_test, skb);
915 break;
916 case MLME_DISCONNECT_IND:
917 case MLME_DISCONNECTED_IND:
918 slsi_fw_test_disconnected_ind(sdev, dev, fw_test, skb);
919 break;
920 case MLME_TDLS_PEER_IND:
921 slsi_fw_test_tdls_peer_ind(sdev, dev, fw_test, skb);
922 break;
923 case MLME_START_CFM:
924 slsi_fw_test_start_cfm(sdev, dev, fw_test, skb);
925 break;
926 case MLME_ADD_VIF_REQ:
927 slsi_fw_test_add_vif_req(sdev, dev, fw_test, skb);
928 break;
929 case MLME_DEL_VIF_REQ:
930 slsi_fw_test_del_vif_req(sdev, dev, fw_test, skb);
931 break;
932 case MA_BLOCKACK_IND:
933 slsi_fw_test_ma_blockack_ind(sdev, dev, fw_test, skb);
934 break;
935 default:
936 WARN(1, "Unhandled Signal");
937 slsi_kfree_skb(skb);
938 break;
939 }
940 SLSI_MUTEX_UNLOCK(sdev->netdev_add_remove_mutex);
941
942 skb = slsi_skb_work_dequeue(&fw_test->fw_test_work);
943 }
944 }
945
946 void slsi_fw_test_init(struct slsi_dev *sdev, struct slsi_fw_test *fwtest)
947 {
948 SLSI_DBG1(sdev, SLSI_FW_TEST, "\n");
949 memset(fwtest, 0x00, sizeof(struct slsi_fw_test));
950 fwtest->sdev = sdev;
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);
953 }
954
955 void slsi_fw_test_deinit(struct slsi_dev *sdev, struct slsi_fw_test *fwtest)
956 {
957 int i;
958
959 SLSI_UNUSED_PARAMETER(sdev);
960
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]);
970
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;
975 }
976 slsi_spinlock_unlock(&fwtest->fw_test_lock);
977 memset(fwtest, 0x00, sizeof(struct slsi_fw_test));
978 }