Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 224247
b: refs/heads/master
c: d4daaea
h: refs/heads/master
i:
  224245: b67e1ea
  224243: 0c17b5c
  224239: c205f9c
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Nov 15, 2010
1 parent 756fd0f commit a65e85c
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 45 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bd50a8ab9f48787109f6ff761c8f0e185e3d0690
refs/heads/master: d4daaea656e0b5543c2e37c31934cea8f044b31e
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-4965.c
Original file line number Diff line number Diff line change
Expand Up @@ -2589,6 +2589,7 @@ struct ieee80211_ops iwl4965_hw_ops = {
.stop = iwlagn_mac_stop,
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
.change_interface = iwl_mac_change_interface,
.config = iwl_legacy_mac_config,
.configure_filter = iwlagn_configure_filter,
.set_key = iwlagn_mac_set_key,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3909,6 +3909,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.stop = iwlagn_mac_stop,
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
.change_interface = iwl_mac_change_interface,
.config = iwlagn_mac_config,
.configure_filter = iwlagn_configure_filter,
.set_key = iwlagn_mac_set_key,
Expand Down
168 changes: 124 additions & 44 deletions trunk/drivers/net/wireless/iwlwifi/iwl-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,10 +1427,8 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);

static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);

iwl_connection_init_rx_config(priv, ctx);

if (priv->cfg->ops->hcmd->set_rxon_chain)
Expand All @@ -1439,12 +1437,49 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
return iwlcore_commit_rxon(priv, ctx);
}

static int iwl_setup_interface(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
struct ieee80211_vif *vif = ctx->vif;
int err;

lockdep_assert_held(&priv->mutex);

/*
* This variable will be correct only when there's just
* a single context, but all code using it is for hardware
* that supports only one context.
*/
priv->iw_mode = vif->type;

ctx->is_active = true;

err = iwl_set_mode(priv, ctx);
if (err) {
if (!ctx->always_active)
ctx->is_active = false;
return err;
}

if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
vif->type == NL80211_IFTYPE_ADHOC) {
/*
* pretend to have high BT traffic as long as we
* are operating in IBSS mode, as this will cause
* the rate scaling etc. to behave as intended.
*/
priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
}

return 0;
}

int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *tmp, *ctx = NULL;
int err = 0;
int err;

IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
vif->type, vif->addr);
Expand Down Expand Up @@ -1486,36 +1521,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)

vif_priv->ctx = ctx;
ctx->vif = vif;
/*
* This variable will be correct only when there's just
* a single context, but all code using it is for hardware
* that supports only one context.
*/
priv->iw_mode = vif->type;

ctx->is_active = true;

err = iwl_set_mode(priv, vif);
if (err) {
if (!ctx->always_active)
ctx->is_active = false;
goto out_err;
}

if (priv->cfg->bt_params &&
priv->cfg->bt_params->advanced_bt_coexist &&
vif->type == NL80211_IFTYPE_ADHOC) {
/*
* pretend to have high BT traffic as long as we
* are operating in IBSS mode, as this will cause
* the rate scaling etc. to behave as intended.
*/
priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
}

goto out;
err = iwl_setup_interface(priv, ctx);
if (!err)
goto out;

out_err:
ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION;
out:
Expand All @@ -1526,27 +1536,24 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
}
EXPORT_SYMBOL(iwl_mac_add_interface);

void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
static void iwl_teardown_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif,
bool mode_change)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);

IWL_DEBUG_MAC80211(priv, "enter\n");

mutex_lock(&priv->mutex);

WARN_ON(ctx->vif != vif);
ctx->vif = NULL;
lockdep_assert_held(&priv->mutex);

if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200);
iwl_force_scan_end(priv);
}
iwl_set_mode(priv, vif);

if (!ctx->always_active)
ctx->is_active = false;
if (!mode_change) {
iwl_set_mode(priv, ctx);
if (!ctx->always_active)
ctx->is_active = false;
}

/*
* When removing the IBSS interface, overwrite the
Expand All @@ -1557,6 +1564,22 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
*/
if (vif->type == NL80211_IFTYPE_ADHOC)
priv->bt_traffic_load = priv->notif_bt_traffic_load;
}

void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);

IWL_DEBUG_MAC80211(priv, "enter\n");

mutex_lock(&priv->mutex);

WARN_ON(ctx->vif != vif);
ctx->vif = NULL;

iwl_teardown_interface(priv, vif, false);

memset(priv->bssid, 0, ETH_ALEN);
mutex_unlock(&priv->mutex);
Expand Down Expand Up @@ -1908,6 +1931,63 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
return 0;
}

int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p)
{
struct iwl_priv *priv = hw->priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
struct iwl_rxon_context *tmp;
u32 interface_modes;
int err;

newtype = ieee80211_iftype_p2p(newtype, newp2p);

mutex_lock(&priv->mutex);

interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;

if (!(interface_modes & BIT(newtype))) {
err = -EBUSY;
goto out;
}

if (ctx->exclusive_interface_modes & BIT(newtype)) {
for_each_context(priv, tmp) {
if (ctx == tmp)
continue;

if (!tmp->vif)
continue;

/*
* The current mode switch would be exclusive, but
* another context is active ... refuse the switch.
*/
err = -EBUSY;
goto out;
}
}

/* success */
iwl_teardown_interface(priv, vif, true);
vif->type = newtype;
err = iwl_setup_interface(priv, ctx);
WARN_ON(err);
/*
* We've switched internally, but submitting to the
* device may have failed for some reason. Mask this
* error, because otherwise mac80211 will not switch
* (and set the interface type back) and we'll be
* out of sync with it.
*/
err = 0;

out:
mutex_unlock(&priv->mutex);
return err;
}
EXPORT_SYMBOL(iwl_mac_change_interface);

/**
* iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
*
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
int iwl_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p);
int iwl_alloc_txq_mem(struct iwl_priv *priv);
void iwl_free_txq_mem(struct iwl_priv *priv);
void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -3832,6 +3832,7 @@ struct ieee80211_ops iwl3945_hw_ops = {
.stop = iwl3945_mac_stop,
.add_interface = iwl_mac_add_interface,
.remove_interface = iwl_mac_remove_interface,
.change_interface = iwl_mac_change_interface,
.config = iwl_legacy_mac_config,
.configure_filter = iwl3945_configure_filter,
.set_key = iwl3945_mac_set_key,
Expand Down

0 comments on commit a65e85c

Please sign in to comment.