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: Nohee Ko <noheek@broadcom.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
c11b0ef8fe
commit
af73713642
4 changed files with 27 additions and 8 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
#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)
|
||||||
}
|
}
|
||||||
#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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
sched_setscheduler(current, SCHED_FIFO, ¶m);
|
sched_setscheduler(current, SCHED_FIFO, ¶m);
|
||||||
|
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)
|
||||||
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)
|
||||||
struct wl_event_q *e;
|
struct wl_event_q *e;
|
||||||
|
|
||||||
sched_setscheduler(current, SCHED_FIFO, ¶m);
|
sched_setscheduler(current, SCHED_FIFO, ¶m);
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@
|
||||||
#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); \
|
if (tsk) \
|
||||||
tsk = pid_task(pid, PIDTYPE_PID); \
|
send_sig(sig, tsk, 1); \
|
||||||
if (tsk) \
|
|
||||||
send_sig(sig, tsk, 1); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* _linuxver_h_ */
|
#endif /* _linuxver_h_ */
|
||||||
|
|
Loading…
Add table
Reference in a new issue