1
0
Fork 0

SSI-87: firmware: imx: scu: Support reception of any size message

The implementation was limiting the size of a message which can be
received to 4 but soem response can be bigger. For example the
response of the 'sc_seco_secvio_config' API is 6 words.

This patch removes this limitation relying on the count of word
received instead of the index of the chan.
It does so by duplicating imx_scu_call_rpc as imx_scu_call_big_rpc
in order to cahnge the RX method using imx_scu_big_rx_callback
instead of imx_scu_rx_callback.

Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
5.4-rM2-2.2.x-imx-squashed
Franck LENORMAND 2020-03-13 11:53:38 +01:00
parent ec19a7176f
commit ccf07c0822
2 changed files with 97 additions and 0 deletions

View File

@ -138,6 +138,29 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
complete(&sc_ipc->done);
}
static void imx_scu_big_rx_callback(struct mbox_client *c, void *msg)
{
struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl);
struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
struct imx_sc_rpc_msg *hdr;
u32 *data = msg;
if (sc_ipc->count == 0) {
hdr = msg;
sc_ipc->rx_size = hdr->size;
dev_dbg(sc_ipc->dev, "msg rx size %u\n", sc_ipc->rx_size);
}
sc_ipc->msg[sc_ipc->count] = *data;
sc_ipc->count++;
dev_dbg(sc_ipc->dev, "mu %u msg %u 0x%x\n", sc_chan->idx,
sc_ipc->count, *data);
if (sc_ipc->count == sc_ipc->rx_size)
complete(&sc_ipc->done);
}
static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
{
struct imx_sc_rpc_msg hdr = *(struct imx_sc_rpc_msg *)msg;
@ -232,6 +255,71 @@ out:
}
EXPORT_SYMBOL(imx_scu_call_rpc);
int imx_scu_call_big_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp)
{
struct imx_sc_rpc_msg *hdr;
struct arm_smccc_res res;
int ret;
int i;
if (WARN_ON(!sc_ipc || !msg))
return -EINVAL;
mutex_lock(&sc_ipc->lock);
for (i = 4; i < 8; i++) {
struct mbox_client *cl = &sc_ipc->chans[i].cl;
cl->rx_callback = imx_scu_big_rx_callback;
}
reinit_completion(&sc_ipc->done);
sc_ipc->msg = msg;
sc_ipc->count = 0;
sc_ipc->rx_size = 0;
if (xen_initial_domain()) {
arm_smccc_hvc(FSL_HVC_SC, (uint64_t)msg, !have_resp, 0, 0, 0,
0, 0, &res);
if (res.a0)
printk("Error FSL_HVC_SC %ld\n", res.a0);
ret = res.a0;
} else {
ret = imx_scu_ipc_write(sc_ipc, msg);
if (ret < 0) {
dev_err(sc_ipc->dev, "RPC send msg failed: %d\n", ret);
goto out;
}
if (have_resp) {
if (!wait_for_completion_timeout(&sc_ipc->done,
MAX_RX_TIMEOUT)) {
dev_err(sc_ipc->dev, "RPC send msg timeout\n");
mutex_unlock(&sc_ipc->lock);
return -ETIMEDOUT;
}
/* response status is stored in hdr->func field */
hdr = msg;
ret = hdr->func;
}
}
out:
for (i = 4; i < 8; i++) {
struct mbox_client *cl = &sc_ipc->chans[i].cl;
cl->rx_callback = imx_scu_rx_callback;
}
mutex_unlock(&sc_ipc->lock);
dev_dbg(sc_ipc->dev, "RPC SVC done\n");
return imx_sc_to_linux_errno(ret);
}
EXPORT_SYMBOL(imx_scu_call_big_rpc);
static int imx_scu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;

View File

@ -48,6 +48,8 @@ struct imx_sc_rpc_msg {
* and returns the result in msg.
*/
int imx_scu_call_rpc(struct imx_sc_ipc *ipc, void *msg, bool have_resp);
int imx_scu_call_big_rpc(struct imx_sc_ipc *ipc, void *msg, bool have_resp);
/*
* This function gets the default ipc handle used by SCU
@ -65,6 +67,13 @@ imx_scu_call_rpc(struct imx_sc_ipc *ipc, void *msg, bool have_resp)
}
static inline int
imx_scu_call_big_rpc(struct imx_sc_ipc *ipc, void *msg, bool have_resp)
{
return -EIO;
}
static inline int imx_scu_get_handle(struct imx_sc_ipc **ipc)
{
return -EIO;