[PATCH] staging:brcm80211:bug fix- rmmod hang problem

nohee ko noheek at broadcom.com
Tue Oct 12 20:33:29 UTC 2010


Bug fix - rmmod hang problem.
Can keep both of kthread & down_interruptible.
And in the meantime, can terminate the threads
properly during rmmod process.


Signed-off-by: Nohee Ko <noheek at broadcom.com>
---
 drivers/staging/brcm80211/brcmfmac/dhd_linux.c   |    7 +++++++
 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c |   15 ++++++++++++++-
 drivers/staging/brcm80211/brcmfmac/wl_iw.c       |    2 ++
 drivers/staging/brcm80211/include/linuxver.h     |   11 ++++-------
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index 5c8224f..d088aad 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -938,6 +938,8 @@ static int _dhd_sysioc_thread(void *data)
 	bool in_ap = FALSE;
 #endif
 
+	allow_signal(SIGTERM);
+
 	while (down_interruptible(&dhd->sysioc_sem) == 0) {
 		if (kthread_should_stop())
 			break;
@@ -1295,6 +1297,7 @@ static int dhd_watchdog_thread(void *data)
 	}
 #endif				/* DHD_SCHED */
 
+	allow_signal(SIGTERM);
 	/* Run until signal received */
 	while (1) {
 		if (kthread_should_stop())
@@ -1360,6 +1363,7 @@ static int dhd_dpc_thread(void *data)
 	}
 #endif				/* DHD_SCHED */
 
+	allow_signal(SIGTERM);
 	/* Run until signal received */
 	while (1) {
 		if (kthread_should_stop())
@@ -2336,17 +2340,20 @@ void dhd_detach(dhd_pub_t *dhdp)
 			}
 
 			if (dhd->watchdog_tsk) {
+				KILL_PROC(dhd->watchdog_tsk->pid, SIGTERM);
 				kthread_stop(dhd->watchdog_tsk);
 				dhd->watchdog_tsk = NULL;
 			}
 
 			if (dhd->dpc_tsk) {
+				KILL_PROC(dhd->dpc_tsk->pid, SIGTERM);
 				kthread_stop(dhd->dpc_tsk);
 				dhd->dpc_tsk = NULL;
 			} else
 				tasklet_kill(&dhd->tasklet);
 
 			if (dhd->sysioc_tsk) {
+				KILL_PROC(dhd->sysioc_tsk->pid, SIGTERM);
 				kthread_stop(dhd->sysioc_tsk);
 				dhd->sysioc_tsk = NULL;
 			}
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index d05c86d..3455e41 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -2849,6 +2849,7 @@ static s32 wl_create_event_handler(struct wl_priv *wl)
 static void wl_destroy_event_handler(struct wl_priv *wl)
 {
 	if (wl->event_tsk) {
+		KILL_PROC(wl->event_tsk->pid, SIGTERM);
 		kthread_stop(wl->event_tsk);
 		wl->event_tsk = NULL;
 	}
@@ -2860,6 +2861,7 @@ static void wl_term_iscan(struct wl_priv *wl)
 
 	if (wl->iscan_on && iscan->tsk) {
 		iscan->state = WL_ISCAN_STATE_IDLE;
+		KILL_PROC(iscan->tsk->pid, SIGTERM);
 		kthread_stop(iscan->tsk);
 		iscan->tsk = NULL;
 	}
@@ -2994,6 +2996,7 @@ static s32 wl_iscan_thread(void *data)
 	int err = 0;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
+	allow_signal(SIGTERM);
 	status = WL_SCAN_RESULTS_PARTIAL;
 	while (likely(!down_interruptible(&iscan->sync))) {
 		if (kthread_should_stop())
@@ -3015,6 +3018,7 @@ static s32 wl_iscan_thread(void *data)
 		del_timer_sync(&iscan->timer);
 		iscan->timer_on = 0;
 	}
+	WL_DBG(("%s was terminated\n", __func__));
 
 	return 0;
 }
@@ -3215,6 +3219,7 @@ static s32 wl_event_handler(void *data)
 	struct wl_event_q *e;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
+	allow_signal(SIGTERM);
 	while (likely(!down_interruptible(&wl->event_sync))) {
 		if (kthread_should_stop())
 			break;
@@ -3232,6 +3237,7 @@ static s32 wl_event_handler(void *data)
 		}
 		wl_put_event(e);
 	}
+	WL_DBG(("%s was terminated\n", __func__));
 	return 0;
 }
 
@@ -3799,7 +3805,14 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
 	if (wl->scan_request) {
 		cfg80211_scan_done(wl->scan_request, true);	/* true
 								 means abort */
-		wl_set_mpc(ndev, 1);
+		/* wl_set_mpc(wl_to_ndev(wl), 1); */	/* BUG
+						* this operation cannot help
+						* but here because sdio
+						* is already down through
+						* rmmod process.
+						* Need to figure out how to
+						* address this issue
+						*/
 		wl->scan_request = NULL;
 	}
 	clear_bit(WL_STATUS_READY, &wl->status);
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
index 3ee4b54..9f2fcea 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
@@ -1177,6 +1177,7 @@ static int _iscan_sysioc_thread(void *data)
 	iscan_info_t *iscan = (iscan_info_t *) data;
 	static bool iscan_pass_abort = FALSE;
 
+	allow_signal(SIGTERM);
 	status = WL_SCAN_RESULTS_PARTIAL;
 	while (down_interruptible(&iscan->sysioc_sem) == 0) {
 		if (kthread_should_stop())
@@ -3744,6 +3745,7 @@ void wl_iw_detach(void)
 	if (!iscan)
 		return;
 	if (iscan->sysioc_tsk) {
+		KILL_PROC(iscan->sysioc_tsk->pid, SIGTERM);
 		kthread_stop(iscan->sysioc_tsk);
 		iscan->sysioc_tsk = NULL;
 	}
diff --git a/drivers/staging/brcm80211/include/linuxver.h b/drivers/staging/brcm80211/include/linuxver.h
index a3a20ae..eb3c093 100644
--- a/drivers/staging/brcm80211/include/linuxver.h
+++ b/drivers/staging/brcm80211/include/linuxver.h
@@ -35,14 +35,11 @@
 #undef IP_TOS
 #include <asm/io.h>
 
-#define KILL_PROC(nr, sig) \
+#define KILL_PROC(pid, sig) \
 	do { \
 		struct task_struct *tsk; \
-		struct pid *pid;    \
-		pid = find_get_pid((pid_t)nr);    \
-		tsk = pid_task(pid, PIDTYPE_PID);    \
-		if (tsk) \
-			send_sig(sig, tsk, 1); \
+		tsk = pid_task(find_vpid(pid), PIDTYPE_PID);    \
+		if (tsk)	\
+		send_sig(sig, tsk, 1); \
 	} while (0)
-
 #endif				/* _linuxver_h_ */
-- 
1.7.0.4




More information about the devel mailing list