iwlwifi: enhance WPA authenication stability
This patch enhanced WPA authenication stability by avoiding scan
immediately followed by association. We don't do any scanning right
after association in next several seconds. This will allow WPA
authentication to take place without any interruption.
Signed-off-by: Mohamed Abbas <mabbas@linux.intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 51b9030..1b81545 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -285,6 +285,8 @@
rxb->skb = NULL;
}
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
struct iwl3945_rx_mem_buffer *rxb)
{
@@ -442,6 +444,13 @@
case IEEE80211_STYPE_REASSOC_RESP:{
struct ieee80211_mgmt *mgnt =
(struct ieee80211_mgmt *)header;
+
+ /* We have just associated, give some
+ * time for the 4-way handshake if
+ * any. Don't start scan too early. */
+ priv->next_scan_jiffies = jiffies +
+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+
priv->assoc_id = (~((1 << 15) | (1 << 14)) &
le16_to_cpu(mgnt->u.
assoc_resp.aid));
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 75cef3ed..1f82061 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -752,6 +752,7 @@
/* Scan related variables */
unsigned long last_scan_jiffies;
+ unsigned long next_scan_jiffies;
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 40c795e..c8e7adf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -3802,6 +3802,8 @@
}
}
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
/* Called for REPLY_4965_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
@@ -3973,6 +3975,12 @@
struct ieee80211_mgmt *mgnt =
(struct ieee80211_mgmt *)header;
+ /* We have just associated, give some
+ * time for the 4-way handshake if
+ * any. Don't start scan too early. */
+ priv->next_scan_jiffies = jiffies +
+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+
priv->assoc_id = (~((1 << 15) | (1 << 14))
& le16_to_cpu(mgnt->u.assoc_resp.aid));
priv->assoc_capability =
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 2930c10..c062738 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -1082,6 +1082,7 @@
/* Scan related variables */
unsigned long last_scan_jiffies;
+ unsigned long next_scan_jiffies;
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 71e9b7c..82c1e0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2800,7 +2800,8 @@
IWL_DEBUG_TX("Sending REASSOC frame\n");
#endif
- if (!iwl3945_is_associated(priv) &&
+ /* drop all data frame if we are not associated */
+ if (!iwl3945_is_associated(priv) && !priv->assoc_id &&
((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
goto drop_unlock;
@@ -3737,6 +3738,7 @@
(priv->last_scan_jiffies, jiffies)));
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -3779,6 +3781,7 @@
}
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO("Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
@@ -6806,6 +6809,8 @@
mutex_unlock(&priv->mutex);
}
+#define IWL_DELAY_NEXT_SCAN (HZ*2)
+
static void iwl3945_bg_post_associate(struct work_struct *data)
{
struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv,
@@ -6906,6 +6911,8 @@
#ifdef CONFIG_IWL3945_QOS
iwl3945_activate_qos(priv, 0);
#endif /* CONFIG_IWL3945_QOS */
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
mutex_unlock(&priv->mutex);
}
@@ -7338,7 +7345,6 @@
}
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
{
int rc = 0;
@@ -7362,16 +7368,20 @@
goto out_unlock;
}
+ /* we don't schedule scan within next_scan_jiffies period */
+ if (priv->next_scan_jiffies &&
+ time_after(priv->next_scan_jiffies, jiffies)) {
+ rc = -EAGAIN;
+ goto out_unlock;
+ }
/* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies &&
- time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
- jiffies)) {
+ if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
+ IWL_DELAY_NEXT_SCAN, jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
if (len) {
- IWL_DEBUG_SCAN("direct scan for "
- "%s [%d]\n ",
+ IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
iwl3945_escape_essid(ssid, len), (int)len);
priv->one_direct_scan = 1;
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index e15986c..670f611 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -2905,7 +2905,8 @@
IWL_DEBUG_TX("Sending REASSOC frame\n");
#endif
- if (!iwl4965_is_associated(priv) &&
+ /* drop all data frame if we are not associated */
+ if (!iwl4965_is_associated(priv) && !priv->assoc_id &&
((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
goto drop_unlock;
@@ -4055,6 +4056,7 @@
(priv->last_scan_jiffies, jiffies)));
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@@ -4097,6 +4099,7 @@
}
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO("Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
@@ -7228,6 +7231,8 @@
mutex_unlock(&priv->mutex);
}
+#define IWL_DELAY_NEXT_SCAN (HZ*2)
+
static void iwl4965_bg_post_associate(struct work_struct *data)
{
struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv,
@@ -7343,6 +7348,8 @@
#ifdef CONFIG_IWL4965_QOS
iwl4965_activate_qos(priv, 0);
#endif /* CONFIG_IWL4965_QOS */
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
mutex_unlock(&priv->mutex);
}
@@ -7811,7 +7818,6 @@
iwl4965_send_rxon_assoc(priv);
}
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
{
int rc = 0;
@@ -7835,16 +7841,20 @@
goto out_unlock;
}
+ /* we don't schedule scan within next_scan_jiffies period */
+ if (priv->next_scan_jiffies &&
+ time_after(priv->next_scan_jiffies, jiffies)) {
+ rc = -EAGAIN;
+ goto out_unlock;
+ }
/* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies &&
- time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
- jiffies)) {
+ if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
+ IWL_DELAY_NEXT_SCAN, jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
if (len) {
- IWL_DEBUG_SCAN("direct scan for "
- "%s [%d]\n ",
+ IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
iwl4965_escape_essid(ssid, len), (int)len);
priv->one_direct_scan = 1;