Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -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 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);
+8 −20
Original line number Diff line number Diff line
@@ -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,7 +1250,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
		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_dynamic);
	if (ret) {
@@ -1271,6 +1258,7 @@ static int iwl_mvm_add_chanctx(struct ieee80211_hw *hw,
		goto out;
	}

	iwl_mvm_phy_ctxt_ref(mvm, phy_ctxt);
	*phy_ctxt_id = phy_ctxt->id;
out:
	mutex_unlock(&mvm->mutex);
+0 −32
Original line number Diff line number Diff line
@@ -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);
}