Commit 53a9d61e authored by Ilan Peer's avatar Ilan Peer Committed by Johannes Berg

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: default avatarIlan Peer <ilan.peer@intel.com>
Reviewed-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent fe0f2de3
...@@ -388,6 +388,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -388,6 +388,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
int iwl_mvm_up(struct iwl_mvm *mvm) int iwl_mvm_up(struct iwl_mvm *mvm)
{ {
int ret, i; int ret, i;
struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef;
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
...@@ -443,8 +445,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -443,8 +445,22 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret) if (ret)
goto error; 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; return 0;
error: error:
iwl_trans_stop_device(mvm->trans); iwl_trans_stop_device(mvm->trans);
......
...@@ -576,8 +576,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -576,8 +576,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
* MAC context is bound to it at this stage. * MAC context is bound to it at this stage.
*/ */
if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { 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); mvmvif->phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
if (!mvmvif->phy_ctxt) { if (!mvmvif->phy_ctxt) {
...@@ -585,21 +583,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -585,21 +583,10 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
goto out_remove_mac; goto out_remove_mac;
} }
/* iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
* 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;
ret = iwl_mvm_binding_add_vif(mvm, vif); ret = iwl_mvm_binding_add_vif(mvm, vif);
if (ret) if (ret)
goto out_remove_phy; goto out_unref_phy;
ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta); ret = iwl_mvm_add_bcast_sta(mvm, vif, &mvmvif->bcast_sta);
if (ret) if (ret)
...@@ -615,7 +602,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -615,7 +602,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unbind: out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif);
out_remove_phy: out_unref_phy:
iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt); iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
out_remove_mac: out_remove_mac:
mvmvif->phy_ctxt = NULL; mvmvif->phy_ctxt = NULL;
...@@ -1254,7 +1241,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, ...@@ -1254,7 +1241,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
struct iwl_mvm_phy_ctxt *phy_ctxt; struct iwl_mvm_phy_ctxt *phy_ctxt;
int ret; int ret;
IWL_DEBUG_MAC80211(mvm, "Add PHY context\n"); IWL_DEBUG_MAC80211(mvm, "Add channel context\n");
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
...@@ -1263,14 +1250,15 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw, ...@@ -1263,14 +1250,15 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
goto out; goto out;
} }
ret = iwl_mvm_phy_ctxt_add(mvm, phy_ctxt, &ctx->def, ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
ctx->rx_chains_static, ctx->rx_chains_static,
ctx->rx_chains_dynamic); ctx->rx_chains_dynamic);
if (ret) { if (ret) {
IWL_ERR(mvm, "Failed to add PHY context\n"); IWL_ERR(mvm, "Failed to add PHY context\n");
goto out; goto out;
} }
iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
*phy_ctxt_id = phy_ctxt->id; *phy_ctxt_id = phy_ctxt->id;
out: out:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
......
...@@ -212,8 +212,6 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, ...@@ -212,8 +212,6 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
chains_static, chains_dynamic, chains_static, chains_dynamic,
FW_CTXT_ACTION_ADD, 0); FW_CTXT_ACTION_ADD, 0);
if (!ret)
ctxt->ref = 1;
return ret; return ret;
} }
...@@ -223,9 +221,7 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, ...@@ -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) 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); lockdep_assert_held(&mvm->mutex);
ctxt->ref++; ctxt->ref++;
} }
...@@ -246,36 +242,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt, ...@@ -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); 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) void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
{ {
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
ctxt->ref--; ctxt->ref--;
if (ctxt->ref != 0)
return;
return iwl_mvm_phy_ctxt_remove(mvm, ctxt);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment