<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Proxmox on Andy Little</title><link>https://andylittle.net/tags/proxmox/</link><description>Recent content in Proxmox on Andy Little</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Wed, 29 Jul 2026 12:00:00 -0500</lastBuildDate><atom:link href="https://andylittle.net/tags/proxmox/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting Fan RPM Out of a Lenovo M900 Tiny via lm-sensors</title><link>https://andylittle.net/blog/2026/nct6683-fan-rpm-lenovo-m900-tiny/</link><pubDate>Wed, 29 Jul 2026 12:00:00 -0500</pubDate><guid>https://andylittle.net/blog/2026/nct6683-fan-rpm-lenovo-m900-tiny/</guid><description>lm-sensors&amp;rsquo; nct6683 driver silently refused to bind on a Lenovo M900 Tiny running Proxmox — no error, just no fan data. The cause was a vendor/build check in the driver tripping on this box&amp;rsquo;s EC firmware, and the fix was a one-line force=1 module param made persistent.</description><content:encoded><![CDATA[<p><code>pve-m900-1</code>, a Lenovo M900 Tiny, is one of the small Proxmox boxes in my
homelab — it runs dev/test workloads and the NetFlow collector VM. It has no
spinning disk (single SSD), so the only moving part worth monitoring is the
fan. <code>sensors</code> was already showing <code>coretemp</code> and PECI temperatures just
fine, but no fan RPM at all — not a zero, just absent, as if the box didn&rsquo;t
have a fan sensor.</p>
<h2 id="the-dead-end-no-error-just-nothing">The dead end: no error, just nothing</h2>
<p>The Super I/O chip on these Tiny-series boards is a Nuvoton NCT6683, and the
matching kernel driver is <code>nct6683</code> (part of <code>lm-sensors</code>). Normally you
<code>modprobe nct6683</code>, run <code>sensors-detect</code>, and get <code>fan1</code>/<code>fan2</code> readings for
free. Here, <code>modprobe nct6683</code> returned cleanly, but <code>sensors</code> still showed no
fan entry:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">modprobe nct6683
</span></span><span class="line"><span class="cl">sensors
</span></span><span class="line"><span class="cl"><span class="c1"># coretemp-isa-0000 and peci entries present, no nct6683 block at all</span>
</span></span><span class="line"><span class="cl">dmesg <span class="p">|</span> grep -i nct6683
</span></span><span class="line"><span class="cl"><span class="c1"># (nothing)</span>
</span></span></code></pre></div><p>No error message, no log line, nothing in <code>dmesg</code> — the module just wasn&rsquo;t
registering a device. That absence of any error is the tell: this isn&rsquo;t a
missing-driver problem, it&rsquo;s a driver that loaded and then quietly declined
to attach to the hardware.</p>
<h2 id="the-cause-an-ec-firmwarevendor-check">The cause: an EC firmware/vendor check</h2>
<p>The <code>nct6683</code> driver does a sanity check against the embedded controller&rsquo;s
firmware build ID before it will bind — it&rsquo;s a safety measure, since writing
to the wrong registers on an unrecognized EC build can do bad things. This
M900 Tiny&rsquo;s EC firmware build (<code>1.0 build 12/30/15</code>) isn&rsquo;t in the driver&rsquo;s
list of known-good builds, so the check fails and the driver bails out with
<code>ENODEV</code> before ever creating the sensor device — silently, since this is
treated as &ldquo;unsupported hardware,&rdquo; not an error condition.</p>
<p>The driver exposes an escape hatch for exactly this: a <code>force</code> module
parameter that skips the vendor/build check and binds anyway.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">modprobe -r nct6683
</span></span><span class="line"><span class="cl">modprobe nct6683 <span class="nv">force</span><span class="o">=</span><span class="m">1</span>
</span></span><span class="line"><span class="cl">sensors
</span></span></code></pre></div><p>With <code>force=1</code>, <code>sensors</code> immediately reports a new block with <code>fan2</code> reading
a baseline of roughly 980 RPM, alongside the existing <code>coretemp</code>/PECI
entries.</p>
<h2 id="making-it-persistent">Making it persistent</h2>
<p>A manual <code>modprobe force=1</code> doesn&rsquo;t survive a reboot, and doesn&rsquo;t help if
<code>nct6683</code> isn&rsquo;t in the auto-loaded module list at all. Two small config
files fix both:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Force the parameter every time the module loads</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;options nct6683 force=1&#34;</span> &gt; /etc/modprobe.d/nct6683.conf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Make sure the module actually loads at boot</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;nct6683&#34;</span> &gt;&gt; /etc/modules
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">update-initramfs -u
</span></span><span class="line"><span class="cl">reboot
</span></span></code></pre></div><p>After the reboot, <code>sensors</code> shows <code>fan2</code> without any manual intervention —
same as it would if the driver&rsquo;s built-in check had recognized the board in
the first place.</p>
<h2 id="reference">Reference</h2>
<table>
	<thead>
			<tr>
					<th>Item</th>
					<th>Value</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Hardware</td>
					<td>Lenovo M900 Tiny (<code>pve-m900-1</code>)</td>
			</tr>
			<tr>
					<td>Super I/O chip</td>
					<td>Nuvoton NCT6683</td>
			</tr>
			<tr>
					<td>Driver</td>
					<td><code>nct6683</code> (lm-sensors)</td>
			</tr>
			<tr>
					<td>Symptom</td>
					<td><code>modprobe</code> succeeds, no fan entry in <code>sensors</code>, nothing in <code>dmesg</code></td>
			</tr>
			<tr>
					<td>Root cause</td>
					<td>EC firmware build <code>1.0 build 12/30/15</code> fails the driver&rsquo;s vendor/build check → silent <code>ENODEV</code></td>
			</tr>
			<tr>
					<td>Fix</td>
					<td><code>force=1</code> module parameter</td>
			</tr>
			<tr>
					<td>Persistence</td>
					<td><code>/etc/modprobe.d/nct6683.conf</code> (<code>options nct6683 force=1</code>) + <code>nct6683</code> in <code>/etc/modules</code></td>
			</tr>
			<tr>
					<td>Result</td>
					<td><code>sensors</code> reports <code>fan2</code>, ~980 RPM baseline</td>
			</tr>
	</tbody>
</table>
<p>If a Super I/O sensor driver loads without error but produces zero fan/temp
entries and <code>dmesg</code> is silent, a vendor or firmware-build allowlist check
inside the driver — not a missing driver — is worth suspecting before
anything else.</p>
<hr>
<p><em>This guide was written by Claude, an AI assistant made by Anthropic, based on
a hands-on troubleshooting session working through this exact problem.</em></p>
]]></content:encoded></item></channel></rss>