cregit-Linux how code gets into the kernel

Release 4.7 drivers/devfreq/governor_passive.c

Directory: drivers/devfreq
/*
 * linux/drivers/devfreq/governor_passive.c
 *
 * Copyright (C) 2016 Samsung Electronics
 * Author: Chanwoo Choi <cw00.choi@samsung.com>
 * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/device.h>
#include <linux/devfreq.h>
#include "governor.h"


static int devfreq_passive_get_target_freq(struct devfreq *devfreq, unsigned long *freq) { struct devfreq_passive_data *p_data = (struct devfreq_passive_data *)devfreq->data; struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent; unsigned long child_freq = ULONG_MAX; struct dev_pm_opp *opp; int i, count, ret = 0; /* * If the devfreq device with passive governor has the specific method * to determine the next frequency, should use the get_target_freq() * of struct devfreq_passive_data. */ if (p_data->get_target_freq) { ret = p_data->get_target_freq(devfreq, freq); goto out; } /* * If the parent and passive devfreq device uses the OPP table, * get the next frequency by using the OPP table. */ /* * - parent devfreq device uses the governors except for passive. * - passive devfreq device uses the passive governor. * * Each devfreq has the OPP table. After deciding the new frequency * from the governor of parent devfreq device, the passive governor * need to get the index of new frequency on OPP table of parent * device. And then the index is used for getting the suitable * new frequency for passive devfreq device. */ if (!devfreq->profile || !devfreq->profile->freq_table || devfreq->profile->max_state <= 0) return -EINVAL; /* * The passive governor have to get the correct frequency from OPP * list of parent device. Because in this case, *freq is temporary * value which is decided by ondemand governor. */ rcu_read_lock(); opp = devfreq_recommended_opp(parent_devfreq->dev.parent, freq, 0); rcu_read_unlock(); if (IS_ERR(opp)) { ret = PTR_ERR(opp); goto out; } /* * Get the OPP table's index of decided freqeuncy by governor * of parent device. */ for (i = 0; i < parent_devfreq->profile->max_state; i++) if (parent_devfreq->profile->freq_table[i] == *freq) break; if (i == parent_devfreq->profile->max_state) { ret = -EINVAL; goto out; } /* Get the suitable frequency by using index of parent device. */ if (i < devfreq->profile->max_state) { child_freq = devfreq->profile->freq_table[i]; } else { count = devfreq->profile->max_state; child_freq = devfreq->profile->freq_table[count - 1]; } /* Return the suitable frequency for passive device. */ *freq = child_freq; out: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi268100.00%1100.00%
Total268100.00%1100.00%


static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq) { int ret; if (!devfreq->governor) return -EINVAL; mutex_lock_nested(&devfreq->lock, SINGLE_DEPTH_NESTING); ret = devfreq->governor->get_target_freq(devfreq, &freq); if (ret < 0) goto out; ret = devfreq->profile->target(devfreq->dev.parent, &freq, 0); if (ret < 0) goto out; devfreq->previous_freq = freq; out: mutex_unlock(&devfreq->lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi110100.00%1100.00%
Total110100.00%1100.00%


static int devfreq_passive_notifier_call(struct notifier_block *nb, unsigned long event, void *ptr) { struct devfreq_passive_data *data = container_of(nb, struct devfreq_passive_data, nb); struct devfreq *devfreq = (struct devfreq *)data->this; struct devfreq *parent = (struct devfreq *)data->parent; struct devfreq_freqs *freqs = (struct devfreq_freqs *)ptr; unsigned long freq = freqs->new; switch (event) { case DEVFREQ_PRECHANGE: if (parent->previous_freq > freq) update_devfreq_passive(devfreq, freq); break; case DEVFREQ_POSTCHANGE: if (parent->previous_freq < freq) update_devfreq_passive(devfreq, freq); break; } return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi129100.00%1100.00%
Total129100.00%1100.00%


static int devfreq_passive_event_handler(struct devfreq *devfreq, unsigned int event, void *data) { struct device *dev = devfreq->dev.parent; struct devfreq_passive_data *p_data = (struct devfreq_passive_data *)devfreq->data; struct devfreq *parent = (struct devfreq *)p_data->parent; struct notifier_block *nb = &p_data->nb; int ret = 0; if (!parent) return -EPROBE_DEFER; switch (event) { case DEVFREQ_GOV_START: if (!p_data->this) p_data->this = devfreq; nb->notifier_call = devfreq_passive_notifier_call; ret = devm_devfreq_register_notifier(dev, parent, nb, DEVFREQ_TRANSITION_NOTIFIER); break; case DEVFREQ_GOV_STOP: devm_devfreq_unregister_notifier(dev, parent, nb, DEVFREQ_TRANSITION_NOTIFIER); break; default: break; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi144100.00%1100.00%
Total144100.00%1100.00%

static struct devfreq_governor devfreq_passive = { .name = "passive", .get_target_freq = devfreq_passive_get_target_freq, .event_handler = devfreq_passive_event_handler, };
static int __init devfreq_passive_init(void) { return devfreq_add_governor(&devfreq_passive); }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi16100.00%1100.00%
Total16100.00%1100.00%

subsys_initcall(devfreq_passive_init);
static void __exit devfreq_passive_exit(void) { int ret; ret = devfreq_remove_governor(&devfreq_passive); if (ret) pr_err("%s: failed remove governor %d\n", __func__, ret); }

Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi33100.00%1100.00%
Total33100.00%1100.00%

module_exit(devfreq_passive_exit); MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); MODULE_DESCRIPTION("DEVFREQ Passive governor"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
chanwoo choichanwoo choi765100.00%1100.00%
Total765100.00%1100.00%
Directory: drivers/devfreq
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}