<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Fix nv_drm_revoke_modeset_permission</title>
  <style>
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    /* The extra [class] is a hack that increases specificity enough to
       override a similar rule in reveal.js */
    ul.task-list[class]{list-style: none;}
    ul.task-list li input[type="checkbox"] {
      font-size: inherit;
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    html { -webkit-text-size-adjust: 100%; }
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css/github-markdown.min.css" />
</head>
<body>
<header id="title-block-header">
<h1 class="title">Fix nv_drm_revoke_modeset_permission</h1>
</header>
<h1 id="fix-nv_drm_revoke_modeset_permission-kernel-warning">Fix:
<code>nv_drm_revoke_modeset_permission</code> kernel WARNING</h1>
<p>Fixes a kernel <code>WARN_ON</code> in
<code>nv_drm_revoke_modeset_permission</code> on the nvidia-drm 550
branch with Debian kernel 6.12. The warning fires every time a DRM file
descriptor is closed (by processes like <code>glxtest</code>,
<code>kioworker</code>, <code>kscreenlocker_greet</code>),
producing:</p>
<pre><code>WARNING at nvidia-drm/nvidia-drm-drv.c:1221 nv_drm_revoke_modeset_permission+0x327/0x340</code></pre>
<p>Two patches are needed: one fixing a conftest compile failure
(primary cause) and one fixing latent error-handling bugs in the
driver.</p>
<h2 id="files">Files</h2>
<table>
<colgroup>
<col style="width: 31%" />
<col style="width: 68%" />
</colgroup>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="plan.md">plan.md</a></td>
<td>Full root-cause analysis with source references to NVIDIA and kernel
code. Covers the conftest failure, the bogus <code>WARN_ON</code> in the
fallback macro, the wrong mutex assertion for atomic drivers, and two
secondary bugs (iterator leak, NULL state dereference). Start here to
understand the problem.</td>
</tr>
<tr>
<td><a href="plan.html">plan.html</a></td>
<td>HTML rendering of <code>plan.md</code> (generated via pandoc). Same
content with clickable hyperlinks, suitable for viewing in a
browser.</td>
</tr>
<tr>
<td><a
href="nvidia-graphics-drivers-550-debian-sources.patch">nvidia-graphics-drivers-550-debian-sources.patch</a></td>
<td>Git-format patch against the <a
href="https://salsa.debian.org/nvidia-team/nvidia-graphics-drivers">Debian
nvidia-graphics-drivers</a> source package. Contains both fix patches
(0084 + 0085), updates to <code>debian/patches/module/series</code>, and
a changelog entry. Apply this to build a fixed <code>.deb</code>.</td>
</tr>
<tr>
<td><a href="conftest.sh.patched">conftest.sh.patched</a></td>
<td>The full <code>conftest.sh</code> from
<code>kernel-open/conftest.sh</code> (tag 550.163.01) with the fix
already applied: prerequisite DRM headers (<code>drm_device.h</code>,
<code>drm_mode_config.h</code>) are included before
<code>drm_connector.h</code>, and a <code>return 0;</code> is added to
avoid <code>-Werror=return-type</code>.</td>
</tr>
<tr>
<td><a href="nvidia-drm-drv.c.patched">nvidia-drm-drv.c.patched</a></td>
<td>The full <code>kernel-open/nvidia-drm/nvidia-drm-drv.c</code> (tag
550.163.01) with error-handling fixes applied: <code>goto done</code>
replaced with <code>break</code> in the connector loop, explicit error
check after iterator end, and NULL guards on
<code>drm_atomic_state_put</code>/<code>drm_atomic_state_free</code>.</td>
</tr>
</tbody>
</table>
<h2 id="how-to-use">How to use</h2>
<h3 id="option-a-patch-dkms-sources-directly">Option A: Patch DKMS
sources directly</h3>
<p>Back up the original files first, then copy the patched versions into
the DKMS source tree and rebuild:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">sudo</span> <span class="at">-s</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Copy patched files to the DKMS source tree</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="fu">cp</span> <span class="at">-v</span> conftest.sh.patched /usr/src/nvidia-current-550.163.01/</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="fu">cp</span> <span class="at">-v</span> nvidia-drm-drv.c.patched /usr/src/nvidia-current-550.163.01/nvidia-drm/</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> /usr/src/nvidia-current-550.163.01</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="co"># Back up originals</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> conftest.sh conftest.sh.orig</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> nvidia-drm/nvidia-drm-drv.c nvidia-drm/nvidia-drm-drv.c.orig</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="co"># Put patched files in place (-i prompts before overwriting)</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> conftest.sh.patched conftest.sh</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> nvidia-drm/nvidia-drm-drv.c.patched nvidia-drm/nvidia-drm-drv.c</span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="co"># Rebuild the DKMS module</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="ex">dkms</span> remove nvidia-current/550.163.01 <span class="at">--all</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="ex">dkms</span> install nvidia-current/550.163.01</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="ex">update-initramfs</span> <span class="at">-u</span>  <span class="co"># or: dracut -f</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="ex">reboot</span></span></code></pre></div>
<p>To revert, restore the backups:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">sudo</span> <span class="at">-s</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> /usr/src/nvidia-current-550.163.01</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> conftest.sh.orig conftest.sh</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="fu">mv</span> <span class="at">-i</span> nvidia-drm/nvidia-drm-drv.c.orig nvidia-drm/nvidia-drm-drv.c</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Rebuild the DKMS module</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ex">dkms</span> remove nvidia-current/550.163.01 <span class="at">--all</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="ex">dkms</span> install nvidia-current/550.163.01</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="ex">update-initramfs</span> <span class="at">-u</span>  <span class="co"># or: dracut -f</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="ex">reboot</span></span></code></pre></div>
<h3 id="option-b-apply-the-debian-source-patch">Option B: Apply the
Debian source patch</h3>
<p>If you maintain a local build of the Debian
<code>nvidia-graphics-drivers</code> package:</p>
<div class="sourceCode" id="cb4"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">cd</span> nvidia-graphics-drivers</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> am nvidia-graphics-drivers-550-debian-sources.patch</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">dpkg-buildpackage</span> <span class="at">-us</span> <span class="at">-uc</span></span></code></pre></div>
<h3 id="verification">Verification</h3>
<p>After rebooting with the patched module:</p>
<div class="sourceCode" id="cb5"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Conftest should now detect the struct:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="fu">grep</span> NV_DRM_CONNECTOR_LIST_ITER /var/lib/dkms/nvidia-current/550.163.01/build/conftest/types.h</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Expected: #define NV_DRM_CONNECTOR_LIST_ITER_PRESENT</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="co"># </span><span class="al">WARNING</span><span class="co"> should no longer appear:</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="fu">dmesg</span> <span class="kw">|</span> <span class="fu">grep</span> nv_drm_revoke_modeset_permission</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co"># Expected: no output</span></span></code></pre></div>
<hr />
<p><em>Analysis and patches created with assistance from Claude Opus 4.6
(Anthropic) via Cursor IDE.</em></p>
</body>
</html>