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