summaryrefslogtreecommitdiff
path: root/drivers/edp
diff options
context:
space:
mode:
authorTimo Alho <talho@nvidia.com>2013-12-29 13:58:09 +0200
committerJuha Tukkinen <jtukkinen@nvidia.com>2013-12-31 00:23:41 -0800
commit02865374406279f3c77fd075e833b1fe4e1daae3 (patch)
treef31a9aa4d80fddb306d4cb6205b962676d5c7ae9 /drivers/edp
parent36d9ee9ef23f9d9437ed0ef93b977418f4ae4e45 (diff)
EDP: remove old system EDP framework (framework code)
Revised system edp software framework has been put in place. This patch removes old framework code under drivers/edp. Bug 1431977 Change-Id: Icde6ad7066e15172863a39388904309ce2c75c39 Signed-off-by: Timo Alho <talho@nvidia.com> Reviewed-on: http://git-master/r/350414 Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
Diffstat (limited to 'drivers/edp')
-rw-r--r--drivers/edp/Makefile10
-rw-r--r--drivers/edp/edp.c702
-rw-r--r--drivers/edp/edp_bestfit.c348
-rw-r--r--drivers/edp/edp_debug.c275
-rw-r--r--drivers/edp/edp_fair.c232
-rw-r--r--drivers/edp/edp_internal.h86
-rw-r--r--drivers/edp/edp_overage.c249
-rw-r--r--drivers/edp/edp_priority.c169
-rw-r--r--drivers/edp/edp_sysfs.c511
-rw-r--r--drivers/edp/edp_temporal.c234
-rw-r--r--drivers/edp/psy_depletion.c414
-rw-r--r--drivers/edp/tegra_core.c697
12 files changed, 0 insertions, 3927 deletions
diff --git a/drivers/edp/Makefile b/drivers/edp/Makefile
index c4aa90c234c1..7a6f2c26b99f 100644
--- a/drivers/edp/Makefile
+++ b/drivers/edp/Makefile
@@ -1,19 +1,9 @@
GCOV_PROFILE := y
-obj-$(CONFIG_EDP_FRAMEWORK) += edp.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_bestfit.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_fair.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_overage.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_priority.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_temporal.o
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_sysfs.o
-obj-$(CONFIG_EDP_FRAMEWORK) += psy_depletion.o
-obj-$(CONFIG_EDP_FRAMEWORK) += tegra_core.o
obj-$(CONFIG_SYSEDP_FRAMEWORK) += sysedp.o
obj-$(CONFIG_SYSEDP_FRAMEWORK) += sysedp_sysfs.o
obj-$(CONFIG_SYSEDP_FRAMEWORK) += sysedp_dynamic_capping.o
obj-$(CONFIG_SYSEDP_FRAMEWORK) += sysedp_batmon_calc.o
ifdef CONFIG_DEBUG_FS
-obj-$(CONFIG_EDP_FRAMEWORK) += edp_debug.o
obj-$(CONFIG_SYSEDP_FRAMEWORK) += sysedp_debug.o
endif \ No newline at end of file
diff --git a/drivers/edp/edp.c b/drivers/edp/edp.c
deleted file mode 100644
index fdee002d4b79..000000000000
--- a/drivers/edp/edp.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/edp.h>
-#include "edp_internal.h"
-
-DEFINE_MUTEX(edp_lock);
-static LIST_HEAD(edp_managers);
-LIST_HEAD(edp_governors);
-
-static struct edp_manager *find_manager(const char *name)
-{
- struct edp_manager *mgr;
-
- if (!name)
- return NULL;
-
- list_for_each_entry(mgr, &edp_managers, link)
- if (!strcmp(mgr->name, name))
- return mgr;
-
- return NULL;
-}
-
-static void update_loans(struct edp_client *client)
-{
- struct edp_governor *gov;
- gov = client->manager ? client->manager->gov : NULL;
- if (gov && client->cur && !list_empty(&client->borrowers)) {
- if (gov->update_loans)
- gov->update_loans(client);
- }
-}
-
-static void promote(struct work_struct *work)
-{
- unsigned int prev_denied;
- struct edp_client *c;
- struct edp_manager *m = container_of(work, struct edp_manager, work);
-
- mutex_lock(&edp_lock);
-
- if (m->num_denied && m->remaining && m->gov) {
- prev_denied = m->num_denied;
- m->gov->promote(m);
- if (prev_denied != m->num_denied)
- sysfs_notify(m->kobj, NULL, "denied");
- list_for_each_entry(c, &m->clients, link)
- update_loans(c);
- }
-
- mutex_unlock(&edp_lock);
-}
-
-void schedule_promotion(struct edp_manager *mgr)
-{
- if (mgr->remaining && mgr->num_denied && mgr->gov->promote)
- schedule_work(&mgr->work);
-}
-
-int edp_register_manager(struct edp_manager *mgr)
-{
- int r = -EEXIST;
-
- if (!mgr)
- return -EINVAL;
- if (!mgr->max)
- return -EINVAL;
-
- mutex_lock(&edp_lock);
- if (!find_manager(mgr->name)) {
- list_add_tail(&mgr->link, &edp_managers);
- mgr->registered = true;
- mgr->remaining = mgr->max;
- mgr->gov = NULL;
- mgr->gov_data = NULL;
- INIT_LIST_HEAD(&mgr->clients);
- INIT_WORK(&mgr->work, promote);
- mgr->kobj = NULL;
- edp_manager_add_kobject(mgr);
- manager_add_dentry(mgr);
- r = 0;
- }
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_register_manager);
-
-int edp_set_governor_unlocked(struct edp_manager *mgr,
- struct edp_governor *gov)
-{
- int r = 0;
-
- if (mgr ? !mgr->registered : 1)
- return -EINVAL;
-
- if (mgr->gov) {
- if (mgr->gov->stop)
- mgr->gov->stop(mgr);
- mgr->gov->refcnt--;
- module_put(mgr->gov->owner);
- mgr->gov = NULL;
- }
-
- if (gov) {
- if (!gov->refcnt)
- return -EINVAL;
- if (!try_module_get(gov->owner))
- return -EINVAL;
- if (gov->start)
- r = gov->start(mgr);
- if (r) {
- module_put(gov->owner);
- WARN_ON(1);
- return r;
- }
-
- gov->refcnt++;
- mgr->gov = gov;
- }
-
- return 0;
-}
-
-int edp_unregister_manager(struct edp_manager *mgr)
-{
- if (!mgr)
- return -EINVAL;
-
- mutex_lock(&edp_lock);
-
- if (!mgr->registered) {
- mutex_unlock(&edp_lock);
- return -ENODEV;
- }
-
- if (!list_empty(&mgr->clients)) {
- mutex_unlock(&edp_lock);
- return -EBUSY;
- }
-
- manager_remove_dentry(mgr);
- edp_manager_remove_kobject(mgr);
- edp_set_governor_unlocked(mgr, NULL);
- list_del(&mgr->link);
- mgr->registered = false;
-
- mutex_unlock(&edp_lock);
- cancel_work_sync(&mgr->work);
-
- return 0;
-}
-EXPORT_SYMBOL(edp_unregister_manager);
-
-struct edp_manager *edp_get_manager(const char *name)
-{
- struct edp_manager *mgr;
-
- mutex_lock(&edp_lock);
- mgr = find_manager(name);
- mutex_unlock(&edp_lock);
-
- return mgr;
-}
-EXPORT_SYMBOL(edp_get_manager);
-
-static struct edp_client *find_client(struct edp_manager *mgr,
- const char *name)
-{
- struct edp_client *p;
-
- if (!name)
- return NULL;
-
- list_for_each_entry(p, &mgr->clients, link)
- if (!strcmp(p->name, name))
- return p;
-
- return NULL;
-}
-
-unsigned int e0_current_sum(struct edp_manager *mgr)
-{
- struct edp_client *p;
- unsigned int sum = 0;
-
- list_for_each_entry(p, &mgr->clients, link)
- sum += p->states[p->e0_index];
-
- return sum;
-}
-
-static bool states_ok(struct edp_client *client)
-{
- int i;
-
- if (!client->states || !client->num_states ||
- client->e0_index >= client->num_states)
- return false;
-
- /* state array should be sorted in descending order */
- for (i = 1; i < client->num_states; i++)
- if (client->states[i] > client->states[i - 1])
- return false;
-
- return client->states[0] ? true : false;
-}
-
-/* Keep the list sorted on priority */
-static void add_client(struct edp_client *new, struct list_head *head)
-{
- struct edp_client *p;
-
- list_for_each_entry(p, head, link) {
- if (p->priority > new->priority) {
- list_add_tail(&new->link, &p->link);
- return;
- }
- }
-
- list_add_tail(&new->link, &p->link);
-}
-
-int register_client(struct edp_manager *mgr, struct edp_client *client)
-{
- if (!mgr || !client)
- return -EINVAL;
-
- if (!mgr->registered)
- return -ENODEV;
-
- if (client->manager || find_client(mgr, client->name))
- return -EEXIST;
-
- if (!states_ok(client) || client->priority > EDP_MIN_PRIO ||
- client->priority < EDP_MAX_PRIO ||
- (client->e0_index && !client->throttle))
- return -EINVAL;
-
- /* make sure that we can satisfy E0 for all registered clients */
- if (e0_current_sum(mgr) + client->states[client->e0_index] > mgr->max)
- return -E2BIG;
-
- add_client(client, &mgr->clients);
- client->manager = mgr;
- client->req = NULL;
- client->cur = NULL;
- INIT_LIST_HEAD(&client->borrowers);
- client->num_borrowers = 0;
- client->num_loans = 0;
- client->ithreshold = client->states[0];
- client->kobj = NULL;
- edp_client_add_kobject(client);
- client_add_dentry(client);
-
- return 0;
-}
-
-int edp_register_client(struct edp_manager *mgr, struct edp_client *client)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = register_client(mgr, client);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_register_client);
-
-/* generic default implementation */
-void edp_default_update_request(struct edp_client *client,
- const unsigned int *req,
- void (*throttle)(struct edp_client *))
-{
- struct edp_manager *m = client->manager;
- unsigned int old = cur_level(client);
- unsigned int new = req ? *req : 0;
- bool was_denied = client->cur != client->req;
-
- client->req = req;
-
- if (new < old) {
- client->cur = req;
- m->remaining += old - new;
- } else if (new - old <= m->remaining) {
- client->cur = req;
- m->remaining -= new - old;
- } else {
- throttle(client);
- }
-
- if (was_denied && client->cur == client->req)
- m->num_denied--;
- else if (!was_denied && client->cur != client->req)
- m->num_denied++;
-}
-
-/* generic default implementation */
-void edp_default_update_loans(struct edp_client *lender)
-{
- unsigned int size;
- unsigned int cur;
- struct loan_client *p;
-
- cur = cur_level(lender);
- size = cur > lender->ithreshold ? cur - lender->ithreshold : 0;
-
- list_for_each_entry(p, &lender->borrowers, link) {
- if (size != p->size) {
- p->size = p->client->notify_loan_update(
- size, lender, p->client->private_data);
- WARN_ON(p->size > size);
- }
-
- size -= min(p->size, size);
- }
-}
-
-unsigned int edp_throttling_point(struct edp_client *c, unsigned int deficit)
-{
- unsigned int lim;
- unsigned int i;
-
- if (cur_level(c) - e0_level(c) <= deficit)
- return c->e0_index;
-
- lim = cur_level(c) - deficit;
- i = cur_index(c);
- while (i < c->e0_index && c->states[i] > lim)
- i++;
-
- return i;
-}
-
-unsigned int edp_promotion_point(struct edp_client *c, unsigned int step)
-{
- unsigned int limit = cur_level(c) + step;
- unsigned int ci = cur_index(c);
- unsigned int i = req_index(c);
-
- while (i < ci && c->states[i] > limit)
- i++;
-
- WARN_ON(i >= c->num_states);
- return i;
-}
-
-static int mod_request(struct edp_client *client, const unsigned int *req)
-{
- struct edp_manager *m = client->manager;
- unsigned int prev_remain = m->remaining;
- unsigned int prev_denied = m->num_denied;
-
- if (!m->gov)
- return -ENODEV;
-
- m->gov->update_request(client, req);
- update_loans(client);
-
- /* Do not block calling clients for promotions */
- if (m->remaining > prev_remain)
- schedule_promotion(m);
-
- if (m->num_denied != prev_denied)
- sysfs_notify(m->kobj, NULL, "denied");
-
- return 0;
-}
-
-static void del_borrower(struct edp_client *lender, struct loan_client *pcl)
-{
- pcl->client->notify_loan_close(lender, pcl->client->private_data);
- lender->num_borrowers--;
- pcl->client->num_loans--;
- list_del(&pcl->link);
- kfree(pcl);
-}
-
-static void close_all_loans(struct edp_client *client)
-{
- struct loan_client *p;
-
- while (!list_empty(&client->borrowers)) {
- p = list_first_entry(&client->borrowers, struct loan_client,
- link);
- del_borrower(client, p);
- }
-}
-
-static inline bool registered_client(struct edp_client *client)
-{
- return client ? client->manager : false;
-}
-
-int unregister_client(struct edp_client *client)
-{
- if (!registered_client(client))
- return -EINVAL;
-
- if (client->num_loans)
- return -EBUSY;
-
- client_remove_dentry(client);
- edp_client_remove_kobject(client);
- close_all_loans(client);
- mod_request(client, NULL);
- list_del(&client->link);
- client->manager = NULL;
-
- return 0;
-}
-
-int edp_unregister_client(struct edp_client *client)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = unregister_client(client);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_unregister_client);
-
-int edp_update_client_request_unlocked(struct edp_client *client,
- unsigned int req, int *approved)
-{
- int r;
-
- if (!registered_client(client))
- return -EINVAL;
-
- if (req >= client->num_states)
- return -EINVAL;
-
- r = mod_request(client, client->states + req);
- if (!r && approved)
- *approved = client->cur - client->states;
-
- return r;
-}
-
-int edp_update_client_request(struct edp_client *client, unsigned int req,
- unsigned int *approved)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = edp_update_client_request_unlocked(client, req, approved);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_update_client_request);
-
-static struct edp_client *get_client(const char *name)
-{
- struct edp_client *client;
- struct edp_manager *mgr;
-
- if (!name)
- return NULL;
-
- list_for_each_entry(mgr, &edp_managers, link) {
- client = find_client(mgr, name);
- if (client)
- return client;
- }
-
- return NULL;
-}
-
-struct edp_client *edp_get_client(const char *name)
-{
- struct edp_client *client;
-
- mutex_lock(&edp_lock);
- client = get_client(name);
- mutex_unlock(&edp_lock);
-
- return client;
-}
-EXPORT_SYMBOL(edp_get_client);
-
-static struct loan_client *find_borrower(struct edp_client *lender,
- struct edp_client *borrower)
-{
- struct loan_client *p;
-
- list_for_each_entry(p, &lender->borrowers, link)
- if (p->client == borrower)
- return p;
- return NULL;
-}
-
-/* Keep the list sorted on priority */
-static void add_borrower(struct loan_client *new, struct list_head *head)
-{
- struct loan_client *p;
-
- list_for_each_entry(p, head, link) {
- if (p->client->priority > new->client->priority) {
- list_add_tail(&new->link, &p->link);
- return;
- }
- }
-
- list_add_tail(&new->link, &p->link);
-}
-
-static int register_loan(struct edp_client *lender, struct edp_client *borrower)
-{
- struct loan_client *p;
-
- if (!registered_client(lender) || !registered_client(borrower))
- return -EINVAL;
-
- if (lender->manager != borrower->manager ||
- !borrower->notify_loan_update ||
- !borrower->notify_loan_close)
- return -EINVAL;
-
- if (find_borrower(lender, borrower))
- return -EEXIST;
-
- if (lender->num_borrowers >= lender->max_borrowers)
- return -EBUSY;
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
-
- p->client = borrower;
- lender->num_borrowers++;
- borrower->num_loans++;
- add_borrower(p, &lender->borrowers);
-
- update_loans(lender);
- return 0;
-}
-
-int edp_register_loan(struct edp_client *lender, struct edp_client *borrower)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = register_loan(lender, borrower);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_register_loan);
-
-static int unregister_loan(struct edp_client *lender,
- struct edp_client *borrower)
-{
- struct loan_client *p;
-
- if (!registered_client(lender) || !registered_client(borrower))
- return -EINVAL;
-
- p = find_borrower(lender, borrower);
- if (!p)
- return -EINVAL;
-
- del_borrower(lender, p);
- update_loans(lender);
- return 0;
-}
-
-int edp_unregister_loan(struct edp_client *lender, struct edp_client *borrower)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = unregister_loan(lender, borrower);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_unregister_loan);
-
-int edp_update_loan_threshold_unlocked(struct edp_client *client,
- unsigned int threshold)
-{
- if (!registered_client(client))
- return -EINVAL;
-
- client->ithreshold = threshold;
- update_loans(client);
- return 0;
-}
-
-int edp_update_loan_threshold(struct edp_client *client, unsigned int threshold)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = edp_update_loan_threshold_unlocked(client, threshold);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_update_loan_threshold);
-
-struct edp_governor *edp_find_governor_unlocked(const char *s)
-{
- struct edp_governor *g;
-
- list_for_each_entry(g, &edp_governors, link)
- if (!strnicmp(s, g->name, EDP_NAME_LEN))
- return g;
-
- return NULL;
-}
-
-int edp_register_governor(struct edp_governor *gov)
-{
- int r = 0;
-
- if (!gov)
- return -EINVAL;
-
- if (!gov->update_request)
- return -EINVAL;
-
- mutex_lock(&edp_lock);
- if (edp_find_governor_unlocked(gov->name)) {
- r = -EEXIST;
- } else {
- gov->refcnt = 1;
- list_add(&gov->link, &edp_governors);
- }
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_register_governor);
-
-int edp_unregister_governor(struct edp_governor *gov)
-{
- int r = 0;
-
- mutex_lock(&edp_lock);
- if (!gov) {
- r = -EINVAL;
- } else if (gov->refcnt != 1) {
- r = gov->refcnt > 1 ? -EBUSY : -ENODEV;
- } else {
- list_del(&gov->link);
- gov->refcnt = 0;
- }
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_unregister_governor);
-
-struct edp_governor *edp_get_governor(const char *name)
-{
- struct edp_governor *g;
-
- mutex_lock(&edp_lock);
- g = edp_find_governor_unlocked(name);
- mutex_unlock(&edp_lock);
-
- return g;
-}
-EXPORT_SYMBOL(edp_get_governor);
-
-int edp_set_governor(struct edp_manager *mgr, struct edp_governor *gov)
-{
- int r;
-
- mutex_lock(&edp_lock);
- r = edp_set_governor_unlocked(mgr, gov);
- mutex_unlock(&edp_lock);
-
- return r;
-}
-EXPORT_SYMBOL(edp_set_governor);
diff --git a/drivers/edp/edp_bestfit.c b/drivers/edp/edp_bestfit.c
deleted file mode 100644
index f9425cc96df0..000000000000
--- a/drivers/edp/edp_bestfit.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include "edp_internal.h"
-
-static struct list_head hilist;
-static struct list_head lolist_hash[10];
-
-static void init_hash(void)
-{
- int i;
- INIT_LIST_HEAD(&hilist);
- for (i = 0; i < ARRAY_SIZE(lolist_hash); i++)
- INIT_LIST_HEAD(lolist_hash + i);
-}
-
-/* Return the minimum state that we must approve */
-static unsigned int min_ai(struct edp_client *c)
-{
- unsigned int ri = req_index(c);
- if (ri >= c->e0_index)
- return ri;
- return min(cur_index(c), c->e0_index);
-}
-
-static struct edp_client *lolist_hi_entry(int hash)
-{
- int i;
-
- for (i = hash; i < ARRAY_SIZE(lolist_hash); i++) {
- if (!list_empty(lolist_hash + i))
- return list_first_entry(lolist_hash + i,
- struct edp_client, glnk);
- }
-
- return NULL;
-}
-
-static struct edp_client *lolist_li_entry(int hash)
-{
- int i;
-
- for (i = hash; i >= 0; i--) {
- if (!list_empty(lolist_hash + i))
- return list_first_entry(lolist_hash + i,
- struct edp_client, glnk);
- }
-
- return NULL;
-}
-
-static struct edp_client *lolist_entry(int hash, bool hifirst)
-{
- struct edp_client *c;
-
- if (hifirst)
- c = lolist_hi_entry(hash) ?: lolist_li_entry(hash - 1);
- else
- c = lolist_li_entry(hash) ?: lolist_hi_entry(hash + 1);
-
- return c;
-}
-
-/*
- * Use hashing to fasten up the lookup for bestfit (we might have to do
- * multiple passes). If a single client can supply the minimum
- * requirement, put them into hilist. Otherwise, compute a simple hash
- * from the ratio of (cur - E0) to the minimum requirement and add to
- * the corresponding lolist queue. Entries are added to the list head
- * so that lower priority clients are throttled first.
- */
-static void prep_throttle_hash(struct edp_client *client, unsigned int mn)
-{
- struct edp_manager *m = client->manager;
- struct edp_client *c;
- unsigned int i;
- unsigned int more;
-
- init_hash();
-
- list_for_each_entry(c, &m->clients, link) {
- if (c == client || cur_level(c) <= e0_level(c))
- continue;
-
- more = cur_level(c) - e0_level(c);
-
- if (more + m->remaining < mn) {
- i = more * ARRAY_SIZE(lolist_hash) / mn;
- list_add(&c->glnk, lolist_hash + i);
- } else {
- list_add(&c->glnk, &hilist);
- }
- }
-}
-
-/*
- * Find the bestfit point between the requesting client and a potential
- * throttle-victim. Choose the one with lowest remaining current.
- */
-static unsigned int bestfit_point(struct edp_client *rc, struct edp_client *c,
- unsigned int mn, unsigned int *opt_bal)
-{
- unsigned int ai = cur_index(rc);
- unsigned int ri = req_index(rc);
- unsigned int cl = cur_level(rc);
- unsigned int step;
- unsigned int bal;
- unsigned int i;
- unsigned int j;
-
- *opt_bal = rc->manager->max;
-
- for (i = cur_index(c) + 1; i <= c->e0_index && ai > ri; i++) {
- step = rc->manager->remaining + *c->cur - c->states[i];
- if (step < mn)
- continue;
-
- j = edp_promotion_point(rc, step);
- bal = step - (rc->states[j] - cl);
- if (bal < *opt_bal) {
- *opt_bal = bal;
- c->gwt = i;
- ai = j;
- }
- }
-
- return ai;
-}
-
-static struct edp_client *throttle_bestfit_hi(struct edp_client *rc,
- unsigned int mn, unsigned int *bfi, unsigned int *opt_bal)
-{
- struct edp_client *c;
- struct edp_client *opt_c;
- unsigned int bal;
- unsigned int i;
-
- if (list_empty(&hilist))
- return NULL;
-
- opt_c = NULL;
- *opt_bal = rc->manager->max;
-
- list_for_each_entry(c, &hilist, glnk) {
- i = bestfit_point(rc, c, mn, &bal);
- if (bal < *opt_bal) {
- *bfi = i;
- *opt_bal = bal;
- opt_c = c;
- }
- }
-
- WARN_ON(!opt_c);
- return opt_c;
-}
-
-static unsigned int throttle_recover(struct edp_manager *m, unsigned int mn)
-{
- struct edp_client *c;
- unsigned int i;
- unsigned int tp;
- unsigned int step;
- unsigned int rsum = m->remaining;
-
- while (rsum < mn) {
- i = ((mn - rsum) * ARRAY_SIZE(lolist_hash) + mn - 1) / mn;
- c = lolist_entry(i, true);
- if (!c)
- break;
-
- list_del(&c->glnk);
- step = min(cur_level(c) - e0_level(c), mn - rsum);
- tp = edp_throttling_point(c, step);
- if (tp == cur_index(c))
- continue;
-
- rsum += cur_level(c) - c->states[tp];
- c->throttle(tp, c->private_data);
- if (c->cur == c->req)
- m->num_denied++;
- c->cur = c->states + tp;
- }
-
- WARN_ON(rsum < mn);
- return rsum;
-}
-
-static void throttle(struct edp_client *client)
-{
- struct edp_manager *m = client->manager;
- unsigned int ai;
- unsigned int mn;
- struct edp_client *c;
- unsigned int balance;
-
- ai = min_ai(client);
- mn = client->states[ai] - cur_level(client);
-
- if (mn <= m->remaining) {
- ai = edp_promotion_point(client, m->remaining);
- m->remaining -= client->states[ai] - cur_level(client);
- client->cur = client->states + ai;
- return;
- }
-
- prep_throttle_hash(client, mn);
- c = throttle_bestfit_hi(client, mn, &ai, &balance);
-
- if (c) {
- c->throttle(c->gwt, c->private_data);
- if (c->cur == c->req)
- m->num_denied++;
- m->remaining = balance;
- c->cur = c->states + c->gwt;
- client->cur = client->states + ai;
- return;
- }
-
- balance = throttle_recover(m, mn);
- WARN_ON(balance < mn);
- ai = edp_promotion_point(client, balance);
- m->remaining = balance - (client->states[ai] - cur_level(client));
- client->cur = client->states + ai;
-}
-
-static void bestfit_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- edp_default_update_request(client, req, throttle);
-}
-
-static void prep_promotion_hash(struct edp_manager *m)
-{
- unsigned int balance = m->remaining;
- struct edp_client *c;
- unsigned int step;
- unsigned int i;
-
- init_hash();
-
- list_for_each_entry(c, &m->clients, link) {
- if (req_level(c) <= cur_level(c) || !c->notify_promotion)
- continue;
-
- step = req_level(c) - cur_level(c);
-
- /*
- * Add to the list tail so that higher priority clients
- * are promoted first
- */
- if (step < balance) {
- i = step * ARRAY_SIZE(lolist_hash) / balance;
- list_add_tail(&c->glnk, lolist_hash + i);
- } else {
- list_add_tail(&c->glnk, &hilist);
- }
- }
-}
-
-static struct edp_client *promotion_bestfit_hi(unsigned int balance)
-{
- struct edp_client *c;
- unsigned int i;
- unsigned int step;
- struct edp_client *opt_c = NULL;
- unsigned int opt_bal = balance;
-
- list_for_each_entry(c, &hilist, glnk) {
- i = edp_promotion_point(c, balance);
- step = c->states[i] - cur_level(c);
- if (balance - step < opt_bal) {
- c->gwt = i;
- opt_c = c;
- }
- }
-
- return opt_c;
-}
-
-static void bestfit_promote(struct edp_manager *mgr)
-{
- unsigned int balance = mgr->remaining;
- struct edp_client *c;
- unsigned int i;
-
- prep_promotion_hash(mgr);
- c = promotion_bestfit_hi(balance);
-
- if (c) {
- balance -= c->states[c->gwt] - cur_level(c);
- c->cur = c->states + c->gwt;
- if (c->cur == c->req)
- mgr->num_denied--;
- c->notify_promotion(c->gwt, c->private_data);
- }
-
- while (balance && mgr->num_denied) {
- i = balance * ARRAY_SIZE(lolist_hash) / mgr->remaining;
- if (i)
- i--;
- c = lolist_entry(i, false);
- if (!c)
- break;
-
- list_del(&c->glnk);
- c->gwt = edp_promotion_point(c, balance);
- if (c->gwt == cur_index(c))
- continue;
-
- balance -= c->states[c->gwt] - cur_level(c);
- c->cur = c->states + c->gwt;
- if (c->cur == c->req)
- mgr->num_denied--;
- c->notify_promotion(c->gwt, c->private_data);
- }
-
- mgr->remaining = balance;
-}
-
-static struct edp_governor bestfit_governor = {
- .name = "bestfit",
- .owner = THIS_MODULE,
- .update_request = bestfit_update_request,
- .update_loans = edp_default_update_loans,
- .promote = bestfit_promote
-};
-
-static int __init bestfit_init(void)
-{
- return edp_register_governor(&bestfit_governor);
-}
-postcore_initcall(bestfit_init);
diff --git a/drivers/edp/edp_debug.c b/drivers/edp/edp_debug.c
deleted file mode 100644
index 2464bcce74d7..000000000000
--- a/drivers/edp/edp_debug.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include <linux/debugfs.h>
-#include "edp_internal.h"
-
-struct dentry *edp_debugfs_dir;
-
-/*
- * Reducing the cap is tricky - we might require throttling of other
- * clients (therefore, involving the governor). So we will fool the
- * framework by using a dummy client that has a single E-state (E0)
- * equalling the reduction.
- */
-static int reduce_cap(struct edp_manager *m, unsigned int new_max)
-{
- int r = 0;
- unsigned int delta = m->max - new_max;
- unsigned int remain;
- struct edp_client c = {
- .name = ".debug",
- .states = &delta,
- .num_states = 1,
- .e0_index = 0,
- .max_borrowers = 0,
- .priority = EDP_MIN_PRIO
- };
-
- r = register_client(m, &c);
- if (r)
- return r;
-
- r = edp_update_client_request_unlocked(&c, 0, NULL);
- if (r)
- return r;
-
- remain = m->remaining;
- r = unregister_client(&c);
- if (r)
- return r;
-
- m->remaining = remain;
- m->max = new_max;
- return 0;
-}
-
-static int __manager_cap_set(struct edp_manager *m, unsigned int new_max)
-{
- if (new_max >= m->max) {
- m->remaining += new_max - m->max;
- m->max = new_max;
- schedule_promotion(m);
- return 0;
- }
-
- return reduce_cap(m, new_max);
-}
-
-static int manager_status_show(struct seq_file *file, void *data)
-{
- struct edp_manager *m;
- struct edp_client *c;
-
- if (!file->private)
- return -ENODEV;
-
- m = file->private;
-
- mutex_lock(&edp_lock);
-
- seq_printf(file, "cap : %u\n", m->max);
- seq_printf(file, "sum(E0) : %u\n", e0_current_sum(m));
- seq_printf(file, "remaining: %u\n", m->remaining);
-
- seq_printf(file, "------------------------------------------\n");
- seq_printf(file, "%-16s %3s %5s %7s %7s\n",
- "client", "pri", "E0", "request", "current");
- seq_printf(file, "------------------------------------------\n");
-
- list_for_each_entry(c, &m->clients, link)
- seq_printf(file, "%-16s %3d %5u %7u %7u\n", c->name,
- c->priority, e0_level(c), req_level(c),
- cur_level(c));
-
- mutex_unlock(&edp_lock);
- return 0;
-}
-
-static int manager_status_open(struct inode *inode, struct file *file)
-{
- return single_open(file, manager_status_show, inode->i_private);
-}
-
-static const struct file_operations manager_status_fops = {
- .open = manager_status_open,
- .read = seq_read,
-};
-
-static int manager_cap_set(void *data, u64 val)
-{
- struct edp_manager *m = data;
- int r;
-
- mutex_lock(&edp_lock);
- r = __manager_cap_set(m, val);
- mutex_unlock(&edp_lock);
- return r;
-}
-
-static int manager_cap_get(void *data, u64 *val)
-{
- struct edp_manager *m = data;
-
- mutex_lock(&edp_lock);
- *val = m->max;
- mutex_unlock(&edp_lock);
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(manager_cap_fops, manager_cap_get,
- manager_cap_set, "%lld\n");
-
-void manager_add_dentry(struct edp_manager *m)
-{
- struct dentry *d;
-
- if (!edp_debugfs_dir)
- return;
-
- d = debugfs_create_dir(m->name, edp_debugfs_dir);
- if (IS_ERR_OR_NULL(d))
- return;
-
- m->dentry = d;
-
- d = debugfs_create_file("status", S_IRUGO, m->dentry, m,
- &manager_status_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-
- d = debugfs_create_file("cap", S_IRUGO | S_IWUSR, m->dentry, m,
- &manager_cap_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-}
-
-void manager_remove_dentry(struct edp_manager *m)
-{
- debugfs_remove_recursive(m->dentry);
- m->dentry = NULL;
-}
-
-static int __client_current_set(struct edp_client *c, unsigned int new)
-{
- struct edp_manager *m;
- unsigned int nl;
- unsigned int cl;
-
- if (new >= c->num_states)
- return -EINVAL;
-
- nl = c->states[new];
- cl = cur_level(c);
- m = c->manager;
-
- if (nl > cl && nl - cl > m->remaining)
- return -EBUSY;
-
- c->cur = c->states + new;
- c->req = c->states + new;
-
- if (nl < cl) {
- m->remaining += cl - nl;
- if (c->throttle)
- c->throttle(new, c->private_data);
- schedule_promotion(m);
- } else if (nl > cl) {
- m->remaining -= nl - cl;
- if (c->notify_promotion)
- c->notify_promotion(new, c->private_data);
- }
-
- return 0;
-}
-
-static int client_current_set(void *data, u64 val)
-{
- struct edp_client *c = data;
- int r;
-
- mutex_lock(&edp_lock);
- r = __client_current_set(c, val);
- mutex_unlock(&edp_lock);
- return r;
-}
-
-static int client_current_get(void *data, u64 *val)
-{
- struct edp_client *c = data;
-
- mutex_lock(&edp_lock);
- *val = cur_level(c);
- mutex_unlock(&edp_lock);
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(client_current_fops, client_current_get,
- client_current_set, "%lld\n");
-
-void client_add_dentry(struct edp_client *c)
-{
- struct dentry *d;
-
- if (!c->manager->dentry)
- return;
-
- d = debugfs_create_dir(c->name, c->manager->dentry);
- if (IS_ERR_OR_NULL(d)) {
- WARN_ON(1);
- return;
- }
-
- c->dentry = d;
-
- d = debugfs_create_file("current", S_IRUGO | S_IWUSR, c->dentry,
- c, &client_current_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-}
-
-void client_remove_dentry(struct edp_client *c)
-{
- debugfs_remove_recursive(c->dentry);
- c->dentry = NULL;
-}
-
-static void dbg_update_request(struct edp_client *c, const unsigned int *r) {}
-static void dbg_update_loans(struct edp_client *c) {}
-static void dbg_promote(struct edp_manager *mgr) {}
-
-static struct edp_governor dbg_governor = {
- .name = "debug",
- .owner = THIS_MODULE,
- .update_request = dbg_update_request,
- .update_loans = dbg_update_loans,
- .promote = dbg_promote
-};
-
-static int __init debug_init(void)
-{
- struct dentry *d;
-
- d = debugfs_create_dir("edp", NULL);
- if (IS_ERR_OR_NULL(d)) {
- WARN_ON(1);
- return -EFAULT;
- }
-
- edp_debugfs_dir = d;
- return edp_register_governor(&dbg_governor);
-}
-postcore_initcall(debug_init);
diff --git a/drivers/edp/edp_fair.c b/drivers/edp/edp_fair.c
deleted file mode 100644
index d21e87f25583..000000000000
--- a/drivers/edp/edp_fair.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include "edp_internal.h"
-
-static unsigned int approvable_req(struct edp_client *c, unsigned int net)
-{
- unsigned int fair_level;
- unsigned int step;
- unsigned int cl;
-
- if (req_index(c) >= c->e0_index)
- return req_index(c);
-
- cl = cur_level(c);
- fair_level = c->manager->max * e0_level(c) / net;
- step = max(fair_level, cl + c->manager->remaining) - cl;
- return edp_promotion_point(c, step);
-}
-
-static struct edp_client *throttle_pledge(struct edp_client *client,
- unsigned int required, unsigned int net,
- unsigned int *pledged)
-{
- struct edp_manager *m = client->manager;
- struct edp_client *c;
- unsigned int step;
- unsigned int fair;
-
- *pledged = m->remaining;
-
- list_for_each_entry_reverse(c, &m->clients, link) {
- fair = c->manager->max * e0_level(c) / net;
- if (c == client || cur_level(c) <= fair)
- continue;
-
- step = min(cur_level(c) - fair, required - *pledged);
- c->gwt = edp_throttling_point(c, step);
- *pledged += cur_level(c) - c->states[c->gwt];
- if (*pledged >= required)
- break;
- }
-
- WARN_ON(*pledged < required);
- return c;
-}
-
-static void throttle_recover(struct edp_client *client, struct edp_client *tp,
- unsigned int required)
-{
- struct edp_manager *m = client->manager;
- unsigned int recovered = m->remaining;
-
- list_for_each_entry_from(tp, &m->clients, link) {
- if (tp == client || cur_level(tp) <= e0_level(tp) ||
- tp->gwt == cur_index(tp))
- continue;
-
- tp->throttle(tp->gwt, tp->private_data);
- recovered += cur_level(tp) - tp->states[tp->gwt];
- if (tp->cur == tp->req)
- m->num_denied++;
-
- tp->cur = tp->states + tp->gwt;
- if (recovered >= required)
- return;
- }
-}
-
-static void throttle(struct edp_client *client)
-{
- struct edp_manager *m = client->manager;
- struct edp_client *tp;
- unsigned int ar;
- unsigned int pledged;
- unsigned int required;
- unsigned int net;
-
- net = e0_current_sum(m);
- if (!net) {
- WARN_ON(1);
- return;
- }
-
- ar = approvable_req(client, net);
- required = client->states[ar] - cur_level(client);
-
- if (required <= m->remaining) {
- client->cur = client->states + ar;
- m->remaining -= required;
- return;
- }
-
- tp = throttle_pledge(client, required, net, &pledged);
-
- /* E-states are discrete - we may get more than we asked for */
- if (pledged > required && ar != req_index(client)) {
- ar = edp_promotion_point(client, pledged);
- required = client->states[ar] - cur_level(client);
- }
-
- throttle_recover(client, tp, required);
- client->cur = client->states + ar;
- m->remaining = pledged - required;
-}
-
-static void fair_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- edp_default_update_request(client, req, throttle);
-}
-
-static unsigned int fair_promotion_point(struct edp_client *c,
- unsigned int step, unsigned int max)
-{
- unsigned int lim = cur_level(c) + step;
- unsigned int ci = cur_index(c);
- unsigned int i = req_index(c);
-
- while (i < ci && c->states[i] > lim)
- i++;
-
- /*
- * While being throttled, we probably contributed more than our
- * fare share - so take the ceiling E-state here
- */
- if (c->states[i] < lim && i > req_index(c)) {
- if (c->states[i - 1] <= cur_level(c) + max)
- i--;
- }
-
- return i;
-}
-
-static unsigned int promotion_pledge(struct edp_manager *m, unsigned int net)
-{
- unsigned int budget = m->remaining;
- unsigned int unpledged = m->remaining;
- unsigned int denied = m->num_denied;
- struct edp_client *c;
- unsigned int step;
-
- list_for_each_entry(c, &m->clients, link) {
- if (req_level(c) <= cur_level(c) || !c->notify_promotion)
- continue;
-
- step = (e0_level(c) * budget + net - 1) / net;
- step = min(step, unpledged);
-
- c->gwt = fair_promotion_point(c, step, unpledged);
- unpledged -= c->states[c->gwt] - cur_level(c);
- if (req_index(c) == c->gwt)
- denied--;
- if (!unpledged || !denied)
- break;
- }
-
- return unpledged;
-}
-
-static void fair_promote(struct edp_manager *mgr)
-{
- unsigned int net = 0;
- struct edp_client *c;
- unsigned int step;
- unsigned int pp;
- unsigned int unpledged;
-
- list_for_each_entry(c, &mgr->clients, link) {
- if (req_level(c) > cur_level(c) && c->notify_promotion) {
- net += e0_level(c);
- c->gwt = cur_index(c);
- }
- }
-
- /* if the net is 0, fall back on priority */
- unpledged = net ? promotion_pledge(mgr, net) : mgr->remaining;
-
- list_for_each_entry(c, &mgr->clients, link) {
- if (req_level(c) <= cur_level(c) || !c->notify_promotion ||
- c->gwt == cur_index(c))
- continue;
-
- pp = c->gwt;
-
- /* make sure that the unpledged current is not wasted */
- if (unpledged && req_index(c) != pp) {
- step = c->states[pp] - cur_level(c) + unpledged;
- pp = edp_promotion_point(c, step);
- unpledged -= c->states[pp] - c->states[c->gwt];
- }
-
- mgr->remaining -= c->states[pp] - cur_level(c);
- c->cur = c->states + pp;
- if (c->cur == c->req)
- mgr->num_denied--;
-
- c->notify_promotion(pp, c->private_data);
- if (!mgr->remaining || !mgr->num_denied)
- return;
- }
-}
-
-static struct edp_governor fair_governor = {
- .name = "fair",
- .owner = THIS_MODULE,
- .update_request = fair_update_request,
- .update_loans = edp_default_update_loans,
- .promote = fair_promote
-};
-
-static int __init fair_init(void)
-{
- return edp_register_governor(&fair_governor);
-}
-postcore_initcall(fair_init);
diff --git a/drivers/edp/edp_internal.h b/drivers/edp/edp_internal.h
deleted file mode 100644
index 37d64ee65c3b..000000000000
--- a/drivers/edp/edp_internal.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef _EDP_INTERNAL_H
-#define _EDP_INTERNAL_H
-
-#include <linux/kernel.h>
-#include <linux/edp.h>
-
-struct loan_client {
- struct list_head link;
- struct edp_client *client;
- unsigned int size;
-};
-
-static inline unsigned int cur_level(struct edp_client *c)
-{
- return c->cur ? *c->cur : 0;
-}
-
-static inline unsigned int req_level(struct edp_client *c)
-{
- return c->req ? *c->req : 0;
-}
-
-static inline unsigned int e0_level(struct edp_client *c)
-{
- return c->states[c->e0_index];
-}
-
-static inline unsigned int cur_index(struct edp_client *c)
-{
- return c->cur ? c->cur - c->states : c->num_states;
-}
-
-static inline unsigned int req_index(struct edp_client *c)
-{
- return c->req ? c->req - c->states : c->num_states;
-}
-
-extern struct mutex edp_lock;
-extern struct list_head edp_governors;
-
-int register_client(struct edp_manager *m, struct edp_client *c);
-int unregister_client(struct edp_client *c);
-
-int edp_update_client_request_unlocked(struct edp_client *client,
- unsigned int req, int *approved);
-int edp_update_loan_threshold_unlocked(struct edp_client *client,
- unsigned int threshold);
-struct edp_governor *edp_find_governor_unlocked(const char *s);
-int edp_set_governor_unlocked(struct edp_manager *mgr,
- struct edp_governor *gov);
-
-void edp_manager_add_kobject(struct edp_manager *mgr);
-void edp_manager_remove_kobject(struct edp_manager *mgr);
-void edp_client_add_kobject(struct edp_client *client);
-void edp_client_remove_kobject(struct edp_client *client);
-void edp_default_update_request(struct edp_client *client,
- const unsigned int *req,
- void (*throttle)(struct edp_client *));
-void edp_default_update_loans(struct edp_client *lender);
-unsigned int edp_throttling_point(struct edp_client *c, unsigned int deficit);
-unsigned int edp_promotion_point(struct edp_client *c, unsigned int step);
-
-void manager_add_dentry(struct edp_manager *m);
-void manager_remove_dentry(struct edp_manager *m);
-void client_add_dentry(struct edp_client *c);
-void client_remove_dentry(struct edp_client *c);
-void schedule_promotion(struct edp_manager *m);
-unsigned int e0_current_sum(struct edp_manager *mgr);
-
-#endif
diff --git a/drivers/edp/edp_overage.c b/drivers/edp/edp_overage.c
deleted file mode 100644
index 2dc1c2edc6aa..000000000000
--- a/drivers/edp/edp_overage.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include "edp_internal.h"
-
-static inline unsigned int cur_overage(struct edp_client *c)
-{
- unsigned int cl = cur_level(c);
- unsigned int el = e0_level(c);
- return cl > el ? cl - el : 0;
-}
-
-static inline unsigned int req_overage(struct edp_client *c)
-{
- unsigned int rl = req_level(c);
- unsigned int el = e0_level(c);
- return rl > el ? rl - el : 0;
-}
-
-/*
- * Find the maximum that we can allocate for this client. Since we are
- * using a propotional allocation, ensure that the allowed budget is
- * fare to other clients. Note that the maximum E-state level is used as
- * reference for normalizing client requests (E0 can not be used since
- * it could be zer0 for some clients)
- */
-static unsigned int approvable_req(struct edp_client *c,
- unsigned int net_overage, unsigned int net_max)
-{
- unsigned int tot_overage;
- unsigned int tot_max;
- unsigned int fair_level;
- unsigned int step;
-
- if (req_index(c) >= c->e0_index)
- return req_index(c);
-
- tot_overage = net_overage + c->manager->remaining;
- if (cur_overage(c))
- tot_overage += cur_overage(c);
- else
- tot_overage -= e0_level(c) - cur_level(c);
- tot_max = net_max + c->states[0];
- fair_level = tot_overage * c->states[0] / tot_max + e0_level(c);
- step = max(fair_level, cur_level(c) + c->manager->remaining) -
- cur_level(c);
-
- return edp_promotion_point(c, step);
-}
-
-static void find_net(struct edp_client *client, unsigned int *net_overage,
- unsigned int *net_max)
-{
- struct edp_client *c;
- struct edp_manager *m = client->manager;
-
- *net_overage = 0;
- *net_max = 0;
-
- list_for_each_entry(c, &m->clients, link) {
- if (c != client && cur_level(c) > e0_level(c)) {
- *net_overage += cur_overage(c);
- *net_max += c->states[0];
- }
- }
-}
-
-static struct edp_client *throttle_pledge(struct edp_client *client,
- unsigned int required, unsigned int net_overage,
- unsigned int *pledged)
-{
- struct edp_manager *m = client->manager;
- unsigned int deficit = required - m->remaining;
- struct edp_client *c;
- unsigned int step;
-
- *pledged = m->remaining;
-
- list_for_each_entry_reverse(c, &m->clients, link) {
- if (c == client || cur_level(c) <= e0_level(c))
- continue;
-
- step = (deficit * cur_overage(c) +
- net_overage - 1) / net_overage;
- c->gwt = edp_throttling_point(c, step);
- *pledged += cur_level(c) - c->states[c->gwt];
- if (*pledged >= required)
- return c;
- }
-
- WARN_ON(*pledged < required);
- return c;
-}
-
-static void throttle_recover(struct edp_client *client, struct edp_client *tp,
- unsigned int required)
-{
- struct edp_manager *m = client->manager;
- unsigned int recovered = m->remaining;
-
- list_for_each_entry_from(tp, &m->clients, link) {
- if (tp == client || cur_level(tp) <= e0_level(tp) ||
- tp->gwt == cur_index(tp))
- continue;
-
- tp->throttle(tp->gwt, tp->private_data);
- recovered += cur_level(tp) - tp->states[tp->gwt];
- if (tp->cur == tp->req)
- m->num_denied++;
-
- tp->cur = tp->states + tp->gwt;
- if (recovered >= required)
- return;
- }
-}
-
-static void throttle(struct edp_client *client)
-{
- struct edp_manager *m = client->manager;
- struct edp_client *tp;
- unsigned int ar;
- unsigned int pledged;
- unsigned int required;
- unsigned int net_overage;
- unsigned int net_max;
-
- find_net(client, &net_overage, &net_max);
- ar = approvable_req(client, net_overage, net_max);
- required = client->states[ar] - cur_level(client);
-
- if (required <= m->remaining) {
- client->cur = client->states + ar;
- m->remaining -= required;
- return;
- }
-
- tp = throttle_pledge(client, required, net_overage, &pledged);
-
- /* E-states are discrete - we may get more than we asked for */
- if (pledged > required && ar != req_index(client)) {
- ar = edp_promotion_point(client, pledged);
- required = client->states[ar] - cur_level(client);
- }
-
- throttle_recover(client, tp, required);
- client->cur = client->states + ar;
- m->remaining = pledged - required;
-}
-
-static void overage_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- edp_default_update_request(client, req, throttle);
-}
-
-static unsigned int overage_promotion_point(struct edp_client *c,
- unsigned int step, unsigned int max)
-{
- unsigned int lim = cur_level(c) + step;
- unsigned int ci = cur_index(c);
- unsigned int i = req_index(c);
-
- while (i < ci && c->states[i] > lim)
- i++;
-
- /*
- * While being throttled, we probably contributed more than our
- * fare share - so take the ceiling E-state here
- */
- if (c->states[i] < lim && i > req_index(c)) {
- if (c->states[i - 1] <= cur_level(c) + max)
- i--;
- }
-
- return i;
-}
-
-static void overage_promote(struct edp_manager *mgr)
-{
- unsigned int budget = mgr->remaining;
- unsigned int net_overage = 0;
- struct edp_client *c;
- unsigned int step;
- unsigned int pp;
-
- list_for_each_entry(c, &mgr->clients, link) {
- if (req_level(c) > cur_level(c) && c->notify_promotion)
- net_overage += req_overage(c);
- }
-
- /* Guarding against division-by-zero */
- if (!net_overage) {
- WARN_ON(1);
- return;
- }
-
- list_for_each_entry(c, &mgr->clients, link) {
- if (req_level(c) <= cur_level(c) || !c->notify_promotion)
- continue;
-
- step = (req_overage(c) * budget +
- net_overage - 1) / net_overage;
- if (step > mgr->remaining)
- step = mgr->remaining;
-
- pp = overage_promotion_point(c, step, mgr->remaining);
- if (pp == cur_index(c))
- continue;
-
- mgr->remaining -= c->states[pp] - cur_level(c);
- c->cur = c->states + pp;
-
- if (c->cur == c->req)
- mgr->num_denied--;
- c->notify_promotion(pp, c->private_data);
- if (!mgr->remaining || !mgr->num_denied)
- return;
- }
-}
-
-static struct edp_governor overage_governor = {
- .name = "overage",
- .owner = THIS_MODULE,
- .update_request = overage_update_request,
- .update_loans = edp_default_update_loans,
- .promote = overage_promote
-};
-
-static int __init overage_init(void)
-{
- return edp_register_governor(&overage_governor);
-}
-postcore_initcall(overage_init);
diff --git a/drivers/edp/edp_priority.c b/drivers/edp/edp_priority.c
deleted file mode 100644
index 937c20bdf16e..000000000000
--- a/drivers/edp/edp_priority.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include "edp_internal.h"
-
-/*
- * Calculate the approvable E-state for the requesting client.
- * Non-negative E-state requests are always approved. A (higher)
- * negative E-state request is approved only if lower priority clients
- * can be throttled (at most to E0) in order to recover the necessary
- * power deficit. If this can not be met, a lower E-state is approved
- * (at least E0).
- */
-static unsigned int approvable_req(struct edp_client *client)
-{
- struct edp_manager *m = client->manager;
- unsigned int old = cur_level(client);
- unsigned int deficit = *client->req - old;
- unsigned int recoverable = m->remaining;
- unsigned int i = req_index(client);
- struct edp_client *p = client;
-
- if (i >= client->e0_index)
- return i;
-
- list_for_each_entry_continue(p, &m->clients, link) {
- if (cur_level(p) > e0_level(p)) {
- recoverable += cur_level(p) - e0_level(p);
- if (recoverable >= deficit)
- return i;
- }
- }
-
- while (i < client->e0_index && recoverable < deficit) {
- i++;
- deficit = client->states[i] - old;
- }
-
- return i;
-}
-
-static void throttle(struct edp_client *client)
-{
- unsigned int ar;
- unsigned int deficit;
- struct edp_client *p;
- struct edp_manager *m = client->manager;
- unsigned int pledged = m->remaining;
- unsigned int recovered = m->remaining;
-
- /* Check if we can satisfy the request as it is */
- ar = approvable_req(client);
- deficit = client->states[ar] - cur_level(client);
- if (m->remaining >= deficit)
- goto ret;
-
- /*
- * We do the throttling in two steps: first we will identify and
- * mark the clients starting from the lower priority ones. We
- * stop when we find the highest priority client that should be
- * throttled.
- */
- list_for_each_entry_reverse(p, &m->clients, link) {
- if (p == client || cur_level(p) <= e0_level(p))
- continue;
-
- p->gwt = edp_throttling_point(p, deficit - pledged);
- pledged += cur_level(p) - p->states[p->gwt];
- if (pledged >= deficit)
- break;
- }
-
- /*
- * By now, we are guaranteed to have at least the adjusted
- * deficit - may be even more.
- */
- WARN_ON(pledged < deficit);
-
- /*
- * We now do the actual throttling starting from where we stoped
- * in step 1 and going in the opposite direction. This way we
- * can avoid situations where clients are throttled needlessly
- * and promoted back immediately.
- */
- list_for_each_entry_from(p, &m->clients, link) {
- if (p == client || cur_level(p) <= e0_level(p) ||
- p->gwt == cur_index(p))
- continue;
-
- p->throttle(p->gwt, p->private_data);
- recovered += cur_level(p) - p->states[p->gwt];
- if (p->cur == p->req)
- m->num_denied++;
-
- p->cur = p->states + p->gwt;
- if (recovered >= deficit)
- break;
- }
-
-ret:
- client->cur = client->states + ar;
- m->remaining = recovered - deficit;
-}
-
-static void prio_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- edp_default_update_request(client, req, throttle);
-}
-
-static void prio_promote(struct edp_manager *mgr)
-{
- struct edp_client *p;
- unsigned int delta;
- unsigned int pp;
-
- list_for_each_entry(p, &mgr->clients, link) {
- if (req_level(p) <= cur_level(p) || !p->notify_promotion)
- continue;
-
- delta = req_level(p) - cur_level(p);
- if (delta > mgr->remaining)
- delta = mgr->remaining;
-
- pp = edp_promotion_point(p, delta);
- if (pp == cur_index(p))
- continue;
-
- mgr->remaining -= p->states[pp] - cur_level(p);
- p->cur = p->states + pp;
-
- if (p->cur == p->req)
- mgr->num_denied--;
-
- p->notify_promotion(pp, p->private_data);
- if (!mgr->remaining || !mgr->num_denied)
- return;
- }
-}
-
-static struct edp_governor prio_governor = {
- .name = "priority",
- .owner = THIS_MODULE,
- .update_request = prio_update_request,
- .update_loans = edp_default_update_loans,
- .promote = prio_promote
-};
-
-static int __init prio_init(void)
-{
- return edp_register_governor(&prio_governor);
-}
-postcore_initcall(prio_init);
diff --git a/drivers/edp/edp_sysfs.c b/drivers/edp/edp_sysfs.c
deleted file mode 100644
index 721a3902a5ee..000000000000
--- a/drivers/edp/edp_sysfs.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include <linux/slab.h>
-#include "edp_internal.h"
-
-static struct kobject edp_kobj;
-
-struct manager_entry {
- struct edp_manager *manager;
- struct kobject kobj;
-};
-
-struct manager_attr {
- struct attribute attr;
- ssize_t (*show)(struct edp_manager *, char *);
- ssize_t (*store)(struct edp_manager *, const char *, size_t);
-};
-
-static ssize_t cap_show(struct edp_manager *m, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", m->max);
-}
-
-static ssize_t remaining_show(struct edp_manager *m, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", m->remaining);
-}
-
-static ssize_t denied_show(struct edp_manager *m, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", m->num_denied);
-}
-
-static ssize_t manager_governor_show(struct edp_manager *m, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%s\n", m->gov ? m->gov->name : "");
-}
-
-static ssize_t manager_governor_store(struct edp_manager *m, const char *s,
- size_t count)
-{
- char name[EDP_NAME_LEN];
- struct edp_governor *gov;
-
- if (!count || count >= sizeof(name))
- return -EINVAL;
-
- memcpy(name, s, count);
- name[count] = 0;
- strim(name);
- gov = edp_find_governor_unlocked(name);
- if (!gov)
- return -EINVAL;
-
- return edp_set_governor_unlocked(m, gov) ?: count;
-}
-
-struct manager_attr attr_cap = __ATTR_RO(cap);
-struct manager_attr attr_remaining = __ATTR_RO(remaining);
-struct manager_attr attr_denied = __ATTR_RO(denied);
-struct manager_attr attr_mgr_gov = __ATTR(governor, 0644,
- manager_governor_show, manager_governor_store);
-
-static struct attribute *manager_attrs[] = {
- &attr_cap.attr,
- &attr_remaining.attr,
- &attr_denied.attr,
- &attr_mgr_gov.attr,
- NULL
-};
-
-static struct edp_manager *to_manager(struct kobject *kobj)
-{
- struct manager_entry *me = container_of(kobj, struct manager_entry,
- kobj);
- return me ? me->manager : NULL;
-}
-
-static ssize_t manager_state_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- ssize_t r;
- struct edp_manager *m;
- struct manager_attr *mattr;
-
- mutex_lock(&edp_lock);
- m = to_manager(kobj);
- mattr = container_of(attr, struct manager_attr, attr);
- r = m && mattr ? mattr->show(m, buf) : -EINVAL;
- mutex_unlock(&edp_lock);
-
- return r;
-}
-
-static ssize_t manager_state_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- ssize_t r;
- struct edp_manager *m;
- struct manager_attr *mattr;
-
- mutex_lock(&edp_lock);
- m = to_manager(kobj);
- mattr = container_of(attr, struct manager_attr, attr);
- r = m && mattr ? mattr->store(m, buf, count) : -EINVAL;
- mutex_unlock(&edp_lock);
-
- return r;
-}
-
-static const struct sysfs_ops manager_sysfs_ops = {
- .show = manager_state_show,
- .store = manager_state_store
-};
-
-static struct kobj_type ktype_manager = {
- .sysfs_ops = &manager_sysfs_ops,
- .default_attrs = manager_attrs
-};
-
-void edp_manager_add_kobject(struct edp_manager *mgr)
-{
- struct manager_entry *me;
-
- me = kzalloc(sizeof(*me), GFP_KERNEL);
- if (!me) {
- pr_err("%s: failed to alloc sysfs manager entry\n",
- mgr->name);
- return;
- }
-
- if (kobject_init_and_add(&me->kobj, &ktype_manager, &edp_kobj,
- mgr->name)) {
- pr_err("%s: failed to init & add sysfs manager entry\n",
- mgr->name);
- kfree(me);
- return;
- }
-
- me->manager = mgr;
- mgr->kobj = &me->kobj;
- kobject_uevent(&me->kobj, KOBJ_ADD);
- return;
-}
-
-void edp_manager_remove_kobject(struct edp_manager *mgr)
-{
- struct manager_entry *me;
-
- if (!mgr->kobj)
- return;
-
- me = container_of(mgr->kobj, struct manager_entry, kobj);
- mgr->kobj = NULL;
- kobject_put(&me->kobj);
- kfree(me);
-}
-
-struct client_entry {
- struct edp_client *client;
- struct kobject kobj;
-};
-
-static ssize_t states_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- unsigned int i;
- int cnt = 0;
- const int sz = sizeof(*c->states) * 3 + 2;
-
- for (i = 0; i < c->num_states && (cnt + sz) < PAGE_SIZE; i++)
- cnt += sprintf(s + cnt, "%s%u", i ? " " : "", c->states[i]);
-
- cnt += sprintf(s + cnt, "\n");
- return cnt;
-}
-
-static ssize_t num_states_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->num_states);
-}
-
-static ssize_t e0_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->states[c->e0_index]);
-}
-
-static ssize_t max_borrowers_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->max_borrowers);
-}
-
-static ssize_t priority_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%d\n", c->priority);
-}
-
-static ssize_t request_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", req_level(c));
-}
-
-/* Allow only updates that are guaranteed to succeed */
-static ssize_t request_store(struct edp_client *c,
- struct edp_client_attribute *attr, const char *s, size_t count)
-{
- unsigned int id;
- int r;
-
- if (sscanf(s, "%u", &id) != 1)
- return -EINVAL;
-
- mutex_lock(&edp_lock);
-
- if (id >= c->num_states) {
- r = -EINVAL;
- goto out;
- }
-
- if (id < c->e0_index && id < req_index(c)) {
- r = -EPERM;
- goto out;
- }
-
- r = edp_update_client_request_unlocked(c, id, NULL);
-
-out:
- mutex_unlock(&edp_lock);
- return r ?: count;
-}
-
-static ssize_t current_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", cur_level(c));
-}
-
-static ssize_t threshold_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->ithreshold);
-}
-
-static ssize_t threshold_store(struct edp_client *c,
- struct edp_client_attribute *attr, const char *s, size_t count)
-{
- unsigned int tv;
- int r;
-
- if (sscanf(s, "%u", &tv) != 1)
- return -EINVAL;
-
- r = edp_update_loan_threshold(c, tv);
- return r ?: count;
-}
-
-static ssize_t borrowers_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->num_borrowers);
-}
-
-static ssize_t loans_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->num_loans);
-}
-
-static ssize_t notify_show(struct edp_client *c,
- struct edp_client_attribute *attr, char *s)
-{
- return scnprintf(s, PAGE_SIZE, "%u\n", c->notify_ui);
-}
-
-static ssize_t notify_store(struct edp_client *c,
- struct edp_client_attribute *attr, const char *s, size_t count)
-{
- unsigned int f;
-
- if (sscanf(s, "%u", &f) != 1)
- return -EINVAL;
- c->notify_ui = f;
- return count;
-}
-
-struct edp_client_attribute attr_states = __ATTR_RO(states);
-struct edp_client_attribute attr_num_states = __ATTR_RO(num_states);
-struct edp_client_attribute attr_e0 = __ATTR_RO(e0);
-struct edp_client_attribute attr_max_borrowers = __ATTR_RO(max_borrowers);
-struct edp_client_attribute attr_priority = __ATTR_RO(priority);
-struct edp_client_attribute attr_request = __ATTR(request, 0644, request_show,
- request_store);
-struct edp_client_attribute attr_threshold = __ATTR(threshold, 0644,
- threshold_show, threshold_store);
-struct edp_client_attribute attr_borrowers = __ATTR_RO(borrowers);
-struct edp_client_attribute attr_loans = __ATTR_RO(loans);
-struct edp_client_attribute attr_current = {
- .attr = { .name = "current", .mode = 0444 },
- .show = current_show
-};
-struct edp_client_attribute attr_notify = __ATTR(notify, 0644, notify_show,
- notify_store);
-
-static struct attribute *client_attrs[] = {
- &attr_states.attr,
- &attr_num_states.attr,
- &attr_e0.attr,
- &attr_max_borrowers.attr,
- &attr_priority.attr,
- &attr_request.attr,
- &attr_current.attr,
- &attr_threshold.attr,
- &attr_borrowers.attr,
- &attr_loans.attr,
- &attr_notify.attr,
- NULL
-};
-
-static struct edp_client *to_client(struct kobject *kobj)
-{
- struct client_entry *ce = container_of(kobj, struct client_entry,
- kobj);
- return ce ? ce->client : NULL;
-}
-
-static ssize_t client_state_show(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- ssize_t r = -EINVAL;
- struct edp_client *c;
- struct edp_client_attribute *cattr;
-
- c = to_client(kobj);
- cattr = container_of(attr, struct edp_client_attribute, attr);
- if (c && cattr) {
- if (cattr->show)
- r = cattr->show(c, cattr, buf);
- }
-
- return r;
-}
-
-static ssize_t client_state_store(struct kobject *kobj,
- struct attribute *attr, const char *buf, size_t count)
-{
- ssize_t r = -EINVAL;
- struct edp_client *c;
- struct edp_client_attribute *cattr;
-
- c = to_client(kobj);
- cattr = container_of(attr, struct edp_client_attribute, attr);
- if (c && cattr) {
- if (cattr->store)
- r = cattr->store(c, cattr, buf, count);
- }
-
- return r;
-}
-
-static const struct sysfs_ops client_sysfs_ops = {
- .show = client_state_show,
- .store = client_state_store
-};
-
-static struct kobj_type ktype_client = {
- .sysfs_ops = &client_sysfs_ops,
- .default_attrs = client_attrs
-};
-
-static void create_driver_attrs(struct edp_client *c)
-{
- struct edp_client_attribute *p;
- int r;
-
- if (!c->attrs)
- return;
-
- for (p = c->attrs; attr_name(*p); p++) {
- r = sysfs_create_file(c->kobj, &p->attr);
- WARN_ON(r);
- }
-}
-
-static void remove_driver_attrs(struct edp_client *c)
-{
- struct edp_client_attribute *p;
-
- if (!c->attrs)
- return;
-
- for (p = c->attrs; attr_name(*p); p++)
- sysfs_remove_file(c->kobj, &p->attr);
-}
-
-void edp_client_add_kobject(struct edp_client *client)
-{
- struct client_entry *ce;
- struct kobject *parent = client->manager->kobj;
-
- if (!parent)
- return;
-
- ce = kzalloc(sizeof(*ce), GFP_KERNEL);
- if (!ce) {
- pr_err("%s: failed to alloc sysfs client entry\n",
- client->name);
- return;
- }
-
- if (kobject_init_and_add(&ce->kobj, &ktype_client, parent,
- client->name)) {
- pr_err("%s: failed to init & add sysfs client entry\n",
- client->name);
- kfree(ce);
- return;
- }
-
- ce->client = client;
- client->kobj = &ce->kobj;
- create_driver_attrs(client);
- kobject_uevent(&ce->kobj, KOBJ_ADD);
-}
-
-void edp_client_remove_kobject(struct edp_client *client)
-{
- struct client_entry *ce;
-
- if (!client->kobj)
- return;
-
- ce = container_of(client->kobj, struct client_entry, kobj);
-
- remove_driver_attrs(client);
- client->kobj = NULL;
- kobject_put(&ce->kobj);
- kfree(ce);
-}
-
-static ssize_t governors_show(struct kobject *kobj, struct attribute *attr,
- char *s)
-{
- struct edp_governor *g;
- int cnt = 0;
-
- mutex_lock(&edp_lock);
-
- list_for_each_entry(g, &edp_governors, link) {
- if (cnt + EDP_NAME_LEN + 2 >= PAGE_SIZE)
- break;
- cnt += sprintf(s + cnt, "%s%s", cnt ? " " : "", g->name);
- }
-
- cnt += sprintf(s + cnt, "\n");
-
- mutex_unlock(&edp_lock);
-
- return cnt;
-}
-
-static const struct sysfs_ops edp_sysfs_ops = {
- .show = governors_show
-};
-
-static struct attribute attr_governors = {
- .name = "governors",
- .mode = 0444
-};
-
-static struct attribute *edp_attrs[] = {
- &attr_governors,
- NULL
-};
-
-static struct kobj_type ktype_edp = {
- .sysfs_ops = &edp_sysfs_ops,
- .default_attrs = edp_attrs
-};
-
-static int __init edp_sysfs_init(void)
-{
- struct kobject *parent = NULL;
-
-#ifdef CONFIG_PM
- parent = power_kobj;
-#endif
-
- return kobject_init_and_add(&edp_kobj, &ktype_edp, parent, "edp");
-}
-postcore_initcall(edp_sysfs_init);
diff --git a/drivers/edp/edp_temporal.c b/drivers/edp/edp_temporal.c
deleted file mode 100644
index 5db123e6e29a..000000000000
--- a/drivers/edp/edp_temporal.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/edp.h>
-#include <linux/slab.h>
-#include "edp_internal.h"
-
-/*
- * This file implements the (1) LRR: least recently requested (2) MRR:
- * most recently requested and (3) RR: round robin governors.
- *
- * Since they are all based on some timestamps, we use a simple list
- * (the 'temporal list') for ordering the clients according to the main
- * selection criteria. This list is maintained in such a way that
- * throttle-victims appear at the tail and promotions are done from the
- * head.
- */
-
-static void throttle(struct edp_client *client);
-
-/* Temporal list is manager specific */
-static int temporal_start(struct edp_manager *m)
-{
- struct list_head *head;
- struct edp_client *c;
-
- head = kzalloc(sizeof(*head), GFP_KERNEL);
- if (!head)
- return -ENOMEM;
-
- INIT_LIST_HEAD(head);
- m->gov_data = head;
-
- list_for_each_entry(c, &m->clients, link) {
- if (req_index(c) < c->e0_index)
- list_add(&c->glnk, head);
- }
-
- return 0;
-}
-
-static void temporal_stop(struct edp_manager *m)
-{
- kfree(m->gov_data);
- m->gov_data = NULL;
-}
-
-/*
- * We need to remember only those clients that can either be throttled
- * or promoted - this way, we have a smaller list.
- */
-static void lrr_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- struct list_head *head;
-
- if (req_index(client) < client->e0_index)
- list_del(&client->glnk);
-
- edp_default_update_request(client, req, throttle);
-
- if (req_index(client) < client->e0_index) {
- head = client->manager->gov_data;
- list_add(&client->glnk, head);
- }
-}
-
-/*
- * We need to remember only those clients that can either be throttled
- * or promoted - this way, we have a smaller list.
- */
-static void mrr_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- struct list_head *head;
-
- if (req_index(client) < client->e0_index)
- list_del(&client->glnk);
-
- edp_default_update_request(client, req, throttle);
-
- if (req_index(client) < client->e0_index) {
- head = client->manager->gov_data;
- list_add_tail(&client->glnk, head);
- }
-}
-
-static void rr_update_request(struct edp_client *client,
- const unsigned int *req)
-{
- struct list_head *head;
-
- /* new entry */
- if (!client->req) {
- head = client->manager->gov_data;
- list_add(&client->glnk, head);
- }
-
- edp_default_update_request(client, req, throttle);
-}
-
-static void temporal_promote(struct edp_manager *m)
-{
- struct list_head *head = m->gov_data;
- struct edp_client *c;
- unsigned int i;
-
- list_for_each_entry(c, head, glnk) {
- if (req_level(c) <= cur_level(c) || !c->notify_promotion)
- continue;
-
- i = edp_promotion_point(c, m->remaining);
- if (i == cur_index(c))
- continue;
-
- m->remaining -= c->states[i] - cur_level(c);
- c->cur = c->states + i;
- if (c->cur == c->req)
- m->num_denied--;
-
- c->notify_promotion(i, c->private_data);
- if (!m->remaining || !m->num_denied)
- return;
- }
-}
-
-#define DEFINE_TEMPORAL_GOV(_gov, _name, _func) \
- struct edp_governor _gov = { \
- .name = _name, \
- .owner = THIS_MODULE, \
- .start = temporal_start, \
- .stop = temporal_stop, \
- .update_request = _func, \
- .update_loans = edp_default_update_loans, \
- .promote = temporal_promote \
- };
-
-static DEFINE_TEMPORAL_GOV(lrr_governor, "least_recent", lrr_update_request);
-static DEFINE_TEMPORAL_GOV(mrr_governor, "most_recent", mrr_update_request);
-static DEFINE_TEMPORAL_GOV(rr_governor, "round_robin", rr_update_request);
-
-static void throttle(struct edp_client *client)
-{
- struct edp_manager *m = client->manager;
- unsigned int required = req_level(client) - cur_level(client);
- struct list_head *head = m->gov_data;
- struct edp_client *n;
- struct edp_client *c;
- unsigned int bal;
-
- bal = m->remaining;
- n = NULL;
-
- list_for_each_entry_reverse(c, head, glnk) {
- if (cur_level(c) > e0_level(c) && c != client) {
- c->gwt = edp_throttling_point(c, required - bal);
- bal += cur_level(c) - c->states[c->gwt];
- n = c;
- if (bal >= required)
- break;
- }
- }
-
- c = n;
- bal = m->remaining;
- if (!c)
- goto finish;
-
- /* use the safe version as we might be re-arraging the list */
- list_for_each_entry_safe_from(c, n, head, glnk) {
- if (cur_level(c) <= e0_level(c) || c == client ||
- c->gwt == cur_index(c))
- continue;
-
- c->throttle(c->gwt, c->private_data);
- bal += cur_level(c) - c->states[c->gwt];
- if (c->cur == c->req)
- m->num_denied++;
- c->cur = c->states + c->gwt;
-
- /* for RR, move this client to the head */
- if (m->gov == &rr_governor)
- list_move(&c->glnk, head);
- if (bal >= required)
- break;
- }
-
-finish:
- m->remaining = bal + cur_level(client);
- client->cur = client->states + edp_promotion_point(client, bal);
- m->remaining -= cur_level(client);
-}
-
-static int __init temporal_init(void)
-{
- int ret = 0;
- int r;
-
- r = edp_register_governor(&lrr_governor);
- if (r) {
- pr_err("least_recent governor registration failed: %d\n", r);
- ret = r;
- }
-
- r = edp_register_governor(&mrr_governor);
- if (r) {
- pr_err("most_recent governor registration failed: %d\n", r);
- ret = r;
- }
-
- r = edp_register_governor(&rr_governor);
- if (r) {
- pr_err("round_robin governor registration failed: %d\n", r);
- ret = r;
- }
-
- return ret;
-}
-postcore_initcall(temporal_init);
diff --git a/drivers/edp/psy_depletion.c b/drivers/edp/psy_depletion.c
deleted file mode 100644
index e31b07609768..000000000000
--- a/drivers/edp/psy_depletion.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/debugfs.h>
-#include <linux/edp.h>
-#include <linux/edpdev.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/power_supply.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-
-#define DEPL_INTERVAL 60000
-
-struct depl_driver {
- struct edp_client client;
- struct psy_depletion_platform_data *pdata;
- struct delayed_work work;
- struct edp_manager *manager;
- struct power_supply *psy;
- bool emulator_mode;
- int capacity;
- int (*get_ocv)(struct depl_driver *drv, unsigned int capacity);
-};
-
-static int depl_psy_get_property(struct depl_driver *drv,
- enum power_supply_property psp, int *val)
-{
- union power_supply_propval pv;
-
- if (!drv->psy)
- return -ENODEV;
- if (drv->psy->get_property(drv->psy, psp, &pv))
- return -EFAULT;
- if (val)
- *val = pv.intval;
- return 0;
-}
-
-static int depl_psy_ocv_from_chip(struct depl_driver *drv,
- unsigned int capacity)
-{
- int val;
- if (depl_psy_get_property(drv, POWER_SUPPLY_PROP_VOLTAGE_OCV, &val))
- return drv->pdata->vsys_min;
- return val;
-}
-
-static int depl_psy_capacity(struct depl_driver *drv)
-{
- int val;
- if (drv->emulator_mode)
- return drv->capacity;
- if (depl_psy_get_property(drv, POWER_SUPPLY_PROP_CAPACITY, &val))
- return 0;
- return val;
-}
-
-static unsigned int depl_psy_temp(struct depl_driver *drv)
-{
- int val;
- if (depl_psy_get_property(drv, POWER_SUPPLY_PROP_TEMP, &val))
- return 25;
- return max(0, val);
-}
-
-static inline unsigned int depl_maximum(struct depl_driver *drv)
-{
- return drv->client.states[0];
-}
-
-/* Given two points (x1, y1) and (x2, y2), find the y coord of x */
-static int depl_interpolate(int x, int x1, int y1, int x2, int y2)
-{
- if (x1 == x2)
- return y1;
- return (y2 * (x - x1) - y1 * (x - x2)) / (x2 - x1);
-}
-
-static int depl_psy_ocv_from_lut(struct depl_driver *drv,
- unsigned int capacity)
-{
- struct psy_depletion_ocv_lut *p;
- struct psy_depletion_ocv_lut *q;
-
- p = drv->pdata->ocv_lut;
-
- while (p->capacity > capacity)
- p++;
-
- if (p == drv->pdata->ocv_lut)
- return p->ocv;
-
- q = p - 1;
-
- return depl_interpolate(capacity, p->capacity, p->ocv, q->capacity,
- q->ocv);
-}
-
-/* Calc RBAT for current capacity (SOC) */
-static int depl_rbat(struct depl_driver *drv, unsigned int capacity)
-{
- struct psy_depletion_rbat_lut *p;
- struct psy_depletion_rbat_lut *q;
- int rbat;
-
- rbat = drv->pdata->r_const;
- p = drv->pdata->rbat_lut;
- if (!p)
- return rbat;
-
- while (p->capacity > capacity)
- p++;
-
- if (p == drv->pdata->rbat_lut)
- return rbat + p->rbat;
-
- q = p - 1;
-
- rbat += depl_interpolate(capacity, p->capacity, p->rbat,
- q->capacity, q->rbat);
- return rbat;
-}
-
-static s64 depl_ibat_possible(struct depl_driver *drv, s64 ocv, s64 rbat)
-{
- return div64_s64(1000 * (ocv - drv->pdata->vsys_min), rbat);
-}
-
-/* Calc IBAT for a given temperature */
-static int depl_ibat(struct depl_driver *drv, unsigned int temp)
-{
- struct psy_depletion_ibat_lut *p;
- struct psy_depletion_ibat_lut *q;
- int ibat;
-
- p = drv->pdata->ibat_lut;
- while (p->ibat && p->temp > temp)
- p++;
-
- if (p == drv->pdata->ibat_lut || !p->ibat)
- return p->ibat;
-
- q = p - 1;
- ibat = depl_interpolate(temp, p->temp, p->ibat, q->temp, q->ibat);
-
- return ibat;
-}
-
-static s64 depl_pbat(s64 ocv, s64 ibat, s64 rbat)
-{
- s64 pbat;
- pbat = ocv - div64_s64(ibat * rbat, 1000);
- pbat = div64_s64(pbat * ibat, 1000000);
- return pbat;
-}
-
-static unsigned int depl_calc(struct depl_driver *drv)
-{
- unsigned int capacity;
- s64 ocv;
- s64 rbat;
- s64 ibat_pos;
- s64 ibat_tbat;
- s64 ibat_lcm;
- s64 pbat_lcm;
- s64 pbat_nom;
- s64 pbat_gain;
- s64 depl;
-
- capacity = depl_psy_capacity(drv);
- if (capacity >= 100)
- return 0;
-
- ocv = drv->get_ocv(drv, capacity);
- rbat = depl_rbat(drv, capacity);
-
- ibat_pos = depl_ibat_possible(drv, ocv, rbat);
- ibat_tbat = depl_ibat(drv, depl_psy_temp(drv));
- ibat_lcm = min(ibat_pos, ibat_tbat);
-
- pbat_lcm = depl_pbat(ocv, ibat_lcm, rbat);
- pbat_nom = depl_pbat(drv->pdata->vcharge, drv->pdata->ibat_nom, rbat);
- pbat_gain = div64_s64(drv->manager->max * 1000, pbat_nom);
-
- depl = drv->manager->max - div64_s64(pbat_gain * pbat_lcm, 1000);
-
- pr_debug("capacity : %u\n", capacity);
- pr_debug("ocv : %lld\n", ocv);
- pr_debug("rbat : %lld\n", rbat);
- pr_debug("ibat_pos : %lld\n", ibat_pos);
- pr_debug("ibat_tbat: %lld\n", ibat_tbat);
- pr_debug("ibat_lcm : %lld\n", ibat_lcm);
- pr_debug("pbat_lcm : %lld\n", pbat_lcm);
- pr_debug("pbat_nom : %lld\n", pbat_nom);
- pr_debug("pbat_gain: %lld\n", pbat_gain);
- pr_debug("depletion: %lld\n", depl);
-
- depl = clamp_t(s64, depl, 0, depl_maximum(drv));
- return depl;
-}
-
-static void depl_update(struct work_struct *work)
-{
- struct depl_driver *drv;
- struct edp_client *c;
- unsigned int depl;
- unsigned int i;
-
- drv = container_of(work, struct depl_driver, work.work);
- c = &drv->client;
- depl = depl_calc(drv);
-
- i = c->num_states - 1;
- while (i && c->states[i] < depl)
- i--;
-
- edp_update_client_request(c, i, NULL);
-
- schedule_delayed_work(to_delayed_work(work),
- msecs_to_jiffies(DEPL_INTERVAL));
-}
-
-/* Nothing to do */
-static void depl_edp_callback(unsigned int new_state, void *priv_data)
-{
-}
-
-static void depl_shutdown(struct platform_device *pdev)
-{
- struct depl_driver *drv = platform_get_drvdata(pdev);
- cancel_delayed_work_sync(&drv->work);
-}
-
-static int depl_suspend(struct platform_device *pdev, pm_message_t state)
-{
- depl_shutdown(pdev);
- return 0;
-}
-
-static int depl_resume(struct platform_device *pdev)
-{
- struct depl_driver *drv = platform_get_drvdata(pdev);
- schedule_delayed_work(&drv->work, 0);
- return 0;
-}
-
-static int depl_init_ocv_reader(struct depl_driver *drv)
-{
- if (!depl_psy_get_property(drv, POWER_SUPPLY_PROP_VOLTAGE_OCV, NULL))
- drv->get_ocv = depl_psy_ocv_from_chip;
- else if (drv->pdata->ocv_lut)
- drv->get_ocv = depl_psy_ocv_from_lut;
- else
- return -ENODEV;
-
- return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static int capacity_set(void *data, u64 val)
-{
- struct depl_driver *drv = data;
-
- drv->capacity = clamp_t(int, val, 0, 100);
- flush_delayed_work(&drv->work);
-
- return 0;
-}
-
-static int capacity_get(void *data, u64 *val)
-{
- struct depl_driver *drv = data;
- *val = drv->capacity;
- return 0;
-}
-
-static int vsysmin_set(void *data, u64 val)
-{
- struct depl_driver *drv = data;
-
- drv->pdata->vsys_min = val;
- flush_delayed_work(&drv->work);
-
- return 0;
-}
-
-static int vsysmin_get(void *data, u64 *val)
-{
- struct depl_driver *drv = data;
- *val = drv->pdata->vsys_min;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(capacity_fops, capacity_get, capacity_set, "%lld\n");
-DEFINE_SIMPLE_ATTRIBUTE(vsysmin_fops, vsysmin_get, vsysmin_set, "%lld\n");
-
-static void init_debug(struct depl_driver *drv)
-{
- struct dentry *d;
-
- if (!drv->client.dentry) {
- WARN_ON(1);
- return;
- }
-
- d = debugfs_create_file("vsys_min", S_IRUGO | S_IWUSR,
- drv->client.dentry, drv, &vsysmin_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-
- if (!drv->emulator_mode)
- return;
-
- d = debugfs_create_file("capacity", S_IRUGO | S_IWUSR,
- drv->client.dentry, drv, &capacity_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-}
-#else
-static inline void init_debug(struct depl_driver *drv) {}
-#endif
-
-static int depl_probe(struct platform_device *pdev)
-{
- struct depl_driver *drv;
- struct edp_manager *m;
- struct edp_client *c;
- int r = -EFAULT;
-
- if (!pdev->dev.platform_data)
- return -EINVAL;
-
- m = edp_get_manager("battery");
- if (!m) {
- dev_err(&pdev->dev, "could not get EDP manager\n");
- return -ENODEV;
- }
-
- drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
- if (!drv)
- return -ENOMEM;
-
- drv->pdata = pdev->dev.platform_data;
- drv->manager = m;
- drv->psy = power_supply_get_by_name(drv->pdata->power_supply);
- if (!drv->psy) {
- if (!drv->pdata->ocv_lut)
- goto fail;
- drv->capacity = 100;
- drv->emulator_mode = true;
- }
-
- r = depl_init_ocv_reader(drv);
- if (r)
- goto fail;
-
- c = &drv->client;
- strncpy(c->name, "depletion", EDP_NAME_LEN - 1);
- c->name[EDP_NAME_LEN - 1] = 0;
- c->priority = EDP_MAX_PRIO;
- c->throttle = depl_edp_callback;
- c->notify_promotion = depl_edp_callback;
- c->states = drv->pdata->states;
- c->num_states = drv->pdata->num_states;
- c->e0_index = drv->pdata->e0_index;
-
- r = edp_register_client(m, c);
- if (r) {
- dev_err(&pdev->dev, "failed to register: %d\n", r);
- goto fail;
- }
-
- platform_set_drvdata(pdev, drv);
- INIT_DEFERRABLE_WORK(&drv->work, depl_update);
- schedule_delayed_work(&drv->work, 0);
-
- init_debug(drv);
-
- return 0;
-
-fail:
- devm_kfree(&pdev->dev, drv);
- return r;
-}
-
-static struct platform_driver depl_driver = {
- .probe = depl_probe,
- .shutdown = depl_shutdown,
- .suspend = depl_suspend,
- .resume = depl_resume,
- .driver = {
- .name = "psy_depletion",
- .owner = THIS_MODULE
- }
-};
-
-static __init int depl_init(void)
-{
- return platform_driver_register(&depl_driver);
-}
-late_initcall(depl_init);
diff --git a/drivers/edp/tegra_core.c b/drivers/edp/tegra_core.c
deleted file mode 100644
index cbde63f58837..000000000000
--- a/drivers/edp/tegra_core.c
+++ /dev/null
@@ -1,697 +0,0 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/clk.h>
-#include <linux/cpu.h>
-#include <linux/debugfs.h>
-#include <linux/edp.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_qos.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/platform_data/tegra_edp.h>
-
-struct freqcap {
- unsigned int cpu;
- unsigned int gpu;
- unsigned int emc;
-};
-
-static unsigned int gpu_high_threshold = 500;
-static unsigned int gpu_window = 80;
-static unsigned int gpu_high_hist;
-static unsigned int gpu_high_count = 2;
-static unsigned int online_cpu_count;
-static bool gpu_busy;
-static unsigned int core_state;
-static unsigned int core_loan;
-static struct tegra_sysedp_corecap *cur_corecap;
-static struct clk *emc_cap_clk;
-static struct clk *gpu_cap_clk;
-static struct pm_qos_request cpufreq_qos;
-static unsigned int cpu_power_offset = 499;
-static unsigned int cpu_power_balance;
-static unsigned int force_gpu_pri;
-static struct delayed_work core_work;
-static unsigned int *core_edp_states;
-static struct tegra_sysedp_platform_data *core_platdata;
-static struct freqcap core_policy;
-static struct freqcap forced_caps;
-static struct freqcap cur_caps;
-static DEFINE_MUTEX(core_lock);
-
-/* To save some cycles from a linear search */
-static unsigned int cpu_lut_match(unsigned int power,
- struct tegra_system_edp_entry *lut, unsigned int lutlen)
-{
- unsigned int fv;
- unsigned int lv;
- unsigned int step;
- unsigned int i;
-
- if (lutlen == 1)
- return 0;
-
- fv = lut[0].power_limit_100mW * 100;
- lv = lut[lutlen - 1].power_limit_100mW * 100;
- step = (lv - fv) / (lutlen - 1);
-
- i = (power - fv + step - 1) / step;
- i = min_t(unsigned int, i, lutlen - 1);
- if (lut[i].power_limit_100mW * 100 >= power)
- return i;
-
- /* Didn't work, search back from the end */
- return lutlen - 1;
-}
-
-static unsigned int get_cpufreq_lim(unsigned int power)
-{
- struct tegra_system_edp_entry *p;
- int i;
-
- i = cpu_lut_match(power, core_platdata->cpufreq_lim,
- core_platdata->cpufreq_lim_size);
- p = core_platdata->cpufreq_lim + i;
-
- for (; i > 0; i--, p--) {
- if (p->power_limit_100mW * 100 <= power)
- break;
- }
-
- WARN_ON(p->power_limit_100mW > power);
- return p->freq_limits[online_cpu_count - 1];
-}
-
-static void pr_caps(struct freqcap *old, struct freqcap *new,
- unsigned int cpu_power)
-{
- if (!IS_ENABLED(CONFIG_DEBUG_KERNEL))
- return;
-
- if (new->cpu == old->cpu &&
- new->gpu == old->gpu &&
- new->emc == old->emc)
- return;
-
- pr_debug("sysedp: ncpus %u, gpupri %d, core %5u mW, "
- "cpu %5u mW %u kHz, gpu %u kHz, emc %u kHz\n",
- online_cpu_count, gpu_busy, cur_corecap->power,
- cpu_power, new->cpu, new->gpu, new->emc);
-}
-
-static void apply_caps(struct tegra_sysedp_devcap *devcap)
-{
- struct freqcap new;
- int r;
-
- core_policy.cpu = get_cpufreq_lim(devcap->cpu_power +
- cpu_power_balance +
- cpu_power_offset);
- core_policy.gpu = devcap->gpufreq;
- core_policy.emc = devcap->emcfreq;
-
- new.cpu = forced_caps.cpu ?: core_policy.cpu;
- new.gpu = forced_caps.gpu ?: core_policy.gpu;
- new.emc = forced_caps.emc ?: core_policy.emc;
-
- if (new.cpu != cur_caps.cpu)
- pm_qos_update_request(&cpufreq_qos, new.cpu);
-
- if (new.emc != cur_caps.emc) {
- r = clk_set_rate(emc_cap_clk, new.emc * 1000);
- WARN_ON(r);
- }
-
- if (new.gpu != cur_caps.gpu) {
- r = clk_set_rate(gpu_cap_clk, new.gpu * 1000);
- WARN_ON(r);
- }
-
- pr_caps(&cur_caps, &new, devcap->cpu_power);
- cur_caps = new;
-}
-
-static inline bool gpu_priority(void)
-{
- return gpu_busy || force_gpu_pri;
-}
-
-static inline struct tegra_sysedp_devcap *get_devcap(void)
-{
- return gpu_priority() ? &cur_corecap->gpupri : &cur_corecap->cpupri;
-}
-
-static void __do_cap_control(void)
-{
- struct tegra_sysedp_devcap *cap;
-
- if (!cur_corecap)
- return;
-
- cap = get_devcap();
- apply_caps(cap);
-}
-
-static void do_cap_control(void)
-{
- mutex_lock(&core_lock);
- __do_cap_control();
- mutex_unlock(&core_lock);
-}
-
-static void update_cur_corecap(void)
-{
- struct tegra_sysedp_corecap *cap;
- unsigned int power;
- int i;
-
- if (!core_platdata)
- return;
-
- power = core_edp_states[core_state] * core_platdata->core_gain / 100;
- power += core_loan;
- i = core_platdata->corecap_size - 1;
- cap = core_platdata->corecap + i;
-
- for (; i >= 0; i--, cap--) {
- if (cap->power <= power) {
- cur_corecap = cap;
- cpu_power_balance = power - cap->power;
- return;
- }
- }
-
- WARN_ON(1);
- cur_corecap = core_platdata->corecap;
-}
-
-static void state_change_cb(unsigned int new_state, void *priv_data)
-{
- mutex_lock(&core_lock);
- core_state = new_state;
- update_cur_corecap();
- __do_cap_control();
- mutex_unlock(&core_lock);
-}
-
-static unsigned int loan_update_cb(unsigned int new_size,
- struct edp_client *lender, void *priv_data)
-{
- mutex_lock(&core_lock);
- core_loan = new_size;
- update_cur_corecap();
- __do_cap_control();
- mutex_unlock(&core_lock);
- return new_size;
-}
-
-static void loan_close_cb(struct edp_client *lender, void *priv_data)
-{
- loan_update_cb(0, lender, priv_data);
-}
-
-static void core_worker(struct work_struct *work)
-{
- if (!gpu_busy)
- do_cap_control();
-}
-
-/*
- * Return true if load was above threshold for at least
- * gpu_high_count number of notifications
- */
-static bool calc_gpu_busy(unsigned int load)
-{
- unsigned int mask;
-
- mask = (1 << gpu_high_count) - 1;
-
- gpu_high_hist <<= 1;
- if (load >= gpu_high_threshold)
- gpu_high_hist |= 1;
-
- return (gpu_high_hist & mask) == mask;
-}
-
-void tegra_edp_notify_gpu_load(unsigned int load)
-{
- bool old;
-
- old = gpu_busy;
- gpu_busy = calc_gpu_busy(load);
-
- if (gpu_busy == old || force_gpu_pri || !core_platdata)
- return;
-
- cancel_delayed_work(&core_work);
-
- if (gpu_busy)
- do_cap_control();
- else
- schedule_delayed_work(&core_work,
- msecs_to_jiffies(gpu_window));
-}
-
-static int tegra_edp_cpu_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- switch (action) {
- case CPU_UP_PREPARE:
- online_cpu_count = num_online_cpus() + 1;
- break;
- case CPU_DEAD:
- online_cpu_count = num_online_cpus();
- break;
- default:
- return NOTIFY_OK;
- }
-
- do_cap_control();
- return NOTIFY_OK;
-}
-
-static struct notifier_block tegra_edp_cpu_nb = {
- .notifier_call = tegra_edp_cpu_notify
-};
-
-static ssize_t core_request_store(struct edp_client *c,
- struct edp_client_attribute *attr, const char *s, size_t count)
-{
- unsigned int id;
- unsigned int approved;
- int r;
-
- if (sscanf(s, "%u", &id) != 1)
- return -EINVAL;
-
- mutex_lock(&core_lock);
-
- r = edp_update_client_request(c, id, &approved);
- if (r)
- goto out;
-
- core_state = approved;
- update_cur_corecap();
- __do_cap_control();
-
-out:
- mutex_unlock(&core_lock);
- return r ?: count;
-}
-
-struct edp_client_attribute core_attrs[] = {
- __ATTR(set_request, 0200, NULL, core_request_store),
- __ATTR_NULL
-};
-
-static struct edp_client core_client = {
- .name = "core",
- .priority = EDP_MIN_PRIO,
- .throttle = state_change_cb,
- .attrs = core_attrs,
- .notify_promotion = state_change_cb,
- .notify_loan_update = loan_update_cb,
- .notify_loan_close = loan_close_cb
-};
-
-#ifdef CONFIG_DEBUG_FS
-static int core_set(void *data, u64 val)
-{
- unsigned int *pdata = data;
- unsigned int old;
-
- old = *pdata;
- *pdata = val;
-
- if (old != *pdata) {
- /* Changes to core_gain require corecap update */
- if (pdata == &core_platdata->core_gain)
- update_cur_corecap();
- do_cap_control();
- }
-
- return 0;
-}
-
-static int core_get(void *data, u64 *val)
-{
- unsigned int *pdata = data;
- *val = *pdata;
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(core_fops, core_get, core_set, "%lld\n");
-
-static void create_attr(const char *name, unsigned int *data)
-{
- struct dentry *d;
-
- d = debugfs_create_file(name, S_IRUGO | S_IWUSR, core_client.dentry,
- data, &core_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-}
-
-static inline void edp_show_2core_cpucaps(struct seq_file *file)
-{
- int i;
- struct tegra_system_edp_entry *p = core_platdata->cpufreq_lim;
-
- seq_printf(file, "%5s %10s %10s\n",
- "Power", "1-core", "2-cores");
-
- for (i = 0; i < core_platdata->cpufreq_lim_size; i++, p++) {
- seq_printf(file, "%5d %10u %10u\n",
- p->power_limit_100mW * 100,
- p->freq_limits[0],
- p->freq_limits[1]);
- }
-}
-
-static inline void edp_show_4core_cpucaps(struct seq_file *file)
-{
- int i;
- struct tegra_system_edp_entry *p = core_platdata->cpufreq_lim;
-
- seq_printf(file, "%5s %10s %10s %10s %10s\n",
- "Power", "1-core", "2-cores", "3-cores", "4-cores");
-
- for (i = 0; i < core_platdata->cpufreq_lim_size; i++, p++) {
- seq_printf(file, "%5d %10u %10u %10u %10u\n",
- p->power_limit_100mW * 100,
- p->freq_limits[0],
- p->freq_limits[1],
- p->freq_limits[2],
- p->freq_limits[3]);
- }
-}
-
-static int cpucaps_show(struct seq_file *file, void *data)
-{
- unsigned int max_nr_cpus = num_possible_cpus();
-
- if (core_platdata ? !core_platdata->cpufreq_lim : true)
- return -ENODEV;
-
- if (max_nr_cpus == 2)
- edp_show_2core_cpucaps(file);
- else if (max_nr_cpus == 4)
- edp_show_4core_cpucaps(file);
-
- return 0;
-}
-
-static int corecaps_show(struct seq_file *file, void *data)
-{
- int i;
- struct tegra_sysedp_corecap *p;
- struct tegra_sysedp_devcap *c;
- struct tegra_sysedp_devcap *g;
-
- if (core_platdata ? !core_platdata->corecap : true)
- return -ENODEV;
-
- p = core_platdata->corecap;
-
- seq_printf(file, "%s %s { %s %9s %9s } %s { %s %9s %9s }\n",
- "E-state",
- "CPU-pri", "CPU-mW", "GPU-kHz", "EMC-kHz",
- "GPU-pri", "CPU-mW", "GPU-kHz", "EMC-kHz");
-
- for (i = 0; i < core_platdata->corecap_size; i++, p++) {
- c = &p->cpupri;
- g = &p->gpupri;
- seq_printf(file, "%7u %16u %9u %9u %18u %9u %9u\n",
- p->power,
- c->cpu_power, c->gpufreq, c->emcfreq,
- g->cpu_power, g->gpufreq, g->emcfreq);
- }
-
- return 0;
-}
-
-static int status_show(struct seq_file *file, void *data)
-{
- mutex_lock(&core_lock);
-
- seq_printf(file, "cpus online : %u\n", online_cpu_count);
- seq_printf(file, "gpu priority: %u\n", gpu_priority());
- seq_printf(file, "E-state : %u\n", core_edp_states[core_state]);
- seq_printf(file, "gain : %u\n", core_platdata->core_gain);
- seq_printf(file, "loan : %u\n", core_loan);
- seq_printf(file, "core cap : %u\n", cur_corecap->power);
- seq_printf(file, "cpu balance : %u\n", cpu_power_balance);
- seq_printf(file, "cpu offset : %u\n", cpu_power_offset);
- seq_printf(file, "cpu power : %u\n", get_devcap()->cpu_power +
- cpu_power_balance + cpu_power_offset);
- seq_printf(file, "cpu cap : %u kHz\n", cur_caps.cpu);
- seq_printf(file, "gpu cap : %u kHz\n", cur_caps.gpu);
- seq_printf(file, "emc cap : %u kHz\n", cur_caps.emc);
-
- mutex_unlock(&core_lock);
- return 0;
-}
-
-static int longattr_open(struct inode *inode, struct file *file)
-{
- return single_open(file, inode->i_private, NULL);
-}
-
-static const struct file_operations longattr_fops = {
- .open = longattr_open,
- .read = seq_read,
-};
-
-static void create_longattr(const char *name,
- int (*show)(struct seq_file *, void *))
-{
- struct dentry *d;
-
- d = debugfs_create_file(name, S_IRUGO, core_client.dentry, show,
- &longattr_fops);
- WARN_ON(IS_ERR_OR_NULL(d));
-}
-
-static void init_debug(void)
-{
- if (!core_client.dentry) {
- WARN_ON(1);
- return;
- }
-
- create_attr("cpu_offset", &cpu_power_offset);
- create_attr("favor_gpu", &force_gpu_pri);
- create_attr("gpu_threshold", &gpu_high_threshold);
- create_attr("force_cpu", &forced_caps.cpu);
- create_attr("force_gpu", &forced_caps.gpu);
- create_attr("force_emc", &forced_caps.emc);
- create_attr("gpu_window", &gpu_window);
- create_attr("gain", &core_platdata->core_gain);
- create_attr("gpu_high_count", &gpu_high_count);
-
- create_longattr("corecaps", corecaps_show);
- create_longattr("cpucaps", cpucaps_show);
- create_longattr("status", status_show);
-}
-#else
-static inline void init_debug(void) {}
-#endif
-
-static void register_loan(struct tegra_sysedp_platform_data *pdata)
-{
- struct edp_client *c;
- int r;
-
- if (!pdata->bbc)
- return;
-
- c = edp_get_client(pdata->bbc);
- if (!c) {
- pr_info("Could not access modem EDP client\n");
- return;
- }
-
- r = edp_register_loan(c, &core_client);
- WARN_ON(r && r != -EEXIST);
-}
-
-/* Power without gain */
-static unsigned int to_base_power(unsigned int power,
- struct tegra_sysedp_platform_data *pdata)
-{
- return (power * 100 + pdata->core_gain - 1) / pdata->core_gain;
-}
-
-static unsigned int get_num_states(
- struct tegra_sysedp_platform_data *pdata)
-{
- unsigned int power = 0;
- unsigned int num = 0;
- unsigned int i;
-
- for (i = 0; i < pdata->corecap_size; i++) {
- if (pdata->corecap[i].power != power) {
- power = pdata->corecap[i].power;
- num++;
- }
- }
-
- return num;
-}
-
-static void get_states(struct tegra_sysedp_platform_data *pdata,
- unsigned int num, unsigned int *states)
-{
- unsigned int power = 0;
- unsigned int e0i = 0;
- unsigned int i;
-
- for (i = 0; i < pdata->corecap_size; i++) {
- if (pdata->corecap[i].power == power)
- continue;
-
- power = to_base_power(pdata->corecap[i].power, pdata);
- states[num - e0i - 1] = power;
- e0i++;
- }
-}
-
-static unsigned int initial_req(struct edp_client *client,
- struct tegra_sysedp_platform_data *pdata)
-{
- int i;
- unsigned int watts;
-
- watts = to_base_power(pdata->init_req_watts, pdata);
-
- for (i = 0; i < client->num_states; i++) {
- if (client->states[i] == watts)
- return i;
- }
-
- WARN_ON(1);
- return 0;
-}
-
-static int init_client(struct tegra_sysedp_platform_data *pdata)
-{
- struct edp_manager *m;
- unsigned int cnt;
- unsigned int ei;
- int r;
-
- m = edp_get_manager("battery");
- if (!m)
- return -ENODEV;
-
- cnt = get_num_states(pdata);
- if (!cnt)
- return -EINVAL;
-
- core_edp_states = kzalloc(sizeof(*core_edp_states) * cnt, GFP_KERNEL);
- if (!core_edp_states)
- return -ENOMEM;
-
- get_states(pdata, cnt, core_edp_states);
-
- core_client.states = core_edp_states;
- core_client.num_states = cnt;
- core_client.e0_index = cnt - 1;
- core_client.private_data = &core_client;
-
- r = edp_register_client(m, &core_client);
- if (r)
- goto fail;
-
- ei = initial_req(&core_client, pdata);
- r = edp_update_client_request(&core_client, ei, &core_state);
- if (r)
- return r;
-
- register_loan(pdata);
- return 0;
-
-fail:
- kfree(core_edp_states);
- core_edp_states = NULL;
- return r;
-}
-
-static int init_clks(void)
-{
- emc_cap_clk = clk_get_sys("battery_edp", "emc");
- if (IS_ERR(emc_cap_clk))
- return -ENODEV;
-
- gpu_cap_clk = clk_get_sys("battery_edp", "gpu");
- if (IS_ERR(gpu_cap_clk)) {
- clk_put(emc_cap_clk);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static int tegra_sysedp_probe(struct platform_device *pdev)
-{
- int r;
-
- if (!pdev->dev.platform_data)
- return -EINVAL;
-
- online_cpu_count = num_online_cpus();
- INIT_DELAYED_WORK(&core_work, core_worker);
- pm_qos_add_request(&cpufreq_qos, PM_QOS_CPU_FREQ_MAX,
- PM_QOS_CPU_FREQ_MAX_DEFAULT_VALUE);
-
- r = register_cpu_notifier(&tegra_edp_cpu_nb);
- if (r)
- return r;
-
- r = init_clks();
- if (r)
- return r;
-
- r = init_client(pdev->dev.platform_data);
- if (r)
- return r;
-
- mutex_lock(&core_lock);
- core_platdata = pdev->dev.platform_data;
- update_cur_corecap();
- __do_cap_control();
- mutex_unlock(&core_lock);
-
- init_debug();
-
- return 0;
-}
-
-static struct platform_driver tegra_sysedp_driver = {
- .probe = tegra_sysedp_probe,
- .driver = {
- .owner = THIS_MODULE,
- .name = "tegra_sysedp"
- }
-};
-
-static __init int tegra_sysedp_init(void)
-{
- return platform_driver_register(&tegra_sysedp_driver);
-}
-late_initcall(tegra_sysedp_init);