Re: [PATCH v6 4/4] memory: tegra: Add MC error logging support for Tegra264
From: Ketan Patil
Date: Wed Feb 18 2026 - 05:30:34 EST
On 17/02/26 14:01, Krzysztof Kozlowski wrote:
External email: Use caution opening links or attachmentsYes, I am taking care of this in the next revision.
On 30/01/2026 18:30, Ketan Patil wrote:
In Tegra264, different components from memory subsystems like MemoryYou should handle it correctly instead. WARN reboots some systems and
Controller Fabric (MCF), HUB, HUB Common (HUBC), Side Band Shim (SBS)
and channels have different interrupt lines for receiving memory
controller error interrupts.
Add support for logging memory controller errors on Tegra264.
- Add MC error handling flow for MCF, HUB, HUBC, SBS and channels.
- Each of these components have different interrupt lines for MC error.
- Register interrupt handlers for interrupts from these different MC
components.
- There is no global interrupt status register in Tegra264 unlike older
Tegra chips.
- There are common interrupt status registers in case of MCF, HUB, HUBC
from which figure out the slice number or hub number responsible for
generating interrupt and then read interrupt status register to find out
type of violation.
- Introduce new SoC specific fields in tegra_mc_soc like interrupt mask
values for MCF, HUB, HUBC etc., which are SoC specific.
Signed-off-by: Ketan Patil <ketanp@xxxxxxxxxx>
---
drivers/memory/tegra/mc.c | 35 +--
drivers/memory/tegra/mc.h | 83 ++++++-
drivers/memory/tegra/tegra114.c | 13 +-
drivers/memory/tegra/tegra124.c | 32 ++-
drivers/memory/tegra/tegra186.c | 24 +-
drivers/memory/tegra/tegra194.c | 17 +-
drivers/memory/tegra/tegra20.c | 23 +-
drivers/memory/tegra/tegra210.c | 16 +-
drivers/memory/tegra/tegra234.c | 17 +-
drivers/memory/tegra/tegra264.c | 428 +++++++++++++++++++++++++++++++-
drivers/memory/tegra/tegra30.c | 13 +-
include/soc/tegra/mc.h | 10 +-
12 files changed, 648 insertions(+), 63 deletions(-)
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 49c470f7b1f7..a102a8ea7926 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -597,16 +597,16 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
}
/* mask all interrupts to avoid flooding */
- status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmask;
+ status = mc_ch_readl(mc, channel, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
} else {
- status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
+ status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmasks[0].mask;
}
if (!status)
return IRQ_NONE;
for_each_set_bit(bit, &status, 32) {
- const char *error = tegra_mc_status_names[bit] ?: "unknown";
+ const char *error = tegra20_mc_status_names[bit] ?: "unknown";
const char *client = "unknown", *desc;
const char *direction, *secure;
u32 status_reg, addr_reg;
@@ -669,9 +669,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
addr = mc_ch_readl(mc, channel, addr_hi_reg);
else
addr = mc_readl(mc, addr_hi_reg);
- } else {
+ } else if (mc->soc->mc_addr_hi_mask) {
addr = ((value >> MC_ERR_STATUS_ADR_HI_SHIFT) &
- MC_ERR_STATUS_ADR_HI_MASK);
+ mc->soc->mc_addr_hi_mask);
+ } else {
+ WARN_ON(1);
this does not look like really impossible path, which would justify it.
I am re-working the series to avoid making these functions public.
}...
addr <<= 32;
}
@@ -696,11 +698,11 @@ irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
}
}
+This is such a confusing design... Function declared in mc.h header,
+#define ERR_GENERALIZED_APERTURE_ID_SHIFT 0
+#define ERR_GENERALIZED_APERTURE_ID_MASK 0x1F
+#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_SHIFT 5
+#define ERR_GENERALIZED_CARVEOUT_APERTURE_ID_MASK 0x1F
+
static inline u32 tegra_mc_scale_percents(u64 val, unsigned int percents)
{
val = val * percents;
@@ -187,15 +255,18 @@ extern const struct tegra_mc_ops tegra30_mc_ops;
#if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
defined(CONFIG_ARCH_TEGRA_194_SOC) || \
- defined(CONFIG_ARCH_TEGRA_234_SOC) || \
- defined(CONFIG_ARCH_TEGRA_264_SOC)
+ defined(CONFIG_ARCH_TEGRA_234_SOC)
extern const struct tegra_mc_ops tegra186_mc_ops;
#endif
irqreturn_t tegra30_mc_handle_irq(int irq, void *data);
extern const irq_handler_t tegra30_mc_irq_handlers[];
-extern const char * const tegra_mc_status_names[32];
-extern const char * const tegra_mc_error_names[8];
+extern const char * const tegra20_mc_status_names[32];
+extern const char * const tegra20_mc_error_names[8];
+int tegra186_mc_probe(struct tegra_mc *mc);
+int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev);
defined in a MODULE but used in a driver which can only be built in,
because it depends on some ARCH_foo stuf. If I deciphered it correctly
this fails and needs EXPORT_SYMBOL_GPL, but maybe I deciphered it wrong,
because code is confusing. Your drivers Makefile should not have
ARCH_TEGRA_FOO, but dedicated entries so the state of each driver is
obvious by reading Kconfig of this directory - it is built-in or tristate.
+int tegra186_mc_resume(struct tegra_mc *mc);_mc {
+void tegra186_mc_remove(struct tegra_mc *mc);
Best regards,
Krzysztof
Thanks