From nobody Mon Feb 9 07:42:41 2026 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 115E13876C1; Thu, 29 Jan 2026 11:43:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=213.167.242.64 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769687004; cv=none; b=soD6oWuQU2989r8ERv6PlG/UdI++TpWTFug9/ixoESosersxQVA1s86mDgm3+fN0W0QRJD/s84sb6gKIms/MfjBPj/cQN6KEds7JaBTldgmrWWkHglVTneTRM3fIz81lmFaPfwqvhbkPyUQ6vrPzGxGVv7l7sHkPllggi7XhBKo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769687004; c=relaxed/simple; bh=jxl41sFQLcak13v1qSdR5pCoV59qLz8tiGeam2Njm0g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qc2AxStBFidm6PAkifYATj/yPFYy9xaL7JzhbT7aUdQ0Gkso2Kv5hrb4ZWrPZHERehwtFPVXbmTlrl+p0iQvUhaYH04N7ZJhX8em+DML9goeGbHhS62zFCh7bH3Yv8HoFOUNpE16m0/+PKCFo5Skijr390Lnx/baDPE66y3r238= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com; spf=pass smtp.mailfrom=ideasonboard.com; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b=ZqeT2Jws; arc=none smtp.client-ip=213.167.242.64 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=ideasonboard.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZqeT2Jws" Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:f52e:2bba:80e9:14d8]) by perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5FE17281A; Thu, 29 Jan 2026 12:42:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1769686964; bh=jxl41sFQLcak13v1qSdR5pCoV59qLz8tiGeam2Njm0g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZqeT2Jws85avCVS4530+7GVn4DGkc7cpLI3yxfEhjY99rZ+d6sK+R9fpCNwql+tv5 xtBBqljJ1oadlkBxYWEHz+LQ2swhdj6DHvSLjenu2203HzHq1LlDxya5PgepOThXoT STjCjjs2P7o8vysX6WBy98XvOUNLqysnI4kPZMQM= From: Stefan Klug Date: Thu, 29 Jan 2026 12:43:12 +0100 Subject: [PATCH v3 3/4] media: dw100: Fix kernel oops with PREEMPT_RT enabled Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-sklug-v6-16-topic-dw100-v3-1-dev-v3-3-2eb5685eaf09@ideasonboard.com> References: <20260129-sklug-v6-16-topic-dw100-v3-1-dev-v3-0-2eb5685eaf09@ideasonboard.com> In-Reply-To: <20260129-sklug-v6-16-topic-dw100-v3-1-dev-v3-0-2eb5685eaf09@ideasonboard.com> To: Xavier Roumegue , Mauro Carvalho Chehab , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Laurent Pinchart Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, Nicolas Dufresne , Stefan Klug X-Mailer: b4 0.14.2 On kernels with PREEMPT_RT enabled, a "BUG: scheduling while atomic" kernel oops occurs inside dw100_irq_handler -> vb2_buffer_done. This is because vb2_buffer_done takes a spinlock which is not allowed within interrupt context on PREEMPT_RT. The first attempt to fix this was to just drop the IRQF_ONESHOT so that the interrupt is handled threaded on PREEMPT_RT systems. This introduced a new issue. The dw100 has an internal timeout counter that is gated by the DW100_BUS_CTRL_AXI_MASTER_ENABLE bit. Depending on the time it takes for the threaded handler to run and the geometry of the data being processed it is possible to reach the timeout resulting in DW100_INTERRUPT_STATUS_INT_ERR_TIME_OUT being set and "dw100 32e30000.dwe: Interrupt error: 0x1" errors in dmesg. To properly fix that, split the interrupt into two halves, reset the DW100_BUS_CTRL_AXI_MASTER_ENABLE bit in the hard interrupt handler and do the v4l2 buffer handling in the threaded half. The IRQF_ONESHOT can still be dropped as the interrupt gets disabled in the hard handler and will only be reenabled on the next dw100_device_run which will not be called before the current job has finished. Signed-off-by: Stefan Klug Reviewed-by: Xavier Roumegue --- Thank you Xavier for the technical support and further details on the interrupt bit. Changes in v3: - Split interrupt in two halves to prevent timeout error - Dropped rby tags, as the patch changed substantially Changes in v2: - Dropped the IRQF_ONESHOT instead of making the interrupt handler threaded to fix the issue. - I didn't keep the r-by tag from Nicolas as the solution is now a different one. --- drivers/media/platform/nxp/dw100/dw100.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/nxp/dw100/dw100.c b/drivers/media/platf= orm/nxp/dw100/dw100.c index d2b1c62b52db47ea1d2242caaf334fff30c6f366..46e3a7b74fb777aa479110a5222= 9f36b8632db44 100644 --- a/drivers/media/platform/nxp/dw100/dw100.c +++ b/drivers/media/platform/nxp/dw100/dw100.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ struct dw100_device { struct clk_bulk_data *clks; int num_clks; struct dentry *debugfs_root; + bool frame_failed; }; =20 struct dw100_q_data { @@ -1406,7 +1408,8 @@ static irqreturn_t dw100_irq_handler(int irq, void *d= ev_id) { struct dw100_device *dw_dev =3D dev_id; u32 pending_irqs, err_irqs, frame_done_irq; - bool with_error =3D true; + + dw_dev->frame_failed =3D true; =20 pending_irqs =3D dw_hw_get_pending_irqs(dw_dev); frame_done_irq =3D pending_irqs & DW100_INTERRUPT_STATUS_INT_FRAME_DONE; @@ -1414,7 +1417,7 @@ static irqreturn_t dw100_irq_handler(int irq, void *d= ev_id) =20 if (frame_done_irq) { dev_dbg(&dw_dev->pdev->dev, "Frame done interrupt\n"); - with_error =3D false; + dw_dev->frame_failed =3D false; err_irqs &=3D ~DW100_INTERRUPT_STATUS_INT_ERR_STATUS (DW100_INTERRUPT_STATUS_INT_ERR_FRAME_DONE); } @@ -1427,7 +1430,14 @@ static irqreturn_t dw100_irq_handler(int irq, void *= dev_id) dw100_hw_clear_irq(dw_dev, pending_irqs | DW100_INTERRUPT_STATUS_INT_ERR_TIME_OUT); =20 - dw100_job_finish(dw_dev, with_error); + return IRQ_WAKE_THREAD; +} + +static irqreturn_t dw100_irq_thread_fn(int irq, void *dev_id) +{ + struct dw100_device *dw_dev =3D dev_id; + + dw100_job_finish(dw_dev, dw_dev->frame_failed); =20 return IRQ_HANDLED; } @@ -1593,8 +1603,9 @@ static int dw100_probe(struct platform_device *pdev) =20 pm_runtime_put_sync(&pdev->dev); =20 - ret =3D devm_request_irq(&pdev->dev, irq, dw100_irq_handler, IRQF_ONESHOT, - dev_name(&pdev->dev), dw_dev); + ret =3D devm_request_threaded_irq(&pdev->dev, irq, dw100_irq_handler, + dw100_irq_thread_fn, 0, + dev_name(&pdev->dev), dw_dev); if (ret < 0) { dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); goto err_pm; --=20 2.51.0