2 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
3 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 #include <linux/kernel.h>
35 #include <linux/interrupt.h>
36 #include <linux/hardirq.h>
40 int __rxe_do_task(struct rxe_task
*task
)
45 while ((ret
= task
->func(task
->arg
)) == 0)
54 * this locking is due to a potential race where
55 * a second caller finds the task already running
56 * but looks just after the last call to func
58 void rxe_do_task(unsigned long data
)
63 struct rxe_task
*task
= (struct rxe_task
*)data
;
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
);
73 task
->state
= TASK_STATE_ARMED
;
75 case TASK_STATE_ARMED
:
76 spin_unlock_irqrestore(&task
->state_lock
, flags
);
80 spin_unlock_irqrestore(&task
->state_lock
, flags
);
81 pr_warn("bad state = %d in rxe_do_task\n", task
->state
);
87 ret
= task
->func(task
->arg
);
89 spin_lock_irqsave(&task
->state_lock
, flags
);
90 switch (task
->state
) {
93 task
->state
= TASK_STATE_START
;
98 /* soneone tried to run the task since the last time we called
99 * func, so we will call one more time regardless of the
102 case TASK_STATE_ARMED
:
103 task
->state
= TASK_STATE_BUSY
;
108 pr_warn("bad state = %d in rxe_do_task\n",
111 spin_unlock_irqrestore(&task
->state_lock
, flags
);
117 int rxe_init_task(void *obj
, struct rxe_task
*task
,
118 void *arg
, int (*func
)(void *), char *name
)
123 snprintf(task
->name
, sizeof(task
->name
), "%s", name
);
125 tasklet_init(&task
->tasklet
, rxe_do_task
, (unsigned long)task
);
127 task
->state
= TASK_STATE_START
;
128 spin_lock_init(&task
->state_lock
);
133 void rxe_cleanup_task(struct rxe_task
*task
)
135 tasklet_kill(&task
->tasklet
);
138 void rxe_run_task(struct rxe_task
*task
, int sched
)
141 tasklet_schedule(&task
->tasklet
);
143 rxe_do_task((unsigned long)task
);
146 void rxe_disable_task(struct rxe_task
*task
)
148 tasklet_disable(&task
->tasklet
);
151 void rxe_enable_task(struct rxe_task
*task
)
153 tasklet_enable(&task
->tasklet
);