| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 |
|
| 22 | (define-module (gnu services pm)
|
| 23 | #:use-module (srfi srfi-1)
|
| 24 | #:use-module (ice-9 match)
|
| 25 | #:use-module (guix gexp)
|
| 26 | #:use-module (guix packages)
|
| 27 | #:use-module (guix records)
|
| 28 | #:use-module (gnu packages admin)
|
| 29 | #:use-module (gnu packages freedesktop)
|
| 30 | #:use-module (gnu packages hardware)
|
| 31 | #:use-module (gnu packages linux)
|
| 32 | #:use-module (gnu services)
|
| 33 | #:use-module (gnu services base)
|
| 34 | #:use-module (gnu services configuration)
|
| 35 | #:use-module (gnu services dbus)
|
| 36 | #:use-module (gnu services shepherd)
|
| 37 | #:use-module (gnu system shadow)
|
| 38 | #:export (power-profiles-daemon-service-type
|
| 39 | power-profiles-daemon-configuration
|
| 40 |
|
| 41 | tlp-service-type
|
| 42 | tlp-configuration
|
| 43 |
|
| 44 | thermald-configuration
|
| 45 | thermald-service-type
|
| 46 |
|
| 47 | powertop-configuration
|
| 48 | powertop-service-type
|
| 49 |
|
| 50 | hd-idle-disk
|
| 51 | hd-idle-disk?
|
| 52 | hd-idle-configuration
|
| 53 | hd-idle-configuration?
|
| 54 | hd-idle-service-type))
|
| 55 |
|
| 56 | |
| 57 | |
| 58 | |
| 59 |
|
| 60 | (define-configuration/no-serialization power-profiles-daemon-configuration
|
| 61 | (power-profiles-daemon
|
| 62 | (file-like power-profiles-daemon)
|
| 63 | "The power-profiles-daemon package."))
|
| 64 |
|
| 65 | (define (power-profiles-daemon-shepherd-service config)
|
| 66 | (match-record
|
| 67 | config <power-profiles-daemon-configuration>
|
| 68 | (power-profiles-daemon)
|
| 69 | (list
|
| 70 | (shepherd-service
|
| 71 | (provision '(power-profiles-daemon))
|
| 72 | (requirement '(user-processes dbus-system))
|
| 73 | (documentation "Run the Power Profiles Daemon.")
|
| 74 | (start #~(make-forkexec-constructor
|
| 75 | (list #$(file-append power-profiles-daemon
|
| 76 | "/libexec/power-profiles-daemon"))))
|
| 77 | (stop #~(make-kill-destructor))))))
|
| 78 |
|
| 79 | (define %power-profiles-daemon-activation
|
| 80 | #~(begin
|
| 81 | (use-modules (guix build utils))
|
| 82 | (mkdir-p "/var/lib/power-profiles-daemon")))
|
| 83 |
|
| 84 | (define power-profiles-daemon-service-type
|
| 85 | (let ((config->package
|
| 86 | (compose list power-profiles-daemon-configuration-power-profiles-daemon)))
|
| 87 | (service-type
|
| 88 | (name 'power-profiles-daemon)
|
| 89 | (extensions (list
|
| 90 | (service-extension shepherd-root-service-type
|
| 91 | power-profiles-daemon-shepherd-service)
|
| 92 | (service-extension dbus-root-service-type
|
| 93 | config->package)
|
| 94 | (service-extension polkit-service-type
|
| 95 | config->package)
|
| 96 | (service-extension profile-service-type
|
| 97 | config->package)
|
| 98 | (service-extension activation-service-type
|
| 99 | (const %power-profiles-daemon-activation))))
|
| 100 | (default-value (power-profiles-daemon-configuration))
|
| 101 | (description "Run the Power Profiles Daemon"))))
|
| 102 |
|
| 103 |
|
| 104 |
|
| 105 | |
| 106 | |
| 107 | |
| 108 |
|
| 109 | (define (uglify-field-name field-name)
|
| 110 | (let ((str (symbol->string field-name)))
|
| 111 | (string-join (string-split
|
| 112 | (string-upcase
|
| 113 | (if (string-suffix? "?" str)
|
| 114 | (substring str 0 (1- (string-length str)))
|
| 115 | str))
|
| 116 | #\-)
|
| 117 | "_")))
|
| 118 |
|
| 119 | (define (serialize-field field-name val)
|
| 120 | (format #t "~a=~a\n" (uglify-field-name field-name) val))
|
| 121 |
|
| 122 | (define (serialize-boolean field-name val)
|
| 123 | (serialize-field field-name (if val "1" "0")))
|
| 124 | (define-maybe boolean)
|
| 125 |
|
| 126 | (define (serialize-string field-name val)
|
| 127 | (serialize-field field-name val))
|
| 128 | (define-maybe string)
|
| 129 |
|
| 130 | (define (space-separated-string-list? val)
|
| 131 | (and (list? val)
|
| 132 | (and-map (lambda (x)
|
| 133 | (and (string? x) (not (string-index x #\space))))
|
| 134 | val)))
|
| 135 | (define (serialize-space-separated-string-list field-name val)
|
| 136 | (serialize-field field-name
|
| 137 | (format #f "~s"
|
| 138 | (string-join val " "))))
|
| 139 | (define-maybe space-separated-string-list)
|
| 140 |
|
| 141 | (define (non-negative-integer? val)
|
| 142 | (and (exact-integer? val) (not (negative? val))))
|
| 143 | (define (serialize-non-negative-integer field-name val)
|
| 144 | (serialize-field field-name val))
|
| 145 | (define-maybe non-negative-integer)
|
| 146 |
|
| 147 | (define (on-off-boolean? val)
|
| 148 | (boolean? val))
|
| 149 | (define (serialize-on-off-boolean field-name val)
|
| 150 | (serialize-field field-name (if val "on" "off")))
|
| 151 | (define-maybe on-off-boolean)
|
| 152 |
|
| 153 | (define (y-n-boolean? val)
|
| 154 | (boolean? val))
|
| 155 | (define (serialize-y-n-boolean field-name val)
|
| 156 | (serialize-field field-name (if val "Y" "N")))
|
| 157 |
|
| 158 | (define-configuration tlp-configuration
|
| 159 | (tlp
|
| 160 | (file-like tlp)
|
| 161 | "The TLP package.")
|
| 162 |
|
| 163 | (tlp-enable?
|
| 164 | (boolean #t)
|
| 165 | "Set to true if you wish to enable TLP.")
|
| 166 |
|
| 167 | (tlp-default-mode
|
| 168 | (string "AC")
|
| 169 | "Default mode when no power supply can be detected. Alternatives are
|
| 170 | AC and BAT.")
|
| 171 |
|
| 172 | (disk-idle-secs-on-ac
|
| 173 | (non-negative-integer 0)
|
| 174 | "Number of seconds Linux kernel has to wait after the disk goes idle,
|
| 175 | before syncing on AC.")
|
| 176 |
|
| 177 | (disk-idle-secs-on-bat
|
| 178 | (non-negative-integer 2)
|
| 179 | "Same as @code{disk-idle-ac} but on BAT mode.")
|
| 180 |
|
| 181 | (max-lost-work-secs-on-ac
|
| 182 | (non-negative-integer 15)
|
| 183 | "Dirty pages flushing periodicity, expressed in seconds.")
|
| 184 |
|
| 185 | (max-lost-work-secs-on-bat
|
| 186 | (non-negative-integer 60)
|
| 187 | "Same as @code{max-lost-work-secs-on-ac} but on BAT mode.")
|
| 188 |
|
| 189 | (cpu-scaling-governor-on-ac
|
| 190 | maybe-space-separated-string-list
|
| 191 | "CPU frequency scaling governor on AC mode. With intel_pstate
|
| 192 | driver, alternatives are powersave and performance. With acpi-cpufreq driver,
|
| 193 | alternatives are ondemand, powersave, performance and conservative.")
|
| 194 |
|
| 195 | (cpu-scaling-governor-on-bat
|
| 196 | maybe-space-separated-string-list
|
| 197 | "Same as @code{cpu-scaling-governor-on-ac} but on BAT mode.")
|
| 198 |
|
| 199 | (cpu-scaling-min-freq-on-ac
|
| 200 | maybe-non-negative-integer
|
| 201 | "Set the min available frequency for the scaling governor on AC.")
|
| 202 |
|
| 203 | (cpu-scaling-max-freq-on-ac
|
| 204 | maybe-non-negative-integer
|
| 205 | "Set the max available frequency for the scaling governor on AC.")
|
| 206 |
|
| 207 | (cpu-scaling-min-freq-on-bat
|
| 208 | maybe-non-negative-integer
|
| 209 | "Set the min available frequency for the scaling governor on BAT.")
|
| 210 |
|
| 211 | (cpu-scaling-max-freq-on-bat
|
| 212 | maybe-non-negative-integer
|
| 213 | "Set the max available frequency for the scaling governor on BAT.")
|
| 214 |
|
| 215 | (cpu-min-perf-on-ac
|
| 216 | maybe-non-negative-integer
|
| 217 | "Limit the min P-state to control the power dissipation of the CPU,
|
| 218 | in AC mode. Values are stated as a percentage of the available performance.")
|
| 219 |
|
| 220 | (cpu-max-perf-on-ac
|
| 221 | maybe-non-negative-integer
|
| 222 | "Limit the max P-state to control the power dissipation of the CPU,
|
| 223 | in AC mode. Values are stated as a percentage of the available performance.")
|
| 224 |
|
| 225 | (cpu-min-perf-on-bat
|
| 226 | maybe-non-negative-integer
|
| 227 | "Same as @code{cpu-min-perf-on-ac} on BAT mode.")
|
| 228 |
|
| 229 | (cpu-max-perf-on-bat
|
| 230 | maybe-non-negative-integer
|
| 231 | "Same as @code{cpu-max-perf-on-ac} on BAT mode.")
|
| 232 |
|
| 233 | (cpu-boost-on-ac?
|
| 234 | maybe-boolean
|
| 235 | "Enable CPU turbo boost feature on AC mode.")
|
| 236 |
|
| 237 | (cpu-boost-on-bat?
|
| 238 | maybe-boolean
|
| 239 | "Same as @code{cpu-boost-on-ac?} on BAT mode.")
|
| 240 |
|
| 241 | (sched-powersave-on-ac?
|
| 242 | (boolean #f)
|
| 243 | "Allow Linux kernel to minimize the number of CPU cores/hyper-threads
|
| 244 | used under light load conditions.")
|
| 245 |
|
| 246 | (sched-powersave-on-bat?
|
| 247 | (boolean #t)
|
| 248 | "Same as @code{sched-powersave-on-ac?} but on BAT mode.")
|
| 249 |
|
| 250 | (nmi-watchdog?
|
| 251 | (boolean #f)
|
| 252 | "Enable Linux kernel NMI watchdog.")
|
| 253 |
|
| 254 | (phc-controls
|
| 255 | maybe-string
|
| 256 | "For Linux kernels with PHC patch applied, change CPU voltages.
|
| 257 | An example value would be @samp{\"F:V F:V F:V F:V\"}.")
|
| 258 |
|
| 259 | (energy-perf-policy-on-ac
|
| 260 | (string "performance")
|
| 261 | "Set CPU performance versus energy saving policy on AC. Alternatives are
|
| 262 | performance, normal, powersave.")
|
| 263 |
|
| 264 | (energy-perf-policy-on-bat
|
| 265 | (string "powersave")
|
| 266 | "Same as @code{energy-perf-policy-ac} but on BAT mode.")
|
| 267 |
|
| 268 | (disks-devices
|
| 269 | (space-separated-string-list '("sda"))
|
| 270 | "Hard disk devices.")
|
| 271 |
|
| 272 | (disk-apm-level-on-ac
|
| 273 | (space-separated-string-list '("254" "254"))
|
| 274 | "Hard disk advanced power management level.")
|
| 275 |
|
| 276 | (disk-apm-level-on-bat
|
| 277 | (space-separated-string-list '("128" "128"))
|
| 278 | "Same as @code{disk-apm-bat} but on BAT mode.")
|
| 279 |
|
| 280 | (disk-spindown-timeout-on-ac
|
| 281 | maybe-space-separated-string-list
|
| 282 | "Hard disk spin down timeout. One value has to be specified for
|
| 283 | each declared hard disk.")
|
| 284 |
|
| 285 | (disk-spindown-timeout-on-bat
|
| 286 | maybe-space-separated-string-list
|
| 287 | "Same as @code{disk-spindown-timeout-on-ac} but on BAT mode.")
|
| 288 |
|
| 289 | (disk-iosched
|
| 290 | maybe-space-separated-string-list
|
| 291 | "Select IO scheduler for disk devices. One value has to be specified
|
| 292 | for each declared hard disk. Example alternatives are cfq, deadline and noop.")
|
| 293 |
|
| 294 | (sata-linkpwr-on-ac
|
| 295 | (string "max_performance")
|
| 296 | "SATA aggressive link power management (ALPM) level. Alternatives are
|
| 297 | min_power, medium_power, max_performance.")
|
| 298 |
|
| 299 | (sata-linkpwr-on-bat
|
| 300 | (string "min_power")
|
| 301 | "Same as @code{sata-linkpwr-ac} but on BAT mode.")
|
| 302 |
|
| 303 | (sata-linkpwr-blacklist
|
| 304 | maybe-string
|
| 305 | "Exclude specified SATA host devices for link power management.")
|
| 306 |
|
| 307 | (ahci-runtime-pm-on-ac?
|
| 308 | maybe-on-off-boolean
|
| 309 | "Enable Runtime Power Management for AHCI controller and disks
|
| 310 | on AC mode.")
|
| 311 |
|
| 312 | (ahci-runtime-pm-on-bat?
|
| 313 | maybe-on-off-boolean
|
| 314 | "Same as @code{ahci-runtime-pm-on-ac} on BAT mode.")
|
| 315 |
|
| 316 | (ahci-runtime-pm-timeout
|
| 317 | (non-negative-integer 15)
|
| 318 | "Seconds of inactivity before disk is suspended.")
|
| 319 |
|
| 320 | (pcie-aspm-on-ac
|
| 321 | (string "performance")
|
| 322 | "PCI Express Active State Power Management level. Alternatives are
|
| 323 | default, performance, powersave.")
|
| 324 |
|
| 325 | (pcie-aspm-on-bat
|
| 326 | (string "powersave")
|
| 327 | "Same as @code{pcie-aspm-ac} but on BAT mode.")
|
| 328 |
|
| 329 | (start-charge-thresh-bat0
|
| 330 | maybe-non-negative-integer
|
| 331 | "Percentage when battery 0 should begin charging.")
|
| 332 |
|
| 333 | (stop-charge-thresh-bat0
|
| 334 | maybe-non-negative-integer
|
| 335 | "Percentage when battery 0 should stop charging.")
|
| 336 |
|
| 337 | (start-charge-thresh-bat1
|
| 338 | maybe-non-negative-integer
|
| 339 | "Percentage when battery 1 should begin charging.")
|
| 340 |
|
| 341 | (stop-charge-thresh-bat1
|
| 342 | maybe-non-negative-integer
|
| 343 | "Percentage when battery 1 should stop charging.")
|
| 344 |
|
| 345 | (radeon-power-profile-on-ac
|
| 346 | (string "high")
|
| 347 | "Radeon graphics clock speed level. Alternatives are
|
| 348 | low, mid, high, auto, default.")
|
| 349 |
|
| 350 | (radeon-power-profile-on-bat
|
| 351 | (string "low")
|
| 352 | "Same as @code{radeon-power-ac} but on BAT mode.")
|
| 353 |
|
| 354 | (radeon-dpm-state-on-ac
|
| 355 | (string "performance")
|
| 356 | "Radeon dynamic power management method (DPM). Alternatives are
|
| 357 | battery, performance.")
|
| 358 |
|
| 359 | (radeon-dpm-state-on-bat
|
| 360 | (string "battery")
|
| 361 | "Same as @code{radeon-dpm-state-ac} but on BAT mode.")
|
| 362 |
|
| 363 | (radeon-dpm-perf-level-on-ac
|
| 364 | (string "auto")
|
| 365 | "Radeon DPM performance level. Alternatives are
|
| 366 | auto, low, high.")
|
| 367 |
|
| 368 | (radeon-dpm-perf-level-on-bat
|
| 369 | (string "auto")
|
| 370 | "Same as @code{radeon-dpm-perf-ac} but on BAT mode.")
|
| 371 |
|
| 372 | (wifi-pwr-on-ac?
|
| 373 | (on-off-boolean #f)
|
| 374 | "Wifi power saving mode.")
|
| 375 |
|
| 376 | (wifi-pwr-on-bat?
|
| 377 | (on-off-boolean #t)
|
| 378 | "Same as @code{wifi-power-ac?} but on BAT mode.")
|
| 379 |
|
| 380 | (wol-disable?
|
| 381 | (y-n-boolean #t)
|
| 382 | "Disable wake on LAN.")
|
| 383 |
|
| 384 | (sound-power-save-on-ac
|
| 385 | (non-negative-integer 0)
|
| 386 | "Timeout duration in seconds before activating audio power saving
|
| 387 | on Intel HDA and AC97 devices. A value of 0 disables power saving.")
|
| 388 |
|
| 389 | (sound-power-save-on-bat
|
| 390 | (non-negative-integer 1)
|
| 391 | "Same as @code{sound-powersave-ac} but on BAT mode.")
|
| 392 |
|
| 393 | (sound-power-save-controller?
|
| 394 | (y-n-boolean #t)
|
| 395 | "Disable controller in powersaving mode on Intel HDA devices.")
|
| 396 |
|
| 397 | (bay-poweroff-on-bat?
|
| 398 | (boolean #f)
|
| 399 | "Enable optical drive in UltraBay/MediaBay on BAT mode.
|
| 400 | Drive can be powered on again by releasing (and reinserting) the eject lever
|
| 401 | or by pressing the disc eject button on newer models.")
|
| 402 |
|
| 403 | (bay-device
|
| 404 | (string "sr0")
|
| 405 | "Name of the optical drive device to power off.")
|
| 406 |
|
| 407 | (runtime-pm-on-ac
|
| 408 | (string "on")
|
| 409 | "Runtime Power Management for PCI(e) bus devices. Alternatives are
|
| 410 | on and auto.")
|
| 411 |
|
| 412 | (runtime-pm-on-bat
|
| 413 | (string "auto")
|
| 414 | "Same as @code{runtime-pm-ac} but on BAT mode.")
|
| 415 |
|
| 416 | (runtime-pm-all?
|
| 417 | (boolean #t)
|
| 418 | "Runtime Power Management for all PCI(e) bus devices, except
|
| 419 | blacklisted ones.")
|
| 420 |
|
| 421 | (runtime-pm-blacklist
|
| 422 | maybe-space-separated-string-list
|
| 423 | "Exclude specified PCI(e) device addresses from Runtime Power Management.")
|
| 424 |
|
| 425 | (runtime-pm-driver-blacklist
|
| 426 | (space-separated-string-list '("radeon" "nouveau"))
|
| 427 | "Exclude PCI(e) devices assigned to the specified drivers from
|
| 428 | Runtime Power Management.")
|
| 429 |
|
| 430 | (usb-autosuspend?
|
| 431 | (boolean #t)
|
| 432 | "Enable USB autosuspend feature.")
|
| 433 |
|
| 434 | (usb-blacklist
|
| 435 | maybe-string
|
| 436 | "Exclude specified devices from USB autosuspend.")
|
| 437 |
|
| 438 | (usb-blacklist-wwan?
|
| 439 | (boolean #t)
|
| 440 | "Exclude WWAN devices from USB autosuspend.")
|
| 441 |
|
| 442 | (usb-whitelist
|
| 443 | maybe-string
|
| 444 | "Include specified devices into USB autosuspend, even if they are
|
| 445 | already excluded by the driver or via @code{usb-blacklist-wwan?}.")
|
| 446 |
|
| 447 | (usb-autosuspend-disable-on-shutdown?
|
| 448 | maybe-boolean
|
| 449 | "Enable USB autosuspend before shutdown.")
|
| 450 |
|
| 451 | (restore-device-state-on-startup?
|
| 452 | (boolean #f)
|
| 453 | "Restore radio device state (bluetooth, wifi, wwan) from previous
|
| 454 | shutdown on system startup.")
|
| 455 |
|
| 456 | (cpu-energy-perf-policy-on-ac
|
| 457 | maybe-string
|
| 458 | "Set CPU energy/performance policy when on AC mode. Possible values are
|
| 459 | performance, balance_performance, default, balance_power and power.")
|
| 460 |
|
| 461 | (cpu-energy-perf-policy-on-bat
|
| 462 | maybe-string
|
| 463 | "Set CPU energy/performance policy when on BAT mode. Possible values are
|
| 464 | performance, balance_performance, default, balance_power and power."))
|
| 465 |
|
| 466 |
|
| 467 | (define (tlp-shepherd-service config)
|
| 468 | (let* ((tlp-bin (file-append
|
| 469 | (tlp-configuration-tlp config) "/sbin/tlp"))
|
| 470 | (tlp-action (lambda (return-value-on-success . args)
|
| 471 | #~(lambda _
|
| 472 | (if (zero? (system* #$tlp-bin #$@args))
|
| 473 | #$return-value-on-success
|
| 474 | (not #$return-value-on-success))))))
|
| 475 | (list (shepherd-service
|
| 476 | (documentation "Run TLP script.")
|
| 477 | (provision '(tlp))
|
| 478 | (requirement '(user-processes))
|
| 479 | (start (tlp-action #t "init" "start"))
|
| 480 | (stop (tlp-action #f "init" "stop"))))))
|
| 481 |
|
| 482 | (define (tlp-activation config)
|
| 483 | (let* ((config-str (with-output-to-string
|
| 484 | (lambda ()
|
| 485 | (serialize-configuration
|
| 486 | config
|
| 487 | tlp-configuration-fields))))
|
| 488 | (config-file (plain-file "tlp" config-str)))
|
| 489 | (with-imported-modules '((guix build utils))
|
| 490 | #~(begin
|
| 491 | (use-modules (guix build utils))
|
| 492 | (copy-file #$config-file "/etc/tlp.conf")))))
|
| 493 |
|
| 494 | (define tlp-service-type
|
| 495 | (service-type
|
| 496 | (name 'tlp)
|
| 497 | (extensions
|
| 498 | (list
|
| 499 | (service-extension shepherd-root-service-type
|
| 500 | tlp-shepherd-service)
|
| 501 | (service-extension udev-service-type
|
| 502 | (compose list tlp-configuration-tlp))
|
| 503 | (service-extension activation-service-type
|
| 504 | tlp-activation)))
|
| 505 | (default-value (tlp-configuration))
|
| 506 | (description "Run TLP, a power management tool.")))
|
| 507 |
|
| 508 | (define (generate-tlp-documentation)
|
| 509 | (generate-documentation
|
| 510 | `((tlp-configuration ,tlp-configuration-fields))
|
| 511 | 'tlp-configuration))
|
| 512 |
|
| 513 |
|
| 514 |
|
| 515 | |
| 516 | |
| 517 | |
| 518 | |
| 519 |
|
| 520 | (define-record-type* <thermald-configuration>
|
| 521 | thermald-configuration make-thermald-configuration
|
| 522 | thermald-configuration?
|
| 523 | (adaptive? thermald-adaptive? |
| 524 | (default #f))
|
| 525 | (ignore-cpuid-check? thermald-ignore-cpuid-check? |
| 526 | (default #f))
|
| 527 | (thermald thermald-thermald |
| 528 | (default thermald)))
|
| 529 |
|
| 530 | (define (thermald-shepherd-service config)
|
| 531 | (list
|
| 532 | (shepherd-service
|
| 533 | (provision '(thermald))
|
| 534 | (requirement '(user-processes))
|
| 535 | (documentation "Run thermald cpu frequency scaling.")
|
| 536 | (start #~(make-forkexec-constructor
|
| 537 | '(#$(file-append (thermald-thermald config) "/sbin/thermald")
|
| 538 | "--no-daemon"
|
| 539 | #$@(if (thermald-adaptive? config)
|
| 540 | '("--adaptive")
|
| 541 | '())
|
| 542 | #$@(if (thermald-ignore-cpuid-check? config)
|
| 543 | '("--ignore-cpuid-check")
|
| 544 | '()))))
|
| 545 | (stop #~(make-kill-destructor)))))
|
| 546 |
|
| 547 | (define thermald-service-type
|
| 548 | (service-type
|
| 549 | (name 'thermald)
|
| 550 | (extensions (list (service-extension shepherd-root-service-type
|
| 551 | thermald-shepherd-service)))
|
| 552 | (default-value (thermald-configuration))
|
| 553 | (description "Run thermald, a CPU frequency scaling service that helps
|
| 554 | prevent overheating.")))
|
| 555 |
|
| 556 |
|
| 557 |
|
| 558 | |
| 559 | |
| 560 | |
| 561 | |
| 562 |
|
| 563 | (define-configuration powertop-configuration
|
| 564 | (powertop (package powertop) "PowerTOP package to use."))
|
| 565 |
|
| 566 | (define powertop-shepherd-service
|
| 567 | (match-lambda
|
| 568 | (($ <powertop-configuration> powertop)
|
| 569 | (shepherd-service
|
| 570 | (documentation "Tune kernel power settings at boot.")
|
| 571 | (provision '(powertop powertop-auto-tune))
|
| 572 | (requirement '(user-processes))
|
| 573 | (one-shot? #t)
|
| 574 | (start #~(lambda _
|
| 575 | (zero? (system* #$(file-append powertop "/sbin/powertop")
|
| 576 | "--auto-tune"))))))))
|
| 577 |
|
| 578 | (define powertop-service-type
|
| 579 | (service-type
|
| 580 | (name 'powertop)
|
| 581 | (extensions
|
| 582 | (list
|
| 583 | (service-extension shepherd-root-service-type
|
| 584 | (compose list powertop-shepherd-service))))
|
| 585 | (compose concatenate)
|
| 586 | (default-value (powertop-configuration))
|
| 587 | (description "Tune power-related kernel parameters to reduce energy
|
| 588 | consumption.")))
|
| 589 |
|
| 590 |
|
| 591 |
|
| 592 | |
| 593 | |
| 594 | |
| 595 | |
| 596 |
|
| 597 | (define (hd-idle-command-type? val)
|
| 598 | (memq val '(scsi ata)))
|
| 599 | (define-maybe/no-serialization hd-idle-command-type)
|
| 600 |
|
| 601 | (define (hd-idle-power-condition? val)
|
| 602 | (and (exact-integer? val) (<= 0 val 15)))
|
| 603 | (define-maybe/no-serialization hd-idle-power-condition)
|
| 604 |
|
| 605 | (define (hd-idle-symlink-policy? val)
|
| 606 | (and (exact-integer? val) (<= 0 val 1)))
|
| 607 |
|
| 608 | (define-configuration/no-serialization hd-idle-disk
|
| 609 | (name
|
| 610 | string
|
| 611 | "The device to configure, either a name under @file{/dev} such as
|
| 612 | @code{\"sda\"}, or an absolute file name such as
|
| 613 | @code{\"/dev/disk/by-uuid/1234-5678\"}.")
|
| 614 |
|
| 615 | (idle-time
|
| 616 | maybe-non-negative-integer
|
| 617 | "Number of seconds this disk must be idle before it is spun down.")
|
| 618 |
|
| 619 | (command-type
|
| 620 | maybe-hd-idle-command-type
|
| 621 | "The command used to spin this disk down, either @code{'scsi} or
|
| 622 | @code{'ata}.")
|
| 623 |
|
| 624 | (power-condition
|
| 625 | maybe-hd-idle-power-condition
|
| 626 | "The power condition to use for this disk."))
|
| 627 |
|
| 628 | (define list-of-hd-idle-disks?
|
| 629 | (list-of hd-idle-disk?))
|
| 630 |
|
| 631 | (define-configuration/no-serialization hd-idle-configuration
|
| 632 | (idle-time
|
| 633 | (non-negative-integer 600)
|
| 634 | "Number of seconds a disk must be idle before it is spun down. A value
|
| 635 | of @code{0} disables spinning down.")
|
| 636 |
|
| 637 | (command-type
|
| 638 | (hd-idle-command-type 'scsi)
|
| 639 | "The command used to spin disks down, either @code{'scsi} or @code{'ata}.")
|
| 640 |
|
| 641 | (power-condition
|
| 642 | (hd-idle-power-condition 0)
|
| 643 | "The power condition passed to the @acronym{SCSI, Small Computer System
|
| 644 | Interface} @code{START STOP UNIT} command, an integer between @code{0} and
|
| 645 | @code{15}. It is ignored when @code{command-type} is @code{'ata}.")
|
| 646 |
|
| 647 | (symlink-policy
|
| 648 | (hd-idle-symlink-policy 0)
|
| 649 | "How to resolve disk names that are symbolic links. @code{0} resolves
|
| 650 | them once at startup, whereas with @code{1} symlinks are also resolved on
|
| 651 | runtime until success.")
|
| 652 |
|
| 653 | (log-file
|
| 654 | maybe-string
|
| 655 | "A file name to which hd-idle logs disk spin-up and spin-down events, for
|
| 656 | instance @code{\"/var/log/hd-idle.log\"}.")
|
| 657 |
|
| 658 | (ignore-spin-down-detection?
|
| 659 | (boolean #f)
|
| 660 | "Whether to skip detection of disks that were spun down by some other
|
| 661 | means.")
|
| 662 |
|
| 663 | (debug?
|
| 664 | (boolean #f)
|
| 665 | "Whether to log the disk statistics that hd-idle reads on each poll.")
|
| 666 |
|
| 667 | (disks
|
| 668 | (list-of-hd-idle-disks '())
|
| 669 | "A list of @code{hd-idle-disk} records describing per-disk overrides.
|
| 670 | Disks that are not listed here are still managed, using the values above.")
|
| 671 |
|
| 672 | (hd-idle
|
| 673 | (file-like hd-idle)
|
| 674 | "The hd-idle package to use."))
|
| 675 |
|
| 676 | (define (hd-idle-disk-arguments disk)
|
| 677 | (match-record disk <hd-idle-disk>
|
| 678 | (name idle-time command-type power-condition)
|
| 679 | `("-a" ,name
|
| 680 | ,@(if (maybe-value-set? idle-time)
|
| 681 | (list "-i" (number->string idle-time))
|
| 682 | '())
|
| 683 | ,@(if (maybe-value-set? command-type)
|
| 684 | (list "-c" (symbol->string command-type))
|
| 685 | '())
|
| 686 | ,@(if (maybe-value-set? power-condition)
|
| 687 | (list "-p" (number->string power-condition))
|
| 688 | '()))))
|
| 689 |
|
| 690 | (define (hd-idle-arguments config)
|
| 691 | (match-record config <hd-idle-configuration>
|
| 692 | (idle-time command-type power-condition symlink-policy
|
| 693 | log-file ignore-spin-down-detection? debug? disks)
|
| 694 | `("-i" ,(number->string idle-time)
|
| 695 | "-c" ,(symbol->string command-type)
|
| 696 | "-p" ,(number->string power-condition)
|
| 697 | "-s" ,(number->string symlink-policy)
|
| 698 | ,@(if (maybe-value-set? log-file) (list "-l" log-file) '())
|
| 699 | ,@(if ignore-spin-down-detection? '("-I") '())
|
| 700 | ,@(if debug? '("-d") '())
|
| 701 | ,@(append-map hd-idle-disk-arguments disks))))
|
| 702 |
|
| 703 | (define (hd-idle-shepherd-service config)
|
| 704 | (list
|
| 705 | (shepherd-service
|
| 706 | (provision '(hd-idle))
|
| 707 | (requirement '(user-processes udev))
|
| 708 | (documentation "Spin down idle hard disks.")
|
| 709 | (start #~(make-forkexec-constructor
|
| 710 | (list #$(file-append (hd-idle-configuration-hd-idle config)
|
| 711 | "/bin/hd-idle")
|
| 712 | #$@(hd-idle-arguments config))))
|
| 713 | (stop #~(make-kill-destructor)))))
|
| 714 |
|
| 715 | (define hd-idle-service-type
|
| 716 | (service-type
|
| 717 | (name 'hd-idle)
|
| 718 | (extensions (list (service-extension shepherd-root-service-type
|
| 719 | hd-idle-shepherd-service)))
|
| 720 | (default-value (hd-idle-configuration))
|
| 721 | (description "Run @command{hd-idle}, which spins down hard disks that have
|
| 722 | not been accessed for a configurable period of time.")))
|