msm: rpc: While powering down flush all the rpcrouter workqueues
When the device is powered down, RPC Router closes all the transports
and releases all the associated data structures. This sometimes lead to
works queued in the RPC router workqueues to access stale data and hence
cause kernel panic. So when the device is powered down, abort the works
queued in the workqueues and wait until the workqueues are flushed and
then free the associated data structures.
Change-Id: I3e3381bff21d78bdb100e673eb96cde68bb1aa77
CRs-Fixed: 312078
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/smd_rpcrouter.c b/arch/arm/mach-msm/smd_rpcrouter.c
index 93fa244..983d0c1 100644
--- a/arch/arm/mach-msm/smd_rpcrouter.c
+++ b/arch/arm/mach-msm/smd_rpcrouter.c
@@ -2126,17 +2126,27 @@
int msm_rpcrouter_close(void)
{
- struct rpcrouter_xprt_info *xprt_info, *tmp_xprt_info;
+ struct rpcrouter_xprt_info *xprt_info;
union rr_control_msg ctl;
ctl.cmd = RPCROUTER_CTRL_CMD_BYE;
mutex_lock(&xprt_info_list_lock);
- list_for_each_entry_safe(xprt_info, tmp_xprt_info,
- &xprt_info_list, list) {
+ while (!list_empty(&xprt_info_list)) {
+ xprt_info = list_first_entry(&xprt_info_list,
+ struct rpcrouter_xprt_info, list);
+ xprt_info->abort_data_read = 1;
+ wake_up(&xprt_info->read_wait);
rpcrouter_send_control_msg(xprt_info, &ctl);
xprt_info->xprt->close();
list_del(&xprt_info->list);
+ mutex_unlock(&xprt_info_list_lock);
+
+ flush_workqueue(xprt_info->workqueue);
+ destroy_workqueue(xprt_info->workqueue);
+ wake_lock_destroy(&xprt_info->wakelock);
kfree(xprt_info);
+
+ mutex_lock(&xprt_info_list_lock);
}
mutex_unlock(&xprt_info_list_lock);
return 0;