| From a6cc5163149532734b84c86cbffa4994e527074b Mon Sep 17 00:00:00 2001 |
| From: Matti Gottlieb <matti.gottlieb@intel.com> |
| Date: Mon, 29 Sep 2014 11:46:04 +0300 |
| Subject: iwlwifi: mvm: ROC - bug fixes around time events and locking |
| |
| From: Matti Gottlieb <matti.gottlieb@intel.com> |
| |
| commit a6cc5163149532734b84c86cbffa4994e527074b upstream. |
| |
| Don't add the time event to the list. We added it several |
| times the same time event, which leads to an infinite loop |
| when walking the list. |
| |
| Since we (currently) don't support more than one ROC for STA |
| vif at a time, enforce this and don't add the time event |
| to any list. |
| |
| We were also missing the locking of the mutex which led to |
| a lockdep splat - fix that. |
| |
| Signed-off-by: Matti Gottlieb <matti.gottlieb@intel.com> |
| Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/wireless/iwlwifi/mvm/mac80211.c | 25 ++++++++++++++++--------- |
| drivers/net/wireless/iwlwifi/mvm/time-event.c | 2 +- |
| 2 files changed, 17 insertions(+), 10 deletions(-) |
| |
| --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c |
| +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c |
| @@ -515,7 +515,8 @@ static void iwl_mvm_mac_tx(struct ieee80 |
| } |
| |
| if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && |
| - !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) |
| + !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) && |
| + !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status)) |
| goto drop; |
| |
| /* treat non-bufferable MMPDUs as broadcast if sta is sleeping */ |
| @@ -2403,14 +2404,19 @@ static int iwl_mvm_send_aux_roc_cmd(stru |
| /* Set the node address */ |
| memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN); |
| |
| + lockdep_assert_held(&mvm->mutex); |
| + |
| + spin_lock_bh(&mvm->time_event_lock); |
| + |
| + if (WARN_ON(te_data->id == HOT_SPOT_CMD)) { |
| + spin_unlock_bh(&mvm->time_event_lock); |
| + return -EIO; |
| + } |
| + |
| te_data->vif = vif; |
| te_data->duration = duration; |
| te_data->id = HOT_SPOT_CMD; |
| |
| - lockdep_assert_held(&mvm->mutex); |
| - |
| - spin_lock_bh(&mvm->time_event_lock); |
| - list_add_tail(&te_data->list, &mvm->time_event_list); |
| spin_unlock_bh(&mvm->time_event_lock); |
| |
| /* |
| @@ -2466,22 +2472,23 @@ static int iwl_mvm_roc(struct ieee80211_ |
| IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
| duration, type); |
| |
| + mutex_lock(&mvm->mutex); |
| + |
| switch (vif->type) { |
| case NL80211_IFTYPE_STATION: |
| /* Use aux roc framework (HS20) */ |
| ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, |
| vif, duration); |
| - return ret; |
| + goto out_unlock; |
| case NL80211_IFTYPE_P2P_DEVICE: |
| /* handle below */ |
| break; |
| default: |
| IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type); |
| - return -EINVAL; |
| + ret = -EINVAL; |
| + goto out_unlock; |
| } |
| |
| - mutex_lock(&mvm->mutex); |
| - |
| for (i = 0; i < NUM_PHY_CTX; i++) { |
| phy_ctxt = &mvm->phy_ctxts[i]; |
| if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt) |
| --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c |
| +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c |
| @@ -303,8 +303,8 @@ static int iwl_mvm_aux_roc_te_handle_not |
| te_data->running = false; |
| te_data->vif = NULL; |
| te_data->uid = 0; |
| + te_data->id = TE_MAX; |
| } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { |
| - set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); |
| set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); |
| te_data->running = true; |
| ieee80211_ready_on_channel(mvm->hw); /* Start TE */ |