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

Commit 20d07e36 authored by Jeff Hugo's avatar Jeff Hugo
Browse files

soc: qcom: smd: Catch missed close state transitions



The SMD state machine contains few sync points where it can be ensured that
the remote side has observed a state transition before proceeding to the
next state.  This can lead to situations where the local side misses an
expected state transition and therefore does not perform expected
processing.

If the local side observes a state transition that could have only occurred
if a close state tranition was missed, perform the missed processing.

CRs-Fixed: 933788
Change-Id: I36e0beddc3afc2f96c090d9b856bb6a4a9a9262f
Signed-off-by: default avatarJeffrey Hugo <jhugo@codeaurora.org>
parent 0191ccd5
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -1276,6 +1276,13 @@ static void do_smd_probe(unsigned remote_pid)
	}
}

static void remote_processed_close(struct smd_channel *ch)
{
	/* The remote side has observed our close, we can allow a reopen */
	list_move(&ch->ch_list, &smd_ch_to_close_list);
	queue_work(channel_close_wq, &finalize_channel_close_work);
}

static void smd_state_change(struct smd_channel *ch,
			     unsigned last, unsigned next)
{
@@ -1285,7 +1292,11 @@ static void smd_state_change(struct smd_channel *ch,

	switch (next) {
	case SMD_SS_OPENING:
		if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSING ||
		if (last == SMD_SS_OPENED &&
		    ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED) {
			/* We missed the CLOSING and CLOSED states */
			remote_processed_close(ch);
		} else if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSING ||
		    ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED) {
			ch->half_ch->set_tail(ch->recv, 0);
			ch->half_ch->set_head(ch->send, 0);
@@ -1310,14 +1321,13 @@ static void smd_state_change(struct smd_channel *ch,
			ch->pending_pkt_sz = 0;
			ch->notify(ch->priv, SMD_EVENT_CLOSE);
		}
		/* We missed the CLOSING state */
		if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED)
			remote_processed_close(ch);
		break;
	case SMD_SS_CLOSING:
		if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED) {
			list_move(&ch->ch_list,
					&smd_ch_to_close_list);
			queue_work(channel_close_wq,
						&finalize_channel_close_work);
		}
		if (ch->half_ch->get_state(ch->send) == SMD_SS_CLOSED)
			remote_processed_close(ch);
		break;
	}
}