From nobody Tue Sep 29 04:14:13 2026 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (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 87BDB36E48B; Wed, 12 Aug 2026 19:52:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564379; cv=none; b=kEC/lDSk/3KYxLyDKObaU+zynC64egehugkjqcbMg7LGJmK/5Ix+bGbpdr4mQJ7yCbPeLRmP1abo3d7I4Jb3wGtg283NyetzQv/RsSHfMC0H76TNbYSlzgSQKYVqw7TNaN9svuKs6GsXK/+yRcBz9RpJaKJ0drjtHRGnkyYhT1Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564379; c=relaxed/simple; bh=ryMndI5dMt7MnECYtwtGRCAXvGKaWyr5nbwIhc9P6LM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZGlyKMD2mmcuYok5eEGyM6od4BkvoZnmcA3Z4Vq62qGHLmLV9R1SU+CmUADCXYoJFXdbIw9nOuuzkiAfYtUd6DiMF45lM6vfZmXiMH5YzNaqJEUszEIRwgnEx84R2Xf/EFvwAP4rf9EK5PT1lkvRQjCJ6Ww1kc3XCT7mhH3luE4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org; spf=pass smtp.mailfrom=mailbox.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=Gb2XwkvI; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=lHZD+u9k; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mailbox.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="Gb2XwkvI"; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="lHZD+u9k" Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4hKzgB5QyLzKsCB; Wed, 12 Aug 2026 21:52:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564374; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WeV/0Qwp/fe3MBvHcKkC8DCA/72k4r0efJC25hKgDBU=; b=Gb2XwkvIXlQWo+QWc7Iie6lW76r6M8bmmbO9LNJwr6B0tEyF4s57JTwWc+du4vbbzQnrRs +R7cXIstXeRWVjHy3Fb0F38D/SHPAODh+8tw/6HK4X0P+WIdHQ60YtrBBdl99nKRp/6loF nX48z2xZLITa/UVIZ4cjlB8/nJR56j3/LKfVsgNgKvoIu01qXvGUZqMPxaKXnzcQoVe9oA OAJmzxg9socsvpklv8tmuxG/WvnPixuTvSFLeyDbqgS23TjQDCgwwC0OtH1nIxbKxdK0IG bO6CvgM6cH39JYN6+6yHqNC172tfMuOXAuby2pDIsZELpPC4dYJ1zz/g8BjsrA== Authentication-Results: outgoing_mbo_mout; dkim=pass header.d=mailbox.org header.s=mail20150812 header.b=lHZD+u9k; spf=pass (outgoing_mbo_mout: domain of mhi@mailbox.org designates 2001:67c:2050:b231:465::2 as permitted sender) smtp.mailfrom=mhi@mailbox.org From: Maurice Hieronymus DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564372; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WeV/0Qwp/fe3MBvHcKkC8DCA/72k4r0efJC25hKgDBU=; b=lHZD+u9kGEirhg4gfsz17ievR96n/GVe0zjSLpU4k9x5UoxR7urhlDRkaU9C3cRJSHiJpj iZflrh+V2nO7F1SWFDJUEUYmsfxyarmuTDhVgN8dhLkJCxyLs0ZDjPfcal89y7AP96oQxO Af5eNE3TaCG/owpxguy1+Bg1B5OZQArbQun2JulWtkBs1EDf+37U4b/rmFl3QmCGcuI6+H UeU5Pv3xszlyeOBBfX9r/fAcrosIBIlABwFSdRJpMvd3w9wF6mtLwMRip5kCerCZry0Yzd eSN4KJg0vEEjptF51UwnVLx9rwjeKO8N7UK1DiwhkDBnJ9/8CkU5hsjZ4l5lSQ== Date: Wed, 12 Aug 2026 21:52:35 +0200 Subject: [PATCH v3 1/5] samples: rust: remove the rust_driver_pci sample 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: <20260812-b4-rust-pci-edu-driver-v3-1-5d0b5594e52b@mailbox.org> References: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> In-Reply-To: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> To: Danilo Krummrich , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Lyude Paul , David Airlie , Simona Vetter Cc: linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, Maurice Hieronymus X-Developer-Signature: v=1; a=ed25519-sha256; t=1786564358; l=7471; i=mhi@mailbox.org; s=20260525; h=from:subject:message-id; bh=ryMndI5dMt7MnECYtwtGRCAXvGKaWyr5nbwIhc9P6LM=; b=7XmYItZ+LpeRsxkVh/CV2/PIn31FnPLHJHq/hRfBK+D4LxwGQdS+x650YCnOEBq/gne39uvlZ Ph+RR/Bxu7bDs4tSOcmx8ps684CzJeFoiehb0/1d+AiF2DTSBteM/Kl X-Developer-Key: i=mhi@mailbox.org; a=ed25519; pk=AHlEkGG3hpXZHntlEzF42Ip/LFyXWOgsNUvaHqAnV80= X-MBO-RS-META: q46pu4riuj5f5dxhiqayxbuyn3c8rd5k X-MBO-RS-ID: 96d048f2579eb44aff9 X-Rspamd-Queue-Id: 4hKzgB5QyLzKsCB The EDU sample added later in this series covers everything rust_driver_pci demonstrates (device matching, BAR mapping, MMIO) and exercises interrupts and DMA on top, against a device every QEMU ships. Remove the old sample in favor of it, as requested by Danilo during review of the EDU series. Link: https://lore.kernel.org/rust-for-linux/DJEQ64V8HE19.2DMBHY4XRPMG6@ker= nel.org Suggested-by: Danilo Krummrich Signed-off-by: Maurice Hieronymus --- MAINTAINERS | 1 - samples/rust/Kconfig | 11 --- samples/rust/Makefile | 1 - samples/rust/rust_driver_pci.rs | 194 ------------------------------------= ---- 4 files changed, 207 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 95f6791c41bc..92bc1f8c4f8a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20915,7 +20915,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/gi= t/pci/pci.git F: rust/helpers/pci.c F: rust/kernel/pci.rs F: rust/kernel/pci/ -F: samples/rust/rust_driver_pci.rs =20 PCIE BANDWIDTH CONTROLLER M: Ilpo J=C3=A4rvinen diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index c49ab9106345..0cae695acd84 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -107,17 +107,6 @@ config SAMPLE_RUST_I2C_CLIENT =20 If unsure, say N. =20 -config SAMPLE_RUST_DRIVER_PCI - tristate "PCI Driver" - depends on PCI - help - This option builds the Rust PCI driver sample. - - To compile this as a module, choose M here: - the module will be called rust_driver_pci. - - If unsure, say N. - config SAMPLE_RUST_DRIVER_PLATFORM tristate "Platform Driver" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 6c0aaa58cccc..70495fed886f 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_SAMPLE_RUST_DEBUGFS_SCOPED) +=3D rust_debugfs_= scoped.o obj-$(CONFIG_SAMPLE_RUST_DMA) +=3D rust_dma.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) +=3D rust_driver_i2c.o obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) +=3D rust_i2c_client.o -obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) +=3D rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) +=3D rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs deleted file mode 100644 index 1aa8197d8698..000000000000 --- a/samples/rust/rust_driver_pci.rs +++ /dev/null @@ -1,194 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! Rust PCI driver sample (based on QEMU's `pci-testdev`). -//! -//! To make this driver probe, QEMU must be run with `-device pci-testdev`. - -use kernel::{ - device::{ - Bound, - Core, // - }, - io::{ - register, - register::Array, - Io, // - }, - num::Bounded, - pci, - prelude::*, // -}; - -mod regs { - use super::*; - - register! { - pub(super) TEST(u8) @ 0x0 { - 7:0 index =3D> TestIndex; - } - - pub(super) OFFSET(u32) @ 0x4 { - 31:0 offset; - } - - pub(super) DATA(u8) @ 0x8 { - 7:0 data; - } - - pub(super) COUNT(u32) @ 0xC { - 31:0 count; - } - } - - pub(super) const END: usize =3D 0x10; -} - -type Bar0<'bound> =3D pci::Bar<'bound, { regs::END }>; - -#[derive(Copy, Clone, Debug)] -struct TestIndex(u8); - -impl From> for TestIndex { - fn from(value: Bounded) -> Self { - Self(value.into()) - } -} - -impl From for Bounded { - fn from(value: TestIndex) -> Self { - value.0.into() - } -} - -impl TestIndex { - const NO_EVENTFD: Self =3D Self(0); -} - -struct SampleDriverData<'bound> { - pdev: &'bound pci::Device, - bar: Bar0<'bound>, - index: TestIndex, -} - -struct SampleDriver; - -kernel::pci_device_table!( - PCI_TABLE, - MODULE_PCI_TABLE, - ::IdInfo, - [( - pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), - TestIndex::NO_EVENTFD - )] -); - -impl SampleDriverData<'_> { - fn testdev(index: &TestIndex, bar: &Bar0<'_>) -> Result { - // Select the test. - bar.write_reg(regs::TEST::zeroed().with_index(*index)); - - let offset =3D bar.read(regs::OFFSET).into_raw() as usize; - let data =3D bar.read(regs::DATA).into(); - - // Write `data` to `offset` to increase `count` by one. - // - // Note that we need `try_write8`, since `offset` can't be checked= at compile-time. - bar.try_write8(data, offset)?; - - Ok(bar.read(regs::COUNT).into()) - } - - fn config_space(pdev: &pci::Device) { - let config =3D pdev.config_space(); - - // Some PCI configuration space registers. - register! { - VENDOR_ID(u16) @ 0x0 { - 15:0 vendor_id; - } - - REVISION_ID(u8) @ 0x8 { - 7:0 revision_id; - } - - BAR(u32)[6] @ 0x10 { - 31:0 value; - } - } - - dev_info!( - pdev, - "pci-testdev config space read8 rev ID: {:x}\n", - config.read(REVISION_ID).revision_id() - ); - - dev_info!( - pdev, - "pci-testdev config space read16 vendor ID: {:x}\n", - config.read(VENDOR_ID).vendor_id() - ); - - dev_info!( - pdev, - "pci-testdev config space read32 BAR 0: {:x}\n", - config.read(BAR::at(0)).value() - ); - } -} - -impl pci::Driver for SampleDriver { - type IdInfo =3D TestIndex; - type Data<'bound> =3D SampleDriverData<'bound>; - - const ID_TABLE: pci::IdTable =3D &PCI_TABLE; - - fn probe<'bound>( - pdev: &'bound pci::Device>, - info: &'bound Self::IdInfo, - ) -> impl PinInit, Error> + 'bound { - let vendor =3D pdev.vendor_id(); - dev_dbg!( - pdev, - "Probe Rust PCI driver sample (PCI ID: {}, 0x{:x}).\n", - vendor, - pdev.device_id() - ); - - pdev.enable_device_mem()?; - pdev.set_master(); - - let bar =3D pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_dri= ver_pci")?; - - dev_info!( - pdev, - "pci-testdev data-match count: {}\n", - SampleDriverData::testdev(info, &bar)? - ); - SampleDriverData::config_space(pdev); - - Ok(SampleDriverData { - pdev, - bar, - index: *info, - }) - } - - fn unbind<'bound>(_pdev: &'bound pci::Device>, this: Pin<&Sel= f::Data<'bound>>) { - this.bar - .write_reg(regs::TEST::zeroed().with_index(this.index)); - } -} - -impl Drop for SampleDriverData<'_> { - fn drop(&mut self) { - dev_dbg!(self.pdev, "Remove Rust PCI driver sample.\n"); - } -} - -kernel::module_pci_driver! { - type: SampleDriver, - name: "rust_driver_pci", - authors: ["Danilo Krummrich"], - description: "Rust PCI driver", - license: "GPL v2", -} --=20 2.54.0 From nobody Tue Sep 29 04:14:13 2026 Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [80.241.56.172]) (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 DC64237F727; Wed, 12 Aug 2026 19:53:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564386; cv=none; b=BfGUCZz7gsFCRz7pW8QAG4yoci/3rFJmGl6+uDTVt1rkPtGtdC+GotL+AE1dBN3RUfJgEYN6N4b9Akz24CkTVkZx5INQYhywYrT3WuGnQE7HdHwMPXEclo9rznBd2kedqG3BCDjZDp3kV/zKzlEV7k6wsfaZ/D0y3HVl+5WO16g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564386; c=relaxed/simple; bh=D76pN2HsNvsOzFc5OXXfTs7V6T+4hgl57lEbVLc4BVg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=q4xZB0Qmpf3SRdmLusdIdzwqDxtzF86klBP2O26qazeJXRGBvoXFC9RIEAWm5LBO2ob/KtMhQ4iyWSAU39XsLKjY6sWfMA8OT5NLdbPS+blaZVwapULSDkZPxQA42Hp732CfbV1n5yjgv2byt8UJT/poLswrp/IUy5AsFTbprj4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org; spf=pass smtp.mailfrom=mailbox.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=Lwdy1ujO; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=UY3Jz/6T; arc=none smtp.client-ip=80.241.56.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mailbox.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="Lwdy1ujO"; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="UY3Jz/6T" Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4hKzgK40SVzMlDx; Wed, 12 Aug 2026 21:53:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564381; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a2j4bMPkaXXP/612jEbge0ol2ikz4HfIDxGfO6ZIrNg=; b=Lwdy1ujOJPg4nS6LRXZC8YmSUVFx/KEjHMl6JSrCRHrt21Vu8HMn7SXFinAydeJPcUWTCe pYBMkgbTjcay96nFGMA05LRqnt2jdKLaI1mZ/ewbXPrFl4B4lXSjcIX90MEOxFWD0DWBOT FpxghU8SpNPm5CgR3Sk7AMPrn3ZJnjnwPFvR8V+eKiZyCEi+stMiz/rVNRaOFZGLlmGZuo SPsN3DhWrGyzt002Tqi3xTDMMJc53QmUN6SLPpt2otZ9XIn8POMluZSu5bD9iVPWCcMURI 5P1SvUwM38f8Ja73xmdzXQuyiUAsKxsMTCEBS5N82zqS5d3QdPVedc+My890uQ== Authentication-Results: outgoing_mbo_mout; dkim=pass header.d=mailbox.org header.s=mail20150812 header.b="UY3Jz/6T"; spf=pass (outgoing_mbo_mout: domain of mhi@mailbox.org designates 2001:67c:2050:b231:465::2 as permitted sender) smtp.mailfrom=mhi@mailbox.org From: Maurice Hieronymus DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564378; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a2j4bMPkaXXP/612jEbge0ol2ikz4HfIDxGfO6ZIrNg=; b=UY3Jz/6T7Fbu/7J0C7AbjNCj/mcxQzygAJrqgXi3H1LRlq6BOUQJyDjMTLtvd5M50JQk1u H8SYp8he2Ita0WJTj2JlFhEsSda6YE3LFryeCFQxIzCeCELkK4aDFZ2vmdA213e8klQGFP adqIlTAR4X2jaHqmblRD7BI6Vu7M3BUtAlOfQtr0E7UsP4C41LycfZvbil4Sn5pcq3mQC/ mqPR+ZuPHPAEuOkIUoU3R7jtMhM/Plh84CycnU6sWGy8ZOy6QH2qZc8ZlwYoTxJ++LvZSu enXTML+LXb2+ExgD08kiBibciC+5fGNSsQhCHCoIGVDQIDR6Qf9/kc1l9SS61w== Date: Wed, 12 Aug 2026 21:52:36 +0200 Subject: [PATCH v3 2/5] rust: pci: rework device enabling API 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: <20260812-b4-rust-pci-edu-driver-v3-2-5d0b5594e52b@mailbox.org> References: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> In-Reply-To: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> To: Danilo Krummrich , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Lyude Paul , David Airlie , Simona Vetter Cc: linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, Maurice Hieronymus X-Developer-Signature: v=1; a=ed25519-sha256; t=1786564358; l=4208; i=mhi@mailbox.org; s=20260525; h=from:subject:message-id; bh=D76pN2HsNvsOzFc5OXXfTs7V6T+4hgl57lEbVLc4BVg=; b=sdAx+YoZlQPnFWBf/QhowMjvRLGeVGFVQbeabipAMPZhBVd7Qbz8qOn/tNggE73ppBHmvqx4N pxtdU8AIp6PBbbZxnOsrDE1NfvFXfiElC0pJYwgTIZw7Xun9kBMIPNw X-Developer-Key: i=mhi@mailbox.org; a=ed25519; pk=AHlEkGG3hpXZHntlEzF42Ip/LFyXWOgsNUvaHqAnV80= X-MBO-RS-META: fjgb93dy3hy6u5bdo85s7zafoxwwthcg X-MBO-RS-ID: 5c69c29456254f39175 X-Rspamd-Queue-Id: 4hKzgK40SVzMlDx `enable_device_mem()` wraps the unmanaged `pci_enable_device_mem()` and has no disable counterpart, so the enable count is leaked on driver unbind and the device does not come back up on a subsequent probe. Replace it with `enable_device()`, which wraps `pci_enable_device()` and returns a `DeviceEnableGuard<'a>`: dropping the guard runs `pci_disable_device()`. The guard borrows the device's bound scope (`&'a Device`), so it cannot outlive the driver binding, and since it is the only way to enable the device from safe code, the enable count always stays balanced. Obtaining the guard still requires a `&Device`, i.e. a bus callback. Unlike `pci_enable_device_mem()`, `pci_enable_device()` enables I/O and memory resources. Convert nova-core, the only user of `enable_device_mem()`, storing the guard as the last field of `NovaCore` so the device is disabled only after the GPU teardown. Link: https://lore.kernel.org/rust-for-linux/DJOEYVBS17MJ.1YD3TNGQBWHNK@ker= nel.org Suggested-by: Danilo Krummrich Signed-off-by: Maurice Hieronymus --- drivers/gpu/nova-core/driver.rs | 5 ++++- rust/kernel/pci.rs | 31 ++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 5738d4ac521b..99b15da59e81 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -30,6 +30,8 @@ pub(crate) struct NovaCore<'bound> { bar: pci::Bar<'bound, BAR0_SIZE>, #[allow(clippy::type_complexity)] _reg: auxiliary::Registration<'bound, ForLt!(())>, + // Declared last so the device stays enabled until everything above is= torn down. + _enable: pci::DeviceEnableGuard<'bound>, } =20 pub(crate) struct NovaCoreDriver; @@ -75,7 +77,7 @@ fn probe<'bound>( pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 - pdev.enable_device_mem()?; + let enable =3D pdev.enable_device()?; pdev.set_master(); =20 Ok(try_pin_init!(NovaCore { @@ -95,6 +97,7 @@ fn probe<'bound>( crate::MODULE_NAME, (), )?, + _enable: enable, })) }) } diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 4def9ca1824c..bd9a8113af35 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -452,11 +452,36 @@ pub fn pci_class(&self) -> Class { } } =20 +/// A guard that keeps the device's I/O and memory resources enabled. +/// +/// # Invariants +/// +/// The device's enable count was incremented once for this guard; droppin= g the guard decrements +/// it again. +pub struct DeviceEnableGuard<'a> { + dev: &'a Device, +} + +impl Drop for DeviceEnableGuard<'_> { + fn drop(&mut self) { + // SAFETY: `self.dev.as_raw()` is a valid pointer to a `struct pci= _dev`, and by the type + // invariant this guard holds one increment of the device's enable= count. + unsafe { bindings::pci_disable_device(self.dev.as_raw()) }; + } +} + impl<'a> Device> { - /// Enable memory resources for this device. - pub fn enable_device_mem(&self) -> Result { + /// Enable I/O and memory resources for this device. + /// + /// The device stays enabled for the lifetime of the returned guard; d= ropping the guard + /// disables the device again. The guard borrows the device's bound sc= ope, so it cannot + /// outlive the driver binding. + pub fn enable_device(&self) -> Result> { // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid = `struct pci_dev`. - to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) = }) + to_result(unsafe { bindings::pci_enable_device(self.as_raw()) })?; + + // INVARIANT: `pci_enable_device()` succeeded, so the enable count= was incremented once. + Ok(DeviceEnableGuard { dev: self }) } =20 /// Enable bus-mastering for this device. --=20 2.54.0 From nobody Tue Sep 29 04:14:13 2026 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (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 E10CD38D40B; Wed, 12 Aug 2026 19:53:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564389; cv=none; b=NpoagoICYpFoEMtB/m0L0TEVTxSqsQ2wa/5gbuHhd6dK0abpKHKSZXWj7+Qp7Papl+GprkZKr9Cbs4IQSZmLl3x2YEm4hqBUxxYxkzcDVWJHVXBeCT0z5NgcOouh0MWzhOB84zrKRzRIYf0goG4QsNxAIkQStRKg71MKhgCsxp4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564389; c=relaxed/simple; bh=tVp41pARDQTrd5p+nu2KEb+o0rIimyub9Ff96tbhd3A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pvTCii5MVCiIsrhApwkzsgddLMRchCKu6qwrxlRYQlNdOoXgxSTxMpcxQr4tmi+l7BUxeCYirUbZkDJQhJt8wYUJ06mtqAVcHLx2u/ax/pvaM0TVFd1g3dewpRzN0klrcUZ8OqdYnjGeAW1gKQJsLMC7NmqK3bzjiBDhUkSQu9M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org; spf=pass smtp.mailfrom=mailbox.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=wBwRcEru; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=izth+783; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mailbox.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="wBwRcEru"; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="izth+783" Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4hKzgP6CVqzKw21; Wed, 12 Aug 2026 21:53:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564385; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kZHA54cdQJXUjeXWtjp31S+ctx/OQCZQTCDq5l2X/Kc=; b=wBwRcEruQaVFSRA1baX5KSOS1rXn0rlKKrzSscJgCR7zyCOuBI9hM/gbpbDVIuuECMYRPy p7KztIItKnk86X6uOZOztIn8QY0WU3+RiDJIaZifxomjY/qjbaHGY2T1FutgzmaipH9CDr hOyjcJX6lJkiWi3+OdNnZx0ZOJHQh+MKsX0nfqcm4pHg8G+AImES8iEx+qs4NJ0F/8wkqa doB8JqbYsDu5dBqJzFO1R/X3NBH6f9cjvk6YoLzZqL90TrAI7N25J4P/bKUFG7Lz6Nbcnr 2JCZNjzsVuVihAcrlYSsZ6y68cSNS/NHJBD3DJqAR2VG13k/7AGG2fAGH7/ILw== Authentication-Results: outgoing_mbo_mout; dkim=pass header.d=mailbox.org header.s=mail20150812 header.b=izth+783; spf=pass (outgoing_mbo_mout: domain of mhi@mailbox.org designates 2001:67c:2050:b231:465::2 as permitted sender) smtp.mailfrom=mhi@mailbox.org From: Maurice Hieronymus DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564384; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=kZHA54cdQJXUjeXWtjp31S+ctx/OQCZQTCDq5l2X/Kc=; b=izth+7830+uza4uzGGB7+jTvwdT1CPZAt4MUYlMJC6e+LxkHxKtdQ+Q+qrSjKgZyazg308 6p1q0eB2YfaZQuvj3Jf2W3tLXC5Ztb0EP5gco17bhezI26VJG+MP198/1sVocoLx2kgCmP 2llbq3RW6vJGzYBPdiGcUrtOnOgYN9fP206T43bxG1GDi8YM/c8O7Biws409IYABr1hqUV viGGImILnjWxXgCcipYR7OD8ILZo1ymZwGNvMtRnGUrr2Cs66r+6ScJfio35SeJhhcnQlA F8YrRoknlNYTG/Sqf8BwJTR3ATsK3bklhrUwjlNAYSfJOL4mSNkLAPCBKZ0+Tw== Date: Wed, 12 Aug 2026 21:52:37 +0200 Subject: [PATCH v3 3/5] rust: pci: make Vendor::from_raw() public 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: <20260812-b4-rust-pci-edu-driver-v3-3-5d0b5594e52b@mailbox.org> References: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> In-Reply-To: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> To: Danilo Krummrich , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Lyude Paul , David Airlie , Simona Vetter Cc: linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, Maurice Hieronymus X-Developer-Signature: v=1; a=ed25519-sha256; t=1786564358; l=1768; i=mhi@mailbox.org; s=20260525; h=from:subject:message-id; bh=tVp41pARDQTrd5p+nu2KEb+o0rIimyub9Ff96tbhd3A=; b=SMWrZA117CCWnksPLtAQDkgM3baLke1SfODAL1kT20tt3MNF9qHO6ZCb38yCkjsVUrsD8sOxC P7bkQLBIJgRAFyrlzSSaW7ik/ozoqmdHMjc70ZhIQNI7OSNBp2mKcvN X-Developer-Key: i=mhi@mailbox.org; a=ed25519; pk=AHlEkGG3hpXZHntlEzF42Ip/LFyXWOgsNUvaHqAnV80= X-MBO-RS-META: 9oo4zaw7zumrk83gfg86gtuq9rjj7fwd X-MBO-RS-ID: ea5f89fe8d5fac0c87e X-Rspamd-Queue-Id: 4hKzgP6CVqzKw21 `Vendor::from_raw()` is currently `pub(super)`, so a Vendor can only be obtained through the named constants generated from the `PCI_VENDOR_ID_*` defines in ``. A driver therefore cannot match a device whose vendor ID has no symbolic name. Such devices exist. QEMU's "edu" educational device and the legacy qemu/Bochs stdvga both use vendor ID 0x1234, which is not registered in `pci_ids.h`. Per the policy stated at the top of that header, IDs are only added there when shared between multiple drivers; a single-driver ID is expected to be open-coded in the driver instead. C drivers already do this -- see `drivers/gpu/drm/tiny/bochs.c`, which matches with a bare ".vendor =3D 0x1234". The Rust abstraction has no equivalent escape hatch: there is no public way to express an unregistered vendor. Make `Vendor::from_raw()` public (and const, so it can be used in the const device-ID tables built by `pci_device_table!`) so that drivers can construct a Vendor from a raw ID, matching what C drivers can already do. Reviewed-by: Gary Guo Reviewed-by: Onur =C3=96zkan Signed-off-by: Maurice Hieronymus --- rust/kernel/pci/id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/kernel/pci/id.rs b/rust/kernel/pci/id.rs index dbaf301666e7..fe3b0047179b 100644 --- a/rust/kernel/pci/id.rs +++ b/rust/kernel/pci/id.rs @@ -156,7 +156,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { impl Vendor { /// Create a Vendor from a raw 16-bit vendor ID. #[inline] - pub(super) fn from_raw(vendor_id: u16) -> Self { + pub const fn from_raw(vendor_id: u16) -> Self { Self(vendor_id) } =20 --=20 2.54.0 From nobody Tue Sep 29 04:14:13 2026 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) (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 896A23793AC; Wed, 12 Aug 2026 19:53:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.152 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564395; cv=none; b=OwSLnuku99H58uFTSIq+sB+/bBsztKWlxWrnEdKkFiNLuoh8XI1Q3sbgkAEvthKdXuVyhap6d6kLRTVGFoeOKU97AbNkYm42MFNgEeCvjyEybGb9Ek6Sy7ZbK8ju71uwbh+yDApq4rsrgS2chL8izr0bajc747DDOnur1wV3fhE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564395; c=relaxed/simple; bh=HWcB9dW46NCDdMFgEmztPn3SKd3bbuPHW1LTSQ3duZs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PgNRhlRIiOQjYA0rzDtsn3uIGQYtiE2ENDG4xc9KjgL5oZgTcJE5IQ58iQcE6Rhb2Ph6lM7WaFpmTkQqdtEl4McgjO0Jgith+JZmZ87+gMdsMtQgraWAZK87Z93ZawKK92ukvq7lCVWBl6rLGRaNBY2anHOjwMk3vnv5GtIitrA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org; spf=pass smtp.mailfrom=mailbox.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=SiTXzoCv; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=gp0R1ymz; arc=none smtp.client-ip=80.241.56.152 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mailbox.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="SiTXzoCv"; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="gp0R1ymz" Received: from smtp2.mailbox.org (smtp2.mailbox.org [IPv6:2001:67c:2050:b231:465::2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4hKzgW6XB7zKw1R; Wed, 12 Aug 2026 21:53:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564391; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=svkrkIj8EgL3gAvbJQNXbPx1gnIdqah5+1xl05bhyEg=; b=SiTXzoCvYFqQiQfZPYyTQb8oAObpW6nLlzAzzWrhMbXacBLqvfARDvp105dmu17x2tsPGe rFpLEGEVVL36aovbzOOe9R2qDw0fhXfi0rwUcTL8vRGVUQTvI5tD6TswK4LFJD21PAXM2a mhgkSAe1Su6ofIMWgy7+IQjViqqyfhWviNmmPuGJaplqRPoh1Rh2XnUJUM5r/3CVkVsxyt b+09aiOESBWGCgdReNOaSqSa5Zt2Ge8oWeP6zSVQkQN4SGbz5AeVMYu5LXBB/eoc9yoh3v +reHO7qH2saJUcs9kN+azvoAZO05EB4PMmoJp8mbKWfcCfmZAlLnrBitUw7WVw== Authentication-Results: outgoing_mbo_mout; dkim=pass header.d=mailbox.org header.s=mail20150812 header.b=gp0R1ymz; spf=pass (outgoing_mbo_mout: domain of mhi@mailbox.org designates 2001:67c:2050:b231:465::2 as permitted sender) smtp.mailfrom=mhi@mailbox.org From: Maurice Hieronymus DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564390; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=svkrkIj8EgL3gAvbJQNXbPx1gnIdqah5+1xl05bhyEg=; b=gp0R1ymzBJO9XHyIK/6UazUn4aIpN+i7NRPc7RKM4H+N5saFYmmhbkwG+KruD3hBwmkj/I 74QrUCc0wlL84vYcsO22JRg+7BhzKBSr7pWrjpRl1sbIj/lmc3ilLznSqBX9X5rJC2IQrJ zn5MBqK3fdAq+Vf2QM/+HuCI+qtcWttmdyGJjM/Bn6MxkK7Dk2p68Hxp8Uz5no2Kfy9K1C aqKLzyLML23U7/e93xqzD3h36z90829uqNwxmqAxZCWD7E69XAQL2uibIE9fosduBVSUQe njgCPSyejl/tKR+dLQH0L1eu1uVkPTh3G9XWCBIkjiOb1LI7Lj3y2HNsVeQFxg== Date: Wed, 12 Aug 2026 21:52:38 +0200 Subject: [PATCH v3 4/5] rust: completion: add complete() 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: <20260812-b4-rust-pci-edu-driver-v3-4-5d0b5594e52b@mailbox.org> References: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> In-Reply-To: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> To: Danilo Krummrich , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Lyude Paul , David Airlie , Simona Vetter Cc: linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, Maurice Hieronymus X-Developer-Signature: v=1; a=ed25519-sha256; t=1786564358; l=1716; i=mhi@mailbox.org; s=20260525; h=from:subject:message-id; bh=HWcB9dW46NCDdMFgEmztPn3SKd3bbuPHW1LTSQ3duZs=; b=NbOFNRlSeu7hQ7ESR5yFNjSaCs08cN07YlPptrDlriaIGtRW9iLhUTSi81jFg6uYbSEvVSOrP DMPhziCQg0+Dthw/XOU7hOmd/zxh3R0poYKWekE013Ff0I+ahoLW0w/ X-Developer-Key: i=mhi@mailbox.org; a=ed25519; pk=AHlEkGG3hpXZHntlEzF42Ip/LFyXWOgsNUvaHqAnV80= X-MBO-RS-META: jcjnyktc496jcd7r5eau4i949ap7anu6 X-MBO-RS-ID: cc005bbae02b89dbc92 X-Rspamd-Queue-Id: 4hKzgW6XB7zKw1R The initial completion abstraction only added complete_all() and wait_for_completion(). complete_all() marks the completion permanently done, which makes a single Completion unsuitable for signalling the same event repeatedly: once complete_all() has run, every subsequent wait_for_completion() returns immediately without waiting. Add complete(), which wakes a single waiter and increments the internal counter by one. Paired one-to-one with wait_for_completion(), it allows the same completion to be reused across multiple cycles, e.g. to wait for consecutive DMA transfers to finish. Acked-by: Gary Guo Signed-off-by: Maurice Hieronymus --- rust/kernel/sync/completion.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs index 35ff049ff078..a54361b53644 100644 --- a/rust/kernel/sync/completion.rs +++ b/rust/kernel/sync/completion.rs @@ -90,6 +90,17 @@ fn as_raw(&self) -> *mut bindings::completion { self.inner.get() } =20 + /// Signal a single task waiting on this completion. + /// + /// This method wakes up a single task waiting on this completion. + /// If no task is currently waiting, the next + /// [`Completion::wait_for_completion`] returns immediately. + #[inline] + pub fn complete(&self) { + // SAFETY: `self.as_raw()` is a pointer to a valid `struct complet= ion`. + unsafe { bindings::complete(self.as_raw()) }; + } + /// Signal all tasks waiting on this completion. /// /// This method wakes up all tasks waiting on this completion; after t= his operation the --=20 2.54.0 From nobody Tue Sep 29 04:14:13 2026 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) (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 8C9DB3793AC; Wed, 12 Aug 2026 19:53:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=80.241.56.151 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564401; cv=none; b=BvG+Ytbj9Lnbv+N0TyuDs9gSgDnk651YtwqRy+5Kkaf3sbH0qcKGgYxQDPzWpw8jVxJJ+ZCEp27FRymam0ApdSNW1QT5o9VDZ+Z53QOJx3vTg8pI2Dc+nlsi8rJVe4owv/EC5VdLg8cmMG2K0pxOWbTEAFjVXzzlltLEuJA+hr8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786564401; c=relaxed/simple; bh=jsMdOjd6Feo0yskvr73lK8H4nDlWqQEkm8dAuS4hQoQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=n5ZaZrrZY9VR4iIx0XmILviPyXeHtoVTYsrLlwFUbExOCASD0ErROxlBLppUvLbNWKflnoREoUN3ca9lacDFYLHaZQ0WBpYPYsYI7T1Hieoo3KI8GUQykphQQo64iE81xYpWNzQvub+kFaE/HzjCYApGixzTRhU85CdPBoEE4do= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org; spf=pass smtp.mailfrom=mailbox.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=ceh4qsb+; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b=pe5/VAdq; arc=none smtp.client-ip=80.241.56.151 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mailbox.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mailbox.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="ceh4qsb+"; dkim=pass (2048-bit key) header.d=mailbox.org header.i=@mailbox.org header.b="pe5/VAdq" Received: from smtp2.mailbox.org (smtp2.mailbox.org [10.196.197.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4hKzgd4v3Dz8tc4; Wed, 12 Aug 2026 21:53:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564397; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FNQ8CmopTMw8BUQn4Y1TnuhBPIe3lpAQ4PrvTv888rs=; b=ceh4qsb+hry5jdLMnzlZdHWVNCgEd1IHjy14cNqnpN87HQ/JEFqOYiSqala8VJAYCOXQza RSCEyK+pOUvIyxJQufSdikuNv/bYkBwLPiiv+Zy27hKIvg9E06qGt62ybqAWjL1XRGvreS iDScW3PUYFVrn3ibazDv7m0vnbIM8YgPwg6FiYVwfq1kCdY6rhyFMsVXqpeAR/ikwqeflo deCHmGkuHJMVi3400XDW5d6z6x8OKS1BRttWkDMGs1yo4igyzKEgiyPcrs7itGrbfVWart 3gjp6QC993Ay+wTk1+VaGqpQTiVIPtiU+/u8PK8ApdJqrpQV1k2fWCiU/0Vs8A== From: Maurice Hieronymus DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mailbox.org; s=mail20150812; t=1786564396; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=FNQ8CmopTMw8BUQn4Y1TnuhBPIe3lpAQ4PrvTv888rs=; b=pe5/VAdqwpqvVE3pipJSQ7TXpcvG1mkw/X8DTU9Uj5lt6RWDDvuujWrNsbthGrri4PkD4G ToAx5dKPCU4UYEsNkSfVkq71hAoK9PSF2LHvtt6jwAOUGap184jHPxWuGYyGKsG/Z76j56 lwj0Qir4Vwd142KKdzQ9mNfz1YzrVn2AQhOrYzRaye5Xe+72snv0kDgMXHUThu9h/DtFnc zhpWHh6iArasJBt+h8lvTrcIFin1Ckyx0wvfgSsgI/y+Ayddn/B7hhEry4+q4wXtc4os1U jsanLgt/h5gntOuGcDM66OmRxsIw2319G/lAcRGVbVysZW5gx990A9CDhzj4gA== Date: Wed, 12 Aug 2026 21:52:39 +0200 Subject: [PATCH v3 5/5] rust: samples: add EDU PCI driver sample 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: <20260812-b4-rust-pci-edu-driver-v3-5-5d0b5594e52b@mailbox.org> References: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> In-Reply-To: <20260812-b4-rust-pci-edu-driver-v3-0-5d0b5594e52b@mailbox.org> To: Danilo Krummrich , Bjorn Helgaas , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Daniel Almeida , Tamir Duberstein , Alexandre Courbot , =?utf-8?q?Onur_=C3=96zkan?= , Lyude Paul , David Airlie , Simona Vetter Cc: linux-pci@vger.kernel.org, rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org, Maurice Hieronymus X-Developer-Signature: v=1; a=ed25519-sha256; t=1786564358; l=14935; i=mhi@mailbox.org; s=20260525; h=from:subject:message-id; bh=jsMdOjd6Feo0yskvr73lK8H4nDlWqQEkm8dAuS4hQoQ=; b=8ip8ypLSA65L7u+Tk7ETKqd4Kek3QqPJ4x39/56sxojnfJsSpHYlJUcLxRR8fMH+BykHE94kg a+wxsw9OXfMB8fTdmXypeWvFLQxs7sc7Snjw5UR5rZj7Qrx2oEcIA7n X-Developer-Key: i=mhi@mailbox.org; a=ed25519; pk=AHlEkGG3hpXZHntlEzF42Ip/LFyXWOgsNUvaHqAnV80= X-MBO-RS-META: wwtuxjik61xooc15ms49wf6nfz7qzfbs X-MBO-RS-ID: 7c651f304e1330fa7a6 Add a Rust sample driver for the QEMU EDU device, wired up via a new SAMPLE_RUST_DRIVER_EDU Kconfig option and the samples Makefile. Signed-off-by: Maurice Hieronymus --- MAINTAINERS | 1 + samples/rust/Kconfig | 11 ++ samples/rust/Makefile | 1 + samples/rust/rust_driver_edu.rs | 421 ++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 434 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 92bc1f8c4f8a..f8a16d7b8260 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20915,6 +20915,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/gi= t/pci/pci.git F: rust/helpers/pci.c F: rust/kernel/pci.rs F: rust/kernel/pci/ +F: samples/rust/rust_driver_edu.rs =20 PCIE BANDWIDTH CONTROLLER M: Ilpo J=C3=A4rvinen diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 0cae695acd84..115f71ed6328 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -107,6 +107,17 @@ config SAMPLE_RUST_I2C_CLIENT =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_EDU + tristate "EDU Driver" + depends on PCI + help + This option builds the Rust EDU driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_edu. + + If unsure, say N. + config SAMPLE_RUST_DRIVER_PLATFORM tristate "Platform Driver" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 70495fed886f..a005d578b7c2 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_SAMPLE_RUST_DEBUGFS_SCOPED) +=3D rust_debugfs_= scoped.o obj-$(CONFIG_SAMPLE_RUST_DMA) +=3D rust_dma.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) +=3D rust_driver_i2c.o obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) +=3D rust_i2c_client.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_EDU) +=3D rust_driver_edu.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) +=3D rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o diff --git a/samples/rust/rust_driver_edu.rs b/samples/rust/rust_driver_edu= .rs new file mode 100644 index 000000000000..52f6c4cf3b08 --- /dev/null +++ b/samples/rust/rust_driver_edu.rs @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust EDU driver sample (based on QEMU's `edu`). +//! +//! To make this driver probe, QEMU must be run with `-device edu`. + +use kernel::{ + device::Bound, + dma::{ + Coherent, + Device, + DmaMask, // + }, + io::{ + poll::read_poll_timeout, + register, + register::Array, + Io, // + }, + irq::{ + self, + Flags, // + }, + pci::{ + self, + IrqTypes, // + }, + prelude::*, + sync::Completion, + time::Delta, // +}; + +const QEMU_VENDOR_ID: u16 =3D 0x1234; +const QEMU_EDU_DEVICE_ID: u32 =3D 0x11e8; +const QEMU_EDU_DEVICE_MAGIC: u8 =3D 0xed; +const QEMU_DMA_BASE: u64 =3D 0x40000; + +const IRQ_MAGIC_VALUE: u32 =3D 42; + +/// Bit set in `IRQ_STATUS` when a DMA transfer has completed. +const DMA_IRQ: u32 =3D 0x100; + +mod regs { + use super::*; + + register! { + pub(super) IDENTIFICATION(u32) @ 0x0 { + 31:24 major; + 23:16 minor; + 7:0 magic; + } + + pub(super) LIVENESS_CHECK(u32) @ 0x04 {} + + pub(super) FACTORIAL(u32) @ 0x08 {} + + pub(super) STATUS(u32) @ 0x20 { + 0:0 computing; + 7:7 raise_interrupt; + } + + pub(super) IRQ_STATUS(u32) @ 0x24 {} + pub(super) IRQ_RAISE(u32) @ 0x60 {} + pub(super) IRQ_ACK(u32) @ 0x64 {} + + pub(super) DMA_SRC(u64) @ 0x80 {} + pub(super) DMA_DST(u64) @ 0x88 {} + pub(super) DMA_COUNT(u64) @ 0x90 {} + pub(super) DMA_COMMAND(u64) @ 0x98 { + 0:0 start_transfer; + 1:1 direction; + 2:2 raise_irq; + } + } + + pub(super) const END: usize =3D 0xA0; +} + +type Bar0<'a> =3D pci::Bar<'a, { regs::END }>; + +struct EduDriver; + +#[pin_data(PinnedDrop)] +struct EduDriverData<'bound> { + pdev: &'bound pci::Device, + #[pin] + irq_handler: irq::Registration<'bound, IrqHandler<'bound>>, + // Declared last so the device stays enabled until the IRQ handler is = freed. + _enable: pci::DeviceEnableGuard<'bound>, +} + +#[pin_data] +struct IrqHandler<'a> { + pdev: &'a pci::Device, + bar: Bar0<'a>, + #[pin] + irq_test_completion: Completion, + #[pin] + irq_dma_completion: Completion, + dma: Coherent, +} + +impl EduDriver { + fn init(pdev: &pci::Device, bar: &Bar0<'_>, handler: &IrqHandle= r<'_>) -> Result { + Self::config_space(pdev); + Self::magic(pdev, bar)?; + Self::liveness_check(pdev, bar)?; + Self::factorial(pdev, bar)?; + Self::test_irq(pdev, handler)?; + Self::test_dma(pdev, handler)?; + Ok(()) + } + + fn config_space(pdev: &pci::Device) { + let config =3D pdev.config_space(); + + // Some PCI configuration space registers. + register! { + VENDOR_ID(u16) @ 0x0 { + 15:0 vendor_id; + } + + REVISION_ID(u8) @ 0x8 { + 7:0 revision_id; + } + + BAR(u32)[6] @ 0x10 { + 31:0 value; + } + } + + dev_info!( + pdev, + "config space read8 rev ID: {:x}\n", + config.read(REVISION_ID).revision_id() + ); + + dev_info!( + pdev, + "config space read16 vendor ID: {:x}\n", + config.read(VENDOR_ID).vendor_id() + ); + + dev_info!( + pdev, + "config space read32 BAR 0: {:x}\n", + config.read(BAR::at(0)).value() + ); + } + + fn magic(pdev: &pci::Device, bar: &Bar0<'_>) -> Result { + let identification =3D bar.read(regs::IDENTIFICATION); + + let magic: u8 =3D identification.magic().into(); + + if magic !=3D QEMU_EDU_DEVICE_MAGIC { + dev_err!( + pdev, + "magic mismatch: expected {:#x} got {:#x}\n", + QEMU_EDU_DEVICE_MAGIC, + magic + ); + return Err(ENODEV); + } + + dev_info!( + pdev, + "major: {:#x} minor: {:#x}\n", + identification.major(), + identification.minor() + ); + Ok(()) + } + + fn liveness_check(pdev: &pci::Device, bar: &Bar0<'_>) -> Result= { + let test_value =3D 0xabcd; + + bar.write(regs::LIVENESS_CHECK, test_value.into()); + + let inverse_value =3D bar.read(regs::LIVENESS_CHECK).into_raw(); + + if inverse_value !=3D !test_value { + dev_err!( + pdev, + "inverse mismatch: expected {:#x} got {:#x}\n", + !test_value, + inverse_value + ); + return Err(ENODEV); + } + + dev_info!(pdev, "inverse test successful\n"); + Ok(()) + } + + fn factorial(pdev: &pci::Device, bar: &Bar0<'_>) -> Result { + Self::wait_until_compute_has_finished(pdev, bar)?; + + bar.write(regs::FACTORIAL, 4.into()); + + Self::wait_until_compute_has_finished(pdev, bar)?; + + let result: u32 =3D bar.read(regs::FACTORIAL).into(); + + let expected =3D 24; + + if result !=3D expected { + dev_err!( + pdev, + "factorial result wrong: expected {} got {}\n", + expected, + result + ); + return Err(ENODEV); + } + + dev_info!(pdev, "factorial test successful\n"); + Ok(()) + } + + fn test_irq(pdev: &pci::Device, handler: &IrqHandler<'_>) -> Re= sult { + dev_dbg!(pdev, "raising irq\n"); + + handler.bar.write(regs::IRQ_RAISE, IRQ_MAGIC_VALUE.into()); + + handler.irq_test_completion.wait_for_completion(); + + dev_info!(pdev, "irq test successful\n"); + Ok(()) + } + + fn test_dma(pdev: &pci::Device, handler: &IrqHandler<'_>) -> Re= sult { + dev_dbg!(pdev, "testing dma\n"); + + let dma =3D &handler.dma; + + const DMA_VALUE: u64 =3D 42; + + kernel::dma_write!(dma, , DMA_VALUE); + + handler.bar.write(regs::DMA_SRC, dma.dma_handle().into()); + handler.bar.write(regs::DMA_DST, QEMU_DMA_BASE.into()); + handler + .bar + .write(regs::DMA_COUNT, (dma.size() as u64).into()); + handler.bar.write( + regs::DMA_COMMAND, + regs::DMA_COMMAND::zeroed() + .with_start_transfer(true) + .with_direction(false) + .with_raise_irq(true), + ); + + handler.irq_dma_completion.wait_for_completion(); + + // Destroy previous value to test roundtrip + kernel::dma_write!(dma, , 0); + + handler.bar.write(regs::DMA_SRC, QEMU_DMA_BASE.into()); + handler.bar.write(regs::DMA_DST, dma.dma_handle().into()); + handler + .bar + .write(regs::DMA_COUNT, (dma.size() as u64).into()); + handler.bar.write( + regs::DMA_COMMAND, + regs::DMA_COMMAND::zeroed() + .with_start_transfer(true) + .with_direction(true) + .with_raise_irq(true), + ); + + handler.irq_dma_completion.wait_for_completion(); + + let result =3D kernel::dma_read!(dma,); + + if result !=3D DMA_VALUE { + dev_err!( + pdev, + "dma result wrong: expected {} got {}\n", + DMA_VALUE, + result + ); + return Err(ENODEV); + } + + dev_info!(pdev, "dma test successful\n"); + Ok(()) + } + + fn wait_until_compute_has_finished(pdev: &pci::Device, bar: &Ba= r0<'_>) -> Result { + read_poll_timeout( + || Ok(bar.read(regs::STATUS)), + |status| status.computing() =3D=3D 0, + Delta::from_millis(10), + Delta::from_millis(100), + ) + .inspect_err(|_| dev_err!(pdev, "computation bit did not clear bef= ore timeout\n")) + .map(|_| ()) + } +} + +impl pci::Driver for EduDriver { + type IdInfo =3D (); + type Data<'bound> =3D EduDriverData<'bound>; + + const ID_TABLE: pci::IdTable =3D &PCI_TABLE; + + fn probe<'bound>( + pdev: &'bound pci::Device>, + _id_info: &'bound Self::IdInfo, + ) -> impl PinInit, Error> + 'bound { + pin_init::pin_init_scope(move || { + let vendor =3D pdev.vendor_id(); + dev_dbg!( + pdev, + "Probe Rust EDU driver sample (PCI ID: {}, 0x{:x}).\n", + vendor, + pdev.device_id() + ); + + let enable =3D pdev.enable_device()?; + pdev.set_master(); + + let mask =3D DmaMask::new::<28>(); + + // SAFETY: There are no concurrent calls to DMA allocation and= mapping primitives. + unsafe { pdev.dma_set_mask_and_coherent(mask)? }; + + let ca: Coherent =3D Coherent::zeroed(pdev.as_ref(), GFP_= KERNEL)?; + + let irq =3D pdev + .alloc_irq_vectors(1, 1, IrqTypes::default().with(pci::Irq= Type::Msi)) + .inspect_err(|e| dev_err!(pdev, "alloc_irq_vectors failed:= {:?}\n", e))?; + + let bar =3D pdev.iomap_region_sized::<{ regs::END }>(0, c"rust= _driver_edu")?; + + // SAFETY: The Registration is not leaked. + let req =3D unsafe { + pdev.request_irq( + *irq.start(), + Flags::TRIGGER_NONE, + c"rust_edu_irq", + try_pin_init!(IrqHandler { + pdev, + bar, + irq_test_completion <- Completion::new(), + irq_dma_completion <- Completion::new(), + dma: ca, + }? Error), + ) + }; + + Ok(try_pin_init!(EduDriverData { + irq_handler <- req, + // Ordering matters: the handler is registered (`irq_handl= er <- req`) + // *before* the `_:` block runs the self-tests, one of whi= ch raises an + // interrupt and waits for the handler. Raising before the= handler is + // registered would hang (the completion is never signalle= d). + _: { + let handler =3D irq_handler.handler(); + EduDriver::init(pdev, &handler.bar, handler)?; + dev_info!( + pdev, + "rust_driver_edu successfully initialized\n", + ); + }, + pdev, + _enable: enable, + })) + }) + } +} + +impl irq::Handler for IrqHandler<'_> { + fn handle(&self) -> irq::IrqReturn { + dev_dbg!(self.pdev, "irq handler called\n"); + let status: u32 =3D self.bar.read(regs::IRQ_STATUS).into(); + + // DMA_IRQ + if status & DMA_IRQ !=3D 0 { + dev_dbg!(self.pdev, "handling dma completion in irq\n"); + self.bar.write(regs::IRQ_ACK, DMA_IRQ.into()); + self.irq_dma_completion.complete(); + } + + // TEST_IRQ + let magic =3D status & !DMA_IRQ; + if magic =3D=3D IRQ_MAGIC_VALUE { + dev_dbg!(self.pdev, "handling test completion in irq\n"); + self.bar.write(regs::IRQ_ACK, magic.into()); + self.irq_test_completion.complete(); + } + + irq::IrqReturn::Handled + } +} + +#[pinned_drop] +impl PinnedDrop for EduDriverData<'_> { + fn drop(self: Pin<&mut Self>) { + dev_dbg!(self.pdev, "Remove Rust EDU driver sample.\n"); + } +} + +kernel::pci_device_table!( + PCI_TABLE, + MODULE_PCI_TABLE, + ::IdInfo, + [( + pci::DeviceId::from_id(pci::Vendor::from_raw(QEMU_VENDOR_ID), QEMU= _EDU_DEVICE_ID), + () + )] +); + +kernel::module_pci_driver! { + type: EduDriver, + name: "rust_driver_edu", + authors: ["Maurice Hieronymus"], + description: "Rust EDU driver", + license: "GPL v2", +} --=20 2.54.0