Using Ansible to alter Kernel Parameters

For months, I’ve had a peculiar problem with my laptop: once in a while, seemingly without reason, my laptop screen would freeze. This only happened on my laptop screen, and not on an external monitor. I had kind of learned to live with it as I couldn’t find a solution online. The only remedy I had was reloading my window manager, which would often unfreeze the screen.

Yesterday I tried Googling once more and I actually found a thread about it on the Arch Linux forums! They talk about the same laptop model, the Lenovo ThinkPad x260, having the problem. Fortunately, they also propose a temporary fix.

Trying the Fix

Apparently, a problem with the Panel Self Refresh (PSR) feature of Intel iGPUs is the culprit. According to the Linux source code, PSR enables the display to go into a lower standby mode when the sytem is idle but the screen is in use. These lower standby modes can reduce power usage of your device when idling.

This all seems useful, except when it makes your screen freeze! The proposed fix disables the PSR feature entirely. To do this, we need to change a parameter to the Intel Graphics Linux Kernel Module (LKM). The LKM for Intel Graphics is called i915. There are multiple ways to change kernel parameters, but I chose to edit my Grub configuration.

First, I wanted to test whether it actually works. When booting into my Linux partition via Grub, you can press e to edit the Grub definition. Somewhere there, you can find the linux command which specifies to boot Linux and how to do that. I simply appended the option i915.enable_psr=0 to this line. After rebooting, I noticed my screen no longer freezes! Success!

Persisting the Fix

To make the change permanent, we need to permanently change Grub’s configuration. One way to do this, is by changing Grub’s defaults in /etc/default/grub. Namely, the GRUB_CMDLINE_LINUX_DEFAULT option specifies what options Grub should pass to the Linux kernel by default. For me, this is a nice solution as the problem exists for both Linux OSes I have installed. I changed this option to:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i915.enable_psr=0"

Next, I wanted to automate this solution using Ansible. This turned out to be quite easy, as the Grub configuration looks a bit like an ini file (maybe it is?):

- name: Edit grub to disable Panel Self Refresh
  become: true
  ini_file:
    path: /etc/default/grub
    section: null
    option: "GRUB_CMDLINE_LINUX_DEFAULT"
    value: '"quiet splash i915.enable_psr=0"'
    no_extra_spaces: true
  notify: update grub

Lastly, I created the notify hook to update the Grub configuration:

- name: update grub
  become: true
  command:
    cmd: update-grub

Update: Just use Nix

Lately, I have been learning a bit of NixOS with the intention of replacing my current setup. Compared to Ansible, applying this fix is a breeze on NixOS:

{
  boot.kernelParams = [ "i915.enable_psr=0" ];
}

That’s it, yep.

Conclusion

It turned out to be quite easy to change Linux kernel parameters using Ansible. Maybe some kernel gurus have better ways to change parameters, but this works for me for now.

As a sidenote, I started reading a bit more about NixOS and realised that it can solve issues like these much more nicely than Ansible does. I might replace my OS with NixOS some day, if I manage to rewrite my Ansible for it.