Survive kernel updates on a /boot this small
Some checks failed
build image / build (push) Has been cancelled
Some checks failed
build image / build (push) Has been cancelled
A dnf upgrade to 7.1.8 installed the kernel rpm cleanly, then ran /boot out of space. dracut wrote no initramfs, and because kernel-install stops at the first failing plugin, 95-c630-devicetree never ran either — leaving a boot entry with neither an initrd nor a devicetree line, which on this machine can never boot. dnf reported success and nothing retried. A kernel costs ~336 MiB here: a 210 MiB hostonly=no initramfs, a 98 MiB dtb-<kver> directory carrying every board's device tree, plus vmlinuz and System.map. Three of those cannot fit 1 GiB, so /boot goes to 2 GiB and installonly_limit drops to 2. Also fixes the quieter half of the same trap. snd-soc-wsa881x lives outside the kernel package, so the speakers go silent after any kernel update with nothing in the logs to explain it. c630-wsa881x rebuilds it and 96-c630-wsa881x.install calls it on each kernel-install add — always exiting 0, since a plugin failure is precisely what caused the damage above. grub.cfg gains the next_entry one-shot block that has been carried by hand all along, so testing a kernel costs a power cycle rather than a rescue. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011XgGF5wfxLDAybVnNz6eNQ
This commit is contained in:
23
overlay/etc/dnf/libdnf5.conf.d/50-c630-installonly.conf
Normal file
23
overlay/etc/dnf/libdnf5.conf.d/50-c630-installonly.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
# Keep two kernels, not the stock three.
|
||||
#
|
||||
# This machine's initramfs is unusually large — hostonly is off (see
|
||||
# /etc/dracut.conf.d/10-c630.conf) so every image carries the full driver and
|
||||
# firmware set, and each installed kernel costs roughly:
|
||||
#
|
||||
# initramfs ~210 MiB
|
||||
# dtb-<kver> ~98 MiB (kernel-core ships every board's device tree)
|
||||
# vmlinuz ~17 MiB
|
||||
# System.map ~11 MiB
|
||||
# ---------------------
|
||||
# total ~336 MiB
|
||||
#
|
||||
# Three of those is ~1008 MiB, which does not fit a 1 GiB /boot. The failure is
|
||||
# nastier than a full disk: dnf installs the kernel rpm successfully, then
|
||||
# dracut dies on ENOSPC, and because kernel-install stops at the first failing
|
||||
# plugin, 95-c630-devicetree never runs either. The result is a boot entry with
|
||||
# no initrd and no devicetree — unbootable — while dnf reports success and
|
||||
# never retries.
|
||||
#
|
||||
# Two kernels is ~672 MiB, which leaves comfortable headroom.
|
||||
[main]
|
||||
installonly_limit=2
|
||||
37
overlay/etc/kernel/install.d/96-c630-wsa881x.install
Executable file
37
overlay/etc/kernel/install.d/96-c630-wsa881x.install
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/bash
|
||||
#
|
||||
# Rebuild the speaker-amplifier module for each new kernel.
|
||||
#
|
||||
# snd-soc-wsa881x is not in any Fedora package (see c630-wsa881x), so it lives
|
||||
# in /lib/modules/<kver>/extra and has to be rebuilt whenever a kernel is
|
||||
# installed. Without this the speakers go silent the first time you run
|
||||
# `dnf upgrade`, and nothing in the logs connects the two events.
|
||||
#
|
||||
# This runs at 96, after 95-c630-devicetree, because it must not come between
|
||||
# 90-loaderentry.install — which rewrites the BLS entry — and the hook that
|
||||
# puts the devicetree line back.
|
||||
#
|
||||
# It always exits 0. kernel-install stops at the first plugin that fails, and
|
||||
# this machine has already been bitten once by that: a full /boot made
|
||||
# 50-dracut.install fail, which meant 95-c630-devicetree never ran, which left
|
||||
# a boot entry with neither an initrd nor a devicetree. Silent speakers are
|
||||
# worth a warning; they are not worth an unbootable machine.
|
||||
|
||||
set -u
|
||||
|
||||
COMMAND="${1:?}"
|
||||
KERNEL_VERSION="${2:?}"
|
||||
|
||||
[ "$COMMAND" = "add" ] || exit 0
|
||||
|
||||
if ! command -v c630-wsa881x >/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! c630-wsa881x "$KERNEL_VERSION"; then
|
||||
echo "96-c630-wsa881x: could not build snd-soc-wsa881x for ${KERNEL_VERSION};" \
|
||||
"the built-in speakers will be silent on that kernel until you run" \
|
||||
"'sudo c630-wsa881x ${KERNEL_VERSION}'" >&2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
78
overlay/usr/local/sbin/c630-wsa881x
Executable file
78
overlay/usr/local/sbin/c630-wsa881x
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/bash
|
||||
#
|
||||
# Build the speaker-amplifier driver Fedora does not ship.
|
||||
#
|
||||
# The C630's two WSA881x amplifiers sit on the WCD9340's SoundWire bus, and
|
||||
# Fedora's aarch64 kernel has never set CONFIG_SND_SOC_WSA881X — the newer
|
||||
# WSA883X and WSA884X the ThinkPad X13s needs are both =m, but this one was
|
||||
# missed. Without it the SoundWire slaves never bind, the machine driver cannot
|
||||
# find its DAIs, and the sound card sits in deferred probe forever: no card, no
|
||||
# speakers, no error that points anywhere useful.
|
||||
#
|
||||
# sound/soc/codecs/wsa881x.c is one self-contained file with no out-of-tree
|
||||
# patches, so building it against kernel-devel and dropping it in extra/ is
|
||||
# enough. Because it lives outside the kernel package, it has to be rebuilt for
|
||||
# every kernel — hence 96-c630-wsa881x.install, which calls this on each
|
||||
# kernel-install add. Audio otherwise goes silent the first time you take a
|
||||
# kernel update, with nothing in the logs to connect the two.
|
||||
#
|
||||
# The real fix is Fedora flipping the config; see docs/drafts/.
|
||||
#
|
||||
# Usage: c630-wsa881x [kernel-version] (defaults to the running kernel)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
KVER="${1:-$(uname -r)}"
|
||||
BUILD="/lib/modules/${KVER}/build"
|
||||
DEST="/lib/modules/${KVER}/extra/snd-soc-wsa881x.ko"
|
||||
|
||||
if [ -f "$DEST" ]; then
|
||||
echo "c630-wsa881x: ${DEST} already built"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Refuse rather than half-do it: a partial build leaves no module and no clue.
|
||||
missing=()
|
||||
[ -d "$BUILD" ] || missing+=("kernel-devel-${KVER}")
|
||||
command -v gcc >/dev/null || missing+=(gcc)
|
||||
command -v make >/dev/null || missing+=(make)
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
echo "c630-wsa881x: cannot build for ${KVER}, missing: ${missing[*]}" >&2
|
||||
echo "c630-wsa881x: install them and re-run 'c630-wsa881x ${KVER}'," \
|
||||
"or the built-in speakers will be silent on that kernel" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fedora's 7.1.8-200.fc44.aarch64 is upstream 7.1.8. A .0 upstream release is
|
||||
# tagged v7.1, not v7.1.0, so try both.
|
||||
base="${KVER%%-*}"
|
||||
tags=("v${base}")
|
||||
[ "${base}" != "${base%.0}" ] && tags+=("v${base%.0}")
|
||||
|
||||
work=$(mktemp -d)
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
|
||||
src=""
|
||||
for tag in "${tags[@]}"; do
|
||||
url="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/plain/sound/soc/codecs/wsa881x.c?h=${tag}"
|
||||
if curl -fsSL --retry 3 -o "$work/wsa881x.c" "$url"; then
|
||||
echo "c630-wsa881x: fetched wsa881x.c at ${tag}"
|
||||
src="$tag"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$src" ]; then
|
||||
echo "c630-wsa881x: could not fetch wsa881x.c for ${KVER} (tried: ${tags[*]})" >&2
|
||||
echo "c630-wsa881x: needs network; re-run 'c630-wsa881x ${KVER}' once online" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "$work/Makefile" <<'EOF'
|
||||
obj-m += snd-soc-wsa881x.o
|
||||
snd-soc-wsa881x-objs := wsa881x.o
|
||||
EOF
|
||||
|
||||
make -C "$BUILD" M="$work" modules
|
||||
install -D -m 0644 "$work/snd-soc-wsa881x.ko" "$DEST"
|
||||
depmod -a "$KVER"
|
||||
echo "c630-wsa881x: installed ${DEST}"
|
||||
Reference in New Issue
Block a user