git: e887179d4bc0 - main - scmi: Add helper to manipulate scmi_msg descriptors

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

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

commit e887179d4bc032e79d0334371d613c5841989a41
Author:     Cristian Marussi <cristian.marussi@arm.com>
AuthorDate: 2025-01-23 13:23:28 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2025-01-23 17:26:26 +0000

    scmi: Add helper to manipulate scmi_msg descriptors
    
    Refactor allocation logic for scmi_req and introduce new helpers to be able
    to obtain an scmi_msg reference to a freshly allocated request.
    
    Tested on:      Arm Morello Board
    Reviewed by:    andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D47423
    Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
 sys/dev/firmware/arm/scmi.c | 77 +++++++++++++++++++++++++++++++++++----------
 sys/dev/firmware/arm/scmi.h |  2 ++
 2 files changed, 63 insertions(+), 16 deletions(-)

diff --git a/sys/dev/firmware/arm/scmi.c b/sys/dev/firmware/arm/scmi.c
index cf5a678370fd..8104f4e10429 100644
--- a/sys/dev/firmware/arm/scmi.c
+++ b/sys/dev/firmware/arm/scmi.c
@@ -132,9 +132,10 @@ static int		scmi_transport_init(struct scmi_softc *, phandle_t);
 static void		scmi_transport_cleanup(struct scmi_softc *);
 static struct scmi_reqs_pool *scmi_reqs_pool_allocate(const int, const int);
 static void		scmi_reqs_pool_free(struct scmi_reqs_pool *);
-static struct scmi_req *scmi_req_alloc(struct scmi_softc *, enum scmi_chan);
+static struct scmi_req	*scmi_req_alloc(struct scmi_softc *, enum scmi_chan);
+static struct scmi_req	*scmi_req_initialized_alloc(device_t, int, int);
 static void		scmi_req_free_unlocked(struct scmi_softc *,
-    enum scmi_chan, struct scmi_req *);
+			    enum scmi_chan, struct scmi_req *);
 static void		scmi_req_get(struct scmi_softc *, struct scmi_req *);
 static void		scmi_req_put(struct scmi_softc *, struct scmi_req *);
 static int		scmi_token_pick(struct scmi_softc *);
@@ -319,6 +320,32 @@ scmi_transport_cleanup(struct scmi_softc *sc)
 	free(sc->trs, M_DEVBUF);
 }
 
+static struct scmi_req *
+scmi_req_initialized_alloc(device_t dev, int tx_payld_sz, int rx_payld_sz)
+{
+	struct scmi_softc *sc;
+	struct scmi_req *req;
+
+	sc = device_get_softc(dev);
+
+	if (tx_payld_sz > SCMI_MAX_MSG_PAYLD_SIZE(sc) ||
+	    rx_payld_sz > SCMI_MAX_MSG_REPLY_SIZE(sc)) {
+		device_printf(dev, "Unsupported payload size. Drop.\n");
+		return (NULL);
+	}
+
+	/* Pick one from free list */
+	req = scmi_req_alloc(sc, SCMI_CHAN_A2P);
+	if (req == NULL)
+		return (NULL);
+
+	req->msg.tx_len = sizeof(req->msg.hdr) + tx_payld_sz;
+	req->msg.rx_len = rx_payld_sz ?
+	    rx_payld_sz + 2 * sizeof(uint32_t) : SCMI_MAX_MSG_SIZE(sc);
+
+	return (req);
+}
+
 static struct scmi_req *
 scmi_req_alloc(struct scmi_softc *sc, enum scmi_chan ch_idx)
 {
@@ -374,6 +401,10 @@ scmi_req_put(struct scmi_softc *sc, struct scmi_req *req)
 {
 	mtx_lock_spin(&req->mtx);
 	if (!refcount_release_if_not_last(&req->cnt)) {
+		req->protocol_id = 0;
+		req->message_id = 0;
+		req->token = 0;
+		req->header = 0;
 		bzero(&req->msg, sizeof(req->msg) + SCMI_MAX_MSG_PAYLD_SIZE(sc));
 		scmi_req_free_unlocked(sc, SCMI_CHAN_A2P, req);
 	}
@@ -604,27 +635,15 @@ void *
 scmi_buf_get(device_t dev, uint8_t protocol_id, uint8_t message_id,
     int tx_payld_sz, int rx_payld_sz)
 {
-	struct scmi_softc *sc;
 	struct scmi_req *req;
 
-	sc = device_get_softc(dev);
-
-	if (tx_payld_sz > SCMI_MAX_MSG_PAYLD_SIZE(sc) ||
-	    rx_payld_sz > SCMI_MAX_MSG_REPLY_SIZE(sc)) {
-		device_printf(dev, "Unsupported payload size. Drop.\n");
-		return (NULL);
-	}
-
-	/* Pick one from free list */
-	req = scmi_req_alloc(sc, SCMI_CHAN_A2P);
+	/* Pick a pre-built req */
+	req = scmi_req_initialized_alloc(dev, tx_payld_sz, rx_payld_sz);
 	if (req == NULL)
 		return (NULL);
 
 	req->protocol_id = protocol_id & SCMI_HDR_PROTOCOL_ID_BF;
 	req->message_id = message_id & SCMI_HDR_MESSAGE_ID_BF;
-	req->msg.tx_len = sizeof(req->msg.hdr) + tx_payld_sz;
-	req->msg.rx_len = rx_payld_sz ?
-	    rx_payld_sz + 2 * sizeof(uint32_t) : SCMI_MAX_MSG_SIZE(sc);
 
 	return (&req->msg.payld[0]);
 }
@@ -641,6 +660,32 @@ scmi_buf_put(device_t dev, void *buf)
 	scmi_req_put(sc, req);
 }
 
+struct scmi_msg *
+scmi_msg_get(device_t dev, int tx_payld_sz, int rx_payld_sz)
+{
+	struct scmi_req *req;
+
+	/* Pick a pre-built req */
+	req = scmi_req_initialized_alloc(dev, tx_payld_sz, rx_payld_sz);
+	if (req == NULL)
+		return (NULL);
+
+	return (&req->msg);
+}
+
+void
+scmi_msg_put(device_t dev, struct scmi_msg *msg)
+{
+	struct scmi_softc *sc;
+	struct scmi_req *req;
+
+	sc = device_get_softc(dev);
+
+	req = msg_to_req(msg);
+
+	scmi_req_put(sc, req);
+}
+
 int
 scmi_request(device_t dev, void *in, void **out)
 {
diff --git a/sys/dev/firmware/arm/scmi.h b/sys/dev/firmware/arm/scmi.h
index 135b49c3b05b..f6aa072caeca 100644
--- a/sys/dev/firmware/arm/scmi.h
+++ b/sys/dev/firmware/arm/scmi.h
@@ -80,6 +80,8 @@ struct scmi_msg {
 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);
+struct scmi_msg *scmi_msg_get(device_t dev, int tx_payld_sz, int rx_payld_sz);
+void scmi_msg_put(device_t dev, struct scmi_msg *msg);
 int scmi_request(device_t dev, void *in, void **);
 void scmi_rx_irq_callback(device_t dev, void *chan, uint32_t hdr, uint32_t rx_len);