* [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