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

Commit d0606a64 authored by Arun Prakash P P's avatar Arun Prakash P P Committed by ArunPrakash
Browse files

mailbox: msm_qmp: Add support for suspend to disk



Add support in qmp driver for suspend to disk feature.

Change-Id: I0135b8fd4efc9168545e63c82e020aa0f407a638
Signed-off-by: default avatarRama Krishna Phani A <rphani@codeaurora.org>
Signed-off-by: default avatarArunPrakash <app@codeaurora.org>
parent e8d900e1
Loading
Loading
Loading
Loading
+66 −3
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, 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
@@ -168,6 +168,7 @@ struct qmp_mbox {
	struct completion ch_complete;
	struct delayed_work dwork;
	struct qmp_device *mdev;
	bool suspend_flag;
};

/**
@@ -208,6 +209,7 @@ struct qmp_device {
	u32 rx_irq_count;

	void *ilc;
	bool early_boot;
};

/**
@@ -376,8 +378,14 @@ static int qmp_send_data(struct mbox_chan *chan, void *data)
	unsigned long flags;
	int i;

	if (!mbox || !data || mbox->local_state != CHANNEL_CONNECTED)
	if (!mbox || !data)
		return -EINVAL;
	/*
	 * Return -EAGAIN if client tried to send data after hibernation
	 * and channel is not yet opened
	 */
	if (!completion_done(&mbox->ch_complete))
		return -EAGAIN;

	mdev = mbox->mdev;

@@ -568,6 +576,16 @@ static void __qmp_rx_worker(struct qmp_mbox *mbox)
		mbox->local_state = LINK_CONNECTED;
		complete_all(&mbox->link_complete);
		QMP_INFO(mdev->ilc, "Set to link connected\n");
		/*
		 * If link connection happened after hibernation
		 * manualy trigger the channel open procedure since client
		 * won't try to re-open the channel
		 */
		if (mbox->suspend_flag == true) {
			set_mcore_ch(mbox, QMP_MBOX_CH_CONNECTED);
			mbox->local_state = LOCAL_CONNECTING;
			send_irq(mbox->mdev);
		}
		break;
	case LINK_CONNECTED:
		if (desc.ucore.ch_state == desc.ucore.ch_state_ack) {
@@ -851,6 +869,7 @@ static int qmp_mbox_init(struct device_node *n, struct qmp_device *mdev)
	mbox->tx_sent = false;
	mbox->num_assigned = 0;
	INIT_DELAYED_WORK(&mbox->dwork, qmp_notify_timeout);
	mbox->suspend_flag = false;

	mdev_add_mbox(mdev, mbox);
	return 0;
@@ -938,6 +957,8 @@ static int qmp_mbox_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	dev_set_drvdata(&pdev->dev, mdev);

	mdev->ilc = ipc_log_context_create(QMP_IPC_LOG_PAGE_CNT, mdev->name, 0);

	kthread_init_work(&mdev->kwork, rx_worker);
@@ -960,12 +981,53 @@ static int qmp_mbox_probe(struct platform_device *pdev)
			mdev->rx_irq_line, ret);

	/* Trigger fake RX in case of missed interrupt */
	if (of_property_read_bool(edge_node, "qcom,early-boot"))
	if (of_property_read_bool(edge_node, "qcom,early-boot")) {
		mdev->early_boot = true;
		qmp_irq_handler(0, mdev);
	}

	return 0;
}

static int qmp_mbox_suspend(struct device *dev)
{
	struct qmp_device *mdev = dev_get_drvdata(dev);
	struct qmp_mbox *mbox;

	list_for_each_entry(mbox, &mdev->mboxes, list) {
		mbox->local_state = LINK_DISCONNECTED;
		init_completion(&mbox->link_complete);
		init_completion(&mbox->ch_complete);
		mbox->tx_sent = false;
		/*
		 * set suspend flag to indicate self channel open is required
		 * after restore operation
		 */
		mbox->suspend_flag = true;
		/* Release rx packet buffer */
		if (mbox->rx_pkt.data) {
			devm_kfree(mdev->dev, mbox->rx_pkt.data);
			mbox->rx_pkt.data = NULL;
		}
	}
	return 0;
}

static int qmp_mbox_resume(struct device *dev)
{
	struct qmp_device *mdev = dev_get_drvdata(dev);

		if (mdev->early_boot)
			qmp_irq_handler(0, mdev);

	return 0;
}

static const struct dev_pm_ops qmp_mbox_pm_ops = {
	.freeze = qmp_mbox_suspend,
	.restore = qmp_mbox_resume,
};

static struct platform_driver qmp_mbox_driver = {
	.probe = qmp_mbox_probe,
	.remove = qmp_mbox_remove,
@@ -973,6 +1035,7 @@ static struct platform_driver qmp_mbox_driver = {
		.name = "qmp_mbox",
		.owner = THIS_MODULE,
		.of_match_table = qmp_mbox_match_table,
		.pm = &qmp_mbox_pm_ops,
	},
};