From: Johannes Berg <johannes.berg@xxxxxxxxx> Only one context can be beaconing at a time, but we need to track which one. Introduce a new variable priv->beacon_ctx to do that. Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@xxxxxxxxx> --- drivers/net/wireless/iwlwifi/iwl-agn.c | 32 +++++++++++++++++--------- drivers/net/wireless/iwlwifi/iwl-core.c | 30 +++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.h | 3 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 +- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4efca99..55d1cd4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -345,6 +345,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, * beacon contents. */ + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); + return -EINVAL; + } + /* Initialize memory */ tx_beacon_cmd = &frame->u.beacon; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); @@ -357,9 +364,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); -#warning "Use proper STA ID" - tx_beacon_cmd->tx.sta_id = - priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id; + tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; @@ -369,7 +374,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, frame_size); /* Set up packet rate and flags */ - rate = iwl_rate_get_lowest_plcp(priv); + rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx); priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, priv->hw_params.valid_tx_ant); rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); @@ -602,25 +607,28 @@ static void iwl_bg_beacon_update(struct work_struct *work) container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; - /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ -#warning "introduce and use beacon context" - beacon = ieee80211_beacon_get(priv->hw, - priv->contexts[IWL_RXON_CTX_BSS].vif); + mutex_lock(&priv->mutex); + if (!priv->beacon_ctx) { + IWL_ERR(priv, "updating beacon w/o beacon context!\n"); + goto out; + } + /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ + beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif); if (!beacon) { IWL_ERR(priv, "update beacon failed\n"); - return; + goto out; } - mutex_lock(&priv->mutex); /* new beacon skb is allocated every time; dispose previous.*/ if (priv->ibss_beacon) dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = beacon; - mutex_unlock(&priv->mutex); iwl_send_beacon_cmd(priv); + out: + mutex_unlock(&priv->mutex); } static void iwl_bg_bt_runtime_config(struct work_struct *work) @@ -3477,6 +3485,8 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); int ret = 0; + lockdep_assert_held(&priv->mutex); + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8ec042d..fb9173b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -699,11 +699,9 @@ int iwl_full_rxon_required(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_full_rxon_required); -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) { -#if !TODO - struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; -#endif /* * Assign the lowest rate -- should really get this from * the beacon skb from mac80211. @@ -1723,6 +1721,14 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "enter\n"); + lockdep_assert_held(&priv->mutex); + + if (!priv->beacon_ctx) { + IWL_ERR(priv, "update beacon but no beacon context!\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); return -EIO; @@ -1741,9 +1747,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211(priv, "leave\n"); spin_unlock_irqrestore(&priv->lock, flags); -#warning "use beacon context?" - priv->cfg->ops->lib->post_associate( - priv, priv->contexts[IWL_RXON_CTX_BSS].vif); + priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); return 0; } @@ -1773,6 +1777,18 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, spin_unlock_irqrestore(&priv->lock, flags); } + if (changes & BSS_CHANGED_BEACON_ENABLED) { + /* + * the add_interface code must make sure we only ever + * have a single interface that could be beaconing at + * any time. + */ + if (vif->bss_conf.enable_beacon) + priv->beacon_ctx = ctx; + else + priv->beacon_ctx = NULL; + } + if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { dev_kfree_skb(priv->ibss_beacon); priv->ibss_beacon = ieee80211_beacon_get(hw, vif); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 289fef8..d2ee55d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -523,7 +523,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); +u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c17c67f..e1565f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1437,6 +1437,8 @@ struct iwl_priv { struct work_struct rx_replenish; struct work_struct abort_scan; struct work_struct beacon_update; + struct iwl_rxon_context *beacon_ctx; + struct work_struct tt_work; struct work_struct ct_enter; struct work_struct ct_exit; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c048c1d..e81c438 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -343,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) return -ENOMEM; } - rate = iwl_rate_get_lowest_plcp(priv); + rate = iwl_rate_get_lowest_plcp(priv, + &priv->contexts[IWL_RXON_CTX_BSS]); frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html