aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c73
1 files changed, 34 insertions, 39 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index a28a1d1f23eb..f80e721eb5d0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -195,21 +195,6 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
195 return ret; 195 return ret;
196} 196}
197 197
198
199struct phy_ctx_used_data {
200 unsigned long used[BITS_TO_LONGS(NUM_PHY_CTX)];
201};
202
203static void iwl_mvm_phy_ctx_used_iter(struct ieee80211_hw *hw,
204 struct ieee80211_chanctx_conf *ctx,
205 void *_data)
206{
207 struct phy_ctx_used_data *data = _data;
208 struct iwl_mvm_phy_ctxt *phy_ctxt = (void *)ctx->drv_priv;
209
210 __set_bit(phy_ctxt->id, data->used);
211}
212
213/* 198/*
214 * Send a command to add a PHY context based on the current HW configuration. 199 * Send a command to add a PHY context based on the current HW configuration.
215 */ 200 */
@@ -217,34 +202,31 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
217 struct cfg80211_chan_def *chandef, 202 struct cfg80211_chan_def *chandef,
218 u8 chains_static, u8 chains_dynamic) 203 u8 chains_static, u8 chains_dynamic)
219{ 204{
220 struct phy_ctx_used_data data = { 205 int ret;
221 .used = { },
222 };
223
224 /*
225 * If this is a regular PHY context (not the ROC one)
226 * skip the ROC PHY context's ID.
227 */
228 if (ctxt != &mvm->phy_ctxt_roc)
229 __set_bit(mvm->phy_ctxt_roc.id, data.used);
230 206
207 WARN_ON(ctxt->ref);
231 lockdep_assert_held(&mvm->mutex); 208 lockdep_assert_held(&mvm->mutex);
232 ctxt->color++;
233 209
234 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 210 ctxt->channel = chandef->chan;
235 ieee80211_iter_chan_contexts_atomic( 211 ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
236 mvm->hw, iwl_mvm_phy_ctx_used_iter, &data); 212 chains_static, chains_dynamic,
213 FW_CTXT_ACTION_ADD, 0);
237 214
238 ctxt->id = find_first_zero_bit(data.used, NUM_PHY_CTX); 215 if (!ret)
239 if (WARN_ONCE(ctxt->id == NUM_PHY_CTX, 216 ctxt->ref = 1;
240 "Failed to init PHY context - no free ID!\n")) 217 return ret;
241 return -EIO; 218}
242 }
243 219
244 ctxt->channel = chandef->chan; 220/*
245 return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef, 221 * Update the number of references to the given PHY context. This is valid only
246 chains_static, chains_dynamic, 222 * in case the PHY context was already created, i.e., its reference count > 0.
247 FW_CTXT_ACTION_ADD, 0); 223 */
224void iwl_mvm_phy_ctxt_ref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
225{
226 WARN_ON(!ctxt->ref);
227 lockdep_assert_held(&mvm->mutex);
228
229 ctxt->ref++;
248} 230}
249 231
250/* 232/*
@@ -269,7 +251,8 @@ int iwl_mvm_phy_ctxt_changed(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
269 * Once the command is sent, regardless of success or failure, the context is 251 * Once the command is sent, regardless of success or failure, the context is
270 * marked as invalid 252 * marked as invalid
271 */ 253 */
272void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) 254static void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm,
255 struct iwl_mvm_phy_ctxt *ctxt)
273{ 256{
274 struct iwl_phy_context_cmd cmd; 257 struct iwl_phy_context_cmd cmd;
275 int ret; 258 int ret;
@@ -280,7 +263,19 @@ void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
280 ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC, 263 ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC,
281 sizeof(struct iwl_phy_context_cmd), 264 sizeof(struct iwl_phy_context_cmd),
282 &cmd); 265 &cmd);
266 ctxt->channel = NULL;
283 if (ret) 267 if (ret)
284 IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n", 268 IWL_ERR(mvm, "Failed to send PHY remove: ctxt id=%d\n",
285 ctxt->id); 269 ctxt->id);
286} 270}
271
272void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
273{
274 lockdep_assert_held(&mvm->mutex);
275
276 ctxt->ref--;
277 if (ctxt->ref != 0)
278 return;
279
280 return iwl_mvm_phy_ctxt_remove(mvm, ctxt);
281}