diff mbox

mac80211: Fix deadlock in ieee80211_do_stop.

Message ID 4D010114.5020604@gmail.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Tejun Heo Dec. 9, 2010, 4:17 p.m. UTC
None
diff mbox

Patch

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b80c386..0ebc386 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -933,6 +933,10 @@  struct ieee80211_local {
 	struct net_device napi_dev;

 	struct napi_struct napi;
+
+	struct timer_list iface_work_timer;
+	unsigned long iface_work_tstmp;
+	unsigned int iface_work_runcnt;
 };

 static inline struct ieee80211_sub_if_data *
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7aa8559..074d5bd 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -715,6 +715,14 @@  static void ieee80211_if_setup(struct net_device *dev)
 	dev->destructor = free_netdev;
 }

+static void dbg_watchdog_timer(unsigned long __arg)
+{
+	struct ieee80211_local *local = (void *)__arg;
+
+	pr_warning("ieee80211_iface_work ran for > 5secs, processed %u\n",
+		   local->iface_work_runcnt);
+}
+
 static void ieee80211_iface_work(struct work_struct *work)
 {
 	struct ieee80211_sub_if_data *sdata =
@@ -738,10 +746,21 @@  static void ieee80211_iface_work(struct work_struct *work)
 		 "interface work scheduled while going to suspend\n"))
 		return;

+	local->iface_work_tstmp = jiffies;
+	local->iface_work_runcnt = 0;
+
+	init_timer(&local->iface_work_timer);
+	local->iface_work_timer.function = dbg_watchdog_timer;
+	local->iface_work_timer.data = (unsigned long)local;
+	local->iface_work_timer.expires = local->iface_work_tstmp + 5 * HZ;
+	add_timer(&local->iface_work_timer);
+
 	/* first process frames */
 	while ((skb = skb_dequeue(&sdata->skb_queue))) {
 		struct ieee80211_mgmt *mgmt = (void *)skb->data;

+		local->iface_work_runcnt++;
+
 		if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) {
 			ra_tid = (void *)&skb->cb;
 			ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra,
@@ -843,6 +862,12 @@  static void ieee80211_iface_work(struct work_struct *work)
 	default:
 		break;
 	}
+
+	del_timer_sync(&local->iface_work_timer);
+	if (time_after(jiffies, local->iface_work_tstmp + 4 * HZ))
+		pr_warning("iee80211_iface_work ran for %lu seconds, runcnt=%u\n",
+			   (jiffies - local->iface_work_tstmp) / HZ,
+			   local->iface_work_runcnt);
 }