Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7de90e70 authored by Karthikeyan Ramasubramanian's avatar Karthikeyan Ramasubramanian
Browse files

net: ipc_router: Fix the race condition during SSR



During subsystem restart, SMD XPRT state is checked after starting the
write operation on a SMD channel. The channel state is different from its
corresponding XPRT state. This causes a writer to start the write operation
and then abort it, since the channel is not in reset state and the XPRT is
in reset state. This in turn causes the channel to be busy.

Check the XPRT state first before performing the write operation on its
corresponding channel. Remove the XPRT from the XPRT list at the earliest
possible, so that any write operation on a reset XPRT is avoided.

Change-Id: Id97870d4d6dae2d778fe0b4f39fc5265ffcaa51b
Signed-off-by: default avatarKarthikeyan Ramasubramanian <kramasub@codeaurora.org>
parent 384894c9
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ static int msm_ipc_router_smd_remote_write(void *data,
	if (!len || pkt->length != len)
		return -EINVAL;

	while ((ret = smd_write_start(smd_xprtp->channel, len)) < 0) {
	do {
		spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
		if (smd_xprtp->ss_reset) {
			spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock,
@@ -198,14 +198,16 @@ static int msm_ipc_router_smd_remote_write(void *data,
			return -ENETRESET;
		}
		spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock, flags);
		if (num_retries >= 5) {
		ret = smd_write_start(smd_xprtp->channel, len);
		if (ret < 0 && num_retries >= 5) {
			IPC_RTR_ERR("%s: Error %d @smd_write_start for %s\n",
				__func__, ret, xprt->name);
			return ret;
		}
		} else if (ret < 0) {
			msleep(50);
			num_retries++;
		}
	} while (ret < 0);

	D("%s: Ready to write %d bytes\n", __func__, len);
	skb_queue_walk(pkt->pkt_fragment_q, ipc_rtr_pkt) {
+2 −1
Original line number Diff line number Diff line
@@ -3272,6 +3272,8 @@ static void msm_ipc_router_remove_xprt(struct msm_ipc_router_xprt *xprt)
		list_del(&xprt_info->list);
		up_write(&xprt_info_list_lock_lha5);

		msm_ipc_cleanup_routing_table(xprt_info);

		flush_workqueue(xprt_info->workqueue);
		destroy_workqueue(xprt_info->workqueue);
		wakeup_source_trash(&xprt_info->ws);
@@ -3301,7 +3303,6 @@ static void xprt_close_worker(struct work_struct *work)
	struct msm_ipc_router_xprt_work *xprt_work =
		container_of(work, struct msm_ipc_router_xprt_work, work);

	msm_ipc_cleanup_routing_table(xprt_work->xprt->priv);
	msm_ipc_router_remove_xprt(xprt_work->xprt);
	xprt_work->xprt->sft_close_done(xprt_work->xprt);
	kfree(xprt_work);