All of lore.kernel.org
 help / color / mirror / Atom feed
From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3] irqchip: gic: Allow interrupt level to be set for PPIs.
Date: Mon, 12 Jan 2015 11:19:25 +0000	[thread overview]
Message-ID: <54B3ADBD.6050009@arm.com> (raw)
In-Reply-To: <20150112111509.GC823@e106497-lin.cambridge.arm.com>

Hi Liviu,

Welcome back! ;-)

On 12/01/15 11:15, Liviu Dudau wrote:
> On Mon, Jan 05, 2015 at 09:05:06AM +0000, Marc Zyngier wrote:
>> Hi Liviu,
> 
> Hi Marc,
> 
>>
>> On 01/12/14 12:45, Liviu Dudau wrote:
>>> During a recent cleanup of the arm64 DTs it has become clear that
>>> the handling of PPIs in xxxx_set_type() is incorrect. The ARM TRMs
>>> for GICv2 and later allow for "implementation defined" support for
>>> setting the edge or level type of the PPI interrupts and don't restrict
>>> the activation level of the signal. Current ARM implementations
>>> do restrict the PPI level type to IRQ_TYPE_LEVEL_LOW, but licensees
>>> of the IP can decide to shoot themselves in the foot at any time.
>>>
>>> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>>> ---
>>>
>>> Made a stupid mistake in v2 and got my bit test confused with logical test.
>>>
>>>  Documentation/devicetree/bindings/arm/gic.txt |  8 ++++++--
>>>  drivers/irqchip/irq-gic-common.c              | 21 +++++++++++++--------
>>>  drivers/irqchip/irq-gic-common.h              |  2 +-
>>>  drivers/irqchip/irq-gic-v3.c                  |  8 ++++----
>>>  drivers/irqchip/irq-gic.c                     |  9 ++++++---
>>>  drivers/irqchip/irq-hip04.c                   |  9 ++++++---
>>>  6 files changed, 36 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
>>> index 8112d0c..c97484b 100644
>>> --- a/Documentation/devicetree/bindings/arm/gic.txt
>>> +++ b/Documentation/devicetree/bindings/arm/gic.txt
>>> @@ -32,12 +32,16 @@ Main node required properties:
>>>    The 3rd cell is the flags, encoded as follows:
>>>  	bits[3:0] trigger type and level flags.
>>>  		1 = low-to-high edge triggered
>>> -		2 = high-to-low edge triggered
>>> +		2 = high-to-low edge triggered (invalid for SPIs)
>>>  		4 = active high level-sensitive
>>> -		8 = active low level-sensitive
>>> +		8 = active low level-sensitive (invalid for SPIs).
>>>  	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
>>>  	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
>>>  	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
>>> +	Also note that the configurability of PPI interrupts is IMPLEMENTATION
>>> +	DEFINED and as such not guaranteed to be present (most SoC available
>>> +	in 2014 seem to ignore the setting of this flag and use the hardware
>>> +	default value).
>>>  
>>>  - reg : Specifies base physical address(s) and size of the GIC registers. The
>>>    first region is the GIC distributor register base and size. The 2nd region is
>>> diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
>>> index 61541ff..ffee521 100644
>>> --- a/drivers/irqchip/irq-gic-common.c
>>> +++ b/drivers/irqchip/irq-gic-common.c
>>> @@ -21,7 +21,7 @@
>>>  
>>>  #include "irq-gic-common.h"
>>>  
>>> -void gic_configure_irq(unsigned int irq, unsigned int type,
>>> +int gic_configure_irq(unsigned int irq, unsigned int type,
>>>  		       void __iomem *base, void (*sync_access)(void))
>>>  {
>>>  	u32 enablemask = 1 << (irq % 32);
>>> @@ -29,16 +29,17 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
>>>  	u32 confmask = 0x2 << ((irq % 16) * 2);
>>>  	u32 confoff = (irq / 16) * 4;
>>>  	bool enabled = false;
>>> -	u32 val;
>>> +	u32 val, oldval;
>>> +	int ret = 0;
>>>  
>>>  	/*
>>>  	 * Read current configuration register, and insert the config
>>>  	 * for "irq", depending on "type".
>>>  	 */
>>> -	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
>>> -	if (type == IRQ_TYPE_LEVEL_HIGH)
>>> +	val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
>>> +	if (type & IRQ_TYPE_LEVEL_MASK)
>>>  		val &= ~confmask;
>>> -	else if (type == IRQ_TYPE_EDGE_RISING)
>>> +	else if (type & IRQ_TYPE_EDGE_BOTH)
>>>  		val |= confmask;
>>>  
>>>  	/*
>>> @@ -54,15 +55,19 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
>>>  
>>>  	/*
>>>  	 * Write back the new configuration, and possibly re-enable
>>> -	 * the interrupt.
>>> +	 * the interrupt. If we tried to write a new configuration and failed,
>>> +	 * return an error.
>>>  	 */
>>>  	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
>>> -
>>> -	if (enabled)
>>> +	if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval)
>>> +		ret = -EINVAL;
>>> +	else if (enabled)
>>>  		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
>>
>> So if you change the configuration of an enabled interrupt and fail to
>> do so, you end-up with the interrupt disabled. This is a change in
>> behaviour, and is likely to introduce regressions.
> 
> Is it? Beforehand we were silently ignoring the fact that the new values haven't been
> set, now we return an error. Should we continue to ignore the fact that there is now
> a difference between what the kernel believes the setup is and what the hardware is
> configured to do?

Returning the error is fine. It is the fact that you've now disabled a
line that was previously enabled.I don't think that sort of side effect
is acceptable.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <marc.zyngier@arm.com>
To: Liviu Dudau <Liviu.Dudau@arm.com>
Cc: Russell King <linux@arm.linux.org.uk>,
	Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <Mark.Rutland@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>,
	Haojian Zhuang <haojian.zhuang@linaro.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	LAKML <linux-arm-kernel@lists.infradead.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3] irqchip: gic: Allow interrupt level to be set for PPIs.
Date: Mon, 12 Jan 2015 11:19:25 +0000	[thread overview]
Message-ID: <54B3ADBD.6050009@arm.com> (raw)
In-Reply-To: <20150112111509.GC823@e106497-lin.cambridge.arm.com>

Hi Liviu,

Welcome back! ;-)

On 12/01/15 11:15, Liviu Dudau wrote:
> On Mon, Jan 05, 2015 at 09:05:06AM +0000, Marc Zyngier wrote:
>> Hi Liviu,
> 
> Hi Marc,
> 
>>
>> On 01/12/14 12:45, Liviu Dudau wrote:
>>> During a recent cleanup of the arm64 DTs it has become clear that
>>> the handling of PPIs in xxxx_set_type() is incorrect. The ARM TRMs
>>> for GICv2 and later allow for "implementation defined" support for
>>> setting the edge or level type of the PPI interrupts and don't restrict
>>> the activation level of the signal. Current ARM implementations
>>> do restrict the PPI level type to IRQ_TYPE_LEVEL_LOW, but licensees
>>> of the IP can decide to shoot themselves in the foot at any time.
>>>
>>> Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
>>> ---
>>>
>>> Made a stupid mistake in v2 and got my bit test confused with logical test.
>>>
>>>  Documentation/devicetree/bindings/arm/gic.txt |  8 ++++++--
>>>  drivers/irqchip/irq-gic-common.c              | 21 +++++++++++++--------
>>>  drivers/irqchip/irq-gic-common.h              |  2 +-
>>>  drivers/irqchip/irq-gic-v3.c                  |  8 ++++----
>>>  drivers/irqchip/irq-gic.c                     |  9 ++++++---
>>>  drivers/irqchip/irq-hip04.c                   |  9 ++++++---
>>>  6 files changed, 36 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
>>> index 8112d0c..c97484b 100644
>>> --- a/Documentation/devicetree/bindings/arm/gic.txt
>>> +++ b/Documentation/devicetree/bindings/arm/gic.txt
>>> @@ -32,12 +32,16 @@ Main node required properties:
>>>    The 3rd cell is the flags, encoded as follows:
>>>  	bits[3:0] trigger type and level flags.
>>>  		1 = low-to-high edge triggered
>>> -		2 = high-to-low edge triggered
>>> +		2 = high-to-low edge triggered (invalid for SPIs)
>>>  		4 = active high level-sensitive
>>> -		8 = active low level-sensitive
>>> +		8 = active low level-sensitive (invalid for SPIs).
>>>  	bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of
>>>  	the 8 possible cpus attached to the GIC.  A bit set to '1' indicated
>>>  	the interrupt is wired to that CPU.  Only valid for PPI interrupts.
>>> +	Also note that the configurability of PPI interrupts is IMPLEMENTATION
>>> +	DEFINED and as such not guaranteed to be present (most SoC available
>>> +	in 2014 seem to ignore the setting of this flag and use the hardware
>>> +	default value).
>>>  
>>>  - reg : Specifies base physical address(s) and size of the GIC registers. The
>>>    first region is the GIC distributor register base and size. The 2nd region is
>>> diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
>>> index 61541ff..ffee521 100644
>>> --- a/drivers/irqchip/irq-gic-common.c
>>> +++ b/drivers/irqchip/irq-gic-common.c
>>> @@ -21,7 +21,7 @@
>>>  
>>>  #include "irq-gic-common.h"
>>>  
>>> -void gic_configure_irq(unsigned int irq, unsigned int type,
>>> +int gic_configure_irq(unsigned int irq, unsigned int type,
>>>  		       void __iomem *base, void (*sync_access)(void))
>>>  {
>>>  	u32 enablemask = 1 << (irq % 32);
>>> @@ -29,16 +29,17 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
>>>  	u32 confmask = 0x2 << ((irq % 16) * 2);
>>>  	u32 confoff = (irq / 16) * 4;
>>>  	bool enabled = false;
>>> -	u32 val;
>>> +	u32 val, oldval;
>>> +	int ret = 0;
>>>  
>>>  	/*
>>>  	 * Read current configuration register, and insert the config
>>>  	 * for "irq", depending on "type".
>>>  	 */
>>> -	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
>>> -	if (type == IRQ_TYPE_LEVEL_HIGH)
>>> +	val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
>>> +	if (type & IRQ_TYPE_LEVEL_MASK)
>>>  		val &= ~confmask;
>>> -	else if (type == IRQ_TYPE_EDGE_RISING)
>>> +	else if (type & IRQ_TYPE_EDGE_BOTH)
>>>  		val |= confmask;
>>>  
>>>  	/*
>>> @@ -54,15 +55,19 @@ void gic_configure_irq(unsigned int irq, unsigned int type,
>>>  
>>>  	/*
>>>  	 * Write back the new configuration, and possibly re-enable
>>> -	 * the interrupt.
>>> +	 * the interrupt. If we tried to write a new configuration and failed,
>>> +	 * return an error.
>>>  	 */
>>>  	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
>>> -
>>> -	if (enabled)
>>> +	if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval)
>>> +		ret = -EINVAL;
>>> +	else if (enabled)
>>>  		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
>>
>> So if you change the configuration of an enabled interrupt and fail to
>> do so, you end-up with the interrupt disabled. This is a change in
>> behaviour, and is likely to introduce regressions.
> 
> Is it? Beforehand we were silently ignoring the fact that the new values haven't been
> set, now we return an error. Should we continue to ignore the fact that there is now
> a difference between what the kernel believes the setup is and what the hardware is
> configured to do?

Returning the error is fine. It is the fact that you've now disabled a
line that was previously enabled.I don't think that sort of side effect
is acceptable.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

  reply	other threads:[~2015-01-12 11:19 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-01 12:45 [PATCH v3] irqchip: gic: Allow interrupt level to be set for PPIs Liviu Dudau
2014-12-01 12:45 ` Liviu Dudau
2014-12-01 12:45 ` Liviu Dudau
2014-12-09 12:29 ` Liviu Dudau
2014-12-09 12:29   ` Liviu Dudau
2014-12-09 12:29   ` Liviu Dudau
2015-01-05  1:36   ` Jason Cooper
2015-01-05  1:36     ` Jason Cooper
2015-01-05  1:36     ` Jason Cooper
2015-01-05  9:05 ` Marc Zyngier
2015-01-05  9:05   ` Marc Zyngier
2015-01-12 11:15   ` Liviu Dudau
2015-01-12 11:15     ` Liviu Dudau
2015-01-12 11:15     ` Liviu Dudau
2015-01-12 11:19     ` Marc Zyngier [this message]
2015-01-12 11:19       ` Marc Zyngier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54B3ADBD.6050009@arm.com \
    --to=marc.zyngier@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.