1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
7 #include <linux/kernel.h>
8 #include <linux/interrupt.h>
9 #include <linux/hardirq.h>
13 int __rxe_do_task(struct rxe_task
*task
)
18 while ((ret
= task
->func(task
->arg
)) == 0)
27 * this locking is due to a potential race where
28 * a second caller finds the task already running
29 * but looks just after the last call to func
31 void rxe_do_task(struct tasklet_struct
*t
)
36 struct rxe_task
*task
= from_tasklet(task
, t
, tasklet
);
38 spin_lock_irqsave(&task
->state_lock
, flags
);
39 switch (task
->state
) {
40 case TASK_STATE_START
:
41 task
->state
= TASK_STATE_BUSY
;
42 spin_unlock_irqrestore(&task
->state_lock
, flags
);
46 task
->state
= TASK_STATE_ARMED
;
48 case TASK_STATE_ARMED
:
49 spin_unlock_irqrestore(&task
->state_lock
, flags
);
53 spin_unlock_irqrestore(&task
->state_lock
, flags
);
54 pr_warn("%s failed with bad state %d\n", __func__
, task
->state
);
60 ret
= task
->func(task
->arg
);
62 spin_lock_irqsave(&task
->state_lock
, flags
);
63 switch (task
->state
) {
66 task
->state
= TASK_STATE_START
;
71 /* soneone tried to run the task since the last time we called
72 * func, so we will call one more time regardless of the
75 case TASK_STATE_ARMED
:
76 task
->state
= TASK_STATE_BUSY
;
81 pr_warn("%s failed with bad state %d\n", __func__
,
84 spin_unlock_irqrestore(&task
->state_lock
, flags
);
90 int rxe_init_task(void *obj
, struct rxe_task
*task
,
91 void *arg
, int (*func
)(void *), char *name
)
96 snprintf(task
->name
, sizeof(task
->name
), "%s", name
);
97 task
->destroyed
= false;
99 tasklet_setup(&task
->tasklet
, rxe_do_task
);
101 task
->state
= TASK_STATE_START
;
102 spin_lock_init(&task
->state_lock
);
107 void rxe_cleanup_task(struct rxe_task
*task
)
113 * Mark the task, then wait for it to finish. It might be
114 * running in a non-tasklet (direct call) context.
116 task
->destroyed
= true;
119 spin_lock_irqsave(&task
->state_lock
, flags
);
120 idle
= (task
->state
== TASK_STATE_START
);
121 spin_unlock_irqrestore(&task
->state_lock
, flags
);
124 tasklet_kill(&task
->tasklet
);
127 void rxe_run_task(struct rxe_task
*task
, int sched
)
133 tasklet_schedule(&task
->tasklet
);
135 rxe_do_task(&task
->tasklet
);
138 void rxe_disable_task(struct rxe_task
*task
)
140 tasklet_disable(&task
->tasklet
);
143 void rxe_enable_task(struct rxe_task
*task
)
145 tasklet_enable(&task
->tasklet
);