From 2af7f8cdac0552998fda87f6b23661af53e5726d Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Tue, 19 Nov 2013 11:20:41 +0400 Subject: [PATCH] [IMPROVE] add lcd_/un/set_energy() new interaction lcd_base with arch dependent code, Kbuild generate function pointer array Change-Id: Ie3d96b0d2f17e8eaf05918e86d7fcf416a8117ce Signed-off-by: Vyacheslav Cherkashin --- energy/Kbuild | 107 ++++++------------------- energy/energy.c | 5 ++ energy/lcd/lcd_base.c | 216 +++++++++++++++++++++++++++++++++----------------- energy/lcd/lcd_base.h | 15 ++-- energy/lcd/maru.c | 84 ++++++++++---------- 5 files changed, 224 insertions(+), 203 deletions(-) diff --git a/energy/Kbuild b/energy/Kbuild index b56015c..715930b 100644 --- a/energy/Kbuild +++ b/energy/Kbuild @@ -23,43 +23,19 @@ swap_energy-y := energy_module.o \ ############################################################################### -### description register functions ### -############################################################################### -REG_ARGS := void -REG_RET := void - - - - - -############################################################################### -### description unregister functions ### -############################################################################### -UNREG_ARGS := void -UNREG_RET := void - - - - - -############################################################################### ### math support ### ############################################################################### # S6E8AA0: ifeq ($(CONFIG_LCD_S6E8AA0), y) - #swap_energy-y += lcd/s6e8aa0.o - - #REG_FUNC_LIST += s6e8aa0_register - #UNREG_FUNC_LIST += s6e8aa0_unregister + #swap_energy-y += lcd/s6e8aa0.o + #LCD_FUNC_LIST += s6e8aa0 endif # MARU: ifeq ($(CONFIG_MARU_BACKLIGHT), y) - swap_energy-y += lcd/maru.o - - REG_FUNC_LIST += maru_register - UNREG_FUNC_LIST += maru_unregister + swap_energy-y += lcd/maru.o + LCD_FUNC_LIST += maru endif @@ -67,69 +43,39 @@ endif ############################################################################### -### generate defines for un/register functions ### +### description functions ### ############################################################################### -EMPTY := -SPACE := $(EMPTY) $(EMPTY) -COMMA := , +LCD_FUNC_ARGS := void +LCD_FUNC_RET := struct lcd_ops * ############################################################################### -### generate defines for register functions ### +### generate defines ### ############################################################################### -TMP := ($(REG_ARGS)); -DEFINITION_REG_FUNC := DEFINITION_REG_FUNC=$(foreach it, $(REG_FUNC_LIST), "extern" $(REG_RET) $(it)$(TMP)) - -ifeq (void,$(REG_ARGS)) - REG_ARGS := -endif - -TMP := $(subst $(SPACE),$(EMPTY),$(REG_ARGS)) # remove space -TMP := $(subst $(COMMA), ,$(TMP)) # replace ',' --> ' ' -LAST := $(words $(TMP)) - -TMP := $(shell seq 1 $(LAST)) -TMP := $(foreach it, $(TMP), "X"$(it)) -TMP := $(strip $(TMP)) -TMP := $(subst $(SPACE),$(COMMA),$(TMP)) # replace ' ' --> ',' -TMP := $(strip $(TMP)) - -REG_ARG_LIST := $(TMP) -TMP := ($(REG_ARG_LIST)); - -CALL_REG_FUNC := REGISTER_ALL_FUNC($(REG_ARG_LIST))={$(foreach it, $(REG_FUNC_LIST), $(it)$(TMP))} - +LCD_PREFIX := lcd_energy_ +# add prefix +TMP := $(foreach it, $(LCD_FUNC_LIST), $(LCD_PREFIX)$(it)) +LCD_FUNC_LIST := $(TMP) +# generate DEFINITION_LCD_FUNC +TMP := ($(LCD_FUNC_ARGS)); +DEFINITION_LCD_FUNC := DEFINITION_LCD_FUNC=\ +$(foreach it, $(LCD_FUNC_LIST), "extern" $(LCD_FUNC_RET) $(it)$(TMP)) -############################################################################### -### generate defines for unregister functions ### -############################################################################### -TMP := ($(UNREG_ARGS)); -DEFINITION_UNREG_FUNC := DEFINITION_UNREG_FUNC=$(foreach it, $(UNREG_FUNC_LIST), "extern" $(UNREG_RET) $(it)$(TMP)) - -ifeq (void, $(UNREG_ARGS)) - UNREG_ARGS := -endif - -TMP := $(subst $(SPACE),$(EMPTY),$(UNREG_ARGS)) # remove space -TMP := $(subst $(COMMA), ,$(TMP)) # replace ',' --> ' ' -LAST := $(words $(TMP)) - -TMP := $(shell seq 1 $(LAST)) -TMP := $(foreach it, $(TMP), "X"$(it)) -TMP := $(strip $(TMP)) -TMP := $(subst $(SPACE),$(COMMA),$(TMP)) # replace ' ' --> ',' -TMP := $(strip $(TMP)) +# generate DEFINITION_LCD_ARRAY +COMMA := , +AND := & +DEFINITION_LCD_ARRAY := DEFINITION_LCD_ARRAY=\ +"{" $(foreach it, $(LCD_FUNC_LIST), &$(it),) "}" -UNREG_ARG_LIST := $(TMP) -TMP := ($(UNREG_ARG_LIST)); -CALL_UNREG_FUNC := UNREGISTER_ALL_FUNC($(UNREG_ARG_LIST))={$(foreach it, $(UNREG_FUNC_LIST), $(it)$(TMP))} +# generate LCD_MAKE_FNAME +LCD_MAKE_FNAME := LCD_MAKE_FNAME(name)=$(LCD_PREFIX)\#\#name @@ -138,7 +84,6 @@ CALL_UNREG_FUNC := UNREGISTER_ALL_FUNC($(UNREG_ARG_LIST))={$(foreach it, $(UNREG ############################################################################### ### add generate defines to EXTRA_CFLAGS ### ############################################################################### -EXTRA_CFLAGS += -D"$(DEFINITION_REG_FUNC)" \ - -D"$(CALL_REG_FUNC)" \ - -D"$(DEFINITION_UNREG_FUNC)" \ - -D"$(CALL_UNREG_FUNC)" +EXTRA_CFLAGS += -D"$(DEFINITION_LCD_FUNC)" \ + -D"$(DEFINITION_LCD_ARRAY)" \ + -D"$(LCD_MAKE_FNAME)" diff --git a/energy/energy.c b/energy/energy.c index 9f90de8..6faf1c3 100644 --- a/energy/energy.c +++ b/energy/energy.c @@ -482,6 +482,9 @@ int do_set_energy(void) goto unregister_sys_write; } + /* TODO: check return value */ + lcd_set_energy(); + return ret; unregister_sys_read: @@ -495,6 +498,8 @@ unregister_sys_write: void do_unset_energy(void) { + lcd_unset_energy(); + dbi_unregister_kretprobe(&switch_to_krp); dbi_unregister_kretprobe(&sys_write_krp); dbi_unregister_kretprobe(&sys_read_krp); diff --git a/energy/lcd/lcd_base.c b/energy/lcd/lcd_base.c index cd75b20..75931c8 100644 --- a/energy/lcd/lcd_base.c +++ b/energy/lcd/lcd_base.c @@ -127,6 +127,19 @@ static struct lcd_priv_data *get_lcd_priv(struct lcd_ops *ops) return (struct lcd_priv_data *)ops->priv; } +static void clean_brightness(struct lcd_ops *ops) +{ + struct lcd_priv_data *lcd = get_lcd_priv(ops); + int i; + + spin_lock(&lcd->lock_tms); + for (i = 0; i < lcd->tms_brt_cnt; ++i) + tm_stat_init(&lcd->tms_brt[i]); + + lcd->brt_old = brt_no_init; + spin_unlock(&lcd->lock_tms); +} + static void set_brightness(struct lcd_ops *ops, int brt) { struct lcd_priv_data *lcd = get_lcd_priv(ops); @@ -168,11 +181,32 @@ static int func_notifier_lcd(struct lcd_ops *ops, enum lcd_action_type action, return 0; } -static LIST_HEAD(lcd_list); -static DEFINE_MUTEX(lcd_lock); +size_t get_lcd_size_array(struct lcd_ops *ops) +{ + struct lcd_priv_data *lcd = get_lcd_priv(ops); + + return lcd->tms_brt_cnt; +} + +void get_lcd_array_time(struct lcd_ops *ops, u64 *array_time) +{ + struct lcd_priv_data *lcd = get_lcd_priv(ops); + int i; + + spin_lock(&lcd->lock_tms); + for (i = 0; i < lcd->tms_brt_cnt; ++i) { + array_time[i] = tm_stat_running(&lcd->tms_brt[i]); + if (i == lcd->brt_old) + array_time[i] += get_ntime() - + tm_stat_timestamp(&lcd->tms_brt[i]); + } + spin_unlock(&lcd->lock_tms); +} -static void add_lcd(struct lcd_ops *ops) +static int register_lcd(struct lcd_ops *ops) { + int ret = 0; + ops->priv = create_lcd_priv(ops, brt_cnt); /* TODO: create init_func() for 'struct rational' */ @@ -182,112 +216,146 @@ static void add_lcd(struct lcd_ops *ops) ops->max_coef.denom = 1; ops->notifier = func_notifier_lcd; - set_brightness(ops, ops->get(ops, LPD_BRIGHTNESS)); - INIT_LIST_HEAD(&ops->list); - list_add(&ops->list, &lcd_list); + ret = register_lcd_debugfs(ops); + if (ret) + destroy_lcd_priv(ops->priv); + + return ret; } -static void del_lcd(struct lcd_ops *ops) +static void unregister_lcd(struct lcd_ops *ops) { - list_del(&ops->list); + unregister_lcd_debugfs(ops); destroy_lcd_priv(ops->priv); } -static struct lcd_ops *find_lcd(const char *name) -{ - struct lcd_ops *ops; - list_for_each_entry(ops, &lcd_list, list) - if (strcmp(ops->name, name) == 0) - return ops; - return NULL; -} -static int lcd_is_register(struct lcd_ops *ops) -{ - struct lcd_ops *o; +/* ============================================================================ + * === LCD_INIT/LCD_EXIT === + * ============================================================================ + */ +typedef struct lcd_ops *(*get_ops_t)(void); - list_for_each_entry(o, &lcd_list, list) - if (o == ops) - return 1; +DEFINITION_LCD_FUNC; - return 0; -} +get_ops_t lcd_ops[] = DEFINITION_LCD_ARRAY; +enum { lcd_ops_cnt = sizeof(lcd_ops) / sizeof(get_ops_t) }; -size_t get_lcd_size_array(struct lcd_ops *ops) -{ - struct lcd_priv_data *lcd = get_lcd_priv(ops); +enum ST_LCD_OPS { + SLO_REGISTER = 1 << 0, + SLO_SET = 1 << 1 +}; - return lcd->tms_brt_cnt; -} +static DEFINE_MUTEX(lcd_lock); +static enum ST_LCD_OPS stat_lcd_ops[lcd_ops_cnt]; -void get_lcd_array_time(struct lcd_ops *ops, u64 *array_time) +void lcd_exit(void) { - struct lcd_priv_data *lcd = get_lcd_priv(ops); int i; + struct lcd_ops *ops; - spin_lock(&lcd->lock_tms); - for (i = 0; i < lcd->tms_brt_cnt; ++i) { - array_time[i] = tm_stat_running(&lcd->tms_brt[i]); - if (i == lcd->brt_old) - array_time[i] += get_ntime() - - tm_stat_timestamp(&lcd->tms_brt[i]); + mutex_lock(&lcd_lock); + for (i = 0; i < lcd_ops_cnt; ++i) { + ops = lcd_ops[i](); + + if (stat_lcd_ops[i] & SLO_SET) { + ops->unset(ops); + stat_lcd_ops[i] &= ~SLO_SET; + } + + if (stat_lcd_ops[i] & SLO_REGISTER) { + unregister_lcd(ops); + stat_lcd_ops[i] &= ~SLO_REGISTER; + } } - spin_unlock(&lcd->lock_tms); + mutex_unlock(&lcd_lock); } -int register_lcd(struct lcd_ops *ops) +int lcd_init(void) { - int ret = 0; - - if (ops->check() == 0) { - printk("error checking %s\n", ops->name); - return -EINVAL; - } + int i, ret, count = 0; + struct lcd_ops *ops; mutex_lock(&lcd_lock); - if (find_lcd(ops->name)) { - ret = -EINVAL; - goto unlock; + for (i = 0; i < lcd_ops_cnt; ++i) { + ops = lcd_ops[i](); + if (ops == NULL) { + printk("error %s [ops == NULL]\n", ops->name); + continue; + } + + if (0 == ops->check(ops)) { + printk("error checking %s\n", ops->name); + continue; + } + + ret = register_lcd(ops); + if (ret) { + printk("error register_lcd %s\n", ops->name); + continue; + } + + stat_lcd_ops[i] |= SLO_REGISTER; + ++count; } - - add_lcd(ops); - ret = register_lcd_debugfs(ops); - if (ret) - del_lcd(ops); - -unlock: mutex_unlock(&lcd_lock); - return ret; -} -void unregister_lcd(struct lcd_ops *ops) -{ - mutex_lock(&lcd_lock); - if (lcd_is_register(ops) == 0) - goto unlock; + return count ? 0 : -EPERM; +} - unregister_lcd_debugfs(ops); - del_lcd(ops); -unlock: - mutex_unlock(&lcd_lock); -} -DEFINITION_REG_FUNC; -DEFINITION_UNREG_FUNC; -void lcd_exit(void) +/* ============================================================================ + * === LCD_SET_ENERGY/LCD_UNSET_ENERGY === + * ============================================================================ + */ +int lcd_set_energy(void) { - UNREGISTER_ALL_FUNC(); + int i, ret, count = 0; + struct lcd_ops *ops; + + mutex_lock(&lcd_lock); + for (i = 0; i < lcd_ops_cnt; ++i) { + ops = lcd_ops[i](); + if (stat_lcd_ops[i] & SLO_REGISTER) { + ret = ops->set(ops); + if (ret) { + printk("error %s set LCD energy", ops->name); + continue; + } + + set_brightness(ops, ops->get(ops, LPD_BRIGHTNESS)); + + stat_lcd_ops[i] |= SLO_SET; + ++count; + } + } + mutex_unlock(&lcd_lock); + + return count ? 0 : -EPERM; } -int lcd_init(void) +void lcd_unset_energy(void) { - REGISTER_ALL_FUNC(); + int i, ret; + struct lcd_ops *ops; - return 0; + mutex_lock(&lcd_lock); + for (i = 0; i < lcd_ops_cnt; ++i) { + ops = lcd_ops[i](); + if (stat_lcd_ops[i] & SLO_SET) { + ret = ops->unset(ops); + if (ret) + printk("error %s unset LCD energy", ops->name); + + clean_brightness(ops); + stat_lcd_ops[i] &= ~SLO_SET; + } + } + mutex_unlock(&lcd_lock); } diff --git a/energy/lcd/lcd_base.h b/energy/lcd/lcd_base.h index 1626e1f..5115cb3 100644 --- a/energy/lcd/lcd_base.h +++ b/energy/lcd/lcd_base.h @@ -42,7 +42,7 @@ enum lcd_parameter_type { struct lcd_ops; -typedef int (*check_lcd)(void); +typedef int (*call_lcd)(struct lcd_ops *ops); typedef int (*notifier_lcd)(struct lcd_ops *ops, enum lcd_action_type action, void *data); typedef unsigned long (*get_parameter_lcd)(struct lcd_ops *ops, @@ -50,13 +50,14 @@ typedef unsigned long (*get_parameter_lcd)(struct lcd_ops *ops, struct lcd_ops { - struct list_head list; - char *name; - check_lcd check; notifier_lcd notifier; get_parameter_lcd get; + call_lcd check; + call_lcd set; + call_lcd unset; + /* for debugfs */ struct dentry *dentry; struct rational min_coef; @@ -68,11 +69,11 @@ struct lcd_ops { size_t get_lcd_size_array(struct lcd_ops *ops); void get_lcd_array_time(struct lcd_ops *ops, u64 *array_time); -int register_lcd(struct lcd_ops *ops); -void unregister_lcd(struct lcd_ops *ops); - int read_val(const char *path); +int lcd_set_energy(void); +void lcd_unset_energy(void); + int lcd_init(void); void lcd_exit(void); diff --git a/energy/lcd/maru.c b/energy/lcd/maru.c index 30563e2..7adb170 100644 --- a/energy/lcd/maru.c +++ b/energy/lcd/maru.c @@ -44,7 +44,7 @@ enum { }; -static int maru_check(void) +static int maru_check(struct lcd_ops *ops) { int i; @@ -73,20 +73,54 @@ static unsigned long maru_get_parameter(struct lcd_ops *ops, return -EINVAL; } -static struct lcd_ops ops = { + + + + +static int entry_handler_set_backlight(struct kretprobe_instance *ri, + struct pt_regs *regs); +static int ret_handler_set_backlight(struct kretprobe_instance *ri, + struct pt_regs *regs); + +static struct kretprobe set_backlight_krp = { + .kp.symbol_name = "marubl_send_intensity", + .entry_handler = entry_handler_set_backlight, + .handler = ret_handler_set_backlight, + .data_size = sizeof(int) +}; + + + + + +static int maru_set(struct lcd_ops *ops) +{ + return dbi_register_kretprobe(&set_backlight_krp); +} + +static int maru_unset(struct lcd_ops *ops) +{ + dbi_unregister_kretprobe(&set_backlight_krp); + return 0; +} + +static struct lcd_ops maru_ops = { .name = "maru", .check = maru_check, + .set = maru_set, + .unset = maru_unset, .get = maru_get_parameter }; +struct lcd_ops *LCD_MAKE_FNAME(maru)(void) +{ + return &maru_ops; +} + -/* ============================================================================ - * === BACKLIGHT === - * ============================================================================ - */ static int entry_handler_set_backlight(struct kretprobe_instance *ri, struct pt_regs *regs) { @@ -105,41 +139,9 @@ static int ret_handler_set_backlight(struct kretprobe_instance *ri, int ret = regs_return_value(regs); int *brightness = (int *)ri->data; - if (!ret && ops.notifier) - ops.notifier(&ops, LAT_BRIGHTNESS, (void *)*brightness); + if (!ret && maru_ops.notifier) + maru_ops.notifier(&maru_ops, LAT_BRIGHTNESS, + (void *)*brightness); return 0; } - -static struct kretprobe set_backlight_krp = { - .kp.symbol_name = "marubl_send_intensity", - .entry_handler = entry_handler_set_backlight, - .handler = ret_handler_set_backlight, - .data_size = sizeof(int) -}; - - - - - -/* ============================================================================ - * === REGISTER/UNREGISTER === - * ============================================================================ - */ -void maru_register(void) -{ - int ret; - - dbi_register_kretprobe(&set_backlight_krp); - - ret = register_lcd(&ops); - if (ret) - printk("error maru_register()\n"); - -} - -void maru_unregister(void) -{ - unregister_lcd(&ops); - dbi_unregister_kretprobe(&set_backlight_krp); -} -- 2.7.4