~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/lib/powercap.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *  (C) 2016 SUSE Software Solutions GmbH
  4  *           Thomas Renninger <trenn@suse.de>
  5  */
  6 
  7 #include <sys/types.h>
  8 #include <sys/stat.h>
  9 #include <unistd.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 #include <fcntl.h>
 13 #include <stdio.h>
 14 #include <dirent.h>
 15 
 16 #include "powercap.h"
 17 
 18 static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
 19 {
 20         int fd;
 21         ssize_t numread;
 22 
 23         fd = open(path, O_RDONLY);
 24         if (fd == -1)
 25                 return 0;
 26 
 27         numread = read(fd, buf, buflen - 1);
 28         if (numread < 1) {
 29                 close(fd);
 30                 return 0;
 31         }
 32 
 33         buf[numread] = '\0';
 34         close(fd);
 35 
 36         return (unsigned int) numread;
 37 }
 38 
 39 static int sysfs_get_enabled(char *path, int *mode)
 40 {
 41         int fd;
 42         char yes_no;
 43         int ret = 0;
 44 
 45         *mode = 0;
 46 
 47         fd = open(path, O_RDONLY);
 48         if (fd == -1) {
 49                 ret = -1;
 50                 goto out;
 51         }
 52 
 53         if (read(fd, &yes_no, 1) != 1) {
 54                 ret = -1;
 55                 goto out_close;
 56         }
 57 
 58         if (yes_no == '1') {
 59                 *mode = 1;
 60                 goto out_close;
 61         } else if (yes_no == '') {
 62                 goto out_close;
 63         } else {
 64                 ret = -1;
 65                 goto out_close;
 66         }
 67 out_close:
 68         close(fd);
 69 out:
 70         return ret;
 71 }
 72 
 73 int powercap_get_enabled(int *mode)
 74 {
 75         char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/intel-rapl/enabled";
 76 
 77         return sysfs_get_enabled(path, mode);
 78 }
 79 
 80 /*
 81  * TODO: implement function. Returns dummy 0 for now.
 82  */
 83 int powercap_set_enabled(int mode)
 84 {
 85         return 0;
 86 }
 87 
 88 /*
 89  * Hardcoded, because rapl is the only powercap implementation
 90 - * this needs to get more generic if more powercap implementations
 91  * should show up
 92  */
 93 int powercap_get_driver(char *driver, int buflen)
 94 {
 95         char file[SYSFS_PATH_MAX] = PATH_TO_RAPL;
 96 
 97         struct stat statbuf;
 98 
 99         if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
100                 driver = "";
101                 return -1;
102         } else if (buflen > 10) {
103                 strcpy(driver, "intel-rapl");
104                 return 0;
105         } else
106                 return -1;
107 }
108 
109 enum powercap_get64 {
110         GET_ENERGY_UJ,
111         GET_MAX_ENERGY_RANGE_UJ,
112         GET_POWER_UW,
113         GET_MAX_POWER_RANGE_UW,
114         MAX_GET_64_FILES
115 };
116 
117 static const char *powercap_get64_files[MAX_GET_64_FILES] = {
118         [GET_POWER_UW] = "power_uw",
119         [GET_MAX_POWER_RANGE_UW] = "max_power_range_uw",
120         [GET_ENERGY_UJ] = "energy_uj",
121         [GET_MAX_ENERGY_RANGE_UJ] = "max_energy_range_uj",
122 };
123 
124 static int sysfs_powercap_get64_val(struct powercap_zone *zone,
125                                       enum powercap_get64 which,
126                                       uint64_t *val)
127 {
128         char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/";
129         int ret;
130         char buf[MAX_LINE_LEN];
131 
132         strcat(file, zone->sys_name);
133         strcat(file, "/");
134         strcat(file, powercap_get64_files[which]);
135 
136         ret = sysfs_read_file(file, buf, MAX_LINE_LEN);
137         if (ret < 0)
138                 return ret;
139         if (ret == 0)
140                 return -1;
141 
142         *val = strtoll(buf, NULL, 10);
143         return 0;
144 }
145 
146 int powercap_get_max_energy_range_uj(struct powercap_zone *zone, uint64_t *val)
147 {
148         return sysfs_powercap_get64_val(zone, GET_MAX_ENERGY_RANGE_UJ, val);
149 }
150 
151 int powercap_get_energy_uj(struct powercap_zone *zone, uint64_t *val)
152 {
153         return sysfs_powercap_get64_val(zone, GET_ENERGY_UJ, val);
154 }
155 
156 int powercap_get_max_power_range_uw(struct powercap_zone *zone, uint64_t *val)
157 {
158         return sysfs_powercap_get64_val(zone, GET_MAX_POWER_RANGE_UW, val);
159 }
160 
161 int powercap_get_power_uw(struct powercap_zone *zone, uint64_t *val)
162 {
163         return sysfs_powercap_get64_val(zone, GET_POWER_UW, val);
164 }
165 
166 int powercap_zone_get_enabled(struct powercap_zone *zone, int *mode)
167 {
168         char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
169 
170         if ((strlen(PATH_TO_POWERCAP) + strlen(zone->sys_name)) +
171             strlen("/enabled") + 1 >= SYSFS_PATH_MAX)
172                 return -1;
173 
174         strcat(path, "/");
175         strcat(path, zone->sys_name);
176         strcat(path, "/enabled");
177 
178         return sysfs_get_enabled(path, mode);
179 }
180 
181 int powercap_zone_set_enabled(struct powercap_zone *zone, int mode)
182 {
183         /* To be done if needed */
184         return 0;
185 }
186 
187 
188 int powercap_read_zone(struct powercap_zone *zone)
189 {
190         struct dirent *dent;
191         DIR *zone_dir;
192         char sysfs_dir[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
193         struct powercap_zone *child_zone;
194         char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
195         int i, ret = 0;
196         uint64_t val = 0;
197 
198         strcat(sysfs_dir, "/");
199         strcat(sysfs_dir, zone->sys_name);
200 
201         zone_dir = opendir(sysfs_dir);
202         if (zone_dir == NULL)
203                 return -1;
204 
205         strcat(file, "/");
206         strcat(file, zone->sys_name);
207         strcat(file, "/name");
208         sysfs_read_file(file, zone->name, MAX_LINE_LEN);
209         if (zone->parent)
210                 zone->tree_depth = zone->parent->tree_depth + 1;
211         ret = powercap_get_energy_uj(zone, &val);
212         if (ret == 0)
213                 zone->has_energy_uj = 1;
214         ret = powercap_get_power_uw(zone, &val);
215         if (ret == 0)
216                 zone->has_power_uw = 1;
217 
218         while ((dent = readdir(zone_dir)) != NULL) {
219                 struct stat st;
220 
221                 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
222                         continue;
223 
224                 if (stat(dent->d_name, &st) != 0 || !S_ISDIR(st.st_mode))
225                         if (fstatat(dirfd(zone_dir), dent->d_name, &st, 0) < 0)
226                                 continue;
227 
228                 if (strncmp(dent->d_name, "intel-rapl:", 11) != 0)
229                         continue;
230 
231                 child_zone = calloc(1, sizeof(struct powercap_zone));
232                 if (child_zone == NULL)
233                         return -1;
234                 for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
235                         if (zone->children[i] == NULL) {
236                                 zone->children[i] = child_zone;
237                                 break;
238                         }
239                         if (i == POWERCAP_MAX_CHILD_ZONES - 1) {
240                                 free(child_zone);
241                                 fprintf(stderr, "Reached POWERCAP_MAX_CHILD_ZONES %d\n",
242                                        POWERCAP_MAX_CHILD_ZONES);
243                                 return -1;
244                         }
245                 }
246                 strcpy(child_zone->sys_name, zone->sys_name);
247                 strcat(child_zone->sys_name, "/");
248                 strcat(child_zone->sys_name, dent->d_name);
249                 child_zone->parent = zone;
250                 if (zone->tree_depth >= POWERCAP_MAX_TREE_DEPTH) {
251                         fprintf(stderr, "Maximum zone hierarchy depth[%d] reached\n",
252                                 POWERCAP_MAX_TREE_DEPTH);
253                         ret = -1;
254                         break;
255                 }
256                 powercap_read_zone(child_zone);
257         }
258         closedir(zone_dir);
259         return ret;
260 }
261 
262 struct powercap_zone *powercap_init_zones(void)
263 {
264         int enabled;
265         struct powercap_zone *root_zone;
266         int ret;
267         char file[SYSFS_PATH_MAX] = PATH_TO_RAPL "/enabled";
268 
269         ret = sysfs_get_enabled(file, &enabled);
270 
271         if (ret)
272                 return NULL;
273 
274         if (!enabled)
275                 return NULL;
276 
277         root_zone = calloc(1, sizeof(struct powercap_zone));
278         if (!root_zone)
279                 return NULL;
280 
281         strcpy(root_zone->sys_name, "intel-rapl/intel-rapl:0");
282 
283         powercap_read_zone(root_zone);
284 
285         return root_zone;
286 }
287 
288 /* Call function *f on the passed zone and all its children */
289 
290 int powercap_walk_zones(struct powercap_zone *zone,
291                         int (*f)(struct powercap_zone *zone))
292 {
293         int i, ret;
294 
295         if (!zone)
296                 return -1;
297 
298         ret = f(zone);
299         if (ret)
300                 return ret;
301 
302         for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
303                 if (zone->children[i] != NULL)
304                         powercap_walk_zones(zone->children[i], f);
305         }
306         return 0;
307 }
308 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php