Browse Source

Merge branch 'throttling' into release

Len Brown 14 years ago
parent
commit
fe3ded5078
3 changed files with 84 additions and 3 deletions
  1. 5 0
      drivers/acpi/processor_driver.c
  2. 73 3
      drivers/acpi/processor_throttling.c
  3. 6 0
      include/acpi/processor.h

+ 5 - 0
drivers/acpi/processor_driver.c

@@ -427,8 +427,13 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
 	if (action == CPU_ONLINE && pr) {
 	if (action == CPU_ONLINE && pr) {
 		acpi_processor_ppc_has_changed(pr, 0);
 		acpi_processor_ppc_has_changed(pr, 0);
 		acpi_processor_cst_has_changed(pr);
 		acpi_processor_cst_has_changed(pr);
+		acpi_processor_reevaluate_tstate(pr, action);
 		acpi_processor_tstate_has_changed(pr);
 		acpi_processor_tstate_has_changed(pr);
 	}
 	}
+	if (action == CPU_DEAD && pr) {
+		/* invalidate the flag.throttling after one CPU is offline */
+		acpi_processor_reevaluate_tstate(pr, action);
+	}
 	return NOTIFY_OK;
 	return NOTIFY_OK;
 }
 }
 
 

+ 73 - 3
drivers/acpi/processor_throttling.c

@@ -365,6 +365,58 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
 	return acpi_processor_set_throttling(pr, target_state, false);
 	return acpi_processor_set_throttling(pr, target_state, false);
 }
 }
 
 
+/*
+ * This function is used to reevaluate whether the T-state is valid
+ * after one CPU is onlined/offlined.
+ * It is noted that it won't reevaluate the following properties for
+ * the T-state.
+ *	1. Control method.
+ *	2. the number of supported T-state
+ *	3. TSD domain
+ */
+void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
+					unsigned long action)
+{
+	int result = 0;
+
+	if (action == CPU_DEAD) {
+		/* When one CPU is offline, the T-state throttling
+		 * will be invalidated.
+		 */
+		pr->flags.throttling = 0;
+		return;
+	}
+	/* the following is to recheck whether the T-state is valid for
+	 * the online CPU
+	 */
+	if (!pr->throttling.state_count) {
+		/* If the number of T-state is invalid, it is
+		 * invalidated.
+		 */
+		pr->flags.throttling = 0;
+		return;
+	}
+	pr->flags.throttling = 1;
+
+	/* Disable throttling (if enabled).  We'll let subsequent
+	 * policy (e.g.thermal) decide to lower performance if it
+	 * so chooses, but for now we'll crank up the speed.
+	 */
+
+	result = acpi_processor_get_throttling(pr);
+	if (result)
+		goto end;
+
+	if (pr->throttling.state) {
+		result = acpi_processor_set_throttling(pr, 0, false);
+		if (result)
+			goto end;
+	}
+
+end:
+	if (result)
+		pr->flags.throttling = 0;
+}
 /*
 /*
  * _PTC - Processor Throttling Control (and status) register location
  * _PTC - Processor Throttling Control (and status) register location
  */
  */
@@ -872,7 +924,11 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr)
 	 */
 	 */
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	/* FIXME: use work_on_cpu() */
 	/* FIXME: use work_on_cpu() */
-	set_cpus_allowed_ptr(current, cpumask_of(pr->id));
+	if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
+		/* Can't migrate to the target pr->id CPU. Exit */
+		free_cpumask_var(saved_mask);
+		return -ENODEV;
+	}
 	ret = pr->throttling.acpi_processor_get_throttling(pr);
 	ret = pr->throttling.acpi_processor_get_throttling(pr);
 	/* restore the previous state */
 	/* restore the previous state */
 	set_cpus_allowed_ptr(current, saved_mask);
 	set_cpus_allowed_ptr(current, saved_mask);
@@ -1047,6 +1103,14 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
+	if (cpu_is_offline(pr->id)) {
+		/*
+		 * the cpu pointed by pr->id is offline. Unnecessary to change
+		 * the throttling state any more.
+		 */
+		return -ENODEV;
+	}
+
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	cpumask_copy(saved_mask, &current->cpus_allowed);
 	t_state.target_state = state;
 	t_state.target_state = state;
 	p_throttling = &(pr->throttling);
 	p_throttling = &(pr->throttling);
@@ -1070,7 +1134,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
 	 */
 	 */
 	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
 	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
 		/* FIXME: use work_on_cpu() */
 		/* FIXME: use work_on_cpu() */
-		set_cpus_allowed_ptr(current, cpumask_of(pr->id));
+		if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
+			/* Can't migrate to the pr->id CPU. Exit */
+			ret = -ENODEV;
+			goto exit;
+		}
 		ret = p_throttling->acpi_processor_set_throttling(pr,
 		ret = p_throttling->acpi_processor_set_throttling(pr,
 						t_state.target_state, force);
 						t_state.target_state, force);
 	} else {
 	} else {
@@ -1102,7 +1170,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
 			}
 			}
 			t_state.cpu = i;
 			t_state.cpu = i;
 			/* FIXME: use work_on_cpu() */
 			/* FIXME: use work_on_cpu() */
-			set_cpus_allowed_ptr(current, cpumask_of(i));
+			if (set_cpus_allowed_ptr(current, cpumask_of(i)))
+				continue;
 			ret = match_pr->throttling.
 			ret = match_pr->throttling.
 				acpi_processor_set_throttling(
 				acpi_processor_set_throttling(
 				match_pr, t_state.target_state, force);
 				match_pr, t_state.target_state, force);
@@ -1122,6 +1191,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr,
 	/* restore the previous state */
 	/* restore the previous state */
 	/* FIXME: use work_on_cpu() */
 	/* FIXME: use work_on_cpu() */
 	set_cpus_allowed_ptr(current, saved_mask);
 	set_cpus_allowed_ptr(current, saved_mask);
+exit:
 	free_cpumask_var(online_throttling_cpus);
 	free_cpumask_var(online_throttling_cpus);
 	free_cpumask_var(saved_mask);
 	free_cpumask_var(saved_mask);
 	return ret;
 	return ret;

+ 6 - 0
include/acpi/processor.h

@@ -324,6 +324,12 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
 extern int acpi_processor_set_throttling(struct acpi_processor *pr,
 extern int acpi_processor_set_throttling(struct acpi_processor *pr,
 					 int state, bool force);
 					 int state, bool force);
+/*
+ * Reevaluate whether the T-state is invalid after one cpu is
+ * onlined/offlined. In such case the flags.throttling will be updated.
+ */
+extern void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
+			unsigned long action);
 extern const struct file_operations acpi_processor_throttling_fops;
 extern const struct file_operations acpi_processor_throttling_fops;
 extern void acpi_processor_throttling_init(void);
 extern void acpi_processor_throttling_init(void);
 /* in processor_idle.c */
 /* in processor_idle.c */