diff --git a/sys/compat/linuxkpi/common/include/linux/interrupt.h b/sys/compat/linuxkpi/common/include/linux/interrupt.h --- a/sys/compat/linuxkpi/common/include/linux/interrupt.h +++ b/sys/compat/linuxkpi/common/include/linux/interrupt.h @@ -134,7 +134,9 @@ /* * LinuxKPI tasklet support */ +struct tasklet_struct; typedef void tasklet_func_t(unsigned long); +typedef void tasklet_callback_t(struct tasklet_struct *); struct tasklet_struct { TAILQ_ENTRY(tasklet_struct) entry; @@ -143,6 +145,8 @@ volatile u_int tasklet_state; atomic_t count; unsigned long data; + tasklet_callback_t *callback; + bool use_callback; }; #define DECLARE_TASKLET(_name, _func, _data) \ @@ -150,6 +154,11 @@ #define tasklet_hi_schedule(t) tasklet_schedule(t) +/* Some other compat code in the tree has this defined as well. */ +#define from_tasklet(_dev, _t, _field) \ + container_of(_t, typeof(*(_dev)), _field) + +void tasklet_setup(struct tasklet_struct *, tasklet_callback_t *); extern void tasklet_schedule(struct tasklet_struct *); extern void tasklet_kill(struct tasklet_struct *); extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *, diff --git a/sys/compat/linuxkpi/common/src/linux_tasklet.c b/sys/compat/linuxkpi/common/src/linux_tasklet.c --- a/sys/compat/linuxkpi/common/src/linux_tasklet.c +++ b/sys/compat/linuxkpi/common/src/linux_tasklet.c @@ -85,7 +85,10 @@ /* reset executing state */ TASKLET_ST_SET(ts, TASKLET_ST_EXEC); - ts->func(ts->data); + if (ts->use_callback) + ts->callback(ts); + else + ts->func(ts->data); } while (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC, TASKLET_ST_IDLE) == 0); @@ -149,9 +152,24 @@ ts->entry.tqe_prev = NULL; ts->entry.tqe_next = NULL; ts->func = func; + ts->callback = NULL; ts->data = data; atomic_set_int(&ts->tasklet_state, TASKLET_ST_IDLE); atomic_set(&ts->count, 0); + ts->use_callback = false; +} + +void +tasklet_setup(struct tasklet_struct *ts, tasklet_callback_t *c) +{ + ts->entry.tqe_prev = NULL; + ts->entry.tqe_next = NULL; + ts->func = NULL; + ts->callback = c; + ts->data = 0; + atomic_set_int(&ts->tasklet_state, TASKLET_ST_IDLE); + atomic_set(&ts->count, 0); + ts->use_callback = true; } void diff --git a/sys/dev/irdma/fbsd_kcompat.h b/sys/dev/irdma/fbsd_kcompat.h --- a/sys/dev/irdma/fbsd_kcompat.h +++ b/sys/dev/irdma/fbsd_kcompat.h @@ -44,8 +44,10 @@ tasklet_init((tasklet), (TASKLET_FUNC_TYPE)(callback), \ (TASKLET_DATA_TYPE)(tasklet)) +#ifndef from_tasklet #define from_tasklet(var, callback_tasklet, tasklet_fieldname) \ container_of(callback_tasklet, typeof(*var), tasklet_fieldname) +#endif #define IRDMA_SET_RDMA_OBJ_SIZE(ib_struct, drv_struct, member) \ (sizeof(struct drv_struct) + \