1
/*******************************************************************************
2
* Copyright (C) 2010, Linaro Limited.
4
* This file is part of PowerDebug.
6
* All rights reserved. This program and the accompanying materials
7
* are made available under the terms of the Eclipse Public License v1.0
8
* which accompanies this distribution, and is available at
9
* http://www.eclipse.org/legal/epl-v10.html
12
* Amit Arora <amit.arora@linaro.org> (IBM Corporation)
13
* - initial API and implementation
14
*******************************************************************************/
16
#include "powerdebug.h"
19
static char clk_dir_path[PATH_MAX];
20
static char clk_name[NAME_MAX];
21
static int bold[MAX_LINES];
23
int init_clock_details(void)
25
char *path = debugfs_locate_mpoint();
29
strcpy(clk_dir_path, path);
32
create_selectedwindow();
33
sprintf(clock_lines[0], "Unable to locate debugfs "
34
"mount point. Mount debugfs "
36
print_one_clock(0, clock_lines[0], 1, 0);
37
old_clock_line_no = 1;
40
fprintf(stderr, "powerdebug: Unable to locate debugfs "
41
"mount point. Mount debugfs and try "
46
sprintf(clk_dir_path, "%s/clock", clk_dir_path);
47
//strcpy(clk_dir_path, "/debug/clock"); // Hardcoded for testing..
48
if (stat(clk_dir_path, &buf)) {
50
create_selectedwindow();
51
sprintf(clock_lines[0], "Unable to find clock tree"
52
" information at %s.\n", clk_dir_path);
53
print_one_clock(0, clock_lines[0], 1, 0);
54
old_clock_line_no = 1;
57
fprintf(stderr, "powerdebug: Unable to find clock tree"
58
" information at %s.\n", clk_dir_path);
66
int get_int_from(char *file)
69
char result[NAME_MAX];
72
filep = fopen(file, "r");
75
return -1; //TBD : What should we return on failure, here ?
77
ret = fscanf(filep, "%s", result);
83
void find_parents_for_clock(char *clkname, int complete)
91
strcat(name, clkname);
92
sprintf(str, "Enter Clock Name : %s\n", name);
93
print_one_clock(2, str, 1, 0);
96
sprintf(name, "Parents for \"%s\" Clock : \n", clkname);
97
print_one_clock(0, name, 1, 1);
98
dump_all_parents(clkname);
101
int read_and_print_clock_info(int verbose, int hrow, int selected)
103
print_one_clock(0, "Reading Clock Tree ...", 1, 1);
105
if (!old_clock_line_no || selected == REFRESH_WINDOW) {
106
destroy_clocks_info();
107
read_clock_info(clk_dir_path);
110
if (!clocks_info->num_children) {
111
fprintf(stderr, "powerdebug: No clocks found. Exiting..\n");
115
if (selected == CLOCK_SELECTED)
120
print_clock_info(verbose, hrow, selected);
121
hrow = (hrow < old_clock_line_no) ? hrow : old_clock_line_no - 1;
126
int calc_delta_screen_size(int hrow)
128
if (hrow >= (maxy - 3))
129
return hrow - (maxy - 4);
134
void print_clock_info(int verbose, int hrow, int selected)
136
int i, count = 0, delta;
140
print_clock_header();
142
for (i = 0; i < clocks_info->num_children; i++)
143
add_clock_details_recur(clocks_info->children[i],
146
delta = calc_delta_screen_size(hrow);
148
while (clock_lines[count + delta] &&
149
strcmp(clock_lines[count + delta], "")) {
154
print_one_clock(count - delta, clock_lines[count + delta],
155
bold[count + delta], (hrow == (count + delta)));
159
old_clock_line_no = clock_line_no;
163
void prepare_name_str(char *namestr, struct clock_info *clock)
168
if (clock->level > 1)
169
for (i = 0; i < (clock->level - 1); i++)
170
strcat(namestr, " ");
171
strcat(namestr, clock->name);
174
void add_clock_details_recur(struct clock_info *clock, int hrow, int selected)
180
double drate = (double)clock->rate;
182
if (drate > 1000 && drate < 1000000) {
186
if (drate > 1000000) {
191
bold[clock_line_no] = 1;
193
bold[clock_line_no] = 0;
195
sprintf(rate_str, "%.2f %s", drate, unit);
196
prepare_name_str(name_str, clock);
197
sprintf(clock_lines[clock_line_no++], "%-55s %-4d %-12s %-12d %-12d",
198
name_str, clock->flags, rate_str, clock->usecount,
199
clock->num_children);
201
if (selected && (hrow == (clock_line_no - 1))) {
203
collapse_all_subclocks(clock);
209
if (clock->expanded && clock->num_children)
210
for (i = 0; i < clock->num_children; i++)
211
add_clock_details_recur(clock->children[i],
213
strcpy(clock_lines[clock_line_no], "");
216
void collapse_all_subclocks(struct clock_info *clock)
221
if (clock->num_children)
222
for (i = 0; i < clock->num_children; i++)
223
collapse_all_subclocks(clock->children[i]);
226
void destroy_clocks_info(void)
233
if (clocks_info->num_children) {
234
for (i = (clocks_info->num_children - 1); i >= 0 ; i--) {
235
destroy_clocks_info_recur(clocks_info->children[i]);
237
free(clocks_info->children);
238
clocks_info->children = NULL;
242
clocks_info->num_children = 0;
247
void destroy_clocks_info_recur(struct clock_info *clock)
251
if (clock && clock->num_children) {
252
for (i = (clock->num_children - 1); i >= 0; i--) {
254
destroy_clocks_info_recur(clock->children[i]);
256
free(clock->children);
257
clock->children = NULL;
258
clock->num_children = 0;
264
void read_and_dump_clock_info_one(char *clk)
266
printf("\nParents for \"%s\" Clock :\n\n", clk);
267
read_clock_info(clk_dir_path);
268
dump_all_parents(clk);
272
void read_and_dump_clock_info(int verbose)
275
printf("\nClock Tree :\n");
276
printf("**********\n");
277
read_clock_info(clk_dir_path);
278
dump_clock_info(clocks_info, 1, 1);
282
void read_clock_info(char *clkpath)
286
char filename[NAME_MAX], clockname[NAME_MAX];
287
struct clock_info *child;
288
struct clock_info *cur;
290
dir = opendir(clkpath);
294
clocks_info = (struct clock_info *)malloc(sizeof(struct clock_info));
295
memset(clocks_info, 0, sizeof(clocks_info));
296
strcpy(clocks_info->name, "/");
297
clocks_info->level = 0;
299
while ((item = readdir(dir))) {
300
/* skip hidden dirs except ".." */
301
if (item->d_name[0] == '.')
304
strcpy(clockname, item->d_name);
305
sprintf(filename, "%s/%s", clkpath, item->d_name);
306
cur = (struct clock_info *)malloc(sizeof(struct clock_info));
307
memset(cur, 0, sizeof(struct clock_info));
308
strcpy(cur->name, clockname);
309
cur->parent = clocks_info;
310
cur->num_children = 0;
313
insert_children(&clocks_info, cur);
314
child = read_clock_info_recur(filename, 2, cur);
319
struct clock_info *read_clock_info_recur(char *clkpath, int level,
320
struct clock_info *parent)
324
char filename[PATH_MAX];
326
struct clock_info *cur = NULL;
329
dir = opendir(clkpath);
333
while ((item = readdir(dir))) {
334
struct clock_info *child;
335
/* skip hidden dirs except ".." */
336
if (item->d_name[0] == '.' )
339
sprintf(filename, "%s/%s", clkpath, item->d_name);
341
ret = stat(filename, &buf);
344
printf("Error doing a stat on %s\n", filename);
348
if (S_ISREG(buf.st_mode)) {
349
if (!strcmp(item->d_name, "flags"))
350
parent->flags = get_int_from(filename);
351
if (!strcmp(item->d_name, "rate"))
352
parent->rate = get_int_from(filename);
353
if (!strcmp(item->d_name, "usecount"))
354
parent->usecount = get_int_from(filename);
358
if (!S_ISDIR(buf.st_mode))
361
cur = (struct clock_info *)malloc(sizeof(struct clock_info));
362
memset(cur, 0, sizeof(cur));
363
strcpy(cur->name, item->d_name);
364
cur->children = NULL;
366
cur->num_children = 0;
369
child = read_clock_info_recur(filename, level + 1, cur);
370
insert_children(&parent, cur);
371
cur->parent = parent;
378
void insert_children(struct clock_info **parent, struct clock_info *clk)
380
if (!(*parent)->num_children || (*parent)->children == NULL) {
381
(*parent)->children = (struct clock_info **)
382
malloc(sizeof(struct clock_info *)*2);
383
(*parent)->num_children = 0;
385
(*parent)->children = (struct clock_info **)
386
realloc((*parent)->children,
387
sizeof(struct clock_info *) *
388
((*parent)->num_children + 2));
389
if ((*parent)->num_children > 0)
390
(*parent)->children[(*parent)->num_children - 1]->last_child
393
(*parent)->children[(*parent)->num_children] = clk;
394
(*parent)->children[(*parent)->num_children + 1] = NULL;
395
(*parent)->num_children++;
398
void dump_parent(struct clock_info *clk, int line)
402
static char spaces[64];
409
if (clk && clk->parent)
410
dump_parent(clk->parent, ++line);
412
drate = (double)clk->rate;
413
if (drate > 1000 && drate < 1000000) {
417
if (drate > 1000000) {
421
if (clk == clocks_info) {
424
sprintf(str, "%s%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
425
spaces, clk->name, clk->flags, clk->usecount, drate,
428
if (!(clk->parent == clocks_info))
430
sprintf(str, "%s`- %s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
431
spaces, clk->name, clk->flags, clk->usecount, drate,
435
//printf("line=%d:m%d:l%d %s", maxline - line + 2, maxline, line, str);
438
print_one_clock(maxline - line + 2, str, 1, 0);
441
void dump_all_parents(char *clkarg)
443
struct clock_info *clk;
448
clk = find_clock(clocks_info, clkarg);
451
printf("Clock NOT found!\n");
453
// while(clk && clk != clocks_info) {
454
// printf("%s\n", clk->name);
455
// strcat(spaces, " ");
456
// clk = clk->parent;
457
// printf("%s <-- ", spaces);
464
struct clock_info *find_clock(struct clock_info *clk, char *clkarg)
467
struct clock_info *ret = clk;
469
if (!strcmp(clk->name, clkarg))
473
for (i = 0; i < clk->num_children; i++) {
474
if (!strcmp(clk->children[i]->name, clkarg))
475
return clk->children[i];
477
for (i = 0; i < clk->num_children; i++) {
478
ret = find_clock(clk->children[i], clkarg);
488
void dump_clock_info(struct clock_info *clk, int level, int bmp)
495
for (i = 1, j = 0; i < level; i++, j = (i - 1)) {
496
if (i == (level - 1)) {
509
if (clk == clocks_info)
510
printf("%s\n", clk->name);
513
double drate = (double)clk->rate;
515
if (drate > 1000 && drate < 1000000) {
519
if (drate > 1000000) {
523
printf("%s (flags:%d,usecount:%d,rate:%5.2f %s)\n",
524
clk->name, clk->flags, clk->usecount, drate, unit);
530
if (clk->last_child) {
531
xbmp ^= 1 << (level - 2);
536
for (i = 0; i < clk->num_children; i++) {
537
tbmp = xbmp | (1 << level);
538
dump_clock_info(clk->children[i], level + 1, tbmp);
543
char *debugfs_locate_mpoint(void)
551
path = likely_mpoints;
553
ret = statfs(*path, &sfs);
554
if (ret >= 0 && sfs.f_type == (long)DEBUGFS_MAGIC)
559
filep = fopen("/proc/mounts", "r");
561
fprintf(stderr, "powerdebug: Error opening /proc/mounts.");
565
while (fscanf(filep, "%*s %s %s %*s %*d %*d\n",
566
debugfs_mntpoint, fsname) == 2)
567
if (!strcmp(fsname, "debugfs"))
571
if (strcmp(fsname, "debugfs"))
574
return debugfs_mntpoint;