Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2007, Intel Corporation
      3  *
      4  * This file is part of PowerTOP
      5  *
      6  * This program file is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License as published by the
      8  * Free Software Foundation; version 2 of the License.
      9  *
     10  * This program is distributed in the hope that it will be useful, but WITHOUT
     11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     13  * for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program in a file named COPYING; if not, write to the
     17  * Free Software Foundation, Inc.,
     18  * 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301 USA
     20  *
     21  * Authors:
     22  * 	Arjan van de Ven <arjan (at) linux.intel.com>
     23  */
     24 
     25 #include <unistd.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <stdint.h>
     30 #include <sys/types.h>
     31 #include <dirent.h>
     32 
     33 #include "powertop.h"
     34 
     35 void set_laptop_mode(void)
     36 {
     37 	FILE *file;
     38 	file = fopen("/proc/sys/vm/laptop_mode", "w");
     39 	if (!file)
     40 		return;
     41 	fprintf(file,"5\n");
     42 	fclose(file);
     43 }
     44 
     45 void suggest_laptop_mode(void)
     46 {
     47 	FILE *file;
     48 	int i;
     49 	char buffer[1024];
     50 	/*
     51 	 * Check to see if we are on AC - lots of distros have
     52 	 * annoying scripts to turn laptop mode off when on AC, which
     53 	 * results in annoying distracting return of set laptop mode
     54 	 * hint.
     55 	 */
     56 	file = fopen("/proc/acpi/ac_adapter/AC/state", "r");
     57 	if (!file)
     58 		return;
     59 	memset(buffer, 0, 1024);
     60 	if (!fgets(buffer, 1023, file)) {
     61 		fclose(file);
     62 		return;
     63 	}
     64 	fclose(file);
     65 	if (strstr(buffer, "on-line") != NULL)
     66 		return;
     67 
     68 	/* Now check for laptop mode */
     69 	file = fopen("/proc/sys/vm/laptop_mode", "r");
     70 	if (!file)
     71 		return;
     72 	memset(buffer, 0, 1024);
     73 	if (!fgets(buffer, 1023, file)) {
     74 		fclose(file);
     75 		return;
     76 	}
     77 	i = strtoul(buffer, NULL, 10);
     78 	if (i<1) {
     79 		add_suggestion( _("Suggestion: Enable laptop-mode by executing the following command:\n"
     80 		 	"   echo 5 > /proc/sys/vm/laptop_mode \n"), 15, 'L', _(" L - enable Laptop mode "), set_laptop_mode);
     81 	}
     82 	fclose(file);
     83 }
     84 
     85 void nmi_watchdog_off(void)
     86 {
     87 	FILE *file;
     88 	file = fopen("/proc/sys/kernel/nmi_watchdog", "w");
     89 	if (!file)
     90 		return;
     91 	fprintf(file,"0\n");
     92 	fclose(file);
     93 }
     94 void suggest_nmi_watchdog(void)
     95 {
     96 	FILE *file;
     97 	int i;
     98 	char buffer[1024];
     99 	file = fopen("/proc/sys/kernel/nmi_watchdog", "r");
    100 	if (!file)
    101 		return;
    102 	memset(buffer, 0, 1024);
    103 	if (!fgets(buffer, 1023, file)) {
    104 		fclose(file);
    105 		return;
    106 	}
    107 	i = strtoul(buffer, NULL, 10);
    108 	if (i!=0) {
    109 		add_suggestion( _("Suggestion: disable the NMI watchdog by executing the following command:\n"
    110 		 	"   echo 0 > /proc/sys/kernel/nmi_watchdog \n"
    111 			"The NMI watchdog is a kernel debug mechanism to detect deadlocks"), 25, 'N', _(" N - Turn NMI watchdog off "), nmi_watchdog_off);
    112 	}
    113 	fclose(file);
    114 }
    115 
    116 void suggest_hpet(void)
    117 {
    118 	FILE *file;
    119 	char buffer[1024];
    120 	file = fopen("/sys/devices/system/clocksource/clocksource0/available_clocksource", "r");
    121 	if (!file)
    122 		return;
    123 	memset(buffer, 0, 1024);
    124 
    125 	if (!fgets(buffer, 1023, file)) {
    126 		fclose(file);
    127 		return;
    128 	}
    129 
    130 	if (strstr(buffer, "hpet")) {
    131 		fclose(file);
    132 		return;
    133 	}
    134 
    135 	fclose(file);
    136 
    137 	add_suggestion( _("Suggestion: enable the HPET (Multimedia Timer) in your BIOS or add \n"
    138 		          "the kernel patch to force-enable HPET. HPET support allows Linux to \n"
    139 			  "have much longer sleep intervals."), 7, 0, NULL, NULL);
    140 }
    141 
    142 void ac97_power_on(void)
    143 {
    144 	FILE *file;
    145 	file = fopen("/sys/module/snd_ac97_codec/parameters/power_save", "w");
    146 	if (!file)
    147 		return;
    148 	fprintf(file,"1");
    149 	fclose(file);
    150 	if (access("/dev/dsp", F_OK))
    151 		return;
    152 	file = fopen("/dev/dsp", "w");
    153 	if (file) {
    154 		fprintf(file,"1");
    155 		fclose(file);
    156 	}
    157 }
    158 
    159 void suggest_ac97_powersave(void)
    160 {
    161 	FILE *file;
    162 	char buffer[1024];
    163 	file = fopen("/sys/module/snd_ac97_codec/parameters/power_save", "r");
    164 	if (!file)
    165 		return;
    166 	memset(buffer, 0, 1024);
    167 	if (!fgets(buffer, 1023, file)) {
    168 		fclose(file);
    169 		return;
    170 	}
    171 	if (buffer[0]=='N') {
    172 		add_suggestion( _("Suggestion: enable AC97 powersave mode by executing the following command:\n"
    173 		 	"   echo 1 > /sys/module/snd_ac97_codec/parameters/power_save \n"
    174 			"or by passing power_save=1 as module parameter."), 25, 'A', _(" A - Turn AC97 powersave on "), ac97_power_on);
    175 	}
    176 	fclose(file);
    177 }
    178 
    179 void noatime_on(void)
    180 {
    181 	system("/bin/mount -o remount,noatime,nodiratime /");
    182 }
    183 
    184 void suggest_noatime(void)
    185 {
    186 	FILE *file;
    187 	char buffer[1024];
    188 	int suggest = 0;
    189 	file = fopen("/proc/mounts","r");
    190 	if (!file)
    191 		return;
    192 	while (!feof(file)) {
    193 		memset(buffer, 0, 1024);
    194 		if (!fgets(buffer, 1023, file))
    195 			break;
    196 		if (strstr(buffer, " / ext3") && !strstr(buffer, "noatime") && !strstr(buffer, "relatime"))
    197 			suggest = 1;
    198 
    199 	}
    200 	if (suggest) {
    201 		add_suggestion( _("Suggestion: enable the noatime filesystem option by executing the following command:\n"
    202 		 	"   mount -o remount,noatime /          or by pressing the T key \n"
    203 			"noatime disables persistent access time of file accesses, which causes lots of disk IO."), 5, 'T', _(" T - enable noatime "), noatime_on);
    204 	}
    205 	fclose(file);
    206 }
    207 
    208 void powersched_on(void)
    209 {
    210 	FILE *file;
    211 	file = fopen("/sys/devices/system/cpu/sched_mc_power_savings", "w");
    212 	if (!file)
    213 		return;
    214 	fprintf(file,"1");
    215 	fclose(file);
    216 }
    217 
    218 void suggest_powersched(void)
    219 {
    220 	FILE *file;
    221 	char buffer[1024];
    222 	int suggest = 0;
    223 	int cpu;
    224 
    225 	file = fopen("/sys/devices/system/cpu/sched_mc_power_savings","r");
    226 	if (!file)
    227 		return;
    228 	memset(buffer, 0, 1024);
    229 	if (!fgets(buffer, 1023, file)) {
    230 		fclose(file);
    231 		return;
    232 	}
    233 	fclose(file);
    234 	if (buffer[0]!='0')
    235 		return;
    236 	/* ok so power saving scheduler is off; now to see if we actually have a multi-package system */
    237 	cpu =  sysconf(_SC_NPROCESSORS_ONLN);
    238 
    239 	if (cpu<2)
    240 		return; /* UP system */
    241 
    242 	file = fopen("/proc/cpuinfo", "r");
    243 	suggest = 1;
    244 	if (!file)
    245 		return;
    246 	while (!feof(file)) {
    247 		memset(buffer, 0, 1024);
    248 		char *c;
    249 		if (!fgets(buffer, 1023, file))
    250 			break;
    251 		if (strstr(buffer, "cpu cores")) {
    252 			c = strchr(buffer, ':');
    253 			if (!c)
    254 				continue;
    255 			c++;
    256 			if (strtoll(c, NULL, 10) >= cpu)
    257 				suggest = 0;
    258 		}
    259 	}
    260 	fclose(file);
    261 
    262 
    263 	if (suggest) {
    264 		add_suggestion( _("Suggestion: enable the power aware CPU scheduler with the following command:\n"
    265 		 	"  echo 1 > /sys/devices/system/cpu/sched_mc_power_savings\n"
    266 			"or by pressing the C key."), 5, 'C', _(" C - Power aware CPU scheduler "), powersched_on);
    267 	}
    268 }
    269 
    270 
    271 void writeback_long(void)
    272 {
    273 	FILE *file;
    274 	file = fopen("/proc/sys/vm/dirty_writeback_centisecs", "w");
    275 	if (!file)
    276 		return;
    277 	fprintf(file,"1500");
    278 	fclose(file);
    279 }
    280 
    281 void suggest_writeback_time(void)
    282 {
    283 	FILE *file;
    284 	char buffer[1024];
    285 	int i;
    286 	file = fopen("/proc/sys/vm/dirty_writeback_centisecs", "r");
    287 	if (!file)
    288 		return;
    289 	memset(buffer, 0, 1024);
    290 	if (!fgets(buffer, 1023, file)) {
    291 		fclose(file);
    292 		return;
    293 	}
    294 	i = strtoull(buffer, NULL, 10);
    295 	if (i<1400) {
    296 		char line[1024];
    297 		sprintf(line,_("Suggestion: increase the VM dirty writeback time from %1.2f to 15 seconds with:\n"
    298 			 	"  echo 1500 > /proc/sys/vm/dirty_writeback_centisecs \n"
    299 				"This wakes the disk up less frequently for background VM activity"),
    300 			i/100.0);
    301 		add_suggestion(line, 15, 'W', _(" W - Increase Writeback time "), writeback_long);
    302 	}
    303 	fclose(file);
    304 }
    305