aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlan Peer <ilan.peer@intel.com>2013-04-02 03:25:46 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-13 12:16:33 -0400
commit31d385aeea7e26e70409cd6f126c516047bc9f96 (patch)
treea6efd2b15f665ee577fc86fe19414a61db9b0723
parentbfc824b05bdc4ea0b7702263f91dc3fed7b630eb (diff)
iwlwifi: mvm: Allow P2P Device to use an existing PHY context
The patch is an optimization, that eliminates unnecessary binding context switching and allows the P2P Device MAC to use the same channel as an existing netdev interface. For each ROC call, check if there is already a channel/phy context that can be used for the P2P Device. If such channel is found, unbind the P2P Device from its current phy context, and bind it to the already used channel/phy context. In case that the phy context is shared, and there is a need to change it, create a new phy context, unbind and create a new binding. 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>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c99
1 files changed, 92 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index d9eabdc6e493..fe22772f3421 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1194,28 +1194,105 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
1194 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1194 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1195 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 1195 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1196 struct cfg80211_chan_def chandef; 1196 struct cfg80211_chan_def chandef;
1197 int ret; 1197 struct iwl_mvm_phy_ctxt *phy_ctxt;
1198 int ret, i;
1199
1200 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
1201 duration, type);
1198 1202
1199 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) { 1203 if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
1200 IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type); 1204 IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
1201 return -EINVAL; 1205 return -EINVAL;
1202 } 1206 }
1203 1207
1204 IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
1205 duration, type);
1206
1207 mutex_lock(&mvm->mutex); 1208 mutex_lock(&mvm->mutex);
1208 1209
1210 for (i = 0; i < NUM_PHY_CTX; i++) {
1211 phy_ctxt = &mvm->phy_ctxts[i];
1212 if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
1213 continue;
1214
1215 if (phy_ctxt->ref && channel == phy_ctxt->channel) {
1216 /*
1217 * Unbind the P2P_DEVICE from the current PHY context,
1218 * and if the PHY context is not used remove it.
1219 */
1220 ret = iwl_mvm_binding_remove_vif(mvm, vif);
1221 if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
1222 goto out_unlock;
1223
1224 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
1225
1226 /* Bind the P2P_DEVICE to the current PHY Context */
1227 mvmvif->phy_ctxt = phy_ctxt;
1228
1229 ret = iwl_mvm_binding_add_vif(mvm, vif);
1230 if (WARN(ret, "Failed binding P2P_DEVICE\n"))
1231 goto out_unlock;
1232
1233 iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
1234 goto schedule_time_event;
1235 }
1236 }
1237
1238 /* Need to update the PHY context only if the ROC channel changed */
1239 if (channel == mvmvif->phy_ctxt->channel)
1240 goto schedule_time_event;
1241
1209 cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); 1242 cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
1210 ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt,
1211 &chandef, 1, 1);
1212 1243
1244 /*
1245 * Change the PHY context configuration as it is currently referenced
1246 * only by the P2P Device MAC
1247 */
1248 if (mvmvif->phy_ctxt->ref == 1) {
1249 ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt,
1250 &chandef, 1, 1);
1251 if (ret)
1252 goto out_unlock;
1253 } else {
1254 /*
1255 * The PHY context is shared with other MACs. Need to remove the
1256 * P2P Device from the binding, allocate an new PHY context and
1257 * create a new binding
1258 */
1259 phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
1260 if (!phy_ctxt) {
1261 ret = -ENOSPC;
1262 goto out_unlock;
1263 }
1264
1265 ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chandef,
1266 1, 1);
1267 if (ret) {
1268 IWL_ERR(mvm, "Failed to change PHY context\n");
1269 goto out_unlock;
1270 }
1271
1272 /* Unbind the P2P_DEVICE from the current PHY context */
1273 ret = iwl_mvm_binding_remove_vif(mvm, vif);
1274 if (WARN(ret, "Failed unbinding P2P_DEVICE\n"))
1275 goto out_unlock;
1276
1277 iwl_mvm_phy_ctxt_unref(mvm, mvmvif->phy_ctxt);
1278
1279 /* Bind the P2P_DEVICE to the new allocated PHY context */
1280 mvmvif->phy_ctxt = phy_ctxt;
1281
1282 ret = iwl_mvm_binding_add_vif(mvm, vif);
1283 if (WARN(ret, "Failed binding P2P_DEVICE\n"))
1284 goto out_unlock;
1285
1286 iwl_mvm_phy_ctxt_ref(mvm, mvmvif->phy_ctxt);
1287 }
1288
1289schedule_time_event:
1213 /* Schedule the time events */ 1290 /* Schedule the time events */
1214 ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type); 1291 ret = iwl_mvm_start_p2p_roc(mvm, vif, duration, type);
1215 1292
1293out_unlock:
1216 mutex_unlock(&mvm->mutex); 1294 mutex_unlock(&mvm->mutex);
1217 IWL_DEBUG_MAC80211(mvm, "leave\n"); 1295 IWL_DEBUG_MAC80211(mvm, "leave\n");
1218
1219 return ret; 1296 return ret;
1220} 1297}
1221 1298
@@ -1285,6 +1362,14 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
1285 u16 *phy_ctxt_id = (u16 *)ctx->drv_priv; 1362 u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
1286 struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id]; 1363 struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
1287 1364
1365 if (WARN_ONCE((phy_ctxt->ref > 1) &&
1366 (changed & ~(IEEE80211_CHANCTX_CHANGE_WIDTH |
1367 IEEE80211_CHANCTX_CHANGE_RX_CHAINS |
1368 IEEE80211_CHANCTX_CHANGE_RADAR)),
1369 "Cannot change PHY. Ref=%d, changed=0x%X\n",
1370 phy_ctxt->ref, changed))
1371 return;
1372
1288 mutex_lock(&mvm->mutex); 1373 mutex_lock(&mvm->mutex);
1289 iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def, 1374 iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->def,
1290 ctx->rx_chains_static, 1375 ctx->rx_chains_static,