staging: brcm80211: fix thread blocking issue in brcmf_sdbrcm_bus_stop()
The function brcmf_sdbrcm_bus_stop() terminates the watchdog and dpc thread, but this function can be called from the dpc thread itself. Stopping the dpc thread is only done when it is not the 'current' thread. Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Roland Vossen <rvossen@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
3956b4a2dd
commit
bbbf4f42f5
@ -2694,7 +2694,10 @@ static int brcmf_sdbrcm_dpc_thread(void *data)
|
||||
if (brcmf_sdbrcm_dpc(bus))
|
||||
complete(&bus->dpc_wait);
|
||||
} else {
|
||||
/* after stopping the bus, exit thread */
|
||||
brcmf_sdbrcm_bus_stop(bus);
|
||||
bus->dpc_tsk = NULL;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
@ -3601,25 +3604,25 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
down(&bus->sdsem);
|
||||
|
||||
bus_wake(bus);
|
||||
|
||||
/* Enable clock for device interrupts */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
if (bus->watchdog_tsk) {
|
||||
send_sig(SIGTERM, bus->watchdog_tsk, 1);
|
||||
kthread_stop(bus->watchdog_tsk);
|
||||
bus->watchdog_tsk = NULL;
|
||||
}
|
||||
|
||||
if (bus->dpc_tsk) {
|
||||
if (bus->dpc_tsk && bus->dpc_tsk != current) {
|
||||
send_sig(SIGTERM, bus->dpc_tsk, 1);
|
||||
kthread_stop(bus->dpc_tsk);
|
||||
bus->dpc_tsk = NULL;
|
||||
}
|
||||
|
||||
down(&bus->sdsem);
|
||||
|
||||
bus_wake(bus);
|
||||
|
||||
/* Enable clock for device interrupts */
|
||||
brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false);
|
||||
|
||||
/* Disable and clear interrupts at the chip level also */
|
||||
w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries);
|
||||
local_hostintmask = bus->hostintmask;
|
||||
|
Loading…
x
Reference in New Issue
Block a user