Module Name: src Committed By: riastradh Date: Sun Dec 19 11:49:57 UTC 2021
Modified Files: src/sys/external/bsd/drm2/include/linux: irq_work.h src/sys/external/bsd/drm2/linux: files.drmkms_linux linux_module.c Added Files: src/sys/external/bsd/drm2/linux: linux_irq_work.c Log Message: linux: Draft irq_work shims, in terms of a softint. Doesn't actually run in hardirq context, but who's gonna notice... To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/sys/external/bsd/drm2/include/linux/irq_work.h cvs rdiff -u -r1.33 -r1.34 src/sys/external/bsd/drm2/linux/files.drmkms_linux cvs rdiff -u -r0 -r1.1 src/sys/external/bsd/drm2/linux/linux_irq_work.c cvs rdiff -u -r1.11 -r1.12 src/sys/external/bsd/drm2/linux/linux_module.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/external/bsd/drm2/include/linux/irq_work.h diff -u src/sys/external/bsd/drm2/include/linux/irq_work.h:1.5 src/sys/external/bsd/drm2/include/linux/irq_work.h:1.6 --- src/sys/external/bsd/drm2/include/linux/irq_work.h:1.5 Sun Dec 19 11:35:51 2021 +++ src/sys/external/bsd/drm2/include/linux/irq_work.h Sun Dec 19 11:49:57 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: irq_work.h,v 1.5 2021/12/19 11:35:51 riastradh Exp $ */ +/* $NetBSD: irq_work.h,v 1.6 2021/12/19 11:49:57 riastradh Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -29,6 +29,7 @@ #ifndef _LINUX_IRQ_WORK_H #define _LINUX_IRQ_WORK_H +#include <sys/queue.h> #include <sys/stdbool.h> #include <asm/cpufeature.h> @@ -38,11 +39,17 @@ #define irq_work_queue linux_irq_work_queue struct irq_work { + SIMPLEQ_ENTRY(irq_work) iw_entry; + volatile unsigned iw_flags; + /* Linux API */ - void (*func)(struct irq_work *); + void (*func)(struct irq_work *); }; void init_irq_work(struct irq_work *, void (*)(struct irq_work *)); bool irq_work_queue(struct irq_work *); +void linux_irq_work_init(void); +void linux_irq_work_fini(void); + #endif /* _LINUX_IRQ_WORK_H */ Index: src/sys/external/bsd/drm2/linux/files.drmkms_linux diff -u src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.33 src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.34 --- src/sys/external/bsd/drm2/linux/files.drmkms_linux:1.33 Sun Dec 19 11:39:24 2021 +++ src/sys/external/bsd/drm2/linux/files.drmkms_linux Sun Dec 19 11:49:57 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.drmkms_linux,v 1.33 2021/12/19 11:39:24 riastradh Exp $ +# $NetBSD: files.drmkms_linux,v 1.34 2021/12/19 11:49:57 riastradh Exp $ define drmkms_linux: i2cexec, i2c_bitbang @@ -16,6 +16,7 @@ file external/bsd/drm2/linux/linux_firmw file external/bsd/drm2/linux/linux_hrtimer.c drmkms_linux file external/bsd/drm2/linux/linux_i2c.c drmkms_linux file external/bsd/drm2/linux/linux_idr.c drmkms_linux +file external/bsd/drm2/linux/linux_irq_work.c drmkms_linux file external/bsd/drm2/linux/linux_kmap.c drmkms_linux file external/bsd/drm2/linux/linux_list_sort.c drmkms_linux file external/bsd/drm2/linux/linux_module.c drmkms_linux Index: src/sys/external/bsd/drm2/linux/linux_module.c diff -u src/sys/external/bsd/drm2/linux/linux_module.c:1.11 src/sys/external/bsd/drm2/linux/linux_module.c:1.12 --- src/sys/external/bsd/drm2/linux/linux_module.c:1.11 Sun Dec 19 01:22:15 2021 +++ src/sys/external/bsd/drm2/linux/linux_module.c Sun Dec 19 11:49:57 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_module.c,v 1.11 2021/12/19 01:22:15 riastradh Exp $ */ +/* $NetBSD: linux_module.c,v 1.12 2021/12/19 11:49:57 riastradh Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.11 2021/12/19 01:22:15 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_module.c,v 1.12 2021/12/19 11:49:57 riastradh Exp $"); #include <sys/module.h> #ifndef _MODULE @@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_module #include <linux/highmem.h> #include <linux/idr.h> #include <linux/io.h> +#include <linux/irq_work.h> #include <linux/mutex.h> #include <linux/rcupdate.h> #include <linux/tasklet.h> @@ -103,6 +104,8 @@ linux_init(void) goto fail7; } + linux_irq_work_init(); + return 0; fail8: __unused @@ -134,6 +137,7 @@ static void linux_fini(void) { + linux_irq_work_fini(); linux_wait_bit_fini(); linux_tasklets_fini(); linux_atomic64_fini(); Added files: Index: src/sys/external/bsd/drm2/linux/linux_irq_work.c diff -u /dev/null src/sys/external/bsd/drm2/linux/linux_irq_work.c:1.1 --- /dev/null Sun Dec 19 11:49:57 2021 +++ src/sys/external/bsd/drm2/linux/linux_irq_work.c Sun Dec 19 11:49:57 2021 @@ -0,0 +1,137 @@ +/* $NetBSD: linux_irq_work.c,v 1.1 2021/12/19 11:49:57 riastradh Exp $ */ + +/*- + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: linux_irq_work.c,v 1.1 2021/12/19 11:49:57 riastradh Exp $"); + +#include <sys/param.h> + +#include <sys/atomic.h> +#include <sys/intr.h> +#include <sys/mutex.h> +#include <sys/percpu.h> +#include <sys/queue.h> + +#include <linux/irq_work.h> + +struct irq_work_cpu { + kmutex_t iwc_lock; + SIMPLEQ_HEAD(, irq_work) iwc_todo; +}; + +enum { + IRQ_WORK_PENDING = 1, +}; + +static struct percpu *irq_work_percpu; +static void *irq_work_sih __read_mostly; + +static void +irq_work_intr(void *cookie) +{ + struct irq_work_cpu *iwc; + SIMPLEQ_HEAD(, irq_work) todo = SIMPLEQ_HEAD_INITIALIZER(todo); + struct irq_work *iw, *next; + + iwc = percpu_getref(irq_work_percpu); + mutex_spin_enter(&iwc->iwc_lock); + SIMPLEQ_CONCAT(&todo, &iwc->iwc_todo); + mutex_spin_exit(&iwc->iwc_lock); + percpu_putref(irq_work_percpu); + + SIMPLEQ_FOREACH_SAFE(iw, &todo, iw_entry, next) { + atomic_store_relaxed(&iw->iw_flags, 0); + (*iw->func)(iw); + } +} + +static void +irq_work_cpu_init(void *ptr, void *cookie, struct cpu_info *ci) +{ + struct irq_work_cpu *iwc = ptr; + + mutex_init(&iwc->iwc_lock, MUTEX_DEFAULT, IPL_HIGH); + SIMPLEQ_INIT(&iwc->iwc_todo); +} + +static void +irq_work_cpu_fini(void *ptr, void *cookie, struct cpu_info *ci) +{ + struct irq_work_cpu *iwc __diagused = ptr; + + KASSERT(SIMPLEQ_EMPTY(&iwc->iwc_todo)); + mutex_destroy(&iwc->iwc_lock); +} + +void +linux_irq_work_init(void) +{ + + irq_work_percpu = percpu_create(sizeof(struct irq_work_cpu), + irq_work_cpu_init, irq_work_cpu_fini, NULL); + irq_work_sih = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE, + irq_work_intr, NULL); +} + +void +linux_irq_work_fini(void) +{ + + softint_disestablish(irq_work_sih); + percpu_free(irq_work_percpu, sizeof(struct irq_work_cpu)); +} + +void +init_irq_work(struct irq_work *iw, void (*func)(struct irq_work *)) +{ + + iw->iw_flags = 0; + iw->func = func; +} + +bool +irq_work_queue(struct irq_work *iw) +{ + struct irq_work_cpu *iwc; + + if (atomic_swap_uint(&iw->iw_flags, IRQ_WORK_PENDING) + & IRQ_WORK_PENDING) + return false; + + iwc = percpu_getref(irq_work_percpu); + mutex_spin_enter(&iwc->iwc_lock); + SIMPLEQ_INSERT_TAIL(&iwc->iwc_todo, iw, iw_entry); + mutex_spin_exit(&iwc->iwc_lock); + softint_schedule(irq_work_sih); + percpu_putref(irq_work_percpu); + + return true; +}