Index: linux-2.6/drivers/cpufreq/cpufreq.c
===================================================================
--- linux-2.6.orig/drivers/cpufreq/cpufreq.c	2009-07-23 09:23:36.000000000 +0800
+++ linux-2.6/drivers/cpufreq/cpufreq.c	2009-07-24 09:08:27.000000000 +0800
@@ -1266,6 +1266,9 @@
 	/* only handle each CPU group once */
 	if (unlikely(cpu_policy->cpu != cpu))
 		goto out;
+	/* Set the flag of suspend/resume */
+	if (!cpufreq_driver->suspend_resume)
+		cpufreq_driver->suspend_resume = 1;
 
 	if (cpufreq_driver->suspend) {
 		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
@@ -1391,6 +1394,10 @@
 	schedule_work(&cpu_policy->update);
 fail:
 	cpufreq_cpu_put(cpu_policy);
+	/* clear the flag of suspend/resume */
+	if (cpufreq_driver->suspend_resume)
+		cpufreq_driver->suspend_resume = 0;
+
 	return ret;
 }
 
Index: linux-2.6/include/linux/cpufreq.h
===================================================================
--- linux-2.6.orig/include/linux/cpufreq.h	2009-07-09 13:03:11.000000000 +0800
+++ linux-2.6/include/linux/cpufreq.h	2009-07-24 09:08:27.000000000 +0800
@@ -234,6 +234,8 @@
 	int	(*suspend)	(struct cpufreq_policy *policy, pm_message_t pmsg);
 	int	(*resume)	(struct cpufreq_policy *policy);
 	struct freq_attr	**attr;
+	int			suspend_resume; /* indicates whether it is
+						 * suspend/resume */
 };
 
 /* flags */
Index: linux-2.6/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c	2009-07-09 13:07:06.000000000 +0800
+++ linux-2.6/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c	2009-07-24 09:08:27.000000000 +0800
@@ -197,19 +197,37 @@
 
 static void drv_read(struct drv_cmd *cmd)
 {
-	cmd->val = 0;
+	struct cpufreq_driver *freq_driver;
 
-	smp_call_function_single(cpumask_any(cmd->mask), do_drv_read, cmd, 1);
+	freq_driver = &acpi_cpufreq_driver;
+	cmd->val = 0;
+	/*
+	 * In fact only CPU0 is availabe in course of sysdev_suspend/resume.
+	 * So do it on the current cpu directly
+	 */
+	if (!freq_driver->suspend_resume)
+		smp_call_function_single(cpumask_any(cmd->mask),
+				do_drv_read, cmd, 1);
+	else
+		do_drv_read(cmd);
 }
 
 static void drv_write(struct drv_cmd *cmd)
 {
+	struct cpufreq_driver *freq_driver;
 	int this_cpu;
 
 	this_cpu = get_cpu();
+	freq_driver = &acpi_cpufreq_driver;
 	if (cpumask_test_cpu(this_cpu, cmd->mask))
 		do_drv_write(cmd);
-	smp_call_function_many(cmd->mask, do_drv_write, cmd, 1);
+
+	/*
+	 * Only CPU0 is available in course of sysdev_suspend/resume.
+	 * Don't use the smp call again when it is in suspend/resume.
+	 */
+	if (!freq_driver->suspend_resume)
+		smp_call_function_many(cmd->mask, do_drv_write, cmd, 1);
 	put_cpu();
 }
 
Index: linux-2.6/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2009-07-23 09:23:36.000000000 +0800
+++ linux-2.6/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2009-07-24 09:08:27.000000000 +0800
@@ -53,6 +53,7 @@
 static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
 
 static int cpu_family = CPU_OPTERON;
+static struct cpufreq_driver cpufreq_amd64_driver;
 
 #ifndef CONFIG_SMP
 static inline const struct cpumask *cpu_core_mask(int cpu)
@@ -1388,11 +1389,21 @@
 	struct powernow_k8_data *data = per_cpu(powernow_data, cpu);
 	unsigned int khz = 0;
 	int err;
+	struct cpufreq_driver *freq_driver = &cpufreq_amd64_driver;
 
 	if (!data)
 		return -EINVAL;
 
-	smp_call_function_single(cpu, query_values_on_cpu, &err, true);
+	/*
+	 * Only CPU0 is available in course of sysdev_suspend/resume.
+	 * So do it on the current cpu directly in course of
+	 * sysdev_suspend/resume.
+	 */
+	if (!freq_driver->suspend_resume)
+		smp_call_function_single(cpu, query_values_on_cpu, &err, true);
+	else
+		query_values_on_cpu(&err);
+
 	if (err)
 		goto out;
 
Index: linux-2.6/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c	2009-07-09 13:07:08.000000000 +0800
+++ linux-2.6/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c	2009-07-24 09:08:27.000000000 +0800
@@ -41,6 +41,8 @@
  */
 static unsigned int speedstep_processor;
 
+static struct cpufreq_driver speedstep_driver;
+
 static u32 pmbase;
 
 /*
@@ -246,11 +248,17 @@
 
 static unsigned int speedstep_get(unsigned int cpu)
 {
+	struct cpufreq_driver *freq_driver = &speedstep_driver;
 	struct get_freq_data data = { .processor = cpu };
 
+	/* In fact only CPU0 is available in course of sysdev_suspend/resume.
+	 * So do it on the current cpu directly
+	 */
+	if (freq_driver->suspend_resume)
+		get_freq_data(&data);
 	/* You're supposed to ensure CPU is online. */
-	if (smp_call_function_single(cpu, get_freq_data, &data, 1) != 0)
-		BUG();
+	else
+		smp_call_function_single(cpu, get_freq_data, &data, 1);
 
 	dprintk("detected %u kHz as current frequency\n", data.speed);
 	return data.speed;
