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

Commit b343ffda authored by Atish Kumar Patra's avatar Atish Kumar Patra
Browse files

glink: Proper channel closing during ssr



The channels are not closed properly during ssr.

Fix the ssr code to invoke link_down to the core for
all the transports present on that subsystem. The link_down
internally moves all the channels to terminal state
and deletes them.

Change-Id: I3cb3e908e8ecf00c362b1da84e538949a1954350
Signed-off-by: default avatarAtish Kumar Patra <apatra@codeaurora.org>
parent e059b11f
Loading
Loading
Loading
Loading
+8 −37
Original line number Diff line number Diff line
@@ -307,9 +307,6 @@ static void ch_remove_tx_pending_remote_done(struct channel_ctx *ctx,
static void glink_core_rx_cmd_rx_intent_req_ack(struct glink_transport_if
					*if_ptr, uint32_t rcid, bool granted);

static void glink_core_simulate_remote_close_for_xprt(
		struct glink_core_xprt_ctx *xprt_ctx);

static void glink_core_remote_close_common(struct channel_ctx *ctx);

static void check_link_notifier_and_notify(struct glink_core_xprt_ctx *xprt_ptr,
@@ -343,9 +340,6 @@ int glink_ssr(const char *subsystem)
				xprt_is_fully_opened(xprt_ctx)) {
			GLINK_INFO_XPRT(xprt_ctx, "%s: SSR\n", __func__);
			xprt_ctx->ops->ssr(xprt_ctx->ops);
			check_link_notifier_and_notify(xprt_ctx,
					GLINK_LINK_STATE_DOWN);
			glink_core_simulate_remote_close_for_xprt(xprt_ctx);
			transport_found = true;
		}
	}
@@ -387,36 +381,6 @@ static void glink_core_remote_close_common(struct channel_ctx *ctx)
	ch_purge_intent_lists(ctx);
}

/**
 * glink_core_simulate_remote_close_for_xprt() - In the case of SSR,
 *                                               simulate receiving a remote
 *                                               close for all channels on a
 *                                               given transport.
 * xprt_ctx:	Pointer to transport instance
 */
static void glink_core_simulate_remote_close_for_xprt(
		struct glink_core_xprt_ctx *xprt_ctx)
{
	struct channel_ctx *entry;
	unsigned long flags;

	spin_lock_irqsave(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
	list_for_each_entry(entry, &xprt_ctx->channels, port_list_node) {
		GLINK_INFO_CH(entry, "%s: Simulating remote close\n", __func__);
		/*
		 * NOTE:  unlocking here is fine as long as channels are not
		 * removed from the transport.
		 */
		spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
		glink_core_remote_close_common(entry);
		spin_lock_irqsave(&xprt_ctx->xprt_ctx_lock_lhb1, flags);

		GLINK_INFO_CH(entry, "%s: Done simulating remote close\n",
				__func__);
	}
	spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1, flags);
}

/**
 * tx_linear_vbuf_provider() - Virtual Buffer Provider for linear buffers
 * @iovec:	Pointer to the beginning of the linear buffer.
@@ -2457,6 +2421,7 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
{
	unsigned long flags;
	struct channel_ctx *ctx, *tmp_ctx;
	struct channel_lcid *temp_lcid, *temp_lcid1;

	spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
	list_for_each_entry_safe(ctx, tmp_ctx, &xprt_ptr->channels,
@@ -2464,7 +2429,8 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
		rwref_get(&ctx->ch_state_lhc0);
		spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags);
		if (!ch_is_fully_closed(ctx)) {
			if (ctx->remote_opened) {
			if (ctx->remote_opened &&
			(ctx->local_open_state == GLINK_CHANNEL_CLOSED)) {
				glink_core_remote_close_common(ctx);
			} else {
				glink_core_remote_close_common(ctx);
@@ -2505,6 +2471,11 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr)
				"channel local state [%d] remote_state [%d]\n",
				ctx->local_open_state, ctx->remote_opened);
		}
		list_for_each_entry_safe(temp_lcid, temp_lcid1,
				&xprt_ptr->free_lcid_list, list_node) {
			list_del(&temp_lcid->list_node);
			kfree(&temp_lcid->list_node);
		}
	}
	spin_unlock_irqrestore(&xprt_ptr->xprt_ctx_lock_lhb1, flags);

+1 −0
Original line number Diff line number Diff line
@@ -805,6 +805,7 @@ static int ssr(struct glink_transport_if *if_ptr)
		ch->is_closing = false;
	}

	einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);
	schedule_delayed_work(&einfo->ssr_work, 5 * HZ);
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -1142,6 +1142,7 @@ static int ssr(struct glink_transport_if *if_ptr)
	einfo->rx_fifo_size = 0;
	einfo->tx_ch_desc->write_index = 0;
	einfo->rx_ch_desc->read_index = 0;
	einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);

	return 0;
}
+5 −2
Original line number Diff line number Diff line
@@ -301,6 +301,8 @@ void glink_ssr_notify_state(void *handle, const void *priv, unsigned event)
		GLINK_INFO("<SSR> %s: event[%d]\n",
				__func__, event);
		cb_data->event = event;
		if (event == GLINK_REMOTE_DISCONNECTED)
			glink_close(handle);
	}
}

@@ -476,7 +478,7 @@ static int notify_for_subsystem(struct subsys_info *ss_info)
			continue;
		}

		glink_tx(handle, (void *)ss_leaf_entry->cb_data,
		ret = glink_tx(handle, (void *)ss_leaf_entry->cb_data,
				(void *)do_cleanup_data,
				sizeof(struct do_cleanup_msg), true);
		if (ret) {
@@ -497,7 +499,8 @@ static int notify_for_subsystem(struct subsys_info *ss_info)

	list_for_each_entry(ss_leaf_entry, &ss_info->notify_list,
			notify_list_node) {
		if (!wait_ret && !ss_leaf_entry->cb_data->responded) {
		if (!wait_ret && !IS_ERR_OR_NULL(ss_leaf_entry->cb_data)
				&& !ss_leaf_entry->cb_data->responded) {
			GLINK_ERR("%s %s: Subsystem %s %s\n",
				"<SSR>", __func__, ss_leaf_entry->edge,
				"failed to respond. Restarting.");