]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mailbox: tegra-hsp: Clear mailbox before using message
authorPekka Pessi <ppessi@nvidia.com>
Mon, 2 Dec 2024 10:05:59 +0000 (15:35 +0530)
committerJassi Brar <jassisinghbrar@gmail.com>
Sat, 18 Jan 2025 22:05:34 +0000 (16:05 -0600)
The Tegra RCE (Camera) driver expects the mailbox to be empty before
processing the IVC messages. On RT kernel, the threads processing the
IVC messages (which are invoked after `mbox_chan_received_data()` is
called) may be on a different CPU or running with a higher priority
than the HSP interrupt handler thread. This can cause it to act on the
message before the mailbox gets cleared in the HSP interrupt handler
resulting in a loss of IVC notification.

Fix this by clearing the mailbox data register before calling
`mbox_chan_received_data()`.

Fixes: 8f585d14030d ("mailbox: tegra-hsp: Add tegra_hsp_sm_ops")
Fixes: 74c20dd0f892 ("mailbox: tegra-hsp: Add 128-bit shared mailbox support")
Cc: stable@vger.kernel.org
Signed-off-by: Pekka Pessi <ppessi@nvidia.com>
Signed-off-by: Kartik Rajput <kkartik@nvidia.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
drivers/mailbox/tegra-hsp.c

index 8d5e2d7dc03b2fe075c7cd74c9a7e667db85a899..c1981f091bd1bb9249afa256dc27eef07555f285 100644 (file)
@@ -388,7 +388,6 @@ static void tegra_hsp_sm_recv32(struct tegra_hsp_channel *channel)
        value = tegra_hsp_channel_readl(channel, HSP_SM_SHRD_MBOX);
        value &= ~HSP_SM_SHRD_MBOX_FULL;
        msg = (void *)(unsigned long)value;
-       mbox_chan_received_data(channel->chan, msg);
 
        /*
         * Need to clear all bits here since some producers, such as TCU, depend
@@ -398,6 +397,8 @@ static void tegra_hsp_sm_recv32(struct tegra_hsp_channel *channel)
         * explicitly, so we have to make sure we cover all possible cases.
         */
        tegra_hsp_channel_writel(channel, 0x0, HSP_SM_SHRD_MBOX);
+
+       mbox_chan_received_data(channel->chan, msg);
 }
 
 static const struct tegra_hsp_sm_ops tegra_hsp_sm_32bit_ops = {
@@ -433,7 +434,6 @@ static void tegra_hsp_sm_recv128(struct tegra_hsp_channel *channel)
        value[3] = tegra_hsp_channel_readl(channel, HSP_SHRD_MBOX_TYPE1_DATA3);
 
        msg = (void *)(unsigned long)value;
-       mbox_chan_received_data(channel->chan, msg);
 
        /*
         * Clear data registers and tag.
@@ -443,6 +443,8 @@ static void tegra_hsp_sm_recv128(struct tegra_hsp_channel *channel)
        tegra_hsp_channel_writel(channel, 0x0, HSP_SHRD_MBOX_TYPE1_DATA2);
        tegra_hsp_channel_writel(channel, 0x0, HSP_SHRD_MBOX_TYPE1_DATA3);
        tegra_hsp_channel_writel(channel, 0x0, HSP_SHRD_MBOX_TYPE1_TAG);
+
+       mbox_chan_received_data(channel->chan, msg);
 }
 
 static const struct tegra_hsp_sm_ops tegra_hsp_sm_128bit_ops = {