iwlwifi: track IBSS manager status
authorJohannes Berg <johannes.berg@intel.com>
Sat, 31 Jul 2010 15:34:10 +0000 (08:34 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 16 Aug 2010 19:26:38 +0000 (15:26 -0400)
Only the IBSS manager, ie. the station that sent
the IBSS beacon last, should be replying to probe
responses. This requires implementing the mac80211
tx_last_beacon callback, which we can do thanks to
the ucode beacon notification.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl3945-base.c

index 8684f26397162529a5802a7e0a22ac06c9746997..43e078b8737825dfd51592e21d7882546c984501 100644 (file)
@@ -764,10 +764,10 @@ static void iwl_bg_ucode_trace(unsigned long data)
 static void iwl_rx_beacon_notif(struct iwl_priv *priv,
                                struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl4965_beacon_notif *beacon =
                (struct iwl4965_beacon_notif *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
        u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
 
        IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@@ -779,6 +779,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
                le32_to_cpu(beacon->low_tsf), rate);
 #endif
 
+       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
        if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
            (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
                queue_work(priv->workqueue, &priv->beacon_update);
@@ -3881,6 +3883,7 @@ static struct ieee80211_ops iwl_hw_ops = {
        .sta_remove = iwl_mac_sta_remove,
        .channel_switch = iwl_mac_channel_switch,
        .flush = iwl_mac_flush,
+       .tx_last_beacon = iwl_mac_tx_last_beacon,
 };
 
 static void iwl_hw_detect(struct iwl_priv *priv)
index 60725a5c1b694b689d42fe6e782c9c141a47ac74..9435fd934d5ed644a5f3feb0bd2f2990518c97eb 100644 (file)
@@ -2919,6 +2919,11 @@ struct iwl_scancomplete_notification {
  *
  *****************************************************************************/
 
+enum iwl_ibss_manager {
+       IWL_NOT_IBSS_MANAGER = 0,
+       IWL_IBSS_MANAGER = 1,
+};
+
 /*
  * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
  */
index 78882f9ab4591033e971cb5301e68ce5b482218d..ccdf3c02bb3c1b18930560d2fd4f43ac9bfce2e1 100644 (file)
@@ -1666,6 +1666,14 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 }
 EXPORT_SYMBOL(iwl_mac_conf_tx);
 
+int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct iwl_priv *priv = hw->priv;
+
+       return priv->ibss_manager == IWL_IBSS_MANAGER;
+}
+EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
+
 static void iwl_ht_conf(struct iwl_priv *priv,
                        struct ieee80211_vif *vif)
 {
index cca7428c238f9676693d111c6cabf0af5511f08c..7f1aaf206078cb926ca87c1c1b727f3d7f056c59 100644 (file)
@@ -350,6 +350,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
 void iwl_activate_qos(struct iwl_priv *priv);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
                    const struct ieee80211_tx_queue_params *params);
+int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
 void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt);
 int iwl_check_rxon_cmd(struct iwl_priv *priv);
 int iwl_full_rxon_required(struct iwl_priv *priv);
index f35bcad56e36bd68779edb3acf930d6b7595359a..599635547021e21cdd568ac0d7e4b5c7491fd817 100644 (file)
@@ -1109,6 +1109,9 @@ struct iwl_priv {
        u32 ucode_beacon_time;
        int missed_beacon_threshold;
 
+       /* track IBSS manager (last beacon) status */
+       u32 ibss_manager;
+
        /* storing the jiffies when the plcp error rate is received */
        unsigned long plcp_jiffies;
 
index de6d592af74871bc1f91c72765c03433b2ad56a1..b14eaf91c7c2bdc4c4bb10b0dc129f9c30eb71ab 100644 (file)
@@ -814,9 +814,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
 static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
                                struct iwl_rx_mem_buffer *rxb)
 {
-#ifdef CONFIG_IWLWIFI_DEBUG
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLWIFI_DEBUG
        u8 rate = beacon->beacon_notify_hdr.rate;
 
        IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
@@ -828,6 +828,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
                le32_to_cpu(beacon->low_tsf), rate);
 #endif
 
+       priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
        if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
            (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
                queue_work(priv->workqueue, &priv->beacon_update);
@@ -3803,6 +3805,7 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .hw_scan = iwl_mac_hw_scan,
        .sta_add = iwl3945_mac_sta_add,
        .sta_remove = iwl_mac_sta_remove,
+       .tx_last_beacon = iwl_mac_tx_last_beacon,
 };
 
 static int iwl3945_init_drv(struct iwl_priv *priv)