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

Commit 991ca50f authored by Konstantin Dorfman's avatar Konstantin Dorfman Committed by Gerrit - the friendly Code Review server
Browse files

soc: qcom: spcom: maintain wakeup window when active packet exchange



This change activate PM wakeup source in following way:
1. Activate on receive a spcom request from SPU
2. Close window in the end of packet exchange or timeout:
   - end of tx of spcom response to SPU (server case)
   - end of delivery of spcom request to usersace (client case)
   - timeout for handling a packet exchange for 2 seconds

Change-Id: Ibbb6ba9870226299e5731fda6133c3dde780ca25
Signed-off-by: default avatarKonstantin Dorfman <kdorfman@codeaurora.org>
parent 8b0fa0a0
Loading
Loading
Loading
Loading
+42 −34
Original line number Diff line number Diff line
@@ -150,6 +150,11 @@
 */
#define INITIAL_TXN_ID	0x12345678

/*
 * Max time to keep PM from suspend.
 * From receive RPMSG packet till wakeup source will be deactivated.
 */
#define SPCOM_PM_PACKET_HANDLE_TIMEOUT  (2 * MSEC_PER_SEC)
/**
 * struct spcom_msg_hdr - Request/Response message header between HLOS and SP.
 *
@@ -259,6 +264,7 @@ struct spcom_device {
	struct class *driver_class;
	struct device *class_dev;
	struct platform_device *pdev;
	struct wakeup_source *ws;

	/* rpmsg channels */
	struct spcom_channel channels[SPCOM_MAX_CHANNELS];
@@ -272,7 +278,6 @@ struct spcom_device {
	/* rx data path */
	struct list_head    rx_list_head;
	spinlock_t          rx_lock;
	atomic_t            rx_active_count;

	int32_t nvm_ion_fd;
	struct mutex ioctl_lock;
@@ -290,34 +295,6 @@ static struct spcom_channel *spcom_find_channel_by_name(const char *name);
static int spcom_register_rpmsg_drv(struct spcom_channel *ch);
static int spcom_unregister_rpmsg_drv(struct spcom_channel *ch);

/**
 * spcom_suspend() - spcom vote for PM runtime-suspend
 *
 * Suspend callback for the device
 * Return 0 on Success, -EBUSY on rx in progress.
 */
static int spcom_suspend(struct device *dev)
{
	(void) *dev;
	if (atomic_read(&spcom_dev->rx_active_count) > 0) {
		spcom_pr_dbg("ch [%s]: rx_active_count\n",
					 spcom_dev->rx_active_count);
		return -EBUSY;
	}

	spcom_pr_err("channel voten\n");
	return 0;
}

/**
 * struct spcom_dev_pm_ops
 *
 * Set PM operations : Suspend, Resume, Idle
 */
static const struct dev_pm_ops spcom_dev_pm_ops = {
	SET_RUNTIME_PM_OPS(spcom_suspend, NULL, NULL)
};

/**
 * spcom_is_channel_open() - channel is open on this side.
 *
@@ -503,7 +480,6 @@ static int spcom_rx(struct spcom_channel *ch,
	if (!ch->actual_rx_size) {
		reinit_completion(&ch->rx_done);

		atomic_inc(&spcom_dev->rx_active_count);
		mutex_unlock(&ch->lock); /* unlock while waiting */
		/* wait for rx response */
		if (timeout_msec)
@@ -512,7 +488,7 @@ static int spcom_rx(struct spcom_channel *ch,
		else
			ret = wait_for_completion_interruptible(&ch->rx_done);
		mutex_lock(&ch->lock);
		atomic_dec(&spcom_dev->rx_active_count);

		if (timeout_msec && timeleft == 0) {
			spcom_pr_err("ch[%s]: timeout expired %d ms, set txn_id=%d\n",
			       ch->name, timeout_msec, ch->txn_id);
@@ -558,6 +534,7 @@ static int spcom_rx(struct spcom_channel *ch,
	return size;
exit_err:
	mutex_unlock(&ch->lock);

	return ret;
}

@@ -863,6 +840,12 @@ static int spcom_handle_send_command(struct spcom_channel *ch,
	if (ret)
		spcom_pr_err("ch [%s] rpmsg_trysend() error (%d), timeout_msec=%d\n",
		       ch->name, ret, timeout_msec);

	if (ch->is_server) {
		__pm_relax(spcom_dev->ws);
		spcom_pr_dbg("ch[%s]:pm_relax() called for server, after tx\n",
			     ch->name);
	}
	mutex_unlock(&ch->lock);

	kfree(tx_buf);
@@ -1074,6 +1057,11 @@ static int spcom_handle_send_modified_command(struct spcom_channel *ch,
		spcom_pr_err("ch [%s] rpmsg_trysend() error (%d), timeout_msec=%d\n",
		       ch->name, ret, timeout_msec);

	if (ch->is_server) {
		__pm_relax(spcom_dev->ws);
		spcom_pr_dbg("ch[%s]:pm_relax() called for server, after tx\n",
			     ch->name);
	}
	mutex_unlock(&ch->lock);
	memset(tx_buf, 0, tx_buf_size);
	kfree(tx_buf);
@@ -1463,6 +1451,14 @@ static int spcom_handle_read(struct spcom_channel *ch,
		ret = spcom_handle_read_req_resp(ch, buf, size);
	}

	mutex_lock(&ch->lock);
	if (!ch->is_server) {
		__pm_relax(spcom_dev->ws);
		spcom_pr_dbg("ch[%s]:pm_relax() called for client\n",
			     ch->name);
	}
	mutex_unlock(&ch->lock);

	return ret;
}

@@ -2315,7 +2311,7 @@ static int spcom_rpdev_cb(struct rpmsg_device *rpdev,
	}
	ch = dev_get_drvdata(&rpdev->dev);
	if (!ch) {
		spcom_pr_err("%s: invalid ch\n");
		spcom_pr_err("%s: invalid ch\n", ch->name);
		return -EINVAL;
	}
	if (len > SPCOM_RX_BUF_SIZE || len <= 0) {
@@ -2335,6 +2331,10 @@ static int spcom_rpdev_cb(struct rpmsg_device *rpdev,
	rx_item->rx_buf_size = len;
	rx_item->ch = ch;

	pm_wakeup_ws_event(spcom_dev->ws, SPCOM_PM_PACKET_HANDLE_TIMEOUT, true);
	spcom_pr_dbg("%s:got new packet, wakeup requested\n", ch->name);


	spin_lock_irqsave(&spcom_dev->rx_lock, flags);
	list_add(&rx_item->list, &spcom_dev->rx_list_head);
	spin_unlock_irqrestore(&spcom_dev->rx_lock, flags);
@@ -2524,7 +2524,6 @@ static int spcom_probe(struct platform_device *pdev)

	spcom_dev = dev;
	spcom_dev->pdev = pdev;
	atomic_set(&spcom_dev->rx_active_count, 0);
	/* start counting exposed channel char devices from 1 */
	spcom_dev->chdev_count = 1;
	mutex_init(&spcom_dev->chdev_count_lock);
@@ -2537,6 +2536,15 @@ static int spcom_probe(struct platform_device *pdev)
	spcom_dev->nvm_ion_fd = -1;
	mutex_init(&spcom_dev->ioctl_lock);

	// register wakeup source
	spcom_dev->ws =
		wakeup_source_register(&spcom_dev->pdev->dev, "spcom_wakeup");
	if (!spcom_dev->ws)  {
		pr_err("failed to register wakeup source\n");
		ret = -ENOMEM;
		goto fail_while_chardev_reg;
	}

	ret = spcom_register_chardev();
	if (ret) {
		pr_err("create character device failed\n");
@@ -2638,6 +2646,7 @@ static int spcom_remove(struct platform_device *pdev)
		kfree(rx_item);
	}
	spin_unlock_irqrestore(&spcom_dev->rx_lock, flags);
	wakeup_source_unregister(spcom_dev->ws);

	if (spcom_ipc_log_context)
		ipc_log_context_destroy(spcom_ipc_log_context);
@@ -2661,7 +2670,6 @@ static struct platform_driver spcom_driver = {
	.remove = spcom_remove,
	.driver = {
			.name = DEVICE_NAME,
			.pm = &spcom_dev_pm_ops,
			.of_match_table = of_match_ptr(spcom_match_table),
	},
};