When booting up preempt-rt kernel, there is below calltrace:
Call trace:
 ......
 __might_resched+0x12c/0x160
 rt_spin_lock+0x38/0xc8
 tegra_bpmp_transfer_atomic+0xa8/0x260
 tegra_bpmp_probe+0x1e8/0x3b0
 ......
 kernel_init_freeable+0x22c/0x2a0
 kernel_init+0x28/0x138
 ret_from_fork+0x10/0x20
This issue is introduced by commit 1abb081e41a7("firmware: tegra:
Simplify channel management"). Because in rt kernel, the spin_lock
might enter sleep status and it is called in atomic status, calltarce
is reported. To fix this issue, remove the irq disable/enable action
when calling function tegra_bpmp_transfer_atomic(), because it does
not need to restrict it to be called under atomic status. Accordingly,
remove the code of checking whether irq is in disabled status.

In addition, in order to protect critical code in both normal and
IRQ contexts, replace current spin_lock()/spin_unlock() with
spin_lock_irqsave()/spin_unlock_irqrestore()

Signed-off-by: Meng Li <[email protected]>
---
 drivers/firmware/tegra/bpmp.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index f114b50cd890..bf577399fd19 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -352,9 +352,7 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
 {
        struct tegra_bpmp_channel *channel;
        int err;
-
-       if (WARN_ON(!irqs_disabled()))
-               return -EPERM;
+       unsigned long flags;
 
        if (!tegra_bpmp_message_valid(msg))
                return -EINVAL;
@@ -369,16 +367,16 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
 
        channel = bpmp->tx_channel;
 
-       spin_lock(&bpmp->atomic_tx_lock);
+       spin_lock_irqsave(&bpmp->atomic_tx_lock, flags);
 
        err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
                                       msg->tx.data, msg->tx.size);
        if (err < 0) {
-               spin_unlock(&bpmp->atomic_tx_lock);
+               spin_unlock_irqrestore(&bpmp->atomic_tx_lock, flags);
                return err;
        }
 
-       spin_unlock(&bpmp->atomic_tx_lock);
+       spin_unlock_irqrestore(&bpmp->atomic_tx_lock, flags);
 
        err = tegra_bpmp_ring_doorbell(bpmp);
        if (err < 0)
@@ -594,7 +592,6 @@ static int tegra_bpmp_ping(struct tegra_bpmp *bpmp)
        struct mrq_ping_response response;
        struct mrq_ping_request request;
        struct tegra_bpmp_message msg;
-       unsigned long flags;
        ktime_t start, end;
        int err;
 
@@ -610,11 +607,9 @@ static int tegra_bpmp_ping(struct tegra_bpmp *bpmp)
        msg.rx.data = &response;
        msg.rx.size = sizeof(response);
 
-       local_irq_save(flags);
        start = ktime_get();
        err = tegra_bpmp_transfer_atomic(bpmp, &msg);
        end = ktime_get();
-       local_irq_restore(flags);
 
        if (!err)
                dev_dbg(bpmp->dev,
@@ -631,7 +626,6 @@ static int tegra_bpmp_get_firmware_tag_old(struct 
tegra_bpmp *bpmp, char *tag,
 {
        struct mrq_query_tag_request request;
        struct tegra_bpmp_message msg;
-       unsigned long flags;
        dma_addr_t phys;
        void *virt;
        int err;
@@ -652,9 +646,7 @@ static int tegra_bpmp_get_firmware_tag_old(struct 
tegra_bpmp *bpmp, char *tag,
        msg.tx.data = &request;
        msg.tx.size = sizeof(request);
 
-       local_irq_save(flags);
        err = tegra_bpmp_transfer_atomic(bpmp, &msg);
-       local_irq_restore(flags);
 
        if (err == 0)
                memcpy(tag, virt, TAG_SZ);
-- 
2.34.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#15970): 
https://lists.yoctoproject.org/g/linux-yocto/message/15970
Mute This Topic: https://lists.yoctoproject.org/mt/116271229/21656
Group Owner: [email protected]
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to