Miscellaneous fixes and cleanup for uv rtc timers.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/kernel/irq.c | 10 +----
arch/x86/kernel/uv_time.c | 81 +++++++++++++++++++++++++++++-------------
2 files changed, 58 insertions(+), 33 deletions(-)
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-08 11:31:05.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-09 07:49:05.000000000 -0500
@@ -25,6 +25,7 @@
#include <asm/uv/bios.h>
#include <asm/uv/uv.h>
#include <asm/apic.h>
+#include <asm/idle.h>
#include <asm/cpu.h>
#define RTC_NAME "sgi_rtc"
@@ -75,6 +76,7 @@ struct uv_rtc_timer_head {
static struct uv_rtc_timer_head **blade_info __read_mostly;
static int uv_rtc_enable;
+static int uv_rtc_evt_enable;
/*
* Hardware interface routines
@@ -123,7 +125,10 @@ static int uv_setup_intr(int cpu, u64 ex
/* Initialize comparator value */
uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
- return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
+ if (uv_read_rtc(NULL) <= expires)
+ return 0;
+
+ return !uv_intr_pending(pnode);
}
/*
@@ -223,6 +228,7 @@ static int uv_rtc_set_timer(int cpu, u64
next_cpu = head->next_cpu;
*t = expires;
+
/* Will this one be next to go off? */
if (next_cpu < 0 || bcpu == next_cpu ||
expires < head->cpu[next_cpu].expires) {
@@ -231,7 +237,7 @@ static int uv_rtc_set_timer(int cpu, u64
*t = ULLONG_MAX;
uv_rtc_find_next_timer(head, pnode);
spin_unlock_irqrestore(&head->lock, flags);
- return 1;
+ return -ETIME;
}
}
@@ -244,7 +250,7 @@ static int uv_rtc_set_timer(int cpu, u64
*
* Returns 1 if this timer was pending.
*/
-static int uv_rtc_unset_timer(int cpu)
+static int uv_rtc_unset_timer(int cpu, int force)
{
int pnode = uv_cpu_to_pnode(cpu);
int bid = uv_cpu_to_blade_id(cpu);
@@ -256,14 +262,15 @@ static int uv_rtc_unset_timer(int cpu)
spin_lock_irqsave(&head->lock, flags);
- if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
+ if ((head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t) || force)
rc = 1;
- *t = ULLONG_MAX;
-
- /* Was the hardware setup for this timer? */
- if (head->next_cpu == bcpu)
- uv_rtc_find_next_timer(head, pnode);
+ if (rc) {
+ *t = ULLONG_MAX;
+ /* Was the hardware setup for this timer? */
+ if (head->next_cpu == bcpu)
+ uv_rtc_find_next_timer(head, pnode);
+ }
spin_unlock_irqrestore(&head->lock, flags);
@@ -310,7 +317,7 @@ static void uv_rtc_timer_setup(enum cloc
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
- uv_rtc_unset_timer(ced_cpu);
+ uv_rtc_unset_timer(ced_cpu, 1);
break;
}
}
@@ -320,13 +327,21 @@ static void uv_rtc_interrupt(void)
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
int cpu = smp_processor_id();
+ exit_idle();
+
+ irq_enter();
+
+ ack_APIC_irq();
+
if (!ced || !ced->event_handler)
- return;
+ goto out;
- if (uv_rtc_unset_timer(cpu) != 1)
- return;
+ if (uv_rtc_unset_timer(cpu, 0) != 1)
+ goto out;
ced->event_handler(ced);
+out:
+ irq_exit();
}
static int __init uv_enable_rtc(char *str)
@@ -337,6 +352,14 @@ static int __init uv_enable_rtc(char *st
}
__setup("uvrtc", uv_enable_rtc);
+static int __init uv_enable_evt_rtc(char *str)
+{
+ uv_rtc_evt_enable = 1;
+
+ return 1;
+}
+__setup("uvrtcevt", uv_enable_evt_rtc);
+
static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
{
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
@@ -353,24 +376,25 @@ static __init int uv_rtc_setup_clock(voi
if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
return -ENODEV;
- generic_interrupt_extension = uv_rtc_interrupt;
-
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
clocksource_uv.shift);
rc = clocksource_register(&clocksource_uv);
- if (rc) {
- generic_interrupt_extension = NULL;
+ if (rc)
+ printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
+ else
+ printk(KERN_INFO "UV RTC clocksource registered freq %lu MHz\n",
+ sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+ if (rc || !uv_rtc_evt_enable)
return rc;
- }
+
+ generic_interrupt_extension = uv_rtc_interrupt;
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
- if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
- return rc;
- }
+ if (rc)
+ goto error;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -383,10 +407,17 @@ static __init int uv_rtc_setup_clock(voi
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
uv_rtc_deallocate_timers();
+ goto error;
}
+ printk(KERN_INFO "UV RTC clockevents registered\n");
+
+ return 0;
+
+error:
+ generic_interrupt_extension = NULL;
+ clocksource_unregister(&clocksource_uv);
+ printk(KERN_INFO "UV RTC clockevents failed rc %d\n", rc);
return rc;
}
Index: linux/arch/x86/kernel/irq.c
===================================================================
--- linux.orig/arch/x86/kernel/irq.c 2009-10-08 11:31:05.000000000 -0500
+++ linux/arch/x86/kernel/irq.c 2009-10-08 11:31:15.000000000 -0500
@@ -257,18 +257,12 @@ void smp_generic_interrupt(struct pt_reg
{
struct pt_regs *old_regs = set_irq_regs(regs);
- ack_APIC_irq();
-
- exit_idle();
-
- irq_enter();
-
inc_irq_stat(generic_irqs);
if (generic_interrupt_extension)
generic_interrupt_extension();
-
- irq_exit();
+ else
+ ack_APIC_irq();
set_irq_regs(old_regs);
}
* Dimitri Sivanich <[email protected]> wrote:
> Miscellaneous fixes and cleanup for uv rtc timers.
>
> Signed-off-by: Dimitri Sivanich <[email protected]>
>
> ---
>
> arch/x86/kernel/irq.c | 10 +----
> arch/x86/kernel/uv_time.c | 81 +++++++++++++++++++++++++++++-------------
> 2 files changed, 58 insertions(+), 33 deletions(-)
>
> Index: linux/arch/x86/kernel/uv_time.c
> ===================================================================
> --- linux.orig/arch/x86/kernel/uv_time.c 2009-10-08 11:31:05.000000000 -0500
> +++ linux/arch/x86/kernel/uv_time.c 2009-10-09 07:49:05.000000000 -0500
> @@ -25,6 +25,7 @@
> #include <asm/uv/bios.h>
> #include <asm/uv/uv.h>
> #include <asm/apic.h>
> +#include <asm/idle.h>
> #include <asm/cpu.h>
>
> #define RTC_NAME "sgi_rtc"
> @@ -75,6 +76,7 @@ struct uv_rtc_timer_head {
> static struct uv_rtc_timer_head **blade_info __read_mostly;
>
> static int uv_rtc_enable;
> +static int uv_rtc_evt_enable;
>
> /*
> * Hardware interface routines
> @@ -123,7 +125,10 @@ static int uv_setup_intr(int cpu, u64 ex
> /* Initialize comparator value */
> uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
>
> - return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
> + if (uv_read_rtc(NULL) <= expires)
> + return 0;
> +
> + return !uv_intr_pending(pnode);
> }
>
> /*
> @@ -223,6 +228,7 @@ static int uv_rtc_set_timer(int cpu, u64
>
> next_cpu = head->next_cpu;
> *t = expires;
> +
> /* Will this one be next to go off? */
> if (next_cpu < 0 || bcpu == next_cpu ||
> expires < head->cpu[next_cpu].expires) {
> @@ -231,7 +237,7 @@ static int uv_rtc_set_timer(int cpu, u64
> *t = ULLONG_MAX;
> uv_rtc_find_next_timer(head, pnode);
> spin_unlock_irqrestore(&head->lock, flags);
> - return 1;
> + return -ETIME;
> }
> }
>
> @@ -244,7 +250,7 @@ static int uv_rtc_set_timer(int cpu, u64
> *
> * Returns 1 if this timer was pending.
> */
> -static int uv_rtc_unset_timer(int cpu)
> +static int uv_rtc_unset_timer(int cpu, int force)
> {
> int pnode = uv_cpu_to_pnode(cpu);
> int bid = uv_cpu_to_blade_id(cpu);
> @@ -256,14 +262,15 @@ static int uv_rtc_unset_timer(int cpu)
>
> spin_lock_irqsave(&head->lock, flags);
>
> - if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
> + if ((head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t) || force)
> rc = 1;
>
> - *t = ULLONG_MAX;
> -
> - /* Was the hardware setup for this timer? */
> - if (head->next_cpu == bcpu)
> - uv_rtc_find_next_timer(head, pnode);
> + if (rc) {
> + *t = ULLONG_MAX;
> + /* Was the hardware setup for this timer? */
> + if (head->next_cpu == bcpu)
> + uv_rtc_find_next_timer(head, pnode);
> + }
>
> spin_unlock_irqrestore(&head->lock, flags);
>
> @@ -310,7 +317,7 @@ static void uv_rtc_timer_setup(enum cloc
> break;
> case CLOCK_EVT_MODE_UNUSED:
> case CLOCK_EVT_MODE_SHUTDOWN:
> - uv_rtc_unset_timer(ced_cpu);
> + uv_rtc_unset_timer(ced_cpu, 1);
> break;
> }
> }
> @@ -320,13 +327,21 @@ static void uv_rtc_interrupt(void)
> struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
> int cpu = smp_processor_id();
>
> + exit_idle();
> +
> + irq_enter();
> +
> + ack_APIC_irq();
> +
> if (!ced || !ced->event_handler)
> - return;
> + goto out;
>
> - if (uv_rtc_unset_timer(cpu) != 1)
> - return;
> + if (uv_rtc_unset_timer(cpu, 0) != 1)
> + goto out;
>
> ced->event_handler(ced);
> +out:
> + irq_exit();
> }
>
> static int __init uv_enable_rtc(char *str)
> @@ -337,6 +352,14 @@ static int __init uv_enable_rtc(char *st
> }
> __setup("uvrtc", uv_enable_rtc);
>
> +static int __init uv_enable_evt_rtc(char *str)
> +{
> + uv_rtc_evt_enable = 1;
> +
> + return 1;
> +}
> +__setup("uvrtcevt", uv_enable_evt_rtc);
> +
> static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
> {
> struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
> @@ -353,24 +376,25 @@ static __init int uv_rtc_setup_clock(voi
> if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
> return -ENODEV;
>
> - generic_interrupt_extension = uv_rtc_interrupt;
> -
> clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
> clocksource_uv.shift);
>
> rc = clocksource_register(&clocksource_uv);
> - if (rc) {
> - generic_interrupt_extension = NULL;
> + if (rc)
> + printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
> + else
> + printk(KERN_INFO "UV RTC clocksource registered freq %lu MHz\n",
> + sn_rtc_cycles_per_second/(unsigned long)1E6);
> +
> + if (rc || !uv_rtc_evt_enable)
> return rc;
> - }
> +
> + generic_interrupt_extension = uv_rtc_interrupt;
>
> /* Setup and register clockevents */
> rc = uv_rtc_allocate_timers();
> - if (rc) {
> - clocksource_unregister(&clocksource_uv);
> - generic_interrupt_extension = NULL;
> - return rc;
> - }
> + if (rc)
> + goto error;
>
> clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
> NSEC_PER_SEC, clock_event_device_uv.shift);
> @@ -383,10 +407,17 @@ static __init int uv_rtc_setup_clock(voi
>
> rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
> if (rc) {
> - clocksource_unregister(&clocksource_uv);
> - generic_interrupt_extension = NULL;
> uv_rtc_deallocate_timers();
> + goto error;
> }
> + printk(KERN_INFO "UV RTC clockevents registered\n");
> +
> + return 0;
> +
> +error:
> + generic_interrupt_extension = NULL;
> + clocksource_unregister(&clocksource_uv);
> + printk(KERN_INFO "UV RTC clockevents failed rc %d\n", rc);
>
> return rc;
> }
> Index: linux/arch/x86/kernel/irq.c
> ===================================================================
> --- linux.orig/arch/x86/kernel/irq.c 2009-10-08 11:31:05.000000000 -0500
> +++ linux/arch/x86/kernel/irq.c 2009-10-08 11:31:15.000000000 -0500
> @@ -257,18 +257,12 @@ void smp_generic_interrupt(struct pt_reg
> {
> struct pt_regs *old_regs = set_irq_regs(regs);
>
> - ack_APIC_irq();
> -
> - exit_idle();
> -
> - irq_enter();
> -
> inc_irq_stat(generic_irqs);
>
> if (generic_interrupt_extension)
> generic_interrupt_extension();
> -
> - irq_exit();
> + else
> + ack_APIC_irq();
>
> set_irq_regs(old_regs);
> }
hm, why is the (unnecessary seeming) pushing of the
ack/exit_idle()/irq_enter()/irq_exit() sequence into the
generic_interrupt_extension() function a cleanup?
Also, the commit log is rather terse - what is being fixed and why isnt
it separate from any cleanups?
Ingo
On Mon, Oct 12, 2009 at 06:23:17PM +0200, Ingo Molnar wrote:
> hm, why is the (unnecessary seeming) pushing of the
> ack/exit_idle()/irq_enter()/irq_exit() sequence into the
> generic_interrupt_extension() function a cleanup?
It seems to make more sense to allow the users of generic_interrupt to
provide their own sequence, rather than being forced into this one.
>
> Also, the commit log is rather terse - what is being fixed and why isnt
> it separate from any cleanups?
>
I have added to the commit log. See below.
-------------------------------------------------------------------------------
Tune/fix early timer expiry handling and return correct early timeout value
for set_next_event.
Modify the irq_enter/ack_APIC_irq/irq_exit sequence and move it out of
smp_generic_interrupt to allow its users more flexibility.
Add clocksource only boot option.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/kernel/irq.c | 10 +----
arch/x86/kernel/uv_time.c | 81 +++++++++++++++++++++++++++++-------------
2 files changed, 58 insertions(+), 33 deletions(-)
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-08 11:31:05.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-09 07:49:05.000000000 -0500
@@ -25,6 +25,7 @@
#include <asm/uv/bios.h>
#include <asm/uv/uv.h>
#include <asm/apic.h>
+#include <asm/idle.h>
#include <asm/cpu.h>
#define RTC_NAME "sgi_rtc"
@@ -75,6 +76,7 @@ struct uv_rtc_timer_head {
static struct uv_rtc_timer_head **blade_info __read_mostly;
static int uv_rtc_enable;
+static int uv_rtc_evt_enable;
/*
* Hardware interface routines
@@ -123,7 +125,10 @@ static int uv_setup_intr(int cpu, u64 ex
/* Initialize comparator value */
uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
- return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
+ if (uv_read_rtc(NULL) <= expires)
+ return 0;
+
+ return !uv_intr_pending(pnode);
}
/*
@@ -223,6 +228,7 @@ static int uv_rtc_set_timer(int cpu, u64
next_cpu = head->next_cpu;
*t = expires;
+
/* Will this one be next to go off? */
if (next_cpu < 0 || bcpu == next_cpu ||
expires < head->cpu[next_cpu].expires) {
@@ -231,7 +237,7 @@ static int uv_rtc_set_timer(int cpu, u64
*t = ULLONG_MAX;
uv_rtc_find_next_timer(head, pnode);
spin_unlock_irqrestore(&head->lock, flags);
- return 1;
+ return -ETIME;
}
}
@@ -244,7 +250,7 @@ static int uv_rtc_set_timer(int cpu, u64
*
* Returns 1 if this timer was pending.
*/
-static int uv_rtc_unset_timer(int cpu)
+static int uv_rtc_unset_timer(int cpu, int force)
{
int pnode = uv_cpu_to_pnode(cpu);
int bid = uv_cpu_to_blade_id(cpu);
@@ -256,14 +262,15 @@ static int uv_rtc_unset_timer(int cpu)
spin_lock_irqsave(&head->lock, flags);
- if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
+ if ((head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t) || force)
rc = 1;
- *t = ULLONG_MAX;
-
- /* Was the hardware setup for this timer? */
- if (head->next_cpu == bcpu)
- uv_rtc_find_next_timer(head, pnode);
+ if (rc) {
+ *t = ULLONG_MAX;
+ /* Was the hardware setup for this timer? */
+ if (head->next_cpu == bcpu)
+ uv_rtc_find_next_timer(head, pnode);
+ }
spin_unlock_irqrestore(&head->lock, flags);
@@ -310,7 +317,7 @@ static void uv_rtc_timer_setup(enum cloc
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
- uv_rtc_unset_timer(ced_cpu);
+ uv_rtc_unset_timer(ced_cpu, 1);
break;
}
}
@@ -320,13 +327,21 @@ static void uv_rtc_interrupt(void)
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
int cpu = smp_processor_id();
+ exit_idle();
+
+ irq_enter();
+
+ ack_APIC_irq();
+
if (!ced || !ced->event_handler)
- return;
+ goto out;
- if (uv_rtc_unset_timer(cpu) != 1)
- return;
+ if (uv_rtc_unset_timer(cpu, 0) != 1)
+ goto out;
ced->event_handler(ced);
+out:
+ irq_exit();
}
static int __init uv_enable_rtc(char *str)
@@ -337,6 +352,14 @@ static int __init uv_enable_rtc(char *st
}
__setup("uvrtc", uv_enable_rtc);
+static int __init uv_enable_evt_rtc(char *str)
+{
+ uv_rtc_evt_enable = 1;
+
+ return 1;
+}
+__setup("uvrtcevt", uv_enable_evt_rtc);
+
static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
{
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
@@ -353,24 +376,25 @@ static __init int uv_rtc_setup_clock(voi
if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
return -ENODEV;
- generic_interrupt_extension = uv_rtc_interrupt;
-
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
clocksource_uv.shift);
rc = clocksource_register(&clocksource_uv);
- if (rc) {
- generic_interrupt_extension = NULL;
+ if (rc)
+ printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
+ else
+ printk(KERN_INFO "UV RTC clocksource registered freq %lu MHz\n",
+ sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+ if (rc || !uv_rtc_evt_enable)
return rc;
- }
+
+ generic_interrupt_extension = uv_rtc_interrupt;
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
- if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
- return rc;
- }
+ if (rc)
+ goto error;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -383,10 +407,17 @@ static __init int uv_rtc_setup_clock(voi
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
uv_rtc_deallocate_timers();
+ goto error;
}
+ printk(KERN_INFO "UV RTC clockevents registered\n");
+
+ return 0;
+
+error:
+ generic_interrupt_extension = NULL;
+ clocksource_unregister(&clocksource_uv);
+ printk(KERN_INFO "UV RTC clockevents failed rc %d\n", rc);
return rc;
}
Index: linux/arch/x86/kernel/irq.c
===================================================================
--- linux.orig/arch/x86/kernel/irq.c 2009-10-08 11:31:05.000000000 -0500
+++ linux/arch/x86/kernel/irq.c 2009-10-08 11:31:15.000000000 -0500
@@ -257,18 +257,12 @@ void smp_generic_interrupt(struct pt_reg
{
struct pt_regs *old_regs = set_irq_regs(regs);
- ack_APIC_irq();
-
- exit_idle();
-
- irq_enter();
-
inc_irq_stat(generic_irqs);
if (generic_interrupt_extension)
generic_interrupt_extension();
-
- irq_exit();
+ else
+ ack_APIC_irq();
set_irq_regs(old_regs);
}
* Dimitri Sivanich <[email protected]> wrote:
> On Mon, Oct 12, 2009 at 06:23:17PM +0200, Ingo Molnar wrote:
> > hm, why is the (unnecessary seeming) pushing of the
> > ack/exit_idle()/irq_enter()/irq_exit() sequence into the
> > generic_interrupt_extension() function a cleanup?
>
> It seems to make more sense to allow the users of generic_interrupt to
> provide their own sequence, rather than being forced into this one.
An IRQ handler is an irq handler. We should make it _more_ generic, not
less generic.
Also, the generic_interrupt_extension() name sucks a bit. Something like
x86_platform_ipi_callback() would be better.
> > Also, the commit log is rather terse - what is being fixed and why isnt
> > it separate from any cleanups?
>
> I have added to the commit log. See below.
Please separate out the fix and do the cleanups on top of that.
Thanks,
Ingo
The following patches provide fixes and cleanup to SGI UV RTC
clocksource/clockevents code.
Subject: [PATCH 1/4 v2] X86: UV RTC fix early expiry handling
Subject: [PATCH 2/4 v2] X86: UV RTC add clocksource only boot option
Subject: [PATCH 3/4 v2] X86: UV RTC cleanup error handling
Subject: [PATCH 4/4 v2] X86: UV RTC rename generic_interrupt
Tune/fix early timer expiry handling and return correct early timeout value
for set_next_event.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/kernel/uv_time.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-13 08:50:44.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-13 10:41:44.000000000 -0500
@@ -123,7 +123,10 @@ static int uv_setup_intr(int cpu, u64 ex
/* Initialize comparator value */
uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
- return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
+ if (uv_read_rtc(NULL) <= expires)
+ return 0;
+
+ return !uv_intr_pending(pnode);
}
/*
@@ -223,6 +226,7 @@ static int uv_rtc_set_timer(int cpu, u64
next_cpu = head->next_cpu;
*t = expires;
+
/* Will this one be next to go off? */
if (next_cpu < 0 || bcpu == next_cpu ||
expires < head->cpu[next_cpu].expires) {
@@ -231,7 +235,7 @@ static int uv_rtc_set_timer(int cpu, u64
*t = ULLONG_MAX;
uv_rtc_find_next_timer(head, pnode);
spin_unlock_irqrestore(&head->lock, flags);
- return 1;
+ return -ETIME;
}
}
@@ -244,7 +248,7 @@ static int uv_rtc_set_timer(int cpu, u64
*
* Returns 1 if this timer was pending.
*/
-static int uv_rtc_unset_timer(int cpu)
+static int uv_rtc_unset_timer(int cpu, int force)
{
int pnode = uv_cpu_to_pnode(cpu);
int bid = uv_cpu_to_blade_id(cpu);
@@ -256,14 +260,15 @@ static int uv_rtc_unset_timer(int cpu)
spin_lock_irqsave(&head->lock, flags);
- if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
+ if ((head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t) || force)
rc = 1;
- *t = ULLONG_MAX;
-
- /* Was the hardware setup for this timer? */
- if (head->next_cpu == bcpu)
- uv_rtc_find_next_timer(head, pnode);
+ if (rc) {
+ *t = ULLONG_MAX;
+ /* Was the hardware setup for this timer? */
+ if (head->next_cpu == bcpu)
+ uv_rtc_find_next_timer(head, pnode);
+ }
spin_unlock_irqrestore(&head->lock, flags);
@@ -310,20 +315,20 @@ static void uv_rtc_timer_setup(enum cloc
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
- uv_rtc_unset_timer(ced_cpu);
+ uv_rtc_unset_timer(ced_cpu, 1);
break;
}
}
static void uv_rtc_interrupt(void)
{
- struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
int cpu = smp_processor_id();
+ struct clock_event_device *ced = &per_cpu(cpu_ced, cpu);
if (!ced || !ced->event_handler)
return;
- if (uv_rtc_unset_timer(cpu) != 1)
+ if (uv_rtc_unset_timer(cpu, 0) != 1)
return;
ced->event_handler(ced);
Add clocksource only boot option for UV RTC.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/kernel/uv_time.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-13 08:50:46.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-13 08:55:23.000000000 -0500
@@ -75,6 +75,7 @@ struct uv_rtc_timer_head {
static struct uv_rtc_timer_head **blade_info __read_mostly;
static int uv_rtc_enable;
+static int uv_rtc_evt_enable;
/*
* Hardware interface routines
@@ -342,6 +343,14 @@ static int __init uv_enable_rtc(char *st
}
__setup("uvrtc", uv_enable_rtc);
+static int __init uv_enable_evt_rtc(char *str)
+{
+ uv_rtc_evt_enable = 1;
+
+ return 1;
+}
+__setup("uvrtcevt", uv_enable_evt_rtc);
+
static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
{
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
@@ -358,16 +367,20 @@ static __init int uv_rtc_setup_clock(voi
if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
return -ENODEV;
- generic_interrupt_extension = uv_rtc_interrupt;
-
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
clocksource_uv.shift);
rc = clocksource_register(&clocksource_uv);
- if (rc) {
- generic_interrupt_extension = NULL;
+ if (rc)
+ printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
+ else
+ printk(KERN_INFO "UV RTC clocksource registered freq %lu MHz\n",
+ sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+ if (rc || !uv_rtc_evt_enable)
return rc;
- }
+
+ generic_interrupt_extension = uv_rtc_interrupt;
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
Cleanup error handling in uv_rtc_setup_clock.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/kernel/uv_time.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-13 08:55:23.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-13 08:56:12.000000000 -0500
@@ -380,15 +380,12 @@ static __init int uv_rtc_setup_clock(voi
if (rc || !uv_rtc_evt_enable)
return rc;
- generic_interrupt_extension = uv_rtc_interrupt;
-
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
- if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
- return rc;
- }
+ if (rc)
+ goto error;
+
+ generic_interrupt_extension = uv_rtc_interrupt;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -401,11 +398,19 @@ static __init int uv_rtc_setup_clock(voi
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- clocksource_unregister(&clocksource_uv);
generic_interrupt_extension = NULL;
uv_rtc_deallocate_timers();
+ goto error;
}
+ printk(KERN_INFO "UV RTC clockevents registered\n");
+
+ return 0;
+
+error:
+ clocksource_unregister(&clocksource_uv);
+ printk(KERN_INFO "UV RTC clockevents failed rc %d\n", rc);
+
return rc;
}
arch_initcall(uv_rtc_setup_clock);
Rename generic_interrupt to x86_platform_ipi.
Signed-off-by: Dimitri Sivanich <[email protected]>
---
arch/x86/include/asm/entry_arch.h | 2 +-
arch/x86/include/asm/hardirq.h | 2 +-
arch/x86/include/asm/hw_irq.h | 4 ++--
arch/x86/include/asm/irq.h | 2 +-
arch/x86/include/asm/irq_vectors.h | 2 +-
arch/x86/kernel/entry_64.S | 4 ++--
arch/x86/kernel/irq.c | 20 ++++++++++----------
arch/x86/kernel/irqinit.c | 4 ++--
arch/x86/kernel/uv_time.c | 10 +++++-----
9 files changed, 25 insertions(+), 25 deletions(-)
Index: linux/arch/x86/include/asm/entry_arch.h
===================================================================
--- linux.orig/arch/x86/include/asm/entry_arch.h 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/include/asm/entry_arch.h 2009-10-13 08:57:41.000000000 -0500
@@ -34,7 +34,7 @@ BUILD_INTERRUPT3(invalidate_interrupt7,I
smp_invalidate_interrupt)
#endif
-BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR)
+BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR)
/*
* every pentium local APIC has two 'local interrupts', with a
Index: linux/arch/x86/include/asm/hardirq.h
===================================================================
--- linux.orig/arch/x86/include/asm/hardirq.h 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/include/asm/hardirq.h 2009-10-13 08:57:41.000000000 -0500
@@ -12,7 +12,7 @@ typedef struct {
unsigned int apic_timer_irqs; /* arch dependent */
unsigned int irq_spurious_count;
#endif
- unsigned int generic_irqs; /* arch dependent */
+ unsigned int x86_platform_ipis; /* arch dependent */
unsigned int apic_perf_irqs;
unsigned int apic_pending_irqs;
#ifdef CONFIG_SMP
Index: linux/arch/x86/include/asm/hw_irq.h
===================================================================
--- linux.orig/arch/x86/include/asm/hw_irq.h 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/include/asm/hw_irq.h 2009-10-13 09:03:39.000000000 -0500
@@ -27,7 +27,7 @@
/* Interrupt handlers registered during init_IRQ */
extern void apic_timer_interrupt(void);
-extern void generic_interrupt(void);
+extern void x86_platform_ipi(void);
extern void error_interrupt(void);
extern void perf_pending_interrupt(void);
@@ -101,7 +101,7 @@ extern void eisa_set_level_irq(unsigned
/* SMP */
extern void smp_apic_timer_interrupt(struct pt_regs *);
extern void smp_spurious_interrupt(struct pt_regs *);
-extern void smp_generic_interrupt(struct pt_regs *);
+extern void smp_x86_platform_ipi(struct pt_regs *);
extern void smp_error_interrupt(struct pt_regs *);
#ifdef CONFIG_X86_IO_APIC
extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
Index: linux/arch/x86/include/asm/irq_vectors.h
===================================================================
--- linux.orig/arch/x86/include/asm/irq_vectors.h 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/include/asm/irq_vectors.h 2009-10-13 08:57:41.000000000 -0500
@@ -106,7 +106,7 @@
/*
* Generic system vector for platform specific use
*/
-#define GENERIC_INTERRUPT_VECTOR 0xed
+#define X86_PLATFORM_IPI_VECTOR 0xed
/*
* Performance monitoring pending work vector:
Index: linux/arch/x86/kernel/entry_64.S
===================================================================
--- linux.orig/arch/x86/kernel/entry_64.S 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/kernel/entry_64.S 2009-10-13 09:04:04.000000000 -0500
@@ -969,8 +969,8 @@ apicinterrupt UV_BAU_MESSAGE \
#endif
apicinterrupt LOCAL_TIMER_VECTOR \
apic_timer_interrupt smp_apic_timer_interrupt
-apicinterrupt GENERIC_INTERRUPT_VECTOR \
- generic_interrupt smp_generic_interrupt
+apicinterrupt X86_PLATFORM_IPI_VECTOR \
+ x86_platform_ipi smp_x86_platform_ipi
#ifdef CONFIG_SMP
apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
Index: linux/arch/x86/kernel/irq.c
===================================================================
--- linux.orig/arch/x86/kernel/irq.c 2009-10-13 08:50:44.000000000 -0500
+++ linux/arch/x86/kernel/irq.c 2009-10-13 09:04:41.000000000 -0500
@@ -18,7 +18,7 @@
atomic_t irq_err_count;
/* Function pointer for generic interrupt vector handling */
-void (*generic_interrupt_extension)(void) = NULL;
+void (*x86_platform_ipi_callback)(void) = NULL;
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
@@ -72,10 +72,10 @@ static int show_other_interrupts(struct
seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
seq_printf(p, " Performance pending work\n");
#endif
- if (generic_interrupt_extension) {
+ if (x86_platform_ipi_callback) {
seq_printf(p, "%*s: ", prec, "PLT");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
+ seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis);
seq_printf(p, " Platform interrupts\n");
}
#ifdef CONFIG_SMP
@@ -187,8 +187,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += irq_stats(cpu)->apic_perf_irqs;
sum += irq_stats(cpu)->apic_pending_irqs;
#endif
- if (generic_interrupt_extension)
- sum += irq_stats(cpu)->generic_irqs;
+ if (x86_platform_ipi_callback)
+ sum += irq_stats(cpu)->x86_platform_ipis;
#ifdef CONFIG_SMP
sum += irq_stats(cpu)->irq_resched_count;
sum += irq_stats(cpu)->irq_call_count;
@@ -251,9 +251,9 @@ unsigned int __irq_entry do_IRQ(struct p
}
/*
- * Handler for GENERIC_INTERRUPT_VECTOR.
+ * Handler for X86_PLATFORM_IPI_VECTOR.
*/
-void smp_generic_interrupt(struct pt_regs *regs)
+void smp_x86_platform_ipi(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
@@ -263,10 +263,10 @@ void smp_generic_interrupt(struct pt_reg
irq_enter();
- inc_irq_stat(generic_irqs);
+ inc_irq_stat(x86_platform_ipis);
- if (generic_interrupt_extension)
- generic_interrupt_extension();
+ if (x86_platform_ipi_callback)
+ x86_platform_ipi_callback();
irq_exit();
Index: linux/arch/x86/kernel/irqinit.c
===================================================================
--- linux.orig/arch/x86/kernel/irqinit.c 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/kernel/irqinit.c 2009-10-13 08:57:41.000000000 -0500
@@ -200,8 +200,8 @@ static void __init apic_intr_init(void)
/* self generated IPI for local APIC timer */
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
- /* generic IPI for platform specific use */
- alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
+ /* IPI for X86 platform specific use */
+ alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi);
/* IPI vectors for APIC spurious and error interrupts */
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
Index: linux/arch/x86/kernel/uv_time.c
===================================================================
--- linux.orig/arch/x86/kernel/uv_time.c 2009-10-13 08:56:12.000000000 -0500
+++ linux/arch/x86/kernel/uv_time.c 2009-10-13 08:57:41.000000000 -0500
@@ -91,7 +91,7 @@ static void uv_rtc_send_IPI(int cpu)
pnode = uv_apicid_to_pnode(apicid);
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
(apicid << UVH_IPI_INT_APIC_ID_SHFT) |
- (GENERIC_INTERRUPT_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
+ (X86_PLATFORM_IPI_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}
@@ -116,7 +116,7 @@ static int uv_setup_intr(int cpu, u64 ex
uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED0_ALIAS,
UVH_EVENT_OCCURRED0_RTC1_MASK);
- val = (GENERIC_INTERRUPT_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
+ val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
((u64)cpu_physical_id(cpu) << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
/* Set configuration */
@@ -364,7 +364,7 @@ static __init int uv_rtc_setup_clock(voi
{
int rc;
- if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
+ if (!uv_rtc_enable || !is_uv_system() || x86_platform_ipi_callback)
return -ENODEV;
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
@@ -385,7 +385,7 @@ static __init int uv_rtc_setup_clock(voi
if (rc)
goto error;
- generic_interrupt_extension = uv_rtc_interrupt;
+ x86_platform_ipi_callback = uv_rtc_interrupt;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -398,7 +398,7 @@ static __init int uv_rtc_setup_clock(voi
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- generic_interrupt_extension = NULL;
+ x86_platform_ipi_callback = NULL;
uv_rtc_deallocate_timers();
goto error;
}
Index: linux/arch/x86/include/asm/irq.h
===================================================================
--- linux.orig/arch/x86/include/asm/irq.h 2009-10-13 08:50:43.000000000 -0500
+++ linux/arch/x86/include/asm/irq.h 2009-10-13 08:57:41.000000000 -0500
@@ -36,7 +36,7 @@ static inline int irq_canonicalize(int i
extern void fixup_irqs(void);
#endif
-extern void (*generic_interrupt_extension)(void);
+extern void (*x86_platform_ipi_callback)(void);
extern void native_init_IRQ(void);
extern bool handle_irq(unsigned irq, struct pt_regs *regs);
Commit-ID: e47938b1faaf9e9041ae842a878901001ce20ea1
Gitweb: http://git.kernel.org/tip/e47938b1faaf9e9041ae842a878901001ce20ea1
Author: Dimitri Sivanich <[email protected]>
AuthorDate: Wed, 14 Oct 2009 09:16:30 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 14 Oct 2009 18:27:09 +0200
x86: UV RTC: Fix early expiry handling
Tune/fix early timer expiry handling and return correct early timeout value
for set_next_event.
Signed-off-by: Dimitri Sivanich <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/uv_time.c | 29 +++++++++++++++++------------
1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index 583f11d..ec14889 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -123,7 +123,10 @@ static int uv_setup_intr(int cpu, u64 expires)
/* Initialize comparator value */
uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);
- return (expires < uv_read_rtc(NULL) && !uv_intr_pending(pnode));
+ if (uv_read_rtc(NULL) <= expires)
+ return 0;
+
+ return !uv_intr_pending(pnode);
}
/*
@@ -223,6 +226,7 @@ static int uv_rtc_set_timer(int cpu, u64 expires)
next_cpu = head->next_cpu;
*t = expires;
+
/* Will this one be next to go off? */
if (next_cpu < 0 || bcpu == next_cpu ||
expires < head->cpu[next_cpu].expires) {
@@ -231,7 +235,7 @@ static int uv_rtc_set_timer(int cpu, u64 expires)
*t = ULLONG_MAX;
uv_rtc_find_next_timer(head, pnode);
spin_unlock_irqrestore(&head->lock, flags);
- return 1;
+ return -ETIME;
}
}
@@ -244,7 +248,7 @@ static int uv_rtc_set_timer(int cpu, u64 expires)
*
* Returns 1 if this timer was pending.
*/
-static int uv_rtc_unset_timer(int cpu)
+static int uv_rtc_unset_timer(int cpu, int force)
{
int pnode = uv_cpu_to_pnode(cpu);
int bid = uv_cpu_to_blade_id(cpu);
@@ -256,14 +260,15 @@ static int uv_rtc_unset_timer(int cpu)
spin_lock_irqsave(&head->lock, flags);
- if (head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t)
+ if ((head->next_cpu == bcpu && uv_read_rtc(NULL) >= *t) || force)
rc = 1;
- *t = ULLONG_MAX;
-
- /* Was the hardware setup for this timer? */
- if (head->next_cpu == bcpu)
- uv_rtc_find_next_timer(head, pnode);
+ if (rc) {
+ *t = ULLONG_MAX;
+ /* Was the hardware setup for this timer? */
+ if (head->next_cpu == bcpu)
+ uv_rtc_find_next_timer(head, pnode);
+ }
spin_unlock_irqrestore(&head->lock, flags);
@@ -310,20 +315,20 @@ static void uv_rtc_timer_setup(enum clock_event_mode mode,
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
- uv_rtc_unset_timer(ced_cpu);
+ uv_rtc_unset_timer(ced_cpu, 1);
break;
}
}
static void uv_rtc_interrupt(void)
{
- struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
int cpu = smp_processor_id();
+ struct clock_event_device *ced = &per_cpu(cpu_ced, cpu);
if (!ced || !ced->event_handler)
return;
- if (uv_rtc_unset_timer(cpu) != 1)
+ if (uv_rtc_unset_timer(cpu, 0) != 1)
return;
ced->event_handler(ced);
Commit-ID: 8c28de4d011f37b2893ecfcec9a985c0e9bd786f
Gitweb: http://git.kernel.org/tip/8c28de4d011f37b2893ecfcec9a985c0e9bd786f
Author: Dimitri Sivanich <[email protected]>
AuthorDate: Wed, 14 Oct 2009 09:18:48 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 14 Oct 2009 18:27:10 +0200
x86: UV RTC: Add clocksource only boot option
Add clocksource only boot option for UV RTC.
Signed-off-by: Dimitri Sivanich <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/uv_time.c | 23 ++++++++++++++++++-----
1 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index ec14889..c6324ad 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -75,6 +75,7 @@ struct uv_rtc_timer_head {
static struct uv_rtc_timer_head **blade_info __read_mostly;
static int uv_rtc_enable;
+static int uv_rtc_evt_enable;
/*
* Hardware interface routines
@@ -342,6 +343,14 @@ static int __init uv_enable_rtc(char *str)
}
__setup("uvrtc", uv_enable_rtc);
+static int __init uv_enable_evt_rtc(char *str)
+{
+ uv_rtc_evt_enable = 1;
+
+ return 1;
+}
+__setup("uvrtcevt", uv_enable_evt_rtc);
+
static __init void uv_rtc_register_clockevents(struct work_struct *dummy)
{
struct clock_event_device *ced = &__get_cpu_var(cpu_ced);
@@ -358,16 +367,20 @@ static __init int uv_rtc_setup_clock(void)
if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
return -ENODEV;
- generic_interrupt_extension = uv_rtc_interrupt;
-
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
clocksource_uv.shift);
rc = clocksource_register(&clocksource_uv);
- if (rc) {
- generic_interrupt_extension = NULL;
+ if (rc)
+ printk(KERN_INFO "UV RTC clocksource failed rc %d\n", rc);
+ else
+ printk(KERN_INFO "UV RTC clocksource registered freq %lu MHz\n",
+ sn_rtc_cycles_per_second/(unsigned long)1E6);
+
+ if (rc || !uv_rtc_evt_enable)
return rc;
- }
+
+ generic_interrupt_extension = uv_rtc_interrupt;
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
Commit-ID: d5991ff297ad2f7e2698eefcd8269df5ecec150f
Gitweb: http://git.kernel.org/tip/d5991ff297ad2f7e2698eefcd8269df5ecec150f
Author: Dimitri Sivanich <[email protected]>
AuthorDate: Wed, 14 Oct 2009 09:21:03 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 14 Oct 2009 18:27:10 +0200
x86: UV RTC: Clean up error handling
Cleanup error handling in uv_rtc_setup_clock.
Signed-off-by: Dimitri Sivanich <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/uv_time.c | 21 +++++++++++++--------
1 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index c6324ad..2556450 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -380,15 +380,12 @@ static __init int uv_rtc_setup_clock(void)
if (rc || !uv_rtc_evt_enable)
return rc;
- generic_interrupt_extension = uv_rtc_interrupt;
-
/* Setup and register clockevents */
rc = uv_rtc_allocate_timers();
- if (rc) {
- clocksource_unregister(&clocksource_uv);
- generic_interrupt_extension = NULL;
- return rc;
- }
+ if (rc)
+ goto error;
+
+ generic_interrupt_extension = uv_rtc_interrupt;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -401,11 +398,19 @@ static __init int uv_rtc_setup_clock(void)
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- clocksource_unregister(&clocksource_uv);
generic_interrupt_extension = NULL;
uv_rtc_deallocate_timers();
+ goto error;
}
+ printk(KERN_INFO "UV RTC clockevents registered\n");
+
+ return 0;
+
+error:
+ clocksource_unregister(&clocksource_uv);
+ printk(KERN_INFO "UV RTC clockevents failed rc %d\n", rc);
+
return rc;
}
arch_initcall(uv_rtc_setup_clock);
Commit-ID: 4a4de9c7d7111ce4caf422b856756125d8304f9d
Gitweb: http://git.kernel.org/tip/4a4de9c7d7111ce4caf422b856756125d8304f9d
Author: Dimitri Sivanich <[email protected]>
AuthorDate: Wed, 14 Oct 2009 09:22:57 -0500
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 14 Oct 2009 18:27:11 +0200
x86: UV RTC: Rename generic_interrupt to x86_platform_ipi
Signed-off-by: Dimitri Sivanich <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/include/asm/entry_arch.h | 2 +-
arch/x86/include/asm/hardirq.h | 2 +-
arch/x86/include/asm/hw_irq.h | 4 ++--
arch/x86/include/asm/irq.h | 2 +-
arch/x86/include/asm/irq_vectors.h | 2 +-
arch/x86/kernel/entry_64.S | 4 ++--
arch/x86/kernel/irq.c | 20 ++++++++++----------
arch/x86/kernel/irqinit.c | 4 ++--
arch/x86/kernel/uv_time.c | 10 +++++-----
9 files changed, 25 insertions(+), 25 deletions(-)
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index f5693c8..8e8ec66 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -34,7 +34,7 @@ BUILD_INTERRUPT3(invalidate_interrupt7,INVALIDATE_TLB_VECTOR_START+7,
smp_invalidate_interrupt)
#endif
-BUILD_INTERRUPT(generic_interrupt, GENERIC_INTERRUPT_VECTOR)
+BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR)
/*
* every pentium local APIC has two 'local interrupts', with a
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 82e3e8f..beaabd7 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -12,7 +12,7 @@ typedef struct {
unsigned int apic_timer_irqs; /* arch dependent */
unsigned int irq_spurious_count;
#endif
- unsigned int generic_irqs; /* arch dependent */
+ unsigned int x86_platform_ipis; /* arch dependent */
unsigned int apic_perf_irqs;
unsigned int apic_pending_irqs;
#ifdef CONFIG_SMP
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index ba180d9..95207ca 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -27,7 +27,7 @@
/* Interrupt handlers registered during init_IRQ */
extern void apic_timer_interrupt(void);
-extern void generic_interrupt(void);
+extern void x86_platform_ipi(void);
extern void error_interrupt(void);
extern void perf_pending_interrupt(void);
@@ -101,7 +101,7 @@ extern void eisa_set_level_irq(unsigned int irq);
/* SMP */
extern void smp_apic_timer_interrupt(struct pt_regs *);
extern void smp_spurious_interrupt(struct pt_regs *);
-extern void smp_generic_interrupt(struct pt_regs *);
+extern void smp_x86_platform_ipi(struct pt_regs *);
extern void smp_error_interrupt(struct pt_regs *);
#ifdef CONFIG_X86_IO_APIC
extern asmlinkage void smp_irq_move_cleanup_interrupt(void);
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index ddda6cb..fcbc6d1 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -36,7 +36,7 @@ static inline int irq_canonicalize(int irq)
extern void fixup_irqs(void);
#endif
-extern void (*generic_interrupt_extension)(void);
+extern void (*x86_platform_ipi_callback)(void);
extern void native_init_IRQ(void);
extern bool handle_irq(unsigned irq, struct pt_regs *regs);
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 5b21f0e..6a635bd 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -106,7 +106,7 @@
/*
* Generic system vector for platform specific use
*/
-#define GENERIC_INTERRUPT_VECTOR 0xed
+#define X86_PLATFORM_IPI_VECTOR 0xed
/*
* Performance monitoring pending work vector:
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b5c061f..6714432 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -969,8 +969,8 @@ apicinterrupt UV_BAU_MESSAGE \
#endif
apicinterrupt LOCAL_TIMER_VECTOR \
apic_timer_interrupt smp_apic_timer_interrupt
-apicinterrupt GENERIC_INTERRUPT_VECTOR \
- generic_interrupt smp_generic_interrupt
+apicinterrupt X86_PLATFORM_IPI_VECTOR \
+ x86_platform_ipi smp_x86_platform_ipi
#ifdef CONFIG_SMP
apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 3912061..9375dce 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -18,7 +18,7 @@
atomic_t irq_err_count;
/* Function pointer for generic interrupt vector handling */
-void (*generic_interrupt_extension)(void) = NULL;
+void (*x86_platform_ipi_callback)(void) = NULL;
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
@@ -72,10 +72,10 @@ static int show_other_interrupts(struct seq_file *p, int prec)
seq_printf(p, "%10u ", irq_stats(j)->apic_pending_irqs);
seq_printf(p, " Performance pending work\n");
#endif
- if (generic_interrupt_extension) {
+ if (x86_platform_ipi_callback) {
seq_printf(p, "%*s: ", prec, "PLT");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", irq_stats(j)->generic_irqs);
+ seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis);
seq_printf(p, " Platform interrupts\n");
}
#ifdef CONFIG_SMP
@@ -187,8 +187,8 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
sum += irq_stats(cpu)->apic_perf_irqs;
sum += irq_stats(cpu)->apic_pending_irqs;
#endif
- if (generic_interrupt_extension)
- sum += irq_stats(cpu)->generic_irqs;
+ if (x86_platform_ipi_callback)
+ sum += irq_stats(cpu)->x86_platform_ipis;
#ifdef CONFIG_SMP
sum += irq_stats(cpu)->irq_resched_count;
sum += irq_stats(cpu)->irq_call_count;
@@ -252,9 +252,9 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
}
/*
- * Handler for GENERIC_INTERRUPT_VECTOR.
+ * Handler for X86_PLATFORM_IPI_VECTOR.
*/
-void smp_generic_interrupt(struct pt_regs *regs)
+void smp_x86_platform_ipi(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
@@ -264,10 +264,10 @@ void smp_generic_interrupt(struct pt_regs *regs)
irq_enter();
- inc_irq_stat(generic_irqs);
+ inc_irq_stat(x86_platform_ipis);
- if (generic_interrupt_extension)
- generic_interrupt_extension();
+ if (x86_platform_ipi_callback)
+ x86_platform_ipi_callback();
run_local_timers();
irq_exit();
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 40f3077..d593222 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -200,8 +200,8 @@ static void __init apic_intr_init(void)
/* self generated IPI for local APIC timer */
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
- /* generic IPI for platform specific use */
- alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
+ /* IPI for X86 platform specific use */
+ alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi);
/* IPI vectors for APIC spurious and error interrupts */
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
diff --git a/arch/x86/kernel/uv_time.c b/arch/x86/kernel/uv_time.c
index 2556450..3da7b1d 100644
--- a/arch/x86/kernel/uv_time.c
+++ b/arch/x86/kernel/uv_time.c
@@ -91,7 +91,7 @@ static void uv_rtc_send_IPI(int cpu)
pnode = uv_apicid_to_pnode(apicid);
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
(apicid << UVH_IPI_INT_APIC_ID_SHFT) |
- (GENERIC_INTERRUPT_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
+ (X86_PLATFORM_IPI_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}
@@ -116,7 +116,7 @@ static int uv_setup_intr(int cpu, u64 expires)
uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED0_ALIAS,
UVH_EVENT_OCCURRED0_RTC1_MASK);
- val = (GENERIC_INTERRUPT_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
+ val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
((u64)cpu_physical_id(cpu) << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
/* Set configuration */
@@ -364,7 +364,7 @@ static __init int uv_rtc_setup_clock(void)
{
int rc;
- if (!uv_rtc_enable || !is_uv_system() || generic_interrupt_extension)
+ if (!uv_rtc_enable || !is_uv_system() || x86_platform_ipi_callback)
return -ENODEV;
clocksource_uv.mult = clocksource_hz2mult(sn_rtc_cycles_per_second,
@@ -385,7 +385,7 @@ static __init int uv_rtc_setup_clock(void)
if (rc)
goto error;
- generic_interrupt_extension = uv_rtc_interrupt;
+ x86_platform_ipi_callback = uv_rtc_interrupt;
clock_event_device_uv.mult = div_sc(sn_rtc_cycles_per_second,
NSEC_PER_SEC, clock_event_device_uv.shift);
@@ -398,7 +398,7 @@ static __init int uv_rtc_setup_clock(void)
rc = schedule_on_each_cpu(uv_rtc_register_clockevents);
if (rc) {
- generic_interrupt_extension = NULL;
+ x86_platform_ipi_callback = NULL;
uv_rtc_deallocate_timers();
goto error;
}