diff options
Diffstat (limited to 'drivers/net/wireless/ath/wil6210/main.c')
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 30 |
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; | |||
25 | module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); | 25 | module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); |
26 | MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery"); | 26 | MODULE_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 | ||
312 | static void wil_target_reset(struct wil6210_priv *wil) | 315 | static 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; |