~ruther/guix-local

bfbf6e1e1009cc2697b38d6c7ea2ebdd9db627f6 — Mathieu Othacehe 9 years ago d02c3c2
gnu: Add tlp service.

* gnu/services/pm.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Add gnu/services/tlp.scm.
* doc/guix.texi (Power management Services): New section.

Signed-off-by: Clément Lassieur <clement@lassieur.org>
3 files changed, 911 insertions(+), 0 deletions(-)

M doc/guix.texi
M gnu/local.mk
A gnu/services/pm.scm
M doc/guix.texi => doc/guix.texi +505 -0
@@ 216,6 216,7 @@ Services
* VPN Services::                VPN daemons.
* Network File System::         NFS related services.
* Continuous Integration::      The Cuirass service.
* Power management Services::   The TLP tool.
* Miscellaneous Services::      Other services.

Defining Services


@@ 8451,6 8452,7 @@ declaration.
* VPN Services::                VPN daemons.
* Network File System::         NFS related services.
* Continuous Integration::      The Cuirass service.
* Power management Services::   The TLP tool.
* Miscellaneous Services::      Other services.
@end menu



@@ 13708,6 13710,509 @@ The Cuirass package to use.
@end table
@end deftp

@node Power management Services
@subsubsection Power management Services

@cindex power management with TLP
The @code{(gnu services pm)} module provides a Guix service definition
for the Linux power management tool TLP.

TLP enables various powersaving modes in userspace and kernel.
Contrary to @code{upower-service}, it is not a passive,
monitoring tool, as it will apply custom settings each time a new power
source is detected.  More information can be found at
@uref{http://linrunner.de/en/tlp/tlp.html, TLP home page}.

@deffn {Scheme Variable} tlp-service-type
The service type for the TLP tool.  Its value should be a valid
TLP configuration (see below).  For example:
@example
(service tlp-service-type (tlp-configuration))
@end example
@end deffn

By default TLP does not need much configuration but most TLP parameters
can be tweaked using @code{tlp-configuration}.

Each parameter definition is preceded by its type; for example,
@samp{boolean foo} indicates that the @code{foo} parameter
should be specified as a boolean.  Types starting with
@code{maybe-} denote parameters that won't show up in TLP config file
when their value is @code{'disabled}.

@c The following documentation was initially generated by
@c (generate-tlp-documentation) in (gnu services pm).  Manually maintained
@c documentation is better, so we shouldn't hesitate to edit below as
@c needed.  However if the change you want to make to this documentation
@c can be done in an automated way, it's probably easier to change
@c (generate-documentation) than to make it below and have to deal with
@c the churn as TLP updates.

Available @code{tlp-configuration} fields are:

@deftypevr {@code{tlp-configuration} parameter} package tlp
The TLP package.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean tlp-enable?
Set to true if you wish to enable TLP.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string tlp-default-mode
Default mode when no power supply can be detected.  Alternatives are AC
and BAT.

Defaults to @samp{"AC"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer disk-idle-secs-on-ac
Number of seconds Linux kernel has to wait after the disk goes idle,
before syncing on AC.

Defaults to @samp{0}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer disk-idle-secs-on-bat
Same as @code{disk-idle-ac} but on BAT mode.

Defaults to @samp{2}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer max-lost-work-secs-on-ac
Dirty pages flushing periodicity, expressed in seconds.

Defaults to @samp{15}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer max-lost-work-secs-on-bat
Same as @code{max-lost-work-secs-on-ac} but on BAT mode.

Defaults to @samp{60}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list cpu-scaling-governor-on-ac
CPU frequency scaling governor on AC mode.  With intel_pstate driver,
alternatives are powersave and performance.  With acpi-cpufreq driver,
alternatives are ondemand, powersave, performance and conservative.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list cpu-scaling-governor-on-bat
Same as @code{cpu-scaling-governor-on-ac} but on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-scaling-min-freq-on-ac
Set the min available frequency for the scaling governor on AC.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-scaling-max-freq-on-ac
Set the max available frequency for the scaling governor on AC.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-scaling-min-freq-on-bat
Set the min available frequency for the scaling governor on BAT.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-scaling-max-freq-on-bat
Set the max available frequency for the scaling governor on BAT.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-min-perf-on-ac
Limit the min P-state to control the power dissipation of the CPU, in AC
mode.  Values are stated as a percentage of the available performance.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-max-perf-on-ac
Limit the max P-state to control the power dissipation of the CPU, in AC
mode.  Values are stated as a percentage of the available performance.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-min-perf-on-bat
Same as @code{cpu-min-perf-on-ac} on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-non-negative-integer cpu-max-perf-on-bat
Same as @code{cpu-max-perf-on-ac} on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-boolean cpu-boost-on-ac?
Enable CPU turbo boost feature on AC mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-boolean cpu-boost-on-bat?
Same as @code{cpu-boost-on-ac?} on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean sched-powersave-on-ac?
Allow Linux kernel to minimize the number of CPU cores/hyper-threads
used under light load conditions.

Defaults to @samp{#f}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean sched-powersave-on-bat?
Same as @code{sched-powersave-on-ac?} but on BAT mode.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean nmi-watchdog?
Enable Linux kernel NMI watchdog.

Defaults to @samp{#f}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-string phc-controls
For Linux kernels with PHC patch applied, change CPU voltages.  An
example value would be @samp{"F:V F:V F:V F:V"}.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string energy-perf-policy-on-ac
Set CPU performance versus energy saving policy on AC.  Alternatives are
performance, normal, powersave.

Defaults to @samp{"performance"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string energy-perf-policy-on-bat
Same as @code{energy-perf-policy-ac} but on BAT mode.

Defaults to @samp{"powersave"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} space-separated-string-list disks-devices
Hard disk devices.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} space-separated-string-list disk-apm-level-on-ac
Hard disk advanced power management level.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} space-separated-string-list disk-apm-level-on-bat
Same as @code{disk-apm-bat} but on BAT mode.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list disk-spindown-timeout-on-ac
Hard disk spin down timeout.  One value has to be specified for each
declared hard disk.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list disk-spindown-timeout-on-bat
Same as @code{disk-spindown-timeout-on-ac} but on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list disk-iosched
Select IO scheduler for disk devices.  One value has to be specified for
each declared hard disk.  Example alternatives are cfq, deadline and
noop.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string sata-linkpwr-on-ac
SATA aggressive link power management (ALPM) level.  Alternatives are
min_power, medium_power, max_performance.

Defaults to @samp{"max_performance"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string sata-linkpwr-on-bat
Same as @code{sata-linkpwr-ac} but on BAT mode.

Defaults to @samp{"min_power"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-string sata-linkpwr-blacklist
Exclude specified SATA host devices for link power management.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-on-off-boolean ahci-runtime-pm-on-ac?
Enable Runtime Power Management for AHCI controller and disks on AC
mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-on-off-boolean ahci-runtime-pm-on-bat?
Same as @code{ahci-runtime-pm-on-ac} on BAT mode.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer ahci-runtime-pm-timeout
Seconds of inactivity before disk is suspended.

Defaults to @samp{15}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string pcie-aspm-on-ac
PCI Express Active State Power Management level.  Alternatives are
default, performance, powersave.

Defaults to @samp{"performance"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string pcie-aspm-on-bat
Same as @code{pcie-aspm-ac} but on BAT mode.

Defaults to @samp{"powersave"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-power-profile-on-ac
Radeon graphics clock speed level.  Alternatives are low, mid, high,
auto, default.

Defaults to @samp{"high"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-power-profile-on-bat
Same as @code{radeon-power-ac} but on BAT mode.

Defaults to @samp{"low"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-dpm-state-on-ac
Radeon dynamic power management method (DPM).  Alternatives are battery,
performance.

Defaults to @samp{"performance"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-dpm-state-on-bat
Same as @code{radeon-dpm-state-ac} but on BAT mode.

Defaults to @samp{"battery"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-dpm-perf-level-on-ac
Radeon DPM performance level.  Alternatives are auto, low, high.

Defaults to @samp{"auto"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string radeon-dpm-perf-level-on-bat
Same as @code{radeon-dpm-perf-ac} but on BAT mode.

Defaults to @samp{"auto"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} on-off-boolean wifi-pwr-on-ac?
Wifi power saving mode.

Defaults to @samp{#f}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} on-off-boolean wifi-pwr-on-bat?
Same as @code{wifi-power-ac?} but on BAT mode.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} y-n-boolean wol-disable?
Disable wake on LAN.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer sound-power-save-on-ac
Timeout duration in seconds before activating audio power saving on
Intel HDA and AC97 devices.  A value of 0 disables power saving.

Defaults to @samp{0}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} non-negative-integer sound-power-save-on-bat
Same as @code{sound-powersave-ac} but on BAT mode.

Defaults to @samp{1}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} y-n-boolean sound-power-save-controller?
Disable controller in powersaving mode on Intel HDA devices.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean bay-poweroff-on-bat?
Enable optical drive in UltraBay/MediaBay on BAT mode.  Drive can be
powered on again by releasing (and reinserting) the eject lever or by
pressing the disc eject button on newer models.

Defaults to @samp{#f}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string bay-device
Name of the optical drive device to power off.

Defaults to @samp{"sr0"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string runtime-pm-on-ac
Runtime Power Management for PCI(e) bus devices.  Alternatives are on
and auto.

Defaults to @samp{"on"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} string runtime-pm-on-bat
Same as @code{runtime-pm-ac} but on BAT mode.

Defaults to @samp{"auto"}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean runtime-pm-all?
Runtime Power Management for all PCI(e) bus devices, except blacklisted
ones.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-space-separated-string-list runtime-pm-blacklist
Exclude specified PCI(e) devices adresses from Runtime Power Management.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} space-separated-string-list runtime-pm-driver-blacklist
Exclude PCI(e) devices assigned to the specified drivers from Runtime
Power Management.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean usb-autosuspend?
Enable USB autosuspend feature.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-string usb-blacklist
Exclude specified devices from USB autosuspend.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean usb-blacklist-wwan?
Exclude WWAN devices from USB autosuspend.

Defaults to @samp{#t}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-string usb-whitelist
Include specified devices into USB autosuspend, even if they are already
excluded by the driver or via @code{usb-blacklist-wwan?}.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} maybe-boolean usb-autosuspend-disable-on-shutdown?
Enable USB autosuspend before shutdown.

Defaults to @samp{disabled}.

@end deftypevr

@deftypevr {@code{tlp-configuration} parameter} boolean restore-device-state-on-startup?
Restore radio device state (bluetooth, wifi, wwan) from previous
shutdown on system startup.

Defaults to @samp{#f}.

@end deftypevr

@node Miscellaneous Services
@subsubsection Miscellaneous Services


M gnu/local.mk => gnu/local.mk +2 -0
@@ 10,6 10,7 @@
# Copyright © 2016, 2017 Ricardo Wurmus <rekado@elephly.net>
# Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
# Copyright © 2017 Clément Lassieur <clement@lassieur.org>
# Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
#
# This file is part of GNU Guix.
#


@@ 422,6 423,7 @@ GNU_SYSTEM_MODULES =				\
  %D%/services/nfs.scm			\
  %D%/services/shepherd.scm			\
  %D%/services/herd.scm				\
  %D%/services/pm.scm				\
  %D%/services/sddm.scm				\
  %D%/services/spice.scm				\
  %D%/services/ssh.scm				\

A gnu/services/pm.scm => gnu/services/pm.scm +404 -0
@@ 0,0 1,404 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (gnu services pm)
  #:use-module (guix gexp)
  #:use-module (guix packages)
  #:use-module (guix records)
  #:use-module (gnu packages linux)
  #:use-module (gnu services)
  #:use-module (gnu services base)
  #:use-module (gnu services configuration)
  #:use-module (gnu services shepherd)
  #:use-module (gnu system shadow)
  #:export (tlp-service-type
            tlp-configuration))

(define (uglify-field-name field-name)
  (let ((str (symbol->string field-name)))
    (string-join (string-split
                  (string-upcase
                   (if (string-suffix? "?" str)
                       (substring str 0 (1- (string-length str)))
                       str))
                  #\-)
                 "_")))

(define (serialize-field field-name val)
  (format #t "~a=~a\n" (uglify-field-name field-name) val))

(define (serialize-boolean field-name val)
  (serialize-field field-name (if val "1" "0")))
(define-maybe boolean)

(define (serialize-string field-name val)
  (serialize-field field-name val))
(define-maybe string)

(define (space-separated-string-list? val)
  (and (list? val)
       (and-map (lambda (x)
                  (and (string? x) (not (string-index x #\space))))
                val)))
(define (serialize-space-separated-string-list field-name val)
  (serialize-field field-name
                   (format #f "~s"
                           (string-join val " "))))
(define-maybe space-separated-string-list)

(define (non-negative-integer? val)
  (and (exact-integer? val) (not (negative? val))))
(define (serialize-non-negative-integer field-name val)
  (serialize-field field-name val))
(define-maybe non-negative-integer)

(define (on-off-boolean? val)
  (boolean? val))
(define (serialize-on-off-boolean field-name val)
  (serialize-field field-name (if val "on" "off")))
(define-maybe on-off-boolean)

(define (y-n-boolean? val)
  (boolean? val))
(define (serialize-y-n-boolean field-name val)
  (serialize-field field-name (if val "Y" "N")))

(define-configuration tlp-configuration
  (tlp
   (package tlp)
   "The TLP package.")

  (tlp-enable?
   (boolean #t)
   "Set to true if you wish to enable TLP.")

  (tlp-default-mode
   (string "AC")
   "Default mode when no power supply can be detected.  Alternatives are
AC and BAT.")

  (disk-idle-secs-on-ac
   (non-negative-integer 0)
   "Number of seconds Linux kernel has to wait after the disk goes idle,
before syncing on AC.")

  (disk-idle-secs-on-bat
   (non-negative-integer 2)
   "Same as @code{disk-idle-ac} but on BAT mode.")

  (max-lost-work-secs-on-ac
   (non-negative-integer 15)
   "Dirty pages flushing periodicity, expressed in seconds.")

  (max-lost-work-secs-on-bat
   (non-negative-integer 60)
   "Same as @code{max-lost-work-secs-on-ac} but on BAT mode.")

  (cpu-scaling-governor-on-ac
   (maybe-space-separated-string-list 'disabled)
   "CPU frequency scaling governor on AC mode.  With intel_pstate
driver, alternatives are powersave and performance.  With acpi-cpufreq driver,
alternatives are ondemand, powersave, performance and conservative.")

  (cpu-scaling-governor-on-bat
   (maybe-space-separated-string-list 'disabled)
   "Same as @code{cpu-scaling-governor-on-ac} but on BAT mode.")

  (cpu-scaling-min-freq-on-ac
   (maybe-non-negative-integer 'disabled)
   "Set the min available frequency for the scaling governor on AC.")

  (cpu-scaling-max-freq-on-ac
   (maybe-non-negative-integer 'disabled)
   "Set the max available frequency for the scaling governor on AC.")

  (cpu-scaling-min-freq-on-bat
   (maybe-non-negative-integer 'disabled)
   "Set the min available frequency for the scaling governor on BAT.")

  (cpu-scaling-max-freq-on-bat
   (maybe-non-negative-integer 'disabled)
   "Set the max available frequency for the scaling governor on BAT.")

  (cpu-min-perf-on-ac
   (maybe-non-negative-integer 'disabled)
   "Limit the min P-state to control the power dissipation of the CPU,
in AC mode.  Values are stated as a percentage of the available performance.")

  (cpu-max-perf-on-ac
   (maybe-non-negative-integer 'disabled)
   "Limit the max P-state to control the power dissipation of the CPU,
in AC mode.  Values are stated as a percentage of the available performance.")

  (cpu-min-perf-on-bat
   (maybe-non-negative-integer 'disabled)
   "Same as @code{cpu-min-perf-on-ac} on BAT mode.")

  (cpu-max-perf-on-bat
   (maybe-non-negative-integer 'disabled)
   "Same as @code{cpu-max-perf-on-ac} on BAT mode.")

  (cpu-boost-on-ac?
   (maybe-boolean 'disabled)
   "Enable CPU turbo boost feature on AC mode.")

  (cpu-boost-on-bat?
   (maybe-boolean 'disabled)
   "Same as @code{cpu-boost-on-ac?} on BAT mode.")

  (sched-powersave-on-ac?
   (boolean #f)
   "Allow Linux kernel to minimize the number of CPU cores/hyper-threads
used under light load conditions.")

  (sched-powersave-on-bat?
   (boolean #t)
   "Same as @code{sched-powersave-on-ac?} but on BAT mode.")

  (nmi-watchdog?
   (boolean #f)
   "Enable Linux kernel NMI watchdog.")

  (phc-controls
   (maybe-string 'disabled)
   "For Linux kernels with PHC patch applied, change CPU voltages.
An example value would be @samp{\"F:V F:V F:V F:V\"}.")

  (energy-perf-policy-on-ac
   (string "performance")
   "Set CPU performance versus energy saving policy on AC.  Alternatives are
performance, normal, powersave.")

  (energy-perf-policy-on-bat
   (string "powersave")
   "Same as @code{energy-perf-policy-ac} but on BAT mode.")

  (disks-devices
   (space-separated-string-list '("sda"))
   "Hard disk devices.")

  (disk-apm-level-on-ac
   (space-separated-string-list '("254" "254"))
   "Hard disk advanced power management level.")

  (disk-apm-level-on-bat
   (space-separated-string-list '("128" "128"))
   "Same as @code{disk-apm-bat} but on BAT mode.")

  (disk-spindown-timeout-on-ac
   (maybe-space-separated-string-list 'disabled)
   "Hard disk spin down timeout.  One value has to be specified for
each declared hard disk.")

  (disk-spindown-timeout-on-bat
   (maybe-space-separated-string-list 'disabled)
   "Same as @code{disk-spindown-timeout-on-ac} but on BAT mode.")

  (disk-iosched
   (maybe-space-separated-string-list 'disabled)
   "Select IO scheduler for disk devices.  One value has to be specified
for each declared hard disk.  Example alternatives are cfq, deadline and noop.")

  (sata-linkpwr-on-ac
   (string "max_performance")
   "SATA aggressive link power management (ALPM) level.  Alternatives are
min_power, medium_power, max_performance.")

  (sata-linkpwr-on-bat
   (string "min_power")
   "Same as @code{sata-linkpwr-ac} but on BAT mode.")

  (sata-linkpwr-blacklist
   (maybe-string 'disabled)
   "Exclude specified SATA host devices for link power management.")

  (ahci-runtime-pm-on-ac?
   (maybe-on-off-boolean 'disabled)
   "Enable Runtime Power Management for AHCI controller and disks
on AC mode.")

  (ahci-runtime-pm-on-bat?
   (maybe-on-off-boolean 'disabled)
   "Same as @code{ahci-runtime-pm-on-ac} on BAT mode.")

  (ahci-runtime-pm-timeout
   (non-negative-integer 15)
   "Seconds of inactivity before disk is suspended.")

  (pcie-aspm-on-ac
   (string "performance")
   "PCI Express Active State Power Management level.  Alternatives are
default, performance, powersave.")

  (pcie-aspm-on-bat
   (string "powersave")
   "Same as @code{pcie-aspm-ac} but on BAT mode.")

  (radeon-power-profile-on-ac
   (string "high")
   "Radeon graphics clock speed level.  Alternatives are
low, mid, high, auto, default.")

  (radeon-power-profile-on-bat
   (string "low")
   "Same as @code{radeon-power-ac} but on BAT mode.")

  (radeon-dpm-state-on-ac
   (string "performance")
   "Radeon dynamic power management method (DPM).  Alternatives are
battery, performance.")

  (radeon-dpm-state-on-bat
   (string "battery")
   "Same as @code{radeon-dpm-state-ac} but on BAT mode.")

  (radeon-dpm-perf-level-on-ac
   (string "auto")
   "Radeon DPM performance level.  Alternatives are
auto, low, high.")

  (radeon-dpm-perf-level-on-bat
   (string "auto")
   "Same as @code{radeon-dpm-perf-ac} but on BAT mode.")

  (wifi-pwr-on-ac?
   (on-off-boolean #f)
   "Wifi power saving mode.")

  (wifi-pwr-on-bat?
   (on-off-boolean #t)
   "Same as @code{wifi-power-ac?} but on BAT mode.")

  (wol-disable?
   (y-n-boolean #t)
   "Disable wake on LAN.")

  (sound-power-save-on-ac
   (non-negative-integer 0)
   "Timeout duration in seconds before activating audio power saving
 on Intel HDA and AC97 devices.  A value of 0 disables power saving.")

  (sound-power-save-on-bat
   (non-negative-integer 1)
   "Same as @code{sound-powersave-ac} but on BAT mode.")

  (sound-power-save-controller?
   (y-n-boolean #t)
   "Disable controller in powersaving mode on Intel HDA devices.")

  (bay-poweroff-on-bat?
   (boolean #f)
   "Enable optical drive in UltraBay/MediaBay on BAT mode.
Drive can be powered on again by releasing (and reinserting) the eject lever
or by pressing the disc eject button on newer models.")

  (bay-device
   (string "sr0")
   "Name of the optical drive device to power off.")

  (runtime-pm-on-ac
   (string "on")
   "Runtime Power Management for PCI(e) bus devices.  Alternatives are
on and auto.")

  (runtime-pm-on-bat
   (string "auto")
   "Same as @code{runtime-pm-ac} but on BAT mode.")

  (runtime-pm-all?
   (boolean #t)
   "Runtime Power Management for all PCI(e) bus devices, except
blacklisted ones.")

  (runtime-pm-blacklist
   (maybe-space-separated-string-list 'disabled)
   "Exclude specified PCI(e) devices adresses from Runtime Power Management.")

  (runtime-pm-driver-blacklist
   (space-separated-string-list '("radeon" "nouveau"))
   "Exclude PCI(e) devices assigned to the specified drivers from
Runtime Power Management.")

  (usb-autosuspend?
   (boolean #t)
   "Enable USB autosuspend feature.")

  (usb-blacklist
   (maybe-string 'disabled)
   "Exclude specified devices from USB autosuspend.")

  (usb-blacklist-wwan?
   (boolean #t)
   "Exclude WWAN devices from USB autosuspend.")

  (usb-whitelist
   (maybe-string 'disabled)
   "Include specified devices into USB autosuspend, even if they are
already excluded by the driver or via @code{usb-blacklist-wwan?}.")

  (usb-autosuspend-disable-on-shutdown?
   (maybe-boolean 'disabled)
   "Enable USB autosuspend before shutdown.")

  (restore-device-state-on-startup?
   (boolean #f)
   "Restore radio device state (bluetooth, wifi, wwan) from previous
shutdown on system startup."))


(define (tlp-shepherd-service config)
  (let* ((tlp-bin (file-append
                   (tlp-configuration-tlp config) "/bin/tlp"))
         (tlp-action (lambda args
                       #~(lambda _
                           (zero? (system* #$tlp-bin #$@args))))))
    (list (shepherd-service
           (documentation "Run TLP script.")
           (provision '(tlp))
           (requirement '(user-processes))
           (start (tlp-action "init" "start"))
           (stop  (tlp-action "init" "stop"))))))

(define (tlp-activation config)
  (let* ((config-str (with-output-to-string
                       (lambda ()
                         (serialize-configuration
                          config
                          tlp-configuration-fields))))
         (config-file (plain-file "tlp" config-str)))
    (with-imported-modules '((guix build utils))
      #~(begin
          (use-modules (guix build utils))
          (copy-file #$config-file "/etc/tlp")))))

(define tlp-service-type
  (service-type
   (name 'tlp)
   (extensions
    (list
     (service-extension shepherd-root-service-type
                        tlp-shepherd-service)
     (service-extension udev-service-type
                        (compose list tlp-configuration-tlp))
     (service-extension activation-service-type
                        tlp-activation)))))

(define (generate-tlp-documentation)
  (generate-documentation
   `((tlp-configuration ,tlp-configuration-fields))
   'tlp-configuration))