Switch APIC to driver model (and make S3 sleep with APIC on)
Hi!
This switches apic code to driver model, cleans code up a lot, and makes S3 while apic is used work. Please apply,
Pavel
arch/i386/kernel/apic.c +35 -76
@@ -54,6 +55,8 @@int prof_old_multiplier[NR_CPUS ] = {1 , };int prof_counter[NR_CPUS ] = {1 , }; +unsigned long apic_phys; +int get_maxlvt (void ) {unsigned int v, ver, maxlvt;
@@ -438,8 +441,8 @@ } #ifdef CONFIG_PM - #include <linux/slab.h> +#include <linux/device.h> #include <linux/pm.h> static struct {
@@ -447,9 +450,6 @@not the BIOS; this signifies that we are also responsible for disabling it before entering apm/acpi suspend */ int active; -/* 'perfctr_pmdev' is here because the current (2.4.1) PM -callback system doesn't handle hierarchical dependencies */ -struct pm_dev *perfctr_pmdev;/* r/w apic fields */ unsigned int apic_id;unsigned int apic_taskpri;
@@ -466,13 +466,15 @@unsigned int apic_thmr; } apic_pm_state; -static void apic_pm_suspend (void *data) +static int apic_suspend (struct device *dev,u32 state,u32 level) {unsigned int l, h;unsigned long flags; -if (apic_pm_state.perfctr_pmdev) -pm_send (apic_pm_state.perfctr_pmdev,PM_SUSPEND , data); +if (level !=SUSPEND_DISABLE ) +return 0 ; + +disable_apic_nmi_watchdog (); apic_pm_state.apic_id =apic_read (APIC_ID ); apic_pm_state.apic_taskpri =apic_read (APIC_TASKPRI ); apic_pm_state.apic_ldr =apic_read (APIC_LDR );
@@ -493,13 +495,19 @@ l &= ~MSR_IA32_APICBASE_ENABLE ;wrmsr (MSR_IA32_APICBASE , l, h);local_irq_restore (flags); +return 0 ; } -static void apic_pm_resume (void *data) +static int apic_resume (struct device *dev,u32 level) {unsigned int l, h;unsigned long flags; +if (level !=RESUME_POWER_ON ) +return 0 ; + +set_fixmap_nocache (FIX_APIC_BASE , apic_phys);/* FIXME: this is needed for S3 resume, but why? */ +local_irq_save (flags);rdmsr (MSR_IA32_APICBASE , l, h); l &= ~MSR_IA32_APICBASE_BASE ;
@@ -524,74 +532,33 @@apic_write (APIC_ESR ,0 );apic_read (APIC_ESR );local_irq_restore (flags); -if (apic_pm_state.perfctr_pmdev) -pm_send (apic_pm_state.perfctr_pmdev,PM_RESUME , data); -} - -static int apic_pm_callback (struct pm_dev *dev,pm_request_t rqst,void *data) -{ -switch (rqst) { -case PM_SUSPEND : -apic_pm_suspend (data); -break ; -case PM_RESUME : -apic_pm_resume (data); -break ; - } +setup_apic_nmi_watchdog (); return 0; } -/* perfctr driver should call this instead of pm_register() */ -struct pm_dev *apic_pm_register (pm_dev_t type, -unsigned long id, -pm_callback callback) -{ -struct pm_dev *dev; - -if (!apic_pm_state.active) -return pm_register (type, id, callback); -if (apic_pm_state.perfctr_pmdev) -return NULL ;/* we're busy */ - dev =kmalloc (sizeof (struct pm_dev ),GFP_KERNEL ); -if (dev) { -memset (dev,0 ,sizeof (*dev)); - dev->type = type; - dev->id = id; - dev->callback = callback; - apic_pm_state.perfctr_pmdev = dev; - } -return dev; -} +static struct device_driver apic_driver = { + .name ="apic" , + .bus = &system_bus_type, + .resume = apic_resume, + .suspend = apic_suspend, +}; + +static struct sys_device device_apic = { + .name ="apic" , + .id =0 , + .dev = { + .name ="APIC" , + .driver = &apic_driver, + }, +}; -/* perfctr driver should call this instead of pm_unregister() */ -void apic_pm_unregister (struct pm_dev *dev) +static int __init init_apic_devicefs (void ) { -if (!apic_pm_state.active) { -pm_unregister (dev); - }else if (dev == apic_pm_state.perfctr_pmdev) { - apic_pm_state.perfctr_pmdev =NULL ; -kfree (dev); - } -} - -static void __init apic_pm_init1 (void ) -{ -/* can't pm_register() at this early stage in the boot process -(causes an immediate reboot), so just set the flag */ - apic_pm_state.active =1 ; -} - -static void __init apic_pm_init2 (void ) -{ -if (apic_pm_state.active) -pm_register (PM_SYS_DEV ,0 , apic_pm_callback); +driver_register (&apic_driver); +return sys_device_register (&device_apic); } -#else /* CONFIG_PM */ - -static inline void apic_pm_init1 (void ) { } -static inline void apic_pm_init2 (void ) { } - +device_initcall (init_apic_devicefs);#endif /* CONFIG_PM */ /*
@@ -658,9 +625,6 @@ nmi_watchdog =NMI_LOCAL_APIC ;printk ("Found and enabled local APIC!\n" ); - -apic_pm_init1 (); -return 0 ; no_apic:
@@ -670,8 +634,6 @@void __init init_apic_mappings (void ) { -unsigned long apic_phys; -/* * If no local APIC can be found then set up a fake all * zeroes page to simulate the local APIC and another
@@ -1141,8 +1103,6 @@ phys_cpu_present_map =1 ;apic_write_around (APIC_ID , boot_cpu_physical_apicid); -apic_pm_init2 (); -setup_local_APIC ();if (nmi_watchdog ==NMI_LOCAL_APIC )
arch/i386/kernel/i386_ksyms.c +0 -4
@@ -161,10 +161,6 @@EXPORT_SYMBOL (flush_tlb_page);#endif -#if defined(CONFIG_X86_LOCAL_APIC ) && defined(CONFIG_PM ) -EXPORT_SYMBOL_GPL (set_nmi_pm_callback); -EXPORT_SYMBOL_GPL (unset_nmi_pm_callback); -#endif #ifdef CONFIG_X86_IO_APIC EXPORT_SYMBOL (IO_APIC_get_PCI_irq_vector);#endif
arch/i386/kernel/nmi.c +2 -45
65 lines not on this page · raw message
Signature · 2 lines
Worst form of spam? Adding advertisment signatures ala sourceforge.net. What goes next? Inserting advertisment *into* email?