cpuquiet: Fix cpuquiet for k3.4
[firefly-linux-kernel-4.4.55.git] / drivers / cpuquiet / governor.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
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that 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 along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16  *
17  */
18
19 #include <linux/mutex.h>
20 #include <linux/module.h>
21 #include <linux/cpuquiet.h>
22
23 #include "cpuquiet.h"
24
25 LIST_HEAD(cpuquiet_governors);
26 struct cpuquiet_governor *cpuquiet_curr_governor;
27
28 struct cpuquiet_governor *cpuquiet_get_first_governor(void)
29 {
30         if (!list_empty(&cpuquiet_governors))
31                 return list_entry(cpuquiet_governors.next,
32                                         struct cpuquiet_governor,
33                                         governor_list);
34         else
35                 return NULL;
36 }
37
38 struct cpuquiet_governor *cpuquiet_find_governor(const char *str)
39 {
40         struct cpuquiet_governor *gov;
41
42         list_for_each_entry(gov, &cpuquiet_governors, governor_list)
43                 if (!strnicmp(str, gov->name, CPUQUIET_NAME_LEN))
44                         return gov;
45
46         return NULL;
47 }
48
49 int cpuquiet_switch_governor(struct cpuquiet_governor *gov)
50 {
51         int err = 0;
52
53         if (cpuquiet_curr_governor) {
54                 if (cpuquiet_curr_governor->stop)
55                         cpuquiet_curr_governor->stop();
56                 module_put(cpuquiet_curr_governor->owner);
57         }
58
59         cpuquiet_curr_governor = gov;
60
61         if (gov) {
62                 if (!try_module_get(cpuquiet_curr_governor->owner))
63                         return -EINVAL;
64                 if (gov->start)
65                         err = gov->start();
66                 if (!err)
67                         cpuquiet_curr_governor = gov;
68         }
69
70         return err;
71 }
72
73 int cpuquiet_register_governor(struct cpuquiet_governor *gov)
74 {
75         int ret = -EEXIST;
76
77         if (!gov)
78                 return -EINVAL;
79
80         mutex_lock(&cpuquiet_lock);
81         if (cpuquiet_find_governor(gov->name) == NULL) {
82                 ret = 0;
83                 list_add_tail(&gov->governor_list, &cpuquiet_governors);
84                 if (!cpuquiet_curr_governor && cpuquiet_get_driver())
85                         cpuquiet_switch_governor(gov);
86         }
87         mutex_unlock(&cpuquiet_lock);
88
89         return ret;
90 }
91
92 void cpuquiet_unregister_governor(struct cpuquiet_governor *gov)
93 {
94         if (!gov)
95                 return;
96
97         mutex_lock(&cpuquiet_lock);
98         if (cpuquiet_curr_governor == gov)
99                 cpuquiet_switch_governor(NULL);
100         list_del(&gov->governor_list);
101         mutex_unlock(&cpuquiet_lock);
102 }
103
104 void cpuquiet_device_busy(void)
105 {
106         if (cpuquiet_curr_governor &&
107                         cpuquiet_curr_governor->device_busy_notification)
108                 cpuquiet_curr_governor->device_busy_notification();
109 }
110
111 void cpuquiet_device_free(void)
112 {
113         if (cpuquiet_curr_governor &&
114                         cpuquiet_curr_governor->device_free_notification)
115                 cpuquiet_curr_governor->device_free_notification();
116 }