From: Vincent Guittot vincent.guittot@linaro.org
[ Upstream commit d1cbd9e0f7e51ae8e3638a36ba884fdbb2fc967e ]
According to scmi specification, the response of the discover agent request is made of: - int32 status - uint32 agent_id - uint8 name[16]
but the current implementation doesn't take into account the agent_id field and only allocates a rx buffer of SCMI_MAX_STR_SIZE length
Allocate the correct length for rx buffer and copy the name from the correct offset in the response.
While no error were returned until v5.15, v5.16-rc1 fails with virtio_scmi transport channel:
| arm-scmi firmware:scmi0: SCMI Notifications - Core Enabled. | arm-scmi firmware:scmi0: SCMI Protocol v2.0 'Linaro:PMWG' Firmware version 0x2090000 | scmi-virtio virtio0: tx:used len 28 is larger than in buflen 24
Link: https://lore.kernel.org/r/20211117081856.9932-1-vincent.guittot@linaro.org Fixes: b6f20ff8bd94 ("firmware: arm_scmi: add common infrastructure and support for base protocol") Tested-by: Cristian Marussi cristian.marussi@arm.com Reviewed-by: Cristian Marussi cristian.marussi@arm.com Signed-off-by: Vincent Guittot vincent.guittot@linaro.org Signed-off-by: Sudeep Holla sudeep.holla@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/firmware/arm_scmi/base.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c index de416f9e79213..f5219334fd3a5 100644 --- a/drivers/firmware/arm_scmi/base.c +++ b/drivers/firmware/arm_scmi/base.c @@ -34,6 +34,12 @@ struct scmi_msg_resp_base_attributes { __le16 reserved; };
+struct scmi_msg_resp_base_discover_agent { + __le32 agent_id; + u8 name[SCMI_MAX_STR_SIZE]; +}; + + struct scmi_msg_base_error_notify { __le32 event_control; #define BASE_TP_NOTIFY_ALL BIT(0) @@ -225,18 +231,21 @@ static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, int id, char *name) { int ret; + struct scmi_msg_resp_base_discover_agent *agent_info; struct scmi_xfer *t;
ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, - sizeof(__le32), SCMI_MAX_STR_SIZE, &t); + sizeof(__le32), sizeof(*agent_info), &t); if (ret) return ret;
put_unaligned_le32(id, t->tx.buf);
ret = ph->xops->do_xfer(ph, t); - if (!ret) - strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE); + if (!ret) { + agent_info = t->rx.buf; + strlcpy(name, agent_info->name, SCMI_MAX_STR_SIZE); + }
ph->xops->xfer_put(ph, t);