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

Commit 4b77f4ea authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: smp2p: Add restart ack feature"

parents 8071ebfc 5dbb0750
Loading
Loading
Loading
Loading
+104 −29
Original line number Diff line number Diff line
@@ -40,8 +40,12 @@
#define SMP2P_MAX_ENTRY_NAME 16

#define SMP2P_FEATURE_SSR_ACK 0x1
#define SMP2P_FLAGS_RESTART_DONE_BIT 0
#define SMP2P_FLAGS_RESTART_ACK_BIT 1

#define SMP2P_MAGIC 0x504d5324
#define SMP2P_VERSION	1
#define SMP2P_FEATURES	SMP2P_FEATURE_SSR_ACK

/**
 * struct smp2p_smem_item - in memory communication structure
@@ -135,6 +139,10 @@ struct qcom_smp2p {

	unsigned valid_entries;

	bool ssr_ack_enabled;
	bool ssr_ack;
	bool open;

	unsigned local_pid;
	unsigned remote_pid;

@@ -163,42 +171,64 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
	}
}

/**
 * qcom_smp2p_intr() - interrupt handler for incoming notifications
 * @irq:	unused
 * @data:	smp2p driver context
 *
 * Handle notifications from the remote side to handle newly allocated entries
 * or any changes to the state bits of existing entries.
 */
static irqreturn_t qcom_smp2p_intr(int irq, void *data)
static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p)
{
	struct smp2p_smem_item *in;
	struct smp2p_entry *entry;
	struct qcom_smp2p *smp2p = data;
	unsigned long status;
	unsigned smem_id = smp2p->smem_items[SMP2P_INBOUND];
	unsigned pid = smp2p->remote_pid;
	size_t size;
	int irq_pin;
	char buf[SMP2P_MAX_ENTRY_NAME];
	struct smp2p_smem_item *in = smp2p->in;
	bool restart;

	if (!smp2p->ssr_ack_enabled)
		return false;

	restart = in->flags & BIT(SMP2P_FLAGS_RESTART_DONE_BIT);
	if (restart == smp2p->ssr_ack)
		return false;

	return true;
}

static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p)
{
	struct smp2p_smem_item *out = smp2p->out;
	u32 ack;
	u32 val;
	int i;

	in = smp2p->in;
	smp2p->ssr_ack = ack = !smp2p->ssr_ack;
	ack = ack << SMP2P_FLAGS_RESTART_ACK_BIT;

	/* Acquire smem item, if not already found */
	if (!in) {
		in = qcom_smem_get(pid, smem_id, &size);
		if (IS_ERR(in)) {
			dev_err(smp2p->dev,
				"Unable to acquire remote smp2p item\n");
			return IRQ_HANDLED;
	val = out->flags & ~BIT(SMP2P_FLAGS_RESTART_ACK_BIT);
	val |= ack;
	out->flags = val;

	qcom_smp2p_kick(smp2p);
}

		smp2p->in = in;
static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
{
	struct smp2p_smem_item *out = smp2p->out;
	struct smp2p_smem_item *in = smp2p->in;
	u32 features;

	if (in->version == out->version) {
		features = in->features & out->features;
		out->features = features;

		if (features & SMP2P_FEATURE_SSR_ACK)
			smp2p->ssr_ack_enabled = true;

		smp2p->open = true;
	}
}

static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
{
	struct smp2p_smem_item *in = smp2p->in;
	struct smp2p_entry *entry;
	unsigned long status;
	int irq_pin;
	char buf[SMP2P_MAX_ENTRY_NAME];
	u32 val;
	int i;

	/* Match newly created entries */
	for (i = smp2p->valid_entries; i < in->valid_entries; i++) {
		list_for_each_entry(entry, &smp2p->inbound, node) {
@@ -240,6 +270,50 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data)
			}
		}
	}
}

/**
 * qcom_smp2p_intr() - interrupt handler for incoming notifications
 * @irq:	unused
 * @data:	smp2p driver context
 *
 * Handle notifications from the remote side to handle newly allocated entries
 * or any changes to the state bits of existing entries.
 */
static irqreturn_t qcom_smp2p_intr(int irq, void *data)
{
	struct smp2p_smem_item *in;
	struct qcom_smp2p *smp2p = data;
	unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND];
	unsigned int pid = smp2p->remote_pid;
	size_t size;

	in = smp2p->in;

	/* Acquire smem item, if not already found */
	if (!in) {
		in = qcom_smem_get(pid, smem_id, &size);
		if (IS_ERR(in)) {
			dev_err(smp2p->dev,
				"Unable to acquire remote smp2p item\n");
			return IRQ_HANDLED;
		}

		smp2p->in = in;
	}

	if (!smp2p->open)
		qcom_smp2p_negotiate(smp2p);

	if (smp2p->open) {
		bool do_restart;

		do_restart = qcom_smp2p_check_ssr(smp2p);
		qcom_smp2p_notify_in(smp2p);

		if (do_restart)
			qcom_smp2p_do_ssr_ack(smp2p);
	}

	return IRQ_HANDLED;
}
@@ -397,13 +471,14 @@ static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p)
	out->remote_pid = smp2p->remote_pid;
	out->total_entries = SMP2P_MAX_ENTRY;
	out->valid_entries = 0;
	out->features = SMP2P_FEATURES;

	/*
	 * Make sure the rest of the header is written before we validate the
	 * item by writing a valid version number.
	 */
	wmb();
	out->version = 1;
	out->version = SMP2P_VERSION;

	qcom_smp2p_kick(smp2p);