nas08-scripts/NAS08-Kernel-Recovery-Summary.html
2026-07-26 21:34:22 -04:00

682 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KingDezigns — NAS08 Kernel Recovery Summary</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500&family=IBM+Plex+Sans:wght@400;500&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f7f6f2;
--surface: #ffffff;
--surface-alt: #f1f0eb;
--border: #e2e0d8;
--border-strong: #c8c5ba;
--text-primary: #1a1917;
--text-secondary: #6b6960;
--text-muted: #9b9890;
--green-bg: #eaf3de;
--green-border: #97c459;
--green-text: #2d5a0e;
--red-bg: #fcebeb;
--red-border: #f09595;
--red-text: #7a1f1f;
--amber-bg: #faeeda;
--amber-border: #fac775;
--amber-text: #633806;
--coral-bg: #faece7;
--coral-border: #f0997b;
--coral-text: #4a1b0c;
--mono: 'IBM Plex Mono', monospace;
--sans: 'IBM Plex Sans', sans-serif;
}
body {
font-family: var(--sans);
font-size: 14px;
background: var(--bg);
color: var(--text-primary);
line-height: 1.7;
padding: 2.5rem 1.5rem;
}
.page { max-width: 860px; margin: 0 auto; }
header {
border-bottom: 1px solid var(--border-strong);
padding-bottom: 1.25rem;
margin-bottom: 2rem;
}
header h1 {
font-family: var(--mono);
font-size: 18px;
font-weight: 500;
letter-spacing: -0.02em;
margin-bottom: 6px;
}
.meta {
font-size: 12px;
color: var(--text-muted);
font-family: var(--mono);
display: flex;
gap: 16px;
flex-wrap: wrap;
}
.section { margin-bottom: 2.25rem; }
.section-title {
font-family: var(--mono);
font-size: 11px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 10px;
}
.section-title::before {
content: attr(data-num);
background: var(--text-primary);
color: var(--bg);
font-size: 10px;
width: 18px;
height: 18px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.section-title::after {
content: '';
flex: 1;
height: 1px;
background: var(--border);
}
p { margin-bottom: 0.75rem; color: var(--text-primary); }
p:last-child { margin-bottom: 0; }
.badge-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 1rem; }
.badge {
font-family: var(--mono);
font-size: 11px;
padding: 3px 10px;
border-radius: 3px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text-secondary);
}
.badge.red { background: var(--red-bg); color: var(--red-text); border-color: var(--red-border); }
.badge.green { background: var(--green-bg); color: var(--green-text); border-color: var(--green-border); }
.badge.amber { background: var(--amber-bg); color: var(--amber-text); border-color: var(--amber-border); }
.step {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 6px;
padding: 1rem 1.25rem;
margin-bottom: 0.6rem;
}
.step-header {
font-family: var(--mono);
font-size: 12px;
font-weight: 500;
color: var(--text-secondary);
margin-bottom: 0.6rem;
display: flex;
align-items: center;
gap: 8px;
}
.step-num {
background: var(--surface-alt);
border: 1px solid var(--border);
border-radius: 50%;
width: 20px;
height: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 10px;
flex-shrink: 0;
color: var(--text-muted);
}
pre {
background: var(--surface-alt);
border: 1px solid var(--border);
border-radius: 4px;
padding: 10px 12px;
font-family: var(--mono);
font-size: 12px;
overflow-x: auto;
margin: 0.5rem 0;
white-space: pre;
line-height: 1.6;
}
code {
font-family: var(--mono);
font-size: 12px;
background: var(--surface-alt);
padding: 1px 5px;
border-radius: 3px;
border: 1px solid var(--border);
}
.why {
font-size: 12px;
color: var(--text-muted);
margin-top: 0.4rem;
padding-left: 2px;
}
.why::before { content: '↳ why: '; font-family: var(--mono); }
.result { font-size: 12px; margin-top: 0.35rem; padding-left: 2px; }
.result.pass { color: var(--green-text); }
.result.pass::before { content: '✓ '; font-family: var(--mono); }
.result.fail { color: var(--red-text); }
.result.fail::before { content: '✗ '; font-family: var(--mono); }
.result.neutral { color: var(--text-secondary); }
.result.neutral::before { content: '→ '; font-family: var(--mono); }
.callout { border-radius: 6px; padding: 1rem 1.25rem; margin-bottom: 0.75rem; }
.callout.coral { background: var(--coral-bg); border: 1px solid var(--coral-border); }
.callout.coral p { color: var(--coral-text); }
.callout.coral pre { background: #fdf0eb; border-color: var(--coral-border); }
.callout.amber { background: var(--amber-bg); border: 1px solid var(--amber-border); }
.callout.amber p { color: var(--amber-text); }
.callout.amber pre { background: #fdf5e6; border-color: var(--amber-border); }
.callout.amber code { background: #fdf5e6; border-color: var(--amber-border); color: var(--amber-text); }
.callout.green { background: var(--green-bg); border: 1px solid var(--green-border); }
.callout.green p { color: var(--green-text); }
.callout.green pre { background: #d8efc0; border-color: var(--green-border); }
.clue-label {
font-family: var(--mono);
font-size: 10px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--amber-text);
margin-bottom: 8px;
}
.script-box { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.script-row { padding: 0.75rem 1.25rem; border-bottom: 1px solid var(--border); }
.script-row:last-child { border-bottom: none; }
.script-label { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); margin-bottom: 6px; }
.script-row pre { margin: 0; }
table { width: 100%; border-collapse: collapse; font-size: 13px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
th { text-align: left; padding: 8px 14px; font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); background: var(--surface-alt); border-bottom: 1px solid var(--border); font-weight: 500; }
td { padding: 9px 14px; border-bottom: 1px solid var(--border); vertical-align: top; line-height: 1.5; }
tr:last-child td { border-bottom: none; }
.footer {
font-family: var(--mono);
font-size: 11px;
color: var(--text-muted);
margin-top: 2.5rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 8px;
}
</style>
</head>
<body>
<div class="page">
<header>
<h1>KingDezigns — NAS08 Kernel Recovery Summary</h1>
<div class="meta">
<span>📅 May 1516, 2026</span>
<span>🖥 NAS08 — Raspberry Pi 5 Model B Rev 1.1</span>
<span>⚙️ OpenMediaVault 8.2.13 / Debian Trixie</span>
<span>🔌 Radxa Penta SATA HAT (JMB585)</span>
<span>🐧 Kernel 6.12.75 → 6.18.29 → rolled back → 6.18.29 (fixed)</span>
</div>
</header>
<!-- SECTION 1 — THE PROBLEM -->
<div class="section">
<div class="section-title" data-num="1">The problem</div>
<p>After a routine apt upgrade that included a kernel jump from 6.12 to 6.18 and a new <code>raspi-firmware</code> package, NAS08 lost all four SATA data drives connected via the Radxa Penta SATA HAT. ZFS reported no pools available and OMV could not see the drives.</p>
<div class="badge-row">
<span class="badge red">zpool status: no pools available</span>
<span class="badge red">ahci: failed to start port 0 (errno=-12)</span>
<span class="badge red">lsblk: sdb/sdc/sdd/sde missing</span>
<span class="badge red">BAR 0 [io size 0x0080]: can't assign; no space</span>
<span class="badge amber">DMA32: empty</span>
</div>
<p>The upgrade included <code>linux-image-6.18.29+rpt-rpi-2712</code>, <code>raspi-firmware 1:1.20260513-1</code>, and <code>openmediavault 8.2.13-1</code> among 20+ packages. The Radxa Penta SATA HAT uses a JMicron JMB585 PCIe SATA controller. An upstream kernel commit (ee95f3c) affecting the JMB585 chipset means kernel 6.18 now requires the <code>pcie-32bit-dma-pi5</code> device tree overlay for the controller to allocate DMA memory successfully. This overlay was present in <code>config.txt</code> but placed under the <code>[cm5]</code> conditional section, which is ignored on a Raspberry Pi 5 Model B. As a result, the overlay never loaded and the JMB585 had no DMA32 address space.</p>
</div>
<!-- SECTION 2 — DIAGNOSTIC COMMANDS -->
<div class="section">
<div class="section-title" data-num="2">Diagnostic commands run &amp; why</div>
<div class="step">
<div class="step-header"><span class="step-num">1</span> Confirm ZFS module is loaded</div>
<pre>lsmod | grep zfs</pre>
<p class="why">Rule out ZFS module as the cause — if it's not loaded, drives won't be visible to any pool.</p>
<p class="result pass">ZFS module loaded correctly — zfs and spl both present. Not the cause.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">2</span> Check running kernel vs installed kernels</div>
<pre>uname -r
dpkg -l | grep linux-image</pre>
<p class="why">Confirm which kernel booted and whether a version mismatch caused the issue.</p>
<p class="result neutral">Booted into 6.18.29 — confirmed the kernel jump from 6.12 happened. Both versions still installed.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">3</span> Check if OS sees the drives at all</div>
<pre>lsblk
ls /dev/disk/by-id/</pre>
<p class="why">Determine if the problem is at the ZFS layer or the OS/hardware layer.</p>
<p class="result fail">Only boot SSD visible. Data drives completely absent — hardware/driver level problem confirmed.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">4</span> Check dmesg for USB/SATA/PCIe errors</div>
<pre>dmesg | grep -iE "usb|sd|storage|attach|disconnect|reset" | grep -v "loop\|zram\|firmware" | tail -60</pre>
<p class="why">Identify whether drives were seen at boot and then lost, or never detected at all.</p>
<p class="result fail">Only one USB device detected at boot (boot SSD). No SATA drives enumerated. Pointed to PCIe HAT issue.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">5</span> Check PCIe controller visibility</div>
<pre>lspci</pre>
<p class="why">Confirm whether the JMicron JMB585 SATA controller on the Radxa HAT is being detected by the PCIe bus.</p>
<p class="result neutral">JMicron JMB585 visible at 0001:01:00.0 — controller detected but not functional.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">6</span> Check PCIe BAR assignment errors</div>
<pre>dmesg | grep -iE "pcie|pci|ahci|sata|asm|jmb|asmedia" | head -40</pre>
<p class="why">Identify why the detected controller isn't working — look for resource allocation failures.</p>
<p class="result fail">BAR 04 all failed to assign I/O space. PCI bridge showed zero-length address range. AHCI errno=-12 (ENOMEM).</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">7</span> Check DMA memory layout</div>
<pre>cat /proc/meminfo | grep -i cma
dmesg | grep -iE "cma|dma|coherent" | head -20</pre>
<p class="why">Determine why AHCI port start was failing with ENOMEM — check DMA zone availability.</p>
<p class="result fail">DMA32 zone empty. CmaFree: 0 kB. JMB585 forced into 32-bit DMA mode with no available DMA32 address space.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">8</span> Check hardware identity</div>
<pre>cat /proc/device-tree/model</pre>
<p class="why">Confirm exact hardware model — critical for applying the correct config.txt overlay section.</p>
<p class="result neutral">Raspberry Pi 5 Model B Rev 1.1 — confirmed Pi 5, not CM5. This meant the [cm5] section in config.txt was being ignored.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">9</span> Check config.txt overlay placement</div>
<pre>cat /boot/firmware/config.txt</pre>
<p class="why">Identify whether the pcie-32bit-dma-pi5 overlay was present and in the correct conditional section.</p>
<p class="result fail">Overlay was present but under [cm5] section — ignored on Pi 5. Moving it to [all] section was the fix.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">10</span> Check EEPROM version and config</div>
<pre>sudo rpi-eeprom-update
sudo rpi-eeprom-config</pre>
<p class="why">Determine if pci=pcie_bus_safe was coming from the EEPROM bootloader config.</p>
<p class="result neutral">EEPROM was 5 months out of date. Updated during recovery session.</p>
</div>
</div>
<!-- SECTION 3 — ROOT CAUSE -->
<div class="section">
<div class="section-title" data-num="3">Root cause</div>
<div class="callout coral">
<p>An upstream Linux kernel commit (ee95f3c) changed how the JMB585 PCIe SATA controller allocates DMA memory on kernel 6.18. The JMB585 now requires the <code>pcie-32bit-dma-pi5</code> device tree overlay to function correctly. This overlay was present in <code>/boot/firmware/config.txt</code> but placed under the <code>[cm5]</code> conditional section, which is silently ignored on a Raspberry Pi 5 Model B. As a result the overlay never loaded, the JMB585 had no DMA32 address space, and AHCI failed with ENOMEM on every port start attempt.</p>
</div>
<div class="callout amber">
<div class="clue-label">⚠ Key clue</div>
<p style="margin-bottom:6px;">The config.txt overlay section mismatch was the root cause. The overlay fix was correct — it was simply applied to the wrong conditional block during the initial recovery attempt.</p>
<pre># Wrong — ignored on Pi 5 Model B:
[cm5]
dtoverlay=pcie-32bit-dma-pi5
# Correct — applies to all Pi hardware:
[all]
dtoverlay=pcie-32bit-dma-pi5</pre>
<p style="margin-top:8px;">The kernel 6.18 requirement for <code>pcie-32bit-dma-pi5</code> on JMB585 hardware is documented upstream. Any Pi 5 running kernel 6.18 with this HAT requires this overlay in the <code>[all]</code> or <code>[pi5]</code> section of config.txt.</p>
</div>
<div class="callout green" style="margin-top:0.75rem;">
<p><strong>Resolution:</strong> Moved <code>dtoverlay=pcie-32bit-dma-pi5</code> from the <code>[cm5]</code> section to the <code>[all]</code> section in <code>/boot/firmware/config.txt</code>, then copied the 6.18.29 kernel binary back to <code>/boot/firmware/kernel_2712.img</code> and rebooted. All four SATA drives appeared immediately on kernel 6.18.</p>
</div>
</div>
<!-- SECTION 4 — RECOVERY PROCEDURE -->
<div class="section">
<div class="section-title" data-num="4">Recovery procedure applied</div>
<div class="step">
<div class="step-header"><span class="step-num">1</span> Roll back to kernel 6.12 (initial emergency recovery)</div>
<pre>sudo apt-mark hold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8 linux-image-6.18.29+rpt-rpi-2712 linux-image-6.18.29+rpt-rpi-v8
sudo cp /boot/vmlinuz-6.12.75+rpt-rpi-2712 /boot/firmware/kernel_2712.img
sudo cp /boot/vmlinuz-6.12.75+rpt-rpi-v8 /boot/firmware/kernel8.img
sudo reboot</pre>
<p class="why">Immediately restored drive visibility on 6.12 while the root cause was investigated. Holds prevented the firmware hook from re-upgrading kernel_2712.img on reboot.</p>
<p class="result pass">All four drives (sdb/sdc/sdd/sde) returned on 6.12.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">2</span> Fix the overlay placement in config.txt</div>
<pre>sudo nano /boot/firmware/config.txt
# Remove dtoverlay=pcie-32bit-dma-pi5 from the [cm5] section
# Add it to the [all] section instead:
[cm5]
dtoverlay=dwc2,dr_mode=host
[all]
dtoverlay=pcie-32bit-dma-pi5</pre>
<p class="why">The overlay was present but in the wrong conditional section. Moving it to [all] ensures it applies to the Pi 5 Model B hardware.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">3</span> Unhold packages and copy 6.18 kernel back</div>
<pre>sudo apt-mark unhold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8 linux-image-6.18.29+rpt-rpi-2712 linux-image-6.18.29+rpt-rpi-v8
sudo cp /boot/vmlinuz-6.18.29+rpt-rpi-2712 /boot/firmware/kernel_2712.img
sudo cp /boot/vmlinuz-6.18.29+rpt-rpi-v8 /boot/firmware/kernel8.img
sudo reboot</pre>
<p class="why">6.18 was already installed — only the kernel_2712.img binary needed updating. The overlay fix was now in place before boot.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">4</span> Verify and re-apply holds</div>
<pre>uname -r # should show 6.18.29+rpt-rpi-2712
lsblk # should show sdb sdc sdd sde
sudo zpool status
sudo apt-mark hold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8 linux-image-6.18.29+rpt-rpi-2712 linux-image-6.18.29+rpt-rpi-v8
sudo apt-mark showhold</pre>
<p class="result pass">All four drives present on 6.18.29. ZFS pool ONLINE. Holds re-applied to prevent uncontrolled kernel upgrades.</p>
</div>
</div>
<!-- SECTION 5 — EMERGENCY ROLLBACK -->
<div class="section">
<div class="section-title" data-num="5">Emergency rollback — if a future upgrade breaks drives again</div>
<p>If a future upgrade causes drives to disappear again, this is the fast rollback procedure. Takes less than 5 minutes.</p>
<div class="step">
<div class="step-header"><span class="step-num">1</span> Hold packages immediately</div>
<pre>sudo apt-mark hold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8 linux-image-6.18.29+rpt-rpi-2712 linux-image-6.18.29+rpt-rpi-v8</pre>
<p class="why">The z50-raspi-firmware hook overwrites kernel_2712.img on every apt operation. Hold first to stop this.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">2</span> Copy 6.12 kernel directly over the firmware kernel image</div>
<pre>sudo cp /boot/vmlinuz-6.12.75+rpt-rpi-2712 /boot/firmware/kernel_2712.img
sudo cp /boot/vmlinuz-6.12.75+rpt-rpi-v8 /boot/firmware/kernel8.img
# Verify sizes — should be 9698043 and 9695883
ls -la /boot/firmware/kernel_2712.img /boot/firmware/kernel8.img</pre>
<p class="why">raspi-firmware boots whichever kernel is in kernel_2712.img directly. Replacing it with 6.12 forces the rollback.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">3</span> Reboot and confirm</div>
<pre>sudo reboot
# After reboot:
uname -r # should show 6.12.75+rpt-rpi-2712
lsblk # should show sdb sdc sdd sde
sudo zpool status</pre>
<p class="result pass">Drives and ZFS pools return immediately on 6.12.</p>
</div>
</div>
<!-- SECTION 6 — SCRIPTS CREATED -->
<div class="section">
<div class="section-title" data-num="6">Scripts created this session</div>
<div class="script-box">
<div class="script-row">
<div class="script-label">NAS08 ZFS Health Report</div>
<pre>zfs_report_nas08.sh</pre>
</div>
<div class="script-row">
<div class="script-label">NAS16 ZFS Health Report</div>
<pre>zfs_report_nas16.sh</pre>
</div>
<div class="script-row">
<div class="script-label">Commands executed per run</div>
<pre>zpool status -v &lt;pool&gt;
zpool list -H -o name,size,alloc,free,frag,cap,health &lt;pool&gt;
zfs list -r -H -o name,used,avail,refer,mountpoint &lt;pool&gt;</pre>
</div>
<div class="script-row">
<div class="script-label">Deploy &amp; schedule (cron)</div>
<pre>chmod +x zfs_report_nas08.sh
sudo mv zfs_report_nas08.sh /opt/scripts/
# Add to crontab — runs daily at 7:00 AM:
0 7 * * * /opt/scripts/zfs_report_nas08.sh >> /var/log/zfs_report.log 2>&amp;1</pre>
</div>
<div class="script-row">
<div class="script-label">Email recipient</div>
<pre>rufus.king@kingdezigns.com</pre>
</div>
</div>
</div>
<!-- SECTION 7 — NAS16 PROTECTION -->
<div class="section">
<div class="section-title" data-num="7">NAS16 — apply same fix</div>
<p>NAS16 runs the identical Radxa Penta SATA HAT on a Raspberry Pi 5. It will hit the exact same kernel 6.18 / JMB585 DMA issue if updated without the overlay fix in place. SSH into NAS16 and follow these steps.</p>
<div class="step">
<div class="step-header"><span class="step-num">1</span> Hold kernel and firmware packages on NAS16</div>
<pre>sudo apt-mark hold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8
sudo apt-mark showhold</pre>
<p class="why">Prevents kernel 6.18 and new raspi-firmware from installing automatically while the config.txt fix is applied.</p>
<p class="result pass">Expected: all packages listed as held.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">2</span> Confirm hardware identity</div>
<pre>cat /proc/device-tree/model</pre>
<p class="why">Verify NAS16 is also a Pi 5 Model B so the [all] section placement is correct.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">3</span> Fix the overlay placement in config.txt</div>
<pre>sudo nano /boot/firmware/config.txt
# Ensure pcie-32bit-dma-pi5 is in the [all] section:
[all]
dtoverlay=pcie-32bit-dma-pi5</pre>
<p class="why">Same fix as NAS08 — overlay must be in [all], not [cm5], to apply on Pi 5 hardware.</p>
</div>
<div class="step">
<div class="step-header"><span class="step-num">4</span> Unhold, upgrade, and reboot</div>
<pre>sudo apt-mark unhold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8
sudo apt upgrade
sudo cp /boot/vmlinuz-6.18.29+rpt-rpi-2712 /boot/firmware/kernel_2712.img
sudo cp /boot/vmlinuz-6.18.29+rpt-rpi-v8 /boot/firmware/kernel8.img
sudo reboot</pre>
</div>
<div class="step">
<div class="step-header"><span class="step-num">5</span> Verify and re-hold</div>
<pre>uname -r
lsblk
sudo zpool status
sudo apt-mark hold raspi-firmware linux-image-rpi-2712 linux-image-rpi-v8 linux-image-6.18.29+rpt-rpi-2712 linux-image-6.18.29+rpt-rpi-v8</pre>
<p class="result pass">Expected: sdb sdc sdd sde all present, uname shows 6.18.x, ZFS ONLINE.</p>
</div>
</div>
<!-- SECTION 8 — LESSONS LEARNED -->
<div class="section">
<div class="section-title" data-num="8">Lessons learned</div>
<table>
<thead>
<tr><th>Lesson</th><th>Detail</th></tr>
</thead>
<tbody>
<tr>
<td>Always identify exact hardware before troubleshooting</td>
<td>Run <code>cat /proc/device-tree/model</code> at the start of every session. The initial recovery misidentified NAS08 as a CM5, which placed the overlay fix under [cm5] where it was silently ignored on the Pi 5 Model B.</td>
</tr>
<tr>
<td>Never update both NAS systems at the same time</td>
<td>Update NAS08 first, confirm stable for 48hrs, then update NAS16. This approach would have prevented both systems from failing simultaneously.</td>
</tr>
<tr>
<td>config.txt conditional sections are silently ignored</td>
<td>Overlays placed under [cm4] or [cm5] are completely ignored on Pi 5 Model B hardware. There is no warning or error. Always verify placement with <code>cat /proc/device-tree/model</code> first.</td>
</tr>
<tr>
<td>Kernel 6.18 requires pcie-32bit-dma-pi5 for JMB585</td>
<td>Upstream commit ee95f3c changed DMA behaviour for the JMB585 chipset. Any Pi 5 running kernel 6.18 with the Radxa Penta SATA HAT must have <code>dtoverlay=pcie-32bit-dma-pi5</code> in the <code>[all]</code> section of config.txt or drives will not appear.</td>
</tr>
<tr>
<td>Hold kernel packages on all Pi-based NAS systems</td>
<td>Kernel updates can silently break HAT compatibility. Always hold and update deliberately, never via unattended-upgrades.</td>
</tr>
<tr>
<td>raspi-firmware manages kernel_2712.img directly</td>
<td>The post-install hook z50-raspi-firmware copies the kernel directly to /boot/firmware/kernel_2712.img. Copying an older kernel binary over this file is the correct rollback mechanism. Hold raspi-firmware before doing so or it will be overwritten on next boot.</td>
</tr>
<tr>
<td>Always simulate before upgrading</td>
<td>Run <code>sudo apt upgrade --simulate 2>&1 | grep -E "raspi-firmware|linux-image|linux-headers|Inst|Remv"</code> before every upgrade. If any kernel or firmware packages appear as Inst lines, investigate before proceeding.</td>
</tr>
</tbody>
</table>
</div>
<!-- SECTION 9 — CONFIG FILE REFERENCE -->
<div class="section">
<div class="section-title" data-num="9">Current working config — NAS08</div>
<p>This is the known-good configuration for NAS08 on kernel 6.18.29 with all four SATA drives visible and ZFS healthy.</p>
<div class="script-box">
<div class="script-row">
<div class="script-label">/boot/firmware/config.txt — bottom section</div>
<pre># Enable PCIe
dtparam=pciex1
dtparam=pciex1_gen=3
[cm4]
otg_mode=1
[cm5]
dtoverlay=dwc2,dr_mode=host
[all]
dtoverlay=pcie-32bit-dma-pi5</pre>
</div>
<div class="script-row">
<div class="script-label">/boot/firmware/cmdline.txt</div>
<pre>console=serial0,115200 console=tty1 root=PARTUUID=57cb028e-02 rootfstype=ext4 fsck.repair=yes rootwait cfg80211.ieee80211_regdom=US</pre>
</div>
<div class="script-row">
<div class="script-label">Active kernel</div>
<pre>6.18.29+rpt-rpi-2712</pre>
</div>
<div class="script-row">
<div class="script-label">Held packages</div>
<pre>raspi-firmware
linux-image-rpi-2712
linux-image-rpi-v8
linux-image-6.18.29+rpt-rpi-2712
linux-image-6.18.29+rpt-rpi-v8</pre>
</div>
</div>
</div>
<!-- SECTION 10 — NETWORK MAP -->
<div class="section">
<div class="section-title" data-num="10">Network map — items to update</div>
<table>
<thead>
<tr><th>Item</th><th>Old value</th><th>New value</th></tr>
</thead>
<tbody>
<tr>
<td>NAS08 kernel version</td>
<td><code>6.12.75+rpt-rpi-2712</code></td>
<td><code>6.18.29+rpt-rpi-2712 (held)</code></td>
</tr>
<tr>
<td>NAS08 config.txt overlay</td>
<td><code>pcie-32bit-dma-pi5 under [cm5] — ignored</code></td>
<td><code>pcie-32bit-dma-pi5 under [all] — active</code></td>
</tr>
<tr>
<td>NAS08 raspi-firmware</td>
<td><code>auto-update enabled</code></td>
<td><code>held at 1:1.20260513-1</code></td>
</tr>
<tr>
<td>NAS16 kernel + overlay fix</td>
<td><code>6.12.75 — pending upgrade</code></td>
<td><code>apply config.txt fix first, then upgrade to 6.18.29</code></td>
</tr>
<tr>
<td>ZFS report scripts</td>
<td><code>not deployed</code></td>
<td><code>zfs_report_nas08.sh + zfs_report_nas16.sh — deploy to /opt/scripts/</code></td>
</tr>
</tbody>
</table>
</div>
<div class="footer">
<span>KingDezigns Home Network</span>
<span>Updated May 16, 2026</span>
</div>
</div>
</body>
</html>