aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/ops.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index af79a14063a9..2fcc8ef88a68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -275,6 +275,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
275 CMD(BEACON_NOTIFICATION), 275 CMD(BEACON_NOTIFICATION),
276 CMD(BEACON_TEMPLATE_CMD), 276 CMD(BEACON_TEMPLATE_CMD),
277 CMD(STATISTICS_NOTIFICATION), 277 CMD(STATISTICS_NOTIFICATION),
278 CMD(REDUCE_TX_POWER_CMD),
278 CMD(TX_ANT_CONFIGURATION_CMD), 279 CMD(TX_ANT_CONFIGURATION_CMD),
279 CMD(D3_CONFIG_CMD), 280 CMD(D3_CONFIG_CMD),
280 CMD(PROT_OFFLOAD_CONFIG_CMD), 281 CMD(PROT_OFFLOAD_CONFIG_CMD),
@@ -301,6 +302,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
301 CMD(MCAST_FILTER_CMD), 302 CMD(MCAST_FILTER_CMD),
302 CMD(REPLY_BEACON_FILTERING_CMD), 303 CMD(REPLY_BEACON_FILTERING_CMD),
303 CMD(REPLY_THERMAL_MNG_BACKOFF), 304 CMD(REPLY_THERMAL_MNG_BACKOFF),
305 CMD(MAC_PM_POWER_TABLE),
304}; 306};
305#undef CMD 307#undef CMD
306 308
@@ -340,6 +342,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
340 mvm->fw = fw; 342 mvm->fw = fw;
341 mvm->hw = hw; 343 mvm->hw = hw;
342 344
345 mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0;
346
343 mutex_init(&mvm->mutex); 347 mutex_init(&mvm->mutex);
344 spin_lock_init(&mvm->async_handlers_lock); 348 spin_lock_init(&mvm->async_handlers_lock);
345 INIT_LIST_HEAD(&mvm->time_event_list); 349 INIT_LIST_HEAD(&mvm->time_event_list);
@@ -431,6 +435,13 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
431 if (err) 435 if (err)
432 goto out_unregister; 436 goto out_unregister;
433 437
438 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD)
439 mvm->pm_ops = &pm_mac_ops;
440 else
441 mvm->pm_ops = &pm_legacy_ops;
442
443 memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
444
434 return op_mode; 445 return op_mode;
435 446
436 out_unregister: 447 out_unregister:
@@ -638,6 +649,22 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
638 ieee80211_free_txskb(mvm->hw, skb); 649 ieee80211_free_txskb(mvm->hw, skb);
639} 650}
640 651
652struct iwl_mvm_reprobe {
653 struct device *dev;
654 struct work_struct work;
655};
656
657static void iwl_mvm_reprobe_wk(struct work_struct *wk)
658{
659 struct iwl_mvm_reprobe *reprobe;
660
661 reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
662 if (device_reprobe(reprobe->dev))
663 dev_err(reprobe->dev, "reprobe failed!\n");
664 kfree(reprobe);
665 module_put(THIS_MODULE);
666}
667
641static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) 668static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
642{ 669{
643 iwl_abort_notification_waits(&mvm->notif_wait); 670 iwl_abort_notification_waits(&mvm->notif_wait);
@@ -649,9 +676,30 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
649 * can't recover this since we're already half suspended. 676 * can't recover this since we're already half suspended.
650 */ 677 */
651 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 678 if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
652 IWL_ERR(mvm, "Firmware error during reconfiguration! Abort.\n"); 679 struct iwl_mvm_reprobe *reprobe;
653 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && 680
654 iwlwifi_mod_params.restart_fw) { 681 IWL_ERR(mvm,
682 "Firmware error during reconfiguration - reprobe!\n");
683
684 /*
685 * get a module reference to avoid doing this while unloading
686 * anyway and to avoid scheduling a work with code that's
687 * being removed.
688 */
689 if (!try_module_get(THIS_MODULE)) {
690 IWL_ERR(mvm, "Module is being unloaded - abort\n");
691 return;
692 }
693
694 reprobe = kzalloc(sizeof(*reprobe), GFP_ATOMIC);
695 if (!reprobe) {
696 module_put(THIS_MODULE);
697 return;
698 }
699 reprobe->dev = mvm->trans->dev;
700 INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
701 schedule_work(&reprobe->work);
702 } else if (mvm->cur_ucode == IWL_UCODE_REGULAR && mvm->restart_fw) {
655 /* 703 /*
656 * This is a bit racy, but worst case we tell mac80211 about 704 * This is a bit racy, but worst case we tell mac80211 about
657 * a stopped/aborted (sched) scan when that was already done 705 * a stopped/aborted (sched) scan when that was already done
@@ -669,6 +717,8 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
669 break; 717 break;
670 } 718 }
671 719
720 if (mvm->restart_fw > 0)
721 mvm->restart_fw--;
672 ieee80211_restart_hw(mvm->hw); 722 ieee80211_restart_hw(mvm->hw);
673 } 723 }
674} 724}
@@ -678,6 +728,8 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
678 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); 728 struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
679 729
680 iwl_mvm_dump_nic_error_log(mvm); 730 iwl_mvm_dump_nic_error_log(mvm);
731 if (!mvm->restart_fw)
732 iwl_mvm_dump_sram(mvm);
681 733
682 iwl_mvm_nic_restart(mvm); 734 iwl_mvm_nic_restart(mvm);
683} 735}