Commit 278c2f6f authored by Daniel Halperin's avatar Daniel Halperin Committed by Reinette Chatre

iwlwifi: update LQ for bcast station on channel change

The rate table in the bcast LQ is computed only when the station is
allocated, and chooses the lowest rate for the band. Because of when this
occurs, this is the 2.4 GHz band and uses the 0x420a (CCK, 1 Mbps) rate. In 5 GHz
beaconing mode, this rate will prevent beacons from being sent and any other
packets from being received.

We can fix this by re-initializing the bcast station's LQ command when the
channel is changed.
Signed-off-by: default avatarDaniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
parent 680788ac
...@@ -217,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = { ...@@ -217,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.set_ct_kill = iwl1000_set_ct_threshold, .set_ct_kill = iwl1000_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -2280,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = { ...@@ -2280,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_ct_kill = iwl4965_set_ct_threshold, .set_ct_kill = iwl4965_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -393,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = { ...@@ -393,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_ct_kill = iwl5000_set_ct_threshold, .set_ct_kill = iwl5000_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
...@@ -455,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = { ...@@ -455,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.set_ct_kill = iwl5150_set_ct_threshold, .set_ct_kill = iwl5150_set_ct_threshold,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -318,6 +318,7 @@ static struct iwl_lib_ops iwl6000_lib = { ...@@ -318,6 +318,7 @@ static struct iwl_lib_ops iwl6000_lib = {
.set_calib_version = iwl6000_set_calib_version, .set_calib_version = iwl6000_set_calib_version,
}, },
.manage_ibss_station = iwlagn_manage_ibss_station, .manage_ibss_station = iwlagn_manage_ibss_station,
.update_bcast_station = iwl_update_bcast_station,
.debugfs_ops = { .debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read, .rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read,
......
...@@ -2110,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2110,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
if (priv->cfg->ops->lib->update_bcast_station)
ret = priv->cfg->ops->lib->update_bcast_station(priv);
set_ch_out: set_ch_out:
/* The list of supported rates and rate mask can be different /* The list of supported rates and rate mask can be different
* for each band; since the band may have changed, reset * for each band; since the band may have changed, reset
......
...@@ -196,6 +196,7 @@ struct iwl_lib_ops { ...@@ -196,6 +196,7 @@ struct iwl_lib_ops {
/* station management */ /* station management */
int (*manage_ibss_station)(struct iwl_priv *priv, int (*manage_ibss_station)(struct iwl_priv *priv,
struct ieee80211_vif *vif, bool add); struct ieee80211_vif *vif, bool add);
int (*update_bcast_station)(struct iwl_priv *priv);
/* recover from tx queue stall */ /* recover from tx queue stall */
void (*recover_from_tx_stall)(unsigned long data); void (*recover_from_tx_stall)(unsigned long data);
/* check for plcp health */ /* check for plcp health */
......
...@@ -1259,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) ...@@ -1259,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
} }
EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
/**
* iwl_update_bcast_station - update broadcast station's LQ command
*
* Only used by iwlagn. Placed here to have all bcast station management
* code together.
*/
int iwl_update_bcast_station(struct iwl_priv *priv)
{
unsigned long flags;
struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = priv->hw_params.bcast_sta_id;
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
if (!link_cmd) {
IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
return -ENOMEM;
}
spin_lock_irqsave(&priv->sta_lock, flags);
if (priv->stations[sta_id].lq)
kfree(priv->stations[sta_id].lq);
else
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->sta_lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
void iwl_dealloc_bcast_station(struct iwl_priv *priv) void iwl_dealloc_bcast_station(struct iwl_priv *priv)
{ {
unsigned long flags; unsigned long flags;
......
...@@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv); ...@@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv);
void iwl_clear_ucode_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv);
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
void iwl_dealloc_bcast_station(struct iwl_priv *priv); void iwl_dealloc_bcast_station(struct iwl_priv *priv);
int iwl_update_bcast_station(struct iwl_priv *priv);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
int iwl_send_add_sta(struct iwl_priv *priv, int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags); struct iwl_addsta_cmd *sta, u8 flags);
......
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