Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3863

kernel-2.6.18-194.11.1.el5.src.rpm

From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 18 May 2009 17:11:31 +0200
Subject: [wireless] mac80211: freeze when ath5k IF brought down
Message-id: 20090518171131.06eb67c1@brian.englab.brq.redhat.com
O-Subject: [RHEL5.4 PATCH] BZ499999: mac80211: fix freeze when an ath5k interface is brought down
Bugzilla: 499999
RH-Acked-by: John W. Linville <linville@redhat.com>
RH-Acked-by: Andy Gospodarek <gospo@redhat.com>

BZ: https://bugzilla.redhat.com/show_bug.cgi?id=499999

Description:
When an ath5k wireless interface is brought down (using ifdown wlan0 or
on shutdown), bad things happen. The reporters' machines freeze
completely. On my system the process just enters eternal uninterruptible
sleep.

The bug was introduced in 2.6.18-135.el5 by the patch
    [wireless] iwlwifi: booting with RF-kill switch enabled

In ieee80211_stop(), upstream uses
cancel_delayed_work_sync(&local->scan_work). Since this function is not
available in RHEL5, the patch used cancel_rearming_delayed_work(...)
instead. One reason this was wrong is that scan_work does not
run on the shared keventd workqueue.

A better substitute for cancel_delayed_work_sync() is
cancel_delayed_work()+flush_workqueue().

Brew build:
https://brewweb.devel.redhat.com/taskinfo?taskID=1801354

KABI:
no effect

Testing:
I reproduced the problem and the patch fixed it. One of the reporters
confirmed it fixed the bug for him too (he reported an additional
issue, but he reproduced that on plain -148.el5 too, so it's not
related to my patch).

Upstream status:
Upstream uses cancel_delayed_work_sync() which we don't have in RHEL5.

--
Michal

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 719c331..adee776 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -533,8 +533,10 @@ static int ieee80211_stop(struct net_device *dev)
 		/* fall through */
 	default:
 		if (local->scan_dev == sdata->dev) {
-			if (!local->ops->hw_scan)
-				cancel_rearming_delayed_work(&local->scan_work);
+			if (!local->ops->hw_scan) {
+				cancel_delayed_work(&local->scan_work);
+				flush_workqueue(local->hw.workqueue);
+			}
 			/*
 			 * The software scan can no longer run now, so we can
 			 * clear out the scan_dev reference. However, the