[PATCH v18 0/7] rust: extend `module!` macro with integer parameter support

Andreas Hindborg posted 7 patches 4 months, 2 weeks ago
MAINTAINERS                  |   2 +
rust/kernel/lib.rs           |   1 +
rust/kernel/module_param.rs  | 181 ++++++++++++++++++++++++++++++++++++++++
rust/kernel/str.rs           |   2 +
rust/kernel/str/parse_int.rs | 148 +++++++++++++++++++++++++++++++++
rust/kernel/sync.rs          |   2 +
rust/kernel/sync/set_once.rs | 125 ++++++++++++++++++++++++++++
rust/macros/helpers.rs       |  25 ++++++
rust/macros/lib.rs           |  31 +++++++
rust/macros/module.rs        | 194 +++++++++++++++++++++++++++++++++++++++----
samples/rust/rust_minimal.rs |  10 +++
11 files changed, 703 insertions(+), 18 deletions(-)
[PATCH v18 0/7] rust: extend `module!` macro with integer parameter support
Posted by Andreas Hindborg 4 months, 2 weeks ago
Extend the `module!` macro with support module parameters. Also add some
string to integer parsing functions.

Based on the original module parameter support by Miguel [1],
later extended and generalized by Adam for more types [2][3].
Originally tracked at [4].

Link: https://github.com/Rust-for-Linux/linux/pull/7 [1]
Link: https://github.com/Rust-for-Linux/linux/pull/82 [2]
Link: https://github.com/Rust-for-Linux/linux/pull/87 [3]
Link: https://github.com/Rust-for-Linux/linux/issues/11 [4]
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
Changes in v18:
- Rebase on Rust atomic patches (tip/master).
- Link to v17: https://lore.kernel.org/r/20250711-module-params-v3-v17-0-cf9b10d4923d@kernel.org

Changes in v17:
- Fix drop impl of `SetOnce` so that it works with `UnsafeCell<MaybeUninit<_>>`.
- Slightly reword safety framework in `SetOnce`.
- Rebase on atomic series v6.
- Link to v16: https://lore.kernel.org/r/20250709-module-params-v3-v16-0-4f926bcccb50@kernel.org

Changes in v16:
- Normalize imports in `set_once.rs`.
- Use `UnsafeCell<MaybeUninit<T>>` rather than `Opaque<T>` for `SetOnce`.
- Use regular load in drop of `SetOnce`.
- Update attribution paragraph in cover letter with details from Miguel.
- Remove stray TODO in `set_once.rs`
- Link to v15: https://lore.kernel.org/r/20250707-module-params-v3-v15-0-c1f4269a57b9@kernel.org

Changes in v15:
- Rebase on v6.16-rc5.
- Dedent code in module macro for better formatting.
- Rename `OnceLock` to `SetOnce`.
- Use "being initialized" rather than "being mutably accessed" when
  describing initialization state of `OnceLock`.
- Use `Relaxed` ordering when transitioning to exclusive access in
  `OnceLock`.
- Add drop implementation for `OnceLock`.
- Re-export `OnceLock` from `kernel::sync` module.
- Improve indentation of in macro code. Prefix `cfg` to `::core::cfg` in
  macro code.
- Use `core::ptr::from_ref` rather than `as` casts.
- Hide `KernelParam` instances behind `const _: ()` blocks.
- Rename `ModuleParamAccess::get` to `ModuleParamAccess::value`.
- Rename `RacyKernelParam` to `KernelParam`.
- Remove `ModuleParam::Value`.
- Move `copy` implementation of `OnceLock`.
- Update safety comments and invariants of `OnceLock`.
- Link to v14: https://lore.kernel.org/r/20250702-module-params-v3-v14-0-5b1cc32311af@kernel.org

Note: This series now depends on the atomics series [1].

[1] https://lore.kernel.org/all/20250618164934.19817-1-boqun.feng@gmail.com

Changes in v14:
- Remove unnecessary `crate::` prefix from `module_param::set_param`.
- Make `FromStrRadix` safe again by moving unsafe blocks to macro implementation (thanks Benno).
- Use `core::ptr::write` in `set_param` and drop safety requirement regarding initialization.
- Add a TODO to use `SyncUnsafeCell` for `ModuleParamAccess` when available.
- Add a NOTE regarding `Copy` bound on `ModuleParam`.
- Remove `'static` lifetime qualifier from `ModuleParam::try_from_param_arg` argument.
- Fix a typo in the safety requirements for `set_param`.
- Remove unused `#[macro_export]` attribute.
- Remove obsolete documentation for `ModuleParam::try_from_param_arg`.
- Make `RacyKernelParam` tuple field private.
- Introduce `OnceLock` and use that to synchronize population of parameter values.
- Link to v13: https://lore.kernel.org/r/20250612-module-params-v3-v13-0-bc219cd1a3f8@kernel.org

Changes in v13:
- remove absolute path for `ffi` types.
- Split patch 2 into 4 separate patches.
- Overhaul safety framework for `set_param`.
- Remove generated docs for `kernel_param_ops`.
- Move `parse_int` to separate file.
- Rebase on v6.16-rc1
- Link to v12: https://lore.kernel.org/r/20250506-module-params-v3-v12-0-c04d80c8a2b1@kernel.org

Changes in v12:
- Assign through pointer rather than using `core::ptr::replace`.
- Prevent a potential use-after-free during module teardown.
- Link to v11: https://lore.kernel.org/r/20250502-module-params-v3-v11-0-6096875a2b78@kernel.org

Changes in v11:
- Apply a few nits from Miguel.
- Link to v10: https://lore.kernel.org/r/20250501-module-params-v3-v10-0-4da485d343d5@kernel.org

Changes in v10:
- Apply fixups from Miguel:
  - Add integer type suffixes to `assert!` in tests.
  - Fix links to docs.kernel.org.
  - Applyy markdown and intra-doc links where possible.
  - Change to `///` for `mod` docs.
  - Slightly reword a comment.
  - Pluralize "Examples" section name.
  - Hide `use`s in example.
  - Removed `#[expect]` for the `rusttest` target.
- Link to v9: https://lore.kernel.org/r/20250321-module-params-v3-v9-0-28b905f2e345@kernel.org

Changes in v9:
- Remove UB when parsing the minimum integer values.
- Make `FromStr` trait unsafe, since wrong implementations can cause UB.
- Drop patches that were applied to rust-next.
- Link to v8: https://lore.kernel.org/r/20250227-module-params-v3-v8-0-ceeee85d9347@kernel.org

Changes in v8:
- Change print statement in sample to better communicate parameter name.
- Use imperative mode in commit messages.
- Remove prefix path from `EINVAL`.
- Change `try_from_param_arg` to accept `&BStr` rather than `&[u8]`.
- Parse integers without 128 bit integer types.
- Seal trait `FromStrRadix`.
- Strengthen safety requirement of `set_param`.
- Remove comment about Display and `PAGE_SIZE`.
- Add note describing why `ModuleParamAccess` is pub.
- Typo and grammar fixes for documentation.
- Update MAINTAINERS with rust module files.
- Link to v7: https://lore.kernel.org/r/20250218-module-params-v3-v7-0-5e1afabcac1b@kernel.org

Changes in v7:
- Remove dependency on `pr_warn_once` patches, replace with TODO.
- Rework `ParseInt::from_str` to avoid allocating.
- Add a comment explaining how we parse "0".
- Change trait bound on `Index` impl for `BStr` to match std library approach.
- Link to v6: https://lore.kernel.org/r/20250211-module-params-v3-v6-0-24b297ddc43d@kernel.org

Changes in v6:
- Fix a bug that prevented parsing of negative default values for
  parameters in the `module!` macro.
- Fix a bug that prevented parsing zero in `strip_radix`. Also add a
  test case for this.
- Add `AsRef<BStr>` for `[u8]` and `BStr`.
- Use `impl AsRef<BStr>` as type of prefix in `BStr::strip_prefix`.
- Link to v5: https://lore.kernel.org/r/20250204-module-params-v3-v5-0-bf5ec2041625@kernel.org

Changes in v5:
- Fix a typo in a safety comment in `set_param`.
- Use a match statement in `parse_int::strip_radix`.
- Add an implementation of `Index` for `BStr`.
- Fix a logic inversion bug where parameters would not be parsed.
- Use `kernel::ffi::c_char` in `set_param` rather than the one in `core`.
- Use `kernel::c_str!` rather than `c"..."` literal in module macro.
- Rebase on v6.14-rc1.
- Link to v4: https://lore.kernel.org/r/20250109-module-params-v3-v4-0-c208bcfbe11f@kernel.org

Changes in v4:
- Add module maintainers to Cc list (sorry)
- Add a few missing [`doc_links`]
- Add panic section to `expect_string_field`
- Fix a typo in safety requirement of `module_params::free`
- Change `assert!` to `pr_warn_once!` in `module_params::set_param`
- Remove `module_params::get_param` and install null pointer instead
- Remove use of the unstable feature `sync_unsafe_cell`
- Link to v3: https://lore.kernel.org/r/20241213-module-params-v3-v3-0-485a015ac2cf@kernel.org

Changes in v3:
- use `SyncUnsafeCell` rather than `static mut` and simplify parameter access
- remove `Display` bound from `ModuleParam`
- automatically generate documentation for `PARAM_OPS_.*`
- remove `as *const _ as *mut_` phrasing
- inline parameter name in struct instantiation in  `emit_params`
- move `RacyKernelParam` out of macro template
- use C string literals rather than byte string literals with explicit null
- template out `__{name}_{param_name}` in `emit_param`
- indent template in `emit_params`
- use let-else expression in `emit_params` to get rid of an indentation level
- document `expect_string_field`
- move invication of `impl_int_module_param` to be closer to macro def
- move attributes after docs in `make_param_ops`
- rename `impl_module_param` to impl_int_module_param`
- use `ty` instead of `ident` in `impl_parse_int`
- use `BStr` instead of `&str` for string manipulation
- move string parsing functions to seperate patch and add examples, fix bugs
- degrade comment about future support from doc comment to regular comment
- remove std lib path from `Sized` marker
- update documentation for `trait ModuleParam`
- Link to v2: https://lore.kernel.org/all/20240819133345.3438739-1-nmi@metaspace.dk/

Changes in v2:
- Remove support for params without values (`NOARG_ALLOWED`).
- Improve documentation for `try_from_param_arg`.
- Use prelude import.
- Refactor `try_from_param_arg` to return `Result`.
- Refactor `ParseInt::from_str` to return `Result`.
- Move C callable functions out of `ModuleParam` trait.
- Rename literal string field parser to `expect_string_field`.
- Move parameter parsing from generation to parsing stage.
- Use absolute type paths in macro code.
- Inline `kparam`and `read_func` values.
- Resolve TODO regarding alignment attributes.
- Remove unnecessary unsafe blocks in macro code.
- Improve error message for unrecognized parameter types.
- Do not use `self` receiver when reading parameter value.
- Add parameter documentation to `module!` macro.
- Use empty `enum` for parameter type.
- Use `addr_of_mut` to get address of parameter value variable.
- Enabled building of docs for for `module_param` module.
- Link to v1: https://lore.kernel.org/rust-for-linux/20240705111455.142790-1-nmi@metaspace.dk/

---
Andreas Hindborg (7):
      rust: sync: add `SetOnce`
      rust: str: add radix prefixed integer parsing functions
      rust: introduce module_param module
      rust: module: use a reference in macros::module::module
      rust: module: update the module macro with module parameter support
      rust: samples: add a module parameter to the rust_minimal sample
      modules: add rust modules files to MAINTAINERS

 MAINTAINERS                  |   2 +
 rust/kernel/lib.rs           |   1 +
 rust/kernel/module_param.rs  | 181 ++++++++++++++++++++++++++++++++++++++++
 rust/kernel/str.rs           |   2 +
 rust/kernel/str/parse_int.rs | 148 +++++++++++++++++++++++++++++++++
 rust/kernel/sync.rs          |   2 +
 rust/kernel/sync/set_once.rs | 125 ++++++++++++++++++++++++++++
 rust/macros/helpers.rs       |  25 ++++++
 rust/macros/lib.rs           |  31 +++++++
 rust/macros/module.rs        | 194 +++++++++++++++++++++++++++++++++++++++----
 samples/rust/rust_minimal.rs |  10 +++
 11 files changed, 703 insertions(+), 18 deletions(-)
---
base-commit: 103265a1a936cfe910c9ac0f0ab153f7dac818ba
change-id: 20241211-module-params-v3-ae7e5c8d8b5a

Best regards,
-- 
Andreas Hindborg <a.hindborg@kernel.org>
Re: [PATCH v18 0/7] rust: extend `module!` macro with integer parameter support
Posted by Daniel Gomez 3 months ago
On Wed, 24 Sep 2025 14:39:23 +0200, Andreas Hindborg wrote:
> Extend the `module!` macro with support module parameters. Also add some
> string to integer parsing functions.
> 
> Based on the original module parameter support by Miguel [1],
> later extended and generalized by Adam for more types [2][3].
> Originally tracked at [4].
> 
> [...]

Applied, thanks!

[1/7] rust: sync: add `SetOnce`
      commit: 821fe7bf16c57d690f4f92997f4e51abb93e0347
[2/7] rust: str: add radix prefixed integer parsing functions
      commit: 51d9ee90ea9060be240830eb28f5f117ad00318c
[3/7] rust: introduce module_param module
      commit: 0b08fc292842a13aa496413b48c1efb83573b8c6
[4/7] rust: module: use a reference in macros::module::module
      commit: 3809d7a89fe550bf4065c04adff6dac610daddad
[5/7] rust: module: update the module macro with module parameter support
      commit: 0b24f9740f26ac7ad91ac0f4de27717c14de91bd
[6/7] rust: samples: add a module parameter to the rust_minimal sample
      commit: e119c2fe8c78632188f6cdeae620951a7032855a
[7/7] modules: add rust modules files to MAINTAINERS
      commit: ee3b8134b2bae848e03e56c090ceca4ae76cee06

Best regards,
-- 
Daniel Gomez <da.gomez@kernel.org>
Re: [PATCH v18 0/7] rust: extend `module!` macro with integer parameter support
Posted by Daniel Gomez 3 months, 1 week ago
On 24/09/2025 14.39, Andreas Hindborg wrote:
> Extend the `module!` macro with support module parameters. Also add some
> string to integer parsing functions.
> 
> Based on the original module parameter support by Miguel [1],
> later extended and generalized by Adam for more types [2][3].
> Originally tracked at [4].
> 
> Link: https://github.com/Rust-for-Linux/linux/pull/7 [1]
> Link: https://github.com/Rust-for-Linux/linux/pull/82 [2]
> Link: https://github.com/Rust-for-Linux/linux/pull/87 [3]
> Link: https://github.com/Rust-for-Linux/linux/issues/11 [4]
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>

I tested this series with rust_minimal module. They LGTM,

Tested-by: Daniel Gomez <da.gomez@samsung.com>

The patches did not apply cleanly to v6.18-rc3, at least not when using b4.
However, when applying them to the base commit and then rebasing onto v6.18-rc3,
I didn't see any conflicts.

I've created a temporary branch with this rebase here:

https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git/log/?h=rebase/20250924-module-params-v3-v18-0-bf512c35d910@kernel.org

Can you take a look when you can? I'll merge this shortly after checking with
Uwe, as there are some minor conflicts with his tree.

+ Uwe

These are the conflicts I see when merging the patch series from Michal [1]
(Introduce import_ns support for Rust). I believe these are trivial things that
we will get notified from linux-next merging. But let me know what you think as
you have requested in that thread.

[1] Link: https://lore.kernel.org/all/20251028-pwm_fixes-v1-0-25a532d31998@samsung.com/

...
Applying: rust: macros: Add support for 'imports_ns' to module!
Patch failed at 0008 rust: macros: Add support for 'imports_ns' to module!
error: patch failed: rust/macros/module.rs:98
error: rust/macros/module.rs: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"

git am --show-current-patch=diff
---
 rust/macros/module.rs | 8 ++++++++
 1 file changed, 8 insertions(+)
---
 rust/macros/module.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index 5ee54a00c0b65699596e660b2d4d60e64be2a50c..408cd115487514c8be79724d901c676435696376 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -98,6 +98,7 @@ struct ModuleInfo {
     description: Option<String>,
     alias: Option<Vec<String>>,
     firmware: Option<Vec<String>>,
+    imports_ns: Option<Vec<String>>,
 }

 impl ModuleInfo {
@@ -112,6 +113,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
             "license",
             "alias",
             "firmware",
+            "imports_ns",
         ];
         const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
         let mut seen_keys = Vec::new();
@@ -137,6 +139,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
                 "license" => info.license = expect_string_ascii(it),
                 "alias" => info.alias = Some(expect_string_array(it)),
                 "firmware" => info.firmware = Some(expect_string_array(it)),
+                "imports_ns" => info.imports_ns = Some(expect_string_array(it)),
                 _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
             }

@@ -195,6 +198,11 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
             modinfo.emit("firmware", &fw);
         }
     }
+    if let Some(imports) = info.imports_ns {
+        for ns in imports {
+            modinfo.emit("import_ns", &ns);
+        }
+    }

     // Built-in modules also export the `file` modinfo string.
     let file =
Re: [PATCH v18 0/7] rust: extend `module!` macro with integer parameter support
Posted by Uwe Kleine-König 3 months, 1 week ago
Hello Daniel,

[Adding Stephen and linux-next to Cc]

On Sat, Nov 01, 2025 at 10:39:08PM +0100, Daniel Gomez wrote:
> On 24/09/2025 14.39, Andreas Hindborg wrote:
> > Extend the `module!` macro with support module parameters. Also add some
> > string to integer parsing functions.
> > 
> > Based on the original module parameter support by Miguel [1],
> > later extended and generalized by Adam for more types [2][3].
> > Originally tracked at [4].
> > 
> > Link: https://github.com/Rust-for-Linux/linux/pull/7 [1]
> > Link: https://github.com/Rust-for-Linux/linux/pull/82 [2]
> > Link: https://github.com/Rust-for-Linux/linux/pull/87 [3]
> > Link: https://github.com/Rust-for-Linux/linux/issues/11 [4]
> > Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
> 
> I tested this series with rust_minimal module. They LGTM,
> 
> Tested-by: Daniel Gomez <da.gomez@samsung.com>
> 
> The patches did not apply cleanly to v6.18-rc3, at least not when using b4.
> However, when applying them to the base commit and then rebasing onto v6.18-rc3,
> I didn't see any conflicts.

I don't know how you use b4, but

	git checkout v6.18-rc3
	b4 am -3 49af6d76-bcb7-4343-8903-390040e2c49b@kernel.org
	git am -3 ./v18_20250924_a_hindborg_rust_extend_module_macro_with_integer_parameter_support.mbx

works fine on my end. Using `-3` should have the same effect as applying
the series on top of the original base and rebase it.

	git fetch https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git rebase/20250924-module-params-v3-v18-0-bf512c35d910@kernel.org
	git range-diff FETCH_HEAD...HEAD

confirms that.
 
> I've created a temporary branch with this rebase here:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git/log/?h=rebase/20250924-module-params-v3-v18-0-bf512c35d910@kernel.org
> 
> Can you take a look when you can? I'll merge this shortly after checking with
> Uwe, as there are some minor conflicts with his tree.
> 
> + Uwe
> 
> These are the conflicts I see when merging the patch series from Michal [1]
> (Introduce import_ns support for Rust). I believe these are trivial things that
> we will get notified from linux-next merging. But let me know what you think as
> you have requested in that thread.
> 
> [1] Link: https://lore.kernel.org/all/20251028-pwm_fixes-v1-0-25a532d31998@samsung.com/

Yeah, I expect that Stephen will highlight the conflicts, but I prefer
to not be surprised by that and consider linux-next more a fallback
security net that I don't want to use. I like it to be the other way
round and tell Stephen about conflicts to expect :-)

> ...
> Applying: rust: macros: Add support for 'imports_ns' to module!
> Patch failed at 0008 rust: macros: Add support for 'imports_ns' to module!
> error: patch failed: rust/macros/module.rs:98
> error: rust/macros/module.rs: patch does not apply
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
> hint: When you have resolved this problem, run "git am --continue".
> hint: If you prefer to skip this patch, run "git am --skip" instead.
> hint: To restore the original branch and stop patching, run "git am --abort".
> hint: Disable this message with "git config set advice.mergeConflict false"
> 
> git am --show-current-patch=diff

That command shows the patch to apply, but not the conflict, let alone
your resolution.

> ---
>  rust/macros/module.rs | 8 ++++++++
>  1 file changed, 8 insertions(+)
> ---
>  rust/macros/module.rs | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
> index 5ee54a00c0b65699596e660b2d4d60e64be2a50c..408cd115487514c8be79724d901c676435696376 100644
> --- a/rust/macros/module.rs
> +++ b/rust/macros/module.rs
> @@ -98,6 +98,7 @@ struct ModuleInfo {
>      description: Option<String>,
>      alias: Option<Vec<String>>,
>      firmware: Option<Vec<String>>,
> +    imports_ns: Option<Vec<String>>,
>  }

So here the addition of `params` is missing.

> [...]

When I merge your branch mentioned above with my pwm/for-next and
resolve the merge conflicts, the resolution looks as follows. The only
non-trivial thing is that

	if let Some(imports) = info.imports_ns {

now needs a & for `info`.

Best regards
Uwe

diff --cc rust/macros/module.rs
index d62e9c1e2a89,408cd1154875..000000000000
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@@ -205,50 -98,7 +205,51 @@@ struct ModuleInfo 
      description: Option<String>,
      alias: Option<Vec<String>>,
      firmware: Option<Vec<String>>,
+     imports_ns: Option<Vec<String>>,
 +    params: Option<Vec<Parameter>>,
 +}
 +
 +#[derive(Debug)]
 +struct Parameter {
 +    name: String,
 +    ptype: String,
 +    default: String,
 +    description: String,
 +}
 +
 +fn expect_params(it: &mut token_stream::IntoIter) -> Vec<Parameter> {
 +    let params = expect_group(it);
 +    assert_eq!(params.delimiter(), Delimiter::Brace);
 +    let mut it = params.stream().into_iter();
 +    let mut parsed = Vec::new();
 +
 +    loop {
 +        let param_name = match it.next() {
 +            Some(TokenTree::Ident(ident)) => ident.to_string(),
 +            Some(_) => panic!("Expected Ident or end"),
 +            None => break,
 +        };
 +
 +        assert_eq!(expect_punct(&mut it), ':');
 +        let param_type = expect_ident(&mut it);
 +        let group = expect_group(&mut it);
 +        assert_eq!(group.delimiter(), Delimiter::Brace);
 +        assert_eq!(expect_punct(&mut it), ',');
 +
 +        let mut param_it = group.stream().into_iter();
 +        let param_default = expect_param_default(&mut param_it);
 +        let param_description = expect_string_field(&mut param_it, "description");
 +        expect_end(&mut param_it);
 +
 +        parsed.push(Parameter {
 +            name: param_name,
 +            ptype: param_type,
 +            default: param_default,
 +            description: param_description,
 +        })
 +    }
 +
 +    parsed
  }
  
  impl ModuleInfo {
@@@ -263,7 -113,7 +264,8 @@@
              "license",
              "alias",
              "firmware",
+             "imports_ns",
 +            "params",
          ];
          const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
          let mut seen_keys = Vec::new();
@@@ -289,7 -139,7 +291,8 @@@
                  "license" => info.license = expect_string_ascii(it),
                  "alias" => info.alias = Some(expect_string_array(it)),
                  "firmware" => info.firmware = Some(expect_string_array(it)),
+                 "imports_ns" => info.imports_ns = Some(expect_string_array(it)),
 +                "params" => info.params = Some(expect_params(it)),
                  _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
              }
  
@@@ -329,25 -179,30 +332,30 @@@ pub(crate) fn module(ts: TokenStream) -
      // Rust does not allow hyphens in identifiers, use underscore instead.
      let ident = info.name.replace('-', "_");
      let mut modinfo = ModInfoBuilder::new(ident.as_ref());
 -    if let Some(authors) = info.authors {
 +    if let Some(authors) = &info.authors {
          for author in authors {
 -            modinfo.emit("author", &author);
 +            modinfo.emit("author", author);
          }
      }
 -    if let Some(description) = info.description {
 -        modinfo.emit("description", &description);
 +    if let Some(description) = &info.description {
 +        modinfo.emit("description", description);
      }
      modinfo.emit("license", &info.license);
 -    if let Some(aliases) = info.alias {
 +    if let Some(aliases) = &info.alias {
          for alias in aliases {
 -            modinfo.emit("alias", &alias);
 +            modinfo.emit("alias", alias);
          }
      }
 -    if let Some(firmware) = info.firmware {
 +    if let Some(firmware) = &info.firmware {
          for fw in firmware {
 -            modinfo.emit("firmware", &fw);
 +            modinfo.emit("firmware", fw);
          }
      }
 -    if let Some(imports) = info.imports_ns {
++    if let Some(imports) = &info.imports_ns {
+         for ns in imports {
+             modinfo.emit("import_ns", &ns);
+         }
+     }
  
      // Built-in modules also export the `file` modinfo string.
      let file =
Re: [PATCH v18 0/7] rust: extend `module!` macro with integer parameter support
Posted by Daniel Gomez 3 months ago
On 02/11/2025 10.56, Uwe Kleine-König wrote:
> Hello Daniel,
> 
> [Adding Stephen and linux-next to Cc]
> 
> On Sat, Nov 01, 2025 at 10:39:08PM +0100, Daniel Gomez wrote:
>> On 24/09/2025 14.39, Andreas Hindborg wrote:
>>> Extend the `module!` macro with support module parameters. Also add some
>>> string to integer parsing functions.
>>>
>>> Based on the original module parameter support by Miguel [1],
>>> later extended and generalized by Adam for more types [2][3].
>>> Originally tracked at [4].
>>>
>>> Link: https://github.com/Rust-for-Linux/linux/pull/7 [1]
>>> Link: https://github.com/Rust-for-Linux/linux/pull/82 [2]
>>> Link: https://github.com/Rust-for-Linux/linux/pull/87 [3]
>>> Link: https://github.com/Rust-for-Linux/linux/issues/11 [4]
>>> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
>>
>> I tested this series with rust_minimal module. They LGTM,
>>
>> Tested-by: Daniel Gomez <da.gomez@samsung.com>
>>
>> The patches did not apply cleanly to v6.18-rc3, at least not when using b4.
>> However, when applying them to the base commit and then rebasing onto v6.18-rc3,
>> I didn't see any conflicts.
> 
> I don't know how you use b4, but
> 
> 	git checkout v6.18-rc3
> 	b4 am -3 49af6d76-bcb7-4343-8903-390040e2c49b@kernel.org
> 	git am -3 ./v18_20250924_a_hindborg_rust_extend_module_macro_with_integer_parameter_support.mbx
> 
> works fine on my end. Using `-3` should have the same effect as applying
> the series on top of the original base and rebase it.

Right, that's what I did but manually. I didn't know about that argument :).

> 
> 	git fetch https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git rebase/20250924-module-params-v3-v18-0-bf512c35d910@kernel.org
> 	git range-diff FETCH_HEAD...HEAD
> 
> confirms that.
>  
>> I've created a temporary branch with this rebase here:
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git/log/?h=rebase/20250924-module-params-v3-v18-0-bf512c35d910@kernel.org
>>
>> Can you take a look when you can? I'll merge this shortly after checking with
>> Uwe, as there are some minor conflicts with his tree.
>>
>> + Uwe
>>
>> These are the conflicts I see when merging the patch series from Michal [1]
>> (Introduce import_ns support for Rust). I believe these are trivial things that
>> we will get notified from linux-next merging. But let me know what you think as
>> you have requested in that thread.
>>
>> [1] Link: https://lore.kernel.org/all/20251028-pwm_fixes-v1-0-25a532d31998@samsung.com/
> 
> Yeah, I expect that Stephen will highlight the conflicts, but I prefer
> to not be surprised by that and consider linux-next more a fallback
> security net that I don't want to use. I like it to be the other way
> round and tell Stephen about conflicts to expect :-)

Please Stephen, check the proposed changes below. I plan to merge this series in
modules' tree and it will conflict with Uwe's tree on rust/macros/module.rs file.

> 
>> ...
>> Applying: rust: macros: Add support for 'imports_ns' to module!
>> Patch failed at 0008 rust: macros: Add support for 'imports_ns' to module!
>> error: patch failed: rust/macros/module.rs:98
>> error: rust/macros/module.rs: patch does not apply
>> hint: Use 'git am --show-current-patch=diff' to see the failed patch
>> hint: When you have resolved this problem, run "git am --continue".
>> hint: If you prefer to skip this patch, run "git am --skip" instead.
>> hint: To restore the original branch and stop patching, run "git am --abort".
>> hint: Disable this message with "git config set advice.mergeConflict false"
>>
>> git am --show-current-patch=diff
> 
> That command shows the patch to apply, but not the conflict, let alone
> your resolution.
> 
>> ---
>>  rust/macros/module.rs | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>> ---
>>  rust/macros/module.rs | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/rust/macros/module.rs b/rust/macros/module.rs
>> index 5ee54a00c0b65699596e660b2d4d60e64be2a50c..408cd115487514c8be79724d901c676435696376 100644
>> --- a/rust/macros/module.rs
>> +++ b/rust/macros/module.rs
>> @@ -98,6 +98,7 @@ struct ModuleInfo {
>>      description: Option<String>,
>>      alias: Option<Vec<String>>,
>>      firmware: Option<Vec<String>>,
>> +    imports_ns: Option<Vec<String>>,
>>  }
> 
> So here the addition of `params` is missing.
> 
>> [...]
> 
> When I merge your branch mentioned above with my pwm/for-next and
> resolve the merge conflicts, the resolution looks as follows. The only
> non-trivial thing is that
> 
> 	if let Some(imports) = info.imports_ns {
> 
> now needs a & for `info`.

Correct.

In case it's necessary, I've merged your changes into the modules's -next
branch and attach the diff for you and Stephen. Not sure which order trees are
taken/merged, though.

> 
> Best regards
> Uwe
> 
> diff --cc rust/macros/module.rs
> index d62e9c1e2a89,408cd1154875..000000000000
> --- a/rust/macros/module.rs
> +++ b/rust/macros/module.rs
> @@@ -205,50 -98,7 +205,51 @@@ struct ModuleInfo 
>       description: Option<String>,
>       alias: Option<Vec<String>>,
>       firmware: Option<Vec<String>>,
> +     imports_ns: Option<Vec<String>>,
>  +    params: Option<Vec<Parameter>>,
>  +}
>  +
>  +#[derive(Debug)]
>  +struct Parameter {
>  +    name: String,
>  +    ptype: String,
>  +    default: String,
>  +    description: String,
>  +}
>  +
>  +fn expect_params(it: &mut token_stream::IntoIter) -> Vec<Parameter> {
>  +    let params = expect_group(it);
>  +    assert_eq!(params.delimiter(), Delimiter::Brace);
>  +    let mut it = params.stream().into_iter();
>  +    let mut parsed = Vec::new();
>  +
>  +    loop {
>  +        let param_name = match it.next() {
>  +            Some(TokenTree::Ident(ident)) => ident.to_string(),
>  +            Some(_) => panic!("Expected Ident or end"),
>  +            None => break,
>  +        };
>  +
>  +        assert_eq!(expect_punct(&mut it), ':');
>  +        let param_type = expect_ident(&mut it);
>  +        let group = expect_group(&mut it);
>  +        assert_eq!(group.delimiter(), Delimiter::Brace);
>  +        assert_eq!(expect_punct(&mut it), ',');
>  +
>  +        let mut param_it = group.stream().into_iter();
>  +        let param_default = expect_param_default(&mut param_it);
>  +        let param_description = expect_string_field(&mut param_it, "description");
>  +        expect_end(&mut param_it);
>  +
>  +        parsed.push(Parameter {
>  +            name: param_name,
>  +            ptype: param_type,
>  +            default: param_default,
>  +            description: param_description,
>  +        })
>  +    }
>  +
>  +    parsed
>   }
>   
>   impl ModuleInfo {
> @@@ -263,7 -113,7 +264,8 @@@
>               "license",
>               "alias",
>               "firmware",
> +             "imports_ns",
>  +            "params",
>           ];
>           const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
>           let mut seen_keys = Vec::new();
> @@@ -289,7 -139,7 +291,8 @@@
>                   "license" => info.license = expect_string_ascii(it),
>                   "alias" => info.alias = Some(expect_string_array(it)),
>                   "firmware" => info.firmware = Some(expect_string_array(it)),
> +                 "imports_ns" => info.imports_ns = Some(expect_string_array(it)),
>  +                "params" => info.params = Some(expect_params(it)),
>                   _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
>               }
>   
> @@@ -329,25 -179,30 +332,30 @@@ pub(crate) fn module(ts: TokenStream) -
>       // Rust does not allow hyphens in identifiers, use underscore instead.
>       let ident = info.name.replace('-', "_");
>       let mut modinfo = ModInfoBuilder::new(ident.as_ref());
>  -    if let Some(authors) = info.authors {
>  +    if let Some(authors) = &info.authors {
>           for author in authors {
>  -            modinfo.emit("author", &author);
>  +            modinfo.emit("author", author);
>           }
>       }
>  -    if let Some(description) = info.description {
>  -        modinfo.emit("description", &description);
>  +    if let Some(description) = &info.description {
>  +        modinfo.emit("description", description);
>       }
>       modinfo.emit("license", &info.license);
>  -    if let Some(aliases) = info.alias {
>  +    if let Some(aliases) = &info.alias {
>           for alias in aliases {
>  -            modinfo.emit("alias", &alias);
>  +            modinfo.emit("alias", alias);
>           }
>       }
>  -    if let Some(firmware) = info.firmware {
>  +    if let Some(firmware) = &info.firmware {
>           for fw in firmware {
>  -            modinfo.emit("firmware", &fw);
>  +            modinfo.emit("firmware", fw);
>           }
>       }
>  -    if let Some(imports) = info.imports_ns {
> ++    if let Some(imports) = &info.imports_ns {
> +         for ns in imports {
> +             modinfo.emit("import_ns", &ns);
> +         }
> +     }
>   
>       // Built-in modules also export the `file` modinfo string.
>       let file =

The resolution looks good to me.

As I applied Michal's patch on top of Andreas changes, it looks like this on
my side:

diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index d62e9c1e2a89..5bf0a487de50 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -206,6 +206,7 @@ struct ModuleInfo {
     alias: Option<Vec<String>>,
     firmware: Option<Vec<String>>,
     params: Option<Vec<Parameter>>,
+    imports_ns: Option<Vec<String>>,
 }

 #[derive(Debug)]
@@ -264,6 +265,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
             "alias",
             "firmware",
             "params",
+            "imports_ns",
         ];
         const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
         let mut seen_keys = Vec::new();
@@ -290,6 +292,7 @@ fn parse(it: &mut token_stream::IntoIter) -> Self {
                 "alias" => info.alias = Some(expect_string_array(it)),
                 "firmware" => info.firmware = Some(expect_string_array(it)),
                 "params" => info.params = Some(expect_params(it)),
+                "imports_ns" => info.imports_ns = Some(expect_string_array(it)),
                 _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
             }

@@ -348,6 +351,11 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
             modinfo.emit("firmware", fw);
         }
     }
+    if let Some(imports) = &info.imports_ns {
+        for ns in imports {
+            modinfo.emit("import_ns", &ns);
+        }
+    }

     // Built-in modules also export the `file` modinfo string.
     let file =