[PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl

Zhi Wang posted 2 patches 2 weeks, 3 days ago
[PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by Zhi Wang 2 weeks, 3 days ago
This patch adds a sample Rust driver demonstrating the usage of the fwctl
Rust abstractions. Add sample code for creating a FwCtl device, getting
device info and issuing an RPC.

Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
 samples/rust/Kconfig              |  11 +++
 samples/rust/Makefile             |   1 +
 samples/rust/rust_driver_fwctl.rs | 136 ++++++++++++++++++++++++++++++
 3 files changed, 148 insertions(+)
 create mode 100644 samples/rust/rust_driver_fwctl.rs

diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index c49ab9106345..3d0b223caa89 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -172,6 +172,17 @@ config SAMPLE_RUST_SOC
 
 	  If unsure, say N.
 
+config SAMPLE_RUST_DRIVER_FWCTL
+	tristate "Fwctl Driver"
+	depends on FWCTL
+	help
+	  This option builds the Rust Fwctl driver sample.
+
+	  To compile this as a module, choose M here:
+	  the module will be called rust_driver_fwctl.
+
+	  If unsure, say N.
+
 config SAMPLE_RUST_HOSTPROGS
 	bool "Host programs"
 	help
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index 6c0aaa58cccc..6f6030e64727 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM)	+= rust_driver_platform.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB)		+= rust_driver_usb.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX)		+= rust_driver_faux.o
 obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY)	+= rust_driver_auxiliary.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_FWCTL)		+= rust_driver_fwctl.o
 obj-$(CONFIG_SAMPLE_RUST_CONFIGFS)		+= rust_configfs.o
 obj-$(CONFIG_SAMPLE_RUST_SOC)			+= rust_soc.o
 
diff --git a/samples/rust/rust_driver_fwctl.rs b/samples/rust/rust_driver_fwctl.rs
new file mode 100644
index 000000000000..ac5f979fd73b
--- /dev/null
+++ b/samples/rust/rust_driver_fwctl.rs
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust fwctl API test (based on QEMU's `pci-testdev`).
+//!
+//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
+
+use kernel::{
+    bindings,
+    device,
+    device::Core,
+    devres::Devres,
+    fwctl,
+    pci,
+    prelude::*,
+    sync::aref::ARef,
+    types,
+};
+
+struct FwctlSampleUserCtx {
+    _drvdata: u32,
+}
+
+struct FwctlSampleOps;
+
+impl fwctl::Operations for FwctlSampleOps {
+    type UserCtx = FwctlSampleUserCtx;
+
+    const DEVICE_TYPE: fwctl::DeviceType = fwctl::DeviceType::RustFwctlTest;
+
+    fn open(
+        fwctl_uctx: &types::Opaque<bindings::fwctl_uctx>
+    ) -> Result<impl PinInit<Self::UserCtx, Error>, Error> {
+        let dev = fwctl::UserCtx::<Self::UserCtx>::parent_device_from_raw(fwctl_uctx);
+
+        dev_info!(dev, "fwctl test driver: open_uctx()");
+
+        // Return an initializer for the user context.
+        // The framework will initialize this in-place in the C-allocated memory.
+        Ok(try_init!(FwctlSampleUserCtx {
+            _drvdata: 0,
+        }))
+    }
+
+    fn close(uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>) {
+        let dev = uctx.get_parent_device();
+
+        dev_info!(dev, "fwctl test driver: close_uctx()");
+    }
+
+    fn info(uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>) -> Result<KVec<u8>, Error> {
+        let dev = uctx.get_parent_device();
+
+        dev_info!(dev, "fwctl test driver: info()");
+
+        let mut infobuf = KVec::<u8>::new();
+        infobuf.push(0xef, GFP_KERNEL)?;
+        infobuf.push(0xbe, GFP_KERNEL)?;
+        infobuf.push(0xad, GFP_KERNEL)?;
+        infobuf.push(0xde, GFP_KERNEL)?;
+
+        Ok(infobuf)
+    }
+
+    fn fw_rpc(
+        uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>,
+        scope: u32,
+        rpc_in: &mut [u8],
+        _out_len: *mut usize,
+    ) -> Result<Option<KVec<u8>>, Error> {
+        let dev = uctx.get_parent_device();
+
+        dev_info!(dev, "fwctl test driver: fw_rpc() scope {}", scope);
+
+        if rpc_in.len() != 4 {
+            return Err(EINVAL);
+        }
+
+        dev_info!(
+            dev,
+            "fwctl test driver: inbuf len{} bytes[0-3] {:x} {:x} {:x} {:x}",
+            rpc_in.len(),
+            rpc_in[0],
+            rpc_in[1],
+            rpc_in[2],
+            rpc_in[3]
+        );
+
+        let mut outbuf = KVec::<u8>::new();
+        outbuf.push(0xef, GFP_KERNEL)?;
+        outbuf.push(0xbe, GFP_KERNEL)?;
+        outbuf.push(0xad, GFP_KERNEL)?;
+        outbuf.push(0xde, GFP_KERNEL)?;
+
+        Ok(Some(outbuf))
+    }
+}
+
+#[pin_data]
+struct FwctlSampleDriver {
+    pdev: ARef<pci::Device>,
+    #[pin]
+    fwctl: Devres<fwctl::Registration<FwctlSampleOps>>,
+}
+
+kernel::pci_device_table!(
+    PCI_TABLE,
+    MODULE_PCI_TABLE,
+    <FwctlSampleDriver as pci::Driver>::IdInfo,
+    [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
+);
+
+impl pci::Driver for FwctlSampleDriver {
+    type IdInfo = ();
+    const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
+
+    fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
+        dev_info!(pdev.as_ref(), "Probe fwctl test driver");
+
+        // `pdev` is `Device<Core>`, which derefs to `Device<Bound>` during probe.
+        let pdev_bound: &pci::Device<device::Bound> = pdev;
+
+        try_pin_init!(Self {
+            pdev: pdev.into(),
+            fwctl <- fwctl::Registration::<FwctlSampleOps>::new(pdev_bound.as_ref()),
+        })
+    }
+}
+
+kernel::module_pci_driver! {
+    type: FwctlSampleDriver,
+    name: "rust_driver_fwctl",
+    authors: ["Zhi Wang"],
+    description: "Rust fwctl test",
+    license: "GPL v2",
+    imports_ns: ["FWCTL"],
+}
-- 
2.51.0
Re: [PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by Gary Guo 1 week, 6 days ago
On Thu Jan 22, 2026 at 8:42 PM GMT, Zhi Wang wrote:
> This patch adds a sample Rust driver demonstrating the usage of the fwctl
> Rust abstractions. Add sample code for creating a FwCtl device, getting
> device info and issuing an RPC.
>
> Cc: Danilo Krummrich <dakr@kernel.org>
> Cc: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
> ---
>  samples/rust/Kconfig              |  11 +++
>  samples/rust/Makefile             |   1 +
>  samples/rust/rust_driver_fwctl.rs | 136 ++++++++++++++++++++++++++++++
>  3 files changed, 148 insertions(+)
>  create mode 100644 samples/rust/rust_driver_fwctl.rs
>
> diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
> index c49ab9106345..3d0b223caa89 100644
> --- a/samples/rust/Kconfig
> +++ b/samples/rust/Kconfig
> @@ -172,6 +172,17 @@ config SAMPLE_RUST_SOC
>  
>  	  If unsure, say N.
>  
> +config SAMPLE_RUST_DRIVER_FWCTL
> +	tristate "Fwctl Driver"
> +	depends on FWCTL
> +	help
> +	  This option builds the Rust Fwctl driver sample.
> +
> +	  To compile this as a module, choose M here:
> +	  the module will be called rust_driver_fwctl.
> +
> +	  If unsure, say N.
> +
>  config SAMPLE_RUST_HOSTPROGS
>  	bool "Host programs"
>  	help
> diff --git a/samples/rust/Makefile b/samples/rust/Makefile
> index 6c0aaa58cccc..6f6030e64727 100644
> --- a/samples/rust/Makefile
> +++ b/samples/rust/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM)	+= rust_driver_platform.o
>  obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB)		+= rust_driver_usb.o
>  obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX)		+= rust_driver_faux.o
>  obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY)	+= rust_driver_auxiliary.o
> +obj-$(CONFIG_SAMPLE_RUST_DRIVER_FWCTL)		+= rust_driver_fwctl.o
>  obj-$(CONFIG_SAMPLE_RUST_CONFIGFS)		+= rust_configfs.o
>  obj-$(CONFIG_SAMPLE_RUST_SOC)			+= rust_soc.o
>  
> diff --git a/samples/rust/rust_driver_fwctl.rs b/samples/rust/rust_driver_fwctl.rs
> new file mode 100644
> index 000000000000..ac5f979fd73b
> --- /dev/null
> +++ b/samples/rust/rust_driver_fwctl.rs
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Rust fwctl API test (based on QEMU's `pci-testdev`).
> +//!
> +//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
> +
> +use kernel::{
> +    bindings,
> +    device,
> +    device::Core,
> +    devres::Devres,
> +    fwctl,
> +    pci,
> +    prelude::*,
> +    sync::aref::ARef,
> +    types,
> +};
> +
> +struct FwctlSampleUserCtx {
> +    _drvdata: u32,
> +}
> +
> +struct FwctlSampleOps;
> +
> +impl fwctl::Operations for FwctlSampleOps {
> +    type UserCtx = FwctlSampleUserCtx;
> +
> +    const DEVICE_TYPE: fwctl::DeviceType = fwctl::DeviceType::RustFwctlTest;
> +
> +    fn open(
> +        fwctl_uctx: &types::Opaque<bindings::fwctl_uctx>
> +    ) -> Result<impl PinInit<Self::UserCtx, Error>, Error> {
> +        let dev = fwctl::UserCtx::<Self::UserCtx>::parent_device_from_raw(fwctl_uctx);

Why does this raw binding need to be handled by the user?

> +
> +        dev_info!(dev, "fwctl test driver: open_uctx()");
> +
> +        // Return an initializer for the user context.
> +        // The framework will initialize this in-place in the C-allocated memory.
> +        Ok(try_init!(FwctlSampleUserCtx {
> +            _drvdata: 0,
> +        }))
> +    }
> +
> +    fn close(uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>) {
> +        let dev = uctx.get_parent_device();
> +
> +        dev_info!(dev, "fwctl test driver: close_uctx()");
> +    }
> +
> +    fn info(uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>) -> Result<KVec<u8>, Error> {

This can just be `Result<KVec<u8>>`.

Best,
Gary

> +        let dev = uctx.get_parent_device();
> +
> +        dev_info!(dev, "fwctl test driver: info()");
> +
> +        let mut infobuf = KVec::<u8>::new();
> +        infobuf.push(0xef, GFP_KERNEL)?;
> +        infobuf.push(0xbe, GFP_KERNEL)?;
> +        infobuf.push(0xad, GFP_KERNEL)?;
> +        infobuf.push(0xde, GFP_KERNEL)?;
> +
> +        Ok(infobuf)
> +    }
> +
> +    fn fw_rpc(
> +        uctx: &mut fwctl::UserCtx<FwctlSampleUserCtx>,
> +        scope: u32,
> +        rpc_in: &mut [u8],
> +        _out_len: *mut usize,
> +    ) -> Result<Option<KVec<u8>>, Error> {
> +        let dev = uctx.get_parent_device();
> +
> +        dev_info!(dev, "fwctl test driver: fw_rpc() scope {}", scope);
> +
> +        if rpc_in.len() != 4 {
> +            return Err(EINVAL);
> +        }
> +
> +        dev_info!(
> +            dev,
> +            "fwctl test driver: inbuf len{} bytes[0-3] {:x} {:x} {:x} {:x}",
> +            rpc_in.len(),
> +            rpc_in[0],
> +            rpc_in[1],
> +            rpc_in[2],
> +            rpc_in[3]
> +        );
> +
> +        let mut outbuf = KVec::<u8>::new();
> +        outbuf.push(0xef, GFP_KERNEL)?;
> +        outbuf.push(0xbe, GFP_KERNEL)?;
> +        outbuf.push(0xad, GFP_KERNEL)?;
> +        outbuf.push(0xde, GFP_KERNEL)?;
> +
> +        Ok(Some(outbuf))
> +    }
> +}
> +
> +#[pin_data]
> +struct FwctlSampleDriver {
> +    pdev: ARef<pci::Device>,
> +    #[pin]
> +    fwctl: Devres<fwctl::Registration<FwctlSampleOps>>,
> +}
> +
> +kernel::pci_device_table!(
> +    PCI_TABLE,
> +    MODULE_PCI_TABLE,
> +    <FwctlSampleDriver as pci::Driver>::IdInfo,
> +    [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())]
> +);
> +
> +impl pci::Driver for FwctlSampleDriver {
> +    type IdInfo = ();
> +    const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
> +
> +    fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
> +        dev_info!(pdev.as_ref(), "Probe fwctl test driver");
> +
> +        // `pdev` is `Device<Core>`, which derefs to `Device<Bound>` during probe.
> +        let pdev_bound: &pci::Device<device::Bound> = pdev;
> +
> +        try_pin_init!(Self {
> +            pdev: pdev.into(),
> +            fwctl <- fwctl::Registration::<FwctlSampleOps>::new(pdev_bound.as_ref()),
> +        })
> +    }
> +}
> +
> +kernel::module_pci_driver! {
> +    type: FwctlSampleDriver,
> +    name: "rust_driver_fwctl",
> +    authors: ["Zhi Wang"],
> +    description: "Rust fwctl test",
> +    license: "GPL v2",
> +    imports_ns: ["FWCTL"],
> +}
Re: [PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by Jason Gunthorpe 2 weeks, 3 days ago
On Thu, Jan 22, 2026 at 10:42:31PM +0200, Zhi Wang wrote:
> This patch adds a sample Rust driver demonstrating the usage of the fwctl
> Rust abstractions. Add sample code for creating a FwCtl device, getting
> device info and issuing an RPC.
> 
> Cc: Danilo Krummrich <dakr@kernel.org>
> Cc: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
> ---
>  samples/rust/Kconfig              |  11 +++
>  samples/rust/Makefile             |   1 +
>  samples/rust/rust_driver_fwctl.rs | 136 ++++++++++++++++++++++++++++++
>  3 files changed, 148 insertions(+)
>  create mode 100644 samples/rust/rust_driver_fwctl.rs

Is this normal for Rust? Can we delete it when a real driver is
merged?

I'm not so keen on sample drivers, I've spent far too much time lately
touching sample drivers that nobody ever uses :(

Jason
Re: [PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by Danilo Krummrich 2 weeks, 3 days ago
On Thu Jan 22, 2026 at 9:58 PM CET, Jason Gunthorpe wrote:
> On Thu, Jan 22, 2026 at 10:42:31PM +0200, Zhi Wang wrote:
>> This patch adds a sample Rust driver demonstrating the usage of the fwctl
>> Rust abstractions. Add sample code for creating a FwCtl device, getting
>> device info and issuing an RPC.
>> 
>> Cc: Danilo Krummrich <dakr@kernel.org>
>> Cc: Jason Gunthorpe <jgg@nvidia.com>
>> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
>> ---
>>  samples/rust/Kconfig              |  11 +++
>>  samples/rust/Makefile             |   1 +
>>  samples/rust/rust_driver_fwctl.rs | 136 ++++++++++++++++++++++++++++++
>>  3 files changed, 148 insertions(+)
>>  create mode 100644 samples/rust/rust_driver_fwctl.rs
>
> Is this normal for Rust? Can we delete it when a real driver is
> merged?
>
> I'm not so keen on sample drivers, I've spent far too much time lately
> touching sample drivers that nobody ever uses :(

I think it is pretty useful for review purposes (at least as long as the first
real user is not yet ready) to see how it turns out from a user perspective.

It may also be pretty useful for people starting out with Rust in the kernel, as
the samples have a very limited scope compared to real drivers.

But there is no policy or anything, i.e. no need to keep it. There's also no
need to even land it if you prefer not to do so.
Re: [PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by John Hubbard 2 weeks, 3 days ago
On 1/22/26 1:06 PM, Danilo Krummrich wrote:
> On Thu Jan 22, 2026 at 9:58 PM CET, Jason Gunthorpe wrote:
>> On Thu, Jan 22, 2026 at 10:42:31PM +0200, Zhi Wang wrote:
>>> This patch adds a sample Rust driver demonstrating the usage of the fwctl
>>> Rust abstractions. Add sample code for creating a FwCtl device, getting
>>> device info and issuing an RPC.
>>>
>>> Cc: Danilo Krummrich <dakr@kernel.org>
>>> Cc: Jason Gunthorpe <jgg@nvidia.com>
>>> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
>>> ---
>>>  samples/rust/Kconfig              |  11 +++
>>>  samples/rust/Makefile             |   1 +
>>>  samples/rust/rust_driver_fwctl.rs | 136 ++++++++++++++++++++++++++++++
>>>  3 files changed, 148 insertions(+)
>>>  create mode 100644 samples/rust/rust_driver_fwctl.rs
>>
>> Is this normal for Rust? Can we delete it when a real driver is
>> merged?
>>
>> I'm not so keen on sample drivers, I've spent far too much time lately
>> touching sample drivers that nobody ever uses :(
> 
> I think it is pretty useful for review purposes (at least as long as the first
> real user is not yet ready) to see how it turns out from a user perspective.
> 
> It may also be pretty useful for people starting out with Rust in the kernel, as
> the samples have a very limited scope compared to real drivers.
> 
> But there is no policy or anything, i.e. no need to keep it. There's also no
> need to even land it if you prefer not to do so.

Zhi, the real code that uses this for vGPU is going to be posted soon-ish,
right? So we could use this patch as a review assist, like Danilo mentions,
but not merge it, because the real code will suffice to exercise the new
fwctl functionality.

thanks,
-- 
John Hubbard
Re: [PATCH v2 2/2] samples: rust: fwctl: add sample code for fwctl
Posted by Zhi Wang 2 weeks, 2 days ago
On Thu, 22 Jan 2026 13:16:29 -0800
John Hubbard <jhubbard@nvidia.com> wrote:

> On 1/22/26 1:06 PM, Danilo Krummrich wrote:
> > On Thu Jan 22, 2026 at 9:58 PM CET, Jason Gunthorpe wrote:
> >> On Thu, Jan 22, 2026 at 10:42:31PM +0200, Zhi Wang wrote:
> >>> This patch adds a sample Rust driver demonstrating the usage of the
> >>> fwctl Rust abstractions. Add sample code for creating a FwCtl
> >>> device, getting device info and issuing an RPC.
> >>>
> >>> Cc: Danilo Krummrich <dakr@kernel.org>
> >>> Cc: Jason Gunthorpe <jgg@nvidia.com>
> >>> Signed-off-by: Zhi Wang <zhiw@nvidia.com>
> >>> ---
> >>>  samples/rust/Kconfig              |  11 +++
> >>>  samples/rust/Makefile             |   1 +
> >>>  samples/rust/rust_driver_fwctl.rs | 136
> >>> ++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+)
> >>>  create mode 100644 samples/rust/rust_driver_fwctl.rs
> >>
> >> Is this normal for Rust? Can we delete it when a real driver is
> >> merged?
> >>
> >> I'm not so keen on sample drivers, I've spent far too much time lately
> >> touching sample drivers that nobody ever uses :(
> > 
> > I think it is pretty useful for review purposes (at least as long as
> > the first real user is not yet ready) to see how it turns out from a
> > user perspective.
> > 
> > It may also be pretty useful for people starting out with Rust in the
> > kernel, as the samples have a very limited scope compared to real
> > drivers.
> > 
> > But there is no policy or anything, i.e. no need to keep it. There's
> > also no need to even land it if you prefer not to do so.
> 
> Zhi, the real code that uses this for vGPU is going to be posted
> soon-ish, right? So we could use this patch as a review assist, like
> Danilo mentions, but not merge it, because the real code will suffice to
> exercise the new fwctl functionality.
> 

I am OK with any solutions. My motivation of updating this one is because
of many changes and improvements in this re-spin comparing to the RFC. As
Jason/Danilo gave quite some feedback on RFC (Thanks for the review
efforts!), I would like to start the review before the vGPU patches.

Z.

> thanks,