1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/workqueue.h>
20 #include <linux/slab.h>
21 #include <linux/module.h>
22 #include "hi_osal.h"
23
24 OSAL_LIST_HEAD(wq_list);
25 struct wq_node {
26 struct osal_work_struct *osal_work;
27 struct work_struct *work;
28 struct osal_list_head node;
29 };
30
osal_find_work(struct work_struct * work)31 static struct osal_work_struct *osal_find_work(struct work_struct *work)
32 {
33 struct osal_list_head *this = NULL;
34 if (osal_list_empty(&wq_list)) {
35 osal_trace("find work failed! wq_list is empty!\n");
36 return NULL;
37 }
38 osal_list_for_each(this, &wq_list) {
39 struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
40 if (ws->work == work) {
41 return ws->osal_work;
42 }
43 }
44 osal_trace("find work failed!\n");
45 return NULL;
46 }
47
osal_del_work(struct work_struct * work)48 static int osal_del_work(struct work_struct *work)
49 {
50 struct osal_list_head *this = NULL;
51 struct osal_list_head *next = NULL;
52 if (osal_list_empty(&wq_list)) {
53 osal_trace("find work failed! wq_list is empty!\n");
54 return -1;
55 }
56 osal_list_for_each_safe(this, next, &wq_list) {
57 struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
58 if (ws->work == work) {
59 osal_list_del(this);
60 kfree(ws);
61 ws = NULL;
62 return 0;
63 }
64 }
65 osal_trace("del work failed!\n");
66 return -1;
67 }
68
osal_work_func(struct work_struct * work)69 static void osal_work_func(struct work_struct *work)
70 {
71 struct osal_work_struct *ow = osal_find_work(work);
72 if ((ow != NULL) && (ow->func != NULL)) {
73 ow->func(ow);
74 }
75 }
76
osal_init_work(struct osal_work_struct * work,osal_work_func_t func)77 int osal_init_work(struct osal_work_struct *work, osal_work_func_t func)
78 {
79 struct work_struct *w = NULL;
80 struct wq_node *w_node = NULL;
81 w = kmalloc(sizeof(struct work_struct), GFP_ATOMIC);
82 if (w == NULL) {
83 osal_trace("osal_init_work kmalloc failed!\n");
84 return -1;
85 }
86
87 w_node = kmalloc(sizeof(struct wq_node), GFP_ATOMIC);
88 if (w_node == NULL) {
89 osal_trace("osal_init_work kmalloc failed!\n");
90 kfree(w);
91 w = NULL;
92 return -1;
93 }
94 INIT_WORK(w, osal_work_func);
95 work->work = w;
96 work->func = func;
97 w_node->osal_work = work;
98 w_node->work = w;
99 osal_list_add(&(w_node->node), &wq_list);
100 return 0;
101 }
102 EXPORT_SYMBOL(osal_init_work);
103
osal_schedule_work(struct osal_work_struct * work)104 int osal_schedule_work(struct osal_work_struct *work)
105 {
106 if ((work != NULL) && (work->work != NULL)) {
107 return (int)schedule_work(work->work);
108 } else {
109 return (int)false;
110 }
111 }
112 EXPORT_SYMBOL(osal_schedule_work);
113
osal_destroy_work(struct osal_work_struct * work)114 void osal_destroy_work(struct osal_work_struct *work)
115 {
116 if ((work != NULL) && (work->work != NULL)) {
117 osal_del_work(work->work);
118 kfree((struct work_struct *)work->work);
119 work->work = NULL;
120 }
121 }
122 EXPORT_SYMBOL(osal_destroy_work);
123