aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
diff options
context:
space:
mode:
authorIlan Peer <ilan.peer@intel.com>2013-03-21 04:23:52 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-13 12:15:18 -0400
commitfe0f2de30cc3417794517afe45f57e851b3188ae (patch)
treeedea6958b2345e6fdc681cf9a867c72980d7fa78 /drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
parentc571573a027bb65ac415141f919df3c0fa0fedb4 (diff)
iwlwifi: mvm: Loosen the channel context/phy context coupling
In current implementation, the phy context is tightly coupled with the channel context. This complicates the possibility of using the same phy context for both netdev interfaces and the P2P Device interface. To loosen this coupling: 1. Manage all the phy contexts in the mvm op mode, and only save the phy context id in the chanctx memory. 2. Reference count the phy contexts and free them only when they are not longer used (both by mac80211 and P2P Device). 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/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}