From: Todd P. <tp...@mv...> - 2005-03-04 23:47:05
|
In case anyone is interested, a patch to speed up searching for device constraints by placing these in their own list (instead of traversing full LDM lists). This also removes the last traces of the in-kernel forced operating point code, which is now relegated to userspace. Planned for the next rev of DPM, comments appreciated. Thanks -- Todd Index: linux-2.6.10/drivers/base/power/power-dpm.c =================================================================== --- linux-2.6.10.orig/drivers/base/power/power-dpm.c 2005-03-03 01:01:59.000000000 +0000 +++ linux-2.6.10/drivers/base/power/power-dpm.c 2005-03-03 03:21:30.000000000 +0000 @@ -17,10 +17,6 @@ #include "power.h" -/* Hack: Special values for power_state */ - -#define DPM_STATE_CONSTRAINED 100 - #ifdef CONFIG_HOTPLUG /* * power hotplug events @@ -160,13 +156,19 @@ */ +LIST_HEAD(dpm_constraints); +DECLARE_MUTEX(dpm_constraints_sem); + void assert_constraints(struct constraints *constraints) { #ifdef CONFIG_DPM 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. */ @@ -180,7 +182,10 @@ if (! constraints || ! constraints->asserted) return; + down(&dpm_constraints_sem); constraints->asserted = 0; + list_del_init(&constraints->entry); + up(&dpm_constraints_sem); #endif /* CONFIG_DPM */ } @@ -226,17 +231,13 @@ int provisional = 0; int ret = 0; - if(!dev->constraints) { + if (!dev->constraints) { if (! (dev->constraints = kmalloc(sizeof(struct constraints), GFP_KERNEL))) return -EINVAL; memset(dev->constraints, 0, sizeof(struct constraints)); - - /* New constraints should start off with same state as power - state */ - dev->constraints->asserted = dev->power.power_state ? 0 : 1; provisional = 1; } @@ -285,6 +286,11 @@ 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 == 0)) + assert_constraints(dev->constraints); + out: if (provisional && (ret < 0)) { @@ -334,13 +340,6 @@ int dpm_constraint_rejects = 0; -#if 0 // move-force-to-userspace -static void dpm_suspend_for_opt(struct device * dev) -{ - suspend_device(dev, DPM_STATE_CONSTRAINED); -} -#endif // move-force-to-userspace - int dpm_default_check_constraint(struct constraint_param *param, struct dpm_opt *opt) @@ -379,38 +378,19 @@ struct list_head * entry; int valid = 1; - list_for_each_prev(entry,&dpm_active) { - struct device * dev = to_device(entry); - - if (!dpm_check_a_constraint(dev->constraints, opt)) { - dev->constraints->violations++; + 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++; -#if 0 // move-force-to-userspace - if (opt->force) - dpm_suspend_for_opt(dev); - else -#endif // move-force-to-userspace - valid = 0; + valid = 0; } } return valid; } -void dpm_recheck_constraints(struct dpm_opt *opt) -{ - struct list_head * entry; - - list_for_each_prev(entry,&dpm_active) { - struct device * dev = to_device(entry); - - if (dev->power.power_state == DPM_STATE_CONSTRAINED) { - if (dpm_check_a_constraint(dev->constraints, opt)) - resume_device(dev); - } - } -} - int dpm_show_opconstraints(struct dpm_opt *opt, char * buf) { struct list_head * entry; Index: linux-2.6.10/drivers/dpm/dpm.c =================================================================== --- linux-2.6.10.orig/drivers/dpm/dpm.c 2005-03-03 01:02:01.000000000 +0000 +++ linux-2.6.10/drivers/dpm/dpm.c 2005-03-03 02:34:32.000000000 +0000 @@ -282,10 +282,6 @@ int dpm_set_opt(struct dpm_opt *new, unsigned flags) { -#if 0 // move-force-to-userspace - struct dpm_opt *old_opt = dpm_active_opt; -#endif // move-force-to-userspace - if (new->flags & DPM_OP_NOP) { if (flags & DPM_UNLOCK) dpm_unlock(); @@ -311,7 +307,7 @@ /* * Remove the IRQ disable since in some cases scheduling is needed - * to set an operating point (sleep or force mode). The spinlock + * to set an operating point (only sleep mode). The spinlock * should suffice. If the machine-dependent code needs interrupts * turned off during the code used for that platform for that * operating point set sequence then IRQs will need to be disabled @@ -327,16 +323,6 @@ if (flags & DPM_UNLOCK) dpm_unlock(); -#if 0 // move-force-to-userspace - /* - * If transitioning away from a forced operating point, see if - * any devices forced off can be resumed. - */ - - if (old_opt && old_opt->force) - dpm_recheck_constraints(new); -#endif // move-force-to-userspace - return 0; } Index: linux-2.6.10/include/linux/pm.h =================================================================== --- linux-2.6.10.orig/include/linux/pm.h 2005-03-03 01:02:01.000000000 +0000 +++ linux-2.6.10/include/linux/pm.h 2005-03-03 01:48:18.000000000 +0000 @@ -270,6 +270,7 @@ int count; int violations; struct constraint_param param[DPM_CONSTRAINT_PARAMS_MAX]; + struct list_head entry; }; enum { |