Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59d66ce2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-x86:
  x86: force timer broadcast on late AMD C1E detection
  x86: move local APIC timer init to the end of start_secondary()
  clockevents: introduce force broadcast notifier
  x86: fix missing include for vsyscall
parents 5c0d6b34 89039b37
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/mce.h>
#include <asm/mce.h>
#include <asm/nmi.h>
#include <asm/nmi.h>
#include <asm/vsyscall.h>


#define MAX_PATCH_LEN (255-1)
#define MAX_PATCH_LEN (255-1)


+26 −0
Original line number Original line Diff line number Diff line
@@ -964,8 +964,34 @@ void __init setup_boot_APIC_clock (void)
	setup_APIC_timer();
	setup_APIC_timer();
}
}


/*
 * AMD C1E enabled CPUs have a real nasty problem: Some BIOSes set the
 * C1E flag only in the secondary CPU, so when we detect the wreckage
 * we already have enabled the boot CPU local apic timer. Check, if
 * disable_apic_timer is set and the DUMMY flag is cleared. If yes,
 * set the DUMMY flag again and force the broadcast mode in the
 * clockevents layer.
 */
void __cpuinit check_boot_apic_timer_broadcast(void)
{
	struct clock_event_device *levt = &per_cpu(lapic_events, boot_cpu_id);

	if (!disable_apic_timer ||
	    (lapic_clockevent.features & CLOCK_EVT_FEAT_DUMMY))
		return;

	printk(KERN_INFO "AMD C1E detected late. Force timer broadcast.\n");
	lapic_clockevent.features |= CLOCK_EVT_FEAT_DUMMY;
	levt->features |= CLOCK_EVT_FEAT_DUMMY;

	local_irq_enable();
	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE, &boot_cpu_id);
	local_irq_disable();
}

void __cpuinit setup_secondary_APIC_clock(void)
void __cpuinit setup_secondary_APIC_clock(void)
{
{
	check_boot_apic_timer_broadcast();
	setup_APIC_timer();
	setup_APIC_timer();
}
}


+2 −5
Original line number Original line Diff line number Diff line
@@ -335,11 +335,6 @@ void __cpuinit start_secondary(void)
 	 */
 	 */
	check_tsc_sync_target();
	check_tsc_sync_target();


	Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); 	
	setup_secondary_APIC_clock();

	Dprintk("cpu %d: enabling apic timer\n", smp_processor_id());

	if (nmi_watchdog == NMI_IO_APIC) {
	if (nmi_watchdog == NMI_IO_APIC) {
		disable_8259A_irq(0);
		disable_8259A_irq(0);
		enable_NMI_through_LVT0(NULL);
		enable_NMI_through_LVT0(NULL);
@@ -374,6 +369,8 @@ void __cpuinit start_secondary(void)


	unlock_ipi_call_lock();
	unlock_ipi_call_lock();


	setup_secondary_APIC_clock();

	cpu_idle();
	cpu_idle();
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@ enum clock_event_nofitiers {
	CLOCK_EVT_NOTIFY_ADD,
	CLOCK_EVT_NOTIFY_ADD,
	CLOCK_EVT_NOTIFY_BROADCAST_ON,
	CLOCK_EVT_NOTIFY_BROADCAST_ON,
	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
	CLOCK_EVT_NOTIFY_BROADCAST_OFF,
	CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
	CLOCK_EVT_NOTIFY_BROADCAST_ENTER,
	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
	CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
	CLOCK_EVT_NOTIFY_SUSPEND,
	CLOCK_EVT_NOTIFY_SUSPEND,
+23 −6
Original line number Original line Diff line number Diff line
@@ -217,26 +217,43 @@ static void tick_do_broadcast_on_off(void *why)
	bc = tick_broadcast_device.evtdev;
	bc = tick_broadcast_device.evtdev;


	/*
	/*
	 * Is the device in broadcast mode forever or is it not
	 * Is the device not affected by the powerstate ?
	 * affected by the powerstate ?
	 */
	 */
	if (!dev || !tick_device_is_functional(dev) ||
	if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP))
	    !(dev->features & CLOCK_EVT_FEAT_C3STOP))
		goto out;
		goto out;


	if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_ON) {
	/*
	 * Defect device ?
	 */
	if (!tick_device_is_functional(dev)) {
		/*
		 * AMD C1E wreckage fixup:
		 *
		 * Device was registered functional in the first
		 * place. Now the secondary CPU detected the C1E
		 * misfeature and notifies us to fix it up
		 */
		if (*reason != CLOCK_EVT_NOTIFY_BROADCAST_FORCE)
			goto out;
	}

	switch (*reason) {
	case CLOCK_EVT_NOTIFY_BROADCAST_ON:
	case CLOCK_EVT_NOTIFY_BROADCAST_FORCE:
		if (!cpu_isset(cpu, tick_broadcast_mask)) {
		if (!cpu_isset(cpu, tick_broadcast_mask)) {
			cpu_set(cpu, tick_broadcast_mask);
			cpu_set(cpu, tick_broadcast_mask);
			if (td->mode == TICKDEV_MODE_PERIODIC)
			if (td->mode == TICKDEV_MODE_PERIODIC)
				clockevents_set_mode(dev,
				clockevents_set_mode(dev,
						     CLOCK_EVT_MODE_SHUTDOWN);
						     CLOCK_EVT_MODE_SHUTDOWN);
		}
		}
	} else {
		break;
	case CLOCK_EVT_NOTIFY_BROADCAST_OFF:
		if (cpu_isset(cpu, tick_broadcast_mask)) {
		if (cpu_isset(cpu, tick_broadcast_mask)) {
			cpu_clear(cpu, tick_broadcast_mask);
			cpu_clear(cpu, tick_broadcast_mask);
			if (td->mode == TICKDEV_MODE_PERIODIC)
			if (td->mode == TICKDEV_MODE_PERIODIC)
				tick_setup_periodic(dev, 0);
				tick_setup_periodic(dev, 0);
		}
		}
		break;
	}
	}


	if (cpus_empty(tick_broadcast_mask))
	if (cpus_empty(tick_broadcast_mask))
Loading