Commit af737136 authored by nohee ko's avatar nohee ko Committed by Greg Kroah-Hartman

staging: brcm80211: bug fix- rmmod hang problem

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: default avatarNohee Ko <noheek@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c11b0ef8
...@@ -938,6 +938,8 @@ static int _dhd_sysioc_thread(void *data) ...@@ -938,6 +938,8 @@ static int _dhd_sysioc_thread(void *data)
bool in_ap = false; bool in_ap = false;
#endif #endif
allow_signal(SIGTERM);
while (down_interruptible(&dhd->sysioc_sem) == 0) { while (down_interruptible(&dhd->sysioc_sem) == 0) {
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
...@@ -1295,6 +1297,7 @@ static int dhd_watchdog_thread(void *data) ...@@ -1295,6 +1297,7 @@ static int dhd_watchdog_thread(void *data)
} }
#endif /* DHD_SCHED */ #endif /* DHD_SCHED */
allow_signal(SIGTERM);
/* Run until signal received */ /* Run until signal received */
while (1) { while (1) {
if (kthread_should_stop()) if (kthread_should_stop())
...@@ -1360,6 +1363,7 @@ static int dhd_dpc_thread(void *data) ...@@ -1360,6 +1363,7 @@ static int dhd_dpc_thread(void *data)
} }
#endif /* DHD_SCHED */ #endif /* DHD_SCHED */
allow_signal(SIGTERM);
/* Run until signal received */ /* Run until signal received */
while (1) { while (1) {
if (kthread_should_stop()) if (kthread_should_stop())
...@@ -2336,17 +2340,20 @@ void dhd_detach(dhd_pub_t *dhdp) ...@@ -2336,17 +2340,20 @@ void dhd_detach(dhd_pub_t *dhdp)
} }
if (dhd->watchdog_tsk) { if (dhd->watchdog_tsk) {
KILL_PROC(dhd->watchdog_tsk->pid, SIGTERM);
kthread_stop(dhd->watchdog_tsk); kthread_stop(dhd->watchdog_tsk);
dhd->watchdog_tsk = NULL; dhd->watchdog_tsk = NULL;
} }
if (dhd->dpc_tsk) { if (dhd->dpc_tsk) {
KILL_PROC(dhd->dpc_tsk->pid, SIGTERM);
kthread_stop(dhd->dpc_tsk); kthread_stop(dhd->dpc_tsk);
dhd->dpc_tsk = NULL; dhd->dpc_tsk = NULL;
} else } else
tasklet_kill(&dhd->tasklet); tasklet_kill(&dhd->tasklet);
if (dhd->sysioc_tsk) { if (dhd->sysioc_tsk) {
KILL_PROC(dhd->sysioc_tsk->pid, SIGTERM);
kthread_stop(dhd->sysioc_tsk); kthread_stop(dhd->sysioc_tsk);
dhd->sysioc_tsk = NULL; dhd->sysioc_tsk = NULL;
} }
......
...@@ -2849,6 +2849,7 @@ static s32 wl_create_event_handler(struct wl_priv *wl) ...@@ -2849,6 +2849,7 @@ static s32 wl_create_event_handler(struct wl_priv *wl)
static void wl_destroy_event_handler(struct wl_priv *wl) static void wl_destroy_event_handler(struct wl_priv *wl)
{ {
if (wl->event_tsk) { if (wl->event_tsk) {
KILL_PROC(wl->event_tsk->pid, SIGTERM);
kthread_stop(wl->event_tsk); kthread_stop(wl->event_tsk);
wl->event_tsk = NULL; wl->event_tsk = NULL;
} }
...@@ -2860,6 +2861,7 @@ static void wl_term_iscan(struct wl_priv *wl) ...@@ -2860,6 +2861,7 @@ static void wl_term_iscan(struct wl_priv *wl)
if (wl->iscan_on && iscan->tsk) { if (wl->iscan_on && iscan->tsk) {
iscan->state = WL_ISCAN_STATE_IDLE; iscan->state = WL_ISCAN_STATE_IDLE;
KILL_PROC(iscan->tsk->pid, SIGTERM);
kthread_stop(iscan->tsk); kthread_stop(iscan->tsk);
iscan->tsk = NULL; iscan->tsk = NULL;
} }
...@@ -2994,6 +2996,7 @@ static s32 wl_iscan_thread(void *data) ...@@ -2994,6 +2996,7 @@ static s32 wl_iscan_thread(void *data)
int err = 0; int err = 0;
sched_setscheduler(current, SCHED_FIFO, &param); sched_setscheduler(current, SCHED_FIFO, &param);
allow_signal(SIGTERM);
status = WL_SCAN_RESULTS_PARTIAL; status = WL_SCAN_RESULTS_PARTIAL;
while (likely(!down_interruptible(&iscan->sync))) { while (likely(!down_interruptible(&iscan->sync))) {
if (kthread_should_stop()) if (kthread_should_stop())
...@@ -3015,6 +3018,7 @@ static s32 wl_iscan_thread(void *data) ...@@ -3015,6 +3018,7 @@ static s32 wl_iscan_thread(void *data)
del_timer_sync(&iscan->timer); del_timer_sync(&iscan->timer);
iscan->timer_on = 0; iscan->timer_on = 0;
} }
WL_DBG(("%s was terminated\n", __func__));
return 0; return 0;
} }
...@@ -3215,6 +3219,7 @@ static s32 wl_event_handler(void *data) ...@@ -3215,6 +3219,7 @@ static s32 wl_event_handler(void *data)
struct wl_event_q *e; struct wl_event_q *e;
sched_setscheduler(current, SCHED_FIFO, &param); sched_setscheduler(current, SCHED_FIFO, &param);
allow_signal(SIGTERM);
while (likely(!down_interruptible(&wl->event_sync))) { while (likely(!down_interruptible(&wl->event_sync))) {
if (kthread_should_stop()) if (kthread_should_stop())
break; break;
...@@ -3232,6 +3237,7 @@ static s32 wl_event_handler(void *data) ...@@ -3232,6 +3237,7 @@ static s32 wl_event_handler(void *data)
} }
wl_put_event(e); wl_put_event(e);
} }
WL_DBG(("%s was terminated\n", __func__));
return 0; return 0;
} }
...@@ -3799,7 +3805,14 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) ...@@ -3799,7 +3805,14 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
if (wl->scan_request) { if (wl->scan_request) {
cfg80211_scan_done(wl->scan_request, true); /* true cfg80211_scan_done(wl->scan_request, true); /* true
means abort */ 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; wl->scan_request = NULL;
} }
clear_bit(WL_STATUS_READY, &wl->status); clear_bit(WL_STATUS_READY, &wl->status);
......
...@@ -1177,6 +1177,7 @@ static int _iscan_sysioc_thread(void *data) ...@@ -1177,6 +1177,7 @@ static int _iscan_sysioc_thread(void *data)
iscan_info_t *iscan = (iscan_info_t *) data; iscan_info_t *iscan = (iscan_info_t *) data;
static bool iscan_pass_abort = false; static bool iscan_pass_abort = false;
allow_signal(SIGTERM);
status = WL_SCAN_RESULTS_PARTIAL; status = WL_SCAN_RESULTS_PARTIAL;
while (down_interruptible(&iscan->sysioc_sem) == 0) { while (down_interruptible(&iscan->sysioc_sem) == 0) {
if (kthread_should_stop()) if (kthread_should_stop())
...@@ -3744,6 +3745,7 @@ void wl_iw_detach(void) ...@@ -3744,6 +3745,7 @@ void wl_iw_detach(void)
if (!iscan) if (!iscan)
return; return;
if (iscan->sysioc_tsk) { if (iscan->sysioc_tsk) {
KILL_PROC(iscan->sysioc_tsk->pid, SIGTERM);
kthread_stop(iscan->sysioc_tsk); kthread_stop(iscan->sysioc_tsk);
iscan->sysioc_tsk = NULL; iscan->sysioc_tsk = NULL;
} }
......
...@@ -35,14 +35,11 @@ ...@@ -35,14 +35,11 @@
#undef IP_TOS #undef IP_TOS
#include <asm/io.h> #include <asm/io.h>
#define KILL_PROC(nr, sig) \ #define KILL_PROC(pid, sig) \
do { \ do { \
struct task_struct *tsk; \ struct task_struct *tsk; \
struct pid *pid; \ tsk = pid_task(find_vpid(pid), PIDTYPE_PID); \
pid = find_get_pid((pid_t)nr); \
tsk = pid_task(pid, PIDTYPE_PID); \
if (tsk) \ if (tsk) \
send_sig(sig, tsk, 1); \ send_sig(sig, tsk, 1); \
} while (0) } while (0)
#endif /* _linuxver_h_ */ #endif /* _linuxver_h_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment