• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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