Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160479430
D14016.id38310.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
36 KB
Referenced Files
None
Subscribers
None
D14016.id38310.diff
View Options
Index: sys/compat/linuxkpi/common/include/asm/atomic.h
===================================================================
--- sys/compat/linuxkpi/common/include/asm/atomic.h
+++ sys/compat/linuxkpi/common/include/asm/atomic.h
@@ -159,36 +159,43 @@
return (ret);
}
-#define cmpxchg(ptr, old, new) ({ \
- __typeof(*(ptr)) __ret; \
- \
- CTASSERT(sizeof(__ret) == 1 || sizeof(__ret) == 2 || \
- sizeof(__ret) == 4 || sizeof(__ret) == 8); \
- \
- __ret = (old); \
- switch (sizeof(__ret)) { \
- case 1: \
- while (!atomic_fcmpset_8((volatile int8_t *)(ptr), \
- (int8_t *)&__ret, (new)) && __ret == (old)) \
- ; \
- break; \
- case 2: \
- while (!atomic_fcmpset_16((volatile int16_t *)(ptr), \
- (int16_t *)&__ret, (new)) && __ret == (old)) \
- ; \
- break; \
- case 4: \
- while (!atomic_fcmpset_32((volatile int32_t *)(ptr), \
- (int32_t *)&__ret, (new)) && __ret == (old)) \
- ; \
- break; \
- case 8: \
- while (!atomic_fcmpset_64((volatile int64_t *)(ptr), \
- (int64_t *)&__ret, (new)) && __ret == (old)) \
- ; \
- break; \
- } \
- __ret; \
+#define cmpxchg(ptr, old, new) ({ \
+ union { \
+ __typeof(*(ptr)) val; \
+ u8 u8[0]; \
+ u16 u16[0]; \
+ u32 u32[0]; \
+ u64 u64[0]; \
+ } __ret = { .val = (old) }, __new = { .val = (new) }; \
+ \
+ CTASSERT(sizeof(__ret) == 1 || sizeof(__ret) == 2 || \
+ sizeof(__ret) == 4 || sizeof(__ret) == 8); \
+ \
+ switch (sizeof(__ret.val)) { \
+ case 1: \
+ while (!atomic_fcmpset_8((volatile u8 *)(ptr), \
+ __ret.u8, __new.u8[0]) && __ret.val == (old)) \
+ ; \
+ break; \
+ case 2: \
+ while (!atomic_fcmpset_16((volatile u16 *)(ptr), \
+ __ret.u16, __new.u16[0]) && __ret.val == (old)) \
+ ; \
+ break; \
+ case 4: \
+ while (!atomic_fcmpset_32((volatile u32 *)(ptr), \
+ __ret.u32, __new.u32[0]) && __ret.val == (old)) \
+ ; \
+ break; \
+ case 8: \
+ while (!atomic_fcmpset_64((volatile u64 *)(ptr), \
+ __ret.u64, __new.u64[0]) && __ret.val == (old)) \
+ ; \
+ break; \
+ default: \
+ break; \
+ } \
+ __ret.val; \
})
#define cmpxchg_relaxed(...) cmpxchg(__VA_ARGS__)
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
@@ -56,6 +56,8 @@
#define __devexit
#define __exit
#define __rcu
+#define __percpu
+#define __weak __attribute__((weak))
#define __malloc
#define ___stringify(...) #__VA_ARGS__
#define __stringify(...) ___stringify(__VA_ARGS__)
Index: sys/compat/linuxkpi/common/include/linux/dcache.h
===================================================================
--- /dev/null
+++ sys/compat/linuxkpi/common/include/linux/dcache.h
@@ -0,0 +1,41 @@
+#ifndef __LINUX_DCACHE_H
+#define __LINUX_DCACHE_H
+
+#include <linux/atomic.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/rcupdate.h>
+
+struct inode;
+struct dentry;
+struct path;
+struct pfs_node;
+#define HASH_LEN_DECLARE u32 hash; u32 len
+
+struct qstr {
+ union {
+ struct {
+ HASH_LEN_DECLARE;
+ };
+ u64 hash_len;
+ };
+ const unsigned char *name;
+};
+
+struct dentry {
+ struct inode *d_inode;
+ struct dentry *d_parent; /* parent directory */
+ struct qstr d_name;
+ /* FreeBSD */
+ struct pfs_node *d_pfs_node;
+};
+
+
+static inline struct inode *d_inode(const struct dentry *dentry)
+{
+ return dentry->d_inode;
+}
+
+#endif
Index: sys/compat/linuxkpi/common/include/linux/device.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/device.h
+++ sys/compat/linuxkpi/common/include/linux/device.h
@@ -46,9 +46,6 @@
#include <sys/bus.h>
-enum irqreturn { IRQ_NONE = 0, IRQ_HANDLED, IRQ_WAKE_THREAD, };
-typedef enum irqreturn irqreturn_t;
-
struct device;
struct fwnode_handle;
@@ -184,7 +181,7 @@
#define dev_notice(dev, fmt, ...) device_printf((dev)->bsddev, fmt, ##__VA_ARGS__)
#define dev_dbg(dev, fmt, ...) do { } while (0)
#define dev_printk(lvl, dev, fmt, ...) \
- device_printf((dev)->bsddev, fmt, ##__VA_ARGS__)
+ device_printf(((const struct device *)dev)->bsddev, fmt, ##__VA_ARGS__)
#define dev_err_ratelimited(dev, ...) do { \
static linux_ratelimit_t __ratelimited; \
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
@@ -42,6 +42,7 @@
#include <linux/wait.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
+#include <linux/dcache.h>
struct module;
struct kiocb;
@@ -65,11 +66,6 @@
typedef struct files_struct *fl_owner_t;
-struct dentry {
- struct inode *d_inode;
- struct pfs_node *d_pfs_node;
-};
-
struct file_operations;
struct linux_file_wait_queue {
@@ -288,6 +284,18 @@
return (file->_file->f_offset);
}
+static inline struct inode *
+file_inode(const struct file *f)
+{
+ return f->f_inode;
+}
+
+static inline int
+call_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ return file->f_op->mmap(file, vma);
+}
+
/* Shared memory support */
unsigned long linux_invalidate_mapping_pages(vm_object_t, pgoff_t, pgoff_t);
struct page *linux_shmem_read_mapping_page_gfp(vm_object_t, int, gfp_t);
Index: sys/compat/linuxkpi/common/include/linux/gfp.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/gfp.h
+++ sys/compat/linuxkpi/common/include/linux/gfp.h
@@ -55,6 +55,9 @@
#define __GFP_WAIT M_WAITOK
#define __GFP_DMA32 (1U << 24) /* LinuxKPI only */
+#define __GFP_BITS_SHIFT 25
+#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
+
#define GFP_NOWAIT M_NOWAIT
#define GFP_ATOMIC (M_NOWAIT | M_USE_RESERVE)
#define GFP_KERNEL M_WAITOK
Index: sys/compat/linuxkpi/common/include/linux/hardirq.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/hardirq.h
+++ sys/compat/linuxkpi/common/include/linux/hardirq.h
@@ -38,5 +38,7 @@
#include <sys/interrupt.h>
#define synchronize_irq(irq) _intr_drain((irq))
+#define disable_irq(irq) do { } while (0)
+#define enable_irq(irq) do { } while (0)
#endif /* _LINUX_HARDIRQ_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
@@ -33,13 +33,13 @@
#include <linux/device.h>
#include <linux/pci.h>
+#include <linux/irqreturn.h>
#include <sys/bus.h>
#include <sys/rman.h>
-typedef irqreturn_t (*irq_handler_t)(int, void *);
-#define IRQ_RETVAL(x) ((x) != IRQ_NONE)
+typedef irqreturn_t (*irq_handler_t)(int, void *);
#define IRQF_SHARED RF_SHAREABLE
@@ -169,4 +169,7 @@
extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *,
unsigned long data);
+extern void tasklet_enable(struct tasklet_struct *);
+extern void tasklet_disable(struct tasklet_struct *);
+
#endif /* _LINUX_INTERRUPT_H_ */
Index: sys/compat/linuxkpi/common/include/linux/irqreturn.h
===================================================================
--- /dev/null
+++ sys/compat/linuxkpi/common/include/linux/irqreturn.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_IRQRETURN_NEXT_H
+#define _LINUX_IRQRETURN_NEXT_H
+
+enum irqreturn {
+ IRQ_NONE = (0 << 0),
+ IRQ_HANDLED = (1 << 0),
+ IRQ_WAKE_THREAD = (1 << 1),
+};
+
+typedef enum irqreturn irqreturn_t;
+#define IRQ_RETVAL(x) ((x) ? IRQ_HANDLED : IRQ_NONE)
+
+
+#endif
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
@@ -89,6 +89,7 @@
#define BUILD_BUG_ON(x) CTASSERT(!(x))
#define BUILD_BUG_ON_MSG(x, msg) BUILD_BUG_ON(x)
#define BUILD_BUG_ON_NOT_POWER_OF_2(x) BUILD_BUG_ON(!powerof2(x))
+#define BUILD_BUG_ON_INVALID(expr) ((void)(sizeof((__force long)(expr))))
#define BUG() panic("BUG at %s:%d", __FILE__, __LINE__)
#define BUG_ON(cond) do { \
Index: sys/compat/linuxkpi/common/include/linux/kref.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/kref.h
+++ sys/compat/linuxkpi/common/include/linux/kref.h
@@ -52,6 +52,12 @@
refcount_init(&kref->refcount.counter, 1);
}
+static inline unsigned int
+kref_read(const struct kref *kref)
+{
+ return atomic_read(&kref->refcount);
+}
+
static inline void
kref_get(struct kref *kref)
{
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
@@ -37,11 +37,7 @@
#define ktime_get_ts(x) getnanouptime(x)
/* time values in nanoseconds */
-union ktime {
- int64_t tv64;
-};
-
-typedef union ktime ktime_t;
+typedef s64 ktime_t;
#define KTIME_MAX ((s64)~((u64)1 << 63))
#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)
@@ -49,22 +45,19 @@
static inline int64_t
ktime_to_ns(ktime_t kt)
{
- return kt.tv64;
+ return kt;
}
-static inline ktime_t
+static inline s64
ns_to_ktime(uint64_t nsec)
{
- ktime_t kt;
-
- kt.tv64 = nsec;
- return (kt);
+ return (nsec);
}
static inline int64_t
ktime_divns(const ktime_t kt, int64_t div)
{
- return kt.tv64 / div;
+ return kt / div;
}
static inline int64_t
@@ -82,7 +75,7 @@
static inline struct timeval
ktime_to_timeval(ktime_t kt)
{
- return ns_to_timeval(kt.tv64);
+ return ns_to_timeval(kt);
}
static inline ktime_t
@@ -90,7 +83,7 @@
{
ktime_t res;
- res.tv64 = kt.tv64 + ns;
+ res = kt + ns;
return kt;
}
@@ -99,7 +92,7 @@
{
ktime_t res;
- res.tv64 = kt.tv64 - ns;
+ res = kt - ns;
return kt;
}
@@ -113,7 +106,7 @@
static inline ktime_t
ktime_sub(ktime_t lhs, ktime_t rhs)
{
- lhs.tv64 -= rhs.tv64;
+ lhs -= rhs;
return (lhs);
}
@@ -134,7 +127,7 @@
static inline ktime_t
ktime_add(ktime_t lhs, ktime_t rhs)
{
- lhs.tv64 += rhs.tv64;
+ lhs += rhs;
return (lhs);
}
@@ -150,9 +143,9 @@
return (ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC));
}
-#define ktime_to_timespec(kt) ns_to_timespec((kt).tv64)
-#define ktime_to_timeval(kt) ns_to_timeval((kt).tv64)
-#define ktime_to_ns(kt) ((kt).tv64)
+#define ktime_to_timespec(kt) ns_to_timespec((kt))
+#define ktime_to_timeval(kt) ns_to_timeval((kt))
+#define ktime_to_ns(kt) (kt)
static inline int64_t
ktime_get_ns(void)
@@ -165,8 +158,6 @@
return (ktime_to_ns(kt));
}
-#define ktime_get_raw_ns() ktime_get_ns()
-
static inline ktime_t
ktime_get(void)
{
@@ -194,4 +185,25 @@
return (timespec_to_ktime(ts));
}
+static inline ktime_t
+ktime_get_real_seconds(void)
+{
+ struct timespec ts;
+ ktime_t kt;
+
+ nanotime(&ts);
+ kt = ts.tv_sec;
+ return (kt);
+}
+
+static inline u64
+ktime_get_raw_ns(void)
+{
+ struct timespec ts;
+
+ nanouptime(&ts);
+
+ return (ts.tv_sec * NSEC_PER_SEC) + ts.tv_nsec;
+}
+
#endif /* _LINUX_KTIME_H */
Index: sys/compat/linuxkpi/common/include/linux/list.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/list.h
+++ sys/compat/linuxkpi/common/include/linux/list.h
@@ -70,6 +70,10 @@
#include <vm/vm_object.h>
#include <vm/pmap.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
#ifndef prefetch
#define prefetch(x)
#endif
@@ -116,6 +120,15 @@
WRITE_ONCE(prev->next, next);
}
+static inline void
+__list_del_entry(struct list_head *entry)
+{
+ // if (!__list_del_entry_valid(entry))
+ // return;
+
+ __list_del(entry->prev, entry->next);
+}
+
static inline void
list_del(struct list_head *entry)
{
@@ -218,6 +231,9 @@
#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = (p)->prev)
+#define list_safe_reset_next(pos, n, member) \
+ n = list_entry(pos->member.next, typeof(*pos), member)
+
static inline void
list_add(struct list_head *new, struct list_head *head)
{
Index: sys/compat/linuxkpi/common/include/linux/lockdep.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/lockdep.h
+++ sys/compat/linuxkpi/common/include/linux/lockdep.h
@@ -47,6 +47,13 @@
#define lockdep_is_held(m) (sx_xholder(&(m)->sx) == curthread)
+// XXX: experimental (johalun 20170913)
+#define lock_is_held(m) lockdep_is_held(m)
+
#define might_lock(m) do { } while (0)
+#define might_lock_read(lock) do { } while (0)
+
+#define lock_acquire(l, s, t, r, c, n, i) do { } while (0)
+#define lock_release(l, n, i) do { } while (0)
#endif /* _LINUX_LOCKDEP_H_ */
Index: sys/compat/linuxkpi/common/include/linux/mm.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/mm.h
+++ sys/compat/linuxkpi/common/include/linux/mm.h
@@ -37,6 +37,7 @@
#include <linux/gfp.h>
#include <linux/kernel.h>
#include <linux/mm_types.h>
+#include <linux/mmzone.h>
#include <linux/pfn.h>
#include <linux/list.h>
@@ -118,14 +119,15 @@
struct vm_fault {
unsigned int flags;
pgoff_t pgoff;
- void *virtual_address; /* user-space address */
+ unsigned long address; /* user-space address */
struct page *page;
+ struct vm_area_struct *vma;
};
struct vm_operations_struct {
void (*open) (struct vm_area_struct *);
void (*close) (struct vm_area_struct *);
- int (*fault) (struct vm_area_struct *, struct vm_fault *);
+ int (*fault) (struct vm_fault *);
};
/*
@@ -237,7 +239,7 @@
get_user_pages_remote(struct task_struct *, struct mm_struct *,
unsigned long start, unsigned long nr_pages,
int gup_flags, struct page **,
- struct vm_area_struct **);
+ struct vm_area_struct **, int *locked);
static inline void
put_page(struct vm_page *page)
Index: sys/compat/linuxkpi/common/include/linux/mm_types.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/mm_types.h
+++ sys/compat/linuxkpi/common/include/linux/mm_types.h
@@ -62,6 +62,12 @@
mmdrop(mm);
}
+static inline void
+mmgrab(struct mm_struct *mm)
+{
+ atomic_inc(&mm->mm_count);
+}
+
extern struct mm_struct *linux_get_task_mm(struct task_struct *);
#define get_task_mm(task) linux_get_task_mm(task)
Index: sys/compat/linuxkpi/common/include/linux/mmzone.h
===================================================================
--- /dev/null
+++ sys/compat/linuxkpi/common/include/linux/mmzone.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_MMZONE_H_
+#define _LINUX_MMZONE_H_
+
+
+// Needed by i915_gem_internal.c
+#define MAX_ORDER 11
+
+
+
+#endif
Index: sys/compat/linuxkpi/common/include/linux/mutex.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/mutex.h
+++ sys/compat/linuxkpi/common/include/linux/mutex.h
@@ -128,4 +128,19 @@
sx_destroy(&m->sx);
}
-#endif /* _LINUX_MUTEX_H_ */
+enum mutex_trylock_recursive_enum {
+ MUTEX_TRYLOCK_FAILED = 0,
+ MUTEX_TRYLOCK_SUCCESS = 1,
+ MUTEX_TRYLOCK_RECURSIVE,
+};
+
+static inline /* __deprecated */ __must_check enum mutex_trylock_recursive_enum
+mutex_trylock_recursive(struct mutex *lock)
+{
+ if (unlikely(sx_xholder(&lock->sx) == curthread))
+ return MUTEX_TRYLOCK_RECURSIVE;
+
+ return mutex_trylock(lock);
+}
+
+#endif /* _LINUX_MUTEX_H_ */
Index: sys/compat/linuxkpi/common/include/linux/pid.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/pid.h
+++ sys/compat/linuxkpi/common/include/linux/pid.h
@@ -52,10 +52,15 @@
})
#define get_pid_task(pid, type) ({ \
- struct task_struct *__ts; \
+ struct task_struct *__ts; \
CTASSERT((type) == PIDTYPE_PID); \
__ts = linux_get_pid_task(pid); \
- __ts; \
+ __ts; \
+})
+
+#define get_task_pid(task, type) ({ \
+ CTASSERT((type) == PIDTYPE_PID); \
+ curthread->td_tid; \
})
struct task_struct;
Index: sys/compat/linuxkpi/common/include/linux/printk.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/printk.h
+++ sys/compat/linuxkpi/common/include/linux/printk.h
@@ -106,6 +106,13 @@
print_hex_dump(NULL, prefix_str, prefix_type, 16, 1, buf, len, 0);
}
+static inline int
+printk_ratelimit() {
+ // XXX: Used in amdgpu/gmc_v{6,7,8}_0.c
+ // Return 0 means no dev_err output.
+ return 1;
+}
+
#define printk_ratelimited(...) do { \
static linux_ratelimit_t __ratelimited; \
if (linux_ratelimited(&__ratelimited)) \
Index: sys/compat/linuxkpi/common/include/linux/radix-tree.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/radix-tree.h
+++ sys/compat/linuxkpi/common/include/linux/radix-tree.h
@@ -32,6 +32,11 @@
#define _LINUX_RADIX_TREE_H_
#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/rcupdate.h>
+
+#define RADIX_TREE_MAX_TAGS 3
#define RADIX_TREE_MAP_SHIFT 6
#define RADIX_TREE_MAP_SIZE (1 << RADIX_TREE_MAP_SHIFT)
@@ -39,9 +44,14 @@
#define RADIX_TREE_MAX_HEIGHT \
DIV_ROUND_UP((sizeof(long) * NBBY), RADIX_TREE_MAP_SHIFT)
+#define RADIX_TREE_TAG_LONGS \
+ ((RADIX_TREE_MAP_SIZE + BITS_PER_LONG - 1) / BITS_PER_LONG)
+
struct radix_tree_node {
+ unsigned char shift;
void *slots[RADIX_TREE_MAP_SIZE];
int count;
+ unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
};
struct radix_tree_root {
@@ -61,4 +71,180 @@
void *radix_tree_delete(struct radix_tree_root *, unsigned long);
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
+
+
+
+
+// Radix Tree Iterator impl
+// Review needed!
+
+#define RADIX_TREE_ENTRY_MASK 3UL
+#define RADIX_TREE_INTERNAL_NODE 1UL
+#define RADIX_TREE_EXCEPTIONAL_ENTRY 2
+#define RADIX_TREE_EXCEPTIONAL_SHIFT 2
+#define ROOT_IS_IDR ((__force gfp_t)(1 << __GFP_BITS_SHIFT))
+#define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT + 1)
+
+struct radix_tree_iter {
+ unsigned long index;
+ unsigned long next_index;
+ unsigned long tags;
+ struct radix_tree_node *node;
+#ifdef CONFIG_RADIX_TREE_MULTIORDER // Probably not using this?
+ unsigned int shift;
+#endif
+};
+
+enum {
+ RADIX_TREE_ITER_TAG_MASK = 0x0f, /* tag index in lower nybble */
+ RADIX_TREE_ITER_TAGGED = 0x10, /* lookup tagged slots */
+ RADIX_TREE_ITER_CONTIG = 0x20, /* stop at first hole */
+};
+
+static inline int radix_tree_exception(void *arg)
+{
+ return unlikely((unsigned long)arg & RADIX_TREE_ENTRY_MASK);
+}
+
+static inline bool radix_tree_is_internal_node(void *ptr)
+{
+ return ((unsigned long)ptr & RADIX_TREE_ENTRY_MASK) ==
+ RADIX_TREE_INTERNAL_NODE;
+}
+
+static inline unsigned int iter_shift(const struct radix_tree_iter *iter)
+{
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
+ return iter->shift;
+#else
+ return 0;
+#endif
+}
+
+
+void __rcu **radix_tree_next_chunk(const struct radix_tree_root *,
+ struct radix_tree_iter *iter, unsigned flags);
+
+
+
+static __always_inline void __rcu **
+radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start)
+{
+ /*
+ * Leave iter->tags uninitialized. radix_tree_next_chunk() will fill it
+ * in the case of a successful tagged chunk lookup. If the lookup was
+ * unsuccessful or non-tagged then nobody cares about ->tags.
+ *
+ * Set index to zero to bypass next_index overflow protection.
+ * See the comment in radix_tree_next_chunk() for details.
+ */
+ iter->index = 0;
+ iter->next_index = start;
+ return NULL;
+}
+
+
+static inline void __rcu **
+radix_tree_iter_lookup(const struct radix_tree_root *root,
+ struct radix_tree_iter *iter, unsigned long index)
+{
+ radix_tree_iter_init(iter, index);
+ return radix_tree_next_chunk(root, iter, RADIX_TREE_ITER_CONTIG);
+}
+
+static inline void __rcu **
+radix_tree_iter_find(const struct radix_tree_root *root,
+ struct radix_tree_iter *iter, unsigned long index)
+{
+ radix_tree_iter_init(iter, index);
+ return radix_tree_next_chunk(root, iter, 0);
+}
+
+static inline __must_check
+void __rcu **radix_tree_iter_retry(struct radix_tree_iter *iter)
+{
+ iter->next_index = iter->index;
+ iter->tags = 0;
+ return NULL;
+}
+
+static inline unsigned long
+__radix_tree_iter_add(struct radix_tree_iter *iter, unsigned long slots)
+{
+ return iter->index + (slots << iter_shift(iter));
+}
+
+void __rcu **__must_check radix_tree_iter_resume(void __rcu **slot,
+ struct radix_tree_iter *iter);
+
+static __always_inline long
+radix_tree_chunk_size(struct radix_tree_iter *iter)
+{
+ return (iter->next_index - iter->index) >> iter_shift(iter);
+}
+
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
+void __rcu **__radix_tree_next_slot(void __rcu **slot,
+ struct radix_tree_iter *iter, unsigned flags);
+#else
+/* Can't happen without sibling entries, but the compiler can't tell that */
+static inline void __rcu **__radix_tree_next_slot(void __rcu **slot,
+ struct radix_tree_iter *iter, unsigned flags)
+{
+ return slot;
+}
+#endif
+
+static __always_inline void __rcu **radix_tree_next_slot(void __rcu **slot,
+ struct radix_tree_iter *iter, unsigned flags)
+{
+ if (flags & RADIX_TREE_ITER_TAGGED) {
+ iter->tags >>= 1;
+ if (unlikely(!iter->tags))
+ return NULL;
+ if (likely(iter->tags & 1ul)) {
+ iter->index = __radix_tree_iter_add(iter, 1);
+ slot++;
+ goto found;
+ }
+ if (!(flags & RADIX_TREE_ITER_CONTIG)) {
+ unsigned offset = __ffs(iter->tags);
+
+ iter->tags >>= offset++;
+ iter->index = __radix_tree_iter_add(iter, offset);
+ slot += offset;
+ goto found;
+ }
+ } else {
+ long count = radix_tree_chunk_size(iter);
+
+ while (--count > 0) {
+ slot++;
+ iter->index = __radix_tree_iter_add(iter, 1);
+
+ if (likely(*slot))
+ goto found;
+ if (flags & RADIX_TREE_ITER_CONTIG) {
+ /* forbid switching to the next chunk */
+ iter->next_index = 0;
+ break;
+ }
+ }
+ }
+ return NULL;
+
+ found:
+ if (unlikely(radix_tree_is_internal_node(rcu_dereference_raw(*slot))))
+ return __radix_tree_next_slot(slot, iter, flags);
+ return slot;
+}
+
+
+#define radix_tree_for_each_slot(slot, root, iter, start) \
+ for (slot = radix_tree_iter_init(iter, start) ; \
+ slot || (slot = radix_tree_next_chunk(root, iter, 0)) ; \
+ slot = radix_tree_next_slot(slot, iter, 0))
+
+
+
#endif /* _LINUX_RADIX_TREE_H_ */
Index: sys/compat/linuxkpi/common/include/linux/rcupdate.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/rcupdate.h
+++ sys/compat/linuxkpi/common/include/linux/rcupdate.h
@@ -82,6 +82,11 @@
#define rcu_dereference(p) \
rcu_dereference_protected(p, 0)
+// Review needed!
+// Added rcu_dereference_raw, is this OK?
+#define rcu_dereference_raw(p) \
+ ((__typeof(*p) *)(p))
+
#define rcu_pointer_handoff(p) (p)
#define rcu_assign_pointer(p, v) do { \
Index: sys/compat/linuxkpi/common/include/linux/slab.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/slab.h
+++ sys/compat/linuxkpi/common/include/linux/slab.h
@@ -65,6 +65,11 @@
#define kmem_cache_free(...) linux_kmem_cache_free(__VA_ARGS__)
#define kmem_cache_destroy(...) linux_kmem_cache_destroy(__VA_ARGS__)
+#define KMEM_CACHE(__struct, __flags) \
+ kmem_cache_create(#__struct, \
+ sizeof(struct __struct), __alignof__(struct __struct), \
+ (__flags), NULL)
+
typedef void linux_kmem_ctor_t (void *);
struct linux_kmem_cache {
Index: sys/compat/linuxkpi/common/include/linux/spinlock.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/spinlock.h
+++ sys/compat/linuxkpi/common/include/linux/spinlock.h
@@ -98,6 +98,9 @@
__ret; \
})
+#define spin_trylock_irq(_l) \
+ spin_trylock(_l)
+
#define spin_lock_nested(_l, _n) do { \
if (SPIN_SKIP()) \
break; \
Index: sys/compat/linuxkpi/common/include/linux/string.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/string.h
+++ sys/compat/linuxkpi/common/include/linux/string.h
@@ -70,6 +70,22 @@
return (retval);
}
+static inline void *
+memdup_user_nul(const void *ptr, size_t len)
+{
+ char *retval;
+ int error;
+
+ retval = malloc(len + 1, M_KMALLOC, M_WAITOK);
+ error = linux_copyin(ptr, retval, len);
+ if (error != 0) {
+ free(retval, M_KMALLOC);
+ return (ERR_PTR(error));
+ }
+ retval[len] = '\0';
+ return (retval);
+}
+
static inline void *
kmemdup(const void *src, size_t len, gfp_t gfp)
{
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
@@ -58,7 +58,7 @@
linux_copyout(&(__x), (_p), sizeof(*(_p))); \
})
#define get_user(_x, _p) linux_copyin((_p), &(_x), sizeof(*(_p)))
-#define put_user(_x, _p) linux_copyout(&(_x), (_p), 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__)
Index: sys/compat/linuxkpi/common/include/linux/wait.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/wait.h
+++ sys/compat/linuxkpi/common/include/linux/wait.h
@@ -36,6 +36,7 @@
#include <linux/compiler.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#include <linux/lockdep.h>
#include <asm/atomic.h>
@@ -96,10 +97,14 @@
}; \
MTX_SYSINIT(name, &(name).lock.m, spin_lock_name("wqhead"), MTX_DEF)
-#define init_waitqueue_head(wqh) do { \
- mtx_init(&(wqh)->lock.m, spin_lock_name("wqhead"), \
- NULL, MTX_DEF | MTX_NEW | MTX_NOWITNESS); \
- INIT_LIST_HEAD(&(wqh)->task_list); \
+static inline void
+__init_waitqueue_head(wait_queue_head_t *wqh, __unused const void *name, __unused void *key) {
+ mtx_init(&(wqh)->lock.m, spin_lock_name("wqhead"), NULL, MTX_DEF | MTX_NEW | MTX_NOWITNESS);
+ INIT_LIST_HEAD(&(wqh)->task_list);
+}
+
+#define init_waitqueue_head(wqh) do { \
+ __init_waitqueue_head(wqh, NULL, NULL); \
} while (0)
void linux_wake_up(wait_queue_head_t *, unsigned int, int, bool);
@@ -133,8 +138,10 @@
\
for (;;) { \
linux_prepare_to_wait(&(wqh), &__wq, state); \
- if (cond) \
+ if (cond) { \
+ __ret = 1; \
break; \
+ } \
__ret = linux_wait_event_common(&(wqh), &__wq, \
__timeout, state, lock); \
if (__ret != 0) \
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
@@ -189,7 +189,7 @@
}
if (error)
sysfs_remove_dir(kobj);
-
+
}
return (error);
}
@@ -545,20 +545,21 @@
struct vm_fault vmf;
/* fill out VM fault structure */
- vmf.virtual_address = (void *)((uintptr_t)pidx << PAGE_SHIFT);
+ vmf.address = (unsigned long)((uintptr_t)pidx << PAGE_SHIFT);
vmf.flags = (fault_type & VM_PROT_WRITE) ? FAULT_FLAG_WRITE : 0;
vmf.pgoff = 0;
vmf.page = NULL;
+ vmf.vma = vmap;
vmap->vm_pfn_count = 0;
vmap->vm_pfn_pcount = &vmap->vm_pfn_count;
vmap->vm_obj = vm_obj;
- err = vmap->vm_ops->fault(vmap, &vmf);
+ err = vmap->vm_ops->fault(&vmf);
while (vmap->vm_pfn_count == 0 && err == VM_FAULT_NOPAGE) {
kern_yield(PRI_USER);
- err = vmap->vm_ops->fault(vmap, &vmf);
+ err = vmap->vm_ops->fault(&vmf);
}
}
@@ -1712,7 +1713,7 @@
{
timer->expires = expires;
- callout_reset(&timer->timer_callout,
+ callout_reset(&timer->timer_callout,
linux_timer_jiffies_until(expires),
&linux_timer_callback_wrapper, timer);
}
Index: sys/compat/linuxkpi/common/src/linux_hrtimer.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_hrtimer.c
+++ sys/compat/linuxkpi/common/src/linux_hrtimer.c
@@ -98,7 +98,7 @@
{
mtx_lock(&hrtimer->mtx);
- callout_reset_sbt(&hrtimer->callout, nstosbt(time.tv64), nstosbt(nsec),
+ callout_reset_sbt(&hrtimer->callout, nstosbt(time), nstosbt(nsec),
hrtimer_call_handler, hrtimer, 0);
mtx_unlock(&hrtimer->mtx);
}
Index: sys/compat/linuxkpi/common/src/linux_page.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_page.c
+++ sys/compat/linuxkpi/common/src/linux_page.c
@@ -267,7 +267,7 @@
long
get_user_pages_remote(struct task_struct *task, struct mm_struct *mm,
unsigned long start, unsigned long nr_pages, int gup_flags,
- struct page **pages, struct vm_area_struct **vmas)
+ struct page **pages, struct vm_area_struct **vmas, int *locked)
{
vm_map_t map;
Index: sys/compat/linuxkpi/common/src/linux_radix.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_radix.c
+++ sys/compat/linuxkpi/common/src/linux_radix.c
@@ -216,3 +216,250 @@
return (0);
}
+
+
+
+
+// Radix Tree Iterator impl
+// Review needed!
+
+static inline void __set_iter_shift(struct radix_tree_iter *iter,
+ unsigned int shift)
+{
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
+ iter->shift = shift;
+#endif
+}
+
+static unsigned int iter_offset(const struct radix_tree_iter *iter)
+{
+ return (iter->index >> iter_shift(iter)) & RADIX_TREE_MAP_MASK;
+}
+
+static inline struct radix_tree_node *entry_to_node(void *ptr)
+{
+ return (void *)((unsigned long)ptr & ~RADIX_TREE_INTERNAL_NODE);
+}
+
+static inline unsigned long shift_maxindex(unsigned int shift)
+{
+ return (RADIX_TREE_MAP_SIZE << shift) - 1;
+}
+
+static inline unsigned long node_maxindex(const struct radix_tree_node *node)
+{
+ return shift_maxindex(node->shift);
+}
+
+static unsigned radix_tree_load_root(const struct radix_tree_root *root,
+ struct radix_tree_node **nodep, unsigned long *maxindex)
+{
+ struct radix_tree_node *node = rcu_dereference_raw(root->rnode);
+
+ *nodep = node;
+
+ if (likely(radix_tree_is_internal_node(node))) {
+ node = entry_to_node(node);
+ *maxindex = node_maxindex(node);
+ return node->shift + RADIX_TREE_MAP_SHIFT;
+ }
+
+ *maxindex = 0;
+ return 0;
+}
+
+static __always_inline unsigned long
+radix_tree_find_next_bit(struct radix_tree_node *node, unsigned int tag,
+ unsigned long offset)
+{
+ const unsigned long *addr = node->tags[tag];
+
+ if (offset < RADIX_TREE_MAP_SIZE) {
+ unsigned long tmp;
+
+ addr += offset / BITS_PER_LONG;
+ tmp = *addr >> (offset % BITS_PER_LONG);
+ if (tmp)
+ return __ffs(tmp) + offset;
+ offset = (offset + BITS_PER_LONG) & ~(BITS_PER_LONG - 1);
+ while (offset < RADIX_TREE_MAP_SIZE) {
+ tmp = *++addr;
+ if (tmp)
+ return __ffs(tmp) + offset;
+ offset += BITS_PER_LONG;
+ }
+ }
+ return RADIX_TREE_MAP_SIZE;
+}
+
+static inline void *node_to_entry(void *ptr)
+{
+ return (void *)((unsigned long)ptr | RADIX_TREE_INTERNAL_NODE);
+}
+
+#define RADIX_TREE_RETRY node_to_entry(NULL)
+
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
+/* Sibling slots point directly to another slot in the same node */
+static inline
+bool is_sibling_entry(const struct radix_tree_node *parent, void *node)
+{
+ void __rcu **ptr = node;
+ return (parent->slots <= ptr) &&
+ (ptr < parent->slots + RADIX_TREE_MAP_SIZE);
+}
+#else
+static inline
+bool is_sibling_entry(const struct radix_tree_node *parent, void *node)
+{
+ return false;
+}
+#endif
+
+/* Construct iter->tags bit-mask from node->tags[tag] array */
+static void set_iter_tags(struct radix_tree_iter *iter,
+ struct radix_tree_node *node, unsigned offset,
+ unsigned tag)
+{
+ unsigned tag_long = offset / BITS_PER_LONG;
+ unsigned tag_bit = offset % BITS_PER_LONG;
+
+ if (!node) {
+ iter->tags = 1;
+ return;
+ }
+
+ iter->tags = node->tags[tag][tag_long] >> tag_bit;
+
+ /* This never happens if RADIX_TREE_TAG_LONGS == 1 */
+ if (tag_long < RADIX_TREE_TAG_LONGS - 1) {
+ /* Pick tags from next element */
+ if (tag_bit)
+ iter->tags |= node->tags[tag][tag_long + 1] <<
+ (BITS_PER_LONG - tag_bit);
+ /* Clip chunk size, here only BITS_PER_LONG tags */
+ iter->next_index = __radix_tree_iter_add(iter, BITS_PER_LONG);
+ }
+}
+
+static inline int tag_get(const struct radix_tree_node *node, unsigned int tag,
+ int offset)
+{
+ return test_bit(offset, __DECONST(unsigned long *, node->tags[tag]));
+}
+
+static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag)
+{
+ return (__force int)root->gfp_mask & (1 << (tag + ROOT_TAG_SHIFT));
+}
+
+static unsigned int radix_tree_descend(const struct radix_tree_node *parent,
+ struct radix_tree_node **nodep, unsigned long index)
+{
+ unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK;
+ void __rcu **entry = rcu_dereference_raw(parent->slots[offset]);
+
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
+ if (radix_tree_is_internal_node(entry)) {
+ if (is_sibling_entry(parent, entry)) {
+ void __rcu **sibentry;
+ sibentry = (void __rcu **) entry_to_node(entry);
+ offset = get_slot_offset(parent, sibentry);
+ entry = rcu_dereference_raw(*sibentry);
+ }
+ }
+#endif
+
+ *nodep = (void *)entry;
+ return offset;
+}
+
+void __rcu **radix_tree_next_chunk(const struct radix_tree_root *root,
+ struct radix_tree_iter *iter, unsigned flags)
+{
+ unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
+ struct radix_tree_node *node, *child;
+ unsigned long index, offset, maxindex;
+
+ if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
+ return NULL;
+
+ /*
+ * Catch next_index overflow after ~0UL. iter->index never overflows
+ * during iterating; it can be zero only at the beginning.
+ * And we cannot overflow iter->next_index in a single step,
+ * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG.
+ *
+ * This condition also used by radix_tree_next_slot() to stop
+ * contiguous iterating, and forbid switching to the next chunk.
+ */
+ index = iter->next_index;
+ if (!index && iter->index)
+ return NULL;
+
+ restart:
+ radix_tree_load_root(root, &child, &maxindex);
+ if (index > maxindex)
+ return NULL;
+ if (!child)
+ return NULL;
+
+ if (!radix_tree_is_internal_node(child)) {
+ /* Single-slot tree */
+ iter->index = index;
+ iter->next_index = maxindex + 1;
+ iter->tags = 1;
+ iter->node = NULL;
+ __set_iter_shift(iter, 0);
+ return __DECONST(void __rcu **, &root->rnode);
+ }
+
+ do {
+ node = entry_to_node(child);
+ offset = radix_tree_descend(node, &child, index);
+
+ if ((flags & RADIX_TREE_ITER_TAGGED) ?
+ !tag_get(node, tag, offset) : !child) {
+ /* Hole detected */
+ if (flags & RADIX_TREE_ITER_CONTIG)
+ return NULL;
+
+ if (flags & RADIX_TREE_ITER_TAGGED)
+ offset = radix_tree_find_next_bit(node, tag,
+ offset + 1);
+ else
+ while (++offset < RADIX_TREE_MAP_SIZE) {
+ void *slot = rcu_dereference_raw(
+ node->slots[offset]);
+ if (is_sibling_entry(node, slot))
+ continue;
+ if (slot)
+ break;
+ }
+ index &= ~node_maxindex(node);
+ index += offset << node->shift;
+ /* Overflow after ~0UL */
+ if (!index)
+ return NULL;
+ if (offset == RADIX_TREE_MAP_SIZE)
+ goto restart;
+ child = rcu_dereference_raw(node->slots[offset]);
+ }
+
+ if (!child)
+ goto restart;
+ if (child == RADIX_TREE_RETRY)
+ break;
+ } while (radix_tree_is_internal_node(child));
+
+ /* Update the iterator state */
+ iter->index = (index &~ node_maxindex(node)) | (offset << node->shift);
+ iter->next_index = (index | node_maxindex(node)) + 1;
+ iter->node = node;
+ __set_iter_shift(iter, node->shift);
+
+ if (flags & RADIX_TREE_ITER_TAGGED)
+ set_iter_tags(iter, node, offset, tag);
+
+ return node->slots + offset;
+}
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
@@ -196,3 +196,15 @@
while (TASKLET_ST_GET(ts) != TASKLET_ST_IDLE)
pause("W", 1);
}
+
+void tasklet_enable(struct tasklet_struct *ts)
+{
+ struct tasklet_worker *tw;
+ tw = &DPCPU_GET(tasklet_worker);
+}
+
+void tasklet_disable(struct tasklet_struct *ts)
+{
+ struct tasklet_worker *tw;
+ tw = &DPCPU_GET(tasklet_worker);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 25, 10:55 PM (12 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34327048
Default Alt Text
D14016.id38310.diff (36 KB)
Attached To
Mode
D14016: Update linuxkpi to Linux 4.11
Attached
Detach File
Event Timeline
Log In to Comment