8ab87ecd9cb0b1a488e67aed5d6df76eba5e716c
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / net / wireless / scsc / cm_if.c
1 /****************************************************************************
2 *
3 * Copyright (c) 2012 - 2019 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 * Chip Manager interface
6 *
7 ****************************************************************************/
8
9 #include "mgt.h"
10 #include "dev.h"
11 #include "debug.h"
12 #include "scsc_wifi_cm_if.h"
13 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
14 #include "hip4_sampler.h"
15 #endif
16
17 #include <scsc/scsc_mx.h>
18 #ifdef CONFIG_SCSC_LOG_COLLECTION
19 #include <scsc/scsc_log_collector.h>
20 #endif
21
22 static bool EnableTestMode;
23 module_param(EnableTestMode, bool, S_IRUGO | S_IWUSR);
24 MODULE_PARM_DESC(EnableTestMode, "Enable WlanLite test mode driver.");
25
26 static BLOCKING_NOTIFIER_HEAD(slsi_wlan_notifier);
27
28 static bool EnableRfTestMode;
29 module_param(EnableRfTestMode, bool, S_IRUGO | S_IWUSR);
30 MODULE_PARM_DESC(EnableRfTestMode, "Enable RF test mode driver.");
31
32 static struct mutex slsi_start_mutex;
33 static int recovery_in_progress;
34 static u16 latest_scsc_panic_code;
35
36 /* TODO: Would be good to get this removed - use module_client? */
37 struct slsi_cm_ctx {
38 struct slsi_dev *sdev;
39 };
40
41 /* Only one wlan service instance is assumed for now. */
42 static struct slsi_cm_ctx cm_ctx;
43
44 static void slsi_hip_block_bh(struct slsi_dev *sdev);
45
46 int slsi_wlan_service_notifier_register(struct notifier_block *nb)
47 {
48 return blocking_notifier_chain_register(&slsi_wlan_notifier, nb);
49 }
50
51 int slsi_wlan_service_notifier_unregister(struct notifier_block *nb)
52 {
53 return blocking_notifier_chain_unregister(&slsi_wlan_notifier, nb);
54 }
55
56 static int wlan_suspend(struct scsc_service_client *client)
57 {
58 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
59
60 SLSI_INFO_NODEV("Nofity registered functions\n");
61 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_SUSPEND, sdev);
62
63 return 0;
64 }
65
66 static int wlan_resume(struct scsc_service_client *client)
67 {
68 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
69
70 SLSI_INFO_NODEV("Nofity registered functions\n");
71 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_RESUME, sdev);
72
73 return 0;
74 }
75
76 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
77 static u8 wlan_failure_notification(struct scsc_service_client *client, struct mx_syserr_decode *err)
78 {
79 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
80 struct netdev_vif *ndev_vif;
81 struct net_device *dev;
82
83 atomic_set(&sdev->cm_if.reset_level, err->level);
84 SLSI_INFO_NODEV("SubSystem:%d,Level:%d,Type:%d,Sub_code:%d\n", err->subsys, err->level, err->type, err->subcode);
85 /* system recovery not tested for p2p. So raise it to highest level for now. */
86 dev = slsi_get_netdev(sdev, SLSI_NET_INDEX_P2PX_SWLAN);
87 if (dev) {
88 ndev_vif = netdev_priv(dev);
89 if (SLSI_IS_VIF_INDEX_P2P_GROUP(sdev, ndev_vif))
90 return SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC;
91 }
92 return err->level;
93 }
94
95 static void wlan_failure_reset_v2(struct scsc_service_client *client, u8 level, u16 scsc_syserr_code)
96 {
97 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
98
99 SLSI_INFO_NODEV("Level:%d scsc_syserr_code:%d\n", level, scsc_syserr_code);
100 mutex_lock(&slsi_start_mutex);
101 atomic_set(&sdev->cm_if.reset_level, level);
102 mutex_unlock(&slsi_start_mutex);
103 if (level < 5)
104 SLSI_WARN_NODEV("Low level error level:%d\n", level);
105 if (level == 5 || level == 6)
106 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_SUBSYSTEM_RESET, sdev);
107 }
108 #endif
109 static void wlan_failure_reset(struct scsc_service_client *client, u16 scsc_panic_code)
110 {
111 SLSI_INFO_NODEV("\n");
112 latest_scsc_panic_code = scsc_panic_code;
113 }
114
115 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
116 static bool wlan_stop_on_failure_v2(struct scsc_service_client *client, struct mx_syserr_decode *err)
117 {
118 int state;
119 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
120
121 SLSI_INFO_NODEV("\n");
122
123 mutex_lock(&slsi_start_mutex);
124 recovery_in_progress = 1;
125 sdev->recovery_status = 1;
126 state = atomic_read(&sdev->cm_if.cm_if_state);
127 atomic_set(&sdev->cm_if.reset_level, err->level);
128 if (state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
129 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED);
130 sdev->fail_reported = true;
131
132 /* If next state is stopped, then don't signal recovery since
133 * the Android framework won't/shouldn't restart (supplicant
134 * stop and start).
135 */
136 if (sdev->recovery_next_state != SCSC_WIFI_CM_IF_STATE_STOPPING) {
137 slsi_hip_block_bh(sdev);
138
139 /* Stop wlan operations. Send event to registered parties */
140 mutex_unlock(&slsi_start_mutex);
141 SLSI_INFO_NODEV("Nofity registered functions\n");
142 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_STOP, sdev);
143 mutex_lock(&slsi_start_mutex);
144 }
145 } else {
146 SLSI_INFO_NODEV("Wi-Fi service driver not started\n");
147 }
148
149 mutex_unlock(&slsi_start_mutex);
150 return true;
151 }
152 #endif
153 static void wlan_stop_on_failure(struct scsc_service_client *client)
154
155 {
156 int state;
157 u8 system_error_level;
158 struct slsi_dev *sdev = container_of(client, struct slsi_dev, mx_wlan_client);
159
160 SLSI_INFO_NODEV("\n");
161
162 mutex_lock(&slsi_start_mutex);
163 recovery_in_progress = 1;
164 sdev->recovery_status = 1;
165 state = atomic_read(&sdev->cm_if.cm_if_state);
166 /* system error level is set in failure_notification. if this is not yet set, consider
167 * a full panic. set it to SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC
168 */
169 system_error_level = atomic_read(&sdev->cm_if.reset_level);
170 if (!system_error_level) {
171 atomic_set(&sdev->cm_if.reset_level, SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC);
172 }
173 if (state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
174 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED);
175 sdev->fail_reported = true;
176
177 /* If next state is stopped, then don't signal recovery since
178 * the Android framework won't/shouldn't restart (supplicant
179 * stop and start).
180 */
181 if (sdev->recovery_next_state != SCSC_WIFI_CM_IF_STATE_STOPPING) {
182 slsi_hip_block_bh(sdev);
183
184 /* Stop wlan operations. Send event to registered parties */
185 mutex_unlock(&slsi_start_mutex);
186 SLSI_INFO_NODEV("Nofity registered functions\n");
187 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_STOP, sdev);
188 mutex_lock(&slsi_start_mutex);
189 }
190 } else {
191 SLSI_INFO_NODEV("Wi-Fi service driver not started\n");
192 }
193
194 mutex_unlock(&slsi_start_mutex);
195 }
196
197 int slsi_check_rf_test_mode(void)
198 {
199 struct file *fp = NULL;
200 #if defined(ANDROID_VERSION) && ANDROID_VERSION >= 90000
201 char *filepath = "/data/vendor/conn/.psm.info";
202 #else
203 char *filepath = "/data/misc/conn/.psm.info";
204 #endif
205 char power_val = 0;
206
207 fp = filp_open(filepath, O_RDONLY, 0);
208 if (IS_ERR(fp) || (!fp)) {
209 pr_err("%s is not exist.\n", filepath);
210 return -ENOENT; /* -2 */
211 }
212
213 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0)
214 kernel_read(fp, &power_val, 1, &fp->f_pos);
215 #else
216 kernel_read(fp, fp->f_pos, &power_val, 1);
217 #endif
218 /* if power_val is 0, it means rf_test mode by rf. */
219 if (power_val == '0') {
220 pr_err("*#rf# is enabled.\n");
221 EnableRfTestMode = 1;
222 } else {
223 pr_err("*#rf# is disabled.\n");
224 EnableRfTestMode = 0;
225 }
226
227 if (fp)
228 filp_close(fp, NULL);
229
230 return 0;
231 }
232
233 /* WLAN service driver registration
234 * ================================
235 */
236 void slsi_wlan_service_probe(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason)
237 {
238 struct slsi_dev *sdev;
239 struct device *dev;
240 struct scsc_service_client mx_wlan_client;
241 #ifdef CONFIG_SCSC_LOG_COLLECTION
242 char buf[SCSC_LOG_FAPI_VERSION_SIZE];
243 #endif
244
245 SLSI_UNUSED_PARAMETER(module_client);
246
247 SLSI_INFO_NODEV("WLAN service probe\n");
248
249 mutex_lock(&slsi_start_mutex);
250
251 if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress)
252 goto done;
253
254 if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY) {
255 SLSI_INFO_NODEV("Probe recovery\n");
256 sdev = cm_ctx.sdev;
257 recovery_in_progress = 0;
258 sdev->fail_reported = false;
259 sdev->recovery_status = 0;
260 sdev->mlme_blocked = false;
261 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
262 mutex_unlock(&slsi_start_mutex);
263 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_CHIP_READY, sdev);
264 mutex_lock(&slsi_start_mutex);
265 #endif
266 complete_all(&sdev->recovery_completed);
267 } else {
268 /* Register callbacks */
269 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
270 mx_wlan_client.failure_notification = wlan_failure_notification;
271 mx_wlan_client.stop_on_failure_v2 = wlan_stop_on_failure_v2;
272 mx_wlan_client.failure_reset_v2 = wlan_failure_reset_v2;
273 #endif
274 mx_wlan_client.stop_on_failure = wlan_stop_on_failure;
275 mx_wlan_client.failure_reset = wlan_failure_reset;
276 mx_wlan_client.suspend = wlan_suspend;
277 mx_wlan_client.resume = wlan_resume;
278
279 dev = scsc_service_get_device_by_mx(mx);
280
281 /* The mutex must be released at this point since the attach
282 * process may call various functions including
283 * slsi_sm_wlan_service_start and slsi_sm_wlan_service_open, which will
284 * claim the same mutex.
285 */
286 mutex_unlock(&slsi_start_mutex);
287 sdev = slsi_dev_attach(dev, mx, &mx_wlan_client);
288 mutex_lock(&slsi_start_mutex);
289 if (!sdev) {
290 SLSI_ERR_NODEV("WLAN attach failed - slsi_dev_attach\n");
291 goto done;
292 }
293
294 cm_ctx.sdev = sdev; /* TODO: For now. */
295
296 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBING);
297 get_device(dev);
298
299 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
300 hip4_sampler_create(sdev, mx);
301 #endif
302 #ifdef CONFIG_SCSC_LOG_COLLECTION
303 memset(buf, 0, SCSC_LOG_FAPI_VERSION_SIZE);
304 /* Write FAPI VERSION to collector header */
305 /* IMPORTANT - Do not change the formatting as User space tooling is parsing the string
306 * to read SAP fapi versions.
307 */
308 snprintf(buf, SCSC_LOG_FAPI_VERSION_SIZE, "ma:%u.%u, mlme:%u.%u, debug:%u.%u, test:%u.%u",
309 FAPI_MAJOR_VERSION(FAPI_DATA_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DATA_SAP_VERSION),
310 FAPI_MAJOR_VERSION(FAPI_CONTROL_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_CONTROL_SAP_VERSION),
311 FAPI_MAJOR_VERSION(FAPI_DEBUG_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_DEBUG_SAP_VERSION),
312 FAPI_MAJOR_VERSION(FAPI_TEST_SAP_VERSION), FAPI_MINOR_VERSION(FAPI_TEST_SAP_VERSION));
313
314 scsc_log_collector_write_fapi(buf, SCSC_LOG_FAPI_VERSION_SIZE);
315 #endif
316 }
317
318 if (reason != SCSC_MODULE_CLIENT_REASON_RECOVERY)
319 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBED);
320 atomic_set(&sdev->cm_if.reset_level, 0);
321 done:
322 mutex_unlock(&slsi_start_mutex);
323 }
324
325 /* service_clean_up_locked expects the slsi_start_mutex mutex to be claimed when
326 * service_clean_up_locked is called.
327 */
328 static void service_clean_up_locked(struct slsi_dev *sdev)
329 {
330 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_REMOVING);
331 put_device(sdev->dev);
332
333 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_REMOVED);
334
335 sdev->maxwell_core = NULL;
336
337 /* The mutex must be released at this point since the tear down
338 * process will call various functions including
339 * slsi_sm_wlan_service_stop and slsi_sm_wlan_service_close, which will
340 * claim the same mutex.
341 */
342 mutex_unlock(&slsi_start_mutex);
343 slsi_dev_detach(sdev);
344 mutex_lock(&slsi_start_mutex);
345 }
346
347 static void slsi_wlan_service_remove(struct scsc_mx_module_client *module_client, struct scsc_mx *mx, enum scsc_module_client_reason reason)
348 {
349 struct slsi_dev *sdev;
350 int state;
351 int level = 0;
352
353 SLSI_UNUSED_PARAMETER(mx);
354 SLSI_UNUSED_PARAMETER(module_client);
355
356 sdev = cm_ctx.sdev;
357 if (!sdev) {
358 SLSI_INFO_NODEV("no sdev\n");
359 return;
360 }
361
362 if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && !recovery_in_progress) {
363 SLSI_INFO_NODEV("WLAN service remove - recovery. Service not active.\n");
364 } else if (reason == SCSC_MODULE_CLIENT_REASON_RECOVERY && recovery_in_progress) {
365 int r;
366
367 SLSI_INFO_NODEV("WLAN service remove - recovery\n");
368
369 /* Only indicate if the next state is not stopping. The recovery
370 * handling won't have any affect if the framework is closing
371 * anyway.
372 */
373 if (sdev->recovery_next_state != SCSC_WIFI_CM_IF_STATE_STOPPING) {
374 SLSI_INFO_NODEV("Nofity registered functions\n");
375 blocking_notifier_call_chain(&slsi_wlan_notifier, SCSC_WIFI_FAILURE_RESET, sdev);
376 }
377 #ifdef CONFIG_SCSC_WLAN_SILENT_RECOVERY
378 level = atomic_read(&sdev->cm_if.reset_level);
379 #endif
380 if (level == SLSI_WIFI_CM_IF_SYSTEM_ERROR_PANIC) {
381 mutex_lock(&slsi_start_mutex);
382 /**
383 * If there was a request to stop during the recovery, then do
384 * not sent a hang - just stop here. The Wi-Fi service driver is
385 * ready to be turned on again. Let the service_stop complete.
386 */
387 complete_all(&sdev->recovery_remove_completion);
388 if (sdev->recovery_next_state == SCSC_WIFI_CM_IF_STATE_STOPPING) {
389 SLSI_INFO_NODEV("Recovery - next state stopping\n");
390 } else {
391 SLSI_INFO_NODEV("Calling slsi_send_hanged_vendor_event with latest_scsc_panic_code=0x%x\n",
392 latest_scsc_panic_code);
393 if (slsi_send_hanged_vendor_event(sdev, latest_scsc_panic_code) < 0)
394 SLSI_ERR(sdev, "Failed to send hang event\n");
395
396 /* Complete any pending ctrl signals, which will prevent
397 * the hang event from being processed.
398 */
399 complete_all(&sdev->sig_wait.completion);
400 }
401
402 mutex_unlock(&slsi_start_mutex);
403
404 r = wait_for_completion_timeout(&sdev->recovery_stop_completion,
405 msecs_to_jiffies(sdev->recovery_timeout));
406 if (r == 0)
407 SLSI_INFO(sdev, "recovery_stop_completion timeout\n");
408 }
409 mutex_lock(&slsi_start_mutex);
410 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
411 reinit_completion(&sdev->recovery_stop_completion);
412 #else
413 /*This is how the macro is used in the older verion.*/
414 INIT_COMPLETION(sdev->recovery_stop_completion);
415 #endif
416 mutex_unlock(&slsi_start_mutex);
417
418 } else {
419 SLSI_INFO_NODEV("WLAN service remove\n");
420
421 #ifdef CONFIG_SCSC_WLAN_HIP4_PROFILING
422 hip4_sampler_destroy(sdev, mx);
423 #endif
424
425 mutex_lock(&slsi_start_mutex);
426 state = atomic_read(&sdev->cm_if.cm_if_state);
427 if (state != SCSC_WIFI_CM_IF_STATE_STARTED &&
428 state != SCSC_WIFI_CM_IF_STATE_PROBED &&
429 state != SCSC_WIFI_CM_IF_STATE_STOPPED &&
430 state != SCSC_WIFI_CM_IF_STATE_BLOCKED) {
431 mutex_unlock(&slsi_start_mutex);
432 SLSI_INFO_NODEV("state-event error %d\n", state);
433 return;
434 }
435
436 service_clean_up_locked(sdev);
437 mutex_unlock(&slsi_start_mutex);
438 }
439 }
440
441 /* Block future HIP runs through the hip_switch */
442 static void slsi_hip_block_bh(struct slsi_dev *sdev)
443 {
444 SLSI_WARN(sdev, "HIP state set to #SLSI_HIP_STATE_BLOCKED#\n");
445 atomic_set(&sdev->hip.hip_state, SLSI_HIP_STATE_BLOCKED);
446 }
447
448 struct scsc_mx_module_client wlan_driver = {
449 .name = "WLAN driver",
450 .probe = slsi_wlan_service_probe,
451 .remove = slsi_wlan_service_remove,
452 };
453
454 int slsi_sm_service_driver_register(void)
455 {
456 struct slsi_cm_ctx *ctx = &cm_ctx;
457
458 memset(ctx, 0, sizeof(*ctx));
459 mutex_init(&slsi_start_mutex);
460 scsc_mx_module_register_client_module(&wlan_driver);
461
462 return 0;
463 }
464
465 void slsi_sm_service_driver_unregister(void)
466 {
467 scsc_mx_module_unregister_client_module(&wlan_driver);
468 }
469
470 /* start/stop wlan service
471 * =======================
472 */
473 void slsi_sm_service_failed(struct slsi_dev *sdev, const char *reason)
474 {
475 int state;
476
477 mutex_lock(&slsi_start_mutex);
478
479 state = atomic_read(&sdev->cm_if.cm_if_state);
480 if (state != SCSC_WIFI_CM_IF_STATE_STARTED &&
481 state != SCSC_WIFI_CM_IF_STATE_STOPPING) {
482 mutex_unlock(&slsi_start_mutex);
483 SLSI_INFO(sdev, "State %d - ignoring event\n", state);
484 return;
485 }
486
487 /* Limit the volume of error reports to the core */
488 if (!sdev->fail_reported) {
489 /* This log may be scraped by test systems */
490 SLSI_ERR(sdev, "scsc_wifibt: FATAL ERROR: %s\n", reason);
491
492 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_BLOCKED);
493 slsi_hip_block_bh(sdev);
494 scsc_mx_service_service_failed(sdev->service, reason);
495 scsc_mx_service_mif_dump_registers(sdev->service);
496 sdev->fail_reported = true;
497 }
498
499 mutex_unlock(&slsi_start_mutex);
500 }
501
502 /* Is production test mode enabled? */
503 bool slsi_is_test_mode_enabled(void)
504 {
505 return EnableTestMode;
506 }
507
508 /* Is production rf test mode enabled? */
509 bool slsi_is_rf_test_mode_enabled(void)
510 {
511 return EnableRfTestMode;
512 }
513
514 #define SLSI_SM_WLAN_SERVICE_RECOVERY_COMPLETED_TIMEOUT 20000
515 #define SLSI_SM_WLAN_SERVICE_RECOVERY_DISABLED_TIMEOUT 2000
516
517 int slsi_sm_recovery_service_stop(struct slsi_dev *sdev)
518 {
519 int err = 0;
520
521 mutex_lock(&slsi_start_mutex);
522 SLSI_INFO_NODEV("Stopping WLAN service\n");
523 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPING);
524 err = scsc_mx_service_stop(sdev->service);
525 if (err == -EILSEQ || err == -EIO)
526 SLSI_INFO(sdev, "scsc_mx_service_stop failed err: %d\n", err);
527 else
528 err = 0;
529 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
530 mutex_unlock(&slsi_start_mutex);
531 return err;
532 }
533
534 int slsi_sm_recovery_service_close(struct slsi_dev *sdev)
535 {
536 int err = 0;
537
538 mutex_lock(&slsi_start_mutex);
539 SLSI_INFO_NODEV("Closing WLAN service\n");
540 err = scsc_mx_service_close(sdev->service);
541 if (err == -EILSEQ || err == -EIO)
542 SLSI_INFO(sdev, "scsc_mx_service_close failed err: %d\n", err);
543 else
544 err = 0;
545 mutex_unlock(&slsi_start_mutex);
546 return err;
547 }
548
549 int slsi_sm_recovery_service_open(struct slsi_dev *sdev)
550 {
551 int err = 0;
552
553 mutex_lock(&slsi_start_mutex);
554 SLSI_INFO_NODEV("Open WLAN service\n");
555 sdev->service = scsc_mx_service_open(sdev->maxwell_core, SCSC_SERVICE_ID_WLAN, &sdev->mx_wlan_client, &err);
556 if (err == -EILSEQ || err == -EIO)
557 SLSI_INFO(sdev, "scsc_mx_service_open failed err: %d\n", err);
558 else
559 err = 0;
560 mutex_unlock(&slsi_start_mutex);
561 return err;
562 }
563
564 int slsi_sm_recovery_service_start(struct slsi_dev *sdev)
565 {
566 int err = 0, err2 = 0;
567 struct slsi_hip4 *hip = &sdev->hip4_inst;
568 scsc_mifram_ref ref;
569 int state;
570
571 mutex_lock(&slsi_start_mutex);
572 state = atomic_read(&sdev->cm_if.cm_if_state);
573 SLSI_INFO(sdev,
574 "Recovery -- Status:%d In_Progress:%d -- cm_if_state:%d\n",
575 sdev->recovery_status, recovery_in_progress, state);
576 if (state != SCSC_WIFI_CM_IF_STATE_PROBED &&
577 state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
578 SLSI_INFO(sdev, "State-event error %d\n", state);
579 mutex_unlock(&slsi_start_mutex);
580 return -EINVAL;
581 }
582
583 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTING);
584 #ifdef CONFIG_SCSC_PCIE
585 err = scsc_mx_service_mifram_alloc(sdev->service, 1.5 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096);
586 #else
587 err = scsc_mx_service_mifram_alloc(sdev->service, 2 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096);
588 #endif
589 if (err) {
590 SLSI_WARN(sdev, "scsc_mx_service_mifram_alloc failed err: %d\n", err);
591 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
592 mutex_unlock(&slsi_start_mutex);
593 return err;
594 }
595
596 err = slsi_hip_start(sdev);
597 if (err) {
598 SLSI_WARN(sdev, "slsi_hip_start failed err: %d\n", err);
599 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
600 slsi_hip_stop(sdev);
601 mutex_unlock(&slsi_start_mutex);
602 return err;
603 }
604
605 err = scsc_mx_service_mif_ptr_to_addr(sdev->service, hip->hip_control, &ref);
606 if (err) {
607 SLSI_WARN(sdev, "scsc_mx_service_mif_ptr_to_addr failed err: %d\n", err);
608 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
609 slsi_hip_stop(sdev);
610 mutex_unlock(&slsi_start_mutex);
611 return err;
612 }
613
614
615 err = scsc_mx_service_start(sdev->service, ref);
616 if (err) {
617 SLSI_WARN(sdev, "scsc_mx_service_start failed err: %d\n", err);
618 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
619 slsi_hip_stop(sdev);
620 mutex_unlock(&slsi_start_mutex);
621 return err;
622 }
623 err = slsi_hip_setup(sdev);
624 if (err) {
625 SLSI_WARN(sdev, "slsi_hip_setup failed err: %d\n", err);
626 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
627 err2 = scsc_mx_service_stop(sdev->service);
628 if (err2)
629 SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2);
630 slsi_hip_stop(sdev);
631 mutex_unlock(&slsi_start_mutex);
632 return err;
633 }
634
635 /* Service has started, inform SAP versions to the registered SAPs */
636 err = slsi_hip_sap_setup(sdev);
637 if (err) {
638 SLSI_WARN(sdev, "slsi_hip_sap_setup failed err: %d\n", err);
639 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
640 err2 = scsc_mx_service_stop(sdev->service);
641 if (err2)
642 SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2);
643 slsi_hip_stop(sdev);
644 mutex_unlock(&slsi_start_mutex);
645 return err;
646 }
647 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTED);
648 mutex_unlock(&slsi_start_mutex);
649 return err;
650 }
651
652 int slsi_sm_wlan_service_open(struct slsi_dev *sdev)
653 {
654 int err = 0;
655 int state;
656
657 mutex_lock(&slsi_start_mutex);
658 state = atomic_read(&sdev->cm_if.cm_if_state);
659 if (state != SCSC_WIFI_CM_IF_STATE_PROBED &&
660 state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
661 SLSI_INFO(sdev, "State-event error %d\n", state);
662 err = -EINVAL;
663 goto exit;
664 }
665
666 sdev->recovery_timeout = mxman_recovery_disabled() ? SLSI_SM_WLAN_SERVICE_RECOVERY_DISABLED_TIMEOUT : SLSI_SM_WLAN_SERVICE_RECOVERY_COMPLETED_TIMEOUT;
667
668 /* Open service - will download FW - will set MBOX0 with Starting address */
669 SLSI_INFO(sdev, "Open WLAN service\n");
670 sdev->service = scsc_mx_service_open(sdev->maxwell_core, SCSC_SERVICE_ID_WLAN, &sdev->mx_wlan_client, &err);
671 if (!sdev->service) {
672 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_PROBED);
673 SLSI_WARN(sdev, "Service open failed\n");
674 err = -EINVAL;
675 goto exit;
676 }
677
678 exit:
679 mutex_unlock(&slsi_start_mutex);
680 return err;
681 }
682
683 #if defined(CONFIG_SLUB_DEBUG_ON) || defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_DEBUG_RT_MUTEXES) || \
684 defined(CONFIG_DEBUG_SPINLOCK) && defined(CONFIG_DEBUG_MUTEXES) && defined(CONFIG_DEBUG_LOCK_ALLOC) || \
685 defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_DEBUG_ATOMIC_SLEEP) && defined(CONFIG_DEBUG_LIST)
686 #define KERNEL_DEBUG_OPTIONS_ENABLED
687 #endif
688
689 int slsi_sm_wlan_service_start(struct slsi_dev *sdev)
690 {
691 struct slsi_hip4 *hip = &sdev->hip4_inst;
692 scsc_mifram_ref ref;
693 int err = 0;
694 int err2 = 0;
695 int state;
696
697 mutex_lock(&slsi_start_mutex);
698 state = atomic_read(&sdev->cm_if.cm_if_state);
699 SLSI_INFO(sdev,
700 "Recovery -- Status:%d In_Progress:%d -- cm_if_state:%d\n",
701 sdev->recovery_status, recovery_in_progress, state);
702 if (state != SCSC_WIFI_CM_IF_STATE_PROBED &&
703 state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
704 SLSI_INFO(sdev, "State-event error %d\n", state);
705 mutex_unlock(&slsi_start_mutex);
706 return -EINVAL;
707 }
708
709 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTING);
710
711 #ifdef KERNEL_DEBUG_OPTIONS_ENABLED
712 SLSI_WARN(sdev, "Kernel config debug options are enabled. This might impact the throughput performance.\n");
713 #endif
714
715 /* Get RAM from the MIF */
716 SLSI_INFO(sdev, "Allocate mifram\n");
717
718 #ifdef CONFIG_SCSC_PCIE
719 err = scsc_mx_service_mifram_alloc(sdev->service, 1.5 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096);
720 #else
721 err = scsc_mx_service_mifram_alloc(sdev->service, 2 * 1024 * 1024, &sdev->hip4_inst.hip_ref, 4096);
722 #endif
723 if (err) {
724 SLSI_WARN(sdev, "scsc_mx_service_mifram_alloc failed err: %d\n", err);
725 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
726 mutex_unlock(&slsi_start_mutex);
727 return err;
728 }
729
730 SLSI_INFO(sdev, "Start HIP\n");
731 err = slsi_hip_start(sdev);
732 if (err) {
733 SLSI_WARN(sdev, "slsi_hip_start failed err: %d\n", err);
734 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
735 slsi_hip_stop(sdev);
736 mutex_unlock(&slsi_start_mutex);
737 return err;
738 }
739
740 err = scsc_mx_service_mif_ptr_to_addr(sdev->service, hip->hip_control, &ref);
741 if (err) {
742 SLSI_WARN(sdev, "scsc_mx_service_mif_ptr_to_addr failed err: %d\n", err);
743 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
744 slsi_hip_stop(sdev);
745 mutex_unlock(&slsi_start_mutex);
746 return err;
747 }
748
749 SLSI_INFO(sdev, "Starting WLAN service\n");
750 err = scsc_mx_service_start(sdev->service, ref);
751 if (err) {
752 SLSI_WARN(sdev, "scsc_mx_service_start failed err: %d\n", err);
753 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
754 slsi_hip_stop(sdev);
755 mutex_unlock(&slsi_start_mutex);
756 return err;
757 }
758 err = slsi_hip_setup(sdev);
759 if (err) {
760 SLSI_WARN(sdev, "slsi_hip_setup failed err: %d\n", err);
761 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
762 SLSI_INFO_NODEV("Stopping WLAN service\n");
763 err2 = scsc_mx_service_stop(sdev->service);
764 if (err2)
765 SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2);
766 slsi_hip_stop(sdev);
767 mutex_unlock(&slsi_start_mutex);
768 return err;
769 }
770 /* Service has started, inform SAP versions to the registered SAPs */
771 err = slsi_hip_sap_setup(sdev);
772 if (err) {
773 SLSI_WARN(sdev, "slsi_hip_sap_setup failed err: %d\n", err);
774 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
775 SLSI_INFO_NODEV("Stopping WLAN service\n");
776 err2 = scsc_mx_service_stop(sdev->service);
777 if (err2)
778 SLSI_INFO(sdev, "scsc_mx_service_stop failed err2: %d\n", err2);
779 slsi_hip_stop(sdev);
780 mutex_unlock(&slsi_start_mutex);
781 return err;
782 }
783 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STARTED);
784 mutex_unlock(&slsi_start_mutex);
785 return 0;
786 }
787
788 static void __slsi_sm_wlan_service_stop_wait_locked(struct slsi_dev *sdev)
789 {
790 int r;
791
792 mutex_unlock(&slsi_start_mutex);
793 r = wait_for_completion_timeout(&sdev->recovery_remove_completion,
794 msecs_to_jiffies(sdev->recovery_timeout));
795 if (r == 0)
796 SLSI_INFO(sdev, "recovery_remove_completion timeout\n");
797
798 mutex_lock(&slsi_start_mutex);
799 sdev->recovery_next_state = SCSC_WIFI_CM_IF_STATE_STOPPED;
800
801 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
802 reinit_completion(&sdev->recovery_remove_completion);
803 #else
804 /*This is how the macro is used in the older verion.*/
805 INIT_COMPLETION(sdev->recovery_remove_completion);
806 #endif
807 }
808
809 void slsi_sm_wlan_service_stop(struct slsi_dev *sdev)
810 {
811 int cm_if_state;
812 int err = 0;
813
814 mutex_lock(&slsi_start_mutex);
815 cm_if_state = atomic_read(&sdev->cm_if.cm_if_state);
816 SLSI_INFO(sdev,
817 "Recovery -- Status:%d In_Progress:%d -- cm_if_state:%d\n",
818 sdev->recovery_status, recovery_in_progress, cm_if_state);
819
820 if (cm_if_state == SCSC_WIFI_CM_IF_STATE_BLOCKED) {
821 __slsi_sm_wlan_service_stop_wait_locked(sdev);
822
823 /* If the wait hasn't timed out, the recovery remove completion
824 * will have completed properly and the cm_if_state will be
825 * set to stopped here. If the probe hasn't fired for some reason
826 * try and do a service_stop regardless, since that's all we can
827 * do in this situation; hence skip the state check.
828 */
829 goto skip_state_check;
830 }
831
832 if (cm_if_state != SCSC_WIFI_CM_IF_STATE_STARTED &&
833 cm_if_state != SCSC_WIFI_CM_IF_STATE_REMOVED &&
834 cm_if_state != SCSC_WIFI_CM_IF_STATE_PROBED) {
835 SLSI_INFO(sdev, "Service not started or incorrect state %d\n",
836 cm_if_state);
837 goto exit;
838 }
839
840 /**
841 * Note that the SCSC_WIFI_CM_IF_STATE_STOPPING state will inhibit
842 * auto-recovery mechanism, so be careful not to abuse it: as an
843 * example if panic happens on start or stop we don't want to
844 * un-necessarily pass by STOPPING in order to have a successful
845 * recovery in such a situation.
846 */
847 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPING);
848 skip_state_check:
849 SLSI_INFO_NODEV("Stopping WLAN service\n");
850 err = scsc_mx_service_stop(sdev->service);
851 if (err == -EILSEQ) {
852 /* scsc_mx_service_stop failed since there's a recovery in
853 * progress, so just wait for it to complete and try again.
854 */
855 SLSI_INFO(sdev, "scsc_mx_service_stop failed err: %d\n", err);
856 __slsi_sm_wlan_service_stop_wait_locked(sdev);
857 goto skip_state_check;
858 } else if (err == -EIO) {
859 char reason[80];
860
861 SLSI_INFO(sdev, "scsc_mx_service_stop failed err: %d\n", err);
862
863 /* scsc_mx_service_stop since there was no respons from firmware
864 * to the stop request. Generate a host initiated panic to reset
865 * the chip and wait for it to complete.
866 */
867 sdev->recovery_next_state = SCSC_WIFI_CM_IF_STATE_STOPPING;
868 snprintf(reason, sizeof(reason), "WLAN scsc_mx_service_stop failed");
869
870 mutex_unlock(&slsi_start_mutex);
871 slsi_sm_service_failed(sdev, reason);
872 mutex_lock(&slsi_start_mutex);
873
874 __slsi_sm_wlan_service_stop_wait_locked(sdev);
875 } else if (err == -EPERM) {
876 /* Special case when recovery is disabled, otherwise the driver
877 * will wait forever for recovery that never comes
878 */
879 SLSI_INFO(sdev, "refused due to previous failure, recovery is disabled: %d\n", err);
880 } else if (err != 0) {
881 SLSI_INFO(sdev, "scsc_mx_service_stop failed, unknown err: %d\n", err);
882 }
883
884 atomic_set(&sdev->cm_if.cm_if_state, SCSC_WIFI_CM_IF_STATE_STOPPED);
885 exit:
886 mutex_unlock(&slsi_start_mutex);
887 }
888
889 #define SLSI_SM_WLAN_SERVICE_CLOSE_RETRY 60
890 void slsi_sm_wlan_service_close(struct slsi_dev *sdev)
891 {
892 int cm_if_state, r;
893
894 mutex_lock(&slsi_start_mutex);
895 cm_if_state = atomic_read(&sdev->cm_if.cm_if_state);
896 if (cm_if_state != SCSC_WIFI_CM_IF_STATE_STOPPED) {
897 SLSI_INFO(sdev, "Service not stopped. cm_if_state = %d\n", cm_if_state);
898
899 /**
900 * Close the service if failure has occurred after service has successfully opened
901 * but before service has attempted to start
902 */
903 if (cm_if_state == SCSC_WIFI_CM_IF_STATE_PROBED) {
904 SLSI_INFO_NODEV("Closing WLAN service on error\n");
905 r = scsc_mx_service_close(sdev->service);
906 }
907 goto exit;
908 }
909
910 SLSI_INFO_NODEV("Closing WLAN service\n");
911 scsc_mx_service_mifram_free(sdev->service, sdev->hip4_inst.hip_ref);
912
913 r = scsc_mx_service_close(sdev->service);
914 if (r == -EIO) {
915 int retry_counter;
916
917 /**
918 * Error handling in progress - try and close again later.
919 * The service close call shall remain blocked until close
920 * service is successful. Try up to 30 seconds.
921 */
922 for (retry_counter = 0;
923 SLSI_SM_WLAN_SERVICE_CLOSE_RETRY > retry_counter;
924 retry_counter++) {
925 msleep(500);
926 r = scsc_mx_service_close(sdev->service);
927 if (r == 0) {
928 SLSI_INFO(sdev, "scsc_mx_service_close closed after %d attempts\n",
929 retry_counter + 1);
930 break;
931 }
932 }
933
934 if (retry_counter + 1 == SLSI_SM_WLAN_SERVICE_CLOSE_RETRY)
935 SLSI_ERR(sdev, "scsc_mx_service_close failed %d times\n",
936 SLSI_SM_WLAN_SERVICE_CLOSE_RETRY);
937 } else if (r == -EPERM) {
938 SLSI_ERR(sdev, "scsc_mx_service_close - recovery is disabled (%d)\n", r);
939 }
940
941 if (recovery_in_progress)
942 complete_all(&sdev->recovery_stop_completion);
943 exit:
944 mutex_unlock(&slsi_start_mutex);
945 }