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

Commit e4811373 authored by Dhoat Harpal's avatar Dhoat Harpal
Browse files

soc: qcom: glink: Add sub system up notification in glink



Glink does not wait for pil to inform about subsystem up. It triggers
link up on first interrupt processed after ssr, this can cause stability
issues if some delayed interrupt is processed after ssr.

Glink waits for PIL to notify about subsystem up and initializes
its state only after that.

CRs-Fixed: 2165753
Change-Id: I71614e6d7e68bf2fa12ac7f27894492019bd3829
Signed-off-by: default avatarDhoat Harpal <hdhoat@codeaurora.org>
parent ad8801e6
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -457,6 +457,42 @@ static void glink_put_ch_ctx(struct channel_ctx *ctx)
	rwref_put(&ctx->ch_state_lhb2);
}


/**
 * glink_subsys_up() - Inform transport about remote subsystem up.
 * @subsystem:	The name of the subsystem
 *
 * Call into the transport using the subsys_up(if_ptr) function to allow it to
 * initialize any necessary structures.
 *
 * Return: Standard error codes.
 */
int glink_subsys_up(const char *subsystem)
{
	int ret = 0;
	bool transport_found = false;
	struct glink_core_xprt_ctx *xprt_ctx = NULL;

	mutex_lock(&transport_list_lock_lha0);
	list_for_each_entry(xprt_ctx, &transport_list, list_node) {
		if (!strcmp(subsystem, xprt_ctx->edge) &&
				!xprt_is_fully_opened(xprt_ctx)) {
			GLINK_INFO_XPRT(xprt_ctx, "%s: %s Subsystem up\n",
							__func__, subsystem);
			if (xprt_ctx->ops->subsys_up)
				xprt_ctx->ops->subsys_up(xprt_ctx->ops);
			transport_found = true;
		}
	}
	mutex_unlock(&transport_list_lock_lha0);

	if (!transport_found)
		ret = -ENODEV;

	return ret;
}
EXPORT_SYMBOL(glink_subsys_up);

/**
 * glink_ssr() - Clean up locally for SSR by simulating remote close
 * @subsystem:	The name of the subsystem being restarted
+9 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -824,6 +824,14 @@ uint32_t glink_ssr_get_seq_num(void);
 */
int glink_ssr(const char *subsystem);

/*
 * glink_subsys_up() - SSR sub system up function.
 * @subsystem:	Constant string for name of remote subsystem.
 *
 * Return: Standard error code.
 */
int glink_subsys_up(const char *subsystem);

/**
 * notify for subsystem() - Notify other subsystems that a subsystem is being
 *                          restarted
+21 −9
Original line number Diff line number Diff line
@@ -947,15 +947,6 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx)

	rcu_id = srcu_read_lock(&einfo->use_ref);

	if (unlikely(!einfo->rx_fifo) && atomic_ctx) {
		if (!get_rx_fifo(einfo)) {
			srcu_read_unlock(&einfo->use_ref, rcu_id);
			return;
		}
		einfo->in_ssr = false;
		einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
	}

	if (einfo->in_ssr) {
		srcu_read_unlock(&einfo->use_ref, rcu_id);
		return;
@@ -1568,6 +1559,24 @@ static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
	srcu_read_unlock(&einfo->use_ref, rcu_id);
}

/**
 * subsys_up() - process a subsystem up notification
 * @if_ptr:	The transport which is up
 *
 */
static void subsys_up(struct glink_transport_if *if_ptr)
{
	struct edge_info *einfo;

	einfo = container_of(if_ptr, struct edge_info, xprt_if);
	if (!einfo->rx_fifo) {
		if (!get_rx_fifo(einfo))
			return;
		einfo->in_ssr = false;
		einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
	}
}

/**
 * ssr() - process a subsystem restart notification of a transport
 * @if_ptr:	The transport to restart
@@ -2261,6 +2270,7 @@ static void init_xprt_if(struct edge_info *einfo)
	einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
	einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
	einfo->xprt_if.ssr = ssr;
	einfo->xprt_if.subsys_up = subsys_up;
	einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
	einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
	einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
@@ -2555,6 +2565,7 @@ static int glink_smem_native_probe(struct platform_device *pdev)
									rc);
		goto request_irq_fail;
	}
	einfo->in_ssr = true;
	rc = enable_irq_wake(irq_line);
	if (rc < 0)
		pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
@@ -3102,6 +3113,7 @@ static int glink_mailbox_probe(struct platform_device *pdev)
	cfg_p_addr = smem_virt_to_phys(mbox_cfg);
	writel_relaxed(lower_32_bits(cfg_p_addr), mbox_loc);
	writel_relaxed(upper_32_bits(cfg_p_addr), mbox_loc + 4);
	einfo->in_ssr = true;
	send_irq(einfo);
	iounmap(mbox_size);
	iounmap(mbox_loc);
+11 −0
Original line number Diff line number Diff line
@@ -492,6 +492,17 @@ static int glink_ssr_restart_notifier_cb(struct notifier_block *this,
					"Subsystem notification failed", ret);
			return ret;
		}
	} else if (code == SUBSYS_AFTER_POWERUP) {
		GLINK_SSR_LOG("<SSR> %s: %s: subsystem restart for %s\n",
				__func__, "SUBSYS_AFTER_POWERUP",
				notifier->subsystem);
		ss_info = get_info_for_subsystem(notifier->subsystem);
		if (ss_info == NULL) {
			GLINK_SSR_ERR("<SSR> %s: ss_info is NULL\n", __func__);
			return -EINVAL;
		}

		glink_subsys_up(ss_info->edge);
	}
	return NOTIFY_DONE;
}
+2 −1
Original line number Diff line number Diff line
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -105,6 +105,7 @@ struct glink_transport_if {
	void (*tx_cmd_ch_remote_close_ack)(struct glink_transport_if *if_ptr,
			uint32_t rcid);
	int (*ssr)(struct glink_transport_if *if_ptr);
	void (*subsys_up)(struct glink_transport_if *if_ptr);

	/* channel data */
	int (*allocate_rx_intent)(struct glink_transport_if *if_ptr,