From: Shaohua Li <shaohua.li-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
To: acpi-dev <acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Cc: linux-JhLEnvuH02M@public.gmane.org,
Venki
<venkatesh.pallipadi-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Zwane Mwaikambo <zwane-T6AQWPvKiI1fDP7aoN8Z5Q@public.gmane.org>,
Len <len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Subject: [PATCH]Make processor module unloading safe
Date: Tue, 06 Sep 2005 16:08:24 +0800 [thread overview]
Message-ID: <1125994104.4644.13.camel@linux-hp.sh.intel.com> (raw)
Hi,
pm_idle isn’t a per-cpu data. In MP case, it is possible one CPU (eg.
the boot CPU) changed pm_idle, but other CPUs it’s not ready for it. The
ACPI module is such a case, CPU 0 changed pm_idle, which caused all CPUs
start using pm_idle, but other CPUs actually aren’t ready (their idle
information isn't initialized). The worse case is unloading ACPI module.
If non-boot CPU first freed their idle information, current code doesn’t
know it, and the CPUs possibly will use the freed memory again till boot
cpu restore pm_idle. This patch tries to fix the gaps.
Makes pm_idle a per-cpu data might be a better idea, but it’s platform
independent, so I didn't touch it but just fix the ACPI issue.
Thanks,
Shaohua
Signed-off-by: Shaohua Li<shaohua.li-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
linux-2.6.13-root/arch/i386/kernel/apm.c | 2 -
linux-2.6.13-root/arch/i386/kernel/process.c | 4 +--
linux-2.6.13-root/arch/ia64/kernel/process.c | 4 +--
linux-2.6.13-root/arch/x86_64/kernel/process.c | 4 +--
linux-2.6.13-root/drivers/acpi/processor_idle.c | 26 +++++++++++++++++++-----
linux-2.6.13-root/include/asm-i386/system.h | 3 +-
linux-2.6.13-root/include/asm-ia64/system.h | 3 +-
linux-2.6.13-root/include/asm-x86_64/system.h | 3 +-
linux-2.6.13-root/kernel/sched.c | 1
9 files changed, 35 insertions(+), 15 deletions(-)
diff -puN drivers/acpi/processor_idle.c~remove_cpu_idle_save drivers/acpi/processor_idle.c
--- linux-2.6.13/drivers/acpi/processor_idle.c~remove_cpu_idle_save 2005-09-05 09:30:34.595622176 +0800
+++ linux-2.6.13-root/drivers/acpi/processor_idle.c 2005-09-05 09:32:47.556409064 +0800
@@ -75,6 +75,8 @@ module_param(bm_history, uint, 0644);
Power Management
-------------------------------------------------------------------------- */
+static void acpi_processor_idle(void);
+static DEFINE_PER_CPU(void (*)(void), acpi_cpu_idle);
/*
* IBM ThinkPad R40e crashes mysteriously when going into C2 or C3.
* For now disable this. Probably a bug somewhere else.
@@ -170,7 +172,7 @@ acpi_processor_power_activate (
static atomic_t c3_cpu_count;
-static void acpi_processor_idle (void)
+static void __acpi_processor_idle (void)
{
struct acpi_processor *pr = NULL;
struct acpi_processor_cx *cx = NULL;
@@ -891,13 +893,13 @@ int acpi_processor_cst_has_changed (stru
return_VALUE(-ENODEV);
/* Fall back to the default idle loop */
- pm_idle = pm_idle_save;
- synchronize_sched(); /* Relies on interrupts forcing exit from idle. */
+ per_cpu(acpi_cpu_idle, pr->id) = NULL;
+ cpu_idle_wait(cpumask_of_cpu(pr->id));
pr->flags.power = 0;
result = acpi_processor_get_power_info(pr);
if ((pr->flags.power == 1) && (pr->flags.power_setup_done))
- pm_idle = acpi_processor_idle;
+ per_cpu(acpi_cpu_idle, pr->id) = __acpi_processor_idle;
return_VALUE(result);
}
@@ -983,6 +985,17 @@ static struct file_operations acpi_proce
.release = single_release,
};
+static void acpi_processor_idle(void)
+{
+ int cpu = raw_smp_processor_id();
+ if (per_cpu(acpi_cpu_idle, cpu))
+ per_cpu(acpi_cpu_idle, cpu)();
+ else if (pm_idle_save)
+ pm_idle_save();
+ else
+ safe_halt();
+}
+
int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device)
{
acpi_status status = 0;
@@ -1046,6 +1059,7 @@ int acpi_processor_power_init(struct acp
}
pr->flags.power_setup_done = 1;
+ per_cpu(acpi_cpu_idle, pr->id) = __acpi_processor_idle;
return_VALUE(0);
}
@@ -1055,6 +1069,8 @@ int acpi_processor_power_exit(struct acp
ACPI_FUNCTION_TRACE("acpi_processor_power_exit");
pr->flags.power_setup_done = 0;
+ per_cpu(acpi_cpu_idle, pr->id) = NULL;
+ cpu_idle_wait(cpumask_of_cpu(pr->id));
if (acpi_device_dir(device))
remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device));
@@ -1068,7 +1084,7 @@ int acpi_processor_power_exit(struct acp
* (pm_idle), Wait for all processors to update cached/local
* copies of pm_idle before proceeding.
*/
- cpu_idle_wait();
+ cpu_idle_wait(cpu_online_map);
}
return_VALUE(0);
diff -puN arch/i386/kernel/process.c~remove_cpu_idle_save arch/i386/kernel/process.c
--- linux-2.6.13/arch/i386/kernel/process.c~remove_cpu_idle_save 2005-09-05 09:30:34.618618680 +0800
+++ linux-2.6.13-root/arch/i386/kernel/process.c 2005-09-05 09:30:34.669610928 +0800
@@ -207,7 +207,7 @@ void cpu_idle(void)
}
}
-void cpu_idle_wait(void)
+void cpu_idle_wait(cpumask_t wait)
{
unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
@@ -216,7 +216,7 @@ void cpu_idle_wait(void)
put_cpu();
cpus_clear(map);
- for_each_online_cpu(cpu) {
+ for_each_cpu_mask(cpu, wait) {
per_cpu(cpu_idle_state, cpu) = 1;
cpu_set(cpu, map);
}
diff -puN arch/x86_64/kernel/process.c~remove_cpu_idle_save arch/x86_64/kernel/process.c
--- linux-2.6.13/arch/x86_64/kernel/process.c~remove_cpu_idle_save 2005-09-05 09:30:34.629617008 +0800
+++ linux-2.6.13-root/arch/x86_64/kernel/process.c 2005-09-05 09:30:34.670610776 +0800
@@ -128,7 +128,7 @@ static void poll_idle (void)
}
}
-void cpu_idle_wait(void)
+void cpu_idle_wait(cpumask_t wait)
{
unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
@@ -137,7 +137,7 @@ void cpu_idle_wait(void)
put_cpu();
cpus_clear(map);
- for_each_online_cpu(cpu) {
+ for_each_cpu_mask(cpu, wait) {
per_cpu(cpu_idle_state, cpu) = 1;
cpu_set(cpu, map);
}
diff -puN arch/ia64/kernel/process.c~remove_cpu_idle_save arch/ia64/kernel/process.c
--- linux-2.6.13/arch/ia64/kernel/process.c~remove_cpu_idle_save 2005-09-05 09:30:34.637615792 +0800
+++ linux-2.6.13-root/arch/ia64/kernel/process.c 2005-09-05 09:30:34.670610776 +0800
@@ -231,7 +231,7 @@ static inline void play_dead(void)
}
#endif /* CONFIG_HOTPLUG_CPU */
-void cpu_idle_wait(void)
+void cpu_idle_wait(cpumask_t wait)
{
unsigned int cpu, this_cpu = get_cpu();
cpumask_t map;
@@ -240,7 +240,7 @@ void cpu_idle_wait(void)
put_cpu();
cpus_clear(map);
- for_each_online_cpu(cpu) {
+ for_each_cpu_mask(cpu, wait) {
per_cpu(cpu_idle_state, cpu) = 1;
cpu_set(cpu, map);
}
diff -puN include/asm-x86_64/system.h~remove_cpu_idle_save include/asm-x86_64/system.h
--- linux-2.6.13/include/asm-x86_64/system.h~remove_cpu_idle_save 2005-09-05 09:30:34.638615640 +0800
+++ linux-2.6.13-root/include/asm-x86_64/system.h 2005-09-05 09:30:34.671610624 +0800
@@ -326,7 +326,8 @@ static inline unsigned long __cmpxchg(vo
/* For spinlocks etc */
#define local_irq_save(x) do { warn_if_not_ulong(x); __asm__ __volatile__("# local_irq_save \n\t pushfq ; popq %0 ; cli":"=g" (x): /* no input */ :"memory"); } while (0)
-void cpu_idle_wait(void);
+#include <linux/cpumask.h>
+void cpu_idle_wait(cpumask_t wait);
/*
* disable hlt during certain critical i/o operations
diff -puN include/asm-i386/system.h~remove_cpu_idle_save include/asm-i386/system.h
--- linux-2.6.13/include/asm-i386/system.h~remove_cpu_idle_save 2005-09-05 09:30:34.646614424 +0800
+++ linux-2.6.13-root/include/asm-i386/system.h 2005-09-05 09:30:34.671610624 +0800
@@ -466,7 +466,8 @@ void disable_hlt(void);
void enable_hlt(void);
extern int es7000_plat;
-void cpu_idle_wait(void);
+#include <linux/cpumask.h>
+void cpu_idle_wait(cpumask_t wait);
extern unsigned long arch_align_stack(unsigned long sp);
diff -puN include/asm-ia64/system.h~remove_cpu_idle_save include/asm-ia64/system.h
--- linux-2.6.13/include/asm-ia64/system.h~remove_cpu_idle_save 2005-09-05 09:30:34.647614272 +0800
+++ linux-2.6.13-root/include/asm-ia64/system.h 2005-09-05 09:30:34.671610624 +0800
@@ -276,7 +276,8 @@ extern void ia64_load_extra (struct task
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
-void cpu_idle_wait(void);
+#include <linux/cpumask.h>
+void cpu_idle_wait(cpumask_t wait);
#define arch_align_stack(x) (x)
diff -puN arch/i386/kernel/apm.c~remove_cpu_idle_save arch/i386/kernel/apm.c
--- linux-2.6.13/arch/i386/kernel/apm.c~remove_cpu_idle_save 2005-09-05 09:30:34.655613056 +0800
+++ linux-2.6.13-root/arch/i386/kernel/apm.c 2005-09-05 09:30:34.673610320 +0800
@@ -2370,7 +2370,7 @@ static void __exit apm_exit(void)
* (pm_idle), Wait for all processors to update cached/local
* copies of pm_idle before proceeding.
*/
- cpu_idle_wait();
+ cpu_idle_wait(cpu_online_map);
}
if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
&& (apm_info.connection_version > 0x0100)) {
diff -puN kernel/sched.c~remove_cpu_idle_save kernel/sched.c
--- linux-2.6.13/kernel/sched.c~remove_cpu_idle_save 2005-09-05 09:30:34.663611840 +0800
+++ linux-2.6.13-root/kernel/sched.c 2005-09-05 09:30:34.675610016 +0800
@@ -3771,6 +3771,7 @@ EXPORT_SYMBOL(cpu_present_map);
#ifndef CONFIG_SMP
cpumask_t cpu_online_map = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_possible_map = CPU_MASK_ALL;
#endif
_
-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
reply other threads:[~2005-09-06 8:08 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1125994104.4644.13.camel@linux-hp.sh.intel.com \
--to=shaohua.li-ral2jqcrhueavxtiumwx3w@public.gmane.org \
--cc=acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=len.brown-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=linux-JhLEnvuH02M@public.gmane.org \
--cc=venkatesh.pallipadi-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=zwane-T6AQWPvKiI1fDP7aoN8Z5Q@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox