]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
soc/tegra: cbb: Fix cross-fabric target timeout lookup
authorSumit Gupta <sumitg@nvidia.com>
Wed, 21 Jan 2026 10:12:05 +0000 (15:42 +0530)
committerThierry Reding <treding@nvidia.com>
Fri, 27 Mar 2026 14:30:54 +0000 (15:30 +0100)
When a fabric receives an error interrupt, the error may have
occurred on a different fabric. The target timeout lookup was using
the wrong base address (cbb->regs) with offsets from a different
fabric's target map, causing a kernel page fault.

  Unable to handle kernel paging request at virtual address ffff80000954cc00
  pc : tegra234_cbb_get_tmo_slv+0xc/0x28
  Call trace:
   tegra234_cbb_get_tmo_slv+0xc/0x28
   print_err_notifier+0x6c0/0x7d0
   tegra234_cbb_isr+0xe4/0x1b4

Add tegra234_cbb_get_fabric() to look up the correct fabric device
using fab_id, and use its base address for accessing target timeout
registers.

Fixes: 25de5c8fe0801 ("soc/tegra: cbb: Improve handling for per SoC fabric data")
Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/soc/tegra/cbb/tegra234-cbb.c

index e67ac058846a9af19991fe6d8f0770a4727c4db8..fb26f085f69143e19bca55f0c48430c70c9d9a73 100644 (file)
@@ -322,12 +322,37 @@ static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *target
        }
 }
 
+static struct tegra234_cbb *tegra234_cbb_get_fabric(u8 fab_id)
+{
+       struct tegra_cbb *entry;
+
+       list_for_each_entry(entry, &cbb_list, node) {
+               struct tegra234_cbb *priv = to_tegra234_cbb(entry);
+
+               if (priv->fabric->fab_id == fab_id)
+                       return priv;
+       }
+
+       return NULL;
+}
+
 static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb,
                                              u8 target_id, u8 fab_id)
 {
        const struct tegra234_target_lookup *map = cbb->fabric->fab_list[fab_id].target_map;
+       struct tegra234_cbb *target_cbb = NULL;
        void __iomem *addr;
 
+       if (fab_id == cbb->fabric->fab_id)
+               target_cbb = cbb;
+       else
+               target_cbb = tegra234_cbb_get_fabric(fab_id);
+
+       if (!target_cbb) {
+               dev_err(cbb->base.dev, "could not find fabric for fab_id:%d\n", fab_id);
+               return;
+       }
+
        if (target_id >= cbb->fabric->fab_list[fab_id].max_targets) {
                tegra_cbb_print_err(file, "\t  Invalid target_id:%d\n", target_id);
                return;
@@ -350,7 +375,7 @@ static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegr
         *      e) Goto step-a till all bits are set.
         */
 
-       addr = cbb->regs + map[target_id].offset;
+       addr = target_cbb->regs + map[target_id].offset;
 
        if (strstr(map[target_id].name, "AXI2APB")) {
                addr += APB_BLOCK_TMO_STATUS_0;