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

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

Merge "mailbox: msm_qmp: Add support for suspend to disk"

parents c88ac321 071a8b12
Loading
Loading
Loading
Loading
+58 −5
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ struct qmp_mbox {
	struct completion ch_complete;
	struct delayed_work dwork;
	struct qmp_device *mdev;
	bool suspend_flag;
};

/**
@@ -207,6 +208,7 @@ struct qmp_device {
	struct mbox_chan *mbox_chan;

	void *ilc;
	bool early_boot;
};

/**
@@ -388,7 +390,7 @@ static int qmp_send_data(struct mbox_chan *chan, void *data)
	u32 size;
	int i;

	if (!mbox || !data || mbox->local_state != CHANNEL_CONNECTED)
	if (!mbox || !data || !completion_done(&mbox->ch_complete))
		return -EINVAL;

	mdev = mbox->mdev;
@@ -567,8 +569,7 @@ static void __qmp_rx_worker(struct qmp_mbox *mbox)
		}
		init_mcore_state(mbox);
		mbox->local_state = LINK_NEGOTIATION;
		mbox->rx_pkt.data = devm_kzalloc(mdev->dev,
						 desc.ucore.mailbox_size,
		mbox->rx_pkt.data = kzalloc(desc.ucore.mailbox_size,
					    GFP_KERNEL);
		if (!mbox->rx_pkt.data) {
			QMP_ERR(mdev->ilc, "Failed to allocate rx pkt\n");
@@ -586,6 +587,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) {
			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) {
@@ -729,6 +740,7 @@ static int qmp_mbox_remove(struct platform_device *pdev)

	list_for_each_entry(mbox, &mdev->mboxes, list) {
		mbox_controller_unregister(&mbox->ctrl);
		kfree(mbox->rx_pkt.data);
	}
	return 0;
}
@@ -870,6 +882,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;
@@ -983,6 +996,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);
@@ -1005,18 +1020,56 @@ 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_freeze(struct device *dev)
{
	return 0;
}

static int qmp_mbox_restore(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 */
		kfree(mbox->rx_pkt.data);
		mbox->rx_pkt.data = NULL;
	}
	if (mdev->early_boot)
		qmp_irq_handler(0, mdev);

	return 0;
}

static const struct dev_pm_ops qmp_mbox_pm_ops = {
	.freeze_late = qmp_mbox_freeze,
	.restore_early = qmp_mbox_restore,
};

static struct platform_driver qmp_mbox_driver = {
	.probe = qmp_mbox_probe,
	.remove = qmp_mbox_remove,
	.driver = {
		.name = "qmp_mbox",
		.of_match_table = qmp_mbox_match_table,
		.pm = &qmp_mbox_pm_ops,
	},
};