aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/wil6210/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/main.c')
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 3704d2a434f3..b69d90f0716f 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2012 Qualcomm Atheros, Inc. 2 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
3 * 3 *
4 * Permission to use, copy, modify, and/or distribute this software for any 4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 5 * purpose with or without fee is hereby granted, provided that the above
@@ -25,6 +25,9 @@ static bool no_fw_recovery;
25module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); 25module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
26MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery"); 26MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery");
27 27
28#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
29#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
30
28/* 31/*
29 * Due to a hardware issue, 32 * Due to a hardware issue,
30 * one has to read/write to/from NIC in 32-bit chunks; 33 * one has to read/write to/from NIC in 32-bit chunks;
@@ -309,7 +312,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
309 destroy_workqueue(wil->wmi_wq); 312 destroy_workqueue(wil->wmi_wq);
310} 313}
311 314
312static void wil_target_reset(struct wil6210_priv *wil) 315static int wil_target_reset(struct wil6210_priv *wil)
313{ 316{
314 int delay = 0; 317 int delay = 0;
315 u32 hw_state; 318 u32 hw_state;
@@ -327,6 +330,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
327 /* register clear = read, AND with inverted, write */ 330 /* register clear = read, AND with inverted, write */
328#define C(a, v) W(a, R(a) & ~v) 331#define C(a, v) W(a, R(a) & ~v)
329 332
333 wmb(); /* If host reorder writes here -> race in NIC */
334 W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
330 wil->hw_version = R(RGF_USER_FW_REV_ID); 335 wil->hw_version = R(RGF_USER_FW_REV_ID);
331 rev_id = wil->hw_version & 0xff; 336 rev_id = wil->hw_version & 0xff;
332 337
@@ -343,8 +348,9 @@ static void wil_target_reset(struct wil6210_priv *wil)
343 wmb(); /* order is important here */ 348 wmb(); /* order is important here */
344 } 349 }
345 350
346 W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
347 W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ 351 W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
352 wmb(); /* If host reorder writes here -> race in NIC */
353 W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
348 wmb(); /* order is important here */ 354 wmb(); /* order is important here */
349 355
350 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); 356 W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
@@ -385,14 +391,14 @@ static void wil_target_reset(struct wil6210_priv *wil)
385 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); 391 W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
386 wmb(); /* order is important here */ 392 wmb(); /* order is important here */
387 393
388 /* wait until device ready */ 394 /* wait until device ready. typical time is 200..250 msec */
389 do { 395 do {
390 msleep(1); 396 msleep(RST_DELAY);
391 hw_state = R(RGF_USER_HW_MACHINE_STATE); 397 hw_state = R(RGF_USER_HW_MACHINE_STATE);
392 if (delay++ > 100) { 398 if (delay++ > RST_COUNT) {
393 wil_err(wil, "Reset not completed, hw_state 0x%08x\n", 399 wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
394 hw_state); 400 hw_state);
395 return; 401 return -ETIME;
396 } 402 }
397 } while (hw_state != HW_MACHINE_BOOT_DONE); 403 } while (hw_state != HW_MACHINE_BOOT_DONE);
398 404
@@ -403,7 +409,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
403 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); 409 C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
404 wmb(); /* order is important here */ 410 wmb(); /* order is important here */
405 411
406 wil_dbg_misc(wil, "Reset completed in %d ms\n", delay); 412 wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY);
413 return 0;
407 414
408#undef R 415#undef R
409#undef W 416#undef W
@@ -468,10 +475,11 @@ int wil_reset(struct wil6210_priv *wil)
468 flush_workqueue(wil->wmi_wq_conn); 475 flush_workqueue(wil->wmi_wq_conn);
469 flush_workqueue(wil->wmi_wq); 476 flush_workqueue(wil->wmi_wq);
470 477
471 /* TODO: put MAC in reset */ 478 rc = wil_target_reset(wil);
472 wil_target_reset(wil);
473
474 wil_rx_fini(wil); 479 wil_rx_fini(wil);
480 if (rc)
481 return rc;
482
475 483
476 /* init after reset */ 484 /* init after reset */
477 wil->pending_connect_cid = -1; 485 wil->pending_connect_cid = -1;