--- /dev/null
+From a44ad90221a4368d06e0f717ac44a12423df8542 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Mar 2020 00:00:05 +0200
+Subject: firmware: imx: scu: Fix corruption of header
+
+From: Franck LENORMAND <franck.lenormand@nxp.com>
+
+[ Upstream commit f5f27b79eab80de0287c243a22169e4876b08d5e ]
+
+The header of the message to send can be changed if the
+response is longer than the request:
+ - 1st word, the header is sent
+ - the remaining words of the message are sent
+ - the response is received asynchronously during the
+ execution of the loop, changing the size field in
+ the header
+ - the for loop test the termination condition using
+ the corrupted header
+
+It is the case for the API build_info which has just a
+header as request but 3 words in response.
+
+This issue is fixed storing the header locally instead of
+using a pointer on it.
+
+Fixes: edbee095fafb (firmware: imx: add SCU firmware driver support)
+
+Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
+Reviewed-by: Leonard Crestez <leonard.crestez@nxp.com>
+Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/imx/imx-scu.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c
+index e94a5585b698..b3da2e193ad2 100644
+--- a/drivers/firmware/imx/imx-scu.c
++++ b/drivers/firmware/imx/imx-scu.c
+@@ -158,7 +158,7 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
+
+ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
+ {
+- struct imx_sc_rpc_msg *hdr = msg;
++ struct imx_sc_rpc_msg hdr = *(struct imx_sc_rpc_msg *)msg;
+ struct imx_sc_chan *sc_chan;
+ u32 *data = msg;
+ int ret;
+@@ -166,13 +166,13 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
+ int i;
+
+ /* Check size */
+- if (hdr->size > IMX_SC_RPC_MAX_MSG)
++ if (hdr.size > IMX_SC_RPC_MAX_MSG)
+ return -EINVAL;
+
+- dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
+- hdr->func, hdr->size);
++ dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr.svc,
++ hdr.func, hdr.size);
+
+- size = sc_ipc->fast_ipc ? 1 : hdr->size;
++ size = sc_ipc->fast_ipc ? 1 : hdr.size;
+ for (i = 0; i < size; i++) {
+ sc_chan = &sc_ipc->chans[i % 4];
+
+--
+2.25.1
+
--- /dev/null
+From 3eadacdc54b15378177fe5060162b690023c20e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Mar 2020 15:49:53 +0800
+Subject: firmware: imx-scu: Support one TX and one RX
+
+From: Peng Fan <peng.fan@nxp.com>
+
+[ Upstream commit f25a066d1a07affb7bea4e5d9c179c3338338e23 ]
+
+Current imx-scu requires four TX and four RX to communicate with
+SCU. This is low efficient and causes lots of mailbox interrupts.
+
+With imx-mailbox driver could support one TX to use all four transmit
+registers and one RX to use all four receive registers, imx-scu
+could use one TX and one RX.
+
+Signed-off-by: Peng Fan <peng.fan@nxp.com>
+Signed-off-by: Shawn Guo <shawnguo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/imx/imx-scu.c | 54 +++++++++++++++++++++++++++-------
+ 1 file changed, 43 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c
+index f71eaa5bf52d..e94a5585b698 100644
+--- a/drivers/firmware/imx/imx-scu.c
++++ b/drivers/firmware/imx/imx-scu.c
+@@ -38,6 +38,7 @@ struct imx_sc_ipc {
+ struct device *dev;
+ struct mutex lock;
+ struct completion done;
++ bool fast_ipc;
+
+ /* temporarily store the SCU msg */
+ u32 *msg;
+@@ -115,6 +116,7 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
+ struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
+ struct imx_sc_rpc_msg *hdr;
+ u32 *data = msg;
++ int i;
+
+ if (!sc_ipc->msg) {
+ dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n",
+@@ -122,6 +124,19 @@ static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
+ return;
+ }
+
++ if (sc_ipc->fast_ipc) {
++ hdr = msg;
++ sc_ipc->rx_size = hdr->size;
++ sc_ipc->msg[0] = *data++;
++
++ for (i = 1; i < sc_ipc->rx_size; i++)
++ sc_ipc->msg[i] = *data++;
++
++ complete(&sc_ipc->done);
++
++ return;
++ }
++
+ if (sc_chan->idx == 0) {
+ hdr = msg;
+ sc_ipc->rx_size = hdr->size;
+@@ -147,6 +162,7 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
+ struct imx_sc_chan *sc_chan;
+ u32 *data = msg;
+ int ret;
++ int size;
+ int i;
+
+ /* Check size */
+@@ -156,7 +172,8 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
+ dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
+ hdr->func, hdr->size);
+
+- for (i = 0; i < hdr->size; i++) {
++ size = sc_ipc->fast_ipc ? 1 : hdr->size;
++ for (i = 0; i < size; i++) {
+ sc_chan = &sc_ipc->chans[i % 4];
+
+ /*
+@@ -168,8 +185,10 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
+ * Wait for tx_done before every send to ensure that no
+ * queueing happens at the mailbox channel level.
+ */
+- wait_for_completion(&sc_chan->tx_done);
+- reinit_completion(&sc_chan->tx_done);
++ if (!sc_ipc->fast_ipc) {
++ wait_for_completion(&sc_chan->tx_done);
++ reinit_completion(&sc_chan->tx_done);
++ }
+
+ ret = mbox_send_message(sc_chan->ch, &data[i]);
+ if (ret < 0)
+@@ -246,6 +265,8 @@ static int imx_scu_probe(struct platform_device *pdev)
+ struct imx_sc_chan *sc_chan;
+ struct mbox_client *cl;
+ char *chan_name;
++ struct of_phandle_args args;
++ int num_channel;
+ int ret;
+ int i;
+
+@@ -253,11 +274,20 @@ static int imx_scu_probe(struct platform_device *pdev)
+ if (!sc_ipc)
+ return -ENOMEM;
+
+- for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
+- if (i < 4)
++ ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
++ "#mbox-cells", 0, &args);
++ if (ret)
++ return ret;
++
++ sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
++
++ num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
++ for (i = 0; i < num_channel; i++) {
++ if (i < num_channel / 2)
+ chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
+ else
+- chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
++ chan_name = kasprintf(GFP_KERNEL, "rx%d",
++ i - num_channel / 2);
+
+ if (!chan_name)
+ return -ENOMEM;
+@@ -269,13 +299,15 @@ static int imx_scu_probe(struct platform_device *pdev)
+ cl->knows_txdone = true;
+ cl->rx_callback = imx_scu_rx_callback;
+
+- /* Initial tx_done completion as "done" */
+- cl->tx_done = imx_scu_tx_done;
+- init_completion(&sc_chan->tx_done);
+- complete(&sc_chan->tx_done);
++ if (!sc_ipc->fast_ipc) {
++ /* Initial tx_done completion as "done" */
++ cl->tx_done = imx_scu_tx_done;
++ init_completion(&sc_chan->tx_done);
++ complete(&sc_chan->tx_done);
++ }
+
+ sc_chan->sc_ipc = sc_ipc;
+- sc_chan->idx = i % 4;
++ sc_chan->idx = i % (num_channel / 2);
+ sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
+ if (IS_ERR(sc_chan->ch)) {
+ ret = PTR_ERR(sc_chan->ch);
+--
+2.25.1
+