diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c | 73 |
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 | |||
199 | struct phy_ctx_used_data { | ||
200 | unsigned long used[BITS_TO_LONGS(NUM_PHY_CTX)]; | ||
201 | }; | ||
202 | |||
203 | static 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 | */ |
224 | void 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 | */ |
272 | void iwl_mvm_phy_ctxt_remove(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) | 254 | static 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 | |||
272 | void 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 | } | ||