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

Commit 57ede672 authored by Steven Cahail's avatar Steven Cahail
Browse files

soc: qcom: glink: Fix potential infinite loop in scheduler



The SMD Transitional Transport does not expect errors on transmit.
However, such errors could occur if SMD is notified of SSR events before
G-Link.  In rare instances, ignoring such errors could cause the G-Link
core to get stuck in an infinite transmit loop.

If such errors occur, pass them up to the core to correctly manage the
channel and avoid an infinite loop.

CRs-Fixed: 903453
Change-Id: Ia8138b8a000e1bdc330b41d08f3f98fef60d094b
Signed-off-by: default avatarSteven Cahail <scahail@codeaurora.org>
parent c8df36dc
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -4963,6 +4963,13 @@ static int glink_scheduler_tx(struct channel_ctx *ctx,
					"%s: unrecoverable xprt failure %d\n",
					__func__, ret);
			break;
		} else if (!ret && tx_info->size_remaining) {
			/*
			 * Transport unable to send any data on this channel.
			 * Break out of the loop so that the scheduler can
			 * continue with the next channel.
			 */
			break;
		} else {
			txd_len += tx_len;
		}
@@ -5039,6 +5046,15 @@ static void tx_work_func(struct work_struct *work)
					"%s: unrecoverable xprt failure %d\n",
					__func__, ret);
			break;
		} else if (!ret) {
			/*
			 * Transport unable to send any data on this channel,
			 * but didn't return an error. Move to the next channel
			 * and continue.
			 */
			mutex_lock(&xprt_ptr->tx_ready_mutex_lhb2);
			list_rotate_left(&xprt_ptr->prio_bin[prio].tx_ready);
			mutex_unlock(&xprt_ptr->tx_ready_mutex_lhb2);
		}

		mutex_lock(&xprt_ptr->tx_ready_mutex_lhb2);
+9 −9
Original line number Diff line number Diff line
@@ -1581,21 +1581,21 @@ static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
	if (!ch->streaming_ch) {
		if (pctx->size == pctx->size_remaining) {
			rc = smd_write_avail(ch->smd_ch);
			if (!rc) {
			if (rc <= 0) {
				srcu_read_unlock(&einfo->ssr_sync, rcu_id);
				return 0;
				return rc;
			}
			rc = smd_write_start(ch->smd_ch, pctx->size);
			if (rc) {
				srcu_read_unlock(&einfo->ssr_sync, rcu_id);
				return 0;
				return rc;
			}
		}

		rc = smd_write_segment_avail(ch->smd_ch);
		if (!rc) {
		if (rc <= 0) {
			srcu_read_unlock(&einfo->ssr_sync, rcu_id);
			return 0;
			return rc;
		}
		if (rc > tx_size)
			rc = tx_size;
@@ -1604,13 +1604,13 @@ static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
			SMDXPRT_ERR("%s: write segment failed %d\n", __func__,
									rc);
			srcu_read_unlock(&einfo->ssr_sync, rcu_id);
			return 0;
			return rc;
		}
	} else {
		rc = smd_write_avail(ch->smd_ch);
		if (!rc) {
		if (rc <= 0) {
			srcu_read_unlock(&einfo->ssr_sync, rcu_id);
			return 0;
			return rc;
		}
		if (rc > tx_size)
			rc = tx_size;
@@ -1618,7 +1618,7 @@ static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
		if (rc < 0) {
			SMDXPRT_ERR("%s: write failed %d\n", __func__, rc);
			srcu_read_unlock(&einfo->ssr_sync, rcu_id);
			return 0;
			return rc;
		}
	}