• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 <linux/version.h>
23 #include "hi_osal.h"
24 
25 OSAL_LIST_HEAD(wq_list);
26 struct wq_node {
27     osal_workqueue *osal_work;
28     struct work_struct *work;
29     struct osal_list_head node;
30 };
31 
osal_find_work(struct work_struct * work)32 static osal_workqueue *osal_find_work(struct work_struct *work)
33 {
34     struct osal_list_head *this = NULL;
35 
36     if (work == NULL) {
37         osal_printk("%s - parameter invalid!\n", __FUNCTION__);
38         return NULL;
39     }
40 
41     if (osal_list_empty(&wq_list)) {
42         osal_printk("find work failed! wq_list is empty!\n");
43         return NULL;
44     }
45     osal_list_for_each(this, &wq_list) {
46         struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
47         if (ws->work == work) {
48             return ws->osal_work;
49         }
50     }
51     osal_printk("find work failed!\n");
52     return NULL;
53 }
54 
osal_del_work(struct work_struct * work)55 static int osal_del_work(struct work_struct *work)
56 {
57     struct osal_list_head *this = NULL;
58     struct osal_list_head *next = NULL;
59 
60     if (work == NULL) {
61         osal_printk("%s - parameter invalid!\n", __FUNCTION__);
62         return -1;
63     }
64 
65     if (osal_list_empty(&wq_list)) {
66         osal_printk("find work failed! wq_list is empty!\n");
67         return -1;
68     }
69     osal_list_for_each_safe(this, next, &wq_list) {
70         struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
71         if (ws->work == work) {
72             osal_list_del(this);
73             kfree(ws);
74             return 0;
75         }
76     }
77     osal_printk("del work failed!\n");
78     return -1;
79 }
80 
osal_work_handler(struct work_struct * work)81 static void osal_work_handler(struct work_struct *work)
82 {
83     osal_workqueue *ow = osal_find_work(work);
84     if ((ow != NULL) && (ow->handler != NULL)) {
85         ow->handler(ow);
86     }
87 }
88 
osal_workqueue_init(osal_workqueue * work,osal_workqueue_handler handler)89 int osal_workqueue_init(osal_workqueue *work, osal_workqueue_handler handler)
90 {
91     struct work_struct *w = NULL;
92     struct wq_node *w_node = NULL;
93 
94     if (work == NULL) {
95         osal_printk("%s - parameter invalid!\n", __FUNCTION__);
96         return -1;
97     }
98 
99     w = kmalloc(sizeof(struct work_struct), GFP_ATOMIC);
100     if (w == NULL) {
101         osal_printk("osal_init_work kmalloc failed!\n");
102         return -1;
103     }
104 
105     w_node = kmalloc(sizeof(struct wq_node), GFP_ATOMIC);
106     if (w_node == NULL) {
107         osal_printk("osal_init_work kmalloc failed!\n");
108         kfree(w);
109         return -1;
110     }
111     INIT_WORK(w, osal_work_handler);
112     work->work = w;
113     work->handler = handler;
114     w_node->osal_work = work;
115     w_node->work = w;
116     osal_list_add(&(w_node->node), &wq_list);
117     return 0;
118 }
119 EXPORT_SYMBOL(osal_workqueue_init);
120 
osal_workqueue_schedule(osal_workqueue * work)121 int osal_workqueue_schedule(osal_workqueue *work)
122 {
123     if ((work != NULL) && (work->work != NULL)) {
124         return (int)schedule_work(work->work);
125     } else {
126         return (int)false;
127     }
128 }
129 EXPORT_SYMBOL(osal_workqueue_schedule);
130 
osal_workqueue_destroy(osal_workqueue * work)131 void osal_workqueue_destroy(osal_workqueue *work)
132 {
133     if ((work != NULL) && (work->work != NULL)) {
134         osal_del_work(work->work);
135         kfree((struct work_struct *)work->work);
136         work->work = NULL;
137     }
138 }
139 EXPORT_SYMBOL(osal_workqueue_destroy);
140 
osal_workqueue_flush(osal_workqueue * work)141 int osal_workqueue_flush(osal_workqueue *work)
142 {
143 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 0, 0))
144     if ((work != NULL) && (work->work != NULL)) {
145         return (int)flush_work(work->work);
146     } else {
147         return -1;
148     }
149 #endif
150     return 0;
151 }
152 EXPORT_SYMBOL(osal_workqueue_flush);
153