moved config to /etc

This commit is contained in:
erpalma
2018-04-03 11:17:18 +02:00
parent d9a459b12b
commit 5d6cfaa572
4 changed files with 81 additions and 46 deletions

View File

@@ -2,6 +2,11 @@ all: install
install: install:
install -d /usr/local/sbin/ install -d /usr/local/sbin/
install -m 700 lenovo_fix.py /usr/local/sbin/
install -d /etc/systemd/system/ install -d /etc/systemd/system/
install -m 644 lenovo_fix.service /etc/systemd/system/ install -m 700 lenovo_fix.py /usr/local/sbin/
install -m 644 systemd/lenovo_fix.service /etc/systemd/system/
@if test -f /etc/lenovo_fix.conf; then \
echo "/etc/lenovo_fix.conf already exists; overwrite manually"; \
else \
install -m 644 etc/lenovo_fix.conf /etc/; \
fi

32
etc/lenovo_fix.conf Normal file
View File

@@ -0,0 +1,32 @@
[GENERAL]
Enabled: True
## Settings to apply while connected to Battery power
[BATTERY]
# Update the registers every this many seconds
Update_Rate_s: 30
# Max package power for time window #1
PL1_Tdp_W: 29
# Time window #1 duration
PL1_Duration_s: 28
# Max package power for time window #2
PL2_Tdp_W: 44
# Time window #2 duration
PL2_Duration_S: 0.002
# Max allowed temperature before throttling
Trip_Temp_C: 85
## Settings to apply while connected to AC power
[AC]
# Update the registers every this many seconds
Update_Rate_s: 5
# Max package power for time window #1
PL1_Tdp_W: 44
# Time window #1 duration
PL1_Duration_s: 28
# Max package power for time window #2
PL2_Tdp_W: 44
# Time window #2 duration
PL2_Duration_S: 0.002
# Max allowed temperature before throttling
Trip_Temp_C: 97

View File

@@ -1,30 +1,16 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
import ConfigParser
import glob import glob
import os import os
import struct import struct
from collections import defaultdict
from periphery import MMIO from periphery import MMIO
from time import sleep from time import sleep
config = { SYSFS_POWER_PATH = '/sys/class/power_supply/AC/online'
'AC': { CONFIG_PATH = '/etc/lenovo_fix.conf'
'UPDATE_RATE_SEC': 5, # Update the registers every this many seconds
'PL1_TDP_W': 44, # Max package power for time window #1
'PL1_DURATION_S': 28, # Time window #1 duration
'PL2_TDP_W': 44, # Max package power for time window #2
'PL2_DURATION_S': 0.002, # Time window #2 duration
'TRIP_TEMP_C': 97 # Max allowed temperature before throttling
},
'BATTERY': {
'UPDATE_RATE_SEC': 30, # Update the registers every this many seconds
'PL1_TDP_W': 29, # Max package power for time window #1
'PL1_DURATION_S': 28, # Time window #1 duration
'PL2_TDP_W': 44, # Max package power for time window #2
'PL2_DURATION_S': 0.002, # Time window #2 duration
'TRIP_TEMP_C': 85 # Max allowed temperature before throttling
},
}
def writemsr(msr, val): def writemsr(msr, val):
@@ -39,7 +25,7 @@ def writemsr(msr, val):
def is_on_battery(): def is_on_battery():
with open('/sys/class/power_supply/AC/online') as f: with open(SYSFS_POWER_PATH) as f:
return not bool(int(f.read())) return not bool(int(f.read()))
@@ -51,52 +37,64 @@ def calc_time_window_vars(t):
raise Exception('Unable to find a good combination!') raise Exception('Unable to find a good combination!')
def check_config(): def load_config():
for k in config: config = ConfigParser.ConfigParser()
assert 0 < config[k]['UPDATE_RATE_SEC'] config.read(CONFIG_PATH)
assert 0 < config[k]['PL1_TDP_W']
assert 0 < config[k]['PL2_TDP_W'] for power_source in ('AC', 'BATTERY'):
assert 0 < config[k]['PL1_DURATION_S'] assert 0 < config.getfloat(power_source, 'Update_Rate_s')
assert 0 < config[k]['PL2_DURATION_S'] assert 0 < config.getfloat(power_source, 'PL1_Tdp_W')
assert 40 < config[k]['TRIP_TEMP_C'] < 98 assert 0 < config.getfloat(power_source, 'PL1_Duration_s')
assert 0 < config.getfloat(power_source, 'PL2_Tdp_W')
assert 0 < config.getfloat(power_source, 'PL2_Duration_S')
assert 40 < config.getfloat(power_source, 'Trip_Temp_C') < 98
return config
def calc_reg_values(): def calc_reg_values(config):
for k in config: regs = defaultdict(dict)
for power_source in ('AC', 'BATTERY'):
# the critical temperature for this CPU is 100 C # the critical temperature for this CPU is 100 C
trip_offset = int(round(100 - config[k]['TRIP_TEMP_C'])) trip_offset = int(round(100 - config.getfloat(power_source, 'Trip_Temp_C')))
config[k]['MSR_TEMPERATURE_TARGET'] = trip_offset << 24 regs[power_source]['MSR_TEMPERATURE_TARGET'] = trip_offset << 24
# 0.125 is the power unit of this CPU # 0.125 is the power unit of this CPU
PL1 = int(round(config[k]['PL1_TDP_W'] / 0.125)) PL1 = int(round(config.getfloat(power_source, 'PL1_Tdp_W') / 0.125))
Y, Z = calc_time_window_vars(config[k]['PL1_DURATION_S']) Y, Z = calc_time_window_vars(config.getfloat(power_source, 'PL1_Duration_s'))
TW1 = Y | (Z << 5) TW1 = Y | (Z << 5)
PL2 = int(round(config[k]['PL2_TDP_W'] / 0.125)) PL2 = int(round(config.getfloat(power_source, 'PL2_Tdp_W') / 0.125))
Y, Z = calc_time_window_vars(config[k]['PL2_DURATION_S']) Y, Z = calc_time_window_vars(config.getfloat(power_source, 'PL2_Duration_s'))
TW2 = Y | (Z << 5) TW2 = Y | (Z << 5)
config[k]['MSR_PKG_POWER_LIMIT'] = PL1 | (1 << 15) | (TW1 << 17) | (PL2 << 32) | (1 << 47) | (TW2 << 49) regs[power_source]['MSR_PKG_POWER_LIMIT'] = PL1 | (1 << 15) | (TW1 << 17) | (PL2 << 32) | (1 << 47) | (
TW2 << 49)
return regs
def main(): def main():
check_config() config = load_config()
calc_reg_values() regs = calc_reg_values(config)
if not config.getboolean('GENERAL', 'Enabled'):
return
mchbar_mmio = MMIO(0xfed159a0, 8) mchbar_mmio = MMIO(0xfed159a0, 8)
while True: while True:
cur_config = config['BATTERY' if is_on_battery() else 'AC'] power_source = 'BATTERY' if is_on_battery() else 'AC'
# set temperature trip point # set temperature trip point
writemsr(0x1a2, cur_config['MSR_TEMPERATURE_TARGET']) writemsr(0x1a2, regs[power_source]['MSR_TEMPERATURE_TARGET'])
# set PL1/2 on MSR # set PL1/2 on MSR
writemsr(0x610, cur_config['MSR_PKG_POWER_LIMIT']) writemsr(0x610, regs[power_source]['MSR_PKG_POWER_LIMIT'])
# set MCHBAR register to the same PL1/2 values # set MCHBAR register to the same PL1/2 values
mchbar_mmio.write32(0, cur_config['MSR_PKG_POWER_LIMIT'] & 0xffffffff) mchbar_mmio.write32(0, regs[power_source]['MSR_PKG_POWER_LIMIT'] & 0xffffffff)
mchbar_mmio.write32(4, cur_config['MSR_PKG_POWER_LIMIT'] >> 32) mchbar_mmio.write32(4, regs[power_source]['MSR_PKG_POWER_LIMIT'] >> 32)
sleep(cur_config['UPDATE_RATE_SEC']) sleep(config.getfloat(power_source, 'Update_Rate_s'))
if __name__ == '__main__': if __name__ == '__main__':