1b47b5b34SRafael Vanoni /* 2b47b5b34SRafael Vanoni * Copyright 2009, Intel Corporation 3b47b5b34SRafael Vanoni * Copyright 2009, Sun Microsystems, Inc 4b47b5b34SRafael Vanoni * 5b47b5b34SRafael Vanoni * This file is part of PowerTOP 6b47b5b34SRafael Vanoni * 7b47b5b34SRafael Vanoni * This program file is free software; you can redistribute it and/or modify it 8b47b5b34SRafael Vanoni * under the terms of the GNU General Public License as published by the 9b47b5b34SRafael Vanoni * Free Software Foundation; version 2 of the License. 10b47b5b34SRafael Vanoni * 11b47b5b34SRafael Vanoni * This program is distributed in the hope that it will be useful, but WITHOUT 12b47b5b34SRafael Vanoni * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13b47b5b34SRafael Vanoni * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14b47b5b34SRafael Vanoni * for more details. 15b47b5b34SRafael Vanoni * 16b47b5b34SRafael Vanoni * You should have received a copy of the GNU General Public License 17b47b5b34SRafael Vanoni * along with this program in a file named COPYING; if not, write to the 18b47b5b34SRafael Vanoni * Free Software Foundation, Inc., 19b47b5b34SRafael Vanoni * 51 Franklin Street, Fifth Floor, 20b47b5b34SRafael Vanoni * Boston, MA 02110-1301 USA 21b47b5b34SRafael Vanoni * 22b47b5b34SRafael Vanoni * Authors: 23b47b5b34SRafael Vanoni * Arjan van de Ven <arjan@linux.intel.com> 24b47b5b34SRafael Vanoni * Eric C Saxe <eric.saxe@sun.com> 25b47b5b34SRafael Vanoni * Aubrey Li <aubrey.li@intel.com> 26b47b5b34SRafael Vanoni */ 27b47b5b34SRafael Vanoni 28b47b5b34SRafael Vanoni /* 29b47b5b34SRafael Vanoni * GPL Disclaimer 30b47b5b34SRafael Vanoni * 31b47b5b34SRafael Vanoni * For the avoidance of doubt, except that if any license choice other 32b47b5b34SRafael Vanoni * than GPL or LGPL is available it will apply instead, Sun elects to 33b47b5b34SRafael Vanoni * use only the General Public License version 2 (GPLv2) at this time 34b47b5b34SRafael Vanoni * for any software where a choice of GPL license versions is made 35b47b5b34SRafael Vanoni * available with the language indicating that GPLv2 or any later 36b47b5b34SRafael Vanoni * version may be used, or where a choice of which version of the GPL 37b47b5b34SRafael Vanoni * is applied is otherwise unspecified. 38b47b5b34SRafael Vanoni */ 39b47b5b34SRafael Vanoni 40b47b5b34SRafael Vanoni #include <unistd.h> 41b47b5b34SRafael Vanoni #include <stdio.h> 42b47b5b34SRafael Vanoni #include <stdlib.h> 43b47b5b34SRafael Vanoni #include <string.h> 44b47b5b34SRafael Vanoni #include "powertop.h" 45b47b5b34SRafael Vanoni 469bbf5ba1SRafael Vanoni /* 479bbf5ba1SRafael Vanoni * Default number of intervals we display a suggestion before moving 489bbf5ba1SRafael Vanoni * to the next. 499bbf5ba1SRafael Vanoni */ 509bbf5ba1SRafael Vanoni #define PT_SUGG_DEF_SLICE 3 51b47b5b34SRafael Vanoni 529bbf5ba1SRafael Vanoni /* 539bbf5ba1SRafael Vanoni * Global pointer to the current suggestion. 549bbf5ba1SRafael Vanoni */ 559bbf5ba1SRafael Vanoni sugg_t *g_curr_sugg; 56b47b5b34SRafael Vanoni 579bbf5ba1SRafael Vanoni /* 589bbf5ba1SRafael Vanoni * Head of the list of suggestions. 599bbf5ba1SRafael Vanoni */ 609bbf5ba1SRafael Vanoni static sugg_t *sugg; 61b47b5b34SRafael Vanoni 629bbf5ba1SRafael Vanoni /* 639bbf5ba1SRafael Vanoni * Add a new suggestion. Only one suggestion per text allowed. 649bbf5ba1SRafael Vanoni */ 65b47b5b34SRafael Vanoni void 669bbf5ba1SRafael Vanoni pt_sugg_add(char *text, int weight, char key, char *sb_msg, sugg_func_t *func) 67b47b5b34SRafael Vanoni { 689bbf5ba1SRafael Vanoni sugg_t *new, *n, *pos = NULL; 69b47b5b34SRafael Vanoni 709bbf5ba1SRafael Vanoni /* 719bbf5ba1SRafael Vanoni * Text is a required field for suggestions 729bbf5ba1SRafael Vanoni */ 739bbf5ba1SRafael Vanoni if (text == NULL) 74b47b5b34SRafael Vanoni return; 75b47b5b34SRafael Vanoni 769bbf5ba1SRafael Vanoni if (sugg == NULL) { 779bbf5ba1SRafael Vanoni /* 789bbf5ba1SRafael Vanoni * Creating first element 799bbf5ba1SRafael Vanoni */ 809bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL) 81b47b5b34SRafael Vanoni return; 82b47b5b34SRafael Vanoni 839bbf5ba1SRafael Vanoni if (sb_msg != NULL) 849bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg); 85b47b5b34SRafael Vanoni 869bbf5ba1SRafael Vanoni if (text != NULL) 879bbf5ba1SRafael Vanoni new->text = strdup(text); 889bbf5ba1SRafael Vanoni 89b47b5b34SRafael Vanoni new->weight = weight; 90b47b5b34SRafael Vanoni new->key = key; 91b47b5b34SRafael Vanoni new->func = func; 929bbf5ba1SRafael Vanoni new->slice = 0; 939bbf5ba1SRafael Vanoni 949bbf5ba1SRafael Vanoni sugg = new; 959bbf5ba1SRafael Vanoni new->prev = NULL; 969bbf5ba1SRafael Vanoni new->next = NULL; 979bbf5ba1SRafael Vanoni } else { 989bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 999bbf5ba1SRafael Vanoni if (strcmp(n->text, text) == 0) 1009bbf5ba1SRafael Vanoni return; 1019bbf5ba1SRafael Vanoni 1029bbf5ba1SRafael Vanoni if (weight > n->weight && pos == NULL) 1039bbf5ba1SRafael Vanoni pos = n; 1049bbf5ba1SRafael Vanoni } 1059bbf5ba1SRafael Vanoni /* 1069bbf5ba1SRafael Vanoni * Create a new element 1079bbf5ba1SRafael Vanoni */ 1089bbf5ba1SRafael Vanoni if ((new = calloc(1, sizeof (sugg_t))) == NULL) 1099bbf5ba1SRafael Vanoni return; 1109bbf5ba1SRafael Vanoni 1119bbf5ba1SRafael Vanoni if (sb_msg != NULL) 1129bbf5ba1SRafael Vanoni new->sb_msg = strdup(sb_msg); 1139bbf5ba1SRafael Vanoni 1149bbf5ba1SRafael Vanoni new->text = strdup(text); 1159bbf5ba1SRafael Vanoni 1169bbf5ba1SRafael Vanoni new->weight = weight; 1179bbf5ba1SRafael Vanoni new->key = key; 1189bbf5ba1SRafael Vanoni new->func = func; 1199bbf5ba1SRafael Vanoni new->slice = 0; 1209bbf5ba1SRafael Vanoni 1219bbf5ba1SRafael Vanoni if (pos == NULL) { 1229bbf5ba1SRafael Vanoni /* 1239bbf5ba1SRafael Vanoni * Ordering placed the new element at the end 1249bbf5ba1SRafael Vanoni */ 1259bbf5ba1SRafael Vanoni for (n = sugg; n->next != NULL; n = n->next) 1269bbf5ba1SRafael Vanoni ; 1279bbf5ba1SRafael Vanoni 1289bbf5ba1SRafael Vanoni n->next = new; 1299bbf5ba1SRafael Vanoni new->prev = n; 1309bbf5ba1SRafael Vanoni new->next = NULL; 1319bbf5ba1SRafael Vanoni } else { 1329bbf5ba1SRafael Vanoni if (pos == sugg) { 1339bbf5ba1SRafael Vanoni /* 1349bbf5ba1SRafael Vanoni * Ordering placed the new element at the start 1359bbf5ba1SRafael Vanoni */ 1369bbf5ba1SRafael Vanoni new->next = sugg; 1379bbf5ba1SRafael Vanoni new->prev = sugg; 1389bbf5ba1SRafael Vanoni sugg->prev = new; 1399bbf5ba1SRafael Vanoni sugg = new; 1409bbf5ba1SRafael Vanoni } else { 1419bbf5ba1SRafael Vanoni /* 1429bbf5ba1SRafael Vanoni * Ordering placed the new element somewhere in 1439bbf5ba1SRafael Vanoni * the middle 1449bbf5ba1SRafael Vanoni */ 1459bbf5ba1SRafael Vanoni new->next = pos; 1469bbf5ba1SRafael Vanoni new->prev = pos->prev; 1479bbf5ba1SRafael Vanoni pos->prev->next = new; 1489bbf5ba1SRafael Vanoni pos->prev = new; 1499bbf5ba1SRafael Vanoni } 1509bbf5ba1SRafael Vanoni } 1519bbf5ba1SRafael Vanoni } 152b47b5b34SRafael Vanoni } 153b47b5b34SRafael Vanoni 1549bbf5ba1SRafael Vanoni /* 1559bbf5ba1SRafael Vanoni * Removes a suggestion, returning 0 if not found and 1 if so. 1569bbf5ba1SRafael Vanoni */ 1579bbf5ba1SRafael Vanoni int 1589bbf5ba1SRafael Vanoni pt_sugg_remove(sugg_func_t *func) 159b47b5b34SRafael Vanoni { 1609bbf5ba1SRafael Vanoni sugg_t *n; 1619bbf5ba1SRafael Vanoni int ret = 0; 162b47b5b34SRafael Vanoni 1639bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 1649bbf5ba1SRafael Vanoni if (n->func == func) { 1659bbf5ba1SRafael Vanoni /* Removing the first element */ 1669bbf5ba1SRafael Vanoni if (n == sugg) { 1679bbf5ba1SRafael Vanoni if (sugg->next == NULL) { 1689bbf5ba1SRafael Vanoni /* Removing the only element */ 1699bbf5ba1SRafael Vanoni sugg = NULL; 1709bbf5ba1SRafael Vanoni } else { 1719bbf5ba1SRafael Vanoni sugg = n->next; 1729bbf5ba1SRafael Vanoni sugg->prev = NULL; 1739bbf5ba1SRafael Vanoni } 1749bbf5ba1SRafael Vanoni } else { 1759bbf5ba1SRafael Vanoni if (n->next == NULL) { 1769bbf5ba1SRafael Vanoni /* Removing the last element */ 1779bbf5ba1SRafael Vanoni n->prev->next = NULL; 1789bbf5ba1SRafael Vanoni } else { 1799bbf5ba1SRafael Vanoni /* Removing an intermediate element */ 1809bbf5ba1SRafael Vanoni n->prev->next = n->next; 1819bbf5ba1SRafael Vanoni n->next->prev = n->prev; 1829bbf5ba1SRafael Vanoni } 1839bbf5ba1SRafael Vanoni } 184b47b5b34SRafael Vanoni 1859bbf5ba1SRafael Vanoni /* 1869bbf5ba1SRafael Vanoni * If this suggestions is currently being suggested, 1879bbf5ba1SRafael Vanoni * remove it and update the screen. 1889bbf5ba1SRafael Vanoni */ 1899bbf5ba1SRafael Vanoni if (n == g_curr_sugg) { 1909bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) { 1919bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg); 1929bbf5ba1SRafael Vanoni pt_display_status_bar(); 1939bbf5ba1SRafael Vanoni } 1949bbf5ba1SRafael Vanoni if (n->text != NULL) 1959bbf5ba1SRafael Vanoni pt_display_suggestions(NULL); 1969bbf5ba1SRafael Vanoni } 1979bbf5ba1SRafael Vanoni 1989bbf5ba1SRafael Vanoni free(n); 1999bbf5ba1SRafael Vanoni ret = 1; 2009bbf5ba1SRafael Vanoni } 2019bbf5ba1SRafael Vanoni } 2029bbf5ba1SRafael Vanoni 2039bbf5ba1SRafael Vanoni return (ret); 2049bbf5ba1SRafael Vanoni } 2059bbf5ba1SRafael Vanoni 2069bbf5ba1SRafael Vanoni /* 2079bbf5ba1SRafael Vanoni * Chose a suggestion to display. The list of suggestions is ordered by weight, 2089bbf5ba1SRafael Vanoni * so we only worry about fariness here. Each suggestion, starting with the 2099bbf5ba1SRafael Vanoni * first (the 'heaviest') is displayed during PT_SUGG_DEF_SLICE intervals. 2109bbf5ba1SRafael Vanoni */ 2119bbf5ba1SRafael Vanoni void 2129bbf5ba1SRafael Vanoni pt_sugg_pick(void) 2139bbf5ba1SRafael Vanoni { 2149bbf5ba1SRafael Vanoni sugg_t *n; 2159bbf5ba1SRafael Vanoni 2169bbf5ba1SRafael Vanoni if (sugg == NULL) { 2179bbf5ba1SRafael Vanoni g_curr_sugg = NULL; 218b47b5b34SRafael Vanoni return; 219b47b5b34SRafael Vanoni } 220b47b5b34SRafael Vanoni 2219bbf5ba1SRafael Vanoni search: 2229bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) { 223b47b5b34SRafael Vanoni 2249bbf5ba1SRafael Vanoni if (n->slice++ < PT_SUGG_DEF_SLICE) { 225b47b5b34SRafael Vanoni 2269bbf5ba1SRafael Vanoni /* 2279bbf5ba1SRafael Vanoni * Don't need to re-suggest the current suggestion. 2289bbf5ba1SRafael Vanoni */ 229*2d83778aSRafael Vanoni if (g_curr_sugg == n && !g_sig_resize) 2309bbf5ba1SRafael Vanoni return; 231b47b5b34SRafael Vanoni 2329bbf5ba1SRafael Vanoni /* 2339bbf5ba1SRafael Vanoni * Remove the current suggestion from screen. 2349bbf5ba1SRafael Vanoni */ 2359bbf5ba1SRafael Vanoni if (g_curr_sugg != NULL) { 2369bbf5ba1SRafael Vanoni if (g_curr_sugg->sb_msg != NULL) { 2379bbf5ba1SRafael Vanoni pt_display_mod_status_bar( 2389bbf5ba1SRafael Vanoni g_curr_sugg->sb_msg); 2399bbf5ba1SRafael Vanoni pt_display_status_bar(); 240b47b5b34SRafael Vanoni } 2419bbf5ba1SRafael Vanoni if (g_curr_sugg->text != NULL) 2429bbf5ba1SRafael Vanoni pt_display_suggestions(NULL); 2439bbf5ba1SRafael Vanoni } 2449bbf5ba1SRafael Vanoni 2459bbf5ba1SRafael Vanoni if (n->sb_msg != NULL) { 2469bbf5ba1SRafael Vanoni pt_display_mod_status_bar(n->sb_msg); 2479bbf5ba1SRafael Vanoni pt_display_status_bar(); 2489bbf5ba1SRafael Vanoni } 2499bbf5ba1SRafael Vanoni 2509bbf5ba1SRafael Vanoni pt_display_suggestions(n->text); 2519bbf5ba1SRafael Vanoni 2529bbf5ba1SRafael Vanoni g_curr_sugg = n; 2539bbf5ba1SRafael Vanoni 254b47b5b34SRafael Vanoni return; 255b47b5b34SRafael Vanoni } 256b47b5b34SRafael Vanoni } 257b47b5b34SRafael Vanoni 2589bbf5ba1SRafael Vanoni /* 2599bbf5ba1SRafael Vanoni * All suggestions have run out of slice quotas, so we restart. 2609bbf5ba1SRafael Vanoni */ 2619bbf5ba1SRafael Vanoni for (n = sugg; n != NULL; n = n->next) 2629bbf5ba1SRafael Vanoni n->slice = 0; 2639bbf5ba1SRafael Vanoni 2649bbf5ba1SRafael Vanoni goto search; 265b47b5b34SRafael Vanoni } 266b47b5b34SRafael Vanoni 267b47b5b34SRafael Vanoni void 2689bbf5ba1SRafael Vanoni pt_sugg_as_root(void) 269b47b5b34SRafael Vanoni { 2709bbf5ba1SRafael Vanoni pt_sugg_add("Suggestion: run as root to get suggestions" 2719bbf5ba1SRafael Vanoni " for reducing system power consumption", 40, NULL, NULL, 2729bbf5ba1SRafael Vanoni NULL); 273b47b5b34SRafael Vanoni } 274