From: marek.vasut@gmail.com (Marek Vasut)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 08/11] ARM: pxa: sanitize IRQ registers access based on offset
Date: Sun, 9 Jan 2011 23:49:19 +0100 [thread overview]
Message-ID: <201101092349.19374.marek.vasut@gmail.com> (raw)
In-Reply-To: <1289546260-6208-8-git-send-email-haojian.zhuang@marvell.com>
On Friday 12 November 2010 08:17:37 Haojian Zhuang wrote:
> Signed-off-by: Eric Miao <eric.y.miao@gmail.com>
> Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
I think there's something wrong with this patch. It crashes my ZipitZ2 (no crash
with this patch reverted). I'll investigate a bit and keep you informed, but see
below.
> ---
> arch/arm/mach-pxa/include/mach/regs-intc.h | 4 -
> arch/arm/mach-pxa/irq.c | 122
> ++++++++++++++++++---------- 2 files changed, 80 insertions(+), 46
> deletions(-)
>
> diff --git a/arch/arm/mach-pxa/include/mach/regs-intc.h
> b/arch/arm/mach-pxa/include/mach/regs-intc.h index 68464ce..662288e 100644
> --- a/arch/arm/mach-pxa/include/mach/regs-intc.h
> +++ b/arch/arm/mach-pxa/include/mach/regs-intc.h
> @@ -27,8 +27,4 @@
> #define ICFP3 __REG(0x40D0013C) /* Interrupt Controller FIQ Pending
> Register 3 */ #define ICPR3 __REG(0x40D00140) /* Interrupt Controller
> Pending Register 3 */
>
> -#define IPR(x) __REG(0x40D0001C + (x < 32 ? (x << 2) \
> - : (x < 64 ? (0x94 + ((x - 32) << 2)) \
> - : (0x128 + ((x - 64) << 2)))))
> -
> #endif /* __ASM_MACH_REGS_INTC_H */
> diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
> index b5cafe2..54e91c9 100644
> --- a/arch/arm/mach-pxa/irq.c
> +++ b/arch/arm/mach-pxa/irq.c
> @@ -16,20 +16,31 @@
> #include <linux/module.h>
> #include <linux/interrupt.h>
> #include <linux/sysdev.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
>
> #include <mach/hardware.h>
> -#include <asm/irq.h>
> -#include <asm/mach/irq.h>
> +#include <mach/irqs.h>
> #include <mach/gpio.h>
> -#include <mach/regs-intc.h>
>
> #include "generic.h"
>
> -#define MAX_INTERNAL_IRQS 128
> +#define IRQ_BASE (void __iomem *)io_p2v(0x40d00000)
> +
> +#define ICIP (0x000)
> +#define ICMR (0x004)
> +#define ICLR (0x008)
> +#define ICFR (0x00c)
> +#define ICPR (0x010)
> +#define ICCR (0x014)
> +#define ICHP (0x018)
> +#define IPR(i) (((i) < 32) ? (0x01c + ((i) << 2)) : \
> + ((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) : \
> + (0x144 + (((i) - 64) << 2)))
> +#define IPR_VALID (1 << 31)
> +#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
>
> -#define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f)
> -#define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR))
> -#define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR))
> +#define MAX_INTERNAL_IRQS 128
>
> /*
> * This is for peripheral IRQs internal to the PXA chip.
> @@ -44,12 +55,20 @@ static inline int cpu_has_ipr(void)
>
> static void pxa_mask_irq(unsigned int irq)
> {
> - _ICMR(irq) &= ~(1 << IRQ_BIT(irq));
> + void __iomem *base = get_irq_chip_data(irq);
> + uint32_t icmr = __raw_readl(base + ICMR);
> +
> + icmr &= ~(1 << IRQ_BIT(irq));
> + __raw_writel(icmr, base + ICMR);
> }
>
> static void pxa_unmask_irq(unsigned int irq)
> {
> - _ICMR(irq) |= 1 << IRQ_BIT(irq);
> + void __iomem *base = get_irq_chip_data(irq);
> + uint32_t icmr = __raw_readl(base + ICMR);
> +
> + icmr |= 1 << IRQ_BIT(irq);
> + __raw_writel(icmr, base + ICMR);
> }
>
> static struct irq_chip pxa_internal_irq_chip = {
> @@ -91,12 +110,16 @@ static void pxa_ack_low_gpio(unsigned int irq)
>
> static void pxa_mask_low_gpio(unsigned int irq)
> {
> - ICMR &= ~(1 << (irq - PXA_IRQ(0)));
> + struct irq_desc *desc = irq_to_desc(irq);
> +
> + desc->chip->mask(irq);
> }
>
> static void pxa_unmask_low_gpio(unsigned int irq)
> {
> - ICMR |= 1 << (irq - PXA_IRQ(0));
> + struct irq_desc *desc = irq_to_desc(irq);
> +
> + desc->chip->unmask(irq);
> }
>
> static struct irq_chip pxa_low_gpio_chip = {
> @@ -125,33 +148,45 @@ static void __init pxa_init_low_gpio_irq(set_wake_t
> fn) pxa_low_gpio_chip.set_wake = fn;
> }
>
> +static inline void __iomem *irq_base(int i)
> +{
> + static unsigned long phys_base[] = {
> + 0x40d00000,
> + 0x40d0009c,
> + 0x40d00130,
> + };
> +
> + return (void __iomem *)io_p2v(phys_base[i >> 5]);
> +}
> +
> void __init pxa_init_irq(int irq_nr, set_wake_t fn)
> {
> - int irq, i;
> + int irq, i, n;
>
> BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
>
> pxa_internal_irq_nr = irq_nr;
>
> - for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) {
> - _ICMR(irq) = 0; /* disable all IRQs */
> - _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */
> - }
> -
> - /* initialize interrupt priority */
> - if (cpu_has_ipr()) {
> - for (i = 0; i < irq_nr; i++)
> - IPR(i) = i | (1 << 31);
> + for (n = 0; n < irq_nr; n += 32) {
> + void __iomem *base = irq_base(n);
> +
> + __raw_writel(0, base + ICMR); /* disable all IRQs */
> + __raw_writel(0, base + ICLR); /* all IRQs are IRQ, not FIQ */
> + for (i = n; (i < (n + 32)) && (i < irq_nr); i++) {
> + /* initialize interrupt priority */
> + if (cpu_has_ipr())
> + __raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
> +
> + irq = PXA_IRQ(i);
> + set_irq_chip(irq, &pxa_internal_irq_chip);
> + set_irq_chip_data(irq, base);
> + set_irq_handler(irq, handle_level_irq);
> + set_irq_flags(irq, IRQF_VALID);
> + }
> }
>
> /* only unmasked interrupts kick us out of idle */
> - ICCR = 1;
> -
> - for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) {
> - set_irq_chip(irq, &pxa_internal_irq_chip);
> - set_irq_handler(irq, handle_level_irq);
> - set_irq_flags(irq, IRQF_VALID);
> - }
> + __raw_writel(1, irq_base(0) + ICCR);
>
> pxa_internal_irq_chip.set_wake = fn;
> pxa_init_low_gpio_irq(fn);
> @@ -163,16 +198,18 @@ static unsigned long saved_ipr[MAX_INTERNAL_IRQS];
>
> static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
> {
> - int i, irq = PXA_IRQ(0);
> + int i;
> +
> + for (i = 0; i < pxa_internal_irq_nr; i += 32) {
> + void __iomem *base = irq_base(i);
>
> - for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
> - saved_icmr[i] = _ICMR(irq);
> - _ICMR(irq) = 0;
> + saved_icmr[i] = __raw_readl(base + ICMR);
> + __raw_writel(0, base + ICMR);
> }
>
> if (cpu_has_ipr()) {
> for (i = 0; i < pxa_internal_irq_nr; i++)
> - saved_ipr[i] = IPR(i);
> + saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i));
> }
>
> return 0;
> @@ -180,19 +217,20 @@ static int pxa_irq_suspend(struct sys_device *dev,
> pm_message_t state)
>
> static int pxa_irq_resume(struct sys_device *dev)
> {
> - int i, irq = PXA_IRQ(0);
> + int i;
>
> - if (cpu_has_ipr()) {
> - for (i = 0; i < pxa_internal_irq_nr; i++)
> - IPR(i) = saved_ipr[i];
> - }
> + for (i = 0; i < pxa_internal_irq_nr; i += 32) {
> + void __iomem *base = irq_base(i);
>
> - for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) {
> - _ICMR(irq) = saved_icmr[i];
> - _ICLR(irq) = 0;
> + __raw_writel(saved_icmr[i], base + ICMR);
eg. here, it just so does out-of-bounds access (saved_icmr[32] is wrong).
> + __raw_writel(0, base + ICLR);
> }
>
> - ICCR = 1;
> + if (!cpu_is_pxa25x())
> + for (i = 0; i < pxa_internal_irq_nr; i++)
> + __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
> +
> + __raw_writel(1, IRQ_BASE + ICCR);
> return 0;
> }
> #else
next prev parent reply other threads:[~2011-01-09 22:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-12 7:17 [PATCH 01/11] ARM: pxa: redefine the cpu_is_pxa3xx Haojian Zhuang
2010-11-12 7:17 ` [PATCH 02/11] ARM: pxa: redefine irqs.h Haojian Zhuang
2010-11-12 7:17 ` [PATCH 03/11] ARM: pxa: split pxa93x from pxa3xx Haojian Zhuang
2010-11-12 7:17 ` [PATCH 04/11] ARM: pxa: update to read ICHP Haojian Zhuang
2010-11-12 7:17 ` [PATCH 05/11] ARM: pxa: support pxa95x Haojian Zhuang
2010-11-12 7:17 ` [PATCH 06/11] ARM: pxa: support saarb platform Haojian Zhuang
2010-11-12 7:17 ` [PATCH 07/11] ARM: mmp: select CPU_PJ4 Haojian Zhuang
2010-11-12 7:17 ` [PATCH 08/11] ARM: pxa: sanitize IRQ registers access based on offset Haojian Zhuang
2010-11-12 7:17 ` [PATCH 09/11] ARM: pxa: auto compute shift and mult of timer Haojian Zhuang
2010-11-12 7:17 ` [PATCH 10/11] ARM: pxa: add 32KHz timer as clock source Haojian Zhuang
2010-11-12 7:17 ` [PATCH 11/11] ARM: pxa: add iwmmx support for PJ4 Haojian Zhuang
2010-11-12 18:43 ` Nicolas Pitre
2010-11-12 17:50 ` [PATCH 10/11] ARM: pxa: add 32KHz timer as clock source Nicolas Pitre
2010-11-16 5:07 ` Haojian Zhuang
2011-01-09 22:49 ` Marek Vasut [this message]
2010-11-12 8:50 ` [PATCH 05/11] ARM: pxa: support pxa95x Haojian Zhuang
2010-11-12 8:34 ` [PATCH 04/11] ARM: pxa: update to read ICHP Eric Miao
2010-11-12 8:53 ` Haojian Zhuang
2010-11-12 8:07 ` [PATCH 03/11] ARM: pxa: split pxa93x from pxa3xx Eric Miao
2010-11-12 8:47 ` Haojian Zhuang
2010-11-12 8:02 ` [PATCH 02/11] ARM: pxa: redefine irqs.h Eric Miao
2010-11-12 8:00 ` [PATCH 01/11] ARM: pxa: redefine the cpu_is_pxa3xx Eric Miao
2010-11-16 14:24 ` Eric Miao
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=201101092349.19374.marek.vasut@gmail.com \
--to=marek.vasut@gmail.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.