iwlwifi: update LQ for bcast station on channel change
authorDaniel Halperin <dhalperi@cs.washington.edu>
Mon, 14 Jun 2010 20:10:29 +0000 (13:10 -0700)
committerReinette Chatre <reinette.chatre@intel.com>
Fri, 25 Jun 2010 21:53:49 +0000 (14:53 -0700)
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: Daniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-sta.h

index 24743b97ba3525769818b9919753b60b57eb4405..1daf159914ad028202a78c1b81d26b4d180afbc0 100644 (file)
@@ -217,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
                .set_ct_kill = iwl1000_set_ct_threshold,
         },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
index 67526a1be025db668e16e2a365ab9dc13ee15303..1dd3bc4c107ef44134b46ca66a0aa8285b8fd731 100644 (file)
@@ -2280,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
                .set_ct_kill = iwl4965_set_ct_threshold,
        },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
index fa2dbb56177c5fc4b643d4448a4a39668e742eef..b8f3e20f2c80d1ff89438bcac71100723f1b73a9 100644 (file)
@@ -393,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
                .set_ct_kill = iwl5000_set_ct_threshold,
         },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
@@ -455,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
                .set_ct_kill = iwl5150_set_ct_threshold,
         },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
index c909a9c5e5e1058b4acb6d82f3bac827380cfcd4..61cf0b3e88c2f460bb350ee2a3ae5ae4507bfab9 100644 (file)
@@ -318,6 +318,7 @@ static struct iwl_lib_ops iwl6000_lib = {
                .set_calib_version = iwl6000_set_calib_version,
         },
        .manage_ibss_station = iwlagn_manage_ibss_station,
+       .update_bcast_station = iwl_update_bcast_station,
        .debugfs_ops = {
                .rx_stats_read = iwl_ucode_rx_stats_read,
                .tx_stats_read = iwl_ucode_tx_stats_read,
index 329e5107b5c32ccd8e87817e72f1f6ef0c1b8228..f47a58ff325231d698d6816b21c666722ac24293 100644 (file)
@@ -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);
                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:
                /* The list of supported rates and rate mask can be different
                 * for each band; since the band may have changed, reset
index cdcb51d8bc213fd9701650158543d84778e3ab25..15930e06402247b8ff360ccab61b76e254b1353b 100644 (file)
@@ -196,6 +196,7 @@ struct iwl_lib_ops {
        /* station management */
        int (*manage_ibss_station)(struct iwl_priv *priv,
                                   struct ieee80211_vif *vif, bool add);
+       int (*update_bcast_station)(struct iwl_priv *priv);
        /* recover from tx queue stall */
        void (*recover_from_tx_stall)(unsigned long data);
        /* check for plcp health */
index 6a9cd08bd4491e531c030bcfec35c741a4f2c0f3..9511f03f07e053b93af68c83bd534ddfab98122d 100644 (file)
@@ -1259,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
 }
 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)
 {
        unsigned long flags;
index 619bb99d85cfc2f4dc1c4814f562603d063c21de..ba95b1a590a5be5c4657b7adb5aaaa503629c67a 100644 (file)
@@ -60,6 +60,7 @@ void iwl_restore_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);
 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_send_add_sta(struct iwl_priv *priv,
                     struct iwl_addsta_cmd *sta, u8 flags);