Make the LinuxKPI task struct persistent accross system calls.
A set of helper functions have been added to manage the life of the LinuxKPI task struct. When an external system call or task is invoked, a check is made to create the task struct by demand. A thread destructor callback is registered to free the task struct when a thread exits to avoid memory leaks. This change lays the ground for emulating the Linux kernel more closely which is a dependency by the code using the LinuxKPI APIs. Add new dedicated td_lkpi_task field has been added to struct thread instead of abusing td_retval[1]. Fix some header file inclusions to make LINT kernel build properly after this change. Bump the __FreeBSD_version to force a rebuild of all kernel modules. MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
823c0e8c36
commit
5a4680a865
@ -31,6 +31,7 @@
|
|||||||
#ifndef _LINUX_BITOPS_H_
|
#ifndef _LINUX_BITOPS_H_
|
||||||
#define _LINUX_BITOPS_H_
|
#define _LINUX_BITOPS_H_
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||||
* Copyright (c) 2010 iX Systems, Inc.
|
* Copyright (c) 2010 iX Systems, Inc.
|
||||||
* Copyright (c) 2010 Panasas, Inc.
|
* Copyright (c) 2010 Panasas, Inc.
|
||||||
* Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
|
* Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,10 +31,29 @@
|
|||||||
#ifndef _LINUX_COMPAT_H_
|
#ifndef _LINUX_COMPAT_H_
|
||||||
#define _LINUX_COMPAT_H_
|
#define _LINUX_COMPAT_H_
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
|
||||||
struct thread;
|
struct thread;
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
|
|
||||||
void linux_set_current(struct thread *td, struct task_struct *t);
|
extern int linux_alloc_current(struct thread *, int flags);
|
||||||
void linux_clear_current(struct thread *td);
|
extern void linux_free_current(struct task_struct *);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
linux_set_current(struct thread *td)
|
||||||
|
{
|
||||||
|
if (__predict_false(td->td_lkpi_task == NULL))
|
||||||
|
linux_alloc_current(td, M_WAITOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
linux_set_current_flags(struct thread *td, int flags)
|
||||||
|
{
|
||||||
|
if (__predict_false(td->td_lkpi_task == NULL))
|
||||||
|
return (linux_alloc_current(td, flags));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _LINUX_COMPAT_H_ */
|
#endif /* _LINUX_COMPAT_H_ */
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
struct linux_file;
|
struct linux_file;
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#define _LINUX_JIFFIES_H_
|
#define _LINUX_JIFFIES_H_
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#ifndef _LINUX_KDEV_T_H_
|
#ifndef _LINUX_KDEV_T_H_
|
||||||
#define _LINUX_KDEV_T_H_
|
#define _LINUX_KDEV_T_H_
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define MAJOR(dev) major((dev))
|
#define MAJOR(dev) major((dev))
|
||||||
#define MINOR(dev) minor((dev))
|
#define MINOR(dev) minor((dev))
|
||||||
#define MKDEV(ma, mi) makedev((ma), (mi))
|
#define MKDEV(ma, mi) makedev((ma), (mi))
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||||
* Copyright (c) 2010 iX Systems, Inc.
|
* Copyright (c) 2010 iX Systems, Inc.
|
||||||
* Copyright (c) 2010 Panasas, Inc.
|
* Copyright (c) 2010 Panasas, Inc.
|
||||||
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
|
* Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -31,74 +31,27 @@
|
|||||||
#ifndef _LINUX_KTHREAD_H_
|
#ifndef _LINUX_KTHREAD_H_
|
||||||
#define _LINUX_KTHREAD_H_
|
#define _LINUX_KTHREAD_H_
|
||||||
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <sys/lock.h>
|
|
||||||
#include <sys/mutex.h>
|
|
||||||
#include <sys/kernel.h>
|
|
||||||
#include <sys/kthread.h>
|
|
||||||
#include <sys/sleepqueue.h>
|
|
||||||
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
static inline void
|
#include <sys/unistd.h>
|
||||||
linux_kthread_fn(void *arg)
|
#include <sys/kthread.h>
|
||||||
{
|
|
||||||
struct task_struct *task;
|
|
||||||
struct thread *td = curthread;
|
|
||||||
|
|
||||||
task = arg;
|
#define kthread_run(fn, data, fmt, ...) ({ \
|
||||||
task_struct_fill(td, task);
|
struct task_struct *__task; \
|
||||||
task_struct_set(td, task);
|
struct thread *__td; \
|
||||||
if (task->should_stop == 0)
|
|
||||||
task->task_ret = task->task_fn(task->task_data);
|
|
||||||
PROC_LOCK(td->td_proc);
|
|
||||||
task->should_stop = TASK_STOPPED;
|
|
||||||
wakeup(task);
|
|
||||||
PROC_UNLOCK(td->td_proc);
|
|
||||||
task_struct_set(td, NULL);
|
|
||||||
kthread_exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct task_struct *
|
|
||||||
linux_kthread_create(int (*threadfn)(void *data), void *data)
|
|
||||||
{
|
|
||||||
struct task_struct *task;
|
|
||||||
|
|
||||||
task = kzalloc(sizeof(*task), GFP_KERNEL);
|
|
||||||
task->task_fn = threadfn;
|
|
||||||
task->task_data = data;
|
|
||||||
|
|
||||||
return (task);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define kthread_run(fn, data, fmt, ...) \
|
|
||||||
({ \
|
|
||||||
struct task_struct *_task; \
|
|
||||||
\
|
\
|
||||||
_task = linux_kthread_create((fn), (data)); \
|
if (kthread_add(linux_kthread_fn, NULL, NULL, &__td, \
|
||||||
if (kthread_add(linux_kthread_fn, _task, NULL, &_task->task_thread, \
|
RFSTOPPED, 0, fmt, ## __VA_ARGS__)) \
|
||||||
0, 0, fmt, ## __VA_ARGS__)) { \
|
__task = NULL; \
|
||||||
kfree(_task); \
|
else \
|
||||||
_task = NULL; \
|
__task = linux_kthread_setup_and_run(__td, fn, data); \
|
||||||
} \
|
__task; \
|
||||||
_task; \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
#define kthread_should_stop() current->should_stop
|
extern int kthread_stop(struct task_struct *);
|
||||||
|
extern bool kthread_should_stop_task(struct task_struct *);
|
||||||
static inline int
|
extern bool kthread_should_stop(void);
|
||||||
kthread_stop(struct task_struct *task)
|
extern void linux_kthread_fn(void *);
|
||||||
{
|
extern struct task_struct *linux_kthread_setup_and_run(struct thread *, linux_task_fn_t *, void *arg);
|
||||||
|
|
||||||
PROC_LOCK(task->task_thread->td_proc);
|
|
||||||
task->should_stop = TASK_SHOULD_STOP;
|
|
||||||
wake_up_process(task);
|
|
||||||
while (task->should_stop != TASK_STOPPED)
|
|
||||||
msleep(task, &task->task_thread->td_proc->p_mtx, PWAIT,
|
|
||||||
"kstop", hz);
|
|
||||||
PROC_UNLOCK(task->task_thread->td_proc);
|
|
||||||
return task->task_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _LINUX_KTHREAD_H_ */
|
#endif /* _LINUX_KTHREAD_H_ */
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/rwlock.h>
|
#include <sys/rwlock.h>
|
||||||
|
#include <sys/libkern.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct rwlock rw;
|
struct rwlock rw;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/sx.h>
|
#include <sys/sx.h>
|
||||||
|
#include <sys/libkern.h>
|
||||||
|
|
||||||
struct rw_semaphore {
|
struct rw_semaphore {
|
||||||
struct sx sx;
|
struct sx sx;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2010 Isilon Systems, Inc.
|
* Copyright (c) 2010 Isilon Systems, Inc.
|
||||||
* Copyright (c) 2010 iX Systems, Inc.
|
* Copyright (c) 2010 iX Systems, Inc.
|
||||||
* Copyright (c) 2010 Panasas, Inc.
|
* Copyright (c) 2010 Panasas, Inc.
|
||||||
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
|
* Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -37,6 +37,12 @@
|
|||||||
#include <sys/sched.h>
|
#include <sys/sched.h>
|
||||||
#include <sys/sleepqueue.h>
|
#include <sys/sleepqueue.h>
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
|
#define MAX_SCHEDULE_TIMEOUT LONG_MAX
|
||||||
|
|
||||||
#define TASK_RUNNING 0
|
#define TASK_RUNNING 0
|
||||||
@ -46,41 +52,22 @@
|
|||||||
#define TASK_WAKEKILL 128
|
#define TASK_WAKEKILL 128
|
||||||
#define TASK_WAKING 256
|
#define TASK_WAKING 256
|
||||||
|
|
||||||
#define TASK_SHOULD_STOP 1
|
|
||||||
#define TASK_STOPPED 2
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A task_struct is only provided for threads created by kthread() and
|
|
||||||
* file operation callbacks.
|
|
||||||
*
|
|
||||||
* Using these routines outside the above mentioned contexts will
|
|
||||||
* cause panics because no task_struct is assigned and td_retval[1] is
|
|
||||||
* overwritten by syscalls.
|
|
||||||
*/
|
|
||||||
struct task_struct {
|
struct task_struct {
|
||||||
struct thread *task_thread;
|
struct thread *task_thread;
|
||||||
int (*task_fn)(void *data);
|
linux_task_fn_t *task_fn;
|
||||||
void *task_data;
|
void *task_data;
|
||||||
int task_ret;
|
int task_ret;
|
||||||
int state;
|
int state;
|
||||||
int should_stop;
|
atomic_t kthread_flags;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
const char *comm;
|
const char *comm;
|
||||||
void *bsd_ioctl_data;
|
void *bsd_ioctl_data;
|
||||||
unsigned bsd_ioctl_len;
|
unsigned bsd_ioctl_len;
|
||||||
|
struct completion parked;
|
||||||
|
struct completion exited;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define current task_struct_get(curthread)
|
#define current ((struct task_struct *)curthread->td_lkpi_task)
|
||||||
#define task_struct_get(x) ((struct task_struct *)(uintptr_t)(x)->td_retval[1])
|
|
||||||
#define task_struct_fill(x, y) do { \
|
|
||||||
(y)->task_thread = (x); \
|
|
||||||
(y)->comm = (x)->td_name; \
|
|
||||||
(y)->pid = (x)->td_tid; \
|
|
||||||
} while (0)
|
|
||||||
#define task_struct_set(x, y) (x)->td_retval[1] = (uintptr_t)(y)
|
|
||||||
|
|
||||||
/* ensure the task_struct pointer fits into the td_retval[1] field */
|
|
||||||
CTASSERT(sizeof(((struct thread *)0)->td_retval[1]) >= sizeof(uintptr_t));
|
|
||||||
|
|
||||||
#define set_current_state(x) \
|
#define set_current_state(x) \
|
||||||
atomic_store_rel_int((volatile int *)¤t->state, (x))
|
atomic_store_rel_int((volatile int *)¤t->state, (x))
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/sema.h>
|
#include <sys/sema.h>
|
||||||
|
#include <sys/libkern.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX BSD semaphores are disused and slow. They also do not provide a
|
* XXX BSD semaphores are disused and slow. They also do not provide a
|
||||||
|
@ -35,9 +35,9 @@
|
|||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
|
#include <sys/libkern.h>
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/rwlock.h>
|
#include <linux/rwlock.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -63,4 +63,6 @@ typedef u64 phys_addr_t;
|
|||||||
#define DECLARE_BITMAP(n, bits) \
|
#define DECLARE_BITMAP(n, bits) \
|
||||||
unsigned long n[howmany(bits, sizeof(long) * 8)]
|
unsigned long n[howmany(bits, sizeof(long) * 8)]
|
||||||
|
|
||||||
|
typedef int linux_task_fn_t(void *data);
|
||||||
|
|
||||||
#endif /* _LINUX_TYPES_H_ */
|
#endif /* _LINUX_TYPES_H_ */
|
||||||
|
@ -32,8 +32,6 @@
|
|||||||
#define _LINUX_WAIT_H_
|
#define _LINUX_WAIT_H_
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
|
|
||||||
|
@ -384,32 +384,14 @@ kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype,
|
|||||||
return kobject_add_complete(kobj, parent);
|
return kobject_add_complete(kobj, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
linux_set_current(struct thread *td, struct task_struct *t)
|
|
||||||
{
|
|
||||||
memset(t, 0, sizeof(*t));
|
|
||||||
task_struct_fill(td, t);
|
|
||||||
task_struct_set(td, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
linux_clear_current(struct thread *td)
|
|
||||||
{
|
|
||||||
task_struct_set(td, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
linux_file_dtor(void *cdp)
|
linux_file_dtor(void *cdp)
|
||||||
{
|
{
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
filp = cdp;
|
filp = cdp;
|
||||||
linux_set_current(td, &t);
|
|
||||||
filp->f_op->release(filp->f_vnode, filp);
|
filp->f_op->release(filp->f_vnode, filp);
|
||||||
linux_clear_current(td);
|
|
||||||
vdrop(filp->f_vnode);
|
vdrop(filp->f_vnode);
|
||||||
kfree(filp);
|
kfree(filp);
|
||||||
}
|
}
|
||||||
@ -419,7 +401,6 @@ linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
|||||||
{
|
{
|
||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -433,7 +414,7 @@ linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
|||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
vhold(file->f_vnode);
|
vhold(file->f_vnode);
|
||||||
filp->f_vnode = file->f_vnode;
|
filp->f_vnode = file->f_vnode;
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->open) {
|
if (filp->f_op->open) {
|
||||||
error = -filp->f_op->open(file->f_vnode, filp);
|
error = -filp->f_op->open(file->f_vnode, filp);
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -447,7 +428,6 @@ linux_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
|||||||
kfree(filp);
|
kfree(filp);
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
linux_clear_current(td);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +518,6 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
|||||||
{
|
{
|
||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct file *file;
|
struct file *file;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
int error;
|
int error;
|
||||||
@ -550,7 +529,8 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
|||||||
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
linux_set_current(td, &t);
|
|
||||||
|
linux_set_current(td);
|
||||||
size = IOCPARM_LEN(cmd);
|
size = IOCPARM_LEN(cmd);
|
||||||
/* refer to logic in sys_ioctl() */
|
/* refer to logic in sys_ioctl() */
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
@ -560,8 +540,8 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
|||||||
* Background: Linux code expects a user-space address
|
* Background: Linux code expects a user-space address
|
||||||
* while FreeBSD supplies a kernel-space address.
|
* while FreeBSD supplies a kernel-space address.
|
||||||
*/
|
*/
|
||||||
t.bsd_ioctl_data = data;
|
current->bsd_ioctl_data = data;
|
||||||
t.bsd_ioctl_len = size;
|
current->bsd_ioctl_len = size;
|
||||||
data = (void *)LINUX_IOCTL_MIN_PTR;
|
data = (void *)LINUX_IOCTL_MIN_PTR;
|
||||||
} else {
|
} else {
|
||||||
/* fetch user-space pointer */
|
/* fetch user-space pointer */
|
||||||
@ -571,7 +551,10 @@ linux_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
|||||||
error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data);
|
error = -filp->f_op->unlocked_ioctl(filp, cmd, (u_long)data);
|
||||||
else
|
else
|
||||||
error = ENOTTY;
|
error = ENOTTY;
|
||||||
linux_clear_current(td);
|
if (size > 0) {
|
||||||
|
current->bsd_ioctl_data = NULL;
|
||||||
|
current->bsd_ioctl_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -581,7 +564,6 @@ linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
{
|
{
|
||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
@ -598,7 +580,7 @@ linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
/* XXX no support for I/O vectors currently */
|
/* XXX no support for I/O vectors currently */
|
||||||
if (uio->uio_iovcnt != 1)
|
if (uio->uio_iovcnt != 1)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->read) {
|
if (filp->f_op->read) {
|
||||||
bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
|
bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
|
||||||
uio->uio_iov->iov_len, &uio->uio_offset);
|
uio->uio_iov->iov_len, &uio->uio_offset);
|
||||||
@ -611,7 +593,6 @@ linux_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
error = -bytes;
|
error = -bytes;
|
||||||
} else
|
} else
|
||||||
error = ENXIO;
|
error = ENXIO;
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -621,7 +602,6 @@ linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
{
|
{
|
||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
@ -638,7 +618,7 @@ linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
/* XXX no support for I/O vectors currently */
|
/* XXX no support for I/O vectors currently */
|
||||||
if (uio->uio_iovcnt != 1)
|
if (uio->uio_iovcnt != 1)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->write) {
|
if (filp->f_op->write) {
|
||||||
bytes = filp->f_op->write(filp, uio->uio_iov->iov_base,
|
bytes = filp->f_op->write(filp, uio->uio_iov->iov_base,
|
||||||
uio->uio_iov->iov_len, &uio->uio_offset);
|
uio->uio_iov->iov_len, &uio->uio_offset);
|
||||||
@ -651,7 +631,6 @@ linux_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
|||||||
error = -bytes;
|
error = -bytes;
|
||||||
} else
|
} else
|
||||||
error = ENXIO;
|
error = ENXIO;
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -661,7 +640,6 @@ linux_dev_poll(struct cdev *dev, int events, struct thread *td)
|
|||||||
{
|
{
|
||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int revents;
|
int revents;
|
||||||
int error;
|
int error;
|
||||||
@ -673,12 +651,11 @@ linux_dev_poll(struct cdev *dev, int events, struct thread *td)
|
|||||||
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->poll)
|
if (filp->f_op->poll)
|
||||||
revents = filp->f_op->poll(filp, NULL) & events;
|
revents = filp->f_op->poll(filp, NULL) & events;
|
||||||
else
|
else
|
||||||
revents = 0;
|
revents = 0;
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (revents);
|
return (revents);
|
||||||
}
|
}
|
||||||
@ -690,7 +667,6 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
|
|||||||
struct linux_cdev *ldev;
|
struct linux_cdev *ldev;
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
struct task_struct t;
|
|
||||||
struct file *file;
|
struct file *file;
|
||||||
struct vm_area_struct vma;
|
struct vm_area_struct vma;
|
||||||
int error;
|
int error;
|
||||||
@ -703,7 +679,7 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
|
|||||||
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
if ((error = devfs_get_cdevpriv((void **)&filp)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
vma.vm_start = 0;
|
vma.vm_start = 0;
|
||||||
vma.vm_end = size;
|
vma.vm_end = size;
|
||||||
vma.vm_pgoff = *offset / PAGE_SIZE;
|
vma.vm_pgoff = *offset / PAGE_SIZE;
|
||||||
@ -735,7 +711,6 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
|
|||||||
} else
|
} else
|
||||||
error = ENODEV;
|
error = ENODEV;
|
||||||
done:
|
done:
|
||||||
linux_clear_current(td);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,7 +731,6 @@ linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred,
|
|||||||
int flags, struct thread *td)
|
int flags, struct thread *td)
|
||||||
{
|
{
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -766,7 +740,7 @@ linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred,
|
|||||||
/* XXX no support for I/O vectors currently */
|
/* XXX no support for I/O vectors currently */
|
||||||
if (uio->uio_iovcnt != 1)
|
if (uio->uio_iovcnt != 1)
|
||||||
return (EOPNOTSUPP);
|
return (EOPNOTSUPP);
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->read) {
|
if (filp->f_op->read) {
|
||||||
bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
|
bytes = filp->f_op->read(filp, uio->uio_iov->iov_base,
|
||||||
uio->uio_iov->iov_len, &uio->uio_offset);
|
uio->uio_iov->iov_len, &uio->uio_offset);
|
||||||
@ -779,7 +753,6 @@ linux_file_read(struct file *file, struct uio *uio, struct ucred *active_cred,
|
|||||||
error = -bytes;
|
error = -bytes;
|
||||||
} else
|
} else
|
||||||
error = ENXIO;
|
error = ENXIO;
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -789,17 +762,15 @@ linux_file_poll(struct file *file, int events, struct ucred *active_cred,
|
|||||||
struct thread *td)
|
struct thread *td)
|
||||||
{
|
{
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
int revents;
|
int revents;
|
||||||
|
|
||||||
filp = (struct linux_file *)file->f_data;
|
filp = (struct linux_file *)file->f_data;
|
||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
if (filp->f_op->poll)
|
if (filp->f_op->poll)
|
||||||
revents = filp->f_op->poll(filp, NULL) & events;
|
revents = filp->f_op->poll(filp, NULL) & events;
|
||||||
else
|
else
|
||||||
revents = 0;
|
revents = 0;
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (revents);
|
return (revents);
|
||||||
}
|
}
|
||||||
@ -808,14 +779,12 @@ static int
|
|||||||
linux_file_close(struct file *file, struct thread *td)
|
linux_file_close(struct file *file, struct thread *td)
|
||||||
{
|
{
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
filp = (struct linux_file *)file->f_data;
|
filp = (struct linux_file *)file->f_data;
|
||||||
filp->f_flags = file->f_flag;
|
filp->f_flags = file->f_flag;
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
error = -filp->f_op->release(NULL, filp);
|
error = -filp->f_op->release(NULL, filp);
|
||||||
linux_clear_current(td);
|
|
||||||
funsetown(&filp->f_sigio);
|
funsetown(&filp->f_sigio);
|
||||||
kfree(filp);
|
kfree(filp);
|
||||||
|
|
||||||
@ -827,14 +796,13 @@ linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred,
|
|||||||
struct thread *td)
|
struct thread *td)
|
||||||
{
|
{
|
||||||
struct linux_file *filp;
|
struct linux_file *filp;
|
||||||
struct task_struct t;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
filp = (struct linux_file *)fp->f_data;
|
filp = (struct linux_file *)fp->f_data;
|
||||||
filp->f_flags = fp->f_flag;
|
filp->f_flags = fp->f_flag;
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
linux_set_current(td, &t);
|
linux_set_current(td);
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case FIONBIO:
|
case FIONBIO:
|
||||||
break;
|
break;
|
||||||
@ -856,7 +824,6 @@ linux_file_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *cred,
|
|||||||
error = ENOTTY;
|
error = ENOTTY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
linux_clear_current(td);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
94
sys/compat/linuxkpi/common/src/linux_current.c
Normal file
94
sys/compat/linuxkpi/common/src/linux_current.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2017 Hans Petter Selasky
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 unmodified, 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 AUTHOR ``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 AUTHOR 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>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <linux/compat.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/eventhandler.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
|
||||||
|
static eventhandler_tag linuxkpi_thread_dtor_tag;
|
||||||
|
|
||||||
|
static MALLOC_DEFINE(M_LINUX_CURRENT, "linuxcurrent", "LinuxKPI task structure");
|
||||||
|
|
||||||
|
int
|
||||||
|
linux_alloc_current(struct thread *td, int flags)
|
||||||
|
{
|
||||||
|
struct task_struct *ts;
|
||||||
|
|
||||||
|
MPASS(td->td_lkpi_task == NULL);
|
||||||
|
|
||||||
|
ts = malloc(sizeof(*ts), M_LINUX_CURRENT, flags | M_ZERO);
|
||||||
|
if (ts == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
atomic_set(&ts->kthread_flags, 0);
|
||||||
|
ts->task_thread = td;
|
||||||
|
ts->comm = td->td_name;
|
||||||
|
ts->pid = td->td_tid;
|
||||||
|
ts->state = TASK_RUNNING;
|
||||||
|
td->td_lkpi_task = ts;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_free_current(struct task_struct *ts)
|
||||||
|
{
|
||||||
|
free(ts, M_LINUX_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linuxkpi_thread_dtor(void *arg __unused, struct thread *td)
|
||||||
|
{
|
||||||
|
struct task_struct *ts;
|
||||||
|
|
||||||
|
ts = td->td_lkpi_task;
|
||||||
|
if (ts == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
td->td_lkpi_task = NULL;
|
||||||
|
free(ts, M_LINUX_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_current_init(void *arg __unused)
|
||||||
|
{
|
||||||
|
linuxkpi_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
|
||||||
|
linuxkpi_thread_dtor, NULL, EVENTHANDLER_PRI_ANY);
|
||||||
|
}
|
||||||
|
SYSINIT(linux_current, SI_SUB_EVENTHANDLER, SI_ORDER_SECOND, linux_current_init, NULL);
|
||||||
|
|
||||||
|
static void
|
||||||
|
linux_current_uninit(void *arg __unused)
|
||||||
|
{
|
||||||
|
EVENTHANDLER_DEREGISTER(thread_dtor, linuxkpi_thread_dtor_tag);
|
||||||
|
}
|
||||||
|
SYSUNINIT(linux_current, SI_SUB_EVENTHANDLER, SI_ORDER_SECOND, linux_current_uninit, NULL);
|
120
sys/compat/linuxkpi/common/src/linux_kthread.c
Normal file
120
sys/compat/linuxkpi/common/src/linux_kthread.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2017 Hans Petter Selasky
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 unmodified, 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 AUTHOR ``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 AUTHOR 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>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
|
|
||||||
|
#include <sys/bus.h>
|
||||||
|
#include <sys/interrupt.h>
|
||||||
|
#include <sys/priority.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
KTHREAD_SHOULD_STOP_MASK = (1 << 0),
|
||||||
|
KTHREAD_SHOULD_PARK_MASK = (1 << 1),
|
||||||
|
KTHREAD_IS_PARKED_MASK = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
kthread_should_stop_task(struct task_struct *task)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (atomic_read(&task->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
kthread_should_stop(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (atomic_read(¤t->kthread_flags) & KTHREAD_SHOULD_STOP_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kthread_stop(struct task_struct *task)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assume task is still alive else caller should not call
|
||||||
|
* kthread_stop():
|
||||||
|
*/
|
||||||
|
atomic_or(KTHREAD_SHOULD_STOP_MASK, &task->kthread_flags);
|
||||||
|
wake_up_process(task);
|
||||||
|
wait_for_completion(&task->exited);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get return code and free task structure:
|
||||||
|
*/
|
||||||
|
retval = task->task_ret;
|
||||||
|
linux_free_current(task);
|
||||||
|
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct task_struct *
|
||||||
|
linux_kthread_setup_and_run(struct thread *td, linux_task_fn_t *task_fn, void *arg)
|
||||||
|
{
|
||||||
|
struct task_struct *task;
|
||||||
|
|
||||||
|
linux_set_current(td);
|
||||||
|
|
||||||
|
task = td->td_lkpi_task;
|
||||||
|
task->task_fn = task_fn;
|
||||||
|
task->task_data = arg;
|
||||||
|
|
||||||
|
thread_lock(td);
|
||||||
|
/* make sure the scheduler priority is raised */
|
||||||
|
sched_prio(td, PI_SWI(SWI_NET));
|
||||||
|
/* put thread into run-queue */
|
||||||
|
sched_add(td, SRQ_BORING);
|
||||||
|
thread_unlock(td);
|
||||||
|
|
||||||
|
return (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
linux_kthread_fn(void *arg __unused)
|
||||||
|
{
|
||||||
|
struct task_struct *task = current;
|
||||||
|
|
||||||
|
if (kthread_should_stop_task(task) == 0)
|
||||||
|
task->task_ret = task->task_fn(task->task_data);
|
||||||
|
|
||||||
|
if (kthread_should_stop_task(task) != 0) {
|
||||||
|
struct thread *td = curthread;
|
||||||
|
|
||||||
|
/* let kthread_stop() free data */
|
||||||
|
td->td_lkpi_task = NULL;
|
||||||
|
|
||||||
|
/* wakeup kthread_stop() */
|
||||||
|
complete(&task->exited);
|
||||||
|
}
|
||||||
|
kthread_exit();
|
||||||
|
}
|
||||||
|
|
@ -121,12 +121,9 @@ linux_pci_attach(device_t dev)
|
|||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct pci_driver *pdrv;
|
struct pci_driver *pdrv;
|
||||||
const struct pci_device_id *id;
|
const struct pci_device_id *id;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
linux_set_current(td, &t);
|
|
||||||
pdrv = linux_pci_find(dev, &id);
|
pdrv = linux_pci_find(dev, &id);
|
||||||
pdev = device_get_softc(dev);
|
pdev = device_get_softc(dev);
|
||||||
pdev->dev.parent = &linux_root_device;
|
pdev->dev.parent = &linux_root_device;
|
||||||
@ -159,7 +156,6 @@ linux_pci_attach(device_t dev)
|
|||||||
put_device(&pdev->dev);
|
put_device(&pdev->dev);
|
||||||
error = -error;
|
error = -error;
|
||||||
}
|
}
|
||||||
linux_clear_current(td);
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,11 +163,8 @@ static int
|
|||||||
linux_pci_detach(device_t dev)
|
linux_pci_detach(device_t dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
linux_set_current(td, &t);
|
|
||||||
pdev = device_get_softc(dev);
|
pdev = device_get_softc(dev);
|
||||||
DROP_GIANT();
|
DROP_GIANT();
|
||||||
pdev->pdrv->remove(pdev);
|
pdev->pdrv->remove(pdev);
|
||||||
@ -180,7 +173,6 @@ linux_pci_detach(device_t dev)
|
|||||||
list_del(&pdev->links);
|
list_del(&pdev->links);
|
||||||
spin_unlock(&pci_lock);
|
spin_unlock(&pci_lock);
|
||||||
put_device(&pdev->dev);
|
put_device(&pdev->dev);
|
||||||
linux_clear_current(td);
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -190,18 +182,14 @@ linux_pci_suspend(device_t dev)
|
|||||||
{
|
{
|
||||||
struct pm_message pm = { };
|
struct pm_message pm = { };
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
linux_set_current(td, &t);
|
|
||||||
pdev = device_get_softc(dev);
|
pdev = device_get_softc(dev);
|
||||||
if (pdev->pdrv->suspend != NULL)
|
if (pdev->pdrv->suspend != NULL)
|
||||||
err = -pdev->pdrv->suspend(pdev, pm);
|
err = -pdev->pdrv->suspend(pdev, pm);
|
||||||
else
|
else
|
||||||
err = 0;
|
err = 0;
|
||||||
linux_clear_current(td);
|
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,18 +197,14 @@ static int
|
|||||||
linux_pci_resume(device_t dev)
|
linux_pci_resume(device_t dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
linux_set_current(td, &t);
|
|
||||||
pdev = device_get_softc(dev);
|
pdev = device_get_softc(dev);
|
||||||
if (pdev->pdrv->resume != NULL)
|
if (pdev->pdrv->resume != NULL)
|
||||||
err = -pdev->pdrv->resume(pdev);
|
err = -pdev->pdrv->resume(pdev);
|
||||||
else
|
else
|
||||||
err = 0;
|
err = 0;
|
||||||
linux_clear_current(td);
|
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,18 +212,14 @@ static int
|
|||||||
linux_pci_shutdown(device_t dev)
|
linux_pci_shutdown(device_t dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
struct task_struct t;
|
|
||||||
struct thread *td;
|
|
||||||
|
|
||||||
td = curthread;
|
linux_set_current(curthread);
|
||||||
linux_set_current(td, &t);
|
|
||||||
pdev = device_get_softc(dev);
|
pdev = device_get_softc(dev);
|
||||||
if (pdev->pdrv->shutdown != NULL) {
|
if (pdev->pdrv->shutdown != NULL) {
|
||||||
DROP_GIANT();
|
DROP_GIANT();
|
||||||
pdev->pdrv->shutdown(pdev);
|
pdev->pdrv->shutdown(pdev);
|
||||||
PICKUP_GIANT();
|
PICKUP_GIANT();
|
||||||
}
|
}
|
||||||
linux_clear_current(td);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +231,7 @@ pci_register_driver(struct pci_driver *pdrv)
|
|||||||
|
|
||||||
bus = devclass_find("pci");
|
bus = devclass_find("pci");
|
||||||
|
|
||||||
|
linux_set_current(curthread);
|
||||||
spin_lock(&pci_lock);
|
spin_lock(&pci_lock);
|
||||||
list_add(&pdrv->links, &pci_drivers);
|
list_add(&pdrv->links, &pci_drivers);
|
||||||
spin_unlock(&pci_lock);
|
spin_unlock(&pci_lock);
|
||||||
|
@ -4266,6 +4266,10 @@ compat/linuxkpi/common/src/linux_kmod.c optional compat_linuxkpi \
|
|||||||
compile-with "${LINUXKPI_C}"
|
compile-with "${LINUXKPI_C}"
|
||||||
compat/linuxkpi/common/src/linux_compat.c optional compat_linuxkpi \
|
compat/linuxkpi/common/src/linux_compat.c optional compat_linuxkpi \
|
||||||
compile-with "${LINUXKPI_C}"
|
compile-with "${LINUXKPI_C}"
|
||||||
|
compat/linuxkpi/common/src/linux_current.c optional compat_linuxkpi \
|
||||||
|
compile-with "${LINUXKPI_C}"
|
||||||
|
compat/linuxkpi/common/src/linux_kthread.c optional compat_linuxkpi \
|
||||||
|
compile-with "${LINUXKPI_C}"
|
||||||
compat/linuxkpi/common/src/linux_pci.c optional compat_linuxkpi pci \
|
compat/linuxkpi/common/src/linux_pci.c optional compat_linuxkpi pci \
|
||||||
compile-with "${LINUXKPI_C}"
|
compile-with "${LINUXKPI_C}"
|
||||||
compat/linuxkpi/common/src/linux_idr.c optional compat_linuxkpi \
|
compat/linuxkpi/common/src/linux_idr.c optional compat_linuxkpi \
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
KMOD= linuxkpi
|
KMOD= linuxkpi
|
||||||
SRCS= linux_kmod.c \
|
SRCS= linux_kmod.c \
|
||||||
linux_compat.c \
|
linux_compat.c \
|
||||||
|
linux_current.c \
|
||||||
|
linux_kthread.c \
|
||||||
linux_pci.c \
|
linux_pci.c \
|
||||||
linux_radix.c \
|
linux_radix.c \
|
||||||
linux_idr.c \
|
linux_idr.c \
|
||||||
|
@ -58,7 +58,7 @@
|
|||||||
* in the range 5 to 9.
|
* in the range 5 to 9.
|
||||||
*/
|
*/
|
||||||
#undef __FreeBSD_version
|
#undef __FreeBSD_version
|
||||||
#define __FreeBSD_version 1200021 /* Master, propagated to newvers */
|
#define __FreeBSD_version 1200022 /* Master, propagated to newvers */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||||
|
@ -339,6 +339,7 @@ struct thread {
|
|||||||
void *td_emuldata; /* Emulator state data */
|
void *td_emuldata; /* Emulator state data */
|
||||||
int td_lastcpu; /* (t) Last cpu we were on. */
|
int td_lastcpu; /* (t) Last cpu we were on. */
|
||||||
int td_oncpu; /* (t) Which cpu we are on. */
|
int td_oncpu; /* (t) Which cpu we are on. */
|
||||||
|
void *td_lkpi_task; /* LinuxKPI task struct pointer */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thread0_storage {
|
struct thread0_storage {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user