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 "hi_osal.h"
20
21 #include <linux/slab.h>
22 #include <linux/spinlock.h>
23 #include "securec.h"
24
25 int hi_drv_module_register(unsigned int module_id, const char *pu8_module_name, void *p_func);
26 int hi_drv_module_un_register(unsigned int module_id);
27 int hi_drv_module_get_function(unsigned int module_id, void **pp_func);
28
29 typedef struct exportfunc_node_ {
30 unsigned int module_id;
31 void *func;
32 struct osal_list_head node;
33 }exportfunc_node;
34
35 static DEFINE_SPINLOCK(g_func_lock);
36 static OSAL_LIST_HEAD(g_func_list);
37
osal_exportfunc_find_node(unsigned int module_id,struct osal_list_head * list)38 void *osal_exportfunc_find_node(unsigned int module_id, struct osal_list_head *list)
39 {
40 exportfunc_node *func_node = NULL;
41
42 osal_list_for_each_entry(func_node, list, node) {
43 if (func_node->module_id == module_id) {
44 return func_node;
45 }
46 }
47
48 return NULL;
49 }
50
osal_exportfunc_register(unsigned int module_id,const char * name,void * func)51 int osal_exportfunc_register(unsigned int module_id, const char *name, void *func)
52 {
53 int ret = 0;
54 unsigned long flags;
55 exportfunc_node *func_node_new = NULL;
56 exportfunc_node *func_node_find = NULL;
57
58 #ifndef CFG_HI_USER_DRV
59 return hi_drv_module_register(module_id, name, func);
60 #endif
61
62 func_node_new = kmalloc(sizeof(exportfunc_node), GFP_KERNEL);
63 if (func_node_new == NULL) {
64 return -1;
65 }
66
67 ret = memset_s(func_node_new, sizeof(exportfunc_node), 0, sizeof(exportfunc_node));
68 if (ret != 0) {
69 return -1;
70 }
71
72 spin_lock_irqsave(&g_func_lock, flags);
73
74 func_node_find = osal_exportfunc_find_node(module_id, &g_func_list);
75 if (func_node_find != NULL) {
76 kfree(func_node_new);
77 spin_unlock_irqrestore(&g_func_lock, flags);
78 return -1;
79 }
80
81 func_node_new->func = func;
82 func_node_new->module_id = module_id;
83
84 osal_list_add_tail(&(func_node_new->node), &g_func_list);
85
86 spin_unlock_irqrestore(&g_func_lock, flags);
87
88 return 0;
89 }
90 EXPORT_SYMBOL(osal_exportfunc_register);
91
osal_exportfunc_unregister(unsigned int module_id)92 int osal_exportfunc_unregister(unsigned int module_id)
93 {
94 unsigned long flags;
95 exportfunc_node *func_node_find = NULL;
96
97 #ifndef CFG_HI_USER_DRV
98 return hi_drv_module_un_register(module_id);
99 #endif
100
101 spin_lock_irqsave(&g_func_lock, flags);
102
103 func_node_find = osal_exportfunc_find_node(module_id, &g_func_list);
104 if (func_node_find != NULL) {
105 spin_unlock_irqrestore(&g_func_lock, flags);
106 return -1;
107 }
108
109 osal_list_del(&func_node_find->node);
110 kfree(func_node_find);
111
112 spin_unlock_irqrestore(&g_func_lock, flags);
113
114 return 0;
115 }
116 EXPORT_SYMBOL(osal_exportfunc_unregister);
117
osal_exportfunc_get(unsigned int module_id,void ** func)118 int osal_exportfunc_get(unsigned int module_id, void **func)
119 {
120 unsigned long flags;
121 exportfunc_node *func_node_find = NULL;
122
123 if (func == NULL) {
124 return -1;
125 }
126
127 #ifndef CFG_HI_USER_DRV
128 return hi_drv_module_get_function(module_id, func);
129 #endif
130
131 spin_lock_irqsave(&g_func_lock, flags);
132
133 func_node_find = osal_exportfunc_find_node(module_id, &g_func_list);
134 if (func_node_find == NULL) {
135 *func = NULL;
136 spin_unlock_irqrestore(&g_func_lock, flags);
137 return -1;
138 }
139
140 *func = func_node_find->func;
141
142 spin_unlock_irqrestore(&g_func_lock, flags);
143
144 return 0;
145 }
146 EXPORT_SYMBOL(osal_exportfunc_get);
147