#1012152 firmware-amd-graphics: All firmware are included in initrd even in dep mode

#1012152#5
Date:
2022-05-30 21:04:41 UTC
From:
To:
Dear Maintainer,

Since the integration of built-in drivers in initramfs-tools (see
https://salsa.debian.org/kernel-team/initramfs-tools/-/merge_requests/35),
firmware files are also included with the corresponding kernel module.
I don't know why, but it only hits my system (AMD Ryzen PRO 4750G) since
May,
7th with Linux 5.17.0. Before that, amdgpu was NOT included in the initrd.

Now that it's included, it brings all firmwares for all AMD graphics card,
making the initrd from 11MB to 38MB. This has 3 drawbacks for me:
1. Building initrd is longer, so updates that trigger this take longer
2. Booting is also longer. It happens that even 1s faster matters to me ;)
3. My /boot partition is too small (182MB, hard to increase due to LUKS
partition after that), and I am hit by "no space left on device" (see
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=972396)

But on top of this, I know that I don't need all those firmwares. In fact,
amdgpu kindly reports which firmwares are loaded at start, so I made a hook
that removes everything but the needed files (see attached).

Now for some benchmarks. First, initrd extraction.

hyperfine -N --warmup 3 "lsinitramfs -l ./initrd.img-5.17.0-3-amd64.nohook"
"lsinitramfs -l ./initrd.img-5.17.0-3-amd64.hook"
Benchmark 1: lsinitramfs -l ./initrd.img-5.17.0-3-amd64.nohook
Time (mean ± σ): 130.7 ms ± 4.4 ms [User: 69.4 ms, System: 100.3 ms]
Range (min … max): 125.2 ms … 146.1 ms 22 runs

Benchmark 2: lsinitramfs -l ./initrd.img-5.17.0-3-amd64.hook
Time (mean ± σ): 68.8 ms ± 1.2 ms [User: 34.9 ms, System: 53.5 ms]
Range (min … max): 66.9 ms … 72.2 ms 42 runs

Summary
'lsinitramfs -l ./initrd.img-5.17.0-3-amd64.hook' ran
1.90 ± 0.07 times faster than 'lsinitramfs -l
./initrd.img-5.17.0-3-amd64.nohook'

So extracting initramfs is 90% faster.

Updating the initrd is less obvious. I use LZ4 for compression on my system,
with MODULES=dep

hyperfine "update-initramfs -u"
Benchmark 1: update-initramfs -u
Time (mean ± σ): 3.379 s ± 0.033 s [User: 2.856 s, System: 0.563 s]
Range (min … max): 3.341 s … 3.456 s 10 runs

Without the hook

hyperfine "update-initramfs -u"
Benchmark 1: update-initramfs -u
Time (mean ± σ): 4.175 s ± 0.048 s [User: 3.436 s, System: 0.738 s]
Range (min … max): 4.118 s … 4.261 s 10 runs

It is only 20% faster.

In the end, I am asking for code review in the hook I wrote. I know I missed
some cases, because I am not used this part of the system.

#1012152#10
Date:
2022-06-01 16:02:25 UTC
From:
To:
Hi,

I confirm that I have the same behavior with my work laptop that uses
i915, between Linux 5.16.0-6 and 5.17.0-1. The i915 driver was not
included, now it is, along with all i915 related firmware.

And it seems that the string "firmware: direct-loading" is present
whatever the driver, to list which file is really needed. Even for WiFi
or Bluetooth.

So I guess that this filtering could be generalized

#1012152#15
Date:
2022-06-01 22:23:35 UTC
From:
To:
Control: reassign -1 src:initramfs-tools
[...]

This really is unfortunate, but the way you've tried to fix wouldn't
work in general:

- Not all drivers log in the same way (at least in the upstream kernel)
- Those messages may have been expired from the kernel message buffer
  when mkinitramfs runs
- The firmware files requested by a driver can change between kernel
  versions

To solve this we would need kernel drivers to specify a mapping between
device IDs and firmware files.

One thing we could perhaps do in initramfs-tools is to add a
configuration variable that lets you override which firmware files get
included (like MODULES=list, but for firmware).  Would that work for
you?

Ben.

#1012152#24
Date:
2022-06-02 19:42:41 UTC
From:
To:
That's what I was asking advice. I feel really uncomfortable about
parsing kernel logs for deducing the next boot. I know that there are
some many ways to make it wrong :)
Yes, I hope this perfect world could exist. But I guess this mapping
exists somewhere in the driver to load the corresponding firmware. Or
the firmware has something like this in its headers.

That would be great. Since I can build my own list myself (based on
kernel logs ;) ), and only where it matters. In case of AMD GPU, the
list is huge. In case of i915, this is nearly useless, except to win at
most 2MB.

Thanks for your quick answer and helpful proposition!

Adrien