From c779273b37bec14c33feeab11c4d457a24bc64e0 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 19 Apr 2015 11:41:04 +0300 Subject: iwlwifi: mvm: fix ROC reference accounting commit b112889c5af8124 ("iwlwifi: mvm: add Aux ROC request/response flow") added aux ROC flow in addition to the existing ROC flow. While doing it, it moved the ROC reference release to a common work item, which is being called for both the ROC and aux ROC flows. This resulted in invalid reference accounting, as no reference was taken in case of aux ROC, while a reference was released on completion. Fix it by adding a reference for the aux ROC as well, and release only the relevant references on completion (according to the set bits). While at it, convert cancel_work_sync() to flush_work(), in order to make sure the references are being cleaned properly. Fixes: b112889c5af8 ("iwlwifi: mvm: add Aux ROC request/response flow") Signed-off-by: Eliad Peller Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/time-event.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c') diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index fd7b0d36f9a6..a7448cf01688 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -32,7 +32,7 @@ * BSD LICENSE * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,12 +108,14 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) * in the case that the time event actually completed in the firmware * (which is handled in iwl_mvm_te_handle_notif). */ - if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) + if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) { queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE); - if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) + iwl_mvm_unref(mvm, IWL_MVM_REF_ROC); + } + if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) { queues |= BIT(mvm->aux_queue); - - iwl_mvm_unref(mvm, IWL_MVM_REF_ROC); + iwl_mvm_unref(mvm, IWL_MVM_REF_ROC_AUX); + } synchronize_net(); @@ -393,6 +395,7 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm, } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); te_data->running = true; + iwl_mvm_ref(mvm, IWL_MVM_REF_ROC_AUX); ieee80211_ready_on_channel(mvm->hw); /* Start TE */ } else { IWL_DEBUG_TE(mvm, -- cgit v1.2.3 From ebf17ff9bb46206ca7a4bc7260bff52f593c25db Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 1 Jun 2015 23:38:23 +0200 Subject: iwlwifi: mvm: simplify iwl_mvm_stop_roc() As pointed out by smatch, there's no need for a loop that always immediately terminates. Use an if statement instead and while at it clean up the mvmvif initialization. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/time-event.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c') diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index a7448cf01688..d24b6a83e68c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -797,13 +797,12 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_stop_roc(struct iwl_mvm *mvm) { - struct iwl_mvm_vif *mvmvif; + struct iwl_mvm_vif *mvmvif = NULL; struct iwl_mvm_time_event_data *te_data; bool is_p2p = false; lockdep_assert_held(&mvm->mutex); - mvmvif = NULL; spin_lock_bh(&mvm->time_event_lock); /* @@ -821,17 +820,14 @@ void iwl_mvm_stop_roc(struct iwl_mvm *mvm) } } - /* - * Iterate over the list of aux roc time events and find the time - * event that is associated with a BSS interface. - * This assumes that a BSS interface can have only a single time - * event at any given time and this time event corresponds to a ROC - * request + /* There can only be at most one AUX ROC time event, we just use the + * list to simplify/unify code. Remove it if it exists. */ - list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) { + te_data = list_first_entry_or_null(&mvm->aux_roc_te_list, + struct iwl_mvm_time_event_data, + list); + if (te_data) mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif); - goto remove_te; - } remove_te: spin_unlock_bh(&mvm->time_event_lock); -- cgit v1.2.3