- i386-apic-timer-use-clockevents-broadcast.patch removed from -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     i386: Use the clockevents broadcast functionality
has been removed from the -mm tree.  Its filename was
     i386-apic-timer-use-clockevents-broadcast.patch

This patch was dropped because an updated version will be merged

------------------------------------------------------
Subject: i386: Use the clockevents broadcast functionality


Replace the existing broadcast implementation and use the clockevents
based broadcasting mechanism

Signed-of-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>

Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
---

 arch/i386/Kconfig             |    4 
 arch/i386/kernel/apic.c       |  184 +++++++++++---------------------
 arch/i386/kernel/smpboot.c    |    5 
 arch/i386/kernel/time.c       |    5 
 drivers/acpi/processor_idle.c |   20 +++
 include/asm-i386/apic.h       |    5 
 include/asm-i386/mpspec.h     |    1 
 7 files changed, 91 insertions(+), 133 deletions(-)

diff -puN arch/i386/Kconfig~i386-apic-timer-use-clockevents-broadcast arch/i386/Kconfig
--- a/arch/i386/Kconfig~i386-apic-timer-use-clockevents-broadcast
+++ a/arch/i386/Kconfig
@@ -22,6 +22,10 @@ config GENERIC_CLOCKEVENTS
 	bool
 	default y
 
+config GENERIC_CLOCKEVENTS_BROADCAST
+	bool
+	default y
+
 config LOCKDEP_SUPPORT
 	bool
 	default y
diff -puN arch/i386/kernel/apic.c~i386-apic-timer-use-clockevents-broadcast arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c~i386-apic-timer-use-clockevents-broadcast
+++ a/arch/i386/kernel/apic.c
@@ -53,12 +53,6 @@
 #endif
 
 /*
- * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
- * IPIs in place of local APIC timers
- */
-static cpumask_t timer_bcast_ipi;
-
-/*
  * Knob to control our willingness to enable the local APIC.
  *
  * -1=force-disable, +1=force-enable
@@ -76,6 +70,7 @@ static void lapic_next_event(unsigned lo
 			     struct clock_event_device *evt);
 static void lapic_timer_setup(enum clock_event_mode mode,
 			      struct clock_event_device *evt);
+static void lapic_timer_broadcast(cpumask_t *mask);
 static void apic_pm_activate(void);
 
 /*
@@ -99,9 +94,6 @@ static struct clock_event_device lapic_c
 };
 static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
 
-/* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer __read_mostly = 0;
-
 /* Local APIC was disabled by the BIOS and enabled by the kernel */
 static int enabled_via_apicbase;
 
@@ -185,7 +177,6 @@ int lapic_get_maxlvt(void)
 static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
 {
 	unsigned int lvtt_value, tmp_value;
-	int cpu = smp_processor_id();
 
 	lvtt_value = LOCAL_TIMER_VECTOR;
 	if (!oneshot)
@@ -225,12 +216,24 @@ static void lapic_next_event(unsigned lo
 static void lapic_timer_setup(enum clock_event_mode mode,
 			      struct clock_event_device *evt)
 {
-	int cpu = smp_processor_id();
 	unsigned long flags;
+	unsigned int v;
 
 	local_irq_save(flags);
-	__setup_APIC_LVTT(calibration_result, mode != CLOCK_EVT_PERIODIC,
-			  cpu_isset(cpu, timer_bcast_ipi));
+
+	switch (mode) {
+	case CLOCK_EVT_PERIODIC:
+	case CLOCK_EVT_ONESHOT:
+		__setup_APIC_LVTT(calibration_result,
+				  mode != CLOCK_EVT_PERIODIC, 1);
+		break;
+	case CLOCK_EVT_SHUTDOWN:
+		v = apic_read(APIC_LVTT);
+		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+		apic_write_around(APIC_LVTT, v);
+		break;
+	}
+
 	local_irq_restore(flags);
 }
 
@@ -324,7 +327,9 @@ void __init setup_boot_APIC_clock(void)
 
 	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
 		    "calibrating APIC timer ...\n");
-	using_apic_timer = 1;
+
+	/* Register broadcast function */
+	clockevents_register_broadcast(lapic_timer_broadcast);
 
 	local_irq_disable();
 
@@ -484,96 +489,42 @@ void __devinit setup_secondary_APIC_cloc
 	setup_APIC_timer();
 }
 
-void disable_APIC_timer(void)
-{
-	if (using_apic_timer) {
-		unsigned long v;
-
-		v = apic_read(APIC_LVTT);
-		/*
-		 * When an illegal vector value (0-15) is written to an LVT
-		 * entry and delivery mode is Fixed, the APIC may signal an
-		 * illegal vector error, with out regard to whether the mask
-		 * bit is set or whether an interrupt is actually seen on
-		 * input.
-		 *
-		 * Boot sequence might call this function when the LVTT has
-		 * '0' vector value. So make sure vector field is set to
-		 * valid value.
-		 */
-		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
-		apic_write_around(APIC_LVTT, v);
-	}
-}
-
-void enable_APIC_timer(void)
-{
-	int cpu = smp_processor_id();
-
-	if (using_apic_timer && !cpu_isset(cpu, timer_bcast_ipi)) {
-		unsigned long v;
-
-		v = apic_read(APIC_LVTT);
-		apic_write_around(APIC_LVTT, v & ~APIC_LVT_MASKED);
-	}
-}
-
 void switch_APIC_timer_to_ipi(void *cpumask)
 {
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 	cpumask_t mask = *(cpumask_t *)cpumask;
 	int cpu = smp_processor_id();
 
-	if (cpu_isset(cpu, mask) &&
-	    !cpu_isset(cpu, timer_bcast_ipi)) {
-		disable_APIC_timer();
-		cpu_set(cpu, timer_bcast_ipi);
-#ifdef CONFIG_HIGH_RES_TIMERS
-		/*
-		 * C3 stops the local apic timer. We can not make high
-		 * resolution timers and dynamic ticks work with one global
-		 * timer. Disable the NEXTEVT capability, so high resolution /
-		 * dyntick mode gets disabled too.
-		 *
-		 * There is a solution for this problem, but this is beyond the
-		 * scope of this initial patchset:
-		 *
-		 * When the local apic timer is unusable in C3, then we can
-		 * utilize the PIT to provide a global wakeup, which can be
-		 * directed to the CPU which has the earliest wakeup
-		 * point. Once the CPU is up again, the local apic is resumed
-		 * and can be used for the per cpu clock events again. It's not
-		 * hard to provide the infrastructure, but I need more insight
-		 * into the ACPI code to get it right.
-		 *
-		 * Disable the highres/dyntick feature in this case for now,
-		 * until somebody beats the ACPI clue into me. :)
-		 *
-		 *	tglx
-		 */
-		printk(KERN_INFO "Disabling NO_HZ and high resolution timers "
-		       "due to timer broadcasting (C3 stops local apic)\n");
-		for_each_possible_cpu(cpu)
-			per_cpu(lapic_events, cpu).capabilities &=
-				~CLOCK_CAP_NEXTEVT;
-#endif
-	}
+	if (cpu_isset(cpu, mask))
+		clockevents_set_global_broadcast(levt, 1);
 }
 EXPORT_SYMBOL(switch_APIC_timer_to_ipi);
 
 void switch_ipi_to_APIC_timer(void *cpumask)
 {
+	struct clock_event_device *levt = &__get_cpu_var(lapic_events);
 	cpumask_t mask = *(cpumask_t *)cpumask;
 	int cpu = smp_processor_id();
 
-	if (cpu_isset(cpu, mask) &&
-	    cpu_isset(cpu, timer_bcast_ipi)) {
-		cpu_clear(cpu, timer_bcast_ipi);
-		enable_APIC_timer();
-	}
+	if (cpu_isset(cpu, mask))
+		clockevents_set_global_broadcast(levt, 0);
 }
 EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
 
 /*
+ * The guts of the apic timer interrupt
+ */
+fastcall void local_apic_timer_interrupt(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+
+	per_cpu(irq_stat, cpu).apic_timer_irqs++;
+
+	evt->event_handler(regs);
+}
+
+/*
  * Local APIC timer interrupt. This is the most natural way for doing
  * local interrupts, but local timer interrupts can be emulated by
  * broadcast interrupts too. [in case the hw doesn't support APIC timers]
@@ -585,13 +536,6 @@ EXPORT_SYMBOL(switch_ipi_to_APIC_timer);
 fastcall void smp_apic_timer_interrupt(struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
-
-	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	per_cpu(irq_stat, cpu).apic_timer_irqs++;
 
 	/*
 	 * NOTE! We'd better ACK the irq immediately,
@@ -604,42 +548,39 @@ fastcall void smp_apic_timer_interrupt(s
 	 * interrupt lock, which is the WrongThing (tm) to do.
 	 */
 	irq_enter();
-	evt->event_handler(regs);
+	local_apic_timer_interrupt(regs);
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
-#ifndef CONFIG_SMP
-static void up_apic_timer_interrupt_call(void)
+/*
+ * Local APIC timer broadcast function
+ */
+static void lapic_timer_broadcast(cpumask_t *cpumask)
 {
 	int cpu = smp_processor_id();
-	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
-
-	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	per_cpu(irq_stat, cpu).apic_timer_irqs++;
-
-	evt->event_handler(get_irq_regs());
-}
-#endif
-
-void smp_send_timer_broadcast_ipi(void)
-{
 	cpumask_t mask;
 
-	cpus_and(mask, cpu_online_map, timer_bcast_ipi);
-	if (!cpus_empty(mask)) {
+	cpus_and(mask, cpu_online_map, *cpumask);
+	if (cpu_isset(cpu, mask)) {
+		cpu_clear(cpu, mask);
+		local_apic_timer_interrupt(get_irq_regs());
+	}
 #ifdef CONFIG_SMP
+	if (!cpus_empty(mask))
 		send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
-#else
-		/*
-		 * We can directly call the apic timer interrupt handler
-		 * in UP case. Minus all irq related functions
-		 */
-		up_apic_timer_interrupt_call();
 #endif
-	}
+}
+
+/*
+ * Local APIC set next event broadcast
+ */
+void lapic_timer_idle_broadcast(int broadcast)
+{
+	int cpu = smp_processor_id();
+	struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+
+	clockevents_set_broadcast(evt, broadcast);
 }
 
 int setup_profiling_timer(unsigned int multiplier)
@@ -1052,6 +993,11 @@ void __devinit setup_local_APIC(void)
 			printk(KERN_INFO "No ESR for 82489DX.\n");
 	}
 
+	/* Disabled the local apic timer */
+	value = apic_read(APIC_LVTT);
+	value |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+	apic_write_around(APIC_LVTT, value);
+
 	setup_apic_nmi_watchdog(NULL);
 	apic_pm_activate();
 }
diff -puN arch/i386/kernel/smpboot.c~i386-apic-timer-use-clockevents-broadcast arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c~i386-apic-timer-use-clockevents-broadcast
+++ a/arch/i386/kernel/smpboot.c
@@ -438,9 +438,7 @@ static void __devinit smp_callin(void)
 	/*
 	 * Save our processor parameters
 	 */
- 	smp_store_cpu_info(cpuid);
-
-	disable_APIC_timer();
+	smp_store_cpu_info(cpuid);
 
 	/*
 	 * Allow the master to continue.
@@ -557,7 +555,6 @@ static void __devinit start_secondary(vo
 		enable_NMI_through_LVT0(NULL);
 		enable_8259A_irq(0);
 	}
-	enable_APIC_timer();
 	/*
 	 * low-memory mappings have been cleared, flush them from
 	 * the local TLBs too.
diff -puN arch/i386/kernel/time.c~i386-apic-timer-use-clockevents-broadcast arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c~i386-apic-timer-use-clockevents-broadcast
+++ a/arch/i386/kernel/time.c
@@ -193,11 +193,6 @@ irqreturn_t timer_interrupt(int irq, voi
 		outb_p( irq_v|0x80, 0x61 );	/* reset the IRQ */
 	}
 
-#ifdef CONFIG_X86_LOCAL_APIC
-	if (using_apic_timer)
-		smp_send_timer_broadcast_ipi();
-#endif
-
 	return IRQ_HANDLED;
 }
 
diff -puN drivers/acpi/processor_idle.c~i386-apic-timer-use-clockevents-broadcast drivers/acpi/processor_idle.c
--- a/drivers/acpi/processor_idle.c~i386-apic-timer-use-clockevents-broadcast
+++ a/drivers/acpi/processor_idle.c
@@ -281,11 +281,27 @@ static void acpi_propagate_timer_broadca
 		on_each_cpu(switch_ipi_to_APIC_timer, &mask, 1, 1);
 }
 
+/* Power(C) State timer broadcast control */
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+				       struct acpi_processor_cx *cx,
+				       int broadcast)
+{
+	int state = cx - pr->power.states;
+
+	if (state >= pr->power.timer_broadcast_on_state)
+		lapic_timer_idle_broadcast(broadcast);
+}
+
 #else
 
 static void acpi_timer_check_state(int state, struct acpi_processor *pr,
 				   struct acpi_processor_cx *cstate) { }
 static void acpi_propagate_timer_broadcast(struct acpi_processor *pr) { }
+static void acpi_state_timer_broadcast(struct acpi_processor *pr,
+				       struct acpi_processor_cx *cx,
+				       int broadcast)
+{
+}
 
 #endif
 
@@ -431,6 +447,7 @@ static void acpi_processor_idle(void)
 		/* Get start time (ticks) */
 		t1 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Invoke C2 */
+		acpi_state_timer_broadcast(pr, cx, 1);
 		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
@@ -445,6 +462,7 @@ static void acpi_processor_idle(void)
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
+		acpi_state_timer_broadcast(pr, cx, 0);
 		break;
 
 	case ACPI_STATE_C3:
@@ -467,6 +485,7 @@ static void acpi_processor_idle(void)
 		/* Get start time (ticks) */
 		t1 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Invoke C3 */
+		acpi_state_timer_broadcast(pr, cx, 1);
 		acpi_cstate_enter(cx);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
@@ -487,6 +506,7 @@ static void acpi_processor_idle(void)
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
+		acpi_state_timer_broadcast(pr, cx, 0);
 		break;
 
 	default:
diff -puN include/asm-i386/apic.h~i386-apic-timer-use-clockevents-broadcast include/asm-i386/apic.h
--- a/include/asm-i386/apic.h~i386-apic-timer-use-clockevents-broadcast
+++ a/include/asm-i386/apic.h
@@ -109,12 +109,9 @@ extern void smp_local_timer_interrupt (v
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern int APIC_init_uniprocessor (void);
-extern void disable_APIC_timer(void);
-extern void enable_APIC_timer(void);
-
+extern void lapic_timer_idle_broadcast(int broadcast);
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-void smp_send_timer_broadcast_ipi(void);
 void switch_APIC_timer_to_ipi(void *cpumask);
 void switch_ipi_to_APIC_timer(void *cpumask);
 #define ARCH_APICTIMER_STOPS_ON_C3	1
diff -puN include/asm-i386/mpspec.h~i386-apic-timer-use-clockevents-broadcast include/asm-i386/mpspec.h
--- a/include/asm-i386/mpspec.h~i386-apic-timer-use-clockevents-broadcast
+++ a/include/asm-i386/mpspec.h
@@ -23,7 +23,6 @@ extern struct mpc_config_intsrc mp_irqs 
 extern int mpc_default_type;
 extern unsigned long mp_lapic_addr;
 extern int pic_mode;
-extern int using_apic_timer;
 
 #ifdef CONFIG_ACPI
 extern void mp_register_lapic (u8 id, u8 enabled);
_

Patches currently in -mm which might be from tglx@xxxxxxxxxxxxx are

setup_irq-better-mismatch-debugging.patch
gtod-exponential-update_wall_time.patch
gtod-persistent-clock-support-core.patch
gtod-persistent-clock-support-i386.patch
time-uninline-jiffiesh.patch
time-uninline-jiffiesh-fix.patch
time-fix-msecs_to_jiffies-bug.patch
time-fix-timeout-overflow.patch
cleanup-uninline-irq_enter-and-move-it-into-a-function.patch
dynticks-extend-next_timer_interrupt-to-use-a-reference-jiffie.patch
dynticks-extend-next_timer_interrupt-to-use-a-reference-jiffie-remove-incorrect-warning-in-kernel-timerc.patch
hrtimers-namespace-and-enum-cleanup.patch
hrtimers-clean-up-locking.patch
updated-hrtimers-state-tracking.patch
updated-hrtimers-clean-up-callback-tracking.patch
updated-hrtimers-move-and-add-documentation.patch
updated-add-a-framework-to-manage-clock-event-devices.patch
updated-acpi-include-apich.patch
updated-acpi-keep-track-of-timer-broadcast.patch
updated-acpi-add-state-propagation-for-dynamic-broadcasting.patch
updated-i386-cleanup-apic-code.patch
updated-i386-convert-to-clock-event-devices.patch
updated-pm_timer-allow-early-access-and-move-externs-to-a-header-file.patch
updated-i386-rework-local-apic-calibration.patch
updated-high-res-timers-core.patch
updated-gtod-mark-tsc-unusable-for-highres-timers.patch
updated-dynticks-core-code.patch
updated-dyntick-add-nohz-stats-to-proc-stat.patch
updated-dynticks-i386-arch-code.patch
updated-dynticks-fix-nmi-watchdog.patch
updated-high-res-timers-dynticks-enable-i386-support.patch
updated-debugging-feature-timer-stats.patch
clockevents-core-check-for-clock-event-device-handler-being-non-null-before-calling-it.patch
round_jiffies-infrastructure.patch
round_jiffies-infrastructure-fix.patch
clocksource-add-usage-of-config_sysfs.patch
clocksource-small-cleanup-2.patch
clocksource-small-cleanup-2-fix.patch
clocksource-small-acpi_pm-cleanup.patch

-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux