aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-06-20 05:47:42 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-21 04:01:43 -0400
commite75dac921d88ac1fa1ad08686ab242556f8b888b (patch)
treeba963445c11d972497f1e06bf543a4b9325548ff /drivers
parente9c03d18c4291c4351d6b9f74bd1278a761015a2 (diff)
iwlwifi: limit mac_change_interface to BSS context
Currently when mac80211 asks to change the interface type, we will accept it for both the BSS and PAN contexts. This is not terribly complicated today, but with the addition of the P2P Device abstraction the PAN context handling will get more complex, so restrict mac_change_interface to the BSS context. Also fix a small locking issue and use is_active instead of the vif pointer to check if the other context is activated, guarding exclusive interface types on the BSS context (IBSS) against the PAN context being used for something else. Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index b581f035d4b0..b83ca358eb18 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -1411,13 +1411,11 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
1411} 1411}
1412 1412
1413static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, 1413static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
1414 struct ieee80211_vif *vif, 1414 struct ieee80211_vif *vif,
1415 enum nl80211_iftype newtype, bool newp2p) 1415 enum nl80211_iftype newtype, bool newp2p)
1416{ 1416{
1417 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); 1417 struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
1418 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); 1418 struct iwl_rxon_context *ctx, *tmp;
1419 struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
1420 struct iwl_rxon_context *tmp;
1421 enum nl80211_iftype newviftype = newtype; 1419 enum nl80211_iftype newviftype = newtype;
1422 u32 interface_modes; 1420 u32 interface_modes;
1423 int err; 1421 int err;
@@ -1428,6 +1426,18 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
1428 1426
1429 mutex_lock(&priv->mutex); 1427 mutex_lock(&priv->mutex);
1430 1428
1429 ctx = iwl_rxon_ctx_from_vif(vif);
1430
1431 /*
1432 * To simplify this code, only support changes on the
1433 * BSS context. The PAN context is usually reassigned
1434 * by creating/removing P2P interfaces anyway.
1435 */
1436 if (ctx->ctxid != IWL_RXON_CTX_BSS) {
1437 err = -EBUSY;
1438 goto out;
1439 }
1440
1431 if (!ctx->vif || !iwl_is_ready_rf(priv)) { 1441 if (!ctx->vif || !iwl_is_ready_rf(priv)) {
1432 /* 1442 /*
1433 * Huh? But wait ... this can maybe happen when 1443 * Huh? But wait ... this can maybe happen when
@@ -1437,32 +1447,19 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
1437 goto out; 1447 goto out;
1438 } 1448 }
1439 1449
1450 /* Check if the switch is supported in the same context */
1440 interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; 1451 interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
1441
1442 if (!(interface_modes & BIT(newtype))) { 1452 if (!(interface_modes & BIT(newtype))) {
1443 err = -EBUSY; 1453 err = -EBUSY;
1444 goto out; 1454 goto out;
1445 } 1455 }
1446 1456
1447 /*
1448 * Refuse a change that should be done by moving from the PAN
1449 * context to the BSS context instead, if the BSS context is
1450 * available and can support the new interface type.
1451 */
1452 if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
1453 (bss_ctx->interface_modes & BIT(newtype) ||
1454 bss_ctx->exclusive_interface_modes & BIT(newtype))) {
1455 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
1456 err = -EBUSY;
1457 goto out;
1458 }
1459
1460 if (ctx->exclusive_interface_modes & BIT(newtype)) { 1457 if (ctx->exclusive_interface_modes & BIT(newtype)) {
1461 for_each_context(priv, tmp) { 1458 for_each_context(priv, tmp) {
1462 if (ctx == tmp) 1459 if (ctx == tmp)
1463 continue; 1460 continue;
1464 1461
1465 if (!tmp->vif) 1462 if (!tmp->is_active)
1466 continue; 1463 continue;
1467 1464
1468 /* 1465 /*