From: Todd P. <tp...@mv...> - 2005-03-11 00:43:24
|
The original thought of placing DPM frequency scaling driver callbacks in the LDM struct device_driver hasn't worked out so well, use the standard kernel notifiers to handle this instead (and require drivers to add explicit notifier registrations). Proposed for the next version of DPM. The new API is incompatible with the previous, but current patches on sourceforge do not add driver scaling callbacks (that may change soon). Comments welcome. -- 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 03:21:30.000000000 +0000 +++ linux-2.6.10/drivers/base/power/power-dpm.c 2005-03-05 00:40:24.000000000 +0000 @@ -313,28 +313,32 @@ * Driver scale callbacks */ +static struct notifier_block *dpm_scale_notifier_list; +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) +void dpm_driver_scale(int level, struct dpm_opt *newop) { - struct list_head * entry; - - /* Go through the list of devices and call all driver LDM - scale functions. */ + down(&dpm_scale_sem); + notifier_call_chain(&dpm_scale_notifier_list, level, newop); + up(&dpm_scale_sem); +} - list_for_each_prev(entry,&dpm_active) { - struct device * dev = to_device(entry); +void dpm_register_scale(struct notifier_block *nb, int level) +{ + down(&dpm_scale_sem); + notifier_chain_register(&dpm_scale_notifier_list, nb); + up(&dpm_scale_sem); +} - /* If this device has a driver and that driver has - a scale callback */ - if (dev->driver && dev->driver->scale) { - /* Call it */ - dev->driver->scale(level); - } - } +void dpm_unregister_scale(struct notifier_block *nb, int level) +{ + down(&dpm_scale_sem); + notifier_chain_unregister(&dpm_scale_notifier_list, nb); + up(&dpm_scale_sem); } int dpm_constraint_rejects = 0; Index: linux-2.6.10/include/linux/device.h =================================================================== --- linux-2.6.10.orig/include/linux/device.h 2005-03-03 01:02:01.000000000 +0000 +++ linux-2.6.10/include/linux/device.h 2005-03-05 00:34:02.000000000 +0000 @@ -120,7 +120,6 @@ void (*shutdown) (struct device * dev); int (*suspend) (struct device * dev, u32 state, u32 level); int (*resume) (struct device * dev, u32 level); - int (*scale) (u32 level); }; Index: linux-2.6.10/include/linux/dpm.h =================================================================== --- linux-2.6.10.orig/include/linux/dpm.h 2005-03-03 01:01:59.000000000 +0000 +++ linux-2.6.10/include/linux/dpm.h 2005-03-05 00:28:00.000000000 +0000 @@ -48,6 +48,7 @@ #include <linux/errno.h> #include <linux/types.h> #include <linux/unistd.h> +#include <linux/notifier.h> /* max size of DPM names */ enum {DPM_NAME_SIZE=256}; @@ -255,9 +256,12 @@ int dpm_check_constraints(struct dpm_opt *opt); int dpm_default_check_constraint(struct constraint_param *param, struct dpm_opt *opt); -void dpm_recheck_constraints(struct dpm_opt *opt); int dpm_show_opconstraints(struct dpm_opt *opt, char * buf); -void dpm_driver_scale(int level); + +/* driver scale callbacks */ +void dpm_driver_scale(int level, struct dpm_opt *newop); +void dpm_register_scale(struct notifier_block *nb, int level); +void dpm_unregister_scale(struct notifier_block *nb, int level); /* utils */ extern void dpm_udelay(unsigned uS); |