Page MenuHomeFreeBSD

D19565.id57415.diff
No OneTemporary

D19565.id57415.diff

Index: sys/compat/linuxkpi/common/include/asm/uaccess.h
===================================================================
--- sys/compat/linuxkpi/common/include/asm/uaccess.h
+++ sys/compat/linuxkpi/common/include/asm/uaccess.h
@@ -52,7 +52,11 @@
#define __copy_from_user(...) copy_from_user(__VA_ARGS__)
#define __copy_in_user(...) copy_from_user(__VA_ARGS__)
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
+#define user_access_begin(ptr, len) access_ok(ptr, len)
+#else
#define user_access_begin() do { } while (0)
+#endif
#define user_access_end() do { } while (0)
#define unsafe_get_user(x, ptr, err) do { \
Index: sys/compat/linuxkpi/common/include/linux/atomic.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/atomic.h
+++ sys/compat/linuxkpi/common/include/linux/atomic.h
@@ -31,5 +31,6 @@
#include <asm/atomic.h>
#include <asm/atomic64.h>
+#include <asm/atomic-long.h>
#endif /* _LINUX_ATOMIC_H_ */
Index: sys/compat/linuxkpi/common/include/linux/compiler.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/compiler.h
+++ sys/compat/linuxkpi/common/include/linux/compiler.h
@@ -81,6 +81,12 @@
#define barrier() __asm__ __volatile__("": : :"memory")
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
+/* Moved from drm_os_freebsd.h */
+#define lower_32_bits(n) ((u32)(n))
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+#endif
+
#define ___PASTE(a,b) a##b
#define __PASTE(a,b) ___PASTE(a,b)
Index: sys/compat/linuxkpi/common/include/linux/dma-mapping.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/dma-mapping.h
+++ sys/compat/linuxkpi/common/include/linux/dma-mapping.h
@@ -229,6 +229,7 @@
dma_sync_single(struct device *dev, dma_addr_t addr, size_t size,
enum dma_data_direction dir)
{
+
dma_sync_single_for_cpu(dev, addr, size, dir);
}
Index: sys/compat/linuxkpi/common/include/linux/fs.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/fs.h
+++ sys/compat/linuxkpi/common/include/linux/fs.h
@@ -323,4 +323,13 @@
#define shmem_truncate_range(...) \
linux_shmem_truncate_range(__VA_ARGS__)
+static inline int
+simple_open(struct inode *inode, struct file *file)
+{
+
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+ return (0);
+}
+
#endif /* _LINUX_FS_H_ */
Index: sys/compat/linuxkpi/common/include/linux/interrupt.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/interrupt.h
+++ sys/compat/linuxkpi/common/include/linux/interrupt.h
@@ -189,11 +189,14 @@
struct tasklet_struct {
TAILQ_ENTRY(tasklet_struct) entry;
tasklet_func_t *func;
+ /* Our state implementation is different. Avoid same name as Linux. */
+ volatile u_int _state;
+ atomic_t count;
unsigned long data;
};
#define DECLARE_TASKLET(name, func, data) \
-struct tasklet_struct name = { { NULL, NULL }, func, data }
+struct tasklet_struct name = { { NULL, NULL }, func, ATOMIC_INIT(0), data }
#define tasklet_hi_schedule(t) tasklet_schedule(t)
@@ -202,6 +205,10 @@
extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *,
unsigned long data);
extern void tasklet_enable(struct tasklet_struct *);
+extern bool tasklet_is_enabled(struct tasklet_struct *);
extern void tasklet_disable(struct tasklet_struct *);
+extern int tasklet_trylock(struct tasklet_struct *);
+extern void tasklet_unlock(struct tasklet_struct *);
+extern void tasklet_unlock_wait(struct tasklet_struct *ts);
#endif /* _LINUX_INTERRUPT_H_ */
Index: sys/compat/linuxkpi/common/include/linux/kernel.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/kernel.h
+++ sys/compat/linuxkpi/common/include/linux/kernel.h
@@ -130,9 +130,13 @@
#define ALIGN(x, y) roundup2((x), (y))
#undef PTR_ALIGN
#define PTR_ALIGN(p, a) ((__typeof(p))ALIGN((uintptr_t)(p), (a)))
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
+#define IS_ALIGNED(x, a) (((x) & ((__typeof(x))(a) - 1)) == 0)
+#endif
#define DIV_ROUND_UP(x, n) howmany(x, n)
#define __KERNEL_DIV_ROUND_UP(x, n) howmany(x, n)
#define DIV_ROUND_UP_ULL(x, n) DIV_ROUND_UP((unsigned long long)(x), (n))
+#define DIV_ROUND_DOWN_ULL(x, n) (((unsigned long long)(x) / (n)) * (n))
#define FIELD_SIZEOF(t, f) sizeof(((t *)0)->f)
#define printk(...) printf(__VA_ARGS__)
Index: sys/compat/linuxkpi/common/include/linux/ktime.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/ktime.h
+++ sys/compat/linuxkpi/common/include/linux/ktime.h
@@ -197,7 +197,7 @@
{
struct timespec ts;
- ktime_get_ts(&ts);
+ ktime_get_ts64(&ts);
return (ktime_to_ns(timespec_to_ktime(ts)));
}
@@ -207,7 +207,7 @@
{
struct timespec ts;
- ktime_get_ts(&ts);
+ ktime_get_ts64(&ts);
return (timespec_to_ktime(ts));
}
Index: sys/compat/linuxkpi/common/include/linux/preempt.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/preempt.h
+++ sys/compat/linuxkpi/common/include/linux/preempt.h
@@ -34,6 +34,9 @@
#define in_interrupt() \
(curthread->td_intr_nesting_level || curthread->td_critnest)
+#define in_task() \
+ (curthread->td_intr_nesting_level == 0 && curthread->td_critnest == 0)
+
#define preempt_disable() critical_enter()
#define preempt_enable() critical_exit()
Index: sys/compat/linuxkpi/common/include/linux/random.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/random.h
+++ sys/compat/linuxkpi/common/include/linux/random.h
@@ -35,6 +35,8 @@
#include <sys/random.h>
#include <sys/libkern.h>
+#define get_random_u32() get_random_int()
+
static inline void
get_random_bytes(void *buf, int nbytes)
{
Index: sys/compat/linuxkpi/common/include/linux/sched.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/sched.h
+++ sys/compat/linuxkpi/common/include/linux/sched.h
@@ -80,6 +80,7 @@
int rcu_recurse;
int bsd_interrupt_value;
struct work_struct *work; /* current work struct, if set */
+ struct task_struct *group_leader;
};
#define current ({ \
Index: sys/compat/linuxkpi/common/include/linux/uaccess.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/uaccess.h
+++ sys/compat/linuxkpi/common/include/linux/uaccess.h
@@ -60,12 +60,17 @@
#define get_user(_x, _p) linux_copyin((_p), &(_x), sizeof(*(_p)))
#define put_user(_x, _p) __put_user(_x, _p)
#define clear_user(...) linux_clear_user(__VA_ARGS__)
-#define access_ok(...) linux_access_ok(__VA_ARGS__)
+
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
+#define access_ok(a,b) linux_access_ok(a,b)
+#else
+#define access_ok(a,b,c) linux_access_ok(b,c)
+#endif
extern int linux_copyin(const void *uaddr, void *kaddr, size_t len);
extern int linux_copyout(const void *kaddr, void *uaddr, size_t len);
extern size_t linux_clear_user(void *uaddr, size_t len);
-extern int linux_access_ok(int rw, const void *uaddr, size_t len);
+extern int linux_access_ok(const void *uaddr, size_t len);
/*
* NOTE: Each pagefault_disable() call must have a corresponding
Index: sys/compat/linuxkpi/common/src/linux_compat.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_compat.c
+++ sys/compat/linuxkpi/common/src/linux_compat.c
@@ -897,7 +897,7 @@
}
int
-linux_access_ok(int rw, const void *uaddr, size_t len)
+linux_access_ok(const void *uaddr, size_t len)
{
uintptr_t saddr;
uintptr_t eaddr;
Index: sys/compat/linuxkpi/common/src/linux_current.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_current.c
+++ sys/compat/linuxkpi/common/src/linux_current.c
@@ -67,6 +67,7 @@
ts->task_thread = td;
ts->comm = td->td_name;
ts->pid = td->td_tid;
+ ts->group_leader = ts;
atomic_set(&ts->usage, 1);
atomic_set(&ts->state, TASK_RUNNING);
init_completion(&ts->parked);
Index: sys/compat/linuxkpi/common/src/linux_tasklet.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_tasklet.c
+++ sys/compat/linuxkpi/common/src/linux_tasklet.c
@@ -41,20 +41,22 @@
#define TASKLET_ST_BUSY 1
#define TASKLET_ST_EXEC 2
#define TASKLET_ST_LOOP 3
-#define TASKLET_ST_PAUSED 4
#define TASKLET_ST_CMPSET(ts, old, new) \
- atomic_cmpset_ptr((volatile uintptr_t *)&(ts)->entry.tqe_prev, old, new)
+ atomic_cmpset_int((volatile u_int *)&(ts)->_state, old, new)
#define TASKLET_ST_SET(ts, new) \
- WRITE_ONCE(*(volatile uintptr_t *)&(ts)->entry.tqe_prev, new)
+ WRITE_ONCE(*(volatile u_int *)&(ts)->_state, new)
#define TASKLET_ST_GET(ts) \
- READ_ONCE(*(volatile uintptr_t *)&(ts)->entry.tqe_prev)
+ READ_ONCE(*(volatile u_int *)&(ts)->_state)
+
+#define TASKLET_ST_TESTANDSET(ts, new) \
+ atomic_testandset_int((volatile u_int *)&(ts)->_state, new)
struct tasklet_worker {
struct mtx mtx;
- TAILQ_HEAD(, tasklet_struct) head;
+ TAILQ_HEAD(tasklet_list, tasklet_struct) head;
struct grouptask gtask;
} __aligned(CACHE_LINE_SIZE);
@@ -68,25 +70,34 @@
{
struct tasklet_worker *tw = (struct tasklet_worker *)arg;
struct tasklet_struct *ts;
+ struct tasklet_struct *last;
linux_set_current(curthread);
TASKLET_WORKER_LOCK(tw);
+ last = TAILQ_LAST(&tw->head, tasklet_list);
while (1) {
ts = TAILQ_FIRST(&tw->head);
if (ts == NULL)
break;
TAILQ_REMOVE(&tw->head, ts, entry);
- TASKLET_WORKER_UNLOCK(tw);
- do {
- /* reset executing state */
- TASKLET_ST_SET(ts, TASKLET_ST_EXEC);
-
- ts->func(ts->data);
-
- } while (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC, TASKLET_ST_IDLE) == 0);
- TASKLET_WORKER_LOCK(tw);
+ if (!atomic_read(&ts->count)) {
+ TASKLET_WORKER_UNLOCK(tw);
+ do {
+ /* reset executing state */
+ TASKLET_ST_SET(ts, TASKLET_ST_EXEC);
+
+ ts->func(ts->data);
+
+ } while (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC,
+ TASKLET_ST_IDLE) == 0);
+ TASKLET_WORKER_LOCK(tw);
+ } else {
+ TAILQ_INSERT_TAIL(&tw->head, ts, entry);
+ }
+ if (ts == last)
+ break;
}
TASKLET_WORKER_UNLOCK(tw);
}
@@ -140,6 +151,8 @@
ts->entry.tqe_next = NULL;
ts->func = func;
ts->data = data;
+ atomic_set_int(&(ts)->_state, TASKLET_ST_IDLE);
+ atomic_set(&ts->count, 0);
}
void
@@ -158,6 +171,10 @@
tasklet_schedule(struct tasklet_struct *ts)
{
+ /* tasklet is paused */
+ if (atomic_read(&ts->count))
+ return;
+
if (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC, TASKLET_ST_LOOP)) {
/* tasklet_handler() will loop */
} else if (TASKLET_ST_CMPSET(ts, TASKLET_ST_IDLE, TASKLET_ST_BUSY)) {
@@ -201,17 +218,47 @@
void
tasklet_enable(struct tasklet_struct *ts)
{
- (void) TASKLET_ST_CMPSET(ts, TASKLET_ST_PAUSED, TASKLET_ST_IDLE);
+
+ atomic_dec(&ts->count);
+}
+
+bool
+tasklet_is_enabled(struct tasklet_struct *ts)
+{
+
+ return !atomic_read(&ts->count);
}
void
tasklet_disable(struct tasklet_struct *ts)
{
- while (1) {
- if (TASKLET_ST_GET(ts) == TASKLET_ST_PAUSED)
- break;
- if (TASKLET_ST_CMPSET(ts, TASKLET_ST_IDLE, TASKLET_ST_PAUSED))
- break;
+
+ atomic_inc(&ts->count);
+ tasklet_unlock_wait(ts);
+ mb();
+}
+
+int
+tasklet_trylock(struct tasklet_struct *ts)
+{
+
+ return (!TASKLET_ST_TESTANDSET(ts, TASKLET_ST_BUSY));
+}
+
+void
+tasklet_unlock(struct tasklet_struct *ts)
+{
+
+ TASKLET_ST_SET(ts, TASKLET_ST_IDLE);
+}
+
+void
+tasklet_unlock_wait(struct tasklet_struct *ts)
+{
+
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "tasklet_kill() can sleep");
+
+ /* wait until tasklet is no longer busy */
+ while (TASKLET_ST_GET(ts) != TASKLET_ST_IDLE)
pause("W", 1);
- }
}

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 12, 8:38 AM (4 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17116485
Default Alt Text
D19565.id57415.diff (11 KB)

Event Timeline