Commit 76d04815 authored by Johannes Berg's avatar Johannes Berg Committed by Wey-Yi Guy

iwlwifi: introduce beacon context

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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent 7e6a5886
...@@ -345,6 +345,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, ...@@ -345,6 +345,13 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
* beacon contents. * 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 */ /* Initialize memory */
tx_beacon_cmd = &frame->u.beacon; tx_beacon_cmd = &frame->u.beacon;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); 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, ...@@ -357,9 +364,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
/* Set up TX command fields */ /* Set up TX command fields */
tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
#warning "Use proper STA ID" tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
tx_beacon_cmd->tx.sta_id =
priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; 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_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_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, ...@@ -369,7 +374,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
frame_size); frame_size);
/* Set up packet rate and flags */ /* 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->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
priv->hw_params.valid_tx_ant); priv->hw_params.valid_tx_ant);
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_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) ...@@ -602,25 +607,28 @@ static void iwl_bg_beacon_update(struct work_struct *work)
container_of(work, struct iwl_priv, beacon_update); container_of(work, struct iwl_priv, beacon_update);
struct sk_buff *beacon; struct sk_buff *beacon;
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */ mutex_lock(&priv->mutex);
#warning "introduce and use beacon context" if (!priv->beacon_ctx) {
beacon = ieee80211_beacon_get(priv->hw, IWL_ERR(priv, "updating beacon w/o beacon context!\n");
priv->contexts[IWL_RXON_CTX_BSS].vif); 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) { if (!beacon) {
IWL_ERR(priv, "update beacon failed\n"); IWL_ERR(priv, "update beacon failed\n");
return; goto out;
} }
mutex_lock(&priv->mutex);
/* new beacon skb is allocated every time; dispose previous.*/ /* new beacon skb is allocated every time; dispose previous.*/
if (priv->ibss_beacon) if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon); dev_kfree_skb(priv->ibss_beacon);
priv->ibss_beacon = beacon; priv->ibss_beacon = beacon;
mutex_unlock(&priv->mutex);
iwl_send_beacon_cmd(priv); iwl_send_beacon_cmd(priv);
out:
mutex_unlock(&priv->mutex);
} }
static void iwl_bg_bt_runtime_config(struct work_struct *work) 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) ...@@ -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); struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
int ret = 0; int ret = 0;
lockdep_assert_held(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
......
...@@ -699,11 +699,9 @@ int iwl_full_rxon_required(struct iwl_priv *priv, ...@@ -699,11 +699,9 @@ int iwl_full_rxon_required(struct iwl_priv *priv,
} }
EXPORT_SYMBOL(iwl_full_rxon_required); 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 * Assign the lowest rate -- should really get this from
* the beacon skb from mac80211. * the beacon skb from mac80211.
...@@ -1723,6 +1721,14 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -1723,6 +1721,14 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
IWL_DEBUG_MAC80211(priv, "enter\n"); 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)) { if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO; return -EIO;
...@@ -1741,9 +1747,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) ...@@ -1741,9 +1747,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
#warning "use beacon context?" priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
priv->cfg->ops->lib->post_associate(
priv, priv->contexts[IWL_RXON_CTX_BSS].vif);
return 0; return 0;
} }
...@@ -1773,6 +1777,18 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1773,6 +1777,18 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&priv->lock, flags); 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) { if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
dev_kfree_skb(priv->ibss_beacon); dev_kfree_skb(priv->ibss_beacon);
priv->ibss_beacon = ieee80211_beacon_get(hw, vif); priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
......
...@@ -523,7 +523,8 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); ...@@ -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); 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); u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
......
...@@ -1437,6 +1437,8 @@ struct iwl_priv { ...@@ -1437,6 +1437,8 @@ struct iwl_priv {
struct work_struct rx_replenish; struct work_struct rx_replenish;
struct work_struct abort_scan; struct work_struct abort_scan;
struct work_struct beacon_update; struct work_struct beacon_update;
struct iwl_rxon_context *beacon_ctx;
struct work_struct tt_work; struct work_struct tt_work;
struct work_struct ct_enter; struct work_struct ct_enter;
struct work_struct ct_exit; struct work_struct ct_exit;
......
...@@ -343,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) ...@@ -343,7 +343,8 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
return -ENOMEM; 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); frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment