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 @@ -75,7 +75,7 @@ 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.c b/sys/dev/firmware/arm/scmi.c --- a/sys/dev/firmware/arm/scmi.c +++ b/sys/dev/firmware/arm/scmi.c @@ -146,7 +146,8 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ return; } - scmi_process_response(sc, hdr); + scmi_process_response(sc, hdr, rx_len); } static int 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 @@ -70,14 +70,14 @@ 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 @@ 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 @@ 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.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 @@ -63,9 +63,9 @@ 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_shmem.c b/sys/dev/firmware/arm/scmi_shmem.c --- a/sys/dev/firmware/arm/scmi_shmem.c +++ b/sys/dev/firmware/arm/scmi_shmem.c @@ -247,7 +247,7 @@ } 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 @@ 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 @@ } 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_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 @@ 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_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 @@ -122,7 +122,7 @@ * 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 @@ 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 --- a/sys/dev/firmware/arm/scmi_virtio.c +++ b/sys/dev/firmware/arm/scmi_virtio.c @@ -76,7 +76,7 @@ } 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 @@ } 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 @@ 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);