diff mbox series

[V1,1/4] memory: tegra: Add support for mc interrupts

Message ID 1641926750-27544-2-git-send-email-amhetre@nvidia.com
State Changes Requested
Headers show
Series memory: tegra: Update mc interrupts | expand

Commit Message

Ashish Mhetre Jan. 11, 2022, 6:45 p.m. UTC
Implement new structure for function related to mc interrupts.
Move handle_irq into this structure.
Add support for clearing interrupts.

Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
---
 drivers/memory/tegra/mc.c       | 14 +++++++++++---
 drivers/memory/tegra/mc.h       |  1 +
 drivers/memory/tegra/tegra114.c |  1 +
 drivers/memory/tegra/tegra124.c |  2 ++
 drivers/memory/tegra/tegra186.c | 14 ++++++++++++++
 drivers/memory/tegra/tegra194.c | 12 ++++++++++++
 drivers/memory/tegra/tegra20.c  |  6 +++++-
 drivers/memory/tegra/tegra210.c |  1 +
 drivers/memory/tegra/tegra30.c  |  1 +
 include/soc/tegra/mc.h          |  7 ++++++-
 10 files changed, 54 insertions(+), 5 deletions(-)

Comments

Krzysztof Kozlowski Jan. 11, 2022, 8:29 p.m. UTC | #1
On 11/01/2022 19:45, Ashish Mhetre wrote:
> Implement new structure for function related to mc interrupts.

s/mc/MC/

> Move handle_irq into this structure.
> Add support for clearing interrupts.

The subject says you are adding support for MC interrupts, so before
they were not supported at all?

Here you also mention clearing of interrupts - another new feature. One
commit for refactoring (adding new structure) which does not change
functionality, second commit for adding new feature.

Different question - why do you need new structure for just two function
pointers? Why these different IRQ handling functions cannot be in
tegra_mc_ops? To me, it's unnecessary code complexity (plus performance
impact, but it's not that important). If this is really, really needed,
please describe the rationale in the commit message.

> 
> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
> ---
>  drivers/memory/tegra/mc.c       | 14 +++++++++++---
>  drivers/memory/tegra/mc.h       |  1 +
>  drivers/memory/tegra/tegra114.c |  1 +
>  drivers/memory/tegra/tegra124.c |  2 ++
>  drivers/memory/tegra/tegra186.c | 14 ++++++++++++++
>  drivers/memory/tegra/tegra194.c | 12 ++++++++++++
>  drivers/memory/tegra/tegra20.c  |  6 +++++-
>  drivers/memory/tegra/tegra210.c |  1 +
>  drivers/memory/tegra/tegra30.c  |  1 +
>  include/soc/tegra/mc.h          |  7 ++++++-
>  10 files changed, 54 insertions(+), 5 deletions(-)
> 


Best regards,
Krzysztof
Dmitry Osipenko Jan. 12, 2022, 8:13 a.m. UTC | #2
11.01.2022 21:45, Ashish Mhetre пишет:
>  
> @@ -765,16 +768,21 @@ static int tegra_mc_probe(struct platform_device *pdev)
>  			return err;
>  	}
>  
> -	if (mc->soc->ops && mc->soc->ops->handle_irq) {
> +	if (mc->soc->interrupt_ops && mc->soc->interrupt_ops->handle_irq) {
>  		mc->irq = platform_get_irq(pdev, 0);
>  		if (mc->irq < 0)
>  			return mc->irq;
>  
>  		WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
>  
> +		/* clear any mc-errs that occurred before. */

s/mc-errs/Memory Controller errors/

> +		if (mc->soc->interrupt_ops->clear_interrupt)
> +			mc->soc->interrupt_ops->clear_interrupt(mc);

There is no explanation of this change neither in the code, nor in the
commit message. Please always provide detailed descriptions for a
non-trivial changes.

Interrupts aren't cleared intentionally by the driver, otherwise you'll
never know about early-boot memory faults which happened before the
probe. Hence this change is incorrect.
Ashish Mhetre Jan. 19, 2022, 7:36 a.m. UTC | #3
On 1/12/2022 1:59 AM, Krzysztof Kozlowski wrote:
> External email: Use caution opening links or attachments
> 
> 
> On 11/01/2022 19:45, Ashish Mhetre wrote:
>> Implement new structure for function related to mc interrupts.
> 
> s/mc/MC/
> 
Okay, I'll update these.
>> Move handle_irq into this structure.
>> Add support for clearing interrupts.
> 
> The subject says you are adding support for MC interrupts, so before
> they were not supported at all?
> 
Interrupt handling and error logging is not supported from Tegra186
onward. So the patches are for adding supported interrupts and logging
them from Tegra186 onward. But you are right, subject/commit message is
misleading. I'll update it in next version.

> Here you also mention clearing of interrupts - another new feature. One
> commit for refactoring (adding new structure) which does not change
> functionality, second commit for adding new feature.
> > Different question - why do you need new structure for just two function
> pointers? Why these different IRQ handling functions cannot be in
> tegra_mc_ops? To me, it's unnecessary code complexity (plus performance
> impact, but it's not that important). If this is really, really needed,
> please describe the rationale in the commit message.
>
clearing_interrupts() won't be needed. As pointed by Dmitry, we should
be logging early boot MC interrupts as well instead of clearing them.
Also, I'll keep handling irq inside tegra_mc_ops instead of adding new
structure.

>>
>> Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
>> ---
>>   drivers/memory/tegra/mc.c       | 14 +++++++++++---
>>   drivers/memory/tegra/mc.h       |  1 +
>>   drivers/memory/tegra/tegra114.c |  1 +
>>   drivers/memory/tegra/tegra124.c |  2 ++
>>   drivers/memory/tegra/tegra186.c | 14 ++++++++++++++
>>   drivers/memory/tegra/tegra194.c | 12 ++++++++++++
>>   drivers/memory/tegra/tegra20.c  |  6 +++++-
>>   drivers/memory/tegra/tegra210.c |  1 +
>>   drivers/memory/tegra/tegra30.c  |  1 +
>>   include/soc/tegra/mc.h          |  7 ++++++-
>>   10 files changed, 54 insertions(+), 5 deletions(-)
>>
> 
> 
> Best regards,
> Krzysztof
Ashish Mhetre Jan. 19, 2022, 8:47 a.m. UTC | #4
On 1/12/2022 1:43 PM, Dmitry Osipenko wrote:
> External email: Use caution opening links or attachments
> 
> 
> 11.01.2022 21:45, Ashish Mhetre пишет:
>>
>> @@ -765,16 +768,21 @@ static int tegra_mc_probe(struct platform_device *pdev)
>>                        return err;
>>        }
>>
>> -     if (mc->soc->ops && mc->soc->ops->handle_irq) {
>> +     if (mc->soc->interrupt_ops && mc->soc->interrupt_ops->handle_irq) {
>>                mc->irq = platform_get_irq(pdev, 0);
>>                if (mc->irq < 0)
>>                        return mc->irq;
>>
>>                WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
>>
>> +             /* clear any mc-errs that occurred before. */
> 
> s/mc-errs/Memory Controller errors/
> 
Sure, I'll update these in next version.
>> +             if (mc->soc->interrupt_ops->clear_interrupt)
>> +                     mc->soc->interrupt_ops->clear_interrupt(mc);
> 
> There is no explanation of this change neither in the code, nor in the
> commit message. Please always provide detailed descriptions for a
> non-trivial changes.
> 
> Interrupts aren't cleared intentionally by the driver, otherwise you'll
> never know about early-boot memory faults which happened before the
> probe. Hence this change is incorrect.
That's true, we should be logging early-boot memory faults as well.
Ideally there shouldn't be any early-boot faults as all clients will
be up after MC, right? But I agree that we should be checking and
logging if any interrupt is present.
Dmitry Osipenko Jan. 19, 2022, 1:42 p.m. UTC | #5
19.01.2022 11:47, Ashish Mhetre пишет:
> 
> 
> On 1/12/2022 1:43 PM, Dmitry Osipenko wrote:
>> External email: Use caution opening links or attachments
>>
>>
>> 11.01.2022 21:45, Ashish Mhetre пишет:
>>>
>>> @@ -765,16 +768,21 @@ static int tegra_mc_probe(struct
>>> platform_device *pdev)
>>>                        return err;
>>>        }
>>>
>>> -     if (mc->soc->ops && mc->soc->ops->handle_irq) {
>>> +     if (mc->soc->interrupt_ops &&
>>> mc->soc->interrupt_ops->handle_irq) {
>>>                mc->irq = platform_get_irq(pdev, 0);
>>>                if (mc->irq < 0)
>>>                        return mc->irq;
>>>
>>>                WARN(!mc->soc->client_id_mask, "missing client ID mask
>>> for this SoC\n");
>>>
>>> +             /* clear any mc-errs that occurred before. */
>>
>> s/mc-errs/Memory Controller errors/
>>
> Sure, I'll update these in next version.
>>> +             if (mc->soc->interrupt_ops->clear_interrupt)
>>> +                     mc->soc->interrupt_ops->clear_interrupt(mc);
>>
>> There is no explanation of this change neither in the code, nor in the
>> commit message. Please always provide detailed descriptions for a
>> non-trivial changes.
>>
>> Interrupts aren't cleared intentionally by the driver, otherwise you'll
>> never know about early-boot memory faults which happened before the
>> probe. Hence this change is incorrect.
> That's true, we should be logging early-boot memory faults as well.
> Ideally there shouldn't be any early-boot faults as all clients will
> be up after MC, right? But I agree that we should be checking and
> logging if any interrupt is present.

Normally there won't be any errors during early boot, otherwise they
need to be fixed.
diff mbox series

Patch

diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 3c5aae7..3b3f052 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -604,9 +604,12 @@  static irqreturn_t tegra30_mc_handle_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+const struct tegra_mc_interrupt_ops tegra30_mc_interrupt_ops = {
+	.handle_irq = tegra30_mc_handle_irq,
+};
+
 const struct tegra_mc_ops tegra30_mc_ops = {
 	.probe = tegra30_mc_probe,
-	.handle_irq = tegra30_mc_handle_irq,
 };
 #endif
 
@@ -765,16 +768,21 @@  static int tegra_mc_probe(struct platform_device *pdev)
 			return err;
 	}
 
-	if (mc->soc->ops && mc->soc->ops->handle_irq) {
+	if (mc->soc->interrupt_ops && mc->soc->interrupt_ops->handle_irq) {
 		mc->irq = platform_get_irq(pdev, 0);
 		if (mc->irq < 0)
 			return mc->irq;
 
 		WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n");
 
+		/* clear any mc-errs that occurred before. */
+		if (mc->soc->interrupt_ops->clear_interrupt)
+			mc->soc->interrupt_ops->clear_interrupt(mc);
+
 		mc_writel(mc, mc->soc->intmask, MC_INTMASK);
 
-		err = devm_request_irq(&pdev->dev, mc->irq, mc->soc->ops->handle_irq, 0,
+		err = devm_request_irq(&pdev->dev, mc->irq,
+				       mc->soc->interrupt_ops->handle_irq, 0,
 				       dev_name(&pdev->dev), mc);
 		if (err < 0) {
 			dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index 1e49298..f1fd457 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -144,6 +144,7 @@  extern const struct tegra_mc_soc tegra194_mc_soc;
     defined(CONFIG_ARCH_TEGRA_210_SOC)
 int tegra30_mc_probe(struct tegra_mc *mc);
 extern const struct tegra_mc_ops tegra30_mc_ops;
+extern const struct tegra_mc_interrupt_ops tegra30_mc_interrupt_ops;
 #endif
 
 #if defined(CONFIG_ARCH_TEGRA_186_SOC) || \
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index 4135057..f7b8dd9 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -1114,4 +1114,5 @@  const struct tegra_mc_soc tegra114_mc_soc = {
 	.resets = tegra114_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra114_mc_resets),
 	.ops = &tegra30_mc_ops,
+	.interrupt_ops = &tegra30_mc_interrupt_ops,
 };
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index d780a84..8b704c1 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1275,6 +1275,7 @@  const struct tegra_mc_soc tegra124_mc_soc = {
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
 	.icc_ops = &tegra124_mc_icc_ops,
 	.ops = &tegra30_mc_ops,
+	.interrupt_ops = &tegra30_mc_interrupt_ops,
 };
 #endif /* CONFIG_ARCH_TEGRA_124_SOC */
 
@@ -1307,5 +1308,6 @@  const struct tegra_mc_soc tegra132_mc_soc = {
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
 	.icc_ops = &tegra124_mc_icc_ops,
 	.ops = &tegra30_mc_ops,
+	.interrupt_ops = &tegra30_mc_interrupt_ops,
 };
 #endif /* CONFIG_ARCH_TEGRA_132_SOC */
diff --git a/drivers/memory/tegra/tegra186.c b/drivers/memory/tegra/tegra186.c
index e65eac5..b548b6a 100644
--- a/drivers/memory/tegra/tegra186.c
+++ b/drivers/memory/tegra/tegra186.c
@@ -12,6 +12,8 @@ 
 
 #include <soc/tegra/mc.h>
 
+#include "mc.h"
+
 #if defined(CONFIG_ARCH_TEGRA_186_SOC)
 #include <dt-bindings/memory/tegra186-mc.h>
 #endif
@@ -20,6 +22,8 @@ 
 #define MC_SID_STREAMID_SECURITY_WRITE_ACCESS_DISABLED BIT(16)
 #define MC_SID_STREAMID_SECURITY_OVERRIDE BIT(8)
 
+#define MC_INTSTATUS_CLEAR			0x00033340
+
 static void tegra186_mc_program_sid(struct tegra_mc *mc)
 {
 	unsigned int i;
@@ -137,6 +141,15 @@  static int tegra186_mc_probe_device(struct tegra_mc *mc, struct device *dev)
 	return 0;
 }
 
+static void tegra186_mc_clear_interrupt(struct tegra_mc *mc)
+{
+	mc_writel(mc, MC_INTSTATUS_CLEAR, MC_INTSTATUS);
+}
+
+const struct tegra_mc_interrupt_ops tegra186_mc_interrupt_ops = {
+	.clear_interrupt = tegra186_mc_clear_interrupt,
+};
+
 const struct tegra_mc_ops tegra186_mc_ops = {
 	.probe = tegra186_mc_probe,
 	.remove = tegra186_mc_remove,
@@ -874,5 +887,6 @@  const struct tegra_mc_soc tegra186_mc_soc = {
 	.clients = tegra186_mc_clients,
 	.num_address_bits = 40,
 	.ops = &tegra186_mc_ops,
+	.interrupt_ops = &tegra186_mc_interrupt_ops,
 };
 #endif
diff --git a/drivers/memory/tegra/tegra194.c b/drivers/memory/tegra/tegra194.c
index cab998b..19f135f 100644
--- a/drivers/memory/tegra/tegra194.c
+++ b/drivers/memory/tegra/tegra194.c
@@ -9,6 +9,17 @@ 
 
 #include "mc.h"
 
+#define MC_INTSTATUS_CLEAR			0x00133340
+
+static void tegra194_mc_clear_interrupt(struct tegra_mc *mc)
+{
+	mc_writel(mc, MC_INTSTATUS_CLEAR, MC_INTSTATUS);
+}
+
+const struct tegra_mc_interrupt_ops tegra194_mc_interrupt_ops = {
+	.clear_interrupt = tegra194_mc_clear_interrupt,
+};
+
 static const struct tegra_mc_client tegra194_mc_clients[] = {
 	{
 		.id = TEGRA194_MEMORY_CLIENT_PTCR,
@@ -1348,4 +1359,5 @@  const struct tegra_mc_soc tegra194_mc_soc = {
 	.clients = tegra194_mc_clients,
 	.num_address_bits = 40,
 	.ops = &tegra186_mc_ops,
+	.interrupt_ops = &tegra194_mc_interrupt_ops,
 };
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
index fcd7738..3bcb2ca 100644
--- a/drivers/memory/tegra/tegra20.c
+++ b/drivers/memory/tegra/tegra20.c
@@ -786,11 +786,15 @@  static irqreturn_t tegra20_mc_handle_irq(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static const struct tegra_mc_interrupt_ops tegra20_mc_interrupt_ops = {
+	.handle_irq = tegra20_mc_handle_irq,
+};
+
 static const struct tegra_mc_ops tegra20_mc_ops = {
 	.probe = tegra20_mc_probe,
 	.suspend = tegra20_mc_suspend,
 	.resume = tegra20_mc_resume,
-	.handle_irq = tegra20_mc_handle_irq,
+	.interrupt_ops = tegra20_mc_interrupt_ops,
 };
 
 const struct tegra_mc_soc tegra20_mc_soc = {
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
index 8ab6498..d7ed163 100644
--- a/drivers/memory/tegra/tegra210.c
+++ b/drivers/memory/tegra/tegra210.c
@@ -1287,4 +1287,5 @@  const struct tegra_mc_soc tegra210_mc_soc = {
 	.resets = tegra210_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra210_mc_resets),
 	.ops = &tegra30_mc_ops,
+	.interrupt_ops = &tegra30_mc_interrupt_ops,
 };
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index 8431635..bb5ff68 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -1400,4 +1400,5 @@  const struct tegra_mc_soc tegra30_mc_soc = {
 	.num_resets = ARRAY_SIZE(tegra30_mc_resets),
 	.icc_ops = &tegra30_mc_icc_ops,
 	.ops = &tegra30_mc_ops,
+	.interrupt_ops = &tegra30_mc_interrupt_ops,
 };
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 1066b11..debc47b 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -170,6 +170,11 @@  struct tegra_mc_icc_ops {
 						void *data);
 };
 
+struct tegra_mc_interrupt_ops {
+	void (*clear_interrupt)(struct tegra_mc *mc);
+	irqreturn_t (*handle_irq)(int irq, void *data);
+};
+
 struct tegra_mc_ops {
 	/*
 	 * @probe: Callback to set up SoC-specific bits of the memory controller. This is called
@@ -179,7 +184,6 @@  struct tegra_mc_ops {
 	void (*remove)(struct tegra_mc *mc);
 	int (*suspend)(struct tegra_mc *mc);
 	int (*resume)(struct tegra_mc *mc);
-	irqreturn_t (*handle_irq)(int irq, void *data);
 	int (*probe_device)(struct tegra_mc *mc, struct device *dev);
 };
 
@@ -205,6 +209,7 @@  struct tegra_mc_soc {
 
 	const struct tegra_mc_icc_ops *icc_ops;
 	const struct tegra_mc_ops *ops;
+	const struct tegra_mc_interrupt_ops *interrupt_ops;
 };
 
 struct tegra_mc {