diff mbox

[RFC,25/31] xen/arm: Use non-blocking mode for SCPI protocol

Message ID 1510247421-24094-26-git-send-email-olekstysh@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Oleksandr Tyshchenko Nov. 9, 2017, 5:10 p.m. UTC
From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

Don't block until data is transmitted.
As we are limited to use only two methods TXDONE_BY_IRQ and TXDONE_BY_ACK,
there are two possible scenario:
- If the mailbox controller has TX-done irq it definitely knows when
  transmitted data has been sent and it is responsible for calling
  mbox_chan_txdone() to signal framework about TX-done.
- If controller can't generate TX-Done irq the client has to signal
  TX-done by itself.

So, in case of "ARM SMC mailbox" we explicitly tick the TX state machine
by calling mbox_client_txdone().

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
CC: Stefano Stabellini <sstabellini@kernel.org>
CC: Julien Grall <julien.grall@linaro.org>
---
 xen/arch/arm/cpufreq/arm_scpi.c | 30 +++++++++++++++++++++++-------
 1 file changed, 23 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/xen/arch/arm/cpufreq/arm_scpi.c b/xen/arch/arm/cpufreq/arm_scpi.c
index 553a516..51a9742 100644
--- a/xen/arch/arm/cpufreq/arm_scpi.c
+++ b/xen/arch/arm/cpufreq/arm_scpi.c
@@ -530,7 +530,7 @@  static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
 static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
 			     void *rx_buf, unsigned int rx_len)
 {
-	int ret;
+	int ret, ret2;
 	u8 chan;
 	u8 cmd;
 	struct scpi_xfer *msg;
@@ -566,21 +566,37 @@  static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
 	reinit_completion(&msg->done);
 
 	ret = mbox_send_message(scpi_chan->chan, msg);
-	if (ret < 0 || !rx_buf)
+	if (ret < 0 || !rx_buf) {
+		/* mbox_send_message returns non-negative value on success */
+		ret2 = ret < 0 ? ret : 0;
 		goto out;
+	}
 
 	if (!wait_for_completion_timeout(&msg->done, MAX_RX_TIMEOUT))
 		ret = -ETIMEDOUT;
 	else
 		/* first status word */
 		ret = msg->status;
+
+	/* SCPI error codes > 0, translate them to Linux scale */
+	ret2 = ret > 0 ? scpi_to_linux_errno(ret) : ret;
+
+	/*
+	 * If the mailbox controller has TX-done irq it definitely knows when
+	 * transmitted data has been sent and it is responsible for calling
+	 * mbox_chan_txdone() to signal framework about TX-done.
+	 * If controller can't generate TX-Done irq the client has to signal
+	 * TX-done by itself.
+	 */
+	if (!scpi_chan->chan->mbox->txdone_irq)
+		mbox_client_txdone(scpi_chan->chan, ret2);
+
 out:
 	if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
 		scpi_process_cmd(scpi_chan, msg->cmd);
 
 	put_scpi_xfer(msg, scpi_chan);
-	/* SCPI error codes > 0, translate them to Linux scale*/
-	return ret > 0 ? scpi_to_linux_errno(ret) : ret;
+	return ret2;
 }
 
 static u32 scpi_get_version(void)
@@ -1026,9 +1042,9 @@  static int scpi_probe(struct platform_device *pdev)
 		cl->dev = dev;
 		cl->rx_callback = scpi_handle_remote_msg;
 		cl->tx_prepare = scpi_tx_prepare;
-		cl->tx_block = true;
-		cl->tx_tout = 20;
-		cl->knows_txdone = false; /* controller can't ack */
+		/* Use non-blocking mode for client */
+		cl->tx_block = false;
+		cl->knows_txdone = true;
 
 		INIT_LIST_HEAD(&pchan->rx_pending);
 		INIT_LIST_HEAD(&pchan->xfers_list);