Revert "ARM: tegra: tegratab: dummy change"
[linux-2.6.git] / drivers / edp / edp_priority.c
1 /*
2  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/edp.h>
20 #include "edp_internal.h"
21
22 /*
23  * Calculate the approvable E-state for the requesting client.
24  * Non-negative E-state requests are always approved.  A (higher)
25  * negative E-state request is approved only if lower priority clients
26  * can be throttled (at most to E0) in order to recover the necessary
27  * power deficit. If this can not be met, a lower E-state is approved
28  * (at least E0).
29  */
30 static unsigned int approvable_req(struct edp_client *client)
31 {
32         struct edp_manager *m = client->manager;
33         unsigned int old = cur_level(client);
34         unsigned int deficit = *client->req - old;
35         unsigned int recoverable = m->remaining;
36         unsigned int i = req_index(client);
37         struct edp_client *p = client;
38
39         if (i >= client->e0_index)
40                 return i;
41
42         list_for_each_entry_continue(p, &m->clients, link) {
43                 if (cur_level(p) > e0_level(p)) {
44                         recoverable += cur_level(p) - e0_level(p);
45                         if (recoverable >= deficit)
46                                 return i;
47                 }
48         }
49
50         while (i < client->e0_index && recoverable < deficit) {
51                 i++;
52                 deficit = client->states[i] - old;
53         }
54
55         return i;
56 }
57
58 static void throttle(struct edp_client *client)
59 {
60         unsigned int ar;
61         unsigned int deficit;
62         struct edp_client *p;
63         struct edp_manager *m = client->manager;
64         unsigned int pledged = m->remaining;
65         unsigned int recovered = m->remaining;
66
67         /* Check if we can satisfy the request as it is */
68         ar = approvable_req(client);
69         deficit = client->states[ar] - cur_level(client);
70         if (m->remaining >= deficit)
71                 goto ret;
72
73         /*
74          * We do the throttling in two steps: first we will identify and
75          * mark the clients starting from the lower priority ones. We
76          * stop when we find the highest priority client that should be
77          * throttled.
78          */
79         list_for_each_entry_reverse(p, &m->clients, link) {
80                 if (p == client || cur_level(p) <= e0_level(p))
81                         continue;
82
83                 p->gwt = edp_throttling_point(p, deficit - pledged);
84                 pledged += cur_level(p) - p->states[p->gwt];
85                 if (pledged >= deficit)
86                         break;
87         }
88
89         /*
90          * By now, we are guaranteed to have at least the adjusted
91          * deficit - may be even more.
92          */
93         WARN_ON(pledged < deficit);
94
95         /*
96          * We now do the actual throttling starting from where we stoped
97          * in step 1 and going in the opposite direction. This way we
98          * can avoid situations where clients are throttled needlessly
99          * and promoted back immediately.
100          */
101         list_for_each_entry_from(p, &m->clients, link) {
102                 if (p == client || cur_level(p) <= e0_level(p) ||
103                                 p->gwt == cur_index(p))
104                         continue;
105
106                 p->throttle(p->gwt, p->private_data);
107                 recovered += cur_level(p) - p->states[p->gwt];
108                 if (p->cur == p->req)
109                         m->num_denied++;
110
111                 p->cur = p->states + p->gwt;
112                 if (recovered >= deficit)
113                         break;
114         }
115
116 ret:
117         client->cur = client->states + ar;
118         m->remaining = recovered - deficit;
119 }
120
121 static void prio_update_request(struct edp_client *client,
122                 const unsigned int *req)
123 {
124         edp_default_update_request(client, req, throttle);
125 }
126
127 static void prio_promote(struct edp_manager *mgr)
128 {
129         struct edp_client *p;
130         unsigned int delta;
131         unsigned int pp;
132
133         list_for_each_entry(p, &mgr->clients, link) {
134                 if (req_level(p) <= cur_level(p) || !p->notify_promotion)
135                         continue;
136
137                 delta = req_level(p) - cur_level(p);
138                 if (delta > mgr->remaining)
139                         delta = mgr->remaining;
140
141                 pp = edp_promotion_point(p, delta);
142                 if (pp == cur_index(p))
143                         continue;
144
145                 mgr->remaining -= p->states[pp] - cur_level(p);
146                 p->cur = p->states + pp;
147
148                 if (p->cur == p->req)
149                         mgr->num_denied--;
150
151                 p->notify_promotion(pp, p->private_data);
152                 if (!mgr->remaining || !mgr->num_denied)
153                         return;
154         }
155 }
156
157 static struct edp_governor prio_governor = {
158         .name = "priority",
159         .owner = THIS_MODULE,
160         .update_request = prio_update_request,
161         .update_loans = edp_default_update_loans,
162         .promote = prio_promote
163 };
164
165 static int __init prio_init(void)
166 {
167         return edp_register_governor(&prio_governor);
168 }
169 postcore_initcall(prio_init);