summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorIlan Peer <ilan.peer@intel.com>2013-04-28 10:55:08 +0200
committerJohannes Berg <johannes.berg@intel.com>2013-05-13 18:15:18 +0200
commit53a9d61eb74e574aec2db86f63d9809b6116d164 (patch)
tree2249b1a5324163a62e82568c5df1805fef7745cf /drivers/net/wireless
parentiwlwifi: mvm: Loosen the channel context/phy context coupling (diff)
downloadlinux-53a9d61eb74e574aec2db86f63d9809b6116d164.tar.xz
linux-53a9d61eb74e574aec2db86f63d9809b6116d164.zip
iwlwifi: mvm: Change PHY context handling
1. All the phy contexts are added immediately after the firmware is loaded and up. 2. Whenever a PHY context needs to be used, its reference counter is incremented and the PHY context is being configured to the appropriate configuration. 3. When a PHY context is no longer needed, its reference count is decremented. 4. PHY contexts are never removed. Signed-off-by: Ilan Peer <ilan.peer@intel.com> Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c18
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c28
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c32
3 files changed, 25 insertions, 53 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index e18c92dd60ec..a4071cf09a24 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -388,6 +388,8 @@ out:
int iwl_mvm_up(struct iwl_mvm *mvm)
{
int ret, i;
+ struct ieee80211_channel *chan;
+ struct cfg80211_chan_def chandef;
lockdep_assert_held(&mvm->mutex);
@@ -443,8 +445,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
- IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
+ /* Add all the PHY contexts */
+ chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
+ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
+ for (i = 0; i < NUM_PHY_CTX; i++) {
+ /*
+ * The channel used here isn't relevant as it's
+ * going to be overwritten in the other flows.
+ * For now use the first channel we have.
+ */
+ ret = iwl_mvm_phy_ctxt_add(mvm, &mvm->phy_ctxts[i],
+ &chandef, 1, 1);
+ if (ret)
+ goto error;
+ }
+ IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:
iwl_trans_stop_device(mvm->trans);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index c1ed5c36bf3a..d9eabdc6e493 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -576,8 +576,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
* MAC context is bound to it at this stage.
*/
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
- struct ieee80211_channel *chan;
- struct cfg80211_chan_def chandef;
mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!mvmvif->phy_ctxt) {
@@ -585,21 +583,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
goto out_remove_mac;
}
- /*
- * The channel used here isn't relevant as it's
- * going to be overwritten as part of the ROC flow.
- * For now use the first channel we have.
- */
- chan = &mvm->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels[0];
- cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
- ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->phy_ctxt,
- &chandef, 1, 1);
- if (ret)
- goto out_remove_mac;
-
+ iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
ret = iwl_mvm_binding_add_vif(mvm, vif);
if (ret)
- goto out_remove_phy;
+ goto out_unref_phy;
ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
if (ret)
@@ -615,7 +602,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif);
- out_remove_phy:
+ out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
out_remove_mac:
mvmvif->phy_ctxt = NULL;
@@ -1254,7 +1241,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret;
- IWL_DEBUG_MAC80211(mvm, "Add PHY context\n");
+ IWL_DEBUG_MAC80211(mvm, "Add channel context\n");
mutex_lock(&mvm->mutex);
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
@@ -1263,14 +1250,15 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
goto out;
}
- ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def,
- ctx->rx_chains_static,
- ctx->rx_chains_dynamic);
+ ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
+ ctx->rx_chains_static,
+ ctx->rx_chains_dynamic);
if (ret) {
IWL_ERR(mvm, "Failed to add PHY context\n");
goto out;
}
+ iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
*phy_ctxt_id = phy_ctxt->id;
out:
mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index f80e721eb5d0..0ea61aaf7754 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -212,8 +212,6 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
chains_static, chains_dynamic,
FW_CTXT_ACTION_ADD, 0);
- if (!ret)
- ctxt->ref = 1;
return ret;
}
@@ -223,9 +221,7 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
*/
void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
{
- WARN_ON(!ctxt->ref);
lockdep_assert_held(&mvm->mutex);
-
ctxt->ref++;
}
@@ -246,36 +242,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
FW_CTXT_ACTION_MODIFY, 0);
}
-/*
- * Send a command to the FW to remove the given phy context.
- * Once the command is sent, regardless of success or failure, the context is
- * marked as invalid
- */
-static void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm,
- struct iwl_mvm_phy_ctxt *ctxt)
-{
- struct iwl_phy_context_cmd cmd;
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- iwl_mvm_phy_ctxt_cmd_hdr(ctxt, &cmd, FW_CTXT_ACTION_REMOVE, 0);
- ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC,
- sizeof(struct iwl_phy_context_cmd),
- &cmd);
- ctxt->channel = NULL;
- if (ret)
- IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n",
- ctxt->id);
-}
-
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
{
lockdep_assert_held(&mvm->mutex);
-
ctxt->ref--;
- if (ctxt->ref != 0)
- return;
-
- return iwl_mvm_phy_ctxt_remove(mvm, ctxt);
}