public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] iwlwifi driver updates 05/15/2009
@ 2009-05-15 23:13 Reinette Chatre
  2009-05-15 23:13 ` [PATCH 1/3] iwlwifi: drop struct iwl3945_hw_key Reinette Chatre
  0 siblings, 1 reply; 7+ messages in thread
From: Reinette Chatre @ 2009-05-15 23:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

We include two cleanup patches in preparation for more 3945 porting
and a fix to kernel.org bug 13224. For this
bugfix we also include a patch that applies to 2.6.30.

[PATCH 1/3] iwlwifi: drop struct iwl3945_hw_key
[PATCH 2/3] iwlwifi: drop iwl3945_tid_data
[PATCH 3/3] iwlwifi: do not cancel delayed work inside spin_lock_irqsave
[PATCH v2.6.30] iwlwifi: do not cancel delayed work inside spin_lock_irqsave


Thank you

Reinette


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] iwlwifi: drop struct iwl3945_hw_key
  2009-05-15 23:13 [PATCH 0/3] iwlwifi driver updates 05/15/2009 Reinette Chatre
@ 2009-05-15 23:13 ` Reinette Chatre
  2009-05-15 23:13   ` [PATCH 2/3] iwlwifi: drop iwl3945_tid_data Reinette Chatre
  0 siblings, 1 reply; 7+ messages in thread
From: Reinette Chatre @ 2009-05-15 23:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Tomas Winkler, Reinette Chatre

From: Tomas Winkler <tomas.winkler@intel.com>

This patch replaces struct iwl3945_hw_key by struct iwl_hw_key.
It's not used directly with any host command therefore removal is trivial

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-dev.h      |    7 +------
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    5 ++---
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 3049ba2..427489a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -503,18 +503,13 @@ struct iwl3945_tid_data {
 	u16 seq_number;
 };
 
-struct iwl3945_hw_key {
-	enum ieee80211_key_alg alg;
-	int keylen;
-	u8 key[32];
-};
 
 struct iwl3945_station_entry {
 	struct iwl3945_addsta_cmd sta;
 	struct iwl3945_tid_data tid[MAX_TID_COUNT];
 	u8 used;
 	u8 ps_status;
-	struct iwl3945_hw_key keyinfo;
+	struct iwl_hw_key keyinfo;
 };
 
 struct iwl_station_entry {
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c32ec80..5d52f22 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -340,7 +340,7 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->sta_lock, flags);
-	memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
+	memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
 	memset(&priv->stations_39[sta_id].sta.key, 0,
 		sizeof(struct iwl4965_keyinfo));
 	priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
@@ -578,8 +578,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
 				      int sta_id)
 {
 	struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	struct iwl3945_hw_key *keyinfo =
-	    &priv->stations_39[sta_id].keyinfo;
+	struct iwl_hw_key *keyinfo = &priv->stations_39[sta_id].keyinfo;
 
 	switch (keyinfo->alg) {
 	case ALG_CCMP:
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] iwlwifi: drop iwl3945_tid_data
  2009-05-15 23:13 ` [PATCH 1/3] iwlwifi: drop struct iwl3945_hw_key Reinette Chatre
@ 2009-05-15 23:13   ` Reinette Chatre
  2009-05-15 23:13     ` [PATCH 3/3] iwlwifi: do not cancel delayed work inside spin_lock_irqsave Reinette Chatre
  0 siblings, 1 reply; 7+ messages in thread
From: Reinette Chatre @ 2009-05-15 23:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Tomas Winkler, Reinette Chatre

From: Tomas Winkler <tomas.winkler@intel.com>

This patch is one of the incremental steps for unifying iwl_station_entry
for all HWs, i.e. removing of iwl3945_station_entry
This patch drops iwl3945_tid_data and use iwl_tid_data instead.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-dev.h |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 427489a..b6b8327 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -499,14 +499,10 @@ struct iwl_qos_info {
 #define STA_PS_STATUS_WAKE             0
 #define STA_PS_STATUS_SLEEP            1
 
-struct iwl3945_tid_data {
-	u16 seq_number;
-};
-
 
 struct iwl3945_station_entry {
 	struct iwl3945_addsta_cmd sta;
-	struct iwl3945_tid_data tid[MAX_TID_COUNT];
+	struct iwl_tid_data tid[MAX_TID_COUNT];
 	u8 used;
 	u8 ps_status;
 	struct iwl_hw_key keyinfo;
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] iwlwifi: do not cancel delayed work inside spin_lock_irqsave
  2009-05-15 23:13   ` [PATCH 2/3] iwlwifi: drop iwl3945_tid_data Reinette Chatre
@ 2009-05-15 23:13     ` Reinette Chatre
  2009-05-15 23:13       ` [PATCH v2.6.30] " Reinette Chatre
  0 siblings, 1 reply; 7+ messages in thread
From: Reinette Chatre @ 2009-05-15 23:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

Calling cancel_delayed_work() from inside
spin_lock_irqsave, introduces a potential deadlock.

As explained by Johannes Berg <johannes@sipsolutions.net>

A - lock
T - timer

phase                   CPU 1           CPU 2
---------------------------------------------

some place that calls
cancel_timer_sync()
(which is the | code)
                                        lock-irq(A)
|                                       "lock-irq"(T)
|                                       "unlock"(T)
|                                       wait(T)
                                        unlock(A)

timer softirq
                        "lock"(T)
                        run(T)
                        "unlock"(T)

irq handler
          lock(A)
          unlock(A)

Now all that again, interleaved, leading to deadlock:

                                        lock-irq(A)
                        "lock"(T)
                         run(T)
IRQ during or maybe
before run(T) -->        lock(A)
                                        "lock-irq"(T)
                                        wait(T)

We fix this by moving the call to cancel_delayed_work() into workqueue.
There are cases where the work may not actually be queued or running
at the time we are trying to cancel it, but cancel_delayed_work() is
able to deal with this.

Also cleanup iwl_set_mode related to this call. This function
(iwl_set_mode) is only called when bringing interface up and there will
thus not be any scanning done. No need to try to cancel scanning.

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13224, which was also
reported at http://marc.info/?l=linux-wireless&m=124081921903223&w=2 .

Tested-by: Miles Lane <miles.lane@gmail.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Acked-by: Zhu Yi <yi.zhu@intel.com>
---
 drivers/net/wireless/iwlwifi/iwl-core.c     |    7 -------
 drivers/net/wireless/iwlwifi/iwl-scan.c     |    7 ++++---
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    2 ++
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5393fb3..967343a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2437,13 +2437,6 @@ int iwl_set_mode(struct iwl_priv *priv, int mode)
 	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
-	cancel_delayed_work(&priv->scan_check);
-	if (iwl_scan_cancel_timeout(priv, 100)) {
-		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-		return -EAGAIN;
-	}
-
 	iwlcore_commit_rxon(priv);
 
 	return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 8029206..41358cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -227,9 +227,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	/* The HW is no longer scanning */
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
-	/* The scan completion notification came in, so kill that timer... */
-	cancel_delayed_work(&priv->scan_check);
-
 	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
 		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
 						"2.4" : "5.2",
@@ -591,6 +588,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
@@ -816,6 +815,8 @@ void iwl_bg_scan_completed(struct work_struct *work)
 
 	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
 
+	cancel_delayed_work(&priv->scan_check);
+
 	priv->scan_request = NULL;
 	ieee80211_scan_completed(priv->hw, false);
 
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 5d52f22..ded7fea 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2995,6 +2995,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2.6.30] iwlwifi:  do not cancel delayed work inside spin_lock_irqsave
  2009-05-15 23:13     ` [PATCH 3/3] iwlwifi: do not cancel delayed work inside spin_lock_irqsave Reinette Chatre
@ 2009-05-15 23:13       ` Reinette Chatre
  2009-05-18 19:22         ` [PATCH] " John W. Linville
  0 siblings, 1 reply; 7+ messages in thread
From: Reinette Chatre @ 2009-05-15 23:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ipw3945-devel, Reinette Chatre

From: Reinette Chatre <reinette.chatre@intel.com>

Calling cancel_delayed_work() from inside
spin_lock_irqsave, introduces a potential deadlock.

As explained by Johannes Berg <johannes@sipsolutions.net>

A - lock
T - timer

phase                   CPU 1           CPU 2
---------------------------------------------

some place that calls
cancel_timer_sync()
(which is the | code)
                                        lock-irq(A)
|                                       "lock-irq"(T)
|                                       "unlock"(T)
|                                       wait(T)
                                        unlock(A)

timer softirq
                        "lock"(T)
                        run(T)
                        "unlock"(T)

irq handler
          lock(A)
          unlock(A)

Now all that again, interleaved, leading to deadlock:

                                        lock-irq(A)
                        "lock"(T)
                         run(T)
IRQ during or maybe
before run(T) -->        lock(A)
                                        "lock-irq"(T)
                                        wait(T)

We fix this by moving the call to cancel_delayed_work() into workqueue.
There are cases where the work may not actually be queued or running
at the time we are trying to cancel it, but cancel_delayed_work() is
able to deal with this.

Also cleanup iwl_set_mode related to this call. This function
(iwl_set_mode) is only called when bringing interface up and there will
thus not be any scanning done. No need to try to cancel scanning.

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13224, which was also
reported at http://marc.info/?l=linux-wireless&m=124081921903223&w=2 .

Tested-by: Miles Lane <miles.lane@gmail.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Acked-by: Zhu Yi <yi.zhu@intel.com>

---
 drivers/net/wireless/iwlwifi/iwl-agn.c      |    7 -------
 drivers/net/wireless/iwlwifi/iwl-scan.c     |    7 ++++---
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    9 ++-------
 3 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 1ef4192..0e6e7ff 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -669,13 +669,6 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode)
 	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
-	cancel_delayed_work(&priv->scan_check);
-	if (iwl_scan_cancel_timeout(priv, 100)) {
-		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-		return -EAGAIN;
-	}
-
 	iwl_commit_rxon(priv);
 
 	return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 23644cf..a879e9c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -227,9 +227,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	/* The HW is no longer scanning */
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
-	/* The scan completion notification came in, so kill that timer... */
-	cancel_delayed_work(&priv->scan_check);
-
 	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
 		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
 						"2.4" : "5.2",
@@ -712,6 +709,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
@@ -925,6 +924,8 @@ void iwl_bg_scan_completed(struct work_struct *work)
 
 	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 617c423..12a2d35 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -782,13 +782,6 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
 	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
-	cancel_delayed_work(&priv->scan_check);
-	if (iwl_scan_cancel_timeout(priv, 100)) {
-		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-		return -EAGAIN;
-	}
-
 	iwl3945_commit_rxon(priv);
 
 	return 0;
@@ -3300,6 +3293,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
-- 
1.5.6.3


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH] iwlwifi: do not cancel delayed work inside spin_lock_irqsave
  2009-05-15 23:13       ` [PATCH v2.6.30] " Reinette Chatre
@ 2009-05-18 19:22         ` John W. Linville
  2009-05-18 21:18           ` reinette chatre
  0 siblings, 1 reply; 7+ messages in thread
From: John W. Linville @ 2009-05-18 19:22 UTC (permalink / raw)
  To: linux-wireless
  Cc: ipw3945-devel, Johannes Berg, Reinette Chatre, John W. Linville

From: Reinette Chatre <reinette.chatre@intel.com>

Calling cancel_delayed_work() from inside
spin_lock_irqsave, introduces a potential deadlock.

As explained by Johannes Berg <johannes@sipsolutions.net>

A - lock
T - timer

phase                   CPU 1           CPU 2
---------------------------------------------

some place that calls
cancel_timer_sync()
(which is the | code)
                                        lock-irq(A)
|                                       "lock-irq"(T)
|                                       "unlock"(T)
|                                       wait(T)
                                        unlock(A)

timer softirq
                        "lock"(T)
                        run(T)
                        "unlock"(T)

irq handler
          lock(A)
          unlock(A)

Now all that again, interleaved, leading to deadlock:

                                        lock-irq(A)
                        "lock"(T)
                         run(T)
IRQ during or maybe
before run(T) -->        lock(A)
                                        "lock-irq"(T)
                                        wait(T)

We fix this by moving the call to cancel_delayed_work() into workqueue.
There are cases where the work may not actually be queued or running
at the time we are trying to cancel it, but cancel_delayed_work() is
able to deal with this.

Also cleanup iwl_set_mode related to this call. This function
(iwl_set_mode) is only called when bringing interface up and there will
thus not be any scanning done. No need to try to cancel scanning.

Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13224, which was also
reported at http://marc.info/?l=linux-wireless&m=124081921903223&w=2 .

Tested-by: Miles Lane <miles.lane@gmail.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Acked-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
Did not apply to 2.6.30-rc6 as posted -- please verify my fix-up!

 drivers/net/wireless/iwlwifi/iwl-agn.c      |    7 -------
 drivers/net/wireless/iwlwifi/iwl-scan.c     |    7 ++++---
 drivers/net/wireless/iwlwifi/iwl3945-base.c |    9 ++-------
 3 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3bb28db..f46ba24 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -669,13 +669,6 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode)
 	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
-	cancel_delayed_work(&priv->scan_check);
-	if (iwl_scan_cancel_timeout(priv, 100)) {
-		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-		return -EAGAIN;
-	}
-
 	iwl_commit_rxon(priv);
 
 	return 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index e7c65c4..6330b91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -227,9 +227,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	/* The HW is no longer scanning */
 	clear_bit(STATUS_SCAN_HW, &priv->status);
 
-	/* The scan completion notification came in, so kill that timer... */
-	cancel_delayed_work(&priv->scan_check);
-
 	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
 		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
 						"2.4" : "5.2",
@@ -712,6 +709,8 @@ static void iwl_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
@@ -925,6 +924,8 @@ void iwl_bg_scan_completed(struct work_struct *work)
 
 	IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
 
+	cancel_delayed_work(&priv->scan_check);
+
 	ieee80211_scan_completed(priv->hw, false);
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4cce661..ff4d0e4 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -782,13 +782,6 @@ static int iwl3945_set_mode(struct iwl_priv *priv, int mode)
 	if (!iwl_is_ready_rf(priv))
 		return -EAGAIN;
 
-	cancel_delayed_work(&priv->scan_check);
-	if (iwl_scan_cancel_timeout(priv, 100)) {
-		IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-		IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-		return -EAGAIN;
-	}
-
 	iwl3945_commit_rxon(priv);
 
 	return 0;
@@ -3298,6 +3291,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
 
 	mutex_lock(&priv->mutex);
 
+	cancel_delayed_work(&priv->scan_check);
+
 	if (!iwl_is_ready(priv)) {
 		IWL_WARN(priv, "request scan called when driver not ready.\n");
 		goto done;
-- 
1.6.0.6


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] iwlwifi: do not cancel delayed work inside spin_lock_irqsave
  2009-05-18 19:22         ` [PATCH] " John W. Linville
@ 2009-05-18 21:18           ` reinette chatre
  0 siblings, 0 replies; 7+ messages in thread
From: reinette chatre @ 2009-05-18 21:18 UTC (permalink / raw)
  To: John W. Linville
  Cc: linux-wireless@vger.kernel.org,
	ipw3945-devel@lists.sourceforge.net, Johannes Berg

Hi John,

On Mon, 2009-05-18 at 12:22 -0700, John W. Linville wrote:
> From: Reinette Chatre <reinette.chatre@intel.com>
> 
> Calling cancel_delayed_work() from inside
> spin_lock_irqsave, introduces a potential deadlock.
> 
> As explained by Johannes Berg <johannes@sipsolutions.net>
> 
> A - lock
> T - timer
> 
> phase                   CPU 1           CPU 2
> ---------------------------------------------
> 
> some place that calls
> cancel_timer_sync()
> (which is the | code)
>                                         lock-irq(A)
> |                                       "lock-irq"(T)
> |                                       "unlock"(T)
> |                                       wait(T)
>                                         unlock(A)
> 
> timer softirq
>                         "lock"(T)
>                         run(T)
>                         "unlock"(T)
> 
> irq handler
>           lock(A)
>           unlock(A)
> 
> Now all that again, interleaved, leading to deadlock:
> 
>                                         lock-irq(A)
>                         "lock"(T)
>                          run(T)
> IRQ during or maybe
> before run(T) -->        lock(A)
>                                         "lock-irq"(T)
>                                         wait(T)
> 
> We fix this by moving the call to cancel_delayed_work() into workqueue.
> There are cases where the work may not actually be queued or running
> at the time we are trying to cancel it, but cancel_delayed_work() is
> able to deal with this.
> 
> Also cleanup iwl_set_mode related to this call. This function
> (iwl_set_mode) is only called when bringing interface up and there will
> thus not be any scanning done. No need to try to cancel scanning.
> 
> Fixes http://bugzilla.kernel.org/show_bug.cgi?id=13224, which was also
> reported at http://marc.info/?l=linux-wireless&m=124081921903223&w=2 .
> 
> Tested-by: Miles Lane <miles.lane@gmail.com>
> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
> Acked-by: Zhu Yi <yi.zhu@intel.com>
> Signed-off-by: John W. Linville <linville@tuxdriver.com>
> ---
> Did not apply to 2.6.30-rc6 as posted -- please verify my fix-up!

I am very sorry - this patch was created against and tested with an
earlier rc release. Thank you very much for fixing it up. It looks good.

Reinette



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-05-18 21:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-05-15 23:13 [PATCH 0/3] iwlwifi driver updates 05/15/2009 Reinette Chatre
2009-05-15 23:13 ` [PATCH 1/3] iwlwifi: drop struct iwl3945_hw_key Reinette Chatre
2009-05-15 23:13   ` [PATCH 2/3] iwlwifi: drop iwl3945_tid_data Reinette Chatre
2009-05-15 23:13     ` [PATCH 3/3] iwlwifi: do not cancel delayed work inside spin_lock_irqsave Reinette Chatre
2009-05-15 23:13       ` [PATCH v2.6.30] " Reinette Chatre
2009-05-18 19:22         ` [PATCH] " John W. Linville
2009-05-18 21:18           ` reinette chatre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox