diff --git a/sys/dev/firmware/arm/scmi.h b/sys/dev/firmware/arm/scmi.h --- a/sys/dev/firmware/arm/scmi.h +++ b/sys/dev/firmware/arm/scmi.h @@ -34,10 +34,21 @@ #include "scmi_if.h" -#define SCMI_MAX_MSG 32 -#define SCMI_MAX_MSG_PAYLD_SIZE 128 -#define SCMI_MAX_MSG_REPLY_SIZE (SCMI_MAX_MSG_PAYLD_SIZE - sizeof(uint32_t)) -#define SCMI_MAX_MSG_SIZE (SCMI_MAX_MSG_PAYLD_SIZE + sizeof(uint32_t)) +#define SCMI_DEF_MAX_MSG 32 +#define SCMI_DEF_MAX_MSG_PAYLD_SIZE 128 +#define SCMI_DEF_MAX_RX_TIMEOUT_MS 30 + +#define SCMI_MAX_MSG(sc) ((sc)->trs_desc.max_msg) +#define SCMI_MAX_MSG_TIMEOUT_MS(sc) ((sc)->trs_desc.reply_timo_ms) + +/* Payload including status, excluding header*/ +#define SCMI_MAX_MSG_PAYLD_SIZE(sc) ((sc)->trs_desc.max_payld_sz) + +/* Payload size minus status field */ +#define SCMI_MAX_MSG_REPLY_SIZE(sc) (SCMI_MAX_MSG_PAYLD_SIZE((sc)) - sizeof(uint32_t)) + +/* Payload size plus header field */ +#define SCMI_MAX_MSG_SIZE(sc) (SCMI_MAX_MSG_PAYLD_SIZE(sc) + sizeof(uint32_t)) enum scmi_chan { SCMI_CHAN_A2P, @@ -47,6 +58,8 @@ struct scmi_transport_desc { bool no_completion_irq; + unsigned int max_msg; + unsigned int max_payld_sz; unsigned int reply_timo_ms; }; diff --git a/sys/dev/firmware/arm/scmi.c b/sys/dev/firmware/arm/scmi.c --- a/sys/dev/firmware/arm/scmi.c +++ b/sys/dev/firmware/arm/scmi.c @@ -127,6 +127,8 @@ struct mtx mtx; }; +static int scmi_transport_configure(device_t, + struct scmi_transport_desc *); static int scmi_transport_init(struct scmi_softc *); static void scmi_transport_cleanup(struct scmi_softc *); static struct scmi_reqs_pool *scmi_reqs_pool_allocate(const int, const int); @@ -169,8 +171,8 @@ if (error != 0) return (error); - device_printf(dev, "Transport reply timeout initialized to %dms\n", - sc->trs_desc.reply_timo_ms); + device_printf(dev, "Transport - max_msg:%d max_payld_sz:%u reply_timo_ms:%d\n", + SCMI_MAX_MSG(sc), SCMI_MAX_MSG_PAYLD_SIZE(sc), SCMI_MAX_MSG_TIMEOUT_MS(sc)); /* * Allow devices to identify. @@ -248,36 +250,54 @@ free(rp, M_DEVBUF); } +static int +scmi_transport_configure(device_t dev, struct scmi_transport_desc *tdesc) +{ + /* Initialize to default values at first ... */ + tdesc->max_msg = SCMI_DEF_MAX_MSG; + tdesc->max_payld_sz = SCMI_DEF_MAX_MSG_PAYLD_SIZE; + tdesc->reply_timo_ms = SCMI_DEF_MAX_RX_TIMEOUT_MS; + + /* ... check against per-transport needs */ + return SCMI_TRANSPORT_CONFIGURE(dev); +} + static int scmi_transport_init(struct scmi_softc *sc) { + struct scmi_transport_desc *tdesc = &sc->trs_desc; struct scmi_transport *trs; int ret; trs = malloc(sizeof(*trs), M_DEVBUF, M_ZERO | M_WAITOK); + sc->trs = trs; + + ret = scmi_transport_configure(sc->dev, tdesc); + if (ret != 0) { + free(trs, M_DEVBUF); + return (ret); + } BIT_FILL(SCMI_MAX_TOKEN, &trs->avail_tokens); mtx_init(&trs->mtx, "tokens", "SCMI", MTX_SPIN); - trs->inflight_ht = hashinit(SCMI_MAX_MSG, M_DEVBUF, - &trs->inflight_mask); + trs->inflight_ht = hashinit(tdesc->max_msg, M_DEVBUF, &trs->inflight_mask); trs->chans[SCMI_CHAN_A2P] = - scmi_reqs_pool_allocate(SCMI_MAX_MSG, SCMI_MAX_MSG_PAYLD_SIZE); + scmi_reqs_pool_allocate(tdesc->max_msg, tdesc->max_payld_sz); if (trs->chans[SCMI_CHAN_A2P] == NULL) { free(trs, M_DEVBUF); return (ENOMEM); } trs->chans[SCMI_CHAN_P2A] = - scmi_reqs_pool_allocate(SCMI_MAX_MSG, SCMI_MAX_MSG_PAYLD_SIZE); + scmi_reqs_pool_allocate(tdesc->max_msg, tdesc->max_payld_sz); if (trs->chans[SCMI_CHAN_P2A] == NULL) { scmi_reqs_pool_free(trs->chans[SCMI_CHAN_A2P]); free(trs, M_DEVBUF); return (ENOMEM); } - sc->trs = trs; ret = SCMI_TRANSPORT_INIT(sc->dev); if (ret != 0) { scmi_reqs_pool_free(trs->chans[SCMI_CHAN_A2P]); @@ -355,7 +375,7 @@ { mtx_lock_spin(&req->mtx); if (!refcount_release_if_not_last(&req->cnt)) { - bzero(&req->msg, sizeof(req->msg) + SCMI_MAX_MSG_PAYLD_SIZE); + bzero(&req->msg, sizeof(req->msg) + SCMI_MAX_MSG_PAYLD_SIZE(sc)); scmi_req_free_unlocked(sc, SCMI_CHAN_A2P, req); } mtx_unlock_spin(&req->mtx); @@ -532,13 +552,13 @@ static int scmi_wait_for_response(struct scmi_softc *sc, struct scmi_req *req, void **out) { + unsigned int reply_timo_ms = SCMI_MAX_MSG_TIMEOUT_MS(sc); int ret; if (req->msg.polling) { bool needs_drop; - ret = SCMI_POLL_MSG(sc->dev, &req->msg, - sc->trs_desc.reply_timo_ms); + ret = SCMI_POLL_MSG(sc->dev, &req->msg, reply_timo_ms); /* * Drop reference to successfully polled req unless it had * already also been processed on the IRQ path. @@ -557,8 +577,7 @@ le32toh(req->msg.hdr), le32toh(req->header)); } } else { - ret = tsleep(req, 0, "scmi_wait4", - (sc->trs_desc.reply_timo_ms * hz) / 1000); + ret = tsleep(req, 0, "scmi_wait4", (reply_timo_ms * hz) / 1000); /* Check for lost wakeups since there is no associated lock */ mtx_lock_spin(&req->mtx); if (ret != 0 && req->done) @@ -591,8 +610,8 @@ sc = device_get_softc(dev); - if (tx_payld_sz > SCMI_MAX_MSG_PAYLD_SIZE || - rx_payld_sz > SCMI_MAX_MSG_REPLY_SIZE) { + 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); } @@ -606,7 +625,7 @@ 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; + rx_payld_sz + 2 * sizeof(uint32_t) : SCMI_MAX_MSG_SIZE(sc); return (&req->msg.payld[0]); } diff --git a/sys/dev/firmware/arm/scmi_if.m b/sys/dev/firmware/arm/scmi_if.m --- a/sys/dev/firmware/arm/scmi_if.m +++ b/sys/dev/firmware/arm/scmi_if.m @@ -31,6 +31,10 @@ struct scmi_msg; }; +METHOD int transport_configure { + device_t dev; +}; + METHOD int transport_init { device_t dev; }; diff --git a/sys/dev/firmware/arm/scmi_mailbox.c b/sys/dev/firmware/arm/scmi_mailbox.c --- a/sys/dev/firmware/arm/scmi_mailbox.c +++ b/sys/dev/firmware/arm/scmi_mailbox.c @@ -56,6 +56,7 @@ struct arm_doorbell *db; }; +static int scmi_mailbox_transport_configure(device_t); static int scmi_mailbox_transport_init(device_t); static void scmi_mailbox_transport_cleanup(device_t); static int scmi_mailbox_xfer_msg(device_t, struct scmi_msg *); @@ -80,6 +81,24 @@ scmi_rx_irq_callback(sc->base.dev, sc->a2p_dev, msg_header, rx_len); } +static int +scmi_mailbox_transport_configure(device_t dev) +{ + struct scmi_mailbox_softc *sc; + + sc = device_get_softc(dev); + + if (sc->base.trs_desc.max_payld_sz <= SCMI_SHMEM_TRANSPORT_LAYOUT_HDR_SZ) { + device_printf(dev, + "Failed to configure transport: max_payld_sz not big enough !\n"); + return (EINVAL); + } + + sc->base.trs_desc.max_payld_sz -= SCMI_SHMEM_TRANSPORT_LAYOUT_HDR_SZ; + + return (0); +} + static int scmi_mailbox_transport_init(device_t dev) { @@ -109,8 +128,6 @@ return (ENXIO); } - sc->base.trs_desc.reply_timo_ms = 30; - arm_doorbell_set_handler(sc->db, scmi_mailbox_a2p_callback, sc); return (0); @@ -211,6 +228,7 @@ DEVMETHOD(device_probe, scmi_mailbox_probe), /* SCMI interface */ + DEVMETHOD(scmi_transport_configure, scmi_mailbox_transport_configure), DEVMETHOD(scmi_transport_init, scmi_mailbox_transport_init), DEVMETHOD(scmi_transport_cleanup, scmi_mailbox_transport_cleanup), DEVMETHOD(scmi_xfer_msg, scmi_mailbox_xfer_msg), diff --git a/sys/dev/firmware/arm/scmi_shmem.h b/sys/dev/firmware/arm/scmi_shmem.h --- a/sys/dev/firmware/arm/scmi_shmem.h +++ b/sys/dev/firmware/arm/scmi_shmem.h @@ -46,6 +46,8 @@ uint8_t msg_payload[0]; }; +#define SCMI_SHMEM_TRANSPORT_LAYOUT_HDR_SZ 24 + #define SMT_SIZE_HEADER sizeof(struct scmi_smt_header) #define SMT_OFFSET_CHAN_STATUS \ diff --git a/sys/dev/firmware/arm/scmi_smc.c b/sys/dev/firmware/arm/scmi_smc.c --- a/sys/dev/firmware/arm/scmi_smc.c +++ b/sys/dev/firmware/arm/scmi_smc.c @@ -54,6 +54,7 @@ device_t a2p_dev; }; +static int scmi_smc_transport_configure(device_t); static int scmi_smc_transport_init(device_t); static int scmi_smc_xfer_msg(device_t, struct scmi_msg *); static int scmi_smc_poll_msg(device_t, struct scmi_msg *, unsigned int); @@ -62,6 +63,17 @@ static int scmi_smc_probe(device_t); +static int +scmi_smc_transport_configure(device_t dev) +{ + struct scmi_smc_softc *sc; + + sc = device_get_softc(dev); + sc->base.trs_desc.no_completion_irq = true; + + return (0); +} + static int scmi_smc_transport_init(device_t dev) { @@ -87,9 +99,6 @@ return (ENXIO); } - sc->base.trs_desc.no_completion_irq = true; - sc->base.trs_desc.reply_timo_ms = 30; - return (0); } @@ -169,6 +178,7 @@ DEVMETHOD(device_probe, scmi_smc_probe), /* SCMI interface */ + DEVMETHOD(scmi_transport_configure, scmi_smc_transport_configure), DEVMETHOD(scmi_transport_init, scmi_smc_transport_init), DEVMETHOD(scmi_xfer_msg, scmi_smc_xfer_msg), DEVMETHOD(scmi_poll_msg, scmi_smc_poll_msg), diff --git a/sys/dev/firmware/arm/scmi_virtio.c b/sys/dev/firmware/arm/scmi_virtio.c --- a/sys/dev/firmware/arm/scmi_virtio.c +++ b/sys/dev/firmware/arm/scmi_virtio.c @@ -54,6 +54,7 @@ static void scmi_virtio_callback(void *, unsigned int, void *); static void *scmi_virtio_p2a_pool_init(device_t, unsigned int); +static int scmi_virtio_transport_configure(device_t); static int scmi_virtio_transport_init(device_t); static void scmi_virtio_transport_cleanup(device_t); static int scmi_virtio_xfer_msg(device_t, struct scmi_msg *); @@ -83,19 +84,19 @@ scmi_virtio_p2a_pool_init(device_t dev, unsigned int max_msg) { struct scmi_virtio_softc *sc; + unsigned int max_msg_sz; void *pool; uint8_t *buf; int i; sc = device_get_softc(dev); + max_msg_sz = SCMI_MAX_MSG_SIZE(&sc->base); + pool = mallocarray(max_msg, max_msg_sz, M_DEVBUF, M_ZERO | M_WAITOK); - pool = mallocarray(max_msg, SCMI_MAX_MSG_SIZE, M_DEVBUF, - M_ZERO | M_WAITOK); - - for (i = 0, buf = pool; i < max_msg; i++, buf += SCMI_MAX_MSG_SIZE) { + for (i = 0, buf = pool; i < max_msg; i++, buf += max_msg_sz) { /* Feed platform with pre-allocated P2A buffers */ virtio_scmi_message_enqueue(sc->virtio_dev, - VIRTIO_SCMI_CHAN_P2A, buf, 0, SCMI_MAX_MSG_SIZE); + VIRTIO_SCMI_CHAN_P2A, buf, 0, max_msg_sz); } device_printf(dev, @@ -111,7 +112,18 @@ sc = device_get_softc(dev); virtio_scmi_message_enqueue(sc->virtio_dev, VIRTIO_SCMI_CHAN_P2A, - msg, 0, SCMI_MAX_MSG_SIZE); + msg, 0, SCMI_MAX_MSG_SIZE(&sc->base)); +} + +static int +scmi_virtio_transport_configure(device_t dev) +{ + struct scmi_virtio_softc *sc; + + sc = device_get_softc(dev); + sc->base.trs_desc.reply_timo_ms = 100; + + return (0); } static int @@ -169,8 +181,6 @@ } } - sc->base.trs_desc.reply_timo_ms = 100; - return (0); } @@ -280,6 +290,7 @@ DEVMETHOD(device_attach, scmi_virtio_attach), /* SCMI interface */ + DEVMETHOD(scmi_transport_configure, scmi_virtio_transport_configure), DEVMETHOD(scmi_transport_init, scmi_virtio_transport_init), DEVMETHOD(scmi_transport_cleanup, scmi_virtio_transport_cleanup), DEVMETHOD(scmi_xfer_msg, scmi_virtio_xfer_msg),