📶 metal: WiFi por ath10k (QCA9377) + cosmic-diag esperaba con reloj en vez de con hecho

WIFI. El OptiPlex 3060 SÍ tiene WiFi: `pci 0000:02:00.0: [168c:0042]` = Qualcomm
Atheros QCA9377. No aparecía interfaz porque el kernel sólo llevaba IWLWIFI. Añadido
ATH10K/ATH10K_PCI a linux-metal-dual + el firmware QCA9377 a la imagen + `wifi-up`.

El detalle que hace falta: con MODULES desactivado el driver va BUILTIN y prueba el
dispositivo a los ~5s pidiendo firmware, pero el rootfs se monta a los ~13s ⇒
`Direct firmware load failed -2` y la tarjeta queda muda, sin módulo que cargar
después. `wifi-up` fuerza un re-probe PCI (remove+rescan) con /lib/firmware ya
montado. Es la MISMA carrera que la del initramfs con el USB, un piso más abajo.

COSMIC-DIAG. La 1ª versión esperaba `sleep 50` y en esa máquina la sesión tarda ~105s
en llegar al compositor ⇒ el dmesg «después» se capturó ANTES de que cosmic-comp
arrancara y salió byte a byte idéntico al de antes. El viaje se gastó sin dato, y yo
leí ese dmesg vacío como «no hubo segfault», que era una conclusión sin respaldo.
Ahora espera al HECHO: que cosmic-comp aparezca y luego desaparezca (techo de 6 min).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-05 17:16:54 -04:00
co-authored by Claude Opus 5
parent 41e8b579d5
commit 095b876bba
2 changed files with 86 additions and 2 deletions
+1
View File
@@ -73,6 +73,7 @@ scripts/config -d MODULE_SIG -d MODULE_SIG_ALL -d DEBUG_INFO_BTF -d DEBUG_INFO -
-e ISO9660_FS -e JOLIET -e DEVTMPFS \
-e WLAN -e WIRELESS -e CFG80211 -e MAC80211 -e RFKILL \
-e WLAN_VENDOR_INTEL -e IWLWIFI -e IWLMVM -e IWLDVM \
-e WLAN_VENDOR_ATH -e ATH_COMMON -e ATH10K -e ATH10K_PCI \
-e ETHERNET -e NET_VENDOR_INTEL -e E1000 -e E1000E -e IGB -e IGC \
-e NET_VENDOR_REALTEK -e R8169 -e NET_VENDOR_BROADCOM -e TG3 \
-e USB_NET_DRIVERS -e USB_USBNET -e USB_NET_CDCETHER -e USB_NET_CDC_NCM -e USB_NET_RNDIS_HOST \
+85 -2
View File
@@ -174,10 +174,28 @@ cat > "$MERGED/usr/bin/cosmic-diag" <<'DIAG'
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
L=/var/log/cosmic
mkdir -p "$L"
echo "== cosmic-diag: corriendo la sesión y capturando todo en $L (unos 60s) =="
echo "== cosmic-diag: corriendo la sesión y capturando todo en $L =="
/bin/busybox dmesg > "$L/dmesg-antes.txt" 2>&1
cosmic-start > "$L/run.txt" 2>&1 &
sleep 50
# ⚠ NO usar un `sleep` fijo. La 1ª versión esperaba 50s y en el OptiPlex 3060 la sesión tarda ~105s
# en llegar al compositor (seatd, bus, logind, pipewire, wireplumber, cada uno con su espera) ⇒ el
# dmesg «después» se capturaba ANTES de que cosmic-comp arrancara, salía byte a byte idéntico al de
# antes, y el viaje se gastaba sin dato. Ahora se espera al HECHO, no al reloj: que cosmic-comp
# aparezca y después desaparezca. Ésa es la ventana donde el kernel diría un segfault.
vivo() { for c in /proc/[0-9]*/comm; do [ "$(cat "$c" 2>/dev/null)" = cosmic-comp ] && return 0; done; return 1; }
i=0; visto=0
while [ $i -lt 72 ]; do # 72 × 5s = 6 min de techo
if vivo; then
[ $visto = 0 ] && echo " cosmic-comp vivo (t=$((i*5))s), esperando a que muera o se estabilice"
visto=1
elif [ $visto = 1 ]; then
echo " cosmic-comp DESAPARECIÓ (t=$((i*5))s) — capturando dmesg"
break
fi
i=$((i + 1)); sleep 5
done
[ $visto = 0 ] && echo " ⚠ cosmic-comp nunca apareció en $((i*5))s — capturo igual"
sleep 2
/bin/busybox dmesg > "$L/dmesg-despues.txt" 2>&1
/bin/busybox sync
echo "== listo. Lo que importa: =="
@@ -190,6 +208,71 @@ echo "== evidencia completa en $L — apagá y traé el USB =="
DIAG
chmod 0755 "$MERGED/usr/bin/cosmic-diag"
# ── WiFi: la QCA9377 del OptiPlex, y por qué hace falta un re-probe ──────────────────────────────
# `pci 0000:02:00.0: [168c:0042]` = Qualcomm Atheros QCA9377, que va por `ath10k`. El kernel ahora lo
# lleva compilado dentro (MODULES está desactivado en esta receta), y ahí aparece un problema de
# ORDEN: un driver builtin prueba el dispositivo a los ~5 s y pide su firmware, pero el rootfs recién
# se monta a los ~13 s ⇒ `Direct firmware load failed -2` y la tarjeta queda muda para siempre. No hay
# módulo que cargar después. La salida es forzar un RE-PROBE del dispositivo PCI cuando /lib/firmware
# ya existe: `remove` + `rescan`. Es el mismo tipo de carrera que la del initramfs con el USB.
FWATH="${FWATH:-/usr/lib/firmware/ath10k}"
if [ -d "$FWATH/QCA9377" ]; then
n=0
for f in "$FWATH"/QCA9377/hw1.0/*.bin*; do
[ -r "$f" ] || continue
b="$(basename "$f")"; d="$MERGED/lib/firmware/ath10k/QCA9377/hw1.0"
mkdir -p "$d"
case "$b" in
*.zst) zstd -qdf "$f" -o "$d/${b%.zst}" 2>/dev/null && n=$((n+1)) ;;
*) cp -a "$f" "$d/" && n=$((n+1)) ;;
esac
done
echo "==> firmware ath10k/QCA9377: $n blobs"
else
echo " ⚠ sin $FWATH/QCA9377 — el WiFi de esa máquina no va a levantar"
fi
cat > "$MERGED/usr/bin/wifi-up" <<'WIFI'
#!/bin/sh
# wifi-up <SSID> <clave> — conecta la WiFi y muestra la IP para entrar por SSH.
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
SSID="$1"; PSK="$2"
[ -n "$SSID" ] || { echo "uso: wifi-up <SSID> <clave>"; exit 1; }
# Re-probe: ath10k pidió su firmware antes de que existiera /lib/firmware (ver el comentario de la
# imagen). Sin esto la tarjeta no aparece como interfaz aunque el driver esté.
for d in /sys/bus/pci/devices/*; do
[ "$(cat "$d/vendor" 2>/dev/null)" = "0x168c" ] || continue
echo "re-probando $(basename "$d") para que ath10k reintente el firmware…"
echo 1 > "$d/remove" 2>/dev/null; sleep 2
echo 1 > /sys/bus/pci/rescan 2>/dev/null; sleep 4
done
IF=""
for i in /sys/class/net/*; do
case "$(basename "$i")" in wlan*|wlp*) IF="$(basename "$i")"; break ;; esac
done
[ -n "$IF" ] || { echo "no apareció interfaz wifi. Mirá: dmesg | grep -i ath10k"; exit 1; }
echo "interfaz: $IF"
ip link set "$IF" up
printf 'network={\n\tssid="%s"\n\tpsk="%s"\n}\n' "$SSID" "$PSK" > /tmp/wpa.conf
wpa_supplicant -B -i "$IF" -c /tmp/wpa.conf -Dnl80211 || { echo "wpa_supplicant falló"; exit 1; }
sleep 6
cat > /tmp/udhcpc.script <<'US'
#!/bin/sh
case "$1" in
bound|renew)
ifconfig "$interface" "$ip" netmask "${subnet:-255.255.255.0}"
[ -n "$router" ] && route add default gw "${router%% *}" dev "$interface" 2>/dev/null
[ -n "$dns" ] && { : > /etc/resolv.conf; for d in $dns; do echo "nameserver $d" >> /etc/resolv.conf; done; }
;;
esac
exit 0
US
chmod +x /tmp/udhcpc.script
udhcpc -i "$IF" -n -q -s /tmp/udhcpc.script
ip -4 addr show "$IF" | grep -w inet || echo "sin IPv4 — ¿clave correcta? wpa_cli status"
echo "== desde el laptop: ssh -i ~/.ssh/hammer-metal root@<la IP de arriba> =="
WIFI
chmod 0755 "$MERGED/usr/bin/wifi-up"
# ── getty en tty1: el prompt TIENE que salir por la PANTALLA ────────────────────────────────────
# Lección del 1er viaje físico de KDE, que costó un USB quemado: el CMDLINE horneado es
# `console=tty0 console=ttyS0,115200 …` y el kernel hace /dev/console = la ÚLTIMA `console=` ⇒ ttyS0.