* [PATCH v7 00/25] Rust support @ 2022-05-23 2:01 Miguel Ojeda 2022-05-23 2:01 ` [PATCH v7 24/25] [RFC] drivers: gpio: PrimeCell PL061 in Rust Miguel Ojeda 2022-07-16 12:42 ` [PATCH v7 00/25] Rust support Conor Dooley 0 siblings, 2 replies; 6+ messages in thread From: Miguel Ojeda @ 2022-05-23 2:01 UTC (permalink / raw) To: Linus Torvalds, Greg Kroah-Hartman Cc: rust-for-linux, linux-kernel, Jarkko Sakkinen, Miguel Ojeda, kunit-dev, linux-arm-kernel, linux-doc, linux-gpio, linux-kbuild, linux-kselftest, linux-perf-users, linuxppc-dev, linux-riscv, linux-um, live-patching Rust support This is the patch series (v7) to add support for Rust as a second language to the Linux kernel. If you are interested in following this effort, please join us in the mailing list at: rust-for-linux@vger.kernel.org and take a look at the project itself at: https://github.com/Rust-for-Linux As usual, special thanks go to ISRG (Internet Security Research Group) and Google for their financial support on this endeavor. Cheers, Miguel -- # Rust support This cover letter explains the major changes and updates done since the previous ones. For those, please see: RFC: https://lore.kernel.org/lkml/20210414184604.23473-1-ojeda@kernel.org/ v1: https://lore.kernel.org/lkml/20210704202756.29107-1-ojeda@kernel.org/ v2: https://lore.kernel.org/lkml/20211206140313.5653-1-ojeda@kernel.org/ v3: https://lore.kernel.org/lkml/20220117053349.6804-1-ojeda@kernel.org/ v4: https://lore.kernel.org/lkml/20220212130410.6901-1-ojeda@kernel.org/ v5: https://lore.kernel.org/lkml/20220317181032.15436-1-ojeda@kernel.org/ v6: https://lore.kernel.org/lkml/20220507052451.12890-1-ojeda@kernel.org/ This is a small round to address the comments made in v6 plus a few related changes: - Added `%pA` to `Documentation/core-api/printk-formats.rst`. - Added `checkpatch.pl` patch to search for `%pA` in C code. - Added `checkpatch.pl` patch to enable language-independent checks. - Added UML (x86_64) support, for KUnit (thanks David Gow!). - Added inline licensing information ("Apache-2.0 OR MIT") in the commit message of the `alloc` patch, as well as in `rust/alloc/README.md` in the following patch. - Added SPDX license identifiers to `Documentation/rust/`. - Reformatted `Documentation/rust/arch-support.rst` list table into simple table. - Removed logo from documentation patch; used Linux GIF one for the Rust generated docs in its place (to be replaced with the SVG one once available). - Used `"GPL"` instead of `"GPL v2"` for the `license` field of the `module!` macro. - Moved `module_misc_device!` macro in `samples/rust/rust_random.rs` to the top of the file in `samples/rust/` for consistency. - Sorted `#include` lists in `rust/kernel/bindings_helper.h` and `rust/helpers.c`. - Fixed some English typos. - Made the patches more `checkpatch.pl`-clean overall. - Picked up Reviewed-by and Acked-by tags. ## Patch series status The Rust support is still to be considered experimental. However, support is good enough that kernel developers can start working on the Rust abstractions for subsystems and write drivers and other modules. The current series has just arrived in `linux-next`, as usual. Similarly, the preview docs for this series can be seen at: https://rust-for-linux.github.io/docs/kernel/ As usual, please see the following link for the live list of unstable Rust features we are using: https://github.com/Rust-for-Linux/linux/issues/2 ## Conferences, meetings and liaisons We would like to remind everyone about the Rust MC (microconference) of LPC 2022 (Linux Plumbers Conference): https://lpc.events/event/16/contributions/1159/ The Rust MC intends to cover talks and discussions on both Rust for Linux as well as other non-kernel Rust topics. The Call for Proposals is open! ## Acknowledgements The signatures in the main commits correspond to the people that wrote code that has ended up in them at the present time. For details on contributions to code and discussions, please see our repository: https://github.com/Rust-for-Linux/linux However, we would like to give credit to everyone that has contributed in one way or another to the Rust for Linux project. Since the previous cover letter: - Kees Cook for his reviews of some of the v6 patches. - David Gow and Brendan Higgins for their reviews of the KUnit prerequisite patch and their feedback. - Jonathan Corbet and Akira Yokosawa for their review of the documentation patch and feedback on documentation rules. - Gary Guo for working on improvements to the Rust compiler that could make our `static_assert!` macro applicable in more cases. - bjorn3 for working on making `rustc_parse_format` compile on a stable Rust compiler so that it may be used by lightweight formatting systems (for instance, by the kernel). - As usual, bjorn3 and Gary Guo for all the input on Rust compiler details, reviews and suggestions. - Esteban Blanc, Arthur Cohen and Martin Schmidt for rebasing their SPI abstraction work. - Maciej Falkowski for continuing his work on the Samsung Exynos TRNG driver and the required abstractions around it, such as adding `delay`, `ktime` and `iopoll` abstractions, new methods to `platform::Device` and run-time power management abstractions. - Yuheng Su for working on cleaning up the `Module::init` interface. - Peng Hao for working on wrapping `mm_struct`. - Sergio González Collado for continuing his work on the GitHub CI problem matchers. - Wei Liu for taking the time to answer questions from newcomers in Zulip. - Philip Li, Yujie Liu et al. for continuing their work on adding Rust support to the Intel 0DAY/LKP kernel test robot. - Philip Herron and Arthur Cohen (and his supporters Open Source Security and Embecosm) et al. for their ongoing work on GCC Rust. - Antoni Boucher (and his supporters) et al. for their ongoing work on `rustc_codegen_gcc`. - Mats Larsen, Marc Poulhiès et al. for their ongoing work on improving Rust support in Compiler Explorer. - Many folks that have reported issues, tested the project, helped spread the word, joined discussions and contributed in other ways! Please see also the acknowledgements on the previous cover letters. Boqun Feng (1): kallsyms: avoid hardcoding the buffer size Gary Guo (2): rust: add `build_error` crate vsprintf: add new `%pA` format specifier Miguel Ojeda (18): kallsyms: support "big" kernel symbols kallsyms: increase maximum kernel symbol length to 512 kunit: take `kunit_assert` as `const` rust: add C helpers rust: add `compiler_builtins` crate rust: import upstream `alloc` crate rust: adapt `alloc` crate to the kernel rust: add `macros` crate rust: export generated symbols scripts: checkpatch: diagnose uses of `%pA` in the C side scripts: checkpatch: enable language-independent checks for Rust scripts: add `rustdoc_test_{builder,gen}.py` scripts scripts: add `generate_rust_analyzer.py` scripts scripts: decode_stacktrace: demangle Rust symbols docs: add Rust documentation Kbuild: add Rust support samples: add Rust examples MAINTAINERS: Rust Wedson Almeida Filho (4): rust: add `kernel` crate's `sync` module rust: add `kernel` crate [RFC] drivers: gpio: PrimeCell PL061 in Rust [RFC] drivers: android: Binder IPC in Rust .gitignore | 5 + .rustfmt.toml | 12 + Documentation/core-api/printk-formats.rst | 10 + Documentation/doc-guide/kernel-doc.rst | 3 + Documentation/index.rst | 1 + Documentation/kbuild/kbuild.rst | 17 + Documentation/kbuild/makefiles.rst | 50 +- Documentation/process/changes.rst | 41 + Documentation/rust/arch-support.rst | 25 + Documentation/rust/coding-guidelines.rst | 216 ++ Documentation/rust/general-information.rst | 79 + Documentation/rust/index.rst | 22 + Documentation/rust/quick-start.rst | 232 ++ MAINTAINERS | 15 + Makefile | 175 +- arch/Kconfig | 6 + arch/arm/Kconfig | 1 + arch/arm64/Kconfig | 1 + arch/powerpc/Kconfig | 1 + arch/riscv/Kconfig | 1 + arch/riscv/Makefile | 5 + arch/um/Kconfig | 1 + arch/x86/Kconfig | 1 + arch/x86/Makefile | 14 + drivers/android/Kconfig | 6 + drivers/android/Makefile | 2 + drivers/android/allocation.rs | 266 ++ drivers/android/context.rs | 80 + drivers/android/defs.rs | 99 + drivers/android/node.rs | 476 +++ drivers/android/process.rs | 960 +++++ drivers/android/range_alloc.rs | 189 + drivers/android/rust_binder.rs | 111 + drivers/android/thread.rs | 870 +++++ drivers/android/transaction.rs | 326 ++ drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio_pl061_rust.rs | 370 ++ include/kunit/test.h | 2 +- include/linux/kallsyms.h | 2 +- include/linux/spinlock.h | 25 +- include/uapi/linux/android/binder.h | 28 +- init/Kconfig | 45 +- kernel/kallsyms.c | 26 +- kernel/livepatch/core.c | 4 +- lib/Kconfig.debug | 155 + lib/kunit/test.c | 4 +- lib/vsprintf.c | 13 + rust/.gitignore | 10 + rust/Makefile | 398 +++ rust/alloc/README.md | 33 + rust/alloc/alloc.rs | 438 +++ rust/alloc/borrow.rs | 498 +++ rust/alloc/boxed.rs | 2007 +++++++++++ rust/alloc/collections/mod.rs | 156 + rust/alloc/fmt.rs | 601 ++++ rust/alloc/lib.rs | 226 ++ rust/alloc/macros.rs | 127 + rust/alloc/raw_vec.rs | 567 +++ rust/alloc/slice.rs | 1282 +++++++ rust/alloc/str.rs | 632 ++++ rust/alloc/string.rs | 2869 +++++++++++++++ rust/alloc/vec/drain.rs | 186 + rust/alloc/vec/drain_filter.rs | 145 + rust/alloc/vec/into_iter.rs | 356 ++ rust/alloc/vec/is_zero.rs | 106 + rust/alloc/vec/mod.rs | 3362 ++++++++++++++++++ rust/alloc/vec/partial_eq.rs | 49 + rust/alloc/vec/set_len_on_drop.rs | 30 + rust/alloc/vec/spec_extend.rs | 174 + rust/bindgen_parameters | 17 + rust/build_error.rs | 29 + rust/compiler_builtins.rs | 57 + rust/exports.c | 20 + rust/helpers.c | 644 ++++ rust/kernel/allocator.rs | 65 + rust/kernel/amba.rs | 257 ++ rust/kernel/bindings.rs | 47 + rust/kernel/bindings_helper.h | 46 + rust/kernel/build_assert.rs | 82 + rust/kernel/c_types.rs | 119 + rust/kernel/chrdev.rs | 207 ++ rust/kernel/clk.rs | 79 + rust/kernel/cred.rs | 46 + rust/kernel/device.rs | 546 +++ rust/kernel/driver.rs | 442 +++ rust/kernel/error.rs | 565 +++ rust/kernel/file.rs | 860 +++++ rust/kernel/gpio.rs | 478 +++ rust/kernel/hwrng.rs | 242 ++ rust/kernel/io_buffer.rs | 153 + rust/kernel/io_mem.rs | 275 ++ rust/kernel/iov_iter.rs | 81 + rust/kernel/irq.rs | 411 +++ rust/kernel/kasync.rs | 6 + rust/kernel/kasync/net.rs | 322 ++ rust/kernel/kunit.rs | 91 + rust/kernel/lib.rs | 261 ++ rust/kernel/linked_list.rs | 247 ++ rust/kernel/miscdev.rs | 291 ++ rust/kernel/mm.rs | 149 + rust/kernel/module_param.rs | 498 +++ rust/kernel/net.rs | 392 ++ rust/kernel/net/filter.rs | 447 +++ rust/kernel/of.rs | 63 + rust/kernel/pages.rs | 144 + rust/kernel/platform.rs | 223 ++ rust/kernel/power.rs | 118 + rust/kernel/prelude.rs | 36 + rust/kernel/print.rs | 405 +++ rust/kernel/random.rs | 42 + rust/kernel/raw_list.rs | 361 ++ rust/kernel/rbtree.rs | 563 +++ rust/kernel/revocable.rs | 161 + rust/kernel/security.rs | 38 + rust/kernel/static_assert.rs | 38 + rust/kernel/std_vendor.rs | 160 + rust/kernel/str.rs | 597 ++++ rust/kernel/sync.rs | 161 + rust/kernel/sync/arc.rs | 503 +++ rust/kernel/sync/condvar.rs | 138 + rust/kernel/sync/guard.rs | 169 + rust/kernel/sync/locked_by.rs | 111 + rust/kernel/sync/mutex.rs | 153 + rust/kernel/sync/nowait.rs | 188 + rust/kernel/sync/revocable.rs | 250 ++ rust/kernel/sync/rwsem.rs | 197 + rust/kernel/sync/seqlock.rs | 202 ++ rust/kernel/sync/smutex.rs | 295 ++ rust/kernel/sync/spinlock.rs | 360 ++ rust/kernel/sysctl.rs | 199 ++ rust/kernel/task.rs | 175 + rust/kernel/types.rs | 679 ++++ rust/kernel/user_ptr.rs | 175 + rust/macros/helpers.rs | 79 + rust/macros/lib.rs | 94 + rust/macros/module.rs | 631 ++++ samples/Kconfig | 2 + samples/Makefile | 1 + samples/rust/Kconfig | 140 + samples/rust/Makefile | 16 + samples/rust/hostprogs/.gitignore | 3 + samples/rust/hostprogs/Makefile | 5 + samples/rust/hostprogs/a.rs | 7 + samples/rust/hostprogs/b.rs | 5 + samples/rust/hostprogs/single.rs | 12 + samples/rust/rust_chrdev.rs | 50 + samples/rust/rust_minimal.rs | 35 + samples/rust/rust_miscdev.rs | 143 + samples/rust/rust_module_parameters.rs | 69 + samples/rust/rust_netfilter.rs | 54 + samples/rust/rust_platform.rs | 22 + samples/rust/rust_print.rs | 54 + samples/rust/rust_random.rs | 60 + samples/rust/rust_semaphore.rs | 171 + samples/rust/rust_semaphore_c.c | 212 ++ samples/rust/rust_stack_probing.rs | 36 + samples/rust/rust_sync.rs | 93 + scripts/.gitignore | 1 + scripts/Kconfig.include | 6 +- scripts/Makefile | 3 + scripts/Makefile.build | 60 + scripts/Makefile.debug | 10 + scripts/Makefile.host | 34 +- scripts/Makefile.lib | 12 + scripts/Makefile.modfinal | 8 +- scripts/cc-version.sh | 12 +- scripts/checkpatch.pl | 8 +- scripts/decode_stacktrace.sh | 14 + scripts/generate_rust_analyzer.py | 134 + scripts/generate_rust_target.rs | 227 ++ scripts/is_rust_module.sh | 13 + scripts/kallsyms.c | 47 +- scripts/kconfig/confdata.c | 75 + scripts/min-tool-version.sh | 6 + scripts/rust-is-available-bindgen-libclang.h | 2 + scripts/rust-is-available.sh | 158 + scripts/rustdoc_test_builder.py | 59 + scripts/rustdoc_test_gen.py | 164 + tools/include/linux/kallsyms.h | 2 +- tools/lib/perf/include/perf/event.h | 2 +- tools/lib/symbol/kallsyms.h | 2 +- 182 files changed, 37614 insertions(+), 69 deletions(-) create mode 100644 .rustfmt.toml create mode 100644 Documentation/rust/arch-support.rst create mode 100644 Documentation/rust/coding-guidelines.rst create mode 100644 Documentation/rust/general-information.rst create mode 100644 Documentation/rust/index.rst create mode 100644 Documentation/rust/quick-start.rst create mode 100644 drivers/android/allocation.rs create mode 100644 drivers/android/context.rs create mode 100644 drivers/android/defs.rs create mode 100644 drivers/android/node.rs create mode 100644 drivers/android/process.rs create mode 100644 drivers/android/range_alloc.rs create mode 100644 drivers/android/rust_binder.rs create mode 100644 drivers/android/thread.rs create mode 100644 drivers/android/transaction.rs create mode 100644 drivers/gpio/gpio_pl061_rust.rs create mode 100644 rust/.gitignore create mode 100644 rust/Makefile create mode 100644 rust/alloc/README.md create mode 100644 rust/alloc/alloc.rs create mode 100644 rust/alloc/borrow.rs create mode 100644 rust/alloc/boxed.rs create mode 100644 rust/alloc/collections/mod.rs create mode 100644 rust/alloc/fmt.rs create mode 100644 rust/alloc/lib.rs create mode 100644 rust/alloc/macros.rs create mode 100644 rust/alloc/raw_vec.rs create mode 100644 rust/alloc/slice.rs create mode 100644 rust/alloc/str.rs create mode 100644 rust/alloc/string.rs create mode 100644 rust/alloc/vec/drain.rs create mode 100644 rust/alloc/vec/drain_filter.rs create mode 100644 rust/alloc/vec/into_iter.rs create mode 100644 rust/alloc/vec/is_zero.rs create mode 100644 rust/alloc/vec/mod.rs create mode 100644 rust/alloc/vec/partial_eq.rs create mode 100644 rust/alloc/vec/set_len_on_drop.rs create mode 100644 rust/alloc/vec/spec_extend.rs create mode 100644 rust/bindgen_parameters create mode 100644 rust/build_error.rs create mode 100644 rust/compiler_builtins.rs create mode 100644 rust/exports.c create mode 100644 rust/helpers.c create mode 100644 rust/kernel/allocator.rs create mode 100644 rust/kernel/amba.rs create mode 100644 rust/kernel/bindings.rs create mode 100644 rust/kernel/bindings_helper.h create mode 100644 rust/kernel/build_assert.rs create mode 100644 rust/kernel/c_types.rs create mode 100644 rust/kernel/chrdev.rs create mode 100644 rust/kernel/clk.rs create mode 100644 rust/kernel/cred.rs create mode 100644 rust/kernel/device.rs create mode 100644 rust/kernel/driver.rs create mode 100644 rust/kernel/error.rs create mode 100644 rust/kernel/file.rs create mode 100644 rust/kernel/gpio.rs create mode 100644 rust/kernel/hwrng.rs create mode 100644 rust/kernel/io_buffer.rs create mode 100644 rust/kernel/io_mem.rs create mode 100644 rust/kernel/iov_iter.rs create mode 100644 rust/kernel/irq.rs create mode 100644 rust/kernel/kasync.rs create mode 100644 rust/kernel/kasync/net.rs create mode 100644 rust/kernel/kunit.rs create mode 100644 rust/kernel/lib.rs create mode 100644 rust/kernel/linked_list.rs create mode 100644 rust/kernel/miscdev.rs create mode 100644 rust/kernel/mm.rs create mode 100644 rust/kernel/module_param.rs create mode 100644 rust/kernel/net.rs create mode 100644 rust/kernel/net/filter.rs create mode 100644 rust/kernel/of.rs create mode 100644 rust/kernel/pages.rs create mode 100644 rust/kernel/platform.rs create mode 100644 rust/kernel/power.rs create mode 100644 rust/kernel/prelude.rs create mode 100644 rust/kernel/print.rs create mode 100644 rust/kernel/random.rs create mode 100644 rust/kernel/raw_list.rs create mode 100644 rust/kernel/rbtree.rs create mode 100644 rust/kernel/revocable.rs create mode 100644 rust/kernel/security.rs create mode 100644 rust/kernel/static_assert.rs create mode 100644 rust/kernel/std_vendor.rs create mode 100644 rust/kernel/str.rs create mode 100644 rust/kernel/sync.rs create mode 100644 rust/kernel/sync/arc.rs create mode 100644 rust/kernel/sync/condvar.rs create mode 100644 rust/kernel/sync/guard.rs create mode 100644 rust/kernel/sync/locked_by.rs create mode 100644 rust/kernel/sync/mutex.rs create mode 100644 rust/kernel/sync/nowait.rs create mode 100644 rust/kernel/sync/revocable.rs create mode 100644 rust/kernel/sync/rwsem.rs create mode 100644 rust/kernel/sync/seqlock.rs create mode 100644 rust/kernel/sync/smutex.rs create mode 100644 rust/kernel/sync/spinlock.rs create mode 100644 rust/kernel/sysctl.rs create mode 100644 rust/kernel/task.rs create mode 100644 rust/kernel/types.rs create mode 100644 rust/kernel/user_ptr.rs create mode 100644 rust/macros/helpers.rs create mode 100644 rust/macros/lib.rs create mode 100644 rust/macros/module.rs create mode 100644 samples/rust/Kconfig create mode 100644 samples/rust/Makefile create mode 100644 samples/rust/hostprogs/.gitignore create mode 100644 samples/rust/hostprogs/Makefile create mode 100644 samples/rust/hostprogs/a.rs create mode 100644 samples/rust/hostprogs/b.rs create mode 100644 samples/rust/hostprogs/single.rs create mode 100644 samples/rust/rust_chrdev.rs create mode 100644 samples/rust/rust_minimal.rs create mode 100644 samples/rust/rust_miscdev.rs create mode 100644 samples/rust/rust_module_parameters.rs create mode 100644 samples/rust/rust_netfilter.rs create mode 100644 samples/rust/rust_platform.rs create mode 100644 samples/rust/rust_print.rs create mode 100644 samples/rust/rust_random.rs create mode 100644 samples/rust/rust_semaphore.rs create mode 100644 samples/rust/rust_semaphore_c.c create mode 100644 samples/rust/rust_stack_probing.rs create mode 100644 samples/rust/rust_sync.rs create mode 100755 scripts/generate_rust_analyzer.py create mode 100644 scripts/generate_rust_target.rs create mode 100755 scripts/is_rust_module.sh create mode 100644 scripts/rust-is-available-bindgen-libclang.h create mode 100755 scripts/rust-is-available.sh create mode 100755 scripts/rustdoc_test_builder.py create mode 100755 scripts/rustdoc_test_gen.py base-commit: 4b0986a3613c92f4ec1bdc7f60ec66fea135991f -- 2.36.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v7 24/25] [RFC] drivers: gpio: PrimeCell PL061 in Rust 2022-05-23 2:01 [PATCH v7 00/25] Rust support Miguel Ojeda @ 2022-05-23 2:01 ` Miguel Ojeda 2022-07-16 12:42 ` [PATCH v7 00/25] Rust support Conor Dooley 1 sibling, 0 replies; 6+ messages in thread From: Miguel Ojeda @ 2022-05-23 2:01 UTC (permalink / raw) To: Linus Torvalds, Greg Kroah-Hartman Cc: rust-for-linux, linux-kernel, Jarkko Sakkinen, Miguel Ojeda, Wedson Almeida Filho, Linus Walleij, Bartosz Golaszewski, linux-gpio From: Wedson Almeida Filho <wedsonaf@google.com> A port to Rust of the PrimeCell PL061 GPIO driver. This module is a work in progress and will be sent for review later on, as well as separately from the Rust support. However, it is included to show how an actual working module written in Rust may look like. Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com> Signed-off-by: Miguel Ojeda <ojeda@kernel.org> --- drivers/gpio/Kconfig | 8 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio_pl061_rust.rs | 370 ++++++++++++++++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 drivers/gpio/gpio_pl061_rust.rs diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 45764ec3b2eb..ad99b96f6d79 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -481,6 +481,14 @@ config GPIO_PL061 help Say yes here to support the PrimeCell PL061 GPIO device. +config GPIO_PL061_RUST + tristate "PrimeCell PL061 GPIO support written in Rust" + depends on ARM_AMBA && RUST + select IRQ_DOMAIN + select GPIOLIB_IRQCHIP + help + Say yes here to support the PrimeCell PL061 GPIO device + config GPIO_PMIC_EIC_SPRD tristate "Spreadtrum PMIC EIC support" depends on MFD_SC27XX_PMIC || COMPILE_TEST diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 14352f6dfe8e..30141fec12be 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -118,6 +118,7 @@ obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o +obj-$(CONFIG_GPIO_PL061_RUST) += gpio_pl061_rust.o obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o diff --git a/drivers/gpio/gpio_pl061_rust.rs b/drivers/gpio/gpio_pl061_rust.rs new file mode 100644 index 000000000000..908914080442 --- /dev/null +++ b/drivers/gpio/gpio_pl061_rust.rs @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Driver for the ARM PrimeCell(tm) General Purpose Input/Output (PL061). +//! +//! Based on the C driver written by Baruch Siach <baruch@tkos.co.il>. + +use kernel::{ + amba, bit, bits_iter, define_amba_id_table, device, gpio, + io_mem::IoMem, + irq::{self, ExtraResult, IrqData, LockedIrqData}, + power, + prelude::*, + sync::{RawSpinLock, Ref, RefBorrow}, +}; + +const GPIODIR: usize = 0x400; +const GPIOIS: usize = 0x404; +const GPIOIBE: usize = 0x408; +const GPIOIEV: usize = 0x40C; +const GPIOIE: usize = 0x410; +const GPIOMIS: usize = 0x418; +const GPIOIC: usize = 0x41C; +const GPIO_SIZE: usize = 0x1000; + +const PL061_GPIO_NR: u16 = 8; + +#[derive(Default)] +struct ContextSaveRegs { + gpio_data: u8, + gpio_dir: u8, + gpio_is: u8, + gpio_ibe: u8, + gpio_iev: u8, + gpio_ie: u8, +} + +#[derive(Default)] +struct PL061DataInner { + csave_regs: ContextSaveRegs, +} + +struct PL061Data { + dev: device::Device, + inner: RawSpinLock<PL061DataInner>, +} + +struct PL061Resources { + base: IoMem<GPIO_SIZE>, + parent_irq: u32, +} + +type PL061Registrations = gpio::RegistrationWithIrqChip<PL061Device>; + +type DeviceData = device::Data<PL061Registrations, PL061Resources, PL061Data>; + +struct PL061Device; + +impl gpio::Chip for PL061Device { + type Data = Ref<DeviceData>; + + kernel::declare_gpio_chip_operations!( + get_direction, + direction_input, + direction_output, + get, + set + ); + + fn get_direction(data: RefBorrow<'_, DeviceData>, offset: u32) -> Result<gpio::LineDirection> { + let pl061 = data.resources().ok_or(ENXIO)?; + Ok(if pl061.base.readb(GPIODIR) & bit(offset) != 0 { + gpio::LineDirection::Out + } else { + gpio::LineDirection::In + }) + } + + fn direction_input(data: RefBorrow<'_, DeviceData>, offset: u32) -> Result { + let _guard = data.inner.lock_irqdisable(); + let pl061 = data.resources().ok_or(ENXIO)?; + let mut gpiodir = pl061.base.readb(GPIODIR); + gpiodir &= !bit(offset); + pl061.base.writeb(gpiodir, GPIODIR); + Ok(()) + } + + fn direction_output(data: RefBorrow<'_, DeviceData>, offset: u32, value: bool) -> Result { + let woffset = bit(offset + 2).into(); + let _guard = data.inner.lock_irqdisable(); + let pl061 = data.resources().ok_or(ENXIO)?; + pl061.base.try_writeb((value as u8) << offset, woffset)?; + let mut gpiodir = pl061.base.readb(GPIODIR); + gpiodir |= bit(offset); + pl061.base.writeb(gpiodir, GPIODIR); + + // gpio value is set again, because pl061 doesn't allow to set value of a gpio pin before + // configuring it in OUT mode. + pl061.base.try_writeb((value as u8) << offset, woffset)?; + Ok(()) + } + + fn get(data: RefBorrow<'_, DeviceData>, offset: u32) -> Result<bool> { + let pl061 = data.resources().ok_or(ENXIO)?; + Ok(pl061.base.try_readb(bit(offset + 2).into())? != 0) + } + + fn set(data: RefBorrow<'_, DeviceData>, offset: u32, value: bool) { + if let Some(pl061) = data.resources() { + let woffset = bit(offset + 2).into(); + let _ = pl061.base.try_writeb((value as u8) << offset, woffset); + } + } +} + +impl gpio::ChipWithIrqChip for PL061Device { + fn handle_irq_flow( + data: RefBorrow<'_, DeviceData>, + desc: &irq::Descriptor, + domain: &irq::Domain, + ) { + let chained = desc.enter_chained(); + + if let Some(pl061) = data.resources() { + let pending = pl061.base.readb(GPIOMIS); + for offset in bits_iter(pending) { + domain.generic_handle_chained(offset, &chained); + } + } + } +} + +impl irq::Chip for PL061Device { + type Data = Ref<DeviceData>; + + kernel::declare_irq_chip_operations!(set_type, set_wake); + + fn set_type( + data: RefBorrow<'_, DeviceData>, + irq_data: &mut LockedIrqData, + trigger: u32, + ) -> Result<ExtraResult> { + let offset = irq_data.hwirq(); + let bit = bit(offset); + + if offset >= PL061_GPIO_NR.into() { + return Err(EINVAL); + } + + if trigger & (irq::Type::LEVEL_HIGH | irq::Type::LEVEL_LOW) != 0 + && trigger & (irq::Type::EDGE_RISING | irq::Type::EDGE_FALLING) != 0 + { + dev_err!( + data.dev, + "trying to configure line {} for both level and edge detection, choose one!\n", + offset + ); + return Err(EINVAL); + } + + let _guard = data.inner.lock_irqdisable(); + let pl061 = data.resources().ok_or(ENXIO)?; + + let mut gpioiev = pl061.base.readb(GPIOIEV); + let mut gpiois = pl061.base.readb(GPIOIS); + let mut gpioibe = pl061.base.readb(GPIOIBE); + + if trigger & (irq::Type::LEVEL_HIGH | irq::Type::LEVEL_LOW) != 0 { + let polarity = trigger & irq::Type::LEVEL_HIGH != 0; + + // Disable edge detection. + gpioibe &= !bit; + // Enable level detection. + gpiois |= bit; + // Select polarity. + if polarity { + gpioiev |= bit; + } else { + gpioiev &= !bit; + } + irq_data.set_level_handler(); + dev_dbg!( + data.dev, + "line {}: IRQ on {} level\n", + offset, + if polarity { "HIGH" } else { "LOW" } + ); + } else if (trigger & irq::Type::EDGE_BOTH) == irq::Type::EDGE_BOTH { + // Disable level detection. + gpiois &= !bit; + // Select both edges, settings this makes GPIOEV be ignored. + gpioibe |= bit; + irq_data.set_edge_handler(); + dev_dbg!(data.dev, "line {}: IRQ on both edges\n", offset); + } else if trigger & (irq::Type::EDGE_RISING | irq::Type::EDGE_FALLING) != 0 { + let rising = trigger & irq::Type::EDGE_RISING != 0; + + // Disable level detection. + gpiois &= !bit; + // Clear detection on both edges. + gpioibe &= !bit; + // Select edge. + if rising { + gpioiev |= bit; + } else { + gpioiev &= !bit; + } + irq_data.set_edge_handler(); + dev_dbg!( + data.dev, + "line {}: IRQ on {} edge\n", + offset, + if rising { "RISING" } else { "FALLING}" } + ); + } else { + // No trigger: disable everything. + gpiois &= !bit; + gpioibe &= !bit; + gpioiev &= !bit; + irq_data.set_bad_handler(); + dev_warn!(data.dev, "no trigger selected for line {}\n", offset); + } + + pl061.base.writeb(gpiois, GPIOIS); + pl061.base.writeb(gpioibe, GPIOIBE); + pl061.base.writeb(gpioiev, GPIOIEV); + + Ok(ExtraResult::None) + } + + fn mask(data: RefBorrow<'_, DeviceData>, irq_data: &IrqData) { + let mask = bit(irq_data.hwirq() % irq::HwNumber::from(PL061_GPIO_NR)); + let _guard = data.inner.lock(); + if let Some(pl061) = data.resources() { + let gpioie = pl061.base.readb(GPIOIE) & !mask; + pl061.base.writeb(gpioie, GPIOIE); + } + } + + fn unmask(data: RefBorrow<'_, DeviceData>, irq_data: &IrqData) { + let mask = bit(irq_data.hwirq() % irq::HwNumber::from(PL061_GPIO_NR)); + let _guard = data.inner.lock(); + if let Some(pl061) = data.resources() { + let gpioie = pl061.base.readb(GPIOIE) | mask; + pl061.base.writeb(gpioie, GPIOIE); + } + } + + // This gets called from the edge IRQ handler to ACK the edge IRQ in the GPIOIC + // (interrupt-clear) register. For level IRQs this is not needed: these go away when the level + // signal goes away. + fn ack(data: RefBorrow<'_, DeviceData>, irq_data: &IrqData) { + let mask = bit(irq_data.hwirq() % irq::HwNumber::from(PL061_GPIO_NR)); + let _guard = data.inner.lock(); + if let Some(pl061) = data.resources() { + pl061.base.writeb(mask.into(), GPIOIC); + } + } + + fn set_wake(data: RefBorrow<'_, DeviceData>, _irq_data: &IrqData, on: bool) -> Result { + let pl061 = data.resources().ok_or(ENXIO)?; + irq::set_wake(pl061.parent_irq, on) + } +} + +impl amba::Driver for PL061Device { + type Data = Ref<DeviceData>; + type PowerOps = Self; + + define_amba_id_table! {(), [ + ({id: 0x00041061, mask: 0x000fffff}, None), + ]} + + fn probe(dev: &mut amba::Device, _data: Option<&Self::IdInfo>) -> Result<Ref<DeviceData>> { + let res = dev.take_resource().ok_or(ENXIO)?; + let irq = dev.irq(0).ok_or(ENXIO)?; + + let mut data = kernel::new_device_data!( + gpio::RegistrationWithIrqChip::new(), + PL061Resources { + // SAFETY: This device doesn't support DMA. + base: unsafe { IoMem::try_new(res)? }, + parent_irq: irq, + }, + PL061Data { + dev: device::Device::from_dev(dev), + // SAFETY: We call `rawspinlock_init` below. + inner: unsafe { RawSpinLock::new(PL061DataInner::default()) }, + }, + "PL061::Registrations" + )?; + + // SAFETY: General part of the data is pinned when `data` is. + let gen_inner = unsafe { data.as_mut().map_unchecked_mut(|d| &mut (**d).inner) }; + kernel::rawspinlock_init!(gen_inner, "PL061Data::inner"); + + let data = Ref::<DeviceData>::from(data); + + data.resources().ok_or(ENXIO)?.base.writeb(0, GPIOIE); // disable irqs + + data.registrations() + .ok_or(ENXIO)? + .as_pinned_mut() + .register::<Self>(PL061_GPIO_NR, None, dev, data.clone(), irq)?; + + dev_info!(data.dev, "PL061 GPIO chip registered\n"); + + Ok(data) + } +} + +impl power::Operations for PL061Device { + type Data = Ref<DeviceData>; + + fn suspend(data: RefBorrow<'_, DeviceData>) -> Result { + let mut inner = data.inner.lock(); + let pl061 = data.resources().ok_or(ENXIO)?; + inner.csave_regs.gpio_data = 0; + inner.csave_regs.gpio_dir = pl061.base.readb(GPIODIR); + inner.csave_regs.gpio_is = pl061.base.readb(GPIOIS); + inner.csave_regs.gpio_ibe = pl061.base.readb(GPIOIBE); + inner.csave_regs.gpio_iev = pl061.base.readb(GPIOIEV); + inner.csave_regs.gpio_ie = pl061.base.readb(GPIOIE); + + for offset in 0..PL061_GPIO_NR { + if inner.csave_regs.gpio_dir & bit(offset) != 0 { + if let Ok(v) = <Self as gpio::Chip>::get(data, offset.into()) { + inner.csave_regs.gpio_data |= (v as u8) << offset; + } + } + } + + Ok(()) + } + + fn resume(data: RefBorrow<'_, DeviceData>) -> Result { + let inner = data.inner.lock(); + let pl061 = data.resources().ok_or(ENXIO)?; + + for offset in 0..PL061_GPIO_NR { + if inner.csave_regs.gpio_dir & bit(offset) != 0 { + let value = inner.csave_regs.gpio_data & bit(offset) != 0; + let _ = <Self as gpio::Chip>::direction_output(data, offset.into(), value); + } else { + let _ = <Self as gpio::Chip>::direction_input(data, offset.into()); + } + } + + pl061.base.writeb(inner.csave_regs.gpio_is, GPIOIS); + pl061.base.writeb(inner.csave_regs.gpio_ibe, GPIOIBE); + pl061.base.writeb(inner.csave_regs.gpio_iev, GPIOIEV); + pl061.base.writeb(inner.csave_regs.gpio_ie, GPIOIE); + + Ok(()) + } + + fn freeze(data: RefBorrow<'_, DeviceData>) -> Result { + Self::suspend(data) + } + + fn restore(data: RefBorrow<'_, DeviceData>) -> Result { + Self::resume(data) + } +} + +module_amba_driver! { + type: PL061Device, + name: b"pl061_gpio", + author: b"Wedson Almeida Filho", + license: b"GPL", +} -- 2.36.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v7 00/25] Rust support 2022-05-23 2:01 [PATCH v7 00/25] Rust support Miguel Ojeda 2022-05-23 2:01 ` [PATCH v7 24/25] [RFC] drivers: gpio: PrimeCell PL061 in Rust Miguel Ojeda @ 2022-07-16 12:42 ` Conor Dooley 2022-07-16 13:36 ` Miguel Ojeda 1 sibling, 1 reply; 6+ messages in thread From: Conor Dooley @ 2022-07-16 12:42 UTC (permalink / raw) To: ojeda Cc: gregkh, jarkko, kunit-dev, linux-arm-kernel, linux-doc, linux-gpio, linux-kbuild, linux-kernel, linux-kselftest, linux-perf-users, linux-riscv, linux-um, linuxppc-dev, live-patching, rust-for-linux, torvalds Hey, Maybe I am just missing something blatantly obvious here, but trying to build rust support in -next fails for me. I am using ClangBuiltLinux clang version 15.0.0 5b0788fef86ed7008a11f6ee19b9d86d42b6fcfa and LLD 15.0.0. Is it just expected that building -next with rust support is not a good idea? My defconfig is the default RISC-V one plus: CONFIG_RUST=y CONFIG_SAMPLES=y CONFIG_SAMPLES_RUST=y CONFIG_SAMPLE_RUST_MINIMAL=y Thanks, Conor. Fail log: UPD rust/target.json BINDGEN rust/bindings_generated.rs BINDGEN rust/bindings_helpers_generated.rs RUSTC L rust/core.o EXPORTS rust/exports_core_generated.h RUSTC P rust/libmacros.so RUSTC L rust/compiler_builtins.o RUSTC L rust/alloc.o RUSTC L rust/build_error.o EXPORTS rust/exports_alloc_generated.h RUSTC L rust/kernel.o error[E0428]: the name `maple_enode` is defined multiple times --> linux/rust/bindings_generated.rs:18009:1 | 18006 | pub struct maple_enode { | ---------------------- previous definition of the type `maple_enode` here ... 18009 | pub type maple_enode = *mut maple_enode; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `maple_enode` redefined here | = note: `maple_enode` must be defined only once in the type namespace of this module error[E0428]: the name `maple_pnode` is defined multiple times --> linux/rust/bindings_generated.rs:18015:1 | 18012 | pub struct maple_pnode { | ---------------------- previous definition of the type `maple_pnode` here ... 18015 | pub type maple_pnode = *mut maple_pnode; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `maple_pnode` redefined here | = note: `maple_pnode` must be defined only once in the type namespace of this module error[E0391]: cycle detected when expanding type alias `bindings::bindings_raw::maple_pnode` --> linux/rust/bindings_generated.rs:18015:29 | 18015 | pub type maple_pnode = *mut maple_pnode; | ^^^^^^^^^^^ | = note: ...which immediately requires expanding type alias `bindings::bindings_raw::maple_pnode` again = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information note: cycle used when computing type of `bindings::bindings_raw::maple_range_64::parent` --> linux/rust/bindings_generated.rs:18058:22 | 18058 | pub parent: *mut maple_pnode, | ^^^^^^^^^^^ error[E0391]: cycle detected when expanding type alias `bindings::bindings_raw::maple_enode` --> linux/rust/bindings_generated.rs:18009:29 | 18009 | pub type maple_enode = *mut maple_enode; | ^^^^^^^^^^^ | = note: ...which immediately requires expanding type alias `bindings::bindings_raw::maple_enode` again = note: type aliases cannot be recursive = help: consider using a struct, enum, or union instead to break the cycle = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information note: cycle used when computing type of `bindings::bindings_raw::maple_topiary::next` --> linux/rust/bindings_generated.rs:18340:20 | 18340 | pub next: *mut maple_enode, | ^^^^^^^^^^^ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> linux/rust/bindings_generated.rs:18005:10 | 18005 | #[derive(Copy, Clone)] | ^^^^ | | | impl doesn't use only types from inside the current crate | `*mut [type error]` is not defined in the current crate | = note: define and implement a trait or new type instead = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> linux/rust/bindings_generated.rs:18011:10 | 18011 | #[derive(Copy, Clone)] | ^^^^ | | | impl doesn't use only types from inside the current crate | `*mut [type error]` is not defined in the current crate | = note: define and implement a trait or new type instead = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> linux/rust/bindings_generated.rs:18005:16 | 18005 | #[derive(Copy, Clone)] | ^^^^^ | | | impl doesn't use only types from inside the current crate | `*mut [type error]` is not defined in the current crate | = note: define and implement a trait or new type instead = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0117]: only traits defined in the current crate can be implemented for arbitrary types --> linux/rust/bindings_generated.rs:18011:16 | 18011 | #[derive(Copy, Clone)] | ^^^^^ | | | impl doesn't use only types from inside the current crate | `*mut [type error]` is not defined in the current crate | = note: define and implement a trait or new type instead = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 8 previous errors ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 00/25] Rust support 2022-07-16 12:42 ` [PATCH v7 00/25] Rust support Conor Dooley @ 2022-07-16 13:36 ` Miguel Ojeda 2022-07-16 13:51 ` Conor.Dooley 0 siblings, 1 reply; 6+ messages in thread From: Miguel Ojeda @ 2022-07-16 13:36 UTC (permalink / raw) To: Conor Dooley Cc: Miguel Ojeda, Greg KH, Jarkko Sakkinen, KUnit Development, Linux ARM, Linux Doc Mailing List, open list:GPIO SUBSYSTEM, Linux Kbuild mailing list, linux-kernel, open list:KERNEL SELFTEST FRAMEWORK, linux-perf-users, linux-riscv, linux-um, linuxppc-dev, live-patching, rust-for-linux, Linus Torvalds Hi Conor, On Sat, Jul 16, 2022 at 2:42 PM Conor Dooley <conor@kernel.org> wrote: > > Maybe I am just missing something blatantly obvious here, but trying > to build rust support in -next fails for me. I am using ClangBuiltLinux > clang version 15.0.0 5b0788fef86ed7008a11f6ee19b9d86d42b6fcfa and LLD > 15.0.0. Is it just expected that building -next with rust support is > not a good idea? Please see https://github.com/Rust-for-Linux/linux/issues/795 for details about the maple tree issue. I will update the `rust-next` branch next week with the new version of the patches; but if you are interested in developing, please use the development `rust` branch instead in GitHub for the moment. Cheers, Miguel ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 00/25] Rust support 2022-07-16 13:36 ` Miguel Ojeda @ 2022-07-16 13:51 ` Conor.Dooley 2022-07-16 13:56 ` Miguel Ojeda 0 siblings, 1 reply; 6+ messages in thread From: Conor.Dooley @ 2022-07-16 13:51 UTC (permalink / raw) To: miguel.ojeda.sandonis, conor Cc: ojeda, gregkh, jarkko, kunit-dev, linux-arm-kernel, linux-doc, linux-gpio, linux-kbuild, linux-kernel, linux-kselftest, linux-perf-users, linux-riscv, linux-um, linuxppc-dev, live-patching, rust-for-linux, torvalds On 16/07/2022 14:36, Miguel Ojeda wrote: > Hi Conor, > > On Sat, Jul 16, 2022 at 2:42 PM Conor Dooley <conor@kernel.org> wrote: >> >> Maybe I am just missing something blatantly obvious here, but trying >> to build rust support in -next fails for me. I am using ClangBuiltLinux >> clang version 15.0.0 5b0788fef86ed7008a11f6ee19b9d86d42b6fcfa and LLD >> 15.0.0. Is it just expected that building -next with rust support is >> not a good idea? > > Please see https://github.com/Rust-for-Linux/linux/issues/795 for > details about the maple tree issue. Ah right, sorry for the noise so. I checked the ml but didn't see a report there. > > I will update the `rust-next` branch next week with the new version of > the patches; but if you are interested in developing, please use the > development `rust` branch instead in GitHub for the moment. Thanks Miguel, good to know! I'll just wait around for a new version. Just been trying to get my CI etc in order for when rust support lands, but it sounds like I should be okay as it's a known problem & not some only-broken-on-riscv thing. Thanks, Conor. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v7 00/25] Rust support 2022-07-16 13:51 ` Conor.Dooley @ 2022-07-16 13:56 ` Miguel Ojeda 0 siblings, 0 replies; 6+ messages in thread From: Miguel Ojeda @ 2022-07-16 13:56 UTC (permalink / raw) To: Conor.Dooley Cc: Conor Dooley, Miguel Ojeda, Greg KH, Jarkko Sakkinen, KUnit Development, Linux ARM, Linux Doc Mailing List, open list:GPIO SUBSYSTEM, Linux Kbuild mailing list, linux-kernel, open list:KERNEL SELFTEST FRAMEWORK, linux-perf-users, linux-riscv, linux-um, linuxppc-dev, live-patching, rust-for-linux, Linus Torvalds On Sat, Jul 16, 2022 at 3:51 PM <Conor.Dooley@microchip.com> wrote: > > Ah right, sorry for the noise so. I checked the ml but didn't see a > report there. No apologies needed -- thanks to you for the report, instead! :) > Thanks Miguel, good to know! I'll just wait around for a new version. > Just been trying to get my CI etc in order for when rust support lands, > but it sounds like I should be okay as it's a known problem & not some > only-broken-on-riscv thing. Yeah, it is a simple `bindgen` issue. Thanks a lot for making the effort to prepare your CI in advance! Cheers, Miguel ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-07-16 13:56 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-05-23 2:01 [PATCH v7 00/25] Rust support Miguel Ojeda 2022-05-23 2:01 ` [PATCH v7 24/25] [RFC] drivers: gpio: PrimeCell PL061 in Rust Miguel Ojeda 2022-07-16 12:42 ` [PATCH v7 00/25] Rust support Conor Dooley 2022-07-16 13:36 ` Miguel Ojeda 2022-07-16 13:51 ` Conor.Dooley 2022-07-16 13:56 ` Miguel Ojeda
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).