From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f42.google.com (mail-wm1-f42.google.com [209.85.128.42]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 194FC49505F for ; Wed, 12 Aug 2026 23:13:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.42 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786576418; cv=none; b=qITh/sD67o8aUtKEQhrA56mMJ4qRdh83eHi6+HW2y3KoRvNt/TbZfbRfQWu6l3StHmXJdxvSQMjbt7WO/hCXt+JyvK1/dGIme10wegFLQS7TvlQYe5Q9pjtWIvrznFG4TwjVPRhw1T5XpWSjnIovDxdQOOiJXQwpNjt0GrI3ooc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786576418; c=relaxed/simple; bh=K1T094YKiTFXwLhyddi87t2RcNlrJTOzphdlDYjsXIQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W1K8VEUhxyRmAra80wp6lyMKl+xcrPtq76llLh/u9m7tFmjeOo1Y8EDS2eBR6clL0tpCSketzfNQmfZIn5nSU1JyulFAOIoF+yt+QRYRCG/C6cliyZqxyz/57rLcVQvDq5aeKAwy5V3n4D+kVWzfM0yTpHp8iNtOqwBvdi6eHyI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=s84DD9aG; arc=none smtp.client-ip=209.85.128.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="s84DD9aG" Received: by mail-wm1-f42.google.com with SMTP id 5b1f17b1804b1-4957799b92fso1195265e9.1 for ; Wed, 12 Aug 2026 16:13:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786576415; x=1787181215; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=b4ewDgBabacjDaP8NBVKD5QYsXGYuSL6SciAIvMhBJc=; b=s84DD9aGl3xrNz2TRpHjjEJIUvT6eDn3CJGzysq8+7sAkRRBCKcAwmVG8UyetbuHM2 yTj0B9tRREJtRMvU1ZzE56kYSy7rWuF35ECtu8YObO5XlXk0DWT6nj4Useq5lte510To 4wxApr7fwdPEfp+usKIz3VclgN1LYaD805/pPrOgI9DtFyK5XqewqH0aukg/Nxjd1h+n HIUC2qMwctvqv3lkCyqYXoSmZoJfIwMHCFzInD9N2EO9ovwRXeRWVBRIL761Gjnh0H0F aUw3bM2p/OM7iY3VCcS1b/lSZF6dyQ4Nup40yN23wtZKZvJ7IIooSfvN7Naol2D2MvXS gUBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786576415; x=1787181215; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=b4ewDgBabacjDaP8NBVKD5QYsXGYuSL6SciAIvMhBJc=; b=VYIEUgGlA+tJobJ4rsfCNObzo7yw12XvH9Sfym9I7NbASD0ziHAcpsGw2yvtwFM4pV 0D/QW338nFPjVyvnd/++6JlEgpL+3zZqpfWXvG+F0Q3WKA0NAb8/3UAwWBbWPJr4Y29s qS21ufivKVS0qEzC/n2wvALkAKYYx3/Q68s/XoOeYJ4WRWfXEicT7mRglGtYPSuPdtJb 6A4VwwYI460g5kwnGYT5sYueRPH6jAsmmpmFTwp3T2l2j3Zr7SOcxMjdybl9uDBMbLmw vKWx84etFrpL9F7XzycmWHirPtpoupySdq2+JdZatqNMmLv6kE1G9+8XMLM49fd7PQmx LMTg== X-Gm-Message-State: AOJu0YxEs+5Youj27G3/G0XdzF1UEfI6JY1KXoVtlk3bCndeOnY3F1WW AXioTdm0ud0E5Pfy5WCBI1RJWDvzsj17mY6vSrRfjpHSU/fgNWYsUI1L4wJFNjSa X-Gm-Gg: AR+sD10mYgKj4CiVV9c73R9VEppaIB/bucBccBcL+plmZd5PE4zBqywp2O85sBvrKzK neLHEe8umR1XoHVjsD6qvaWkDPGl3XRJoghwf1+da2Hg5IDYeNi1TKqdpHN5hRh2o1DkhPmN04M 5lSApzdjzsAFDL0pEEKm76WyeGkG3opebtfdhgHootiETHA6+lVIEUK57aCZnhUyDugV9x+gLKs M4gYTY1BFyF/wln9I3dDFEyCM8KcXaXy18L/SsPpAaukS08VMjYVQOHUqdhRqzIm7csmW3zQoI2 S0WghpoIWvvB1fqfG4R+kao+Yv+ay8JBm3KriqDIN1ApHMpLTSuH0XyV4P+tJW5lAATC60ufuVR a/hlRhyYTgwlOE+1Wx0D5XS2sKStMr0tYcj+Ydb1gc+XkmQ6k3uV+OtpH48rxn26CpEz01bjHnQ r4D8UBUS6Vx5ITdaaMTR4SejqT7GmsFKtTvX1zsk1jQ9n5sgamgAv0UMBPKA/9G+qlcojdrilnw 1GQIdQeYZTrxd6Q5G2nP8bGjQZV1yIh5Z325WsRN/+rFHH2m/BR8aQ= X-Received: by 2002:a05:600c:e547:20b0:499:4d41:cd13 with SMTP id 5b1f17b1804b1-4998212ee6amr4162105e9.0.1786576415303; Wed, 12 Aug 2026 16:13:35 -0700 (PDT) Received: from Neo.taile6b6ba.ts.net (ip-109-193-028-127.um39.pools.vodafone-ip.de. [109.193.28.127]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49981b631c1sm44532245e9.14.2026.08.12.16.13.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 Aug 2026 16:13:34 -0700 (PDT) From: Marek Czernohous To: nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org, Danilo Krummrich , Lyude Paul , David Airlie , Simona Vetter , Ben Skeggs Subject: [PATCH v3 2/4] drm/nouveau: subscribe to the channel-kill event after the fence context Date: Thu, 13 Aug 2026 01:13:28 +0200 Message-ID: <20260812231330.705425-3-mczernohous@gmail.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260812231330.705425-1-mczernohous@gmail.com> References: <20260812231330.705425-1-mczernohous@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Marek Czernohous nouveau_channel_init() arms the channel-kill subscription early, right after mapping userd, and only creates the fence context at the very end of the same function. The handler it installs, nouveau_channel_killed(), reaches nouveau_fence_context_kill(chan->fence). The NULL check in nouveau_channel_kill() does not cover the window in between. The backends publish the pointer before the context is usable: fctx = chan->fence = kzalloc_obj(*fctx); if (!fctx) return -ENOMEM; nouveau_fence_context_new(chan, &fctx->base); and nouveau_fence_context_new() is what runs spin_lock_init(&fctx->lock) and INIT_LIST_HEAD(&fctx->pending). An event arriving after the assignment but before that call finds chan->fence non-NULL and unusable: nouveau_fence_context_kill() takes a lock that was never initialised and walks a list head whose next pointer is still the NULL left by kzalloc(). Move the subscription behind context_new() so the handler cannot observe a half-built fence context. The failure path is unchanged in effect: the caller drops the channel with nouveau_channel_del() either way, which since the previous patch unsubscribes before freeing the context. One behavioural change worth naming, and it is not free: a kill delivered while the channel is still initialising is no longer observed, because the subscription is not armed yet. That window does not close here, it moves, and on Fermi and newer it grows by the span between the old subscription point and context_new(). What changes is what the window costs. Before, a kill landing in it reached a half-built fence context; now it is missed, and the channel is left blocked with chan->killed still 0, so nouveau_channel_idle() and the checks in nouveau_gem_ioctl_pushbuf() and nouveau_exec_ioctl_exec() keep treating it as alive. The missed-kill window is not introduced by this patch either: nvkm_uchan_init() already calls nvkm_chan_allow() and nvkm_chan_insert(), so the channel is schedulable before nouveau_channel_init() subscribes at all. Closing it properly means subscribing before the channel becomes schedulable, which is a bigger change than this fix. As with the previous patch this is unreachable below Fermi today, and the last patch in this series lowers the gate to NV50. Fixes: ea13e5abf807 ("drm/nouveau: signal pending fences when channel has been killed") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-5 Signed-off-by: Marek Czernohous --- drivers/gpu/drm/nouveau/nouveau_chan.c | 55 +++++++++++++++----------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index f142f6310596..07b0bd1bc519 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -370,27 +370,6 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) if (ret) return ret; - if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { - DEFINE_RAW_FLEX(struct nvif_event_v0, args, data, - sizeof(struct nvif_chan_event_v0)); - struct nvif_chan_event_v0 *host = - (struct nvif_chan_event_v0 *)args->data; - - host->version = 0; - host->type = NVIF_CHAN_EVENT_V0_KILLED; - - ret = nvif_event_ctor(&chan->user, "abi16ChanKilled", chan->chid, - nouveau_channel_killed, false, - args, __struct_size(args), &chan->kill); - if (ret == 0) - ret = nvif_event_allow(&chan->kill); - if (ret) { - NV_ERROR(drm, "Failed to request channel kill " - "notification: %d\n", ret); - return ret; - } - } - /* allocate dma objects to cover all allowed vram, and gart */ if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { @@ -494,7 +473,39 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) } /* initialise synchronisation */ - return nouveau_fence(drm)->context_new(chan); + ret = nouveau_fence(drm)->context_new(chan); + if (ret) + return ret; + + /* + * Subscribe to the channel-kill event last. The handler + * dereferences chan->fence, and the fence context is only complete + * once context_new() has returned: the backends assign chan->fence + * from kzalloc() before nouveau_fence_context_new() initialises the + * lock and the pending list, so an event arriving in between would + * find a non-NULL but unusable context and walk a NULL list head. + */ + if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { + DEFINE_RAW_FLEX(struct nvif_event_v0, args, data, + sizeof(struct nvif_chan_event_v0)); + struct nvif_chan_event_v0 *host = + (struct nvif_chan_event_v0 *)args->data; + + host->version = 0; + host->type = NVIF_CHAN_EVENT_V0_KILLED; + + ret = nvif_event_ctor(&chan->user, "abi16ChanKilled", chan->chid, + nouveau_channel_killed, false, + args, __struct_size(args), &chan->kill); + if (ret == 0) + ret = nvif_event_allow(&chan->kill); + if (ret) { + NV_ERROR(drm, "Failed to request channel kill notification: %d\n", ret); + return ret; + } + } + + return 0; } int -- 2.54.0