Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
- Original Message Follows - From: Michael Ellerman [EMAIL PROTECTED] To: [EMAIL PROTECTED] Cc: Paul Mackerras [EMAIL PROTECTED], linuxppc-dev@ozlabs.org, Segher Boessenkool [EMAIL PROTECTED] Subject: Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later Date: Wed, 06 Aug 2008 14:53:54 +1000 On Tue, 2008-08-05 at 20:55 -0600, miltonm wrote: - Original Message Follows - From: Michael Ellerman [EMAIL PROTECTED] To: Paul Mackerras [EMAIL PROTECTED] Cc: linuxppc-dev@ozlabs.org, Milton Miller [EMAIL PROTECTED], Segher Boessenkool [EMAIL PROTECTED] Subject: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later Date: Wed, 6 Aug 2008 12:03:37 +1000 (EST) I really dislike this great big if in the middle of a function. we called this function from two different call sites where the choice of which to call was based on their environment. Please move the call to eoi the hwirq to the callers, who know which path to take. It's not pretty, but the alternative is worse I think: Well, it needs a bit of refinement. From 0a908825c8de6cd4c26288aba8c5b7fe3ed0a69f Mon Sep 17 00:00:00 2001 From: Michael Ellerman [EMAIL PROTECTED] Date: Tue, 5 Aug 2008 22:34:48 +1000 Subject: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq, the console is non-functional because we're receiving no console interrupts. So when we receive a spurious irq mask it and then EOI it. Signed-off-by: Michael Ellerman [EMAIL PROTECTED] --- arch/powerpc/platforms/pseries/xics.c | 74 ++--- 1 files changed, 50 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..754706c 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -90,7 +90,7 @@ static inline unsigned int direct_xirr_info_get(void) { int cpu = smp_processor_id(); -return in_be32(xics_per_cpu[cpu]-xirr.word); +return in_be32(xics_per_cpu[cpu]-xirr.word) 0x00ff; } static inline void direct_xirr_info_set(int value) @@ -124,7 +124,8 @@ static inline unsigned int lpar_xirr_info_get(void) lpar_rc = plpar_xirr(return_value); if (lpar_rc != H_SUCCESS) panic( bad return code xirr - rc = %lx \n, lpar_rc); -return (unsigned int)return_value; + +return (unsigned int)return_value 0x00ff; } No, don't put the 0x00FF here. (1) this is not get_vector (2) we can take advantage of the full value Instead we need a macro to extract this out. The value returned is the value that is supposed to be used to EOI. The top byte is the old priority of the CPPR and the bottom 3 is the vector. xics has priority levels even though linux does not, and hence can allow limited nesting. we use that to allow only ipis to nest hardware irqs, but once we take an eoi we actually drop and let any new hwirq in. that's a seperate bug/hole. static inline void lpar_xirr_info_set(int value) @@ -321,49 +322,74 @@ static unsigned int xics_startup(unsigned int virq) return 0; } +static void xics_eoi_hwirq_direct(unsigned int hwirq) +{ +iosync(); +direct_xirr_info_set((0xff 24) | hwirq); +} + static void xics_eoi_direct(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; +xics_eoi_hwirq_direct((unsigned int)irq_map[virq].hwirq); +} +static void xics_eoi_hwirq_lpar(unsigned int hwirq) +{ iosync(); -direct_xirr_info_set((0xff 24) | irq); +lpar_xirr_info_set((0xff 24) | hwirq); } - static void xics_eoi_lpar(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; - -iosync(); -lpar_xirr_info_set((0xff 24) | irq); +xics_eoi_hwirq_lpar((unsigned int)irq_map[virq].hwirq); } so if we undo this part static inline unsigned int xics_remap_irq(unsigned int vec) { -unsigned int irq; - -vec = 0x00ff; - -if (vec == XICS_IRQ_SPURIOUS) -return NO_IRQ; -irq = irq_radix_revmap(xics_host, vec); -if (likely(irq != NO_IRQ)) -return irq; +return irq_radix_revmap(xics_host, vec); +} -printk(KERN_ERR Interrupt %u (real) is invalid, -disabling it.\n, vec); -xics_mask_real_irq(vec); -return NO_IRQ
[PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq later in boot, the console is non-functional because we're receiving no console interrupts. So when we receive a spurious irq, EOI it, and then mask it. Signed-off-by: Michael Ellerman [EMAIL PROTECTED] --- arch/powerpc/platforms/pseries/xics.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) Probably 27 material unless there are objections .. diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..dc007f4 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -321,21 +321,26 @@ static unsigned int xics_startup(unsigned int virq) return 0; } +static void xics_eoi_hwirq_direct(unsigned int hwirq) +{ + iosync(); + direct_xirr_info_set((0xff 24) | hwirq); +} + static void xics_eoi_direct(unsigned int virq) { - unsigned int irq = (unsigned int)irq_map[virq].hwirq; + xics_eoi_hwirq_direct((unsigned int)irq_map[virq].hwirq); +} +static void xics_eoi_hwirq_lpar(unsigned int hwirq) +{ iosync(); - direct_xirr_info_set((0xff 24) | irq); + lpar_xirr_info_set((0xff 24) | hwirq); } - static void xics_eoi_lpar(unsigned int virq) { - unsigned int irq = (unsigned int)irq_map[virq].hwirq; - - iosync(); - lpar_xirr_info_set((0xff 24) | irq); + xics_eoi_hwirq_lpar((unsigned int)irq_map[virq].hwirq); } static inline unsigned int xics_remap_irq(unsigned int vec) @@ -350,9 +355,15 @@ static inline unsigned int xics_remap_irq(unsigned int vec) if (likely(irq != NO_IRQ)) return irq; - printk(KERN_ERR Interrupt %u (real) is invalid, - disabling it.\n, vec); + pr_err(%s: no mapping for hwirq %u, disabling it.\n, __func__, vec); + + if (firmware_has_feature(FW_FEATURE_LPAR)) + xics_eoi_hwirq_lpar(vec); + else + xics_eoi_hwirq_direct(vec); + xics_mask_real_irq(vec); + return NO_IRQ; } -- 1.5.5 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
So when we receive a spurious irq, EOI it, and then mask it. What happens when a new IRQ arrives on the interrupt controller between these EOI and mask calls? Should you instead first mask it, and only then EOI it? Or doesn't that work on XICS? Segher ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
On Tue, 2008-08-05 at 18:48 +0200, Segher Boessenkool wrote: So when we receive a spurious irq, EOI it, and then mask it. What happens when a new IRQ arrives on the interrupt controller between these EOI and mask calls? Should you instead first mask it, and only then EOI it? Or doesn't that work on XICS? Yeah right, in which case we'd have not EOI'ed that one and we're back at square one. It seems to work with a mask then EOI, so unless Milton says otherwise I'll do it that way - new patch coming. cheers -- Michael Ellerman OzLabs, IBM Australia Development Lab wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person signature.asc Description: This is a digitally signed message part ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
[PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq, the console is non-functional because we're receiving no console interrupts. So when we receive a spurious irq mask it and then EOI it. Signed-off-by: Michael Ellerman [EMAIL PROTECTED] --- arch/powerpc/platforms/pseries/xics.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) Updated to mask then EOI, thanks to Segher for whacking me with the clue stick. diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..4c692b2 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -321,21 +321,26 @@ static unsigned int xics_startup(unsigned int virq) return 0; } +static void xics_eoi_hwirq_direct(unsigned int hwirq) +{ + iosync(); + direct_xirr_info_set((0xff 24) | hwirq); +} + static void xics_eoi_direct(unsigned int virq) { - unsigned int irq = (unsigned int)irq_map[virq].hwirq; + xics_eoi_hwirq_direct((unsigned int)irq_map[virq].hwirq); +} +static void xics_eoi_hwirq_lpar(unsigned int hwirq) +{ iosync(); - direct_xirr_info_set((0xff 24) | irq); + lpar_xirr_info_set((0xff 24) | hwirq); } - static void xics_eoi_lpar(unsigned int virq) { - unsigned int irq = (unsigned int)irq_map[virq].hwirq; - - iosync(); - lpar_xirr_info_set((0xff 24) | irq); + xics_eoi_hwirq_lpar((unsigned int)irq_map[virq].hwirq); } static inline unsigned int xics_remap_irq(unsigned int vec) @@ -350,9 +355,15 @@ static inline unsigned int xics_remap_irq(unsigned int vec) if (likely(irq != NO_IRQ)) return irq; - printk(KERN_ERR Interrupt %u (real) is invalid, - disabling it.\n, vec); + pr_err(%s: no mapping for hwirq %u, disabling it.\n, __func__, vec); + xics_mask_real_irq(vec); + + if (firmware_has_feature(FW_FEATURE_LPAR)) + xics_eoi_hwirq_lpar(vec); + else + xics_eoi_hwirq_direct(vec); + return NO_IRQ; } -- 1.5.5 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
- Original Message Follows - From: Michael Ellerman [EMAIL PROTECTED] To: Paul Mackerras [EMAIL PROTECTED] Cc: linuxppc-dev@ozlabs.org, Milton Miller [EMAIL PROTECTED], Segher Boessenkool [EMAIL PROTECTED] Subject: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later Date: Wed, 6 Aug 2008 12:03:37 +1000 (EST) In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq, the console is non-functional because we're receiving no console interrupts. which means some driver didn't disable interrupts on its shutdown, but I digress. So when we receive a spurious irq mask it and then EOI it. Signed-off-by: Michael Ellerman [EMAIL PROTECTED] --- arch/powerpc/platforms/pseries/xics.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) Updated to mask then EOI, thanks to Segher for whacking me with the clue stick. Actually, just sending the EOI would likely result in the exact same interrupt comming back, as the mask will set a bit near the source but the interrupt would have already been missed. (most irqs in xics systems are level). Thanks to segher for noticing the order. However... diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..4c692b2 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -321,21 +321,26 @@ static unsigned int xics_startup(unsigned int virq) return 0; } +static void xics_eoi_hwirq_direct(unsigned int hwirq) +{ +iosync(); +direct_xirr_info_set((0xff 24) | hwirq); +} + static void xics_eoi_direct(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; +xics_eoi_hwirq_direct((unsigned int)irq_map[virq].hwirq); +} +static void xics_eoi_hwirq_lpar(unsigned int hwirq) +{ iosync(); -direct_xirr_info_set((0xff 24) | irq); +lpar_xirr_info_set((0xff 24) | hwirq); } - static void xics_eoi_lpar(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; - -iosync(); -lpar_xirr_info_set((0xff 24) | irq); +xics_eoi_hwirq_lpar((unsigned int)irq_map[virq].hwirq); } static inline unsigned int xics_remap_irq(unsigned int vec) @@ -350,9 +355,15 @@ static inline unsigned int xics_remap_irq(unsigned int vec) if (likely(irq != NO_IRQ)) return irq; -printk(KERN_ERR Interrupt %u (real) is invalid, -disabling it.\n, vec); +pr_err(%s: no mapping for hwirq %u, disabling it.\n , __func__, vec); + xics_mask_real_irq(vec); + +if (firmware_has_feature(FW_FEATURE_LPAR)) +xics_eoi_hwirq_lpar(vec); +else +xics_eoi_hwirq_direct(vec); + return NO_IRQ; } I really dislike this great big if in the middle of a function. we called this function from two different call sites where the choice of which to call was based on their environment. Please move the call to eoi the hwirq to the callers, who know which path to take. I guess it might make sense to put the printk in a mask_invalid_real_irq wrapper, and then perhaps just duplicate the small remaining code? Or split the return of spurious from NO_IRQ (ie should spurious be NO_IRQ_IGNORE?) -- 1.5.5 ___ Linuxppc-dev mailing list Linuxppc-dev@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-dev
Re: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later
On Tue, 2008-08-05 at 20:55 -0600, miltonm wrote: - Original Message Follows - From: Michael Ellerman [EMAIL PROTECTED] To: Paul Mackerras [EMAIL PROTECTED] Cc: linuxppc-dev@ozlabs.org, Milton Miller [EMAIL PROTECTED], Segher Boessenkool [EMAIL PROTECTED] Subject: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later Date: Wed, 6 Aug 2008 12:03:37 +1000 (EST) In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq, the console is non-functional because we're receiving no console interrupts. which means some driver didn't disable interrupts on its shutdown, but I digress. But in the case of kdump the driver never gets a chance to shutdown its irq, but I digress too :) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..4c692b2 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -321,21 +321,26 @@ static unsigned int xics_startup(unsigned int virq) return 0; } +static void xics_eoi_hwirq_direct(unsigned int hwirq) +{ +iosync(); +direct_xirr_info_set((0xff 24) | hwirq); +} + static void xics_eoi_direct(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; +xics_eoi_hwirq_direct((unsigned int)irq_map[virq].hwirq); +} +static void xics_eoi_hwirq_lpar(unsigned int hwirq) +{ iosync(); -direct_xirr_info_set((0xff 24) | irq); +lpar_xirr_info_set((0xff 24) | hwirq); } - static void xics_eoi_lpar(unsigned int virq) { -unsigned int irq = (unsigned int)irq_map[virq].hwirq; - -iosync(); -lpar_xirr_info_set((0xff 24) | irq); +xics_eoi_hwirq_lpar((unsigned int)irq_map[virq].hwirq); } static inline unsigned int xics_remap_irq(unsigned int vec) @@ -350,9 +355,15 @@ static inline unsigned int xics_remap_irq(unsigned int vec) if (likely(irq != NO_IRQ)) return irq; -printk(KERN_ERR Interrupt %u (real) is invalid, -disabling it.\n, vec); +pr_err(%s: no mapping for hwirq %u, disabling it.\n , __func__, vec); + xics_mask_real_irq(vec); + +if (firmware_has_feature(FW_FEATURE_LPAR)) +xics_eoi_hwirq_lpar(vec); +else +xics_eoi_hwirq_direct(vec); + return NO_IRQ; } I really dislike this great big if in the middle of a function. we called this function from two different call sites where the choice of which to call was based on their environment. Please move the call to eoi the hwirq to the callers, who know which path to take. It's not pretty, but the alternative is worse I think: From 0a908825c8de6cd4c26288aba8c5b7fe3ed0a69f Mon Sep 17 00:00:00 2001 From: Michael Ellerman [EMAIL PROTECTED] Date: Tue, 5 Aug 2008 22:34:48 +1000 Subject: [PATCH] powerpc: EOI spurious irqs during boot so they can be reenabled later In the xics code, if we receive an irq during boot that hasn't been setup yet - ie. we have no reverse mapping for it - we mask the irq so we don't hear from it again. Later on if someone request_irq()'s that irq, we'll unmask it but it will still never fire. This is because we never EOI'ed the irq when we originally received it - when it was spurious. This can be reproduced trivially by banging the keyboard while kexec'ing on a P5 LPAR, even though the hvc_console driver request's the console irq, the console is non-functional because we're receiving no console interrupts. So when we receive a spurious irq mask it and then EOI it. Signed-off-by: Michael Ellerman [EMAIL PROTECTED] --- arch/powerpc/platforms/pseries/xics.c | 74 ++--- 1 files changed, 50 insertions(+), 24 deletions(-) diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 0fc830f..754706c 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -90,7 +90,7 @@ static inline unsigned int direct_xirr_info_get(void) { int cpu = smp_processor_id(); - return in_be32(xics_per_cpu[cpu]-xirr.word); + return in_be32(xics_per_cpu[cpu]-xirr.word) 0x00ff; } static inline void direct_xirr_info_set(int value) @@ -124,7 +124,8 @@ static inline unsigned int lpar_xirr_info_get(void) lpar_rc = plpar_xirr(return_value); if (lpar_rc != H_SUCCESS) panic( bad return code xirr - rc = %lx \n