1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: workqueue
15 *
16 * Create: 2021-12-16
17 */
18
19 #include <linux/workqueue.h>
20 #include "soc_osal.h"
21 #include "osal_errno.h"
22 #include "osal_inner.h"
23
24 OSAL_LIST_HEAD(g_wq_list);
25 struct wq_node {
26 osal_workqueue *osal_work;
27 struct work_struct *work;
28 struct osal_list_head node;
29 };
30
osal_find_work(const struct work_struct * work)31 static osal_workqueue *osal_find_work(const struct work_struct *work)
32 {
33 struct osal_list_head *cur = NULL;
34
35 if (work == NULL) {
36 osal_log("parameter invalid!\n");
37 return NULL;
38 }
39
40 if (osal_list_empty(&g_wq_list) != 0) {
41 osal_log("g_wq_list is empty!\n");
42 return NULL;
43 }
44 osal_list_for_each(cur, &g_wq_list)
45 {
46 struct wq_node *ws = osal_list_entry(cur, struct wq_node, node);
47 if (ws->work == work) {
48 return ws->osal_work;
49 }
50 }
51 osal_log("find work failed!\n");
52 return NULL;
53 }
54
osal_del_work(const struct work_struct * work)55 static int osal_del_work(const struct work_struct *work)
56 {
57 struct osal_list_head *cur = NULL;
58 struct osal_list_head *next = NULL;
59
60 if (work == NULL) {
61 osal_log("parameter invalid!\n");
62 return OSAL_FAILURE;
63 }
64
65 if (osal_list_empty(&g_wq_list) != 0) {
66 osal_log("g_wq_list is empty!\n");
67 return OSAL_FAILURE;
68 }
69 osal_list_for_each_safe(cur, next, &g_wq_list)
70 {
71 struct wq_node *ws = osal_list_entry(cur, struct wq_node, node);
72 if (ws->work == work) {
73 osal_list_del(cur);
74 LOS_MemFree((void *)m_aucSysMem0, (void *)ws);
75 return OSAL_SUCCESS;
76 }
77 }
78 osal_log("find work failed!\n");
79 return OSAL_FAILURE;
80 }
81
osal_work_handler(struct work_struct * work)82 static void osal_work_handler(struct work_struct *work)
83 {
84 osal_workqueue *ow = osal_find_work(work);
85 if ((ow != NULL) && (ow->handler != NULL)) {
86 ow->handler(ow);
87 }
88 }
89
osal_workqueue_init(osal_workqueue * work,osal_workqueue_handler handler)90 int osal_workqueue_init(osal_workqueue *work, osal_workqueue_handler handler)
91 {
92 struct work_struct *w = NULL;
93 struct wq_node *w_node = NULL;
94
95 if (work == NULL || work->work != NULL) {
96 osal_log("parameter invalid!\n");
97 return OSAL_FAILURE;
98 }
99
100 w = LOS_MemAlloc((void *)m_aucSysMem0, sizeof(struct work_struct));
101 if (w == NULL) {
102 osal_log("LOS_MemAlloc failed!\n");
103 return OSAL_FAILURE;
104 }
105
106 w_node = LOS_MemAlloc((void *)m_aucSysMem0, sizeof(struct wq_node));
107 if (w_node == NULL) {
108 osal_log("LOS_MemAlloc failed!\n");
109 LOS_MemFree((void *)m_aucSysMem0, (void *)w);
110 return OSAL_FAILURE;
111 }
112 INIT_WORK(w, osal_work_handler);
113 work->work = w;
114 work->handler = handler;
115 w_node->osal_work = work;
116 w_node->work = w;
117 osal_list_add(&(w_node->node), &g_wq_list);
118 return OSAL_SUCCESS;
119 }
120
osal_workqueue_schedule(osal_workqueue * work)121 int osal_workqueue_schedule(osal_workqueue *work)
122 {
123 if (work == NULL || work->work == NULL) {
124 osal_log("parameter invalid!\n");
125 return FALSE;
126 }
127 if (!schedule_work(work->work)) {
128 return FALSE;
129 }
130 return TRUE;
131 }
132
osal_workqueue_destroy(osal_workqueue * work)133 void osal_workqueue_destroy(osal_workqueue *work)
134 {
135 if (work == NULL || work->work == NULL) {
136 osal_log("parameter invalid!\n");
137 return;
138 }
139 osal_del_work(work->work);
140 LOS_MemFree((void *)m_aucSysMem0, work->work);
141 work->work = NULL;
142 }
143
osal_workqueue_flush(osal_workqueue * work)144 int osal_workqueue_flush(osal_workqueue *work)
145 {
146 if (work == NULL || work->work == NULL) {
147 osal_log("parameter invalid!\n");
148 return OSAL_FAILURE;
149 }
150 if (!flush_work(work->work)) {
151 return FALSE;
152 }
153 return TRUE;
154 }
155