diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 41 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 6 |
4 files changed, 51 insertions, 42 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 6dfed1259260..56254a837214 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
@@ -32,7 +32,7 @@ | |||
32 | * BSD LICENSE | 32 | * BSD LICENSE |
33 | * | 33 | * |
34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. | 34 | * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
36 | * All rights reserved. | 36 | * All rights reserved. |
37 | * | 37 | * |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without |
@@ -421,8 +421,9 @@ struct iwl_trans_txq_scd_cfg { | |||
421 | * | 421 | * |
422 | * All the handlers MUST be implemented | 422 | * All the handlers MUST be implemented |
423 | * | 423 | * |
424 | * @start_hw: starts the HW- from that point on, the HW can send interrupts | 424 | * @start_hw: starts the HW. If low_power is true, the NIC needs to be taken |
425 | * May sleep | 425 | * out of a low power state. From that point on, the HW can send |
426 | * interrupts. May sleep. | ||
426 | * @op_mode_leave: Turn off the HW RF kill indication if on | 427 | * @op_mode_leave: Turn off the HW RF kill indication if on |
427 | * May sleep | 428 | * May sleep |
428 | * @start_fw: allocates and inits all the resources for the transport | 429 | * @start_fw: allocates and inits all the resources for the transport |
@@ -432,10 +433,11 @@ struct iwl_trans_txq_scd_cfg { | |||
432 | * the SCD base address in SRAM, then provide it here, or 0 otherwise. | 433 | * the SCD base address in SRAM, then provide it here, or 0 otherwise. |
433 | * May sleep | 434 | * May sleep |
434 | * @stop_device: stops the whole device (embedded CPU put to reset) and stops | 435 | * @stop_device: stops the whole device (embedded CPU put to reset) and stops |
435 | * the HW. From that point on, the HW will be in low power but will still | 436 | * the HW. If low_power is true, the NIC will be put in low power state. |
436 | * issue interrupt if the HW RF kill is triggered. This callback must do | 437 | * From that point on, the HW will be stopped but will still issue an |
437 | * the right thing and not crash even if start_hw() was called but not | 438 | * interrupt if the HW RF kill switch is triggered. |
438 | * start_fw(). May sleep | 439 | * This callback must do the right thing and not crash even if %start_hw() |
440 | * was called but not &start_fw(). May sleep. | ||
439 | * @d3_suspend: put the device into the correct mode for WoWLAN during | 441 | * @d3_suspend: put the device into the correct mode for WoWLAN during |
440 | * suspend. This is optional, if not implemented WoWLAN will not be | 442 | * suspend. This is optional, if not implemented WoWLAN will not be |
441 | * supported. This callback may sleep. | 443 | * supported. This callback may sleep. |
@@ -491,14 +493,14 @@ struct iwl_trans_txq_scd_cfg { | |||
491 | */ | 493 | */ |
492 | struct iwl_trans_ops { | 494 | struct iwl_trans_ops { |
493 | 495 | ||
494 | int (*start_hw)(struct iwl_trans *iwl_trans); | 496 | int (*start_hw)(struct iwl_trans *iwl_trans, bool low_power); |
495 | void (*op_mode_leave)(struct iwl_trans *iwl_trans); | 497 | void (*op_mode_leave)(struct iwl_trans *iwl_trans); |
496 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, | 498 | int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw, |
497 | bool run_in_rfkill); | 499 | bool run_in_rfkill); |
498 | int (*update_sf)(struct iwl_trans *trans, | 500 | int (*update_sf)(struct iwl_trans *trans, |
499 | struct iwl_sf_region *st_fwrd_space); | 501 | struct iwl_sf_region *st_fwrd_space); |
500 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); | 502 | void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); |
501 | void (*stop_device)(struct iwl_trans *trans); | 503 | void (*stop_device)(struct iwl_trans *trans, bool low_power); |
502 | 504 | ||
503 | void (*d3_suspend)(struct iwl_trans *trans, bool test); | 505 | void (*d3_suspend)(struct iwl_trans *trans, bool test); |
504 | int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, | 506 | int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, |
@@ -652,11 +654,16 @@ static inline void iwl_trans_configure(struct iwl_trans *trans, | |||
652 | trans->ops->configure(trans, trans_cfg); | 654 | trans->ops->configure(trans, trans_cfg); |
653 | } | 655 | } |
654 | 656 | ||
655 | static inline int iwl_trans_start_hw(struct iwl_trans *trans) | 657 | static inline int _iwl_trans_start_hw(struct iwl_trans *trans, bool low_power) |
656 | { | 658 | { |
657 | might_sleep(); | 659 | might_sleep(); |
658 | 660 | ||
659 | return trans->ops->start_hw(trans); | 661 | return trans->ops->start_hw(trans, low_power); |
662 | } | ||
663 | |||
664 | static inline int iwl_trans_start_hw(struct iwl_trans *trans) | ||
665 | { | ||
666 | return trans->ops->start_hw(trans, true); | ||
660 | } | 667 | } |
661 | 668 | ||
662 | static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans) | 669 | static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans) |
@@ -703,15 +710,21 @@ static inline int iwl_trans_update_sf(struct iwl_trans *trans, | |||
703 | return 0; | 710 | return 0; |
704 | } | 711 | } |
705 | 712 | ||
706 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) | 713 | static inline void _iwl_trans_stop_device(struct iwl_trans *trans, |
714 | bool low_power) | ||
707 | { | 715 | { |
708 | might_sleep(); | 716 | might_sleep(); |
709 | 717 | ||
710 | trans->ops->stop_device(trans); | 718 | trans->ops->stop_device(trans, low_power); |
711 | 719 | ||
712 | trans->state = IWL_TRANS_NO_FW; | 720 | trans->state = IWL_TRANS_NO_FW; |
713 | } | 721 | } |
714 | 722 | ||
723 | static inline void iwl_trans_stop_device(struct iwl_trans *trans) | ||
724 | { | ||
725 | _iwl_trans_stop_device(trans, true); | ||
726 | } | ||
727 | |||
715 | static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) | 728 | static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) |
716 | { | 729 | { |
717 | might_sleep(); | 730 | might_sleep(); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 9c28fe72fd74..df869633f4dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * GPL LICENSE SUMMARY | 6 | * GPL LICENSE SUMMARY |
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 12 | * it under the terms of version 2 of the GNU General Public License as |
@@ -32,7 +32,7 @@ | |||
32 | * BSD LICENSE | 32 | * BSD LICENSE |
33 | * | 33 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 35 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH |
36 | * All rights reserved. | 36 | * All rights reserved. |
37 | * | 37 | * |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without |
@@ -322,7 +322,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
322 | 322 | ||
323 | lockdep_assert_held(&mvm->mutex); | 323 | lockdep_assert_held(&mvm->mutex); |
324 | 324 | ||
325 | if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating)) | 325 | if (WARN_ON_ONCE(mvm->calibrating)) |
326 | return 0; | 326 | return 0; |
327 | 327 | ||
328 | iwl_init_notification_wait(&mvm->notif_wait, | 328 | iwl_init_notification_wait(&mvm->notif_wait, |
@@ -396,8 +396,6 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
396 | */ | 396 | */ |
397 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, | 397 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, |
398 | MVM_UCODE_CALIB_TIMEOUT); | 398 | MVM_UCODE_CALIB_TIMEOUT); |
399 | if (!ret) | ||
400 | mvm->init_ucode_complete = true; | ||
401 | 399 | ||
402 | if (ret && iwl_mvm_is_radio_killed(mvm)) { | 400 | if (ret && iwl_mvm_is_radio_killed(mvm)) { |
403 | IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); | 401 | IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); |
@@ -649,25 +647,24 @@ int iwl_mvm_up(struct iwl_mvm *mvm) | |||
649 | * module loading, load init ucode now | 647 | * module loading, load init ucode now |
650 | * (for example, if we were in RFKILL) | 648 | * (for example, if we were in RFKILL) |
651 | */ | 649 | */ |
652 | if (!mvm->init_ucode_complete) { | 650 | ret = iwl_run_init_mvm_ucode(mvm, false); |
653 | ret = iwl_run_init_mvm_ucode(mvm, false); | 651 | if (ret && !iwlmvm_mod_params.init_dbg) { |
654 | if (ret && !iwlmvm_mod_params.init_dbg) { | 652 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); |
655 | IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret); | 653 | /* this can't happen */ |
656 | /* this can't happen */ | 654 | if (WARN_ON(ret > 0)) |
657 | if (WARN_ON(ret > 0)) | 655 | ret = -ERFKILL; |
658 | ret = -ERFKILL; | 656 | goto error; |
659 | goto error; | 657 | } |
660 | } | 658 | if (!iwlmvm_mod_params.init_dbg) { |
661 | if (!iwlmvm_mod_params.init_dbg) { | 659 | /* |
662 | /* | 660 | * Stop and start the transport without entering low power |
663 | * should stop and start HW since that INIT | 661 | * mode. This will save the state of other components on the |
664 | * image just loaded | 662 | * device that are triggered by the INIT firwmare (MFUART). |
665 | */ | 663 | */ |
666 | iwl_trans_stop_device(mvm->trans); | 664 | _iwl_trans_stop_device(mvm->trans, false); |
667 | ret = iwl_trans_start_hw(mvm->trans); | 665 | _iwl_trans_start_hw(mvm->trans, false); |
668 | if (ret) | 666 | if (ret) |
669 | return ret; | 667 | return ret; |
670 | } | ||
671 | } | 668 | } |
672 | 669 | ||
673 | if (iwlmvm_mod_params.init_dbg) | 670 | if (iwlmvm_mod_params.init_dbg) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index d5522a161242..cf70f681d1ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -603,7 +603,6 @@ struct iwl_mvm { | |||
603 | 603 | ||
604 | enum iwl_ucode_type cur_ucode; | 604 | enum iwl_ucode_type cur_ucode; |
605 | bool ucode_loaded; | 605 | bool ucode_loaded; |
606 | bool init_ucode_complete; | ||
607 | bool calibrating; | 606 | bool calibrating; |
608 | u32 error_event_table; | 607 | u32 error_event_table; |
609 | u32 log_event_table; | 608 | u32 log_event_table; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 6debb0c9111a..47bbf573fdc8 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -1021,7 +1021,7 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | |||
1021 | iwl_pcie_tx_start(trans, scd_addr); | 1021 | iwl_pcie_tx_start(trans, scd_addr); |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | 1024 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) |
1025 | { | 1025 | { |
1026 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1026 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1027 | bool hw_rfkill, was_hw_rfkill; | 1027 | bool hw_rfkill, was_hw_rfkill; |
@@ -1116,7 +1116,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
1116 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) | 1116 | void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) |
1117 | { | 1117 | { |
1118 | if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) | 1118 | if (iwl_op_mode_hw_rf_kill(trans->op_mode, state)) |
1119 | iwl_trans_pcie_stop_device(trans); | 1119 | iwl_trans_pcie_stop_device(trans, true); |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) | 1122 | static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) |
@@ -1201,7 +1201,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
1201 | return 0; | 1201 | return 0; |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | 1204 | static int iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) |
1205 | { | 1205 | { |
1206 | bool hw_rfkill; | 1206 | bool hw_rfkill; |
1207 | int err; | 1207 | int err; |