git: 9342829d578e - main - scmi: Make transports report the effective length of the received messages
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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);