1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <linux/kernel.h>
35#include <linux/interrupt.h>
36#include <linux/hardirq.h>
37
38#include "rxe_task.h"
39
40int __rxe_do_task(struct rxe_task *task)
41
42{
43 int ret;
44
45 while ((ret = task->func(task->arg)) == 0)
46 ;
47
48 task->ret = ret;
49
50 return ret;
51}
52
53
54
55
56
57
58void rxe_do_task(unsigned long data)
59{
60 int cont;
61 int ret;
62 unsigned long flags;
63 struct rxe_task *task = (struct rxe_task *)data;
64
65 spin_lock_irqsave(&task->state_lock, flags);
66 switch (task->state) {
67 case TASK_STATE_START:
68 task->state = TASK_STATE_BUSY;
69 spin_unlock_irqrestore(&task->state_lock, flags);
70 break;
71
72 case TASK_STATE_BUSY:
73 task->state = TASK_STATE_ARMED;
74
75 case TASK_STATE_ARMED:
76 spin_unlock_irqrestore(&task->state_lock, flags);
77 return;
78
79 default:
80 spin_unlock_irqrestore(&task->state_lock, flags);
81 pr_warn("bad state = %d in rxe_do_task\n", task->state);
82 return;
83 }
84
85 do {
86 cont = 0;
87 ret = task->func(task->arg);
88
89 spin_lock_irqsave(&task->state_lock, flags);
90 switch (task->state) {
91 case TASK_STATE_BUSY:
92 if (ret)
93 task->state = TASK_STATE_START;
94 else
95 cont = 1;
96 break;
97
98
99
100
101
102 case TASK_STATE_ARMED:
103 task->state = TASK_STATE_BUSY;
104 cont = 1;
105 break;
106
107 default:
108 pr_warn("bad state = %d in rxe_do_task\n",
109 task->state);
110 }
111 spin_unlock_irqrestore(&task->state_lock, flags);
112 } while (cont);
113
114 task->ret = ret;
115}
116
117int rxe_init_task(void *obj, struct rxe_task *task,
118 void *arg, int (*func)(void *), char *name)
119{
120 task->obj = obj;
121 task->arg = arg;
122 task->func = func;
123 snprintf(task->name, sizeof(task->name), "%s", name);
124 task->destroyed = false;
125
126 tasklet_init(&task->tasklet, rxe_do_task, (unsigned long)task);
127
128 task->state = TASK_STATE_START;
129 spin_lock_init(&task->state_lock);
130
131 return 0;
132}
133
134void rxe_cleanup_task(struct rxe_task *task)
135{
136 unsigned long flags;
137 bool idle;
138
139
140
141
142
143 task->destroyed = true;
144
145 do {
146 spin_lock_irqsave(&task->state_lock, flags);
147 idle = (task->state == TASK_STATE_START);
148 spin_unlock_irqrestore(&task->state_lock, flags);
149 } while (!idle);
150
151 tasklet_kill(&task->tasklet);
152}
153
154void rxe_run_task(struct rxe_task *task, int sched)
155{
156 if (task->destroyed)
157 return;
158
159 if (sched)
160 tasklet_schedule(&task->tasklet);
161 else
162 rxe_do_task((unsigned long)task);
163}
164
165void rxe_disable_task(struct rxe_task *task)
166{
167 tasklet_disable(&task->tasklet);
168}
169
170void rxe_enable_task(struct rxe_task *task)
171{
172 tasklet_enable(&task->tasklet);
173}
174