* Re: [PATCH 04/11] treewide: Convert struct kernel_param_ops initializers to DEFINE_KERNEL_PARAM_OPS
From: Rafael J. Wysocki @ 2026-05-22 17:01 UTC (permalink / raw)
To: Kees Cook
Cc: Luis Chamberlain, Pengpeng Hou, Petr Pavlu, Richard Weinberger,
Anton Ivanov, Johannes Berg, Rafael J. Wysocki, Len Brown,
Corey Minyard, Gabriel Somlo, Michael S. Tsirkin, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, David Airlie,
Simona Vetter, Bart Van Assche, Jason Gunthorpe, Leon Romanovsky,
Laurent Pinchart, Hans de Goede, Mauro Carvalho Chehab,
Bjorn Helgaas, Hannes Reinecke, James E.J. Bottomley,
Martin K. Petersen, Daniel Lezcano, Zhang Rui, Lukasz Luba,
Greg Kroah-Hartman, Jiri Slaby, Alan Stern, Jason Wang, Xuan Zhuo,
Eugenio Pérez, Jason Baron, Jim Cromie, Tiwei Bie,
Benjamin Berg, Ilpo Järvinen, David E. Box,
Maciej W. Rozycki, Srinivas Pandruvada, Peter Zijlstra,
Heiko Carstens, Vasily Gorbik, Sean Christopherson, Paolo Bonzini,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Vinod Koul, Frank Li, Daniel Gomez, Sami Tolvanen,
Aaron Tomlin, Alexander Potapenko, Marco Elver, Dmitry Vyukov,
Andrew Morton, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Andy Shevchenko, Georgia Garcia, kvm, dmaengine,
linux-modules, kasan-dev, linux-mm, apparmor,
linux-security-module, linux-um, linux-acpi, openipmi-developer,
qemu-devel, intel-gfx, dri-devel, linux-rdma, linux-media,
linux-pci, linux-scsi, linux-pm, linuxppc-dev, linux-serial,
linux-usb, usb-storage, virtualization, linux-kernel, linux-arch,
netdev, linux-fsdevel, linux-hardening
In-Reply-To: <20260521133326.2465264-4-kees@kernel.org>
On Thu, May 21, 2026 at 3:33 PM Kees Cook <kees@kernel.org> wrote:
>
> Using Coccinelle, rewrite every struct kernel_param_ops initializer that
> sets .get into a DEFINE_KERNEL_PARAM_OPS-family macro invocation,
> for example:
>
> @@
> declarer name DEFINE_KERNEL_PARAM_OPS;
> identifier OPS;
> expression SET, GET;
> @@
> - const struct kernel_param_ops OPS = {
> - .set = SET,
> - .get = GET,
> - };
> + DEFINE_KERNEL_PARAM_OPS(OPS, SET, GET);
>
> Using the macro for initialization means future changes can manipulate
> the struct layout and callback prototypes without having to change every
> initializer.
>
> Signed-off-by: Kees Cook <kees@kernel.org>
For ACPI and hibernation:
Acked-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
> ---
> mm/kfence/core.c | 7 +-
> arch/powerpc/kvm/book3s_hv.c | 5 +-
> arch/s390/kernel/perf_cpum_sf.c | 6 +-
> arch/um/drivers/vfio_kern.c | 6 +-
> arch/um/drivers/virtio_uml.c | 6 +-
> arch/x86/kernel/msr.c | 6 +-
> arch/x86/kvm/mmu/mmu.c | 12 +--
> arch/x86/kvm/svm/avic.c | 6 +-
> arch/x86/kvm/vmx/vmx.c | 6 +-
> arch/x86/platform/uv/uv_nmi.c | 12 +--
> block/disk-events.c | 6 +-
> drivers/acpi/sysfs.c | 25 +++----
> drivers/block/loop.c | 12 +--
> drivers/block/null_blk/main.c | 12 +--
> drivers/block/rnbd/rnbd-srv.c | 6 +-
> drivers/block/ublk_drv.c | 7 +-
> drivers/char/ipmi/ipmi_msghandler.c | 6 +-
> drivers/char/ipmi/ipmi_watchdog.c | 17 ++---
> drivers/crypto/hisilicon/hpre/hpre_main.c | 16 +---
> drivers/crypto/hisilicon/sec2/sec_main.c | 23 ++----
> drivers/crypto/hisilicon/zip/zip_crypto.c | 5 +-
> drivers/crypto/hisilicon/zip/zip_main.c | 21 ++----
> drivers/dma/dmatest.c | 20 ++---
> drivers/edac/i10nm_base.c | 6 +-
> drivers/firmware/efi/efi-pstore.c | 6 +-
> drivers/firmware/qcom/qcom_scm.c | 6 +-
> drivers/firmware/qemu_fw_cfg.c | 6 +-
> drivers/gpu/drm/drm_panic.c | 6 +-
> drivers/gpu/drm/i915/i915_mitigations.c | 5 +-
> drivers/gpu/drm/imagination/pvr_fw_trace.c | 6 +-
> drivers/hid/hid-cougar.c | 6 +-
> drivers/hid/hid-steam.c | 6 +-
> drivers/infiniband/hw/hfi1/driver.c | 5 +-
> drivers/infiniband/ulp/iser/iscsi_iser.c | 6 +-
> drivers/infiniband/ulp/isert/ib_isert.c | 6 +-
> drivers/infiniband/ulp/srp/ib_srp.c | 5 +-
> drivers/input/misc/ati_remote2.c | 13 ++--
> drivers/input/mouse/psmouse-base.c | 6 +-
> drivers/media/usb/uvc/uvc_driver.c | 6 +-
> drivers/misc/lis3lv02d/lis3lv02d.c | 5 +-
> drivers/net/wireless/ath/wil6210/main.c | 10 +--
> drivers/nvme/host/multipath.c | 12 +--
> drivers/nvme/host/pci.c | 18 ++---
> drivers/nvme/target/rdma.c | 5 +-
> drivers/nvme/target/tcp.c | 5 +-
> drivers/platform/x86/acerhdf.c | 5 +-
> drivers/power/supply/bq27xxx_battery.c | 6 +-
> drivers/power/supply/test_power.c | 75 ++++++++-----------
> drivers/scsi/sg.c | 6 +-
> drivers/target/target_core_user.c | 13 ++--
> .../processor_thermal_soc_slider.c | 12 +--
> drivers/thermal/intel/intel_powerclamp.c | 20 +----
> drivers/tty/hvc/hvc_iucv.c | 6 +-
> drivers/tty/sysrq.c | 6 +-
> drivers/ufs/core/ufs-fault-injection.c | 5 +-
> drivers/ufs/core/ufs-mcq.c | 18 ++---
> drivers/ufs/core/ufs-txeq.c | 5 +-
> drivers/ufs/core/ufshcd.c | 12 +--
> drivers/usb/core/quirks.c | 6 +-
> drivers/usb/gadget/legacy/serial.c | 5 +-
> drivers/usb/storage/usb.c | 5 +-
> drivers/vhost/scsi.c | 7 +-
> drivers/virt/nitro_enclaves/ne_misc_dev.c | 6 +-
> drivers/virtio/virtio_mmio.c | 6 +-
> fs/ceph/super.c | 10 +--
> fs/fuse/dir.c | 5 +-
> fs/nfs/namespace.c | 6 +-
> fs/nfs/super.c | 6 +-
> fs/ubifs/super.c | 6 +-
> kernel/locking/locktorture.c | 6 +-
> kernel/panic.c | 6 +-
> kernel/params.c | 44 +++--------
> kernel/power/hibernate.c | 6 +-
> kernel/rcu/tree.c | 18 ++---
> kernel/sched/ext.c | 11 +--
> kernel/workqueue.c | 12 +--
> lib/dynamic_debug.c | 6 +-
> lib/test_dynamic_debug.c | 6 +-
> mm/damon/lru_sort.c | 19 ++---
> mm/damon/reclaim.c | 19 ++---
> mm/damon/stat.c | 6 +-
> mm/memory_hotplug.c | 12 +--
> mm/page_reporting.c | 11 +--
> mm/shuffle.c | 6 +-
> mm/zswap.c | 14 ++--
> net/batman-adv/bat_algo.c | 6 +-
> net/ceph/ceph_common.c | 5 +-
> net/ipv4/tcp_dctcp.c | 6 +-
> net/sunrpc/auth.c | 6 +-
> net/sunrpc/xprtsock.c | 18 ++---
> samples/damon/mtier.c | 6 +-
> samples/damon/prcl.c | 6 +-
> samples/damon/wsse.c | 6 +-
> security/apparmor/lsm.c | 34 +++------
> sound/hda/controllers/intel.c | 5 +-
> sound/usb/card.c | 7 +-
> 96 files changed, 307 insertions(+), 660 deletions(-)
>
> diff --git a/mm/kfence/core.c b/mm/kfence/core.c
> index 655dc5ce3240..e14102c01520 100644
> --- a/mm/kfence/core.c
> +++ b/mm/kfence/core.c
> @@ -92,10 +92,9 @@ static int param_get_sample_interval(char *buffer, const struct kernel_param *kp
> return param_get_ulong(buffer, kp);
> }
>
> -static const struct kernel_param_ops sample_interval_param_ops = {
> - .set = param_set_sample_interval,
> - .get = param_get_sample_interval,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sample_interval_param_ops,
> + param_set_sample_interval,
> + param_get_sample_interval);
> module_param_cb(sample_interval, &sample_interval_param_ops, &kfence_sample_interval, 0600);
>
> /* Pool usage% threshold when currently covered allocations are skipped. */
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index 61dbeea317f3..0c15f0426671 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -114,10 +114,7 @@ module_param(one_vm_per_core, bool, S_IRUGO | S_IWUSR);
> MODULE_PARM_DESC(one_vm_per_core, "Only run vCPUs from the same VM on a core (requires POWER8 or older)");
>
> #ifdef CONFIG_KVM_XICS
> -static const struct kernel_param_ops module_param_ops = {
> - .set = param_set_int,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(module_param_ops, param_set_int, param_get_int);
>
> module_param_cb(kvm_irq_bypass, &module_param_ops, &kvm_irq_bypass, 0644);
> MODULE_PARM_DESC(kvm_irq_bypass, "Bypass passthrough interrupt optimization");
> diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
> index 7bfeb5208177..76119542562b 100644
> --- a/arch/s390/kernel/perf_cpum_sf.c
> +++ b/arch/s390/kernel/perf_cpum_sf.c
> @@ -2029,10 +2029,8 @@ static int param_set_sfb_size(const char *val, const struct kernel_param *kp)
> }
>
> #define param_check_sfb_size(name, p) __param_check(name, p, void)
> -static const struct kernel_param_ops param_ops_sfb_size = {
> - .set = param_set_sfb_size,
> - .get = param_get_sfb_size,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_sfb_size, param_set_sfb_size,
> + param_get_sfb_size);
>
> enum {
> RS_INIT_FAILURE_BSDES = 2, /* Bad basic sampling size */
> diff --git a/arch/um/drivers/vfio_kern.c b/arch/um/drivers/vfio_kern.c
> index e6dab473cde4..fb7988dc5482 100644
> --- a/arch/um/drivers/vfio_kern.c
> +++ b/arch/um/drivers/vfio_kern.c
> @@ -628,10 +628,8 @@ static int uml_vfio_cmdline_get(char *buffer, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops uml_vfio_cmdline_param_ops = {
> - .set = uml_vfio_cmdline_set,
> - .get = uml_vfio_cmdline_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(uml_vfio_cmdline_param_ops, uml_vfio_cmdline_set,
> + uml_vfio_cmdline_get);
>
> device_param_cb(device, ¨_vfio_cmdline_param_ops, NULL, 0400);
> __uml_help(uml_vfio_cmdline_param_ops,
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index 7425a8548141..f9ae745f4586 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -1398,10 +1398,8 @@ static int vu_cmdline_get(char *buffer, const struct kernel_param *kp)
> return strlen(buffer) + 1;
> }
>
> -static const struct kernel_param_ops vu_cmdline_param_ops = {
> - .set = vu_cmdline_set,
> - .get = vu_cmdline_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vu_cmdline_param_ops, vu_cmdline_set,
> + vu_cmdline_get);
>
> device_param_cb(device, &vu_cmdline_param_ops, NULL, S_IRUSR);
> __uml_help(vu_cmdline_param_ops,
> diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
> index 4469c784eaa0..5f4e1814dc4d 100644
> --- a/arch/x86/kernel/msr.c
> +++ b/arch/x86/kernel/msr.c
> @@ -322,10 +322,8 @@ static int get_allow_writes(char *buf, const struct kernel_param *kp)
> return sprintf(buf, "%s\n", res);
> }
>
> -static const struct kernel_param_ops allow_writes_ops = {
> - .set = set_allow_writes,
> - .get = get_allow_writes
> -};
> +static DEFINE_KERNEL_PARAM_OPS(allow_writes_ops, set_allow_writes,
> + get_allow_writes);
>
> module_param_cb(allow_writes, &allow_writes_ops, NULL, 0600);
>
> diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
> index 24fbc9ea502a..996818ee9b09 100644
> --- a/arch/x86/kvm/mmu/mmu.c
> +++ b/arch/x86/kvm/mmu/mmu.c
> @@ -74,15 +74,11 @@ static int get_nx_huge_pages(char *buffer, const struct kernel_param *kp);
> static int set_nx_huge_pages(const char *val, const struct kernel_param *kp);
> static int set_nx_huge_pages_recovery_param(const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops nx_huge_pages_ops = {
> - .set = set_nx_huge_pages,
> - .get = get_nx_huge_pages,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(nx_huge_pages_ops, set_nx_huge_pages,
> + get_nx_huge_pages);
>
> -static const struct kernel_param_ops nx_huge_pages_recovery_param_ops = {
> - .set = set_nx_huge_pages_recovery_param,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(nx_huge_pages_recovery_param_ops,
> + set_nx_huge_pages_recovery_param, param_get_uint);
>
> module_param_cb(nx_huge_pages, &nx_huge_pages_ops, &nx_huge_pages, 0644);
> __MODULE_PARM_TYPE(nx_huge_pages, "bool");
> diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> index adf211860949..7907f9addff9 100644
> --- a/arch/x86/kvm/svm/avic.c
> +++ b/arch/x86/kvm/svm/avic.c
> @@ -87,11 +87,7 @@ static int avic_param_get(char *buffer, const struct kernel_param *kp)
> return param_get_bool(buffer, kp);
> }
>
> -static const struct kernel_param_ops avic_ops = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = avic_param_set,
> - .get = avic_param_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS_NOARG(avic_ops, avic_param_set, avic_param_get);
>
> /*
> * Enable / disable AVIC. In "auto" mode (default behavior), AVIC is enabled
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index a29896a9ef14..07f4c7209ac0 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -465,10 +465,8 @@ static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
> }
> #endif
>
> -static const struct kernel_param_ops vmentry_l1d_flush_ops = {
> - .set = vmentry_l1d_flush_set,
> - .get = vmentry_l1d_flush_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vmentry_l1d_flush_ops, vmentry_l1d_flush_set,
> + vmentry_l1d_flush_get);
> module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, NULL, 0644);
>
> static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
> diff --git a/arch/x86/platform/uv/uv_nmi.c b/arch/x86/platform/uv/uv_nmi.c
> index 5c50e550ab63..a7ac80b5f8d9 100644
> --- a/arch/x86/platform/uv/uv_nmi.c
> +++ b/arch/x86/platform/uv/uv_nmi.c
> @@ -123,10 +123,8 @@ static int param_set_local64(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops param_ops_local64 = {
> - .get = param_get_local64,
> - .set = param_set_local64,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_local64, param_set_local64,
> + param_get_local64);
> #define param_check_local64(name, p) __param_check(name, p, local64_t)
>
> static local64_t uv_nmi_count;
> @@ -232,10 +230,8 @@ static int param_set_action(const char *val, const struct kernel_param *kp)
> return -EINVAL;
> }
>
> -static const struct kernel_param_ops param_ops_action = {
> - .get = param_get_action,
> - .set = param_set_action,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_action, param_set_action,
> + param_get_action);
> #define param_check_action(name, p) __param_check(name, p, enum action_t)
>
> module_param_named(action, uv_nmi_action, action, 0644);
> diff --git a/block/disk-events.c b/block/disk-events.c
> index 074731ecc3d2..f2d4b48294c6 100644
> --- a/block/disk-events.c
> +++ b/block/disk-events.c
> @@ -416,10 +416,8 @@ static int disk_events_set_dfl_poll_msecs(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops disk_events_dfl_poll_msecs_param_ops = {
> - .set = disk_events_set_dfl_poll_msecs,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(disk_events_dfl_poll_msecs_param_ops,
> + disk_events_set_dfl_poll_msecs, param_get_ulong);
>
> #undef MODULE_PARAM_PREFIX
> #define MODULE_PARAM_PREFIX "block."
> diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
> index a625de3c3c8b..3d32a5280432 100644
> --- a/drivers/acpi/sysfs.c
> +++ b/drivers/acpi/sysfs.c
> @@ -138,15 +138,11 @@ static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
> return result;
> }
>
> -static const struct kernel_param_ops param_ops_debug_layer = {
> - .set = param_set_uint,
> - .get = param_get_debug_layer,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_debug_layer, param_set_uint,
> + param_get_debug_layer);
>
> -static const struct kernel_param_ops param_ops_debug_level = {
> - .set = param_set_uint,
> - .get = param_get_debug_level,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_debug_level, param_set_uint,
> + param_get_debug_level);
>
> module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644);
> module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644);
> @@ -201,15 +197,12 @@ static int param_get_trace_method_name(char *buffer, const struct kernel_param *
> return sysfs_emit(buffer, "%s\n", acpi_gbl_trace_method_name);
> }
>
> -static const struct kernel_param_ops param_ops_trace_method = {
> - .set = param_set_trace_method_name,
> - .get = param_get_trace_method_name,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_trace_method,
> + param_set_trace_method_name,
> + param_get_trace_method_name);
>
> -static const struct kernel_param_ops param_ops_trace_attrib = {
> - .set = param_set_uint,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_trace_attrib, param_set_uint,
> + param_get_uint);
>
> module_param_cb(trace_method_name, ¶m_ops_trace_method, &trace_method_name, 0644);
> module_param_cb(trace_debug_layer, ¶m_ops_trace_attrib, &acpi_gbl_trace_dbg_layer, 0644);
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index 0000913f7efc..147ad561e584 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -1806,10 +1806,8 @@ static int max_loop_param_set_int(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops max_loop_param_ops = {
> - .set = max_loop_param_set_int,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(max_loop_param_ops, max_loop_param_set_int,
> + param_get_int);
>
> module_param_cb(max_loop, &max_loop_param_ops, &max_loop, 0444);
> MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
> @@ -1836,10 +1834,8 @@ static int loop_set_hw_queue_depth(const char *s, const struct kernel_param *p)
> return 0;
> }
>
> -static const struct kernel_param_ops loop_hw_qdepth_param_ops = {
> - .set = loop_set_hw_queue_depth,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(loop_hw_qdepth_param_ops,
> + loop_set_hw_queue_depth, param_get_int);
>
> device_param_cb(hw_queue_depth, &loop_hw_qdepth_param_ops, &hw_queue_depth, 0444);
> MODULE_PARM_DESC(hw_queue_depth, "Queue depth for each hardware queue. Default: " __stringify(LOOP_DEFAULT_HW_Q_DEPTH));
> diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
> index f8c0fd57e041..332ad6ac838a 100644
> --- a/drivers/block/null_blk/main.c
> +++ b/drivers/block/null_blk/main.c
> @@ -149,10 +149,8 @@ static int null_set_queue_mode(const char *str, const struct kernel_param *kp)
> return null_param_store_val(str, &g_queue_mode, NULL_Q_BIO, NULL_Q_MQ);
> }
>
> -static const struct kernel_param_ops null_queue_mode_param_ops = {
> - .set = null_set_queue_mode,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(null_queue_mode_param_ops, null_set_queue_mode,
> + param_get_int);
>
> device_param_cb(queue_mode, &null_queue_mode_param_ops, &g_queue_mode, 0444);
> MODULE_PARM_DESC(queue_mode, "Block interface to use (0=bio,1=rq,2=multiqueue)");
> @@ -193,10 +191,8 @@ static int null_set_irqmode(const char *str, const struct kernel_param *kp)
> NULL_IRQ_TIMER);
> }
>
> -static const struct kernel_param_ops null_irqmode_param_ops = {
> - .set = null_set_irqmode,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(null_irqmode_param_ops, null_set_irqmode,
> + param_get_int);
>
> device_param_cb(irqmode, &null_irqmode_param_ops, &g_irqmode, 0444);
> MODULE_PARM_DESC(irqmode, "IRQ completion handler. 0-none, 1-softirq, 2-timer");
> diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
> index 10e8c438bb43..81961f7c883a 100644
> --- a/drivers/block/rnbd/rnbd-srv.c
> +++ b/drivers/block/rnbd/rnbd-srv.c
> @@ -49,10 +49,8 @@ static struct kparam_string dev_search_path_kparam_str = {
> .string = dev_search_path
> };
>
> -static const struct kernel_param_ops dev_search_path_ops = {
> - .set = dev_search_path_set,
> - .get = param_get_string,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(dev_search_path_ops, dev_search_path_set,
> + param_get_string);
>
> module_param_cb(dev_search_path, &dev_search_path_ops,
> &dev_search_path_kparam_str, 0444);
> diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
> index 8e5f3738c203..f7bf7ea2d088 100644
> --- a/drivers/block/ublk_drv.c
> +++ b/drivers/block/ublk_drv.c
> @@ -5874,10 +5874,9 @@ static int ublk_get_max_unprivileged_ublks(char *buf,
> return sysfs_emit(buf, "%u\n", unprivileged_ublks_max);
> }
>
> -static const struct kernel_param_ops ublk_max_unprivileged_ublks_ops = {
> - .set = ublk_set_max_unprivileged_ublks,
> - .get = ublk_get_max_unprivileged_ublks,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ublk_max_unprivileged_ublks_ops,
> + ublk_set_max_unprivileged_ublks,
> + ublk_get_max_unprivileged_ublks);
>
> module_param_cb(ublks_max, &ublk_max_unprivileged_ublks_ops,
> &unprivileged_ublks_max, 0644);
> diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
> index 869ac87a4b6a..b5fed11707e8 100644
> --- a/drivers/char/ipmi/ipmi_msghandler.c
> +++ b/drivers/char/ipmi/ipmi_msghandler.c
> @@ -102,10 +102,8 @@ static int panic_op_read_handler(char *buffer, const struct kernel_param *kp)
> return sprintf(buffer, "%s\n", event_str);
> }
>
> -static const struct kernel_param_ops panic_op_ops = {
> - .set = panic_op_write_handler,
> - .get = panic_op_read_handler
> -};
> +static DEFINE_KERNEL_PARAM_OPS(panic_op_ops, panic_op_write_handler,
> + panic_op_read_handler);
> module_param_cb(panic_op, &panic_op_ops, NULL, 0600);
> MODULE_PARM_DESC(panic_op, "Sets if the IPMI driver will attempt to store panic information in the event log in the event of a panic. Set to 'none' for no, 'event' for a single event, or 'string' for a generic event and the panic string in IPMI OEM events.");
>
> diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
> index a013ddbf1466..91a99417d204 100644
> --- a/drivers/char/ipmi/ipmi_watchdog.c
> +++ b/drivers/char/ipmi/ipmi_watchdog.c
> @@ -193,10 +193,8 @@ static int set_param_timeout(const char *val, const struct kernel_param *kp)
> return rv;
> }
>
> -static const struct kernel_param_ops param_ops_timeout = {
> - .set = set_param_timeout,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_timeout, set_param_timeout,
> + param_get_int);
> #define param_check_timeout param_check_int
>
> typedef int (*action_fn)(const char *intval, char *outval);
> @@ -259,17 +257,12 @@ static int set_param_wdog_ifnum(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops param_ops_wdog_ifnum = {
> - .set = set_param_wdog_ifnum,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_wdog_ifnum, set_param_wdog_ifnum,
> + param_get_int);
>
> #define param_check_wdog_ifnum param_check_int
>
> -static const struct kernel_param_ops param_ops_str = {
> - .set = set_param_str,
> - .get = get_param_str,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_str, set_param_str, get_param_str);
>
> module_param(ifnum_to_use, wdog_ifnum, 0644);
> MODULE_PARM_DESC(ifnum_to_use, "The interface number to use for the watchdog "
> diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
> index 357ab5e5887e..1104184c2f63 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre_main.c
> +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
> @@ -420,10 +420,8 @@ static int hpre_cluster_regs_show(struct seq_file *s, void *unused)
>
> DEFINE_SHOW_ATTRIBUTE(hpre_cluster_regs);
>
> -static const struct kernel_param_ops hpre_uacce_mode_ops = {
> - .set = uacce_mode_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(hpre_uacce_mode_ops, uacce_mode_set,
> + param_get_int);
>
> /*
> * uacce_mode = 0 means hpre only register to crypto,
> @@ -441,19 +439,13 @@ static int pf_q_num_set(const char *val, const struct kernel_param *kp)
> return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_HPRE_PF);
> }
>
> -static const struct kernel_param_ops hpre_pf_q_num_ops = {
> - .set = pf_q_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(hpre_pf_q_num_ops, pf_q_num_set, param_get_int);
>
> static u32 pf_q_num = HPRE_PF_DEF_Q_NUM;
> module_param_cb(pf_q_num, &hpre_pf_q_num_ops, &pf_q_num, 0444);
> MODULE_PARM_DESC(pf_q_num, "Number of queues in PF of CS(2-1024)");
>
> -static const struct kernel_param_ops vfs_num_ops = {
> - .set = vfs_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vfs_num_ops, vfs_num_set, param_get_int);
>
> static u32 vfs_num;
> module_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444);
> diff --git a/drivers/crypto/hisilicon/sec2/sec_main.c b/drivers/crypto/hisilicon/sec2/sec_main.c
> index 056bd8f4da5a..3d13f2faa3d0 100644
> --- a/drivers/crypto/hisilicon/sec2/sec_main.c
> +++ b/drivers/crypto/hisilicon/sec2/sec_main.c
> @@ -362,10 +362,8 @@ static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp)
> return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_SEC_PF);
> }
>
> -static const struct kernel_param_ops sec_pf_q_num_ops = {
> - .set = sec_pf_q_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sec_pf_q_num_ops, sec_pf_q_num_set,
> + param_get_int);
>
> static u32 pf_q_num = SEC_PF_DEF_Q_NUM;
> module_param_cb(pf_q_num, &sec_pf_q_num_ops, &pf_q_num, 0444);
> @@ -391,18 +389,13 @@ static int sec_ctx_q_num_set(const char *val, const struct kernel_param *kp)
> return param_set_int(val, kp);
> }
>
> -static const struct kernel_param_ops sec_ctx_q_num_ops = {
> - .set = sec_ctx_q_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sec_ctx_q_num_ops, sec_ctx_q_num_set,
> + param_get_int);
> static u32 ctx_q_num = SEC_CTX_Q_NUM_DEF;
> module_param_cb(ctx_q_num, &sec_ctx_q_num_ops, &ctx_q_num, 0444);
> MODULE_PARM_DESC(ctx_q_num, "Queue num in ctx (2 default, 2, 4, ..., 32)");
>
> -static const struct kernel_param_ops vfs_num_ops = {
> - .set = vfs_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vfs_num_ops, vfs_num_set, param_get_int);
>
> static u32 vfs_num;
> module_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444);
> @@ -454,10 +447,8 @@ u64 sec_get_alg_bitmap(struct hisi_qm *qm, u32 high, u32 low)
> return ((u64)cap_val_h << SEC_ALG_BITMAP_SHIFT) | (u64)cap_val_l;
> }
>
> -static const struct kernel_param_ops sec_uacce_mode_ops = {
> - .set = uacce_mode_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sec_uacce_mode_ops, uacce_mode_set,
> + param_get_int);
>
> /*
> * uacce_mode = 0 means sec only register to crypto,
> diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c
> index 70adde049b53..8f8d57420fb4 100644
> --- a/drivers/crypto/hisilicon/zip/zip_crypto.c
> +++ b/drivers/crypto/hisilicon/zip/zip_crypto.c
> @@ -108,10 +108,7 @@ static int sgl_sge_nr_set(const char *val, const struct kernel_param *kp)
> return param_set_ushort(val, kp);
> }
>
> -static const struct kernel_param_ops sgl_sge_nr_ops = {
> - .set = sgl_sge_nr_set,
> - .get = param_get_ushort,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sgl_sge_nr_ops, sgl_sge_nr_set, param_get_ushort);
>
> static u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
> module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
> diff --git a/drivers/crypto/hisilicon/zip/zip_main.c b/drivers/crypto/hisilicon/zip/zip_main.c
> index 44df9c859bd8..e07d0cf8eca8 100644
> --- a/drivers/crypto/hisilicon/zip/zip_main.c
> +++ b/drivers/crypto/hisilicon/zip/zip_main.c
> @@ -394,10 +394,7 @@ static int perf_mode_set(const char *val, const struct kernel_param *kp)
> return param_set_int(val, kp);
> }
>
> -static const struct kernel_param_ops zip_com_perf_ops = {
> - .set = perf_mode_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(zip_com_perf_ops, perf_mode_set, param_get_int);
>
> /*
> * perf_mode = 0 means enable high compression rate mode,
> @@ -408,10 +405,8 @@ static u32 perf_mode = HZIP_HIGH_COMP_RATE;
> module_param_cb(perf_mode, &zip_com_perf_ops, &perf_mode, 0444);
> MODULE_PARM_DESC(perf_mode, "ZIP high perf mode 0(default), 1(enable)");
>
> -static const struct kernel_param_ops zip_uacce_mode_ops = {
> - .set = uacce_mode_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(zip_uacce_mode_ops, uacce_mode_set,
> + param_get_int);
>
> /*
> * uacce_mode = 0 means zip only register to crypto,
> @@ -429,19 +424,13 @@ static int pf_q_num_set(const char *val, const struct kernel_param *kp)
> return hisi_qm_q_num_set(val, kp, PCI_DEVICE_ID_HUAWEI_ZIP_PF);
> }
>
> -static const struct kernel_param_ops pf_q_num_ops = {
> - .set = pf_q_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(pf_q_num_ops, pf_q_num_set, param_get_int);
>
> static u32 pf_q_num = HZIP_PF_DEF_Q_NUM;
> module_param_cb(pf_q_num, &pf_q_num_ops, &pf_q_num, 0444);
> MODULE_PARM_DESC(pf_q_num, "Number of queues in PF(v1 2-4096, v2 2-1024)");
>
> -static const struct kernel_param_ops vfs_num_ops = {
> - .set = vfs_num_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vfs_num_ops, vfs_num_set, param_get_int);
>
> static u32 vfs_num;
> module_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444);
> diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
> index df38681a1ff4..a7bddadcc52d 100644
> --- a/drivers/dma/dmatest.c
> +++ b/drivers/dma/dmatest.c
> @@ -154,20 +154,15 @@ static struct dmatest_info {
>
> static int dmatest_run_set(const char *val, const struct kernel_param *kp);
> static int dmatest_run_get(char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops run_ops = {
> - .set = dmatest_run_set,
> - .get = dmatest_run_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(run_ops, dmatest_run_set, dmatest_run_get);
> static bool dmatest_run;
> module_param_cb(run, &run_ops, &dmatest_run, 0644);
> MODULE_PARM_DESC(run, "Run the test (default: false)");
>
> static int dmatest_chan_set(const char *val, const struct kernel_param *kp);
> static int dmatest_chan_get(char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops multi_chan_ops = {
> - .set = dmatest_chan_set,
> - .get = dmatest_chan_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(multi_chan_ops, dmatest_chan_set,
> + dmatest_chan_get);
>
> static char test_channel[20];
> static struct kparam_string newchan_kps = {
> @@ -178,9 +173,7 @@ module_param_cb(channel, &multi_chan_ops, &newchan_kps, 0644);
> MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
>
> static int dmatest_test_list_get(char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops test_list_ops = {
> - .get = dmatest_test_list_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(test_list_ops, NULL, dmatest_test_list_get);
> module_param_cb(test_list, &test_list_ops, NULL, 0444);
> MODULE_PARM_DESC(test_list, "Print current test list");
>
> @@ -292,10 +285,7 @@ static int dmatest_wait_get(char *val, const struct kernel_param *kp)
> return param_get_bool(val, kp);
> }
>
> -static const struct kernel_param_ops wait_ops = {
> - .get = dmatest_wait_get,
> - .set = param_set_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(wait_ops, param_set_bool, dmatest_wait_get);
> module_param_cb(wait, &wait_ops, &wait, 0444);
> MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
>
> diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
> index 63df35444214..ab05e58faaa8 100644
> --- a/drivers/edac/i10nm_base.c
> +++ b/drivers/edac/i10nm_base.c
> @@ -1284,10 +1284,8 @@ static int set_decoding_via_mca(const char *buf, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops decoding_via_mca_param_ops = {
> - .set = set_decoding_via_mca,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(decoding_via_mca_param_ops, set_decoding_via_mca,
> + param_get_int);
>
> module_param_cb(decoding_via_mca, &decoding_via_mca_param_ops, &decoding_via_mca, 0644);
> MODULE_PARM_DESC(decoding_via_mca, "decoding_via_mca: 0=off(default), 1=enable");
> diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
> index a253b6144945..fd0f3579fd54 100644
> --- a/drivers/firmware/efi/efi-pstore.c
> +++ b/drivers/firmware/efi/efi-pstore.c
> @@ -43,10 +43,8 @@ static int efi_pstore_disable_set(const char *val, const struct kernel_param *kp
> return 0;
> }
>
> -static const struct kernel_param_ops pstore_disable_ops = {
> - .set = efi_pstore_disable_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(pstore_disable_ops, efi_pstore_disable_set,
> + param_get_bool);
>
> module_param_cb(pstore_disable, &pstore_disable_ops, &pstore_disable, 0644);
> __MODULE_PARM_TYPE(pstore_disable, "bool");
> diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
> index 9b06a69d3a6d..ef57df53e087 100644
> --- a/drivers/firmware/qcom/qcom_scm.c
> +++ b/drivers/firmware/qcom/qcom_scm.c
> @@ -2725,10 +2725,8 @@ static int set_download_mode(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops download_mode_param_ops = {
> - .get = get_download_mode,
> - .set = set_download_mode,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(download_mode_param_ops, set_download_mode,
> + get_download_mode);
>
> module_param_cb(download_mode, &download_mode_param_ops, NULL, 0644);
> MODULE_PARM_DESC(download_mode, "download mode: off/0/N for no dump mode, full/on/1/Y for full dump mode, mini for minidump mode and full,mini for both full and minidump mode together are acceptable values");
> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> index 87a5421bc7d5..c87a5449ba8c 100644
> --- a/drivers/firmware/qemu_fw_cfg.c
> +++ b/drivers/firmware/qemu_fw_cfg.c
> @@ -897,10 +897,8 @@ static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops fw_cfg_cmdline_param_ops = {
> - .set = fw_cfg_cmdline_set,
> - .get = fw_cfg_cmdline_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(fw_cfg_cmdline_param_ops, fw_cfg_cmdline_set,
> + fw_cfg_cmdline_get);
>
> device_param_cb(ioport, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);
> device_param_cb(mmio, &fw_cfg_cmdline_param_ops, NULL, S_IRUSR);
> diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c
> index d6d3b8d85dea..c35d1adf2ce3 100644
> --- a/drivers/gpu/drm/drm_panic.c
> +++ b/drivers/gpu/drm/drm_panic.c
> @@ -847,10 +847,8 @@ static int drm_panic_type_get(char *buffer, const struct kernel_param *kp)
> drm_panic_type_map[drm_panic_type]);
> }
>
> -static const struct kernel_param_ops drm_panic_ops = {
> - .set = drm_panic_type_set,
> - .get = drm_panic_type_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(drm_panic_ops, drm_panic_type_set,
> + drm_panic_type_get);
>
> module_param_cb(panic_screen, &drm_panic_ops, NULL, 0644);
> MODULE_PARM_DESC(panic_screen,
> diff --git a/drivers/gpu/drm/i915/i915_mitigations.c b/drivers/gpu/drm/i915/i915_mitigations.c
> index def7302ef7fe..6061eae84e9c 100644
> --- a/drivers/gpu/drm/i915/i915_mitigations.c
> +++ b/drivers/gpu/drm/i915/i915_mitigations.c
> @@ -124,10 +124,7 @@ static int mitigations_get(char *buffer, const struct kernel_param *kp)
> return count;
> }
>
> -static const struct kernel_param_ops ops = {
> - .set = mitigations_set,
> - .get = mitigations_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ops, mitigations_set, mitigations_get);
>
> module_param_cb_unsafe(mitigations, &ops, NULL, 0600);
> MODULE_PARM_DESC(mitigations,
> diff --git a/drivers/gpu/drm/imagination/pvr_fw_trace.c b/drivers/gpu/drm/imagination/pvr_fw_trace.c
> index 6193811ef7be..2df7274e21a8 100644
> --- a/drivers/gpu/drm/imagination/pvr_fw_trace.c
> +++ b/drivers/gpu/drm/imagination/pvr_fw_trace.c
> @@ -71,10 +71,8 @@ pvr_fw_trace_init_mask_set(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
> - .set = pvr_fw_trace_init_mask_set,
> - .get = param_get_hexint,
> -};
> +DEFINE_KERNEL_PARAM_OPS(pvr_fw_trace_init_mask_ops, pvr_fw_trace_init_mask_set,
> + param_get_hexint);
>
> param_check_hexint(init_fw_trace_mask, &pvr_fw_trace_init_mask);
> module_param_cb(init_fw_trace_mask, &pvr_fw_trace_init_mask_ops, &pvr_fw_trace_init_mask, 0600);
> diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c
> index ad027c45f162..271048bdf7fc 100644
> --- a/drivers/hid/hid-cougar.c
> +++ b/drivers/hid/hid-cougar.c
> @@ -314,10 +314,8 @@ static int cougar_param_set_g6_is_space(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops cougar_g6_is_space_ops = {
> - .set = cougar_param_set_g6_is_space,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(cougar_g6_is_space_ops,
> + cougar_param_set_g6_is_space, param_get_bool);
> module_param_cb(g6_is_space, &cougar_g6_is_space_ops, &g6_is_space, 0644);
>
> static const struct hid_device_id cougar_id_table[] = {
> diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
> index 197126d6e081..962ed60492ea 100644
> --- a/drivers/hid/hid-steam.c
> +++ b/drivers/hid/hid-steam.c
> @@ -1840,10 +1840,8 @@ static int steam_param_set_lizard_mode(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops steam_lizard_mode_ops = {
> - .set = steam_param_set_lizard_mode,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(steam_lizard_mode_ops,
> + steam_param_set_lizard_mode, param_get_bool);
>
> module_param_cb(lizard_mode, &steam_lizard_mode_ops, &lizard_mode, 0644);
> MODULE_PARM_DESC(lizard_mode,
> diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
> index c7259cc39013..5b9b0b38b419 100644
> --- a/drivers/infiniband/hw/hfi1/driver.c
> +++ b/drivers/infiniband/hw/hfi1/driver.c
> @@ -42,10 +42,7 @@ MODULE_PARM_DESC(cu, "Credit return units");
> unsigned long hfi1_cap_mask = HFI1_CAP_MASK_DEFAULT;
> static int hfi1_caps_set(const char *val, const struct kernel_param *kp);
> static int hfi1_caps_get(char *buffer, const struct kernel_param *kp);
> -static const struct kernel_param_ops cap_ops = {
> - .set = hfi1_caps_set,
> - .get = hfi1_caps_get
> -};
> +static DEFINE_KERNEL_PARAM_OPS(cap_ops, hfi1_caps_set, hfi1_caps_get);
> module_param_cb(cap_mask, &cap_ops, &hfi1_cap_mask, S_IWUSR | S_IRUGO);
> MODULE_PARM_DESC(cap_mask, "Bit mask of enabled/disabled HW features");
>
> diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
> index 7df441685780..758e527ca7c4 100644
> --- a/drivers/infiniband/ulp/iser/iscsi_iser.c
> +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
> @@ -90,10 +90,8 @@ module_param_named(debug_level, iser_debug_level, int, S_IRUGO | S_IWUSR);
> MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)");
>
> static int iscsi_iser_set(const char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops iscsi_iser_size_ops = {
> - .set = iscsi_iser_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(iscsi_iser_size_ops, iscsi_iser_set,
> + param_get_uint);
>
> static unsigned int iscsi_max_lun = 512;
> module_param_cb(max_lun, &iscsi_iser_size_ops, &iscsi_max_lun, S_IRUGO);
> diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
> index 348005e71891..bd91900a0ebf 100644
> --- a/drivers/infiniband/ulp/isert/ib_isert.c
> +++ b/drivers/infiniband/ulp/isert/ib_isert.c
> @@ -30,10 +30,8 @@ MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:0)");
>
> static int isert_sg_tablesize_set(const char *val,
> const struct kernel_param *kp);
> -static const struct kernel_param_ops sg_tablesize_ops = {
> - .set = isert_sg_tablesize_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(sg_tablesize_ops, isert_sg_tablesize_set,
> + param_get_int);
>
> static int isert_sg_tablesize = ISCSI_ISER_MIN_SG_TABLESIZE;
> module_param_cb(sg_tablesize, &sg_tablesize_ops, &isert_sg_tablesize, 0644);
> diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
> index b58868e1cf11..a81515f52a4f 100644
> --- a/drivers/infiniband/ulp/srp/ib_srp.c
> +++ b/drivers/infiniband/ulp/srp/ib_srp.c
> @@ -195,10 +195,7 @@ static int srp_tmo_set(const char *val, const struct kernel_param *kp)
> return res;
> }
>
> -static const struct kernel_param_ops srp_tmo_ops = {
> - .get = srp_tmo_get,
> - .set = srp_tmo_set,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(srp_tmo_ops, srp_tmo_set, srp_tmo_get);
>
> static inline struct srp_target_port *host_to_target(struct Scsi_Host *host)
> {
> diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
> index 8db2dca84975..8b4ef7e163d3 100644
> --- a/drivers/input/misc/ati_remote2.c
> +++ b/drivers/input/misc/ati_remote2.c
> @@ -89,19 +89,16 @@ static int ati_remote2_get_mode_mask(char *buffer,
>
> static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK;
> #define param_check_channel_mask(name, p) __param_check(name, p, unsigned int)
> -static const struct kernel_param_ops param_ops_channel_mask = {
> - .set = ati_remote2_set_channel_mask,
> - .get = ati_remote2_get_channel_mask,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_channel_mask,
> + ati_remote2_set_channel_mask,
> + ati_remote2_get_channel_mask);
> module_param(channel_mask, channel_mask, 0644);
> MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>");
>
> static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK;
> #define param_check_mode_mask(name, p) __param_check(name, p, unsigned int)
> -static const struct kernel_param_ops param_ops_mode_mask = {
> - .set = ati_remote2_set_mode_mask,
> - .get = ati_remote2_get_mode_mask,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_mode_mask, ati_remote2_set_mode_mask,
> + ati_remote2_get_mode_mask);
> module_param(mode_mask, mode_mask, 0644);
> MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>");
>
> diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
> index 6ab5f1d96eae..f9ebb1fd0b6f 100644
> --- a/drivers/input/mouse/psmouse-base.c
> +++ b/drivers/input/mouse/psmouse-base.c
> @@ -45,10 +45,8 @@ MODULE_LICENSE("GPL");
> static unsigned int psmouse_max_proto = PSMOUSE_AUTO;
> static int psmouse_set_maxproto(const char *val, const struct kernel_param *);
> static int psmouse_get_maxproto(char *buffer, const struct kernel_param *kp);
> -static const struct kernel_param_ops param_ops_proto_abbrev = {
> - .set = psmouse_set_maxproto,
> - .get = psmouse_get_maxproto,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_proto_abbrev, psmouse_set_maxproto,
> + psmouse_get_maxproto);
> #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
> module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644);
> MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches.");
> diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> index 31b4ac3b48c1..2338cab7fef9 100644
> --- a/drivers/media/usb/uvc/uvc_driver.c
> +++ b/drivers/media/usb/uvc/uvc_driver.c
> @@ -2488,10 +2488,8 @@ static int param_set_nodrop(const char *val, const struct kernel_param *kp)
> return param_set_bool(val, kp);
> }
>
> -static const struct kernel_param_ops param_ops_nodrop = {
> - .set = param_set_nodrop,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_nodrop, param_set_nodrop,
> + param_get_uint);
>
> param_check_uint(nodrop, &uvc_no_drop_param);
> module_param_cb(nodrop, ¶m_ops_nodrop, &uvc_no_drop_param, 0644);
> diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
> index 21e8ad0a7444..6e40c14be51e 100644
> --- a/drivers/misc/lis3lv02d/lis3lv02d.c
> +++ b/drivers/misc/lis3lv02d/lis3lv02d.c
> @@ -103,10 +103,7 @@ static int param_set_axis(const char *val, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops param_ops_axis = {
> - .set = param_set_axis,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_axis, param_set_axis, param_get_int);
>
> #define param_check_axis(name, p) param_check_int(name, p)
>
> diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
> index d5aec72ecdce..e566d94d5f5c 100644
> --- a/drivers/net/wireless/ath/wil6210/main.c
> +++ b/drivers/net/wireless/ath/wil6210/main.c
> @@ -62,10 +62,7 @@ static int mtu_max_set(const char *val, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops mtu_max_ops = {
> - .set = mtu_max_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(mtu_max_ops, mtu_max_set, param_get_uint);
>
> module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, 0444);
> MODULE_PARM_DESC(mtu_max, " Max MTU value.");
> @@ -91,10 +88,7 @@ static int ring_order_set(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops ring_order_ops = {
> - .set = ring_order_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ring_order_ops, ring_order_set, param_get_uint);
>
> module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, 0444);
> MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
> diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
> index 263161cb8ac0..f7362377e427 100644
> --- a/drivers/nvme/host/multipath.c
> +++ b/drivers/nvme/host/multipath.c
> @@ -30,10 +30,8 @@ static int multipath_param_set(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops multipath_param_ops = {
> - .set = multipath_param_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(multipath_param_ops, multipath_param_set,
> + param_get_bool);
>
> module_param_cb(multipath, &multipath_param_ops, &multipath, 0444);
> MODULE_PARM_DESC(multipath,
> @@ -55,10 +53,8 @@ static int multipath_always_on_set(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops multipath_always_on_ops = {
> - .set = multipath_always_on_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(multipath_always_on_ops, multipath_always_on_set,
> + param_get_bool);
>
> module_param_cb(multipath_always_on, &multipath_always_on_ops,
> &multipath_always_on, 0444);
> diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
> index 9fd04cd7c5cb..c77e9b848d03 100644
> --- a/drivers/nvme/host/pci.c
> +++ b/drivers/nvme/host/pci.c
> @@ -100,10 +100,8 @@ MODULE_PARM_DESC(sgl_threshold,
> #define NVME_PCI_MIN_QUEUE_SIZE 2
> #define NVME_PCI_MAX_QUEUE_SIZE 4095
> static int io_queue_depth_set(const char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops io_queue_depth_ops = {
> - .set = io_queue_depth_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(io_queue_depth_ops, io_queue_depth_set,
> + param_get_uint);
>
> static unsigned int io_queue_depth = 1024;
> module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644);
> @@ -232,10 +230,8 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
> }
>
> static char quirks_param[128];
> -static const struct kernel_param_ops quirks_param_ops = {
> - .set = quirks_param_set,
> - .get = param_get_string,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(quirks_param_ops, quirks_param_set,
> + param_get_string);
>
> static struct kparam_string quirks_param_string = {
> .maxlen = sizeof(quirks_param),
> @@ -257,10 +253,8 @@ static int io_queue_count_set(const char *val, const struct kernel_param *kp)
> return param_set_uint(val, kp);
> }
>
> -static const struct kernel_param_ops io_queue_count_ops = {
> - .set = io_queue_count_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(io_queue_count_ops, io_queue_count_set,
> + param_get_uint);
>
> static unsigned int write_queues;
> module_param_cb(write_queues, &io_queue_count_ops, &write_queues, 0644);
> diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
> index e6e2c3f9afdf..dc544813300f 100644
> --- a/drivers/nvme/target/rdma.c
> +++ b/drivers/nvme/target/rdma.c
> @@ -147,10 +147,7 @@ module_param_named(use_srq, nvmet_rdma_use_srq, bool, 0444);
> MODULE_PARM_DESC(use_srq, "Use shared receive queue.");
>
> static int srq_size_set(const char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops srq_size_ops = {
> - .set = srq_size_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(srq_size_ops, srq_size_set, param_get_int);
>
> static int nvmet_rdma_srq_size = 1024;
> module_param_cb(srq_size, &srq_size_ops, &nvmet_rdma_srq_size, 0644);
> diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
> index 164a564ba3b4..2f336cd7e559 100644
> --- a/drivers/nvme/target/tcp.c
> +++ b/drivers/nvme/target/tcp.c
> @@ -46,10 +46,7 @@ static int set_params(const char *str, const struct kernel_param *kp)
> return param_store_val(str, kp->arg, 0, INT_MAX);
> }
>
> -static const struct kernel_param_ops set_param_ops = {
> - .set = set_params,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(set_param_ops, set_params, param_get_int);
>
> /* Define the socket priority to use for connections were it is desirable
> * that the NIC consider performing optimized packet processing or filtering.
> diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
> index 5ce5ad3efe69..bd59c3f3f2c5 100644
> --- a/drivers/platform/x86/acerhdf.c
> +++ b/drivers/platform/x86/acerhdf.c
> @@ -762,10 +762,7 @@ static int interval_set_uint(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops interval_ops = {
> - .set = interval_set_uint,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(interval_ops, interval_set_uint, param_get_uint);
>
> module_param_cb(interval, &interval_ops, &interval, 0000);
> MODULE_PARM_DESC(interval, "Polling interval of temperature check");
> diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
> index 45f0e39b8c2d..09829ee1a49d 100644
> --- a/drivers/power/supply/bq27xxx_battery.c
> +++ b/drivers/power/supply/bq27xxx_battery.c
> @@ -1133,10 +1133,8 @@ static int poll_interval_param_set(const char *val, const struct kernel_param *k
> return ret;
> }
>
> -static const struct kernel_param_ops param_ops_poll_interval = {
> - .get = param_get_uint,
> - .set = poll_interval_param_set,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_poll_interval, poll_interval_param_set,
> + param_get_uint);
>
> static unsigned int poll_interval = 360;
> module_param_cb(poll_interval, ¶m_ops_poll_interval, &poll_interval, 0644);
> diff --git a/drivers/power/supply/test_power.c b/drivers/power/supply/test_power.c
> index 2c0e9ad820c0..0bf2bef3383a 100644
> --- a/drivers/power/supply/test_power.c
> +++ b/drivers/power/supply/test_power.c
> @@ -649,60 +649,47 @@ static int param_set_battery_extension(const char *key,
>
> #define param_get_battery_extension param_get_bool
>
> -static const struct kernel_param_ops param_ops_ac_online = {
> - .set = param_set_ac_online,
> - .get = param_get_ac_online,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_ac_online, param_set_ac_online,
> + param_get_ac_online);
>
> -static const struct kernel_param_ops param_ops_usb_online = {
> - .set = param_set_usb_online,
> - .get = param_get_usb_online,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_usb_online, param_set_usb_online,
> + param_get_usb_online);
>
> -static const struct kernel_param_ops param_ops_battery_status = {
> - .set = param_set_battery_status,
> - .get = param_get_battery_status,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_status,
> + param_set_battery_status,
> + param_get_battery_status);
>
> -static const struct kernel_param_ops param_ops_battery_present = {
> - .set = param_set_battery_present,
> - .get = param_get_battery_present,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_present,
> + param_set_battery_present,
> + param_get_battery_present);
>
> -static const struct kernel_param_ops param_ops_battery_technology = {
> - .set = param_set_battery_technology,
> - .get = param_get_battery_technology,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_technology,
> + param_set_battery_technology,
> + param_get_battery_technology);
>
> -static const struct kernel_param_ops param_ops_battery_health = {
> - .set = param_set_battery_health,
> - .get = param_get_battery_health,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_health,
> + param_set_battery_health,
> + param_get_battery_health);
>
> -static const struct kernel_param_ops param_ops_battery_capacity = {
> - .set = param_set_battery_capacity,
> - .get = param_get_battery_capacity,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_capacity,
> + param_set_battery_capacity,
> + param_get_battery_capacity);
>
> -static const struct kernel_param_ops param_ops_battery_voltage = {
> - .set = param_set_battery_voltage,
> - .get = param_get_battery_voltage,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_voltage,
> + param_set_battery_voltage,
> + param_get_battery_voltage);
>
> -static const struct kernel_param_ops param_ops_battery_charge_counter = {
> - .set = param_set_battery_charge_counter,
> - .get = param_get_battery_charge_counter,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_charge_counter,
> + param_set_battery_charge_counter,
> + param_get_battery_charge_counter);
>
> -static const struct kernel_param_ops param_ops_battery_current = {
> - .set = param_set_battery_current,
> - .get = param_get_battery_current,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_current,
> + param_set_battery_current,
> + param_get_battery_current);
>
> -static const struct kernel_param_ops param_ops_battery_extension = {
> - .set = param_set_battery_extension,
> - .get = param_get_battery_extension,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_battery_extension,
> + param_set_battery_extension,
> + param_get_battery_extension);
>
> #define param_check_ac_online(name, p) __param_check(name, p, void);
> #define param_check_usb_online(name, p) __param_check(name, p, void);
> diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
> index 2b4b2a1a8e44..c075b567f84e 100644
> --- a/drivers/scsi/sg.c
> +++ b/drivers/scsi/sg.c
> @@ -1644,10 +1644,8 @@ static int def_reserved_size_set(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops def_reserved_size_ops = {
> - .set = def_reserved_size_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(def_reserved_size_ops, def_reserved_size_set,
> + param_get_int);
>
> module_param_cb(def_reserved_size, &def_reserved_size_ops, &def_reserved_size,
> S_IRUGO | S_IWUSR);
> diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
> index edc2afd5f4ee..676a12b44e88 100644
> --- a/drivers/target/target_core_user.c
> +++ b/drivers/target/target_core_user.c
> @@ -255,10 +255,9 @@ static int tcmu_get_global_max_data_area(char *buffer,
> return sprintf(buffer, "%d\n", TCMU_PAGES_TO_MBS(tcmu_global_max_pages));
> }
>
> -static const struct kernel_param_ops tcmu_global_max_data_area_op = {
> - .set = tcmu_set_global_max_data_area,
> - .get = tcmu_get_global_max_data_area,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(tcmu_global_max_data_area_op,
> + tcmu_set_global_max_data_area,
> + tcmu_get_global_max_data_area);
>
> module_param_cb(global_max_data_area_mb, &tcmu_global_max_data_area_op, NULL,
> S_IWUSR | S_IRUGO);
> @@ -292,10 +291,8 @@ static int tcmu_set_block_netlink(const char *str,
> return 0;
> }
>
> -static const struct kernel_param_ops tcmu_block_netlink_op = {
> - .set = tcmu_set_block_netlink,
> - .get = tcmu_get_block_netlink,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(tcmu_block_netlink_op, tcmu_set_block_netlink,
> + tcmu_get_block_netlink);
>
> module_param_cb(block_netlink, &tcmu_block_netlink_op, NULL, S_IWUSR | S_IRUGO);
> MODULE_PARM_DESC(block_netlink, "Block new netlink commands.");
> diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_soc_slider.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_soc_slider.c
> index 91f291627132..68275c3f2c9b 100644
> --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_soc_slider.c
> +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_soc_slider.c
> @@ -83,10 +83,8 @@ static int slider_def_balance_get(char *buf, const struct kernel_param *kp)
> return sysfs_emit(buf, "%02x\n", slider_values[SOC_POWER_SLIDER_BALANCE]);
> }
>
> -static const struct kernel_param_ops slider_def_balance_ops = {
> - .set = slider_def_balance_set,
> - .get = slider_def_balance_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(slider_def_balance_ops, slider_def_balance_set,
> + slider_def_balance_get);
>
> module_param_cb(slider_balance, &slider_def_balance_ops, NULL, 0644);
> MODULE_PARM_DESC(slider_balance, "Set slider default value for balance");
> @@ -117,10 +115,8 @@ static int slider_def_offset_get(char *buf, const struct kernel_param *kp)
> return sysfs_emit(buf, "%02x\n", slider_offset);
> }
>
> -static const struct kernel_param_ops slider_offset_ops = {
> - .set = slider_def_offset_set,
> - .get = slider_def_offset_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(slider_offset_ops, slider_def_offset_set,
> + slider_def_offset_get);
>
> /*
> * To enhance power efficiency dynamically, the firmware can optionally
> diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c
> index ccf380da12f2..98fbc6892714 100644
> --- a/drivers/thermal/intel/intel_powerclamp.c
> +++ b/drivers/thermal/intel/intel_powerclamp.c
> @@ -112,10 +112,7 @@ static int duration_get(char *buf, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops duration_ops = {
> - .set = duration_set,
> - .get = duration_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(duration_ops, duration_set, duration_get);
>
> module_param_cb(duration, &duration_ops, NULL, 0644);
> MODULE_PARM_DESC(duration, "forced idle time for each attempt in msec.");
> @@ -203,10 +200,7 @@ static int cpumask_get(char *buf, const struct kernel_param *kp)
> return cpumap_print_to_pagebuf(false, buf, idle_injection_cpu_mask);
> }
>
> -static const struct kernel_param_ops cpumask_ops = {
> - .set = cpumask_set,
> - .get = cpumask_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(cpumask_ops, cpumask_set, cpumask_get);
>
> module_param_cb(cpumask, &cpumask_ops, NULL, 0644);
> MODULE_PARM_DESC(cpumask, "Mask of CPUs to use for idle injection.");
> @@ -252,10 +246,7 @@ static int max_idle_set(const char *arg, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops max_idle_ops = {
> - .set = max_idle_set,
> - .get = param_get_byte,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(max_idle_ops, max_idle_set, param_get_byte);
>
> module_param_cb(max_idle, &max_idle_ops, &max_idle, 0644);
> MODULE_PARM_DESC(max_idle, "maximum injected idle time to the total CPU time ratio in percent range:1-100");
> @@ -299,10 +290,7 @@ static int window_size_set(const char *arg, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops window_size_ops = {
> - .set = window_size_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(window_size_ops, window_size_set, param_get_int);
>
> module_param_cb(window_size, &window_size_ops, &window_size, 0644);
> MODULE_PARM_DESC(window_size, "sliding window in number of clamping cycles\n"
> diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
> index 37db8a3e5158..29612a4a32cb 100644
> --- a/drivers/tty/hvc/hvc_iucv.c
> +++ b/drivers/tty/hvc/hvc_iucv.c
> @@ -1290,10 +1290,8 @@ static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp)
>
> #define param_check_vmidfilter(name, p) __param_check(name, p, void)
>
> -static const struct kernel_param_ops param_ops_vmidfilter = {
> - .set = param_set_vmidfilter,
> - .get = param_get_vmidfilter,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_vmidfilter, param_set_vmidfilter,
> + param_get_vmidfilter);
>
> /**
> * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
> diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
> index c2e4b31b699a..c6279c496279 100644
> --- a/drivers/tty/sysrq.c
> +++ b/drivers/tty/sysrq.c
> @@ -1074,10 +1074,8 @@ static int sysrq_reset_seq_param_set(const char *buffer,
> return 0;
> }
>
> -static const struct kernel_param_ops param_ops_sysrq_reset_seq = {
> - .get = param_get_ushort,
> - .set = sysrq_reset_seq_param_set,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_sysrq_reset_seq,
> + sysrq_reset_seq_param_set, param_get_ushort);
>
> #define param_check_sysrq_reset_seq(name, p) \
> __param_check(name, p, unsigned short)
> diff --git a/drivers/ufs/core/ufs-fault-injection.c b/drivers/ufs/core/ufs-fault-injection.c
> index 55db38e75cc4..7d2873da7dc5 100644
> --- a/drivers/ufs/core/ufs-fault-injection.c
> +++ b/drivers/ufs/core/ufs-fault-injection.c
> @@ -11,10 +11,7 @@
> static int ufs_fault_get(char *buffer, const struct kernel_param *kp);
> static int ufs_fault_set(const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops ufs_fault_ops = {
> - .get = ufs_fault_get,
> - .set = ufs_fault_set,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ufs_fault_ops, ufs_fault_set, ufs_fault_get);
>
> enum { FAULT_INJ_STR_SIZE = 80 };
>
> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
> index c1b1d67a1ddc..83100aad2a97 100644
> --- a/drivers/ufs/core/ufs-mcq.c
> +++ b/drivers/ufs/core/ufs-mcq.c
> @@ -43,10 +43,8 @@ static int rw_queue_count_set(const char *val, const struct kernel_param *kp)
> num_possible_cpus());
> }
>
> -static const struct kernel_param_ops rw_queue_count_ops = {
> - .set = rw_queue_count_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(rw_queue_count_ops, rw_queue_count_set,
> + param_get_uint);
>
> static unsigned int rw_queues;
> module_param_cb(rw_queues, &rw_queue_count_ops, &rw_queues, 0644);
> @@ -59,10 +57,8 @@ static int read_queue_count_set(const char *val, const struct kernel_param *kp)
> num_possible_cpus());
> }
>
> -static const struct kernel_param_ops read_queue_count_ops = {
> - .set = read_queue_count_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(read_queue_count_ops, read_queue_count_set,
> + param_get_uint);
>
> static unsigned int read_queues;
> module_param_cb(read_queues, &read_queue_count_ops, &read_queues, 0644);
> @@ -75,10 +71,8 @@ static int poll_queue_count_set(const char *val, const struct kernel_param *kp)
> num_possible_cpus());
> }
>
> -static const struct kernel_param_ops poll_queue_count_ops = {
> - .set = poll_queue_count_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(poll_queue_count_ops, poll_queue_count_set,
> + param_get_uint);
>
> static unsigned int poll_queues = 1;
> module_param_cb(poll_queues, &poll_queue_count_ops, &poll_queues, 0644);
> diff --git a/drivers/ufs/core/ufs-txeq.c b/drivers/ufs/core/ufs-txeq.c
> index b2dc89124353..3bdd87b434ad 100644
> --- a/drivers/ufs/core/ufs-txeq.c
> +++ b/drivers/ufs/core/ufs-txeq.c
> @@ -23,10 +23,7 @@ static int txeq_gear_set(const char *val, const struct kernel_param *kp)
> return param_set_uint_minmax(val, kp, UFS_HS_G1, UFS_HS_GEAR_MAX);
> }
>
> -static const struct kernel_param_ops txeq_gear_ops = {
> - .set = txeq_gear_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(txeq_gear_ops, txeq_gear_set, param_get_uint);
>
> static unsigned int adaptive_txeq_gear = UFS_HS_G6;
> module_param_cb(adaptive_txeq_gear, &txeq_gear_ops, &adaptive_txeq_gear, 0644);
> diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
> index 4805e40ed4d7..4e930710d9a6 100644
> --- a/drivers/ufs/core/ufshcd.c
> +++ b/drivers/ufs/core/ufshcd.c
> @@ -128,10 +128,8 @@ static int uic_cmd_timeout_set(const char *val, const struct kernel_param *kp)
> UIC_CMD_TIMEOUT_MAX);
> }
>
> -static const struct kernel_param_ops uic_cmd_timeout_ops = {
> - .set = uic_cmd_timeout_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(uic_cmd_timeout_ops, uic_cmd_timeout_set,
> + param_get_uint);
>
> module_param_cb(uic_cmd_timeout, &uic_cmd_timeout_ops, &uic_cmd_timeout, 0644);
> MODULE_PARM_DESC(uic_cmd_timeout,
> @@ -145,10 +143,8 @@ static int dev_cmd_timeout_set(const char *val, const struct kernel_param *kp)
> QUERY_REQ_TIMEOUT_MAX);
> }
>
> -static const struct kernel_param_ops dev_cmd_timeout_ops = {
> - .set = dev_cmd_timeout_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(dev_cmd_timeout_ops, dev_cmd_timeout_set,
> + param_get_uint);
>
> module_param_cb(dev_cmd_timeout, &dev_cmd_timeout_ops, &dev_cmd_timeout, 0644);
> MODULE_PARM_DESC(dev_cmd_timeout,
> diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
> index 0ffdaefba508..d52ecc886925 100644
> --- a/drivers/usb/core/quirks.c
> +++ b/drivers/usb/core/quirks.c
> @@ -160,10 +160,8 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops quirks_param_ops = {
> - .set = quirks_param_set,
> - .get = param_get_string,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(quirks_param_ops, quirks_param_set,
> + param_get_string);
>
> static struct kparam_string quirks_param_string = {
> .maxlen = sizeof(quirks_param),
> diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c
> index 4974bee6049a..e34717e553da 100644
> --- a/drivers/usb/gadget/legacy/serial.c
> +++ b/drivers/usb/gadget/legacy/serial.c
> @@ -121,10 +121,7 @@ static int enable_set(const char *s, const struct kernel_param *kp)
> return ret;
> }
>
> -static const struct kernel_param_ops enable_ops = {
> - .set = enable_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enable_ops, enable_set, param_get_bool);
>
> module_param_cb(enable, &enable_ops, &enable, 0644);
>
> diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
> index fa83fe0defe2..71dd623b95c9 100644
> --- a/drivers/usb/storage/usb.c
> +++ b/drivers/usb/storage/usb.c
> @@ -158,10 +158,7 @@ static int delay_use_get(char *s, const struct kernel_param *kp)
> return format_delay_ms(delay_ms, 3, "ms", s, PAGE_SIZE);
> }
>
> -static const struct kernel_param_ops delay_use_ops = {
> - .set = delay_use_set,
> - .get = delay_use_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(delay_use_ops, delay_use_set, delay_use_get);
> module_param_cb(delay_use, &delay_use_ops, &delay_use, 0644);
> MODULE_PARM_DESC(delay_use, "time to delay before using a new device");
>
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 9a1253b9d8c5..fd52f2213e27 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -87,10 +87,9 @@ static int vhost_scsi_get_inline_sg_cnt(char *buf,
> return sprintf(buf, "%u\n", vhost_scsi_inline_sg_cnt);
> }
>
> -static const struct kernel_param_ops vhost_scsi_inline_sg_cnt_op = {
> - .get = vhost_scsi_get_inline_sg_cnt,
> - .set = vhost_scsi_set_inline_sg_cnt,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vhost_scsi_inline_sg_cnt_op,
> + vhost_scsi_set_inline_sg_cnt,
> + vhost_scsi_get_inline_sg_cnt);
>
> module_param_cb(inline_sg_cnt, &vhost_scsi_inline_sg_cnt_op, NULL, 0644);
> MODULE_PARM_DESC(inline_sg_cnt, "Set the number of scatterlist entries to pre-allocate. The default is 2048.");
> diff --git a/drivers/virt/nitro_enclaves/ne_misc_dev.c b/drivers/virt/nitro_enclaves/ne_misc_dev.c
> index c91300a73f50..218ddd93f960 100644
> --- a/drivers/virt/nitro_enclaves/ne_misc_dev.c
> +++ b/drivers/virt/nitro_enclaves/ne_misc_dev.c
> @@ -86,10 +86,8 @@ struct ne_devs ne_devs = {
> */
> static int ne_set_kernel_param(const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops ne_cpu_pool_ops = {
> - .get = param_get_string,
> - .set = ne_set_kernel_param,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ne_cpu_pool_ops, ne_set_kernel_param,
> + param_get_string);
>
> static char ne_cpus[NE_CPUS_SIZE];
> static struct kparam_string ne_cpus_arg = {
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 595c2274fbb5..f6df9c76ee81 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -748,10 +748,8 @@ static int vm_cmdline_get(char *buffer, const struct kernel_param *kp)
> return strlen(buffer) + 1;
> }
>
> -static const struct kernel_param_ops vm_cmdline_param_ops = {
> - .set = vm_cmdline_set,
> - .get = vm_cmdline_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(vm_cmdline_param_ops, vm_cmdline_set,
> + vm_cmdline_get);
>
> device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR);
>
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index c05fbd4237f8..dec8024b8ac7 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -1684,10 +1684,8 @@ static int param_set_metrics(const char *val, const struct kernel_param *kp)
> return 0;
> }
>
> -static const struct kernel_param_ops param_ops_metrics = {
> - .set = param_set_metrics,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_metrics, param_set_metrics,
> + param_get_bool);
>
> bool disable_send_metrics = false;
> module_param_cb(disable_send_metrics, ¶m_ops_metrics, &disable_send_metrics, 0644);
> @@ -1695,9 +1693,7 @@ MODULE_PARM_DESC(disable_send_metrics, "Enable sending perf metrics to ceph clus
>
> /* for both v1 and v2 syntax */
> static bool mount_support = true;
> -static const struct kernel_param_ops param_ops_mount_syntax = {
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_mount_syntax, NULL, param_get_bool);
> module_param_cb(mount_syntax_v1, ¶m_ops_mount_syntax, &mount_support, 0444);
> module_param_cb(mount_syntax_v2, ¶m_ops_mount_syntax, &mount_support, 0444);
>
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index b658b6baf72f..cc955c9952d1 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -71,10 +71,7 @@ static int inval_wq_set(const char *val, const struct kernel_param *kp)
>
> return 0;
> }
> -static const struct kernel_param_ops inval_wq_ops = {
> - .set = inval_wq_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(inval_wq_ops, inval_wq_set, param_get_uint);
> module_param_cb(inval_wq, &inval_wq_ops, &inval_wq, 0644);
> __MODULE_PARM_TYPE(inval_wq, "uint");
> MODULE_PARM_DESC(inval_wq,
> diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
> index af9be0c5f516..f2fba60dc5ed 100644
> --- a/fs/nfs/namespace.c
> +++ b/fs/nfs/namespace.c
> @@ -372,10 +372,8 @@ static int param_get_nfs_timeout(char *buffer, const struct kernel_param *kp)
> return sysfs_emit(buffer, "%li\n", num);
> }
>
> -static const struct kernel_param_ops param_ops_nfs_timeout = {
> - .set = param_set_nfs_timeout,
> - .get = param_get_nfs_timeout,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_nfs_timeout, param_set_nfs_timeout,
> + param_get_nfs_timeout);
> #define param_check_nfs_timeout(name, p) __param_check(name, p, int)
>
> module_param(nfs_mountpoint_expiry_timeout, nfs_timeout, 0644);
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index 4cd420b14ce3..59d89a18aba6 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -1419,10 +1419,8 @@ static int param_set_portnr(const char *val, const struct kernel_param *kp)
> *((unsigned int *)kp->arg) = num;
> return 0;
> }
> -static const struct kernel_param_ops param_ops_portnr = {
> - .set = param_set_portnr,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_portnr, param_set_portnr,
> + param_get_uint);
> #define param_check_portnr(name, p) __param_check(name, p, unsigned int)
>
> module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index 9a77d8b64ffa..e44f8e18f756 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -36,10 +36,8 @@ static int ubifs_default_version_set(const char *val, const struct kernel_param
> return param_set_int(val, kp);
> }
>
> -static const struct kernel_param_ops ubifs_default_version_ops = {
> - .set = ubifs_default_version_set,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(ubifs_default_version_ops,
> + ubifs_default_version_set, param_get_int);
>
> int ubifs_default_version = UBIFS_FORMAT_VERSION;
> module_param_cb(default_version, &ubifs_default_version_ops, &ubifs_default_version, 0600);
> diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
> index e618bcf75e2d..38ae3b596ef2 100644
> --- a/kernel/locking/locktorture.c
> +++ b/kernel/locking/locktorture.c
> @@ -98,10 +98,8 @@ static bool cpumask_nonempty(cpumask_var_t mask)
> return cpumask_available(mask) && !cpumask_empty(mask);
> }
>
> -static const struct kernel_param_ops lt_bind_ops = {
> - .set = param_set_cpumask,
> - .get = param_get_cpumask,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(lt_bind_ops, param_set_cpumask,
> + param_get_cpumask);
>
> module_param_cb(bind_readers, <_bind_ops, &bind_readers, 0444);
> module_param_cb(bind_writers, <_bind_ops, &bind_writers, 0444);
> diff --git a/kernel/panic.c b/kernel/panic.c
> index 42e5ebde4585..8698374b0d21 100644
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -1214,10 +1214,8 @@ static int panic_print_set(const char *val, const struct kernel_param *kp)
> return param_set_ulong(val, kp);
> }
>
> -static const struct kernel_param_ops panic_print_ops = {
> - .set = panic_print_set,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(panic_print_ops, panic_print_set,
> + param_get_ulong);
> __core_param_cb(panic_print, &panic_print_ops, &panic_print, 0644);
>
> static int __init oops_setup(char *s)
> diff --git a/kernel/params.c b/kernel/params.c
> index 2cbad1f4dd06..e19fff2926bc 100644
> --- a/kernel/params.c
> +++ b/kernel/params.c
> @@ -297,11 +297,8 @@ void param_free_charp(void *arg)
> }
> EXPORT_SYMBOL(param_free_charp);
>
> -const struct kernel_param_ops param_ops_charp = {
> - .set = param_set_charp,
> - .get = param_get_charp,
> - .free = param_free_charp,
> -};
> +DEFINE_KERNEL_PARAM_OPS_FREE(param_ops_charp, param_set_charp, param_get_charp,
> + param_free_charp);
> EXPORT_SYMBOL(param_ops_charp);
>
> /* Actually could be a bool or an int, for historical reasons. */
> @@ -322,11 +319,7 @@ int param_get_bool(char *buffer, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL(param_get_bool);
>
> -const struct kernel_param_ops param_ops_bool = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = param_set_bool,
> - .get = param_get_bool,
> -};
> +DEFINE_KERNEL_PARAM_OPS_NOARG(param_ops_bool, param_set_bool, param_get_bool);
> EXPORT_SYMBOL(param_ops_bool);
>
> int param_set_bool_enable_only(const char *val, const struct kernel_param *kp)
> @@ -353,11 +346,8 @@ int param_set_bool_enable_only(const char *val, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL_GPL(param_set_bool_enable_only);
>
> -const struct kernel_param_ops param_ops_bool_enable_only = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = param_set_bool_enable_only,
> - .get = param_get_bool,
> -};
> +DEFINE_KERNEL_PARAM_OPS_NOARG(param_ops_bool_enable_only,
> + param_set_bool_enable_only, param_get_bool);
> EXPORT_SYMBOL_GPL(param_ops_bool_enable_only);
>
> /* This one must be bool. */
> @@ -381,10 +371,7 @@ int param_get_invbool(char *buffer, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL(param_get_invbool);
>
> -const struct kernel_param_ops param_ops_invbool = {
> - .set = param_set_invbool,
> - .get = param_get_invbool,
> -};
> +DEFINE_KERNEL_PARAM_OPS(param_ops_invbool, param_set_invbool, param_get_invbool);
> EXPORT_SYMBOL(param_ops_invbool);
>
> int param_set_bint(const char *val, const struct kernel_param *kp)
> @@ -403,11 +390,7 @@ int param_set_bint(const char *val, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL(param_set_bint);
>
> -const struct kernel_param_ops param_ops_bint = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = param_set_bint,
> - .get = param_get_int,
> -};
> +DEFINE_KERNEL_PARAM_OPS_NOARG(param_ops_bint, param_set_bint, param_get_int);
> EXPORT_SYMBOL(param_ops_bint);
>
> /* We break the rule and mangle the string. */
> @@ -515,11 +498,8 @@ static void param_array_free(void *arg)
> arr->ops->free(arr->elem + arr->elemsize * i);
> }
>
> -const struct kernel_param_ops param_array_ops = {
> - .set = param_array_set,
> - .get = param_array_get,
> - .free = param_array_free,
> -};
> +DEFINE_KERNEL_PARAM_OPS_FREE(param_array_ops, param_array_set, param_array_get,
> + param_array_free);
> EXPORT_SYMBOL(param_array_ops);
>
> int param_set_copystring(const char *val, const struct kernel_param *kp)
> @@ -544,10 +524,8 @@ int param_get_string(char *buffer, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL(param_get_string);
>
> -const struct kernel_param_ops param_ops_string = {
> - .set = param_set_copystring,
> - .get = param_get_string,
> -};
> +DEFINE_KERNEL_PARAM_OPS(param_ops_string, param_set_copystring,
> + param_get_string);
> EXPORT_SYMBOL(param_ops_string);
>
> /* sysfs output in /sys/modules/XYZ/parameters/ */
> diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
> index af8d07bafe02..aba1e4489447 100644
> --- a/kernel/power/hibernate.c
> +++ b/kernel/power/hibernate.c
> @@ -1528,10 +1528,8 @@ static int hibernate_compressor_param_set(const char *compressor,
> return ret;
> }
>
> -static const struct kernel_param_ops hibernate_compressor_param_ops = {
> - .set = hibernate_compressor_param_set,
> - .get = param_get_string,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(hibernate_compressor_param_ops,
> + hibernate_compressor_param_set, param_get_string);
>
> static struct kparam_string hibernate_compressor_param_string = {
> .maxlen = sizeof(hibernate_compressor),
> diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
> index 55df6d37145e..e675d7f1b4ee 100644
> --- a/kernel/rcu/tree.c
> +++ b/kernel/rcu/tree.c
> @@ -498,15 +498,11 @@ static int param_set_next_fqs_jiffies(const char *val, const struct kernel_param
> return ret;
> }
>
> -static const struct kernel_param_ops first_fqs_jiffies_ops = {
> - .set = param_set_first_fqs_jiffies,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(first_fqs_jiffies_ops,
> + param_set_first_fqs_jiffies, param_get_ulong);
>
> -static const struct kernel_param_ops next_fqs_jiffies_ops = {
> - .set = param_set_next_fqs_jiffies,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(next_fqs_jiffies_ops, param_set_next_fqs_jiffies,
> + param_get_ulong);
>
> module_param_cb(jiffies_till_first_fqs, &first_fqs_jiffies_ops, &jiffies_till_first_fqs, 0644);
> module_param_cb(jiffies_till_next_fqs, &next_fqs_jiffies_ops, &jiffies_till_next_fqs, 0644);
> @@ -3979,10 +3975,8 @@ static int param_get_do_rcu_barrier(char *buffer, const struct kernel_param *kp)
> return sprintf(buffer, "%d\n", atomic_read((atomic_t *)kp->arg));
> }
>
> -static const struct kernel_param_ops do_rcu_barrier_ops = {
> - .set = param_set_do_rcu_barrier,
> - .get = param_get_do_rcu_barrier,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(do_rcu_barrier_ops, param_set_do_rcu_barrier,
> + param_get_do_rcu_barrier);
> static atomic_t do_rcu_barrier;
> module_param_cb(do_rcu_barrier, &do_rcu_barrier_ops, &do_rcu_barrier, 0644);
>
> diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
> index 345aa11b84b2..fcf31e3e4965 100644
> --- a/kernel/sched/ext.c
> +++ b/kernel/sched/ext.c
> @@ -166,20 +166,15 @@ static int set_slice_us(const char *val, const struct kernel_param *kp)
> return param_set_uint_minmax(val, kp, 100, 100 * USEC_PER_MSEC);
> }
>
> -static const struct kernel_param_ops slice_us_param_ops = {
> - .set = set_slice_us,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(slice_us_param_ops, set_slice_us, param_get_uint);
>
> static int set_bypass_lb_intv_us(const char *val, const struct kernel_param *kp)
> {
> return param_set_uint_minmax(val, kp, 0, 10 * USEC_PER_SEC);
> }
>
> -static const struct kernel_param_ops bypass_lb_intv_us_param_ops = {
> - .set = set_bypass_lb_intv_us,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(bypass_lb_intv_us_param_ops,
> + set_bypass_lb_intv_us, param_get_uint);
>
> #undef MODULE_PARAM_PREFIX
> #define MODULE_PARAM_PREFIX "sched_ext."
> diff --git a/kernel/workqueue.c b/kernel/workqueue.c
> index 5f747f241a5f..42562b811d94 100644
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -7162,10 +7162,8 @@ static int wq_affn_dfl_get(char *buffer, const struct kernel_param *kp)
> return scnprintf(buffer, PAGE_SIZE, "%s\n", wq_affn_names[wq_affn_dfl]);
> }
>
> -static const struct kernel_param_ops wq_affn_dfl_ops = {
> - .set = wq_affn_dfl_set,
> - .get = wq_affn_dfl_get,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(wq_affn_dfl_ops, wq_affn_dfl_set,
> + wq_affn_dfl_get);
>
> module_param_cb(default_affinity_scope, &wq_affn_dfl_ops, NULL, 0644);
>
> @@ -7861,10 +7859,8 @@ static int wq_watchdog_param_set_thresh(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops wq_watchdog_thresh_ops = {
> - .set = wq_watchdog_param_set_thresh,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(wq_watchdog_thresh_ops,
> + wq_watchdog_param_set_thresh, param_get_ulong);
>
> module_param_cb(watchdog_thresh, &wq_watchdog_thresh_ops, &wq_watchdog_thresh,
> 0644);
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index 18a71a9108d3..cf0405ba0dbd 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -807,10 +807,8 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
> }
> EXPORT_SYMBOL(param_get_dyndbg_classes);
>
> -const struct kernel_param_ops param_ops_dyndbg_classes = {
> - .set = param_set_dyndbg_classes,
> - .get = param_get_dyndbg_classes,
> -};
> +DEFINE_KERNEL_PARAM_OPS(param_ops_dyndbg_classes, param_set_dyndbg_classes,
> + param_get_dyndbg_classes);
> EXPORT_SYMBOL(param_ops_dyndbg_classes);
>
> #define PREFIX_SIZE 128
> diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
> index 77c2a669b6af..30880b6c726a 100644
> --- a/lib/test_dynamic_debug.c
> +++ b/lib/test_dynamic_debug.c
> @@ -23,10 +23,8 @@ static int param_get_do_prints(char *buffer, const struct kernel_param *kp)
> do_prints();
> return scnprintf(buffer, PAGE_SIZE, "did do_prints\n");
> }
> -static const struct kernel_param_ops param_ops_do_prints = {
> - .set = param_set_do_prints,
> - .get = param_get_do_prints,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_do_prints, param_set_do_prints,
> + param_get_do_prints);
> module_param_cb(do_prints, ¶m_ops_do_prints, NULL, 0600);
>
> /*
> diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
> index 8494040b1ee4..5feb93c5262e 100644
> --- a/mm/damon/lru_sort.c
> +++ b/mm/damon/lru_sort.c
> @@ -405,10 +405,8 @@ static int damon_lru_sort_addr_unit_store(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops addr_unit_param_ops = {
> - .set = damon_lru_sort_addr_unit_store,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(addr_unit_param_ops,
> + damon_lru_sort_addr_unit_store, param_get_ulong);
>
> module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);
> MODULE_PARM_DESC(addr_unit,
> @@ -446,10 +444,8 @@ static int damon_lru_sort_enabled_load(char *buffer,
> return sprintf(buffer, "%c\n", damon_lru_sort_enabled() ? 'Y' : 'N');
> }
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_lru_sort_enabled_store,
> - .get = damon_lru_sort_enabled_load,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops, damon_lru_sort_enabled_store,
> + damon_lru_sort_enabled_load);
>
> module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> MODULE_PARM_DESC(enabled,
> @@ -478,10 +474,9 @@ static int damon_lru_sort_kdamond_pid_load(char *buffer,
> return sprintf(buffer, "%d\n", kdamond_pid);
> }
>
> -static const struct kernel_param_ops kdamond_pid_param_ops = {
> - .set = damon_lru_sort_kdamond_pid_store,
> - .get = damon_lru_sort_kdamond_pid_load,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(kdamond_pid_param_ops,
> + damon_lru_sort_kdamond_pid_store,
> + damon_lru_sort_kdamond_pid_load);
>
> /*
> * PID of the DAMON thread
> diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
> index fe7fce26cf6c..27e772b095fa 100644
> --- a/mm/damon/reclaim.c
> +++ b/mm/damon/reclaim.c
> @@ -307,10 +307,8 @@ static int damon_reclaim_addr_unit_store(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops addr_unit_param_ops = {
> - .set = damon_reclaim_addr_unit_store,
> - .get = param_get_ulong,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(addr_unit_param_ops,
> + damon_reclaim_addr_unit_store, param_get_ulong);
>
> module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);
> MODULE_PARM_DESC(addr_unit,
> @@ -348,10 +346,8 @@ static int damon_reclaim_enabled_load(char *buffer,
> return sprintf(buffer, "%c\n", damon_reclaim_enabled() ? 'Y' : 'N');
> }
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_reclaim_enabled_store,
> - .get = damon_reclaim_enabled_load,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops, damon_reclaim_enabled_store,
> + damon_reclaim_enabled_load);
>
> module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> MODULE_PARM_DESC(enabled,
> @@ -380,10 +376,9 @@ static int damon_reclaim_kdamond_pid_load(char *buffer,
> return sprintf(buffer, "%d\n", kdamond_pid);
> }
>
> -static const struct kernel_param_ops kdamond_pid_param_ops = {
> - .set = damon_reclaim_kdamond_pid_store,
> - .get = damon_reclaim_kdamond_pid_load,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(kdamond_pid_param_ops,
> + damon_reclaim_kdamond_pid_store,
> + damon_reclaim_kdamond_pid_load);
>
> /*
> * PID of the DAMON thread
> diff --git a/mm/damon/stat.c b/mm/damon/stat.c
> index 3951b762cbdd..6eb548793802 100644
> --- a/mm/damon/stat.c
> +++ b/mm/damon/stat.c
> @@ -22,10 +22,8 @@ static int damon_stat_enabled_store(
> static int damon_stat_enabled_load(char *buffer,
> const struct kernel_param *kp);
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_stat_enabled_store,
> - .get = damon_stat_enabled_load,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops, damon_stat_enabled_store,
> + damon_stat_enabled_load);
>
> static bool enabled __read_mostly = IS_ENABLED(
> CONFIG_DAMON_STAT_ENABLED_DEFAULT);
> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
> index 2a943ec57c85..42e0cf313281 100644
> --- a/mm/memory_hotplug.c
> +++ b/mm/memory_hotplug.c
> @@ -109,10 +109,8 @@ static int get_memmap_mode(char *buffer, const struct kernel_param *kp)
> return sprintf(buffer, "%c\n", mode ? 'Y' : 'N');
> }
>
> -static const struct kernel_param_ops memmap_mode_ops = {
> - .set = set_memmap_mode,
> - .get = get_memmap_mode,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(memmap_mode_ops, set_memmap_mode,
> + get_memmap_mode);
> module_param_cb(memmap_on_memory, &memmap_mode_ops, &memmap_mode, 0444);
> MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for memory hotplug\n"
> "With value \"force\" it could result in memory wastage due "
> @@ -163,10 +161,8 @@ static int get_online_policy(char *buffer, const struct kernel_param *kp)
> * (auto_movable_ratio, auto_movable_numa_aware) allows for it
> */
> static int online_policy __read_mostly = ONLINE_POLICY_CONTIG_ZONES;
> -static const struct kernel_param_ops online_policy_ops = {
> - .set = set_online_policy,
> - .get = get_online_policy,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(online_policy_ops, set_online_policy,
> + get_online_policy);
> module_param_cb(online_policy, &online_policy_ops, &online_policy, 0644);
> MODULE_PARM_DESC(online_policy,
> "Set the online policy (\"contig-zones\", \"auto-movable\") "
> diff --git a/mm/page_reporting.c b/mm/page_reporting.c
> index 7418f2e500bb..61351e12b4d9 100644
> --- a/mm/page_reporting.c
> +++ b/mm/page_reporting.c
> @@ -23,15 +23,8 @@ static int page_order_update_notify(const char *val, const struct kernel_param *
> return param_set_uint_minmax(val, kp, 0, MAX_PAGE_ORDER);
> }
>
> -static const struct kernel_param_ops page_reporting_param_ops = {
> - .set = &page_order_update_notify,
> - /*
> - * For the get op, use param_get_int instead of param_get_uint.
> - * This is to make sure that when unset the initialized value of
> - * -1 is shown correctly
> - */
> - .get = ¶m_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(page_reporting_param_ops,
> + &page_order_update_notify, ¶m_get_int);
>
> module_param_cb(page_reporting_order, &page_reporting_param_ops,
> &page_reporting_order, 0644);
> diff --git a/mm/shuffle.c b/mm/shuffle.c
> index fb1393b8b3a9..114fe7467516 100644
> --- a/mm/shuffle.c
> +++ b/mm/shuffle.c
> @@ -23,10 +23,8 @@ static __meminit int shuffle_param_set(const char *val,
> return 0;
> }
>
> -static const struct kernel_param_ops shuffle_param_ops = {
> - .set = shuffle_param_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(shuffle_param_ops, shuffle_param_set,
> + param_get_bool);
> module_param_cb(shuffle, &shuffle_param_ops, &shuffle_param, 0400);
>
> /*
> diff --git a/mm/zswap.c b/mm/zswap.c
> index 4b5149173b0e..ed3aa07c2f1d 100644
> --- a/mm/zswap.c
> +++ b/mm/zswap.c
> @@ -90,21 +90,17 @@ static DEFINE_STATIC_KEY_MAYBE(CONFIG_ZSWAP_DEFAULT_ON, zswap_ever_enabled);
> static bool zswap_enabled = IS_ENABLED(CONFIG_ZSWAP_DEFAULT_ON);
> static int zswap_enabled_param_set(const char *,
> const struct kernel_param *);
> -static const struct kernel_param_ops zswap_enabled_param_ops = {
> - .set = zswap_enabled_param_set,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(zswap_enabled_param_ops, zswap_enabled_param_set,
> + param_get_bool);
> module_param_cb(enabled, &zswap_enabled_param_ops, &zswap_enabled, 0644);
>
> /* Crypto compressor to use */
> static char *zswap_compressor = CONFIG_ZSWAP_COMPRESSOR_DEFAULT;
> static int zswap_compressor_param_set(const char *,
> const struct kernel_param *);
> -static const struct kernel_param_ops zswap_compressor_param_ops = {
> - .set = zswap_compressor_param_set,
> - .get = param_get_charp,
> - .free = param_free_charp,
> -};
> +static DEFINE_KERNEL_PARAM_OPS_FREE(zswap_compressor_param_ops,
> + zswap_compressor_param_set, param_get_charp,
> + param_free_charp);
> module_param_cb(compressor, &zswap_compressor_param_ops,
> &zswap_compressor, 0644);
>
> diff --git a/net/batman-adv/bat_algo.c b/net/batman-adv/bat_algo.c
> index 49e5861b58ec..54d66a948298 100644
> --- a/net/batman-adv/bat_algo.c
> +++ b/net/batman-adv/bat_algo.c
> @@ -134,10 +134,8 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
> return param_set_copystring(algo_name, kp);
> }
>
> -static const struct kernel_param_ops batadv_param_ops_ra = {
> - .set = batadv_param_set_ra,
> - .get = param_get_string,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(batadv_param_ops_ra, batadv_param_set_ra,
> + param_get_string);
>
> static struct kparam_string batadv_param_string_ra = {
> .maxlen = sizeof(batadv_routing_algo),
> diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
> index 952121849180..633202a99e4a 100644
> --- a/net/ceph/ceph_common.c
> +++ b/net/ceph/ceph_common.c
> @@ -52,9 +52,8 @@ static int param_get_supported_features(char *buffer,
> {
> return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT);
> }
> -static const struct kernel_param_ops param_ops_supported_features = {
> - .get = param_get_supported_features,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_supported_features, NULL,
> + param_get_supported_features);
> module_param_cb(supported_features, ¶m_ops_supported_features, NULL,
> 0444);
>
> diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c
> index 274e628e7cf8..2c9c3d0f3c3d 100644
> --- a/net/ipv4/tcp_dctcp.c
> +++ b/net/ipv4/tcp_dctcp.c
> @@ -64,10 +64,8 @@ static int dctcp_shift_g_set(const char *val, const struct kernel_param *kp)
> return param_set_uint_minmax(val, kp, 0, 10);
> }
>
> -static const struct kernel_param_ops dctcp_shift_g_ops = {
> - .set = dctcp_shift_g_set,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(dctcp_shift_g_ops, dctcp_shift_g_set,
> + param_get_uint);
>
> module_param_cb(dctcp_shift_g, &dctcp_shift_g_ops, &dctcp_shift_g, 0644);
> MODULE_PARM_DESC(dctcp_shift_g, "parameter g for updating dctcp_alpha");
> diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
> index 68c0595ea2fd..64a3e894fd4c 100644
> --- a/net/sunrpc/auth.c
> +++ b/net/sunrpc/auth.c
> @@ -83,10 +83,8 @@ static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp)
>
> #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int);
>
> -static const struct kernel_param_ops param_ops_hashtbl_sz = {
> - .set = param_set_hashtbl_sz,
> - .get = param_get_hashtbl_sz,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_hashtbl_sz, param_set_hashtbl_sz,
> + param_get_hashtbl_sz);
>
> module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
> MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index 2e1fe6013361..e8d087798994 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -3710,10 +3710,8 @@ static int param_set_portnr(const char *val, const struct kernel_param *kp)
> RPC_MAX_RESVPORT);
> }
>
> -static const struct kernel_param_ops param_ops_portnr = {
> - .set = param_set_portnr,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_portnr, param_set_portnr,
> + param_get_uint);
>
> #define param_check_portnr(name, p) \
> __param_check(name, p, unsigned int);
> @@ -3729,10 +3727,8 @@ static int param_set_slot_table_size(const char *val,
> RPC_MAX_SLOT_TABLE);
> }
>
> -static const struct kernel_param_ops param_ops_slot_table_size = {
> - .set = param_set_slot_table_size,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_slot_table_size,
> + param_set_slot_table_size, param_get_uint);
>
> #define param_check_slot_table_size(name, p) \
> __param_check(name, p, unsigned int);
> @@ -3745,10 +3741,8 @@ static int param_set_max_slot_table_size(const char *val,
> RPC_MAX_SLOT_TABLE_LIMIT);
> }
>
> -static const struct kernel_param_ops param_ops_max_slot_table_size = {
> - .set = param_set_max_slot_table_size,
> - .get = param_get_uint,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_max_slot_table_size,
> + param_set_max_slot_table_size, param_get_uint);
>
> #define param_check_max_slot_table_size(name, p) \
> __param_check(name, p, unsigned int);
> diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c
> index 775838a23d93..c8018a7ea891 100644
> --- a/samples/damon/mtier.c
> +++ b/samples/damon/mtier.c
> @@ -38,10 +38,8 @@ module_param(node0_mem_free_bp, ulong, 0600);
> static int damon_sample_mtier_enable_store(
> const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_sample_mtier_enable_store,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops,
> + damon_sample_mtier_enable_store, param_get_bool);
>
> static bool enabled __read_mostly;
> module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> diff --git a/samples/damon/prcl.c b/samples/damon/prcl.c
> index b7c50f2656ce..7cab9bd0f7bd 100644
> --- a/samples/damon/prcl.c
> +++ b/samples/damon/prcl.c
> @@ -22,10 +22,8 @@ module_param(target_pid, int, 0600);
> static int damon_sample_prcl_enable_store(
> const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_sample_prcl_enable_store,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops,
> + damon_sample_prcl_enable_store, param_get_bool);
>
> static bool enabled __read_mostly;
> module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> diff --git a/samples/damon/wsse.c b/samples/damon/wsse.c
> index 799ad4443943..56634853bd0b 100644
> --- a/samples/damon/wsse.c
> +++ b/samples/damon/wsse.c
> @@ -23,10 +23,8 @@ module_param(target_pid, int, 0600);
> static int damon_sample_wsse_enable_store(
> const char *val, const struct kernel_param *kp);
>
> -static const struct kernel_param_ops enabled_param_ops = {
> - .set = damon_sample_wsse_enable_store,
> - .get = param_get_bool,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(enabled_param_ops,
> + damon_sample_wsse_enable_store, param_get_bool);
>
> static bool enabled __read_mostly;
> module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
> index 3491e9f60194..8a253c743363 100644
> --- a/security/apparmor/lsm.c
> +++ b/security/apparmor/lsm.c
> @@ -1767,38 +1767,30 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = {
> static int param_set_aabool(const char *val, const struct kernel_param *kp);
> static int param_get_aabool(char *buffer, const struct kernel_param *kp);
> #define param_check_aabool param_check_bool
> -static const struct kernel_param_ops param_ops_aabool = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = param_set_aabool,
> - .get = param_get_aabool
> -};
> +static DEFINE_KERNEL_PARAM_OPS_NOARG(param_ops_aabool, param_set_aabool,
> + param_get_aabool);
>
> static int param_set_aauint(const char *val, const struct kernel_param *kp);
> static int param_get_aauint(char *buffer, const struct kernel_param *kp);
> #define param_check_aauint param_check_uint
> -static const struct kernel_param_ops param_ops_aauint = {
> - .set = param_set_aauint,
> - .get = param_get_aauint
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_aauint, param_set_aauint,
> + param_get_aauint);
>
> static int param_set_aacompressionlevel(const char *val,
> const struct kernel_param *kp);
> static int param_get_aacompressionlevel(char *buffer,
> const struct kernel_param *kp);
> #define param_check_aacompressionlevel param_check_int
> -static const struct kernel_param_ops param_ops_aacompressionlevel = {
> - .set = param_set_aacompressionlevel,
> - .get = param_get_aacompressionlevel
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_aacompressionlevel,
> + param_set_aacompressionlevel,
> + param_get_aacompressionlevel);
>
> static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp);
> static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp);
> #define param_check_aalockpolicy param_check_bool
> -static const struct kernel_param_ops param_ops_aalockpolicy = {
> - .flags = KERNEL_PARAM_OPS_FL_NOARG,
> - .set = param_set_aalockpolicy,
> - .get = param_get_aalockpolicy
> -};
> +static DEFINE_KERNEL_PARAM_OPS_NOARG(param_ops_aalockpolicy,
> + param_set_aalockpolicy,
> + param_get_aalockpolicy);
>
> static int param_set_debug(const char *val, const struct kernel_param *kp);
> static int param_get_debug(char *buffer, const struct kernel_param *kp);
> @@ -1879,10 +1871,8 @@ module_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO);
> static int param_get_aaintbool(char *buffer, const struct kernel_param *kp);
> static int param_set_aaintbool(const char *val, const struct kernel_param *kp);
> #define param_check_aaintbool param_check_int
> -static const struct kernel_param_ops param_ops_aaintbool = {
> - .set = param_set_aaintbool,
> - .get = param_get_aaintbool
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_aaintbool, param_set_aaintbool,
> + param_get_aaintbool);
> /* Boot time disable flag */
> static int apparmor_enabled __ro_after_init = 1;
> module_param_named(enabled, apparmor_enabled, aaintbool, 0444);
> diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c
> index c87d75dbd8aa..02bd61e67902 100644
> --- a/sound/hda/controllers/intel.c
> +++ b/sound/hda/controllers/intel.c
> @@ -164,10 +164,7 @@ MODULE_PARM_DESC(ctl_dev_id, "Use control device identifier (based on codec addr
>
> #ifdef CONFIG_PM
> static int param_set_xint(const char *val, const struct kernel_param *kp);
> -static const struct kernel_param_ops param_ops_xint = {
> - .set = param_set_xint,
> - .get = param_get_int,
> -};
> +static DEFINE_KERNEL_PARAM_OPS(param_ops_xint, param_set_xint, param_get_int);
> #define param_check_xint param_check_int
>
> static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index f42d72cd0378..34cbb9d72315 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -118,11 +118,8 @@ static int param_set_quirkp(const char *val,
> return param_set_charp(val, kp);
> }
>
> -static const struct kernel_param_ops param_ops_quirkp = {
> - .set = param_set_quirkp,
> - .get = param_get_charp,
> - .free = param_free_charp,
> -};
> +static DEFINE_KERNEL_PARAM_OPS_FREE(param_ops_quirkp, param_set_quirkp,
> + param_get_charp, param_free_charp);
>
> #define param_check_quirkp param_check_charp
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-22 15:53 UTC (permalink / raw)
To: Barry Song
Cc: David Hildenbrand (Arm), Matthew Wilcox, Liam R. Howlett,
Suren Baghdasaryan, akpm, linux-mm, vbabka, rppt, mhocko, jack,
pfalcato, wanglian, chentao, lianux.mm, kunwu.chan, liyangouwen1,
chrisl, kasong, shikemeng, nphamcs, bhe, youngjun.park,
linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev,
linux-riscv, linux-s390, Nanzhe Zhao
In-Reply-To: <CAGsJ_4xC5LdhuoWV1=tK-RZ5rkjc8aOKOkmb1L_8BG_3gtJhDg@mail.gmail.com>
On Thu, May 21, 2026 at 07:37:58AM +0800, Barry Song wrote:
> On Thu, May 21, 2026 at 5:35 AM David Hildenbrand (Arm)
> <david@kernel.org> wrote:
> >
> > On 5/20/26 23:15, Matthew Wilcox wrote:
> > > On Thu, May 21, 2026 at 05:14:20AM +0800, Barry Song wrote:
> > >> My understanding is that we should not blame applications here. This is 2026:
> > >> there are basically only two kinds of applications — single-threaded and
> > >> multi-threaded — and single-threaded applications are nearly extinct.
> > >
> > > all of the applications i run are either single threaded or don't fork.
> > > what multithreaded applications call fork?
> >
> > Traditionally the problem was random libraries using fork+execve to launch other
> > programs ... instead of using alternatives like posix_spwan (some use cases
> > require more work done before execve and cannot yet switch to that). I'd hope
> > that that is less of a problem on Android.
> >
> > I assume Android zygote might be multi threaded? Maybe sshd as well? Systemd?
> > But I'd be surprised if there are really performance implications.
>
> I am trying to answer the question above:
>
> 1. zygote, multi-threaded on my phone using Android13.
> / # ls /proc/`pidof zygote64`/task/
> 1359 22728 22729 22730 22731 22732
>
> /proc/1359/task # cat 22728/comm
> Jit thread pool
> /proc/1359/task # cat 22730/comm
> ReferenceQueueD
> /proc/1359/task # cat 22731/comm
> FinalizerDaemon
> /proc/1359/task # cat 22732/comm
> FinalizerWatchd
> /proc/1359/task # cat 1359/comm
> main
>
> But on another phone of mine running Android 16, zygote64 is
> single-threaded.
> Not sure if it is due to the Android team making some changes
> related to threads from Android 13 to Android 16.
>
> 2. sshd, multi-processes instead of multi-threads:
> $ ps aux | grep sshd
> root 1192 0.0 0.0 15444 9032 ? Ss 09:42 0:00
> sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
> root 2465 0.0 0.0 17164 10760 ? Ss 09:42 0:00
> sshd: barry [priv]
> barry 2632 0.0 0.0 17164 7852 ? S 09:42 0:00
> sshd: barry@pts/0
> root 3305 2.5 0.0 17164 10772 ? Ss 09:44 0:00
> sshd: barry [priv]
> barry 3406 0.0 0.0 17164 7940 ? S 09:44 0:00
> sshd: barry@pts/1
>
> 3. systemd, also multi-processes
>
> $ ps ax | grep systemd
> 350 ? S<s 0:00 /lib/systemd/systemd-journald
> 387 ? Ss 0:00 /lib/systemd/systemd-udevd
> 666 ? Ss 0:00 /lib/systemd/systemd-oomd
> 667 ? Ss 0:00 /lib/systemd/systemd-resolved
> 728 ? Ss 0:00 @dbus-daemon --system --address=systemd:
> --nofork --nopidfile --systemd-activation --syslog-only
> 751 ? Ss 0:00 /lib/systemd/systemd-logind
> 753 ? Ssl 0:00 /usr/sbin/thermald --systemd
> --dbus-enable --adaptive
> 1350 ? Ss 0:00 /lib/systemd/systemd --user
> 1428 ? Ss 0:00 /usr/bin/dbus-daemon --session
> --address=systemd: --nofork --nopidfile --systemd-activation
> --syslog-only
> 1900 ? Ssl 0:00 /usr/libexec/gnome-session-binary
> --systemd-service --session=ubuntu
> 2141 ? Ssl 0:00 /lib/systemd/systemd-timesyncd
>
> >
> > Not sure about webbroswers .... I think most of them switched to fork servers,
> > where I would assume fork servers would be single-threaded.
>
> On my phone, Chrome is multi-process, but its parent process
> chrome_zygote (10774) is single-threaded:
>
> ps -A | grep chrome
> u0_i15 9883 10774 321066464 119452 do_epoll_wait 0 S
> com.android.chrome:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:15
> u0_a142 10164 1359 35110548 277640 do_epoll_wait 0 S
> com.android.chrome
> u0_a278 10724 1359 9779864 104988 do_epoll_wait 0 S
> com.google.android.apps.chromecast.app
> u0_a142 10774 1359 32803908 64076 do_sys_poll 0 S
> com.android.chrome_zygote
> u0_a142 11173 1359 34208592 142192 do_epoll_wait 0 S
> com.android.chrome:privileged_process0
>
> /proc/10774/task # ls
> 10774
>
> >
> > So, yeah, getting a clear understanding how this ends up being a problem on
> > Android would be great.
>
> I guess the real issue is that in the Android market, there
> are so many applications that are out of our control?
>
> Here are some trace examples from Nanzhe:
>
> iQIYI plugin
> vma reader thread:
> PbMisc-0, pid=27183, tgid=26444
>
> vma writer thread:
> i.video:plugin1, pid=27298, tgid=26444
> writer blocked: 440394938 ns (440 ms)
>
> reader stack:
> vma_start_read
> lock_vma_under_rcu
> do_page_fault
> do_translation_fault
> do_mem_abort
> el0_da
> el0t_64_sync_handler
> el0t_64_sync
>
> writer stack:
> __vma_start_write
> dup_mmap
> copy_mm
> copy_process
> kernel_clone
> __arm64_sys_clone
> invoke_syscall
> el0_svc_common
> do_el0_svc
> el0_svc
>
>
> Baidu Tieba
> vma reader thread:
> elastic_pms_pro, pid=7731, tgid=7575
>
> vma writer thread:
> com.baidu.tieba, pid=8005, tgid=7575
> writer blocked: 514975545 ns(515 ms)
>
> reader stack:
> vma_start_read
> lock_vma_under_rcu
> do_page_fault
> do_translation_fault
> do_mem_abort
> el0_da
> el0t_64_sync_handler
> el0t_64_sync
>
> writer stack:
> __vma_start_write
> dup_mmap
> copy_mm
> copy_process
> kernel_clone
> __arm64_sys_clone
> invoke_syscall
> el0_svc_common
> do_el0_svc
> el0_svc
>
> Thanks
> Barry
Again this is making me want to sit outside and sip on some lemonade and
ice :)
Yes - android processes are aggressively multi-threaded, sure of course.
The missing bit here is the forking - what, where, why, when?
And then you say zygote is sometimes multi-threaded but sometimes
single-threaded, which is adding a whole bunch of confusion on top of all
that.
I don't find these stack trace dumps all that useful (though thanks of
course for taking the time to gather them), I think we'd be better off with
specific data on forking, in some _concise_ _summarised_ form, ideally with
numbers.
There's such a thing as too much information :))
Anyway, again, please let's see a new _RFC_ with the approach proposed by
Suren, with some _succinct_ data demonstrating _exactly_ what the problem
is, so we can make some headway here.
And now I'm off for a cornetto! :)
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-22 15:42 UTC (permalink / raw)
To: Barry Song
Cc: Matthew Wilcox, akpm, bhe, chentao, chrisl, david, jack, kasong,
kunwu.chan, liam, lianux.mm, linux-arm-kernel, linux-kernel,
linux-mm, linux-riscv, linux-s390, linuxppc-dev, liyangouwen1,
loongarch, mhocko, nphamcs, nzzhao, pfalcato, rppt, shikemeng,
surenb, vbabka, wanglian, youngjun.park
In-Reply-To: <CAGsJ_4zrm3sCp8Uz0Gh+sAwRcdtNF8rDLqX250sFVG3rZy9HNw@mail.gmail.com>
On Fri, May 22, 2026 at 09:48:35PM +0800, Barry Song wrote:
> On Fri, May 22, 2026 at 9:36 PM Barry Song <baohua@kernel.org> wrote:
> >
> > On Fri, May 22, 2026 at 9:09 PM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > On Fri, May 22, 2026 at 10:33:05AM +0800, Barry Song (Xiaomi) wrote:
> > > > need to touch `filemap.c` at all (probably because you are already
> > > > maintaining `filemap.c` perfectly):
> > >
> > > I'm going to give you one chance to apologise for that.
> >
> > Apologies if my wording caused any misunderstanding.
> > That was not my intention at all.
> >
> > What I meant is that filemap.c already has a very
> > solid design.
> >
> > For memory.c, I had to touch several places for the
> > blacklist; otherwise, the kernel would hang.
> >
> > But for filemap.c, I basically didn't need to touch
> > anything, and preliminary testing shows no issues after
> > moving it from the whitelist to the blacklist. This is
>
> Sorry, I feel I may be causing some misunderstanding
> again.
>
> By "whitelist", I mean I used to allow certain cases
> to use per-vma retry.
>
> By "blacklist", I mean I am now moving to disallow
> certain cases from using per-vma retry.
>
> Right now, I have to add several cases in memory.c
> to the blacklist; otherwise, the kernel would hang.
>
> But it seems that everything in filemap.c is fine so
> far based on testing.
>
> I'm not sure if I've explained things clearly. Please
> let me know if anything is still unclear or insufficient.
Barry - this thread is completely out of hand and getting _rapidly_
unproductive.
It's certainly about as clear as mud where we stand right now, so here's my
suggestion - let's just stop adding to the noise here :) and instead, you
take the approach suggested by Suren at LSF and send that as an _RFC_
series.
That way we can look at that and hopefully actually circle in on a solution
rather than have endless sub threads and sub discussions :) It's far too
sunny out in the UK right now for that ;)
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-22 15:39 UTC (permalink / raw)
To: Suren Baghdasaryan
Cc: Barry Song, Matthew Wilcox, akpm, linux-mm, david, liam, vbabka,
rppt, mhocko, jack, pfalcato, wanglian, chentao, lianux.mm,
kunwu.chan, liyangouwen1, chrisl, kasong, shikemeng, nphamcs, bhe,
youngjun.park, linux-arm-kernel, linux-kernel, loongarch,
linuxppc-dev, linux-riscv, linux-s390, Nanzhe Zhao
In-Reply-To: <CAJuCfpG2Zmpf5N_ejB6ZDv8LDjpVtTfA_tYQ6sW+Noc9Y+XhdA@mail.gmail.com>
On Wed, May 20, 2026 at 05:51:23AM +0000, Suren Baghdasaryan wrote:
> On Tue, May 19, 2026 at 12:53 PM Lorenzo Stoakes <ljs@kernel.org> wrote:
> >
> > On Mon, May 18, 2026 at 12:56:59PM -0700, Suren Baghdasaryan wrote:
> >
> > > >
> > > > I think we either need to fix `fork()`, or keep the current
> > > > behavior of dropping the VMA lock before performing I/O.
> > >
> > > I see. So, this problem arises from the fact that we are changing the
> > > pagefaults requiring I/O operation to hold VMA lock...
> > > And you want to lock VMA on fork only if vma_is_anonymous(vma) ||
> > > is_cow_mapping(vma->vm_flags). So, we will be blocking page faults for
> > > anonymous and COW VMAs only while holding mmap_write_lock, preventing
> > > any VMA modification. On the surface, that looks ok to me but I might
> > > be missing some corner cases. If nobody sees any obvious issues, I
> > > think it's worth a try.
> >
> > Not sure if you noticed but I did raise concerns ;)
>
> Sorry, I didn't realize your first comment was a conceptual objection
> to this approach of allowing page faults to race with the fork.
Ah yeah it's understandable I think there's been so many threads in this
conversation that it's easy to get lost :)
>
>
> >
> > I wonder if you've confused the fault path and fork here, as I think Barry has
> > been a little unclear on that.
> >
> > What's being suggested in this thread is to fundamentally change fork behaviour
> > so it's different from the entire history of the kernel (or - presumably - at
> > least recent history :) and permit concurrent page faults to occur on a forking
> > process.
> >
> > I absolutely object to this for being pretty crazy. I mean I'm not sure we
> > really want to be simultaneously modifying page tables while invoking
> > copy_page_range()? No?
> >
> > OK you cover anon and MAP_PRIVATE file-backed but hang on there's
> > VM_COPY_ON_FORK too.. so PFN mapped, mixed map and (the accursed) UFFD W/P as
> > well as possibly-guard region containing VMAs now can have page tables raced.
>
> Ugh, yeah, I realize now this is a minefield. Resolving all possible
> races there would not be trivial and might introduce other performance
> issues.
Yeah, it's dangerous waters :)
>
> >
> > That's not to mention anything else that relies on serialisation here (this
> > would be changing how forking has been done in general) that we may or may not
> > know about.
> >
> > The risk level is high, for what amounts to a hack to work around the fault
> > issue.
> >
> > I suggest that if we have a problem with the fault path, let's look at the fault
> > path :)
> >
> > So yeah I'm very opposed to this unless I'm somehow horribly mistaken here or a
> > very convincing argument is made.
>
> So, current approach of dropping locks during I/O sounds like still
> the best solution.
Yeah _of those proposed_ I think importantly. This doesn't mean there aren't
other potential solutions.
Thanks, Lorenzo
>
> >
> >
> > >
> > >
> > >
> > >
> > > >
> > > > >
> > > > > I'd also like to get Suren's input, however.
> > > >
> > > > Yes. of course.
> > > >
> > > > >
> > > > > Thanks, Lorenzo
> > > >
> > > > Best Regards
> > > > Barry
> >
> > Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Lorenzo Stoakes @ 2026-05-22 15:37 UTC (permalink / raw)
To: Yang Shi
Cc: David Hildenbrand (Arm), Suren Baghdasaryan, Barry Song,
Matthew Wilcox, akpm, linux-mm, liam, vbabka, rppt, mhocko, jack,
pfalcato, wanglian, chentao, lianux.mm, kunwu.chan, liyangouwen1,
chrisl, kasong, shikemeng, nphamcs, bhe, youngjun.park,
linux-arm-kernel, linux-kernel, loongarch, linuxppc-dev,
linux-riscv, linux-s390, Nanzhe Zhao
In-Reply-To: <CAHbLzkq3S7NDYe4LXjurKNQU+40-wtqrD_PT18YcyHbAcNxiRQ@mail.gmail.com>
On Wed, May 20, 2026 at 02:39:49PM -0700, Yang Shi wrote:
> On Wed, May 20, 2026 at 3:34 AM David Hildenbrand (Arm)
> <david@kernel.org> wrote:
> >
> > On 5/19/26 14:53, Lorenzo Stoakes wrote:
> > > On Mon, May 18, 2026 at 12:56:59PM -0700, Suren Baghdasaryan wrote:
> > >
> > >>>
> > >>> I think we either need to fix `fork()`, or keep the current
> > >>> behavior of dropping the VMA lock before performing I/O.
> > >>
> > >> I see. So, this problem arises from the fact that we are changing the
> > >> pagefaults requiring I/O operation to hold VMA lock...
> > >> And you want to lock VMA on fork only if vma_is_anonymous(vma) ||
> > >> is_cow_mapping(vma->vm_flags). So, we will be blocking page faults for
> > >> anonymous and COW VMAs only while holding mmap_write_lock, preventing
> > >> any VMA modification. On the surface, that looks ok to me but I might
> > >> be missing some corner cases. If nobody sees any obvious issues, I
> > >> think it's worth a try.
> > >
> > > Not sure if you noticed but I did raise concerns ;)
> > >
> > > I wonder if you've confused the fault path and fork here, as I think Barry has
> > > been a little unclear on that.
> > >
> > > What's being suggested in this thread is to fundamentally change fork behaviour
> > > so it's different from the entire history of the kernel (or - presumably - at
> > > least recent history :)
> > I don't want fork() to become different in that regard.
> >
> > There is already a slight difference with vs. without per-VMA locks, because
> > there is a window in-between us taking the write mmap_lock and all the per-VMA
> > locks. I raised that previously [1] and assumed that it is probably fine.
> >
> > I also raised in the past why I think we must not allow concurrent page faults,
> > at least as soon as anonymous memory is involved [2].
>
> Thanks for sharing the context, it is quite helpful to understand the
> race conditions. Because Lorenzo also raised the concern about page
> fault race, I will reply to all the concerns regarding page fault race
> together in this thread.
>
> IIUC, there is already some sort of race with per vma lock. Before per
> vma lock, mmap_lock did lock everything. So page fault happened either
> before fork or after fork. But page fault can happen on other VMAs
> which have not been lock'ed yet during fork with per vma lock. For
> example, we have 3 VMAs, we lock the first VMA, but page fault still
> can happen on the other 2 VMAs during fork if they already have
> anon_vma. This is the status quo now, but it seems not harmful.
>
> The bad race shared by David is caused by racing with copy page. So it
> seems like it will be fine as long as we serialize copy page against
> page fault if I don't miss anything. Since we decide whether to copy
> page or not by checking vma->anon_vma, so it seems fine to not take
> vma lock if vma->anon_vma is NULL. This will not introduce more race
> either because setting up a new anon_vma in page fault or madvise
> requires taking mmap_lock according to the earlier discussions.
NAK. No.
We're not doing this, we're not changing how fork fundamentally behaves because
of concerns about the fault path.
I've delineated exactly why I think this is a problem and you're pressing ahead
without addressing those concerns.
So at this point I'm going to be a grumpy maintainer and just say no, stop
please :)
Let's fix this in the right place. You don't fix a leak in the roof by repairing
a shelf next door :)
Thanks, Lorenzo
>
> Thanks,
> Yang
>
> >
> > ... and I raised that this is pretty much slower by design right now: "Well, the
> > design decision that CONFIG_PER_VMA_LOCK made for now to make page faults fast
> > and to make blocking any page faults from happening to be slower ..." [3]
> >
> > [1] https://lore.kernel.org/all/970295ab-e85d-7af3-76e6-df53a5c52f8b@redhat.com/
> > [2] https://lore.kernel.org/all/7e3f35cc-59b9-bf12-b8b1-4ed78223844a@redhat.com/
> > [3] https://lore.kernel.org/all/2efa2c89-3765-721d-2c3c-00590054aa5b@redhat.com/
> >
> > --
> > Cheers,
> >
> > David
> >
^ permalink raw reply
* [PATCH v3 5/5] KVM: PPC: Document KVM_PPC_GET_COMPAT_CAPS ioctl
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
In-Reply-To: <20260522152744.55251-1-amachhiw@linux.ibm.com>
Add documentation for the KVM_PPC_GET_COMPAT_CAPS ioctl to the KVM API
documentation.
The ioctl exposes host processor compatibility modes supported for
nested KVM guests on PowerPC systems.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605140717.W1StD3Ke-lkp@intel.com/
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
Documentation/virt/kvm/api.rst | 35 ++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 52bbbb553ce1..d11e054e6665 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6555,6 +6555,41 @@ KVM_S390_KEYOP_SSKE
.. _kvm_run:
+4.145 KVM_PPC_GET_COMPAT_CAPS
+-----------------------------
+:Capability: KVM_CAP_PPC_COMPAT_CAPS
+:Architectures: powerpc
+:Type: vm ioctl
+:Parameters: struct kvm_ppc_compat_caps (out)
+:Returns:
+ 0 on successful completion,
+ -EFAULT if ``struct kvm_ppc_compat_caps`` cannot be written
+
+IBM POWER system server-based processors provide a compatibility mode feature
+where an Nth generation processor can operate in modes consistent with earlier
+generations such as (N-1) and (N-2).
+
+This ioctl provides userspace with information about the CPU compatibility modes
+supported by the current host processor for booting the nested KVM guests on
+PowerNV (KVM nested APIv1) and PowerVM (KVM nested APIv2) platforms.
+
+::
+
+ struct kvm_ppc_compat_caps {
+ __u64 flags; /* Reserved for future use */
+ __u64 compat_capabilities; /* Capabilities supported by the host */
+ };
+
+The ``compat_capabilities`` bit field describes the processor compatibility
+modes supported by the host. For example, the following bits indicate support
+for specific processor modes.
+
+::
+
+ H_GUEST_CAP_POWER9 (bit 1): KVM guests can run in Power9 processor mode
+ H_GUEST_CAP_POWER10 (bit 2): KVM guests can run in Power10 processor mode
+ H_GUEST_CAP_POWER11 (bit 3): KVM guests can run in Power11 processor mode
+
5. The kvm_run structure
========================
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v3 4/5] KVM: PPC: Book3S HV: Add support for compat CPU capabilities for KVM on PowerNV
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
In-Reply-To: <20260522152744.55251-1-amachhiw@linux.ibm.com>
Currently, when booting a compatibility-mode KVM guest (L1) on a PowerNV
hypervisor (L0), the guest runs with the expected processor
compatibility level. However, when booting a nested KVM guest (L2)
inside the L1, QEMU derives the CPU model from the raw host PVR and
attempts to run the nested guest at that level, instead of honoring the
compatibility mode of the L1.
Extend host CPU compatibility capability reporting to support nested
virtualization on PowerNV systems (PAPR nested API v1).
For nested API v2 (PowerVM), compatibility capabilities are obtained
from the hypervisor via the H_GUEST_GET_CAPABILITIES hcall. This
information is not available on PowerNV systems.
For nested API v1, derive the compatibility capabilities from the L1
guest by reading the "cpu-version" property from the device tree, which
reflects the effective (logical) processor compatibility level. Map this
value to the corresponding compatibility capability bitmap.
Introduce a helper to translate CPU version values into compatibility
capability bits and integrate it into kvmppc_get_compat_cpu_caps().
This allows userspace to query host CPU compatibility modes on both
PowerVM and PowerNV platforms via the KVM_PPC_GET_COMPAT_CAPS ioctl.
Suggested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
arch/powerpc/kvm/book3s_hv.c | 37 +++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 38de7040e2b7..18774c49af85 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -6522,15 +6522,50 @@ static bool kvmppc_hash_v3_possible(void)
return true;
}
+static int kvmppc_map_compat_capabilities(const __be32 cpu_version,
+ unsigned long *capabilities)
+{
+ switch (cpu_version) {
+ case PVR_ARCH_31_P11:
+ *capabilities |= H_GUEST_CAP_POWER11;
+ break;
+ case PVR_ARCH_31:
+ *capabilities |= H_GUEST_CAP_POWER10;
+ break;
+ case PVR_ARCH_300:
+ *capabilities |= H_GUEST_CAP_POWER9;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
static int kvmppc_get_compat_cpu_caps(struct kvm_ppc_compat_caps *host_caps)
{
+ struct device_node *np;
unsigned long capabilities = 0;
+ const __be32 *prop = NULL;
long rc = -EINVAL;
+ u32 cpu_version;
if (kvmhv_on_pseries()) {
- if (kvmhv_is_nestedv2())
+ if (kvmhv_is_nestedv2()) {
rc = plpar_guest_get_capabilities(0, &capabilities);
+ } else {
+ for_each_node_by_type(np, "cpu") {
+ prop = of_get_property(np, "cpu-version", NULL);
+ if (prop) {
+ cpu_version = be32_to_cpup(prop);
+ break;
+ }
+ }
+ if (!prop)
+ return -EINVAL;
+ rc = kvmppc_map_compat_capabilities(cpu_version,
+ &capabilities);
+ }
host_caps->compat_capabilities = capabilities;
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v3 2/5] KVM: PPC: Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
In-Reply-To: <20260522152744.55251-1-amachhiw@linux.ibm.com>
Introduce a new capability and ioctl to expose CPU compatibility modes
supported by the host processor for nested guests.
On IBM POWER systems, newer processor generations (N) can operate in
compatibility modes corresponding to earlier generations, like (N-1) and
(N-2). This is particularly relevant for nested virtualization, where
nested KVM guests may need to run with a specific processor compatibility
level.
Introduce KVM_CAP_PPC_COMPAT_CAPS capability and the corresponding
KVM_PPC_GET_COMPAT_CAPS vm ioctl. The ioctl returns a bitmap describing
the compatibility modes supported by the host in respective bit numbers,
allowing userspace (e.g., QEMU) to select an appropriate compatibility
level when configuring nested KVM guests.
The ioctl handling is added in kvm_arch_vm_ioctl() and retrieves host
CPU compatibility capabilities via a PowerPC-specific backend
implementation when available. If the capability is not supported, the
ioctl returns success with no capabilities set, allowing userspace to
fall back gracefully.
Suggested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
arch/powerpc/include/asm/kvm_ppc.h | 1 +
arch/powerpc/include/uapi/asm/kvm.h | 6 ++++++
arch/powerpc/kvm/powerpc.c | 21 +++++++++++++++++++++
include/uapi/linux/kvm.h | 4 ++++
4 files changed, 32 insertions(+)
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 0953f2daa466..cadfb839e836 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -319,6 +319,7 @@ struct kvmppc_ops {
bool (*hash_v3_possible)(void);
int (*create_vm_debugfs)(struct kvm *kvm);
int (*create_vcpu_debugfs)(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry);
+ int (*get_compat_cpu_ver)(struct kvm_ppc_compat_caps *host_caps);
};
extern struct kvmppc_ops *kvmppc_hv_ops;
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 077c5437f521..081d6c7f7f70 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -437,6 +437,12 @@ struct kvm_ppc_cpu_char {
__u64 behaviour_mask; /* valid bits in behaviour */
};
+/* For KVM_PPC_GET_COMPAT_CAPS */
+struct kvm_ppc_compat_caps {
+ __u64 flags; /* Reserved for future use */
+ __u64 compat_capabilities; /* Capabilities supported by the host */
+};
+
/*
* Values for character and character_mask.
* These are identical to the values used by H_GET_CPU_CHARACTERISTICS.
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 00302399fc37..02b834ebd8d3 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -697,6 +697,13 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
}
}
break;
+#if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
+ case KVM_CAP_PPC_COMPAT_CAPS:
+ r = 0;
+ if (kvmhv_on_pseries())
+ r = 1;
+ break;
+#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
default:
r = 0;
break;
@@ -2463,6 +2470,20 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
r = kvm->arch.kvm_ops->svm_off(kvm);
break;
}
+ case KVM_PPC_GET_COMPAT_CAPS: {
+ struct kvm_ppc_compat_caps host_caps;
+
+ r = -ENOTTY;
+ memset(&host_caps, 0, sizeof(host_caps));
+ if (!kvm->arch.kvm_ops->get_compat_cpu_ver)
+ goto out;
+
+ r = kvm->arch.kvm_ops->get_compat_cpu_ver(&host_caps);
+ if (!r && copy_to_user(argp, &host_caps,
+ sizeof(host_caps)))
+ r = -EFAULT;
+ break;
+ }
default: {
struct kvm *kvm = filp->private_data;
r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg);
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6c8afa2047bf..1788a0068662 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -996,6 +996,7 @@ struct kvm_enable_cap {
#define KVM_CAP_S390_USER_OPEREXEC 246
#define KVM_CAP_S390_KEYOP 247
#define KVM_CAP_S390_VSIE_ESAMODE 248
+#define KVM_CAP_PPC_COMPAT_CAPS 249
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1349,6 +1350,9 @@ struct kvm_s390_keyop {
#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr)
+/* Available with KVM_CAP_PPC_COMPAT_CAPS */
+#define KVM_PPC_GET_COMPAT_CAPS _IOR(KVMIO, 0xe4, struct kvm_ppc_compat_caps)
+
/*
* ioctls for vcpu fds
*/
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v3 3/5] KVM: PPC: Book3S HV: Implement compat CPU capability retrieval for KVM on PowerVM
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
In-Reply-To: <20260522152744.55251-1-amachhiw@linux.ibm.com>
On POWER systems, the host CPU may run in a compatibility mode (e.g., a
Power11 processor operating in Power10 compatibility mode). In such
cases, the effective CPU level exposed to guests differs from the
physical processor generation.
When running nested KVM guests, QEMU derives the host CPU type using
mfpvr(), which reflects the physical processor version. This can result
in a mismatch between the CPU model selected by QEMU and the
compatibility mode enforced by the host, leading to guest boot failures.
For example, booting a nested guest on a Power11 LPAR configured in
Power10 compatibility mode fails with:
KVM-NESTEDv2: couldn't set guest wide elements
[..KVM reg dump..]
This occurs because QEMU selects a CPU model corresponding to the
physical processor (via mfpvr()), while the host operates in a lower
compatibility mode. As a result, KVM rejects the requested compatibility
level during guest initialization.
Add support for retrieving host CPU compatibility capabilities for
nested guests on PowerVM (PAPR nested API v2). The hypervisor provides
the effective compatibility levels via the H_GUEST_GET_CAPABILITIES
hcall, which reflects the processor modes negotiated between the Power
hypervisor (L0) and the host partition (L1).
On pseries systems, obtain the capability bitmap using
plpar_guest_get_capabilities() and return it via struct
kvm_ppc_compat_caps. This information is then exposed to userspace
through the KVM_PPC_GET_COMPAT_CAPS ioctl.
Hook the implementation into the Book3S HV kvmppc_ops so that it can be
invoked by the generic KVM ioctl handling code.
Suggested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
arch/powerpc/kvm/book3s_hv.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 249d1f2e4e2c..38de7040e2b7 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -6522,6 +6522,21 @@ static bool kvmppc_hash_v3_possible(void)
return true;
}
+
+static int kvmppc_get_compat_cpu_caps(struct kvm_ppc_compat_caps *host_caps)
+{
+ unsigned long capabilities = 0;
+ long rc = -EINVAL;
+
+ if (kvmhv_on_pseries()) {
+ if (kvmhv_is_nestedv2())
+ rc = plpar_guest_get_capabilities(0, &capabilities);
+ host_caps->compat_capabilities = capabilities;
+ }
+
+ return rc;
+}
+
static struct kvmppc_ops kvm_ops_hv = {
.get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv,
.set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv,
@@ -6564,6 +6579,7 @@ static struct kvmppc_ops kvm_ops_hv = {
.hash_v3_possible = kvmppc_hash_v3_possible,
.create_vcpu_debugfs = kvmppc_arch_create_vcpu_debugfs_hv,
.create_vm_debugfs = kvmppc_arch_create_vm_debugfs_hv,
+ .get_compat_cpu_ver = kvmppc_get_compat_cpu_caps,
};
static int kvm_init_subcore_bitmap(void)
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v3 1/5] KVM: PPC: Book3S HV: Validate arch_compat against host compatibility mode
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
In-Reply-To: <20260522152744.55251-1-amachhiw@linux.ibm.com>
On IBM POWER systems, newer processor generations can operate in
compatibility modes corresponding to earlier generations. This becomes
relevant for nested virtualization, where nested KVM guests may need to
run with a specific processor compatibility level.
Currently, when running a nested KVM guest (L2) inside a Power11 pSeries
logical partition (L1) booted in Power10 compatibility mode, the guest
fails to boot while setting 'arch_compat'. This happens because the CPU
class is derived from the hardware PVR (via mfspr()), which reflects the
physical processor generation (Power11), rather than the effective
compatibility mode (Power10).
As a result, userspace may request a Power11 arch_compat for the L2
guest. However, the L1 partition, running in Power10 compatibility, has
only negotiated support up to Power10 with the Power Hypervisor (L0).
When H_SET_STATE is invoked with a Power11 Logical PVR, the hypervisor
rejects the request, leading to a late guest boot failure:
KVM-NESTEDv2: couldn't set guest wide elements
[..KVM reg dump..]
This situation should be detected earlier. Rejecting unsupported
'arch_compat' values in 'kvmppc_set_arch_compat()' avoids issuing an
invalid H_SET_STATE hcall and provides a clearer failure mode.
Add a check to reject Power11 'arch_compat' requests when the host is
running in Power10 compatibility mode, returning -EINVAL early instead
of deferring the failure to the hypervisor.
Suggested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
arch/powerpc/kvm/book3s_hv.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 61dbeea317f3..249d1f2e4e2c 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -446,7 +446,19 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
guest_pcr_bit = PCR_ARCH_300;
break;
case PVR_ARCH_31:
+ guest_pcr_bit = PCR_ARCH_31;
+ break;
case PVR_ARCH_31_P11:
+ /*
+ * Need to check this for ISA 3.1, as Power10 and
+ * Power11 share the same PCR. For any subsequent ISA
+ * versions, this will be taken care of by the guest vs
+ * host PCR comparison below.
+ */
+ if ((PVR_ARCH_31 & cur_cpu_spec->pvr_mask) ==
+ cur_cpu_spec->pvr_value) {
+ return -EINVAL;
+ }
guest_pcr_bit = PCR_ARCH_31;
break;
default:
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* [PATCH v3 0/5] KVM: PPC: Handle CPU compatibility mode for nested guests
From: Amit Machhiwal @ 2026-05-22 15:27 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Vaibhav Jain, Amit Machhiwal, Anushree Mathur, Paolo Bonzini,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Jonathan Corbet, Shuah Khan, kvm, linux-kernel, linux-doc, lkp
On POWER systems, newer processor generations can operate in compatibility
modes corresponding to earlier generations (e.g., a Power11 system running
in Power10 compatibility mode). In such cases, the effective CPU level
exposed to guests differs from the physical processor generation.
This creates a problem for nested virtualization. When booting a nested KVM
guest (L2) inside a host KVM guest (L1) running in a compatibility mode,
userspace (e.g., QEMU) may derive the CPU model from the raw hardware PVR
and attempt to configure the nested guest accordingly. However, the L1
partition is constrained by the compatibility level negotiated with the
hypervisor (L0), and requests exceeding that level are rejected, leading to
guest boot failures such as:
KVM-NESTEDv2: couldn't set guest wide elements
This series addresses the issue in two steps:
1. Detect and reject invalid compatibility requests early in KVM to avoid
late failures.
2. Provide a mechanism for userspace to query the effective CPU
compatibility modes supported by the host, so it can select an
appropriate CPU model for nested guests.
To achieve this, the series introduces a new KVM capability and ioctl
(KVM_CAP_PPC_COMPAT_CAPS / KVM_PPC_GET_COMPAT_CAPS) that expose the
compatibility modes supported by the host.
Why a new UAPI?
---------------
While cpu-version is available in /proc/device-tree/cpus/<cpu#>/cpu-version
on both L1 booted on PowerNV and PowerVM LPARs, the UAPI approach is
preferable for several reasons:
1. pHYP (L0) capabilities: On PowerVM, we need to rely on capabilities
negotiated with pHYP in KVM, not just device tree properties. The
cpu-version property depicts the current compat mode but doesn't point
to what all compat modes are supported for the nested guest.
2. procfs dependency: Not all systems run with procfs enabled (CONFIG_PROC_FS
is optional). Minimal configurations like buildroot might disable it, but
KVM ioctl works regardless since it accesses kernel data structures
directly.
3. Kernel validation: The kernel validates and normalizes the compatibility
information. Patch 1 adds validation logic that rejects invalid
compatibility requests early, ensuring userspace gets validated,
consistent data.
4. Abstraction & stability: /proc/device-tree is an implementation detail.
The UAPI provides a stable interface that won't break if the underlying
mechanism changes.
5. Semantic clarity: KVM_PPC_GET_COMPAT_CAPS clearly expresses what
compatibility modes can be used for KVM guests, vs. parsing device tree
which requires understanding the semantic meaning of cpu-version.
The implementation supports both:
- PowerVM (nested API v2), where compatibility information is obtained
via the H_GUEST_GET_CAPABILITIES hypercall.
- PowerNV (nested API v1), where compatibility is derived from the device
tree ("cpu-version") representing the effective processor compatibility
level.
This allows userspace (e.g., QEMU) to select a CPU model consistent with
the host compatibility mode, avoiding mismatches and enabling successful
nested guest boot.
Changes in v3:
- Added "Why a new UAPI?" section to cover letter addressing questions
about the need for a new UAPI vs. using existing mechanisms like
/proc/device-tree
- Fixed initialization of 'r' in KVM_PPC_GET_COMPAT_CAPS ioctl handler
from 0 to -ENOTTY for proper error handling when the operation is not
supported
- Added Vaibhav's "Suggested-by" tags
- Have retained Anushree's "Tested-by" tags as no major code changes
- Fixed documentation build warning reported by kernel test robot and
added "Reported-by" and "Closes" tags to patch 5
Changes in v2:
- Squashed patches 2 and 3 from v1 (capability introduction and ioctl
wiring) into a single patch for better logical grouping
- Changed kvm_ppc_compat_caps.flags from __u32 to __u64 for consistency
and future extensibility
- Addressed other review comments
- Improved commit messages with clearer explanations of the changes
Patch summary:
[1/5] Validate arch_compat against host compatibility mode
[2/5] Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl
[3/5] Implement capability retrieval for PowerVM (API v2)
[4/5] Add PowerNV support (API v1)
[5/5] Document the new ioctl
Tested on:
- Power11 pSeries LPAR in Power10 compatibility mode (nested API v2)
- Power10 PowerNV system (and QEMU TCG PowerNV 11) with nested
virtualization (API v1) with various combinations of KVM L1/L2 guests
in various supported compatibility modes.
With this series, nested guests boot successfully in configurations where
they previously failed due to compatibility mismatches.
Related QEMU series:
A corresponding QEMU series adds support for querying and using these
compatibility capabilities when configuring nested KVM guests:
https://lore.kernel.org/all/20260502140021.69712-1-amachhiw@linux.ibm.com/
v2: https://lore.kernel.org/linuxppc-dev/20260513100755.83215-1-amachhiw@linux.ibm.com/
v1: https://lore.kernel.org/linuxppc-dev/20260430054906.94431-1-amachhiw@linux.ibm.com/
Amit Machhiwal (5):
KVM: PPC: Book3S HV: Validate arch_compat against host compatibility
mode
KVM: PPC: Introduce KVM_CAP_PPC_COMPAT_CAPS and wire up ioctl
KVM: PPC: Book3S HV: Implement compat CPU capability retrieval for KVM
on PowerVM
KVM: PPC: Book3S HV: Add support for compat CPU capabilities for KVM
on PowerNV
KVM: PPC: Document KVM_PPC_GET_COMPAT_CAPS ioctl
Documentation/virt/kvm/api.rst | 35 ++++++++++++++++
arch/powerpc/include/asm/kvm_ppc.h | 1 +
arch/powerpc/include/uapi/asm/kvm.h | 6 +++
arch/powerpc/kvm/book3s_hv.c | 63 +++++++++++++++++++++++++++++
arch/powerpc/kvm/powerpc.c | 21 ++++++++++
include/uapi/linux/kvm.h | 4 ++
6 files changed, 130 insertions(+)
base-commit: 1d5dcaa3bd65f2e8c9baa14a393d3a2dc5db7524
--
2.50.1 (Apple Git-155)
^ permalink raw reply
* Re: [PATCH v2 0/4] fbdev: Internalize fbcon
From: Helge Deller @ 2026-05-22 13:59 UTC (permalink / raw)
To: Thomas Zimmermann; +Cc: dri-devel, linux-fbdev, linuxppc-dev
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
On 5/22/26 14:28, Thomas Zimmermann wrote:
> Turn fbcon into an internal client of fbdev. Manage all interactions
> with graphics drivers within fbdev. Add helpers for these tasks and
> convert drivers.
>
> Fbdev's PS3 and SH-Mobile drivers update fbcon as part of user-invoked
> mode changes. Call the new helpers, which also fix inconsistencies
> among the various code paths.
>
> Vga-switcheroo remaps the fbcon terminals when switching physical
> outputs. For now, hide this in another helper. The call will later
> move into DRM's fbdev emulation.
>
> When all refactoring in place, fbdev manages fbcon interactions by
> itself. Remove the public interfaces.
>
> v2:
> - use '#if defined' (Helge)
>
> Thomas Zimmermann (4):
> fbdev: Wrap user-invoked calls to fb_set_var() in helper
> fbdev: Wrap user-invoked calls to fb_blank() in helper
> fbdev: Wrap fbcon updates from vga-switcheroo in helper
> fbdev: Do not export fbcon from fbdev
>
> MAINTAINERS | 1 -
> drivers/gpu/vga/vga_switcheroo.c | 6 +--
> drivers/video/fbdev/core/fb_chrdev.c | 12 ++----
> drivers/video/fbdev/core/fb_internal.h | 1 +
> drivers/video/fbdev/core/fbcon.c | 3 --
> drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++
> drivers/video/fbdev/core/fbmem.c | 35 +++++++++++++++-
> drivers/video/fbdev/core/fbsysfs.c | 9 +----
> drivers/video/fbdev/ps3fb.c | 5 +--
> drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +--
> include/linux/fb.h | 3 ++
> include/linux/fbcon.h | 55 --------------------------
> 12 files changed, 98 insertions(+), 87 deletions(-)
> delete mode 100644 include/linux/fbcon.h
series applied to fbdev git tree.
Thanks!
Helge
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Barry Song @ 2026-05-22 13:48 UTC (permalink / raw)
To: Matthew Wilcox
Cc: akpm, bhe, chentao, chrisl, david, jack, kasong, kunwu.chan, liam,
lianux.mm, linux-arm-kernel, linux-kernel, linux-mm, linux-riscv,
linux-s390, linuxppc-dev, liyangouwen1, ljs, loongarch, mhocko,
nphamcs, nzzhao, pfalcato, rppt, shikemeng, surenb, vbabka,
wanglian, youngjun.park
In-Reply-To: <CAGsJ_4zQuJx1reJxgV387Gh0AqWF0KdoFn9KahQ1BNLPRm57TQ@mail.gmail.com>
On Fri, May 22, 2026 at 9:36 PM Barry Song <baohua@kernel.org> wrote:
>
> On Fri, May 22, 2026 at 9:09 PM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Fri, May 22, 2026 at 10:33:05AM +0800, Barry Song (Xiaomi) wrote:
> > > need to touch `filemap.c` at all (probably because you are already
> > > maintaining `filemap.c` perfectly):
> >
> > I'm going to give you one chance to apologise for that.
>
> Apologies if my wording caused any misunderstanding.
> That was not my intention at all.
>
> What I meant is that filemap.c already has a very
> solid design.
>
> For memory.c, I had to touch several places for the
> blacklist; otherwise, the kernel would hang.
>
> But for filemap.c, I basically didn't need to touch
> anything, and preliminary testing shows no issues after
> moving it from the whitelist to the blacklist. This is
Sorry, I feel I may be causing some misunderstanding
again.
By "whitelist", I mean I used to allow certain cases
to use per-vma retry.
By "blacklist", I mean I am now moving to disallow
certain cases from using per-vma retry.
Right now, I have to add several cases in memory.c
to the blacklist; otherwise, the kernel would hang.
But it seems that everything in filemap.c is fine so
far based on testing.
I'm not sure if I've explained things clearly. Please
let me know if anything is still unclear or insufficient.
^ permalink raw reply
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Barry Song @ 2026-05-22 13:36 UTC (permalink / raw)
To: Matthew Wilcox
Cc: akpm, bhe, chentao, chrisl, david, jack, kasong, kunwu.chan, liam,
lianux.mm, linux-arm-kernel, linux-kernel, linux-mm, linux-riscv,
linux-s390, linuxppc-dev, liyangouwen1, ljs, loongarch, mhocko,
nphamcs, nzzhao, pfalcato, rppt, shikemeng, surenb, vbabka,
wanglian, youngjun.park
In-Reply-To: <ahBVh4NM2uoyhPNm@casper.infradead.org>
On Fri, May 22, 2026 at 9:09 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Fri, May 22, 2026 at 10:33:05AM +0800, Barry Song (Xiaomi) wrote:
> > need to touch `filemap.c` at all (probably because you are already
> > maintaining `filemap.c` perfectly):
>
> I'm going to give you one chance to apologise for that.
Apologies if my wording caused any misunderstanding.
That was not my intention at all.
What I meant is that filemap.c already has a very
solid design.
For memory.c, I had to touch several places for the
blacklist; otherwise, the kernel would hang.
But for filemap.c, I basically didn't need to touch
anything, and preliminary testing shows no issues after
moving it from the whitelist to the blacklist. This is
probably because the current filemap.c design is
already handling some aspects really well.
That is all I meant.
^ permalink raw reply
* Soft lockup in smp_call_function_many_cond
From: Mark Tomlinson @ 2026-05-21 4:34 UTC (permalink / raw)
To: linuxppc-dev@lists.ozlabs.org
We have been experiencing random softlockups with a P2040 (e500mc) CPU.
The rate of these occurring is very low.
The stack trace appears below:
watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [systemd:1]
CPU: 0 UID: 0 PID: 1 Comm: systemd Tainted: G O 6.12.85 #1
Tainted: [O]=OOT_MODULE
Hardware name: x930 e500mc 0x80230032 CoreNet Generic
NIP: 800f6e88 LR: 8001cae8 CTR: 80028e50
REGS: 81029c40 TRAP: 0900 Tainted: G O (6.12.85)
MSR: 00029002 <CE,EE,ME> CR: 48042842 XER: 20000000
GPR00: 8001cae8 81029d30 81080000 0000000c abc2db70 abc2b380 00000001
80db697c
GPR08: abc11b70 00000001 00000001 0000000f 48042842 10038020 100a0000
00000000
GPR16: 00000000 7fcff900 00000001 00000000 abc013c0 00000000 10013db0
77fb8ff0
GPR24: 00000001 ae3a1e10 81029f10 8001c790 81029dac 00000000 00000000
00000000
NIP [800f6e88] smp_call_function_many_cond+0x29c/0x4ac
LR [8001cae8] __flush_tlb_page+0xe4/0x108
Call Trace:
[81029d30] [00000008] 0x8 (unreliable)
[81029d90] [8001cae8] __flush_tlb_page+0xe4/0x108
[81029dd0] [80019c54] ptep_set_access_flags+0xcc/0x120
[81029df0] [8020e8bc] do_wp_page+0x160/0xe28
[81029e40] [80211308] handle_mm_fault+0x75c/0xe78
[81029ed0] [800190a0] do_page_fault+0x154/0x694
[81029f00] [8000091c] DataStorage+0x15c/0x180
I suspect that the issue is more than one CPU is running this code path at
the same time, and the two are deadlocked waiting for a response from each
other. My reasoning for is that the following patch fixes the issue:
diff --git a/kernel/smp.c b/kernel/smp.c
index fa6faf50fb43..d986b5075eb7 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -875,7 +875,7 @@ static void smp_call_function_many_cond(const struct
cpumask *mask,
csd_do_func(func, info, NULL);
local_irq_restore(flags);
}
-
+ flush_smp_call_function_queue();
if (run_remote && wait) {
for_each_cpu(cpu, cfd->cpumask) {
call_single_data_t *csd;
That is, after making a request to the other CPU(s), process our own list.
I suspect I shouldn't have to do this, and the problem lies elsewhere;
perhaps an interrupt not being enabled? Does anyone have any suggestions?
^ permalink raw reply related
* Re: [PATCH v2 0/5] mm: reduce mmap_lock contention and improve page fault performance
From: Matthew Wilcox @ 2026-05-22 13:09 UTC (permalink / raw)
To: Barry Song (Xiaomi)
Cc: akpm, bhe, chentao, chrisl, david, jack, kasong, kunwu.chan, liam,
lianux.mm, linux-arm-kernel, linux-kernel, linux-mm, linux-riscv,
linux-s390, linuxppc-dev, liyangouwen1, ljs, loongarch, mhocko,
nphamcs, nzzhao, pfalcato, rppt, shikemeng, surenb, vbabka,
wanglian, youngjun.park
In-Reply-To: <20260522023305.98223-1-baohua@kernel.org>
On Fri, May 22, 2026 at 10:33:05AM +0800, Barry Song (Xiaomi) wrote:
> need to touch `filemap.c` at all (probably because you are already
> maintaining `filemap.c` perfectly):
I'm going to give you one chance to apologise for that.
^ permalink raw reply
* Re: [PATCH v1 2/8] powerpc/signal64: Untangle setup_tm_sigcontexts() and user_access_begin()
From: Christophe Leroy (CS GROUP) @ 2026-05-22 12:44 UTC (permalink / raw)
To: David Laight
Cc: Michael Ellerman, Nicholas Piggin, Madhavan Srinivasan,
linux-kernel, linuxppc-dev
In-Reply-To: <69bd69b1-97f7-41e2-934b-bed28dc2fef7@kernel.org>
Le 22/05/2026 à 14:06, Christophe Leroy (CS GROUP) a écrit :
>
>
> Le 22/05/2026 à 13:12, David Laight a écrit :
>> On Fri, 22 May 2026 11:56:02 +0200
>> "Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
>>
>>> Call setup_tm_sigcontexts() before opening user access to avoid
>>> having to close and open again.
>>>
>>> Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
>>> ---
>>> arch/powerpc/kernel/signal_64.c | 22 +++++++++-------------
>>> 1 file changed, 9 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/
>>> signal_64.c
>>> index 86bb5bb4c143..3849af21e1d8 100644
>>> --- a/arch/powerpc/kernel/signal_64.c
>>> +++ b/arch/powerpc/kernel/signal_64.c
>>> @@ -873,6 +873,15 @@ int handle_rt_signal64(struct ksignal *ksig,
>>> sigset_t *set,
>>> if (!MSR_TM_ACTIVE(msr))
>>> prepare_setup_sigcontext(tsk);
>>> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>>> + if (MSR_TM_ACTIVE(msr))
>>
>> Can't that be done without the ugly #ifdef?
>> I assume MSR_TM_ACTIVE() will be zero - so it will all get optimised
>> away.
>
> Yes but struct rt_sigframe field uc_transact only exists when
> CONFIG_PPC_TRANSACTIONAL_MEM is defined.
>
> And that would also require a stub setup_tm_sigcontexts()
After thinking once more, I think we can do the following, is it better
for you ?
diff --git a/arch/powerpc/kernel/signal_64.c
b/arch/powerpc/kernel/signal_64.c
index 86bb5bb4c143..c70732e8002d 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -203,8 +203,7 @@ static long notrace __unsafe_setup_sigcontext(struct
sigcontext __user *sc,
* examine the transactional registers in the 2nd sigcontext to
determine the
* real origin of the signal.
*/
-static long setup_tm_sigcontexts(struct sigcontext __user *sc,
- struct sigcontext __user *tm_sc,
+static long setup_tm_sigcontexts(struct rt_sigframe __user *frame,
struct task_struct *tsk,
int signr, sigset_t *set, unsigned long handler,
unsigned long msr)
@@ -217,6 +216,8 @@ static long setup_tm_sigcontexts(struct sigcontext
__user *sc,
* Userland shall check AT_HWCAP to know wether it can rely on the
* v_regs pointer or not.
*/
+ struct sigcontext __user *sc = &frame->uc.uc_mcontext;
+ struct sigcontext __user *tm_sc = &frame->uc_transact.uc_mcontext;
#ifdef CONFIG_ALTIVEC
elf_vrreg_t __user *v_regs = sigcontext_vmx_regs(sc);
elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
@@ -325,6 +326,14 @@ static long setup_tm_sigcontexts(struct sigcontext
__user *sc,
return err;
}
+#else
+static long setup_tm_sigcontexts(struct rt_sigframe __user *frame,
+ struct task_struct *tsk,
+ int signr, sigset_t *set, unsigned long handler,
+ unsigned long msr)
+{
+ return -EINVAL;
+}
#endif
/*
@@ -872,6 +881,9 @@ int handle_rt_signal64(struct ksignal *ksig,
sigset_t *set,
*/
if (!MSR_TM_ACTIVE(msr))
prepare_setup_sigcontext(tsk);
+ else
+ err |= setup_tm_sigcontexts(frame, tsk, ksig->sig, NULL,
+ (unsigned long)ksig->ka.sa.sa_handler, msr);
if (!user_write_access_begin(frame, sizeof(*frame)))
goto badframe;
@@ -889,19 +901,6 @@ int handle_rt_signal64(struct ksignal *ksig,
sigset_t *set,
* ucontext_t (for transactional state) with its uc_link ptr.
*/
unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link,
badframe_block);
-
- user_write_access_end();
-
- err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
- &frame->uc_transact.uc_mcontext,
- tsk, ksig->sig, NULL,
- (unsigned long)ksig->ka.sa.sa_handler,
- msr);
-
- if (!user_write_access_begin(&frame->uc.uc_sigmask,
- sizeof(frame->uc.uc_sigmask)))
- goto badframe;
-
#endif
} else {
unsafe_put_user(0, &frame->uc.uc_link, badframe_block);
Christophe
^ permalink raw reply related
* [PATCH v2 4/4] fbdev: Do not export fbcon from fbdev
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
There are no callers of fbcon outside fbdev. Move the declarations
into the internal header.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
MAINTAINERS | 1 -
drivers/video/fbdev/core/fb_chrdev.c | 2 +-
drivers/video/fbdev/core/fbcon.c | 1 -
drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++++
drivers/video/fbdev/core/fbmem.c | 2 +-
include/linux/fbcon.h | 55 ----------------------------
6 files changed, 52 insertions(+), 59 deletions(-)
delete mode 100644 include/linux/fbcon.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 6810710e7a57..0ed3ef0b466a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10147,7 +10147,6 @@ F: drivers/video/fbdev/core/fbcon_rotate.h
F: drivers/video/fbdev/core/fbcon_ud.c
F: drivers/video/fbdev/core/softcursor.c
F: drivers/video/fbdev/core/tileblit.c
-F: include/linux/fbcon.h
F: include/linux/font.h
F: lib/fonts/
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 035e67d2c28f..ba1d0bc214c5 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -3,10 +3,10 @@
#include <linux/compat.h>
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* We hold a reference to the fb_info in file->private_data,
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 50b84cd32938..853b52b40d01 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -70,7 +70,6 @@
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/font.h>
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 321cc7f44baa..407d207b14f1 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -11,6 +11,7 @@
#ifndef _VIDEO_FBCON_H
#define _VIDEO_FBCON_H
+#include <linux/compiler_types.h>
#include <linux/font.h>
#include <linux/types.h>
#include <linux/vt_buffer.h>
@@ -19,6 +20,11 @@
#include <asm/io.h>
+struct fb_blit_caps;
+struct fb_info;
+struct fb_var_screeninfo;
+struct fb_videomode;
+
/*
* This is the interface between the low-level console driver and the
* low-level frame buffer device
@@ -233,4 +239,48 @@ static inline int get_attribute(struct fb_info *info, u16 c)
(void) (&_r == &_v); \
(i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE
+void __init fb_console_init(void);
+void __exit fb_console_exit(void);
+int fbcon_fb_registered(struct fb_info *info);
+void fbcon_fb_unregistered(struct fb_info *info);
+void fbcon_fb_unbind(struct fb_info *info);
+void fbcon_suspended(struct fb_info *info);
+void fbcon_resumed(struct fb_info *info);
+int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode);
+void fbcon_delete_modelist(struct list_head *head);
+void fbcon_new_modelist(struct fb_info *info);
+void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps);
+void fbcon_fb_blanked(struct fb_info *info, int blank);
+int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var);
+void fbcon_update_vcs(struct fb_info *info, bool all);
+void fbcon_remap_all(struct fb_info *info);
+int fbcon_set_con2fb_map_ioctl(void __user *argp);
+int fbcon_get_con2fb_map_ioctl(void __user *argp);
+#else
+static inline void fb_console_init(void) {}
+static inline void fb_console_exit(void) {}
+static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
+static inline void fbcon_fb_unregistered(struct fb_info *info) {}
+static inline void fbcon_fb_unbind(struct fb_info *info) {}
+static inline void fbcon_suspended(struct fb_info *info) {}
+static inline void fbcon_resumed(struct fb_info *info) {}
+static inline int fbcon_mode_deleted(struct fb_info *info,
+ struct fb_videomode *mode) { return 0; }
+static inline void fbcon_delete_modelist(struct list_head *head) {}
+static inline void fbcon_new_modelist(struct fb_info *info) {}
+static inline void fbcon_get_requirement(struct fb_info *info,
+ struct fb_blit_caps *caps) {}
+static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
+static inline int fbcon_modechange_possible(struct fb_info *info,
+ struct fb_var_screeninfo *var) { return 0; }
+static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
+static inline void fbcon_remap_all(struct fb_info *info) {}
+static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
+static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
+#endif
+
#endif /* _VIDEO_FBCON_H */
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index ecadbc58abff..e5221653ec2b 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -14,13 +14,13 @@
#include <linux/console.h>
#include <linux/export.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/lcd.h>
#include <linux/leds.h>
#include <video/nomodeset.h>
#include "fb_internal.h"
+#include "fbcon.h"
/*
* Frame buffer device initialization and setup routines
diff --git a/include/linux/fbcon.h b/include/linux/fbcon.h
deleted file mode 100644
index f206370060e1..000000000000
--- a/include/linux/fbcon.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef _LINUX_FBCON_H
-#define _LINUX_FBCON_H
-
-#include <linux/compiler_types.h>
-
-struct fb_blit_caps;
-struct fb_info;
-struct fb_var_screeninfo;
-struct fb_videomode;
-
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-void __init fb_console_init(void);
-void __exit fb_console_exit(void);
-int fbcon_fb_registered(struct fb_info *info);
-void fbcon_fb_unregistered(struct fb_info *info);
-void fbcon_fb_unbind(struct fb_info *info);
-void fbcon_suspended(struct fb_info *info);
-void fbcon_resumed(struct fb_info *info);
-int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode);
-void fbcon_delete_modelist(struct list_head *head);
-void fbcon_new_modelist(struct fb_info *info);
-void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps);
-void fbcon_fb_blanked(struct fb_info *info, int blank);
-int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var);
-void fbcon_update_vcs(struct fb_info *info, bool all);
-void fbcon_remap_all(struct fb_info *info);
-int fbcon_set_con2fb_map_ioctl(void __user *argp);
-int fbcon_get_con2fb_map_ioctl(void __user *argp);
-#else
-static inline void fb_console_init(void) {}
-static inline void fb_console_exit(void) {}
-static inline int fbcon_fb_registered(struct fb_info *info) { return 0; }
-static inline void fbcon_fb_unregistered(struct fb_info *info) {}
-static inline void fbcon_fb_unbind(struct fb_info *info) {}
-static inline void fbcon_suspended(struct fb_info *info) {}
-static inline void fbcon_resumed(struct fb_info *info) {}
-static inline int fbcon_mode_deleted(struct fb_info *info,
- struct fb_videomode *mode) { return 0; }
-static inline void fbcon_delete_modelist(struct list_head *head) {}
-static inline void fbcon_new_modelist(struct fb_info *info) {}
-static inline void fbcon_get_requirement(struct fb_info *info,
- struct fb_blit_caps *caps) {}
-static inline void fbcon_fb_blanked(struct fb_info *info, int blank) {}
-static inline int fbcon_modechange_possible(struct fb_info *info,
- struct fb_var_screeninfo *var) { return 0; }
-static inline void fbcon_update_vcs(struct fb_info *info, bool all) {}
-static inline void fbcon_remap_all(struct fb_info *info) {}
-static inline int fbcon_set_con2fb_map_ioctl(void __user *argp) { return 0; }
-static inline int fbcon_get_con2fb_map_ioctl(void __user *argp) { return 0; }
-#endif
-
-#endif /* _LINUX_FBCON_H */
--
2.54.0
^ permalink raw reply related
* [PATCH v2 3/4] fbdev: Wrap fbcon updates from vga-switcheroo in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle console remapping in fbcon in fb_switch_output(). Vga-switcheroo
invokes this functionality before switching physical outputs to a new
graphics device. Open-coding fbcon state in vga-switcheroo exposed fbdev
implementation details.
Vga-switcheroo is used for switching physical outputs among graphics
hardware. This functionality is only supported by DRM drivers. A later
update will further move fb_switch_output() into DRM's fbdev emulation;
thus fully decoupling vga-switcheroo from fbdev.
v2:
- use '#if defined' (Helge)
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/gpu/vga/vga_switcheroo.c | 6 +++---
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
include/linux/fb.h | 1 +
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 8fe1ae3c71bb..22cf52b78b75 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -31,11 +31,9 @@
#define pr_fmt(fmt) "vga_switcheroo: " fmt
#include <linux/apple-gmux.h>
-#include <linux/console.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
#include <linux/fs.h>
-#include <linux/fbcon.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_domain.h>
@@ -735,8 +733,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
if (!active->driver_power_control)
set_audio_state(active->id, VGA_SWITCHEROO_OFF);
+#if defined(CONFIG_FB)
if (new_client->fb_info)
- fbcon_remap_all(new_client->fb_info);
+ fb_switch_outputs(new_client->fb_info);
+#endif
mutex_lock(&vgasr_priv.mux_hw_lock);
ret = vgasr_priv.handler->switchto(new_client->id);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 1a6758653b64..ecadbc58abff 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -684,6 +684,16 @@ void fb_set_suspend(struct fb_info *info, int state)
}
EXPORT_SYMBOL(fb_set_suspend);
+/**
+ * fb_switch_outputs - framebuffer got the outputs from vga-switcheroo
+ * @info: framebuffer
+ */
+void fb_switch_outputs(struct fb_info *info)
+{
+ fbcon_remap_all(info);
+}
+EXPORT_SYMBOL(fb_switch_outputs);
+
static int __init fbmem_init(void)
{
int ret;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 88680a7cabd5..e9a26e82322a 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -608,6 +608,7 @@ void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 h
u32 shift_high, u32 shift_low, u32 mod);
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
+extern void fb_switch_outputs(struct fb_info *info);
extern int fb_get_color_depth(struct fb_var_screeninfo *var,
struct fb_fix_screeninfo *fix);
extern int fb_get_options(const char *name, char **option);
--
2.54.0
^ permalink raw reply related
* [PATCH v2 2/4] fbdev: Wrap user-invoked calls to fb_blank() in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle fbcon during blanking in fb_blank_from_user(). First blank the
hardware, then blank fbcon. Same for unblanking. Update all callers and
resolve the duplicated logic.
With the new helper, fbdev's sysfb code no longer maintains fbcon state
by itself.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 4 +---
drivers/video/fbdev/core/fb_internal.h | 1 +
drivers/video/fbdev/core/fbmem.c | 10 ++++++++++
drivers/video/fbdev/core/fbsysfs.c | 5 +----
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 54f926fb411b..035e67d2c28f 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -138,9 +138,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
return -EINVAL;
console_lock();
lock_fb_info(info);
- ret = fb_blank(info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(info, arg);
+ ret = fb_blank_from_user(info, arg);
unlock_fb_info(info);
console_unlock();
break;
diff --git a/drivers/video/fbdev/core/fb_internal.h b/drivers/video/fbdev/core/fb_internal.h
index 613832d335fe..62e75bf15b9b 100644
--- a/drivers/video/fbdev/core/fb_internal.h
+++ b/drivers/video/fbdev/core/fb_internal.h
@@ -44,6 +44,7 @@ extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
struct fb_info *get_fb_info(unsigned int idx);
void put_fb_info(struct fb_info *fb_info);
+int fb_blank_from_user(struct fb_info *info, int blank);
/* fb_procfs.c */
#if defined(CONFIG_FB_DEVICE)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index d37a1039e221..1a6758653b64 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -422,6 +422,16 @@ int fb_blank(struct fb_info *info, int blank)
}
EXPORT_SYMBOL(fb_blank);
+int fb_blank_from_user(struct fb_info *info, int blank)
+{
+ int ret = fb_blank(info, blank);
+
+ /* might again call into fb_blank */
+ fbcon_fb_blanked(info, blank);
+
+ return ret;
+}
+
static int fb_check_foreignness(struct fb_info *fi)
{
const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index 5ece236e6252..d9743ef35355 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -7,7 +7,6 @@
#include <linux/console.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/major.h>
#include "fb_internal.h"
@@ -229,9 +228,7 @@ static ssize_t store_blank(struct device *device,
arg = simple_strtoul(buf, &last, 0);
console_lock();
- err = fb_blank(fb_info, arg);
- /* might again call into fb_blank */
- fbcon_fb_blanked(fb_info, arg);
+ err = fb_blank_from_user(fb_info, arg);
console_unlock();
if (err < 0)
return err;
--
2.54.0
^ permalink raw reply related
* [PATCH v2 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
In-Reply-To: <20260522123019.211059-1-tzimmermann@suse.de>
Handle fbcon during display updates in fb_set_var_from_user(). Check
with fbcon if the mode change is possible, update hardware state and
finally update fbcon. Update all callers.
Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
mode-changes callers in sysfs and driver code are missing fbcon-related
steps.
With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
fbcon state themselves.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
drivers/video/fbdev/core/fbcon.c | 2 --
drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
drivers/video/fbdev/core/fbsysfs.c | 4 +---
drivers/video/fbdev/ps3fb.c | 5 +----
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
include/linux/fb.h | 2 ++
7 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/video/fbdev/core/fb_chrdev.c b/drivers/video/fbdev/core/fb_chrdev.c
index 4ebd16b7e3b8..54f926fb411b 100644
--- a/drivers/video/fbdev/core/fb_chrdev.c
+++ b/drivers/video/fbdev/core/fb_chrdev.c
@@ -85,11 +85,7 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
var.activate &= ~FB_ACTIVATE_KD_TEXT;
console_lock();
lock_fb_info(info);
- ret = fbcon_modechange_possible(info, &var);
- if (!ret)
- ret = fb_set_var(info, &var);
- if (!ret)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ ret = fb_set_var_from_user(info, &var);
unlock_fb_info(info);
console_unlock();
if (!ret && copy_to_user(argp, &var, sizeof(var)))
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index b0e3e765360d..50b84cd32938 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2699,7 +2699,6 @@ void fbcon_update_vcs(struct fb_info *info, bool all)
else
fbcon_modechanged(info);
}
-EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
@@ -2727,7 +2726,6 @@ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *va
return 0;
}
-EXPORT_SYMBOL_GPL(fbcon_modechange_possible);
int fbcon_mode_deleted(struct fb_info *info,
struct fb_videomode *mode)
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 30f2b59c47bf..d37a1039e221 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -346,6 +346,19 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
}
EXPORT_SYMBOL(fb_set_var);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+ int ret = fbcon_modechange_possible(info, var);
+
+ if (!ret)
+ ret = fb_set_var(info, var);
+ if (!ret)
+ fbcon_update_vcs(info, var->activate & FB_ACTIVATE_ALL);
+
+ return ret;
+}
+EXPORT_SYMBOL(fb_set_var_from_user);
+
static void fb_lcd_notify_blank(struct fb_info *info)
{
int power;
diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c
index baa2bae0fb5b..5ece236e6252 100644
--- a/drivers/video/fbdev/core/fbsysfs.c
+++ b/drivers/video/fbdev/core/fbsysfs.c
@@ -19,9 +19,7 @@ static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
var->activate |= FB_ACTIVATE_FORCE;
console_lock();
lock_fb_info(fb_info);
- err = fb_set_var(fb_info, var);
- if (!err)
- fbcon_update_vcs(fb_info, var->activate & FB_ACTIVATE_ALL);
+ err = fb_set_var_from_user(fb_info, var);
unlock_fb_info(fb_info);
console_unlock();
if (err)
diff --git a/drivers/video/fbdev/ps3fb.c b/drivers/video/fbdev/ps3fb.c
index dbcda307f6a6..1376d19b19ae 100644
--- a/drivers/video/fbdev/ps3fb.c
+++ b/drivers/video/fbdev/ps3fb.c
@@ -29,7 +29,6 @@
#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <linux/fb.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <asm/cell-regs.h>
@@ -830,9 +829,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd,
/* Force, in case only special bits changed */
var.activate |= FB_ACTIVATE_FORCE;
par->new_mode_id = val;
- retval = fb_set_var(info, &var);
- if (!retval)
- fbcon_update_vcs(info, var.activate & FB_ACTIVATE_ALL);
+ retval = fb_set_var_from_user(info, &var);
console_unlock();
}
break;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index 72969fe8e513..e8324b01700f 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -15,7 +15,6 @@
#include <linux/ctype.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/fbcon.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
@@ -1768,11 +1767,9 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
var.height = ch->display.height;
var.activate = FB_ACTIVATE_NOW;
- if (fb_set_var(info, &var) < 0)
+ if (fb_set_var_from_user(info, &var) < 0)
/* Couldn't reconfigure, hopefully, can continue as before */
return;
-
- fbcon_update_vcs(info, true);
}
/*
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 5178a33c752c..88680a7cabd5 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var);
extern int fb_blank(struct fb_info *info, int blank);
+int fb_set_var_from_user(struct fb_info *info, struct fb_var_screeninfo *var);
+
/*
* Helpers for framebuffers in I/O memory
*/
--
2.54.0
^ permalink raw reply related
* [PATCH v2 0/4] fbdev: Internalize fbcon
From: Thomas Zimmermann @ 2026-05-22 12:28 UTC (permalink / raw)
To: deller, simona, airlied, lukas, maddy, mpe, npiggin, chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev, Thomas Zimmermann
Turn fbcon into an internal client of fbdev. Manage all interactions
with graphics drivers within fbdev. Add helpers for these tasks and
convert drivers.
Fbdev's PS3 and SH-Mobile drivers update fbcon as part of user-invoked
mode changes. Call the new helpers, which also fix inconsistencies
among the various code paths.
Vga-switcheroo remaps the fbcon terminals when switching physical
outputs. For now, hide this in another helper. The call will later
move into DRM's fbdev emulation.
When all refactoring in place, fbdev manages fbcon interactions by
itself. Remove the public interfaces.
v2:
- use '#if defined' (Helge)
Thomas Zimmermann (4):
fbdev: Wrap user-invoked calls to fb_set_var() in helper
fbdev: Wrap user-invoked calls to fb_blank() in helper
fbdev: Wrap fbcon updates from vga-switcheroo in helper
fbdev: Do not export fbcon from fbdev
MAINTAINERS | 1 -
drivers/gpu/vga/vga_switcheroo.c | 6 +--
drivers/video/fbdev/core/fb_chrdev.c | 12 ++----
drivers/video/fbdev/core/fb_internal.h | 1 +
drivers/video/fbdev/core/fbcon.c | 3 --
drivers/video/fbdev/core/fbcon.h | 50 +++++++++++++++++++++++
drivers/video/fbdev/core/fbmem.c | 35 +++++++++++++++-
drivers/video/fbdev/core/fbsysfs.c | 9 +----
drivers/video/fbdev/ps3fb.c | 5 +--
drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +--
include/linux/fb.h | 3 ++
include/linux/fbcon.h | 55 --------------------------
12 files changed, 98 insertions(+), 87 deletions(-)
delete mode 100644 include/linux/fbcon.h
base-commit: f103db97c610a41177720b08aa4a2a05f9b42d49
prerequisite-patch-id: c67e5d886a47b7d0266d81100837557fda34cb24
prerequisite-patch-id: a5a973e527c88a5b47053d7a72aefe0b550197cb
prerequisite-patch-id: b9adc9622920a3e70168e672c2c92795b3e3a106
prerequisite-patch-id: 5030de433a01c2e99056cadb676a8e2ba35f055a
--
2.54.0
^ permalink raw reply
* Re: [PATCH 1/4] fbdev: Wrap user-invoked calls to fb_set_var() in helper
From: Thomas Zimmermann @ 2026-05-22 12:14 UTC (permalink / raw)
To: Helge Deller, simona, airlied, lukas, maddy, mpe, npiggin,
chleroy
Cc: dri-devel, linux-fbdev, linuxppc-dev
In-Reply-To: <0ce59eaf-1124-48c5-b812-c8e6b58e01d0@gmx.de>
Hi
Am 20.05.26 um 20:51 schrieb Helge Deller:
> On 5/20/26 18:00, Thomas Zimmermann wrote:
>> Handle fbcon during display updates in fb_set_var_from_user(). Check
>> with fbcon if the mode change is possible, update hardware state and
>> finally update fbcon. Update all callers.
>>
>> Only the FBIOPUT_VSCREENINFO ioctl currently does all steps. Other
>> mode-changes callers in sysfs and driver code are missing fbcon-related
>> steps.
>>
>> With the new helper, ps3fb and sh_mobile_lcdcfb no longer maintain
>> fbcon state themselves.
>>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> ---
>> drivers/video/fbdev/core/fb_chrdev.c | 6 +-----
>> drivers/video/fbdev/core/fbcon.c | 2 --
>> drivers/video/fbdev/core/fbmem.c | 13 +++++++++++++
>> drivers/video/fbdev/core/fbsysfs.c | 4 +---
>> drivers/video/fbdev/ps3fb.c | 5 +----
>> drivers/video/fbdev/sh_mobile_lcdcfb.c | 5 +----
>> include/linux/fb.h | 2 ++
>> 7 files changed, 19 insertions(+), 18 deletions(-)
>>
>> ...
>> diff --git a/include/linux/fb.h b/include/linux/fb.h
>> index 5178a33c752c..88680a7cabd5 100644
>> --- a/include/linux/fb.h
>> +++ b/include/linux/fb.h
>> @@ -533,6 +533,8 @@ extern int fb_set_var(struct fb_info *info,
>> struct fb_var_screeninfo *var);
>> extern int fb_pan_display(struct fb_info *info, struct
>> fb_var_screeninfo *var);
>> extern int fb_blank(struct fb_info *info, int blank);
>> +int fb_set_var_from_user(struct fb_info *info, struct
>> fb_var_screeninfo *var);
>> +
>
> "extern" int fb_set_var_from_user(...) ?
As Christophe ointed out, not having extern is correct. I think, if
anything, we should remove the existing externs from the headers.
>
> Other than that the series is a nice cleanup!
Thanks. I'll send you an updated series with the #ifdef fix for patch
3. Sending just fixup patches can confuse the tracker bots and services
(say patchwork), so I'd avoid that.
Best regards
Thomas
>
> Thanks!
> Helge
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)
^ permalink raw reply
* Re: [PATCH v1 2/8] powerpc/signal64: Untangle setup_tm_sigcontexts() and user_access_begin()
From: Christophe Leroy (CS GROUP) @ 2026-05-22 12:06 UTC (permalink / raw)
To: David Laight
Cc: Michael Ellerman, Nicholas Piggin, Madhavan Srinivasan,
linux-kernel, linuxppc-dev
In-Reply-To: <20260522121237.3089276f@pumpkin>
Le 22/05/2026 à 13:12, David Laight a écrit :
> On Fri, 22 May 2026 11:56:02 +0200
> "Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
>
>> Call setup_tm_sigcontexts() before opening user access to avoid
>> having to close and open again.
>>
>> Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
>> ---
>> arch/powerpc/kernel/signal_64.c | 22 +++++++++-------------
>> 1 file changed, 9 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
>> index 86bb5bb4c143..3849af21e1d8 100644
>> --- a/arch/powerpc/kernel/signal_64.c
>> +++ b/arch/powerpc/kernel/signal_64.c
>> @@ -873,6 +873,15 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
>> if (!MSR_TM_ACTIVE(msr))
>> prepare_setup_sigcontext(tsk);
>>
>> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>> + if (MSR_TM_ACTIVE(msr))
>
> Can't that be done without the ugly #ifdef?
> I assume MSR_TM_ACTIVE() will be zero - so it will all get optimised away.
Yes but struct rt_sigframe field uc_transact only exists when
CONFIG_PPC_TRANSACTIONAL_MEM is defined.
And that would also require a stub setup_tm_sigcontexts()
Chistophe
>
> -- David
>
>> + err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
>> + &frame->uc_transact.uc_mcontext,
>> + tsk, ksig->sig, NULL,
>> + (unsigned long)ksig->ka.sa.sa_handler,
>> + msr);
>> +
>> +#endif
>> if (!user_write_access_begin(frame, sizeof(*frame)))
>> goto badframe;
>>
>> @@ -889,19 +898,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
>> * ucontext_t (for transactional state) with its uc_link ptr.
>> */
>> unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link, badframe_block);
>> -
>> - user_write_access_end();
>> -
>> - err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
>> - &frame->uc_transact.uc_mcontext,
>> - tsk, ksig->sig, NULL,
>> - (unsigned long)ksig->ka.sa.sa_handler,
>> - msr);
>> -
>> - if (!user_write_access_begin(&frame->uc.uc_sigmask,
>> - sizeof(frame->uc.uc_sigmask)))
>> - goto badframe;
>> -
>> #endif
>> } else {
>> unsafe_put_user(0, &frame->uc.uc_link, badframe_block);
>
^ permalink raw reply
* Re: [PATCH v1 2/8] powerpc/signal64: Untangle setup_tm_sigcontexts() and user_access_begin()
From: David Laight @ 2026-05-22 11:12 UTC (permalink / raw)
To: Christophe Leroy (CS GROUP)
Cc: Michael Ellerman, Nicholas Piggin, Madhavan Srinivasan,
linux-kernel, linuxppc-dev
In-Reply-To: <7c83fe5a596514a02fde37da987a48d638d0d097.1779441786.git.chleroy@kernel.org>
On Fri, 22 May 2026 11:56:02 +0200
"Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
> Call setup_tm_sigcontexts() before opening user access to avoid
> having to close and open again.
>
> Signed-off-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
> ---
> arch/powerpc/kernel/signal_64.c | 22 +++++++++-------------
> 1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
> index 86bb5bb4c143..3849af21e1d8 100644
> --- a/arch/powerpc/kernel/signal_64.c
> +++ b/arch/powerpc/kernel/signal_64.c
> @@ -873,6 +873,15 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
> if (!MSR_TM_ACTIVE(msr))
> prepare_setup_sigcontext(tsk);
>
> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> + if (MSR_TM_ACTIVE(msr))
Can't that be done without the ugly #ifdef?
I assume MSR_TM_ACTIVE() will be zero - so it will all get optimised away.
-- David
> + err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
> + &frame->uc_transact.uc_mcontext,
> + tsk, ksig->sig, NULL,
> + (unsigned long)ksig->ka.sa.sa_handler,
> + msr);
> +
> +#endif
> if (!user_write_access_begin(frame, sizeof(*frame)))
> goto badframe;
>
> @@ -889,19 +898,6 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
> * ucontext_t (for transactional state) with its uc_link ptr.
> */
> unsafe_put_user(&frame->uc_transact, &frame->uc.uc_link, badframe_block);
> -
> - user_write_access_end();
> -
> - err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
> - &frame->uc_transact.uc_mcontext,
> - tsk, ksig->sig, NULL,
> - (unsigned long)ksig->ka.sa.sa_handler,
> - msr);
> -
> - if (!user_write_access_begin(&frame->uc.uc_sigmask,
> - sizeof(frame->uc.uc_sigmask)))
> - goto badframe;
> -
> #endif
> } else {
> unsafe_put_user(0, &frame->uc.uc_link, badframe_block);
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox