git: 9342829d578e - main - scmi: Make transports report the effective length of the received messages

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Thu, 23 Jan 2025 17:27:31 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=9342829d578e26f10a5cbc26e2b9e66cfd9864c4

commit 9342829d578e26f10a5cbc26e2b9e66cfd9864c4
Author:     Cristian Marussi <cristian.marussi@arm.com>
AuthorDate: 2025-01-23 12:49:02 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-01-23 17:26:26 +0000

    scmi: Make transports report the effective length of the received messages
    
    Once a message is received that fits into the RX buffer, update the
    msg.rx_len field with the effective length of the message received.
    
    Tested on:      Arm Morello Board
    Reviewed by:    andrew
    Sponsored by:   Arm Ltd
    Pull Request:   https://reviews.freebsd.org/D47420
    Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 sys/dev/firmware/arm/scmi.c         | 10 ++++++----
 sys/dev/firmware/arm/scmi.h         |  2 +-
 sys/dev/firmware/arm/scmi_mailbox.c | 10 +++++-----
 sys/dev/firmware/arm/scmi_shmem.c   | 22 +++++++++-------------
 sys/dev/firmware/arm/scmi_shmem.h   |  6 +++---
 sys/dev/firmware/arm/scmi_smc.c     |  4 ++--
 sys/dev/firmware/arm/scmi_virtio.c  |  5 ++---
 7 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/sys/dev/firmware/arm/scmi.c b/sys/dev/firmware/arm/scmi.c
index 37496136c828..00a229762414 100644
--- a/sys/dev/firmware/arm/scmi.c
+++ b/sys/dev/firmware/arm/scmi.c
@@ -146,7 +146,8 @@ static struct scmi_req *scmi_req_lookup_inflight(struct scmi_softc *, uint32_t);
 
 static int		scmi_wait_for_response(struct scmi_softc *,
 			    struct scmi_req *, void **);
-static void		scmi_process_response(struct scmi_softc *, uint32_t);
+static void		scmi_process_response(struct scmi_softc *, uint32_t,
+			    unsigned int);
 
 int
 scmi_attach(device_t dev)
@@ -469,7 +470,7 @@ scmi_req_lookup_inflight(struct scmi_softc *sc, uint32_t hdr)
 }
 
 static void
-scmi_process_response(struct scmi_softc *sc, uint32_t hdr)
+scmi_process_response(struct scmi_softc *sc, uint32_t hdr, uint32_t rx_len)
 {
 	bool timed_out = false;
 	struct scmi_req *req;
@@ -484,6 +485,7 @@ scmi_process_response(struct scmi_softc *sc, uint32_t hdr)
 
 	mtx_lock_spin(&req->mtx);
 	req->done = true;
+	req->msg.rx_len = rx_len;
 	if (!req->timed_out) {
 		/*
 		 * Consider the case in which a polled message is picked
@@ -512,7 +514,7 @@ scmi_process_response(struct scmi_softc *sc, uint32_t hdr)
 }
 
 void
-scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr)
+scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr, uint32_t rx_len)
 {
 	struct scmi_softc *sc;
 
@@ -524,7 +526,7 @@ scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr)
 		return;
 	}
 
-	scmi_process_response(sc, hdr);
+	scmi_process_response(sc, hdr, rx_len);
 }
 
 static int
diff --git a/sys/dev/firmware/arm/scmi.h b/sys/dev/firmware/arm/scmi.h
index 345ae6eeb03a..5ad7b0db3f5f 100644
--- a/sys/dev/firmware/arm/scmi.h
+++ b/sys/dev/firmware/arm/scmi.h
@@ -75,7 +75,7 @@ void *scmi_buf_get(device_t dev, uint8_t protocol_id, uint8_t message_id,
 		   int tx_payd_sz, int rx_payld_sz);
 void scmi_buf_put(device_t dev, void *buf);
 int scmi_request(device_t dev, void *in, void **);
-void scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr);
+void scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr, uint32_t rx_len);
 
 DECLARE_CLASS(scmi_driver);
 
diff --git a/sys/dev/firmware/arm/scmi_mailbox.c b/sys/dev/firmware/arm/scmi_mailbox.c
index 858b81f68845..d7b642b69b85 100644
--- a/sys/dev/firmware/arm/scmi_mailbox.c
+++ b/sys/dev/firmware/arm/scmi_mailbox.c
@@ -70,14 +70,14 @@ static void
 scmi_mailbox_a2p_callback(void *arg)
 {
 	struct scmi_mailbox_softc *sc;
-	uint32_t msg_header;
+	uint32_t msg_header, rx_len;
 	int ret;
 
 	sc = arg;
 
-	ret = scmi_shmem_read_msg_header(sc->a2p_dev, &msg_header);
+	ret = scmi_shmem_read_msg_header(sc->a2p_dev, &msg_header, &rx_len);
 	if (ret == 0)
-		scmi_rx_irq_callback(sc->base.dev, sc->a2p_dev, msg_header);
+		scmi_rx_irq_callback(sc->base.dev, sc->a2p_dev, msg_header, rx_len);
 }
 
 static int
@@ -154,7 +154,7 @@ scmi_mailbox_poll_msg(device_t dev, struct scmi_msg *msg, unsigned int tmo_ms)
 	sc = device_get_softc(dev);
 
 	do {
-		if (scmi_shmem_poll_msg(sc->a2p_dev, &msg->hdr))
+		if (scmi_shmem_poll_msg(sc->a2p_dev, &msg->hdr, &msg->rx_len))
 			break;
 		DELAY(SCMI_MBOX_POLL_INTERVAL_MS * 1000);
 	} while (tmo_loops--);
@@ -171,7 +171,7 @@ scmi_mailbox_collect_reply(device_t dev, struct scmi_msg *msg)
 	sc = device_get_softc(dev);
 
 	ret = scmi_shmem_read_msg_payload(sc->a2p_dev,
-	    msg->payld, msg->rx_len - SCMI_MSG_HDR_SIZE);
+	    msg->payld, msg->rx_len - SCMI_MSG_HDR_SIZE, msg->rx_len);
 
 	return (ret);
 }
diff --git a/sys/dev/firmware/arm/scmi_shmem.c b/sys/dev/firmware/arm/scmi_shmem.c
index 9bab4bc4004e..a63d96b64cb5 100644
--- a/sys/dev/firmware/arm/scmi_shmem.c
+++ b/sys/dev/firmware/arm/scmi_shmem.c
@@ -247,7 +247,7 @@ scmi_shmem_clear_channel(device_t dev)
 }
 
 int
-scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header)
+scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header, unsigned int *rx_len)
 {
 	uint32_t length, header;
 
@@ -256,6 +256,7 @@ scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header)
 	if (le32toh(length) < sizeof(header))
 		return (EINVAL);
 
+	*rx_len = le32toh(length);
 	/* Read header. */
 	scmi_shmem_read(dev, SMT_OFFSET_MSG_HEADER, &header,
 	    SMT_SIZE_MSG_HEADER);
@@ -266,14 +267,11 @@ scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header)
 }
 
 int
-scmi_shmem_read_msg_payload(device_t dev, uint8_t *buf, uint32_t buf_len)
+scmi_shmem_read_msg_payload(device_t dev, uint8_t *buf, uint32_t buf_len, uint32_t rx_len)
 {
-	uint32_t length, payld_len;
-
-	/* Read length. */
-	scmi_shmem_read(dev, SMT_OFFSET_LENGTH, &length, SMT_SIZE_LENGTH);
-	payld_len = le32toh(length) - SCMI_MSG_HDR_SIZE;
+	uint32_t payld_len;
 
+	payld_len = rx_len - SCMI_MSG_HDR_SIZE;
 	if (payld_len > buf_len) {
 		device_printf(dev,
 		    "RX payload %dbytes exceeds buflen %dbytes. Truncate.\n",
@@ -296,7 +294,7 @@ scmi_shmem_tx_complete(device_t dev)
 	scmi_shmem_release_channel(sc);
 }
 
-bool scmi_shmem_poll_msg(device_t dev, uint32_t *msg_header)
+bool scmi_shmem_poll_msg(device_t dev, uint32_t *msg_header, uint32_t *rx_len)
 {
 	uint32_t status;
 	bool ret;
@@ -306,12 +304,10 @@ bool scmi_shmem_poll_msg(device_t dev, uint32_t *msg_header)
 
 	ret = (status & (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
 	    SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE));
+	if (ret == 0)
+		return (ret);
 
-	if (ret)
-		scmi_shmem_read(dev, SMT_OFFSET_MSG_HEADER, msg_header,
-		    SMT_SIZE_MSG_HEADER);
-
-	return (ret);
+	return (scmi_shmem_read_msg_header(dev, msg_header, rx_len));
 }
 
 static device_method_t shmem_methods[] = {
diff --git a/sys/dev/firmware/arm/scmi_shmem.h b/sys/dev/firmware/arm/scmi_shmem.h
index ed8763d5c145..bc8284502129 100644
--- a/sys/dev/firmware/arm/scmi_shmem.h
+++ b/sys/dev/firmware/arm/scmi_shmem.h
@@ -63,9 +63,9 @@ struct scmi_smt_header {
 device_t scmi_shmem_get(device_t sdev, phandle_t node, int index);
 int scmi_shmem_prepare_msg(device_t dev, uint8_t *msg, uint32_t tx_len,
     bool polling);
-bool scmi_shmem_poll_msg(device_t dev, uint32_t *msg_header);
-int scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header);
-int scmi_shmem_read_msg_payload(device_t dev, uint8_t *buf, uint32_t buf_len);
+bool scmi_shmem_poll_msg(device_t dev, uint32_t *msg_header, uint32_t *rx_len);
+int scmi_shmem_read_msg_header(device_t dev, uint32_t *msg_header, uint32_t *rx_len);
+int scmi_shmem_read_msg_payload(device_t dev, uint8_t *buf, uint32_t buf_len, uint32_t rx_len);
 void scmi_shmem_tx_complete(device_t);
 void scmi_shmem_clear_channel(device_t);
 
diff --git a/sys/dev/firmware/arm/scmi_smc.c b/sys/dev/firmware/arm/scmi_smc.c
index 9f0d899233fa..81c66ad7bb46 100644
--- a/sys/dev/firmware/arm/scmi_smc.c
+++ b/sys/dev/firmware/arm/scmi_smc.c
@@ -122,7 +122,7 @@ scmi_smc_poll_msg(device_t dev, struct scmi_msg *msg, unsigned int tmo)
 	 * Nothing to poll since commands are completed as soon as smc
 	 * returns ... but did we get back what we were poling for ?
 	 */
-	scmi_shmem_read_msg_header(sc->a2p_dev, &msg->hdr);
+	scmi_shmem_read_msg_header(sc->a2p_dev, &msg->hdr, &msg->rx_len);
 
 	return (0);
 }
@@ -136,7 +136,7 @@ scmi_smc_collect_reply(device_t dev, struct scmi_msg *msg)
 	sc = device_get_softc(dev);
 
 	ret = scmi_shmem_read_msg_payload(sc->a2p_dev,
-	    msg->payld, msg->rx_len - SCMI_MSG_HDR_SIZE);
+	    msg->payld, msg->rx_len - SCMI_MSG_HDR_SIZE, msg->rx_len);
 
 	return (ret);
 }
diff --git a/sys/dev/firmware/arm/scmi_virtio.c b/sys/dev/firmware/arm/scmi_virtio.c
index 12cbb9ecefd5..8714fee2ec87 100644
--- a/sys/dev/firmware/arm/scmi_virtio.c
+++ b/sys/dev/firmware/arm/scmi_virtio.c
@@ -76,7 +76,7 @@ scmi_virtio_callback(void *msg, unsigned int len, void *priv)
 	}
 
 	hdr = le32toh(*((uint32_t *)msg));
-	scmi_rx_irq_callback(sc->base.dev, msg, hdr);
+	scmi_rx_irq_callback(sc->base.dev, msg, hdr, len);
 }
 
 static void *
@@ -225,7 +225,6 @@ scmi_virtio_poll_msg(device_t dev, struct scmi_msg *msg, unsigned int tmo_ms)
 		}
 
 		rx_msg = hdr_to_msg(rx_buf);
-		rx_msg->rx_len = rx_len;
 		/* Complete the polling on any poll path */
 		if (rx_msg->polling)
 			atomic_store_rel_int(&rx_msg->poll_done, 1);
@@ -242,7 +241,7 @@ scmi_virtio_poll_msg(device_t dev, struct scmi_msg *msg, unsigned int tmo_ms)
 		    rx_msg->hdr, rx_msg->polling);
 
 		if (!rx_msg->polling)
-			scmi_rx_irq_callback(sc->base.dev, rx_msg, rx_msg->hdr);
+			scmi_rx_irq_callback(sc->base.dev, rx_msg, rx_msg->hdr, rx_len);
 	}
 
 	return (tmo_loops > 0 ? 0 : ETIMEDOUT);