⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dpm-core-2.6.16.patch

📁 Linus Dynamic Power Management Soruce code
💻 PATCH
📖 第 1 页 / 共 5 页
字号:
+		return;+	memset (envp, 0x00, NUM_ENVP * sizeof (char *));++	buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);+	if (!buffer)+		goto exit;++	argv [0] = uevent_helper;+	argv [1] = "power";+	argv [2] = 0;++	/* minimal command environment */+	envp [i++] = "HOME=/";+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";++	scratch = buffer;++	envp [i++] = scratch;+	scratch += sprintf(scratch, "ACTION=device-event") + 1;++	spin_lock(&sequence_lock);+	seq = sequence_num++;+	spin_unlock(&sequence_lock);++	envp [i++] = scratch;+	scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;+	envp [i++] = scratch;+	scratch += sprintf(scratch, "DEVICE=%s", dev->bus_id) + 1;+	envp [i++] = scratch;+	scratch += sprintf(scratch, "EVENT=%s", eventstr) + 1;+	envp [i++] = scratch;+	scratch += sprintf(scratch, "SUBSYSTEM=power") + 1;++	pr_debug ("%s: %s %s %s %s %s %s %s %s %2\n", __FUNCTION__, argv[0], argv[1],+		  envp[0], envp[1], envp[2], envp[3], envp[4], envp[5],+		  envp[6]);+	retval = call_usermodehelper (argv[0], argv, envp, 0);+	if (retval)+		pr_debug ("%s - call_usermodehelper returned %d\n",+			  __FUNCTION__, retval);++exit:+	kfree(buffer);+	kfree(envp);+	return;+}++/*+ * Device constraints+ */++#ifdef CONFIG_DPM+LIST_HEAD(dpm_constraints);+DECLARE_MUTEX(dpm_constraints_sem);++void assert_constraints(struct constraints *constraints)+{+	if (! constraints || constraints->asserted)+		return;++	down(&dpm_constraints_sem);+	constraints->asserted = 1;+	list_add_tail(&constraints->entry, &dpm_constraints);+	up(&dpm_constraints_sem);++	/* DPM-PM-TODO: Check against DPM state. */++}+++void deassert_constraints(struct constraints *constraints)+{+	if (! constraints || ! constraints->asserted)+		return;++	down(&dpm_constraints_sem);+	constraints->asserted = 0;+	list_del_init(&constraints->entry);+	up(&dpm_constraints_sem);+}+++EXPORT_SYMBOL(assert_constraints);+EXPORT_SYMBOL(deassert_constraints);++static ssize_t+constraints_show(struct device * dev, struct device_attribute *attr,+		 char * buf)+{+	int i, cnt = 0;++	if (dev->constraints) {+		for (i = 0; i < dev->constraints->count; i++) {+			cnt += sprintf(buf + cnt,"%s: min=%d max=%d\n",+				       dpm_param_names[dev->constraints->param[i].id],+				       dev->constraints->param[i].min,+				       dev->constraints->param[i].max);+		}++		cnt += sprintf(buf + cnt,"asserted=%s violations=%d\n",+			       dev->constraints->asserted ?+			       "yes" : "no", dev->constraints->violations);+	} else {+		cnt += sprintf(buf + cnt,"none\n");+	}++	return cnt;+}++static ssize_t+constraints_store(struct device * dev, struct device_attribute *attr,+		  const char * buf, size_t count)+{+	int num_args, paramid, min, max;+	int cidx;+	const char *cp, *paramname;+	int paramnamelen;+	int provisional = 0;+	int ret = 0;++	if (!dev->constraints) {+		if (! (dev->constraints = kmalloc(sizeof(struct constraints),+						  GFP_KERNEL)))+			return -EINVAL;++		memset(dev->constraints, 0,+		       sizeof(struct constraints));+		provisional = 1;+	}++	cp = buf;+	while((cp - buf < count) && *cp && (*cp == ' '))+		cp++;++	paramname = cp;++	while((cp - buf < count) && *cp && (*cp != ' '))+		cp++;++	paramnamelen = cp - paramname;+	num_args = sscanf(cp, "%d %d", &min, &max);++	if (num_args != 2) {+		printk("DPM: Need 2 integer parameters for constraint min/max.\n");+		ret = -EINVAL;+		goto out;+	}++	for (paramid = 0; paramid < DPM_PP_NBR; paramid++) {+		if (strncmp(paramname, dpm_param_names[paramid], paramnamelen) == 0)+			break;+	}++	if (paramid >= DPM_PP_NBR) {+		printk("DPM: Unknown power parameter name in device constraints\n");+		ret = -EINVAL;+		goto out;+	}++	for (cidx = 0; cidx < dev->constraints->count; cidx++)+		/*+		 * If the new range overlaps an existing range,+		 * modify the existing one.+		 */++		if ((dev->constraints->param[cidx].id == paramid) &&+		    ((max == -1) || +		     (max >= dev->constraints->param[cidx].min)) &&+		    ((min == -1) ||+		     (min <= dev->constraints->param[cidx].max)))+			break;++	if (cidx >= DPM_CONSTRAINT_PARAMS_MAX) {+		ret = -EINVAL;+		goto out;+	}++	/* Error if max is less than min */+	if (max < min) {+		printk("DPM: Max value of the constraint should not be less than min\n");+		ret = -EINVAL;+		goto out;+	}++	dev->constraints->param[cidx].id = paramid;+	dev->constraints->param[cidx].max = max;+	dev->constraints->param[cidx].min = min;++	if (cidx == dev->constraints->count)+		dev->constraints->count++;++	/* New constraints should start off with same state as power+	   state */+	if (provisional && (dev->power.power_state.event == PM_EVENT_ON))+		assert_constraints(dev->constraints);++out:++	if (provisional && (ret < 0)) {+		kfree(dev->constraints);+		dev->constraints = NULL;+	}++	return ret < 0 ? ret : count;+}++DEVICE_ATTR(constraints,S_IWUSR | S_IRUGO,+            constraints_show,constraints_store);++#else /* CONFIG_DPM */+void assert_constraints(struct constraints *constraints)+{+}++void deassert_constraints(struct constraints *constraints)+{+}+#endif /* CONFIG_DPM */++#ifdef CONFIG_DPM++/*+ * Driver scale callbacks+ */++static struct notifier_block *dpm_scale_notifier_list[SCALE_MAX];+static DECLARE_MUTEX(dpm_scale_sem);++/* This function may be called by the platform frequency scaler before+   or after a frequency change, in order to let drivers adjust any+   clocks or calculations for the new frequency. */++void dpm_driver_scale(int level, struct dpm_opt *newop)+{+	if (down_trylock(&dpm_scale_sem))+		return;++	notifier_call_chain(&dpm_scale_notifier_list[level], level, newop);+	up(&dpm_scale_sem);+}++void dpm_register_scale(struct notifier_block *nb, int level)+{+	down(&dpm_scale_sem);+	notifier_chain_register(&dpm_scale_notifier_list[level], nb);+	up(&dpm_scale_sem);+}++void dpm_unregister_scale(struct notifier_block *nb, int level)+{+	down(&dpm_scale_sem);+	notifier_chain_unregister(&dpm_scale_notifier_list[level], nb);+	up(&dpm_scale_sem);+}++int dpm_constraint_rejects = 0;+++int+dpm_default_check_constraint(struct constraint_param *param,+			     struct dpm_opt *opt)+{+	return (opt->pp[param->id] == -1) ||+		((param->min == -1 || opt->pp[param->id] >= param->min) &&+		 (param->max == -1 || opt->pp[param->id] <= param->max));+}++static int+dpm_check_a_constraint(struct constraints *constraints, struct dpm_opt *opt)+{+	int i;+	int failid = -1;+	int ppconstraint[DPM_PP_NBR];+++	if (! constraints || !constraints->asserted)+		return 1;++	/*+	 * ppconstraint[ppid] == 0  means power param has not been checked+	 *                          for a constraint+	 *                    == -1 means power param has matched a constraint+	 *                     > 0  means constraint #n-1 mismatched+	 *+	 * failid == pp id of (a) failed constraint+	 */++	memset(ppconstraint, 0, sizeof(ppconstraint));++	for (i = 0; i < constraints->count; i++) {+		struct constraint_param *param = &constraints->param[i];++		if (! dpm_md_check_constraint(param, opt)) {+			if (ppconstraint[param->id] == 0) {+				failid = param->id;+				ppconstraint[failid] = i+1;+			}+		} else+			ppconstraint[param->id] = -1;+	}++	if ((failid >= 0) && (ppconstraint[failid] > 0)) {+#ifdef CONFIG_DPM_TRACE+		struct constraint_param *param =+			&constraints->param[ppconstraint[failid]-1];++		dpm_trace(DPM_TRACE_CONSTRAINT_ASSERTED,+			  param->id, param->min, param->max,+			  opt);+#endif+		return 0;+	}++	return 1;+}++int dpm_check_constraints(struct dpm_opt *opt)+{+	struct list_head * entry;+	int valid = 1;++	list_for_each(entry,&dpm_constraints) {+		struct constraints *constraints =+			list_entry(entry, struct constraints, entry);+		if (!dpm_check_a_constraint(constraints, opt)) {+			constraints->violations++;+			dpm_constraint_rejects++;+			valid = 0;+		}+	}++	return valid;+}++int dpm_show_opconstraints(struct dpm_opt *opt, char * buf)+{+#ifdef CONFIG_PM+	struct list_head * entry;+	int len = 0;++	list_for_each_prev(entry,&dpm_active) {+		struct device * dev = to_device(entry);++		if (!dpm_check_a_constraint(dev->constraints, opt)) {+			len += sprintf(buf + len, "%s/%s\n", dev->bus->name,+				       dev->bus_id);+		}+	}++	return len;+#else /* CONFIG_PM */+	return 0;+#endif /* CONFIG_PM */+}++void dpm_force_off_constrainers(struct dpm_opt *opt)+{+#ifdef CONFIG_PM+	struct list_head * entry;++	list_for_each_prev(entry,&dpm_active) {+		struct device * dev = to_device(entry);++		if (!dpm_check_a_constraint(dev->constraints, opt)) {+			suspend_device(dev, PMSG_SUSPEND);+		}+	}+#endif+}++EXPORT_SYMBOL(dpm_force_off_constrainers);+#endif /* CONFIG_DPM */+Index: linux-2.6.16/drivers/base/power/resume.c===================================================================--- linux-2.6.16.orig/drivers/base/power/resume.c	2006-03-20 05:53:29.000000000 +0000+++ linux-2.6.16/drivers/base/power/resume.c	2006-04-11 06:34:10.000000000 +0000@@ -34,6 +34,8 @@ 	if (dev->bus && dev->bus->resume) { 		dev_dbg(dev,"resuming\n"); 		error = dev->bus->resume(dev);+		if (!error)+			assert_constraints(dev->constraints); 	} 	up(&dev->sem); 	return error;Index: linux-2.6.16/drivers/base/power/suspend.c===================================================================--- linux-2.6.16.orig/drivers/base/power/suspend.c	2006-03-20 05:53:29.000000000 +0000+++ linux-2.6.16/drivers/base/power/suspend.c	2006-04-11 06:34:10.000000000 +0000@@ -57,6 +57,9 @@ 	if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) { 		dev_dbg(dev, "suspending\n"); 		error = dev->bus->suspend(dev, state);++		if (! error)+			deassert_constraints(dev->constraints); 	} 	up(&dev->sem); 	return error;Index: linux-2.6.16/drivers/base/power/sysfs.c===================================================================--- linux-2.6.16.orig/drivers/base/power/sysfs.c	2006-03-20 05:53:29.000000000 +0000+++ linux-2.6.16/drivers/base/power/sysfs.c	2006-04-11 06:34:10.000000000 +0000@@ -56,7 +56,6 @@  static DEVICE_ATTR(state, 0644, state_show, state_store); - /*  *	wakeup - Report/change current wakeup option for device  *@@ -128,10 +127,14 @@  static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); +extern struct device_attribute dev_attr_constraints;  static struct attribute * power_attrs[] = { 	&dev_attr_state.attr, 	&dev_attr_wakeup.attr,+#ifdef CONFIG_DPM+	&dev_attr_constraints.attr,+#endif 	NULL, }; static struct attribute_group pm_attr_group = {Index: linux-2.6.16/drivers/dpm/Kconfig===================================================================--- linux-2.6.16.orig/drivers/dpm/Kconfig	1970-01-01 00:00:00.000000000 +0000+++ linux-2.6.16/drivers/dpm/Kconfig	2006-04-11 06:34:10.000000000 +0000@@ -0,0 +1,43 @@+#+# Dynamic Power Management+#++menu "Dynamic Power Management"++config DPM+	bool "Dynamic Power Management"+	help+	  Enable Dynamic Power Management, if implemented for your platform.+	  DPM conserves power by adjusting power parameters according to+	  system state (such as idle, running a high-power-usage task, etc.)+	  and enables associated power management features such as device+	  constraints on power parameters.  DPM relies on power policy and+	  machine-dependent power operating points and such to be configured+	  from userspace after boot.++	  If in doubt, say N.++config DPM_STATS+	bool "  Enable DPM Statistics Gathering"+	depends on DPM+	help+	  This enables gathering and reporting statistics for DPM.+	  This can be useful during development of DPM platform code or+	  in other situations where information on the operation of DPM is+	  needed.++	  If in doubt, say N.+++config DPM_PROCFS+	bool "  Enable old DPM /proc interface (deprecated)"+	depends on DPM && PROC_FS+	help+	  This enables the /proc/driver/dpm interface for controlling+	  DPM.  Please note that it is recommended to use the sysfs+	  interface instead (which is built automatically).++	  If in doubt, say N.++endmenu+Index: linux-2.6.16/drivers/dpm/Makefile===================================================================--- linux-2.6.16.orig/drivers/dpm/Makefile	1970-01-01 00:00:00.000000000 +0000+++ linux-2.6.16/drivers/dpm/Makefile	2006-04-11 06:34:10.000000000 +0000@@ -0,0 +1,7 @@+#+# Makefile for the kernel DPM driver.+#++obj-$(CONFIG_DPM)		+= dpm.o dpm-idle.o dpm-ui.o+obj-$(CONFIG_DPM_PROCFS)	+= proc.o+Index: linux-2.6.16/drivers/dpm/dpm-idle.c===================================================================--- linux-2.6.16.orig/drivers/dpm/dpm-idle.c	1970-01-01 00:00:00.000000000 +0000+++ linux-2.6.16/drivers/dpm/dpm-idle.c	2006-04-11 06:34:10.000000000 +0000@@ -0,0 +1,167 @@+/*+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation; either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -