Module Name: src Committed By: riastradh Date: Sun Dec 19 01:17:47 UTC 2021
Modified Files: src/sys/external/bsd/common/include/linux: tasklet.h src/sys/external/bsd/common/linux: linux_tasklet.c Log Message: Add some i915drmkms additions to the tasklet API. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/common/include/linux/tasklet.h cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/common/linux/linux_tasklet.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/common/include/linux/tasklet.h diff -u src/sys/external/bsd/common/include/linux/tasklet.h:1.3 src/sys/external/bsd/common/include/linux/tasklet.h:1.4 --- src/sys/external/bsd/common/include/linux/tasklet.h:1.3 Sun Dec 19 01:17:31 2021 +++ src/sys/external/bsd/common/include/linux/tasklet.h Sun Dec 19 01:17:46 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: tasklet.h,v 1.3 2021/12/19 01:17:31 riastradh Exp $ */ +/* $NetBSD: tasklet.h,v 1.4 2021/12/19 01:17:46 riastradh Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -34,9 +34,12 @@ /* namespace */ #define tasklet_disable linux_tasklet_disable +#define tasklet_disable_sync_once linux_tasklet_disable_sync_once #define tasklet_enable linux_tasklet_enable +#define tasklet_enable_sync_once linux_tasklet_enable_sync_once #define tasklet_hi_schedule linux_tasklet_hi_schedule #define tasklet_init linux_tasklet_init +#define tasklet_is_enabled linux_tasklet_is_enabled #define tasklet_kill linux_tasklet_kill #define tasklet_schedule linux_tasklet_schedule #define tasklet_struct linux_tasklet_struct @@ -78,4 +81,9 @@ void tasklet_schedule(struct tasklet_str void tasklet_hi_schedule(struct tasklet_struct *); void tasklet_kill(struct tasklet_struct *); +/* i915drmkms hack */ +void tasklet_disable_sync_once(struct tasklet_struct *); +void tasklet_enable_sync_once(struct tasklet_struct *); +bool tasklet_is_enabled(const struct tasklet_struct *); + #endif /* _LINUX_TASKLET_H_ */ Index: src/sys/external/bsd/common/linux/linux_tasklet.c diff -u src/sys/external/bsd/common/linux/linux_tasklet.c:1.2 src/sys/external/bsd/common/linux/linux_tasklet.c:1.3 --- src/sys/external/bsd/common/linux/linux_tasklet.c:1.2 Sun Dec 19 01:17:39 2021 +++ src/sys/external/bsd/common/linux/linux_tasklet.c Sun Dec 19 01:17:46 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_tasklet.c,v 1.2 2021/12/19 01:17:39 riastradh Exp $ */ +/* $NetBSD: linux_tasklet.c,v 1.3 2021/12/19 01:17:46 riastradh Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_tasklet.c,v 1.2 2021/12/19 01:17:39 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_tasklet.c,v 1.3 2021/12/19 01:17:46 riastradh Exp $"); #include <sys/types.h> #include <sys/atomic.h> @@ -470,3 +470,76 @@ tasklet_kill(struct tasklet_struct *task */ membar_sync(); } + +/* + * tasklet_disable_sync_once(tasklet) + * + * Increment the disable count of tasklet, and if this is the + * first time it was disabled and it was already running, + * busy-wait for it to complete. + * + * Caller must not care about whether the tasklet is running, or + * about waiting for any side effects of the tasklet to complete, + * if this was not the first time it was disabled. + */ +void +tasklet_disable_sync_once(struct tasklet_struct *tasklet) +{ + unsigned int disablecount; + + /* Increment the disable count. */ + disablecount = atomic_inc_uint_nv(&tasklet->tl_disablecount); + KASSERT(disablecount < UINT_MAX); + KASSERT(disablecount != 0); + + /* + * If it was zero, wait for it to finish running. If it was + * not zero, caller must not care whether it was running. + */ + if (disablecount == 1) { + while (tasklet->tl_state & TASKLET_RUNNING) + SPINLOCK_BACKOFF_HOOK; + membar_sync(); + } +} + +/* + * tasklet_enable_sync_once(tasklet) + * + * Decrement the disable count of tasklet, and if it goes to zero, + * kill tasklet. + */ +void +tasklet_enable_sync_once(struct tasklet_struct *tasklet) +{ + unsigned int disablecount; + + /* Decrement the disable count. */ + disablecount = atomic_dec_uint_nv(&tasklet->tl_disablecount); + KASSERT(disablecount < UINT_MAX); + + /* + * If it became zero, kill the tasklet. If it was not zero, + * caller must not care whether it was running. + */ + if (disablecount == 0) + tasklet_kill(tasklet); +} + +/* + * tasklet_is_enabled(tasklet) + * + * True if tasklet is not currently disabled. Answer may be stale + * as soon as it is returned -- caller must use it only as a hint, + * or must arrange synchronization externally. + */ +bool +tasklet_is_enabled(const struct tasklet_struct *tasklet) +{ + unsigned int disablecount; + + disablecount = tasklet->tl_disablecount; + __insn_barrier(); + + return (disablecount == 0); +}