Skip to content

Commit 8445d69

Browse files
Sumit Guptagregkh
authored andcommitted
soc/tegra: cbb: Fix cross-fabric target timeout lookup
[ Upstream commit a5f51b0 ] 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: 25de5c8 ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5c009a5 commit 8445d69

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

drivers/soc/tegra/cbb/tegra234-cbb.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,37 @@ static void tegra234_cbb_lookup_apbslv(struct seq_file *file, const char *target
313313
}
314314
}
315315

316+
static struct tegra234_cbb *tegra234_cbb_get_fabric(u8 fab_id)
317+
{
318+
struct tegra_cbb *entry;
319+
320+
list_for_each_entry(entry, &cbb_list, node) {
321+
struct tegra234_cbb *priv = to_tegra234_cbb(entry);
322+
323+
if (priv->fabric->fab_id == fab_id)
324+
return priv;
325+
}
326+
327+
return NULL;
328+
}
329+
316330
static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegra234_cbb *cbb,
317331
u8 target_id, u8 fab_id)
318332
{
319333
const struct tegra234_target_lookup *map = cbb->fabric->fab_list[fab_id].target_map;
334+
struct tegra234_cbb *target_cbb = NULL;
320335
void __iomem *addr;
321336

337+
if (fab_id == cbb->fabric->fab_id)
338+
target_cbb = cbb;
339+
else
340+
target_cbb = tegra234_cbb_get_fabric(fab_id);
341+
342+
if (!target_cbb) {
343+
dev_err(cbb->base.dev, "could not find fabric for fab_id:%d\n", fab_id);
344+
return;
345+
}
346+
322347
if (target_id >= cbb->fabric->fab_list[fab_id].max_targets) {
323348
tegra_cbb_print_err(file, "\t Invalid target_id:%d\n", target_id);
324349
return;
@@ -341,7 +366,7 @@ static void tegra234_sw_lookup_target_timeout(struct seq_file *file, struct tegr
341366
* e) Goto step-a till all bits are set.
342367
*/
343368

344-
addr = cbb->regs + map[target_id].offset;
369+
addr = target_cbb->regs + map[target_id].offset;
345370

346371
if (strstr(map[target_id].name, "AXI2APB")) {
347372
addr += APB_BLOCK_TMO_STATUS_0;

0 commit comments

Comments
 (0)