1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_hwi.h"
33 #include "los_memory.h"
34 #include "los_spinlock.h"
35 #ifdef LOSCFG_KERNEL_CPUP
36 #include "los_cpup_pri.h"
37 #endif
38 #include "los_sched_pri.h"
39 #include "los_hook.h"
40
41 /* spinlock for hwi module, only available on SMP mode */
42 LITE_OS_SEC_BSS SPIN_LOCK_INIT(g_hwiSpin);
43 #define HWI_LOCK(state) LOS_SpinLockSave(&g_hwiSpin, &(state))
44 #define HWI_UNLOCK(state) LOS_SpinUnlockRestore(&g_hwiSpin, (state))
45
46 size_t g_intCount[LOSCFG_KERNEL_CORE_NUM] = {0};
47 HwiHandleForm g_hwiForm[OS_HWI_MAX_NUM];
48 STATIC CHAR *g_hwiFormName[OS_HWI_MAX_NUM] = {0};
49 STATIC UINT32 g_hwiFormCnt[LOSCFG_KERNEL_CORE_NUM][OS_HWI_MAX_NUM] = {0};
50
OsGetHwiFormCnt(UINT16 cpuid,UINT32 index)51 UINT32 OsGetHwiFormCnt(UINT16 cpuid, UINT32 index)
52 {
53 return g_hwiFormCnt[cpuid][index];
54 }
55
OsGetHwiFormName(UINT32 index)56 CHAR *OsGetHwiFormName(UINT32 index)
57 {
58 return g_hwiFormName[index];
59 }
60
LOS_GetSystemHwiMaximum(VOID)61 UINT32 LOS_GetSystemHwiMaximum(VOID)
62 {
63 return OS_HWI_MAX_NUM;
64 }
65
66 typedef VOID (*HWI_PROC_FUNC0)(VOID);
67 typedef VOID (*HWI_PROC_FUNC2)(INT32, VOID *);
OsInterrupt(UINT32 intNum)68 VOID OsInterrupt(UINT32 intNum)
69 {
70 HwiHandleForm *hwiForm = NULL;
71 UINT32 *intCnt = NULL;
72 UINT16 cpuid = ArchCurrCpuid();
73
74 /* Must keep the operation at the beginning of the interface */
75 intCnt = &g_intCount[cpuid];
76 *intCnt = *intCnt + 1;
77
78 #ifdef LOSCFG_CPUP_INCLUDE_IRQ
79 OsCpupIrqStart(cpuid);
80 #endif
81
82 OsSchedIrqStartTime();
83 OsHookCall(LOS_HOOK_TYPE_ISR_ENTER, intNum);
84 hwiForm = (&g_hwiForm[intNum]);
85 #ifndef LOSCFG_NO_SHARED_IRQ
86 while (hwiForm->pstNext != NULL) {
87 hwiForm = hwiForm->pstNext;
88 #endif
89 if (hwiForm->uwParam) {
90 HWI_PROC_FUNC2 func = (HWI_PROC_FUNC2)hwiForm->pfnHook;
91 if (func != NULL) {
92 UINTPTR *param = (UINTPTR *)(hwiForm->uwParam);
93 func((INT32)(*param), (VOID *)(*(param + 1)));
94 }
95 } else {
96 HWI_PROC_FUNC0 func = (HWI_PROC_FUNC0)hwiForm->pfnHook;
97 if (func != NULL) {
98 func();
99 }
100 }
101 #ifndef LOSCFG_NO_SHARED_IRQ
102 }
103 #endif
104 ++g_hwiFormCnt[cpuid][intNum];
105
106 OsHookCall(LOS_HOOK_TYPE_ISR_EXIT, intNum);
107 OsSchedIrqUsedTimeUpdate();
108
109 #ifdef LOSCFG_CPUP_INCLUDE_IRQ
110 OsCpupIrqEnd(cpuid, intNum);
111 #endif
112 /* Must keep the operation at the end of the interface */
113 *intCnt = *intCnt - 1;
114 }
115
OsHwiCpIrqParam(const HwiIrqParam * irqParam)116 STATIC HWI_ARG_T OsHwiCpIrqParam(const HwiIrqParam *irqParam)
117 {
118 HwiIrqParam *paramByAlloc = NULL;
119
120 if (irqParam != NULL) {
121 paramByAlloc = (HwiIrqParam *)LOS_MemAlloc(m_aucSysMem0, sizeof(HwiIrqParam));
122 if (paramByAlloc == NULL) {
123 return LOS_NOK;
124 }
125 (VOID)memcpy_s(paramByAlloc, sizeof(HwiIrqParam), irqParam, sizeof(HwiIrqParam));
126 }
127 /* When "irqParam" is NULL, the function return 0(LOS_OK). */
128 return (HWI_ARG_T)paramByAlloc;
129 }
130
131 #ifdef LOSCFG_NO_SHARED_IRQ
OsHwiDelNoShared(HWI_HANDLE_T hwiNum)132 STATIC UINT32 OsHwiDelNoShared(HWI_HANDLE_T hwiNum)
133 {
134 UINT32 intSave;
135
136 HWI_LOCK(intSave);
137 g_hwiForm[hwiNum].pfnHook = NULL;
138 if (g_hwiForm[hwiNum].uwParam) {
139 (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)g_hwiForm[hwiNum].uwParam);
140 }
141 g_hwiForm[hwiNum].uwParam = 0;
142
143 HWI_UNLOCK(intSave);
144 return LOS_OK;
145 }
146
OsHwiCreateNoShared(HWI_HANDLE_T hwiNum,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,const HwiIrqParam * irqParam)147 STATIC UINT32 OsHwiCreateNoShared(HWI_HANDLE_T hwiNum, HWI_MODE_T hwiMode,
148 HWI_PROC_FUNC hwiHandler, const HwiIrqParam *irqParam)
149 {
150 HWI_ARG_T retParam;
151 UINT32 intSave;
152
153 HWI_LOCK(intSave);
154 if (g_hwiForm[hwiNum].pfnHook == NULL) {
155 g_hwiForm[hwiNum].pfnHook = hwiHandler;
156
157 retParam = OsHwiCpIrqParam(irqParam);
158 if (retParam == LOS_NOK) {
159 HWI_UNLOCK(intSave);
160 return OS_ERRNO_HWI_NO_MEMORY;
161 }
162 g_hwiForm[hwiNum].uwParam = retParam;
163 } else {
164 HWI_UNLOCK(intSave);
165 return OS_ERRNO_HWI_ALREADY_CREATED;
166 }
167 HWI_UNLOCK(intSave);
168 return LOS_OK;
169 }
170 #else
OsHwiDelShared(HWI_HANDLE_T hwiNum,const HwiIrqParam * irqParam)171 STATIC UINT32 OsHwiDelShared(HWI_HANDLE_T hwiNum, const HwiIrqParam *irqParam)
172 {
173 HwiHandleForm *hwiForm = NULL;
174 HwiHandleForm *hwiFormtmp = NULL;
175 UINT32 hwiValid = FALSE;
176 UINT32 intSave;
177
178 HWI_LOCK(intSave);
179 hwiForm = &g_hwiForm[hwiNum];
180 hwiFormtmp = hwiForm;
181
182 if ((hwiForm->uwParam & IRQF_SHARED) && ((irqParam == NULL) || (irqParam->pDevId == NULL))) {
183 HWI_UNLOCK(intSave);
184 return OS_ERRNO_HWI_SHARED_ERROR;
185 }
186
187 if ((hwiForm->pstNext != NULL) && !(hwiForm->uwParam & IRQF_SHARED)) {
188 hwiForm = hwiForm->pstNext;
189 if (hwiForm->uwParam) {
190 (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)hwiForm->uwParam);
191 }
192 (VOID)LOS_MemFree(m_aucSysMem0, hwiForm);
193 hwiFormtmp->pstNext = NULL;
194
195 g_hwiFormName[hwiNum] = NULL;
196
197 HWI_UNLOCK(intSave);
198 return LOS_OK;
199 }
200 hwiForm = hwiForm->pstNext;
201 while (hwiForm != NULL) {
202 if (((HwiIrqParam *)(hwiForm->uwParam))->pDevId != irqParam->pDevId) {
203 hwiFormtmp = hwiForm;
204 hwiForm = hwiForm->pstNext;
205 } else {
206 hwiFormtmp->pstNext = hwiForm->pstNext;
207 (VOID)LOS_MemFree(m_aucSysMem0, (VOID *)hwiForm->uwParam);
208 (VOID)LOS_MemFree(m_aucSysMem0, hwiForm);
209
210 hwiValid = TRUE;
211 break;
212 }
213 }
214
215 if (hwiValid != TRUE) {
216 HWI_UNLOCK(intSave);
217 return OS_ERRNO_HWI_HWINUM_UNCREATE;
218 }
219
220 if (g_hwiForm[hwiNum].pstNext == NULL) {
221 g_hwiForm[hwiNum].uwParam = 0;
222 g_hwiFormName[hwiNum] = NULL;
223 }
224
225 HWI_UNLOCK(intSave);
226 return LOS_OK;
227 }
228
OsHwiCreateShared(HWI_HANDLE_T hwiNum,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,const HwiIrqParam * irqParam)229 STATIC UINT32 OsHwiCreateShared(HWI_HANDLE_T hwiNum, HWI_MODE_T hwiMode,
230 HWI_PROC_FUNC hwiHandler, const HwiIrqParam *irqParam)
231 {
232 UINT32 intSave;
233 HwiHandleForm *hwiFormNode = NULL;
234 HwiHandleForm *hwiForm = NULL;
235 HwiIrqParam *hwiParam = NULL;
236 HWI_MODE_T modeResult = hwiMode & IRQF_SHARED;
237
238 if (modeResult && ((irqParam == NULL) || (irqParam->pDevId == NULL))) {
239 return OS_ERRNO_HWI_SHARED_ERROR;
240 }
241
242 HWI_LOCK(intSave);
243
244 hwiForm = &g_hwiForm[hwiNum];
245 if ((hwiForm->pstNext != NULL) && ((modeResult == 0) || (!(hwiForm->uwParam & IRQF_SHARED)))) {
246 HWI_UNLOCK(intSave);
247 return OS_ERRNO_HWI_SHARED_ERROR;
248 }
249
250 while (hwiForm->pstNext != NULL) {
251 hwiForm = hwiForm->pstNext;
252 hwiParam = (HwiIrqParam *)(hwiForm->uwParam);
253 if (hwiParam->pDevId == irqParam->pDevId) {
254 HWI_UNLOCK(intSave);
255 return OS_ERRNO_HWI_ALREADY_CREATED;
256 }
257 }
258
259 hwiFormNode = (HwiHandleForm *)LOS_MemAlloc(m_aucSysMem0, sizeof(HwiHandleForm));
260 if (hwiFormNode == NULL) {
261 HWI_UNLOCK(intSave);
262 return OS_ERRNO_HWI_NO_MEMORY;
263 }
264
265 hwiFormNode->uwParam = OsHwiCpIrqParam(irqParam);
266 if (hwiFormNode->uwParam == LOS_NOK) {
267 HWI_UNLOCK(intSave);
268 (VOID)LOS_MemFree(m_aucSysMem0, hwiFormNode);
269 return OS_ERRNO_HWI_NO_MEMORY;
270 }
271
272 hwiFormNode->pfnHook = hwiHandler;
273 hwiFormNode->pstNext = (struct tagHwiHandleForm *)NULL;
274 hwiForm->pstNext = hwiFormNode;
275
276 if ((irqParam != NULL) && (irqParam->pName != NULL)) {
277 g_hwiFormName[hwiNum] = (CHAR *)irqParam->pName;
278 }
279
280 g_hwiForm[hwiNum].uwParam = modeResult;
281
282 HWI_UNLOCK(intSave);
283 return LOS_OK;
284 }
285 #endif
286
287 /*
288 * Description : initialization of the hardware interrupt
289 */
OsHwiInit(VOID)290 LITE_OS_SEC_TEXT_INIT VOID OsHwiInit(VOID)
291 {
292 UINT32 hwiNum;
293
294 for (hwiNum = 0; hwiNum < OS_HWI_MAX_NUM; hwiNum++) {
295 g_hwiForm[hwiNum].pfnHook = NULL;
296 g_hwiForm[hwiNum].uwParam = 0;
297 g_hwiForm[hwiNum].pstNext = NULL;
298 }
299
300 (VOID)memset_s(g_hwiFormName, (sizeof(CHAR *) * OS_HWI_MAX_NUM), 0, (sizeof(CHAR *) * OS_HWI_MAX_NUM));
301
302 HalIrqInit();
303
304 return;
305 }
306
LOS_HwiCreate(HWI_HANDLE_T hwiNum,HWI_PRIOR_T hwiPrio,HWI_MODE_T hwiMode,HWI_PROC_FUNC hwiHandler,HwiIrqParam * irqParam)307 LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiCreate(HWI_HANDLE_T hwiNum,
308 HWI_PRIOR_T hwiPrio,
309 HWI_MODE_T hwiMode,
310 HWI_PROC_FUNC hwiHandler,
311 HwiIrqParam *irqParam)
312 {
313 UINT32 ret;
314
315 (VOID)hwiPrio;
316 if (hwiHandler == NULL) {
317 return OS_ERRNO_HWI_PROC_FUNC_NULL;
318 }
319 if ((hwiNum > OS_USER_HWI_MAX) || ((INT32)hwiNum < OS_USER_HWI_MIN)) {
320 return OS_ERRNO_HWI_NUM_INVALID;
321 }
322
323 #ifdef LOSCFG_NO_SHARED_IRQ
324 ret = OsHwiCreateNoShared(hwiNum, hwiMode, hwiHandler, irqParam);
325 #else
326 ret = OsHwiCreateShared(hwiNum, hwiMode, hwiHandler, irqParam);
327 #endif
328 return ret;
329 }
330
LOS_HwiDelete(HWI_HANDLE_T hwiNum,HwiIrqParam * irqParam)331 LITE_OS_SEC_TEXT_INIT UINT32 LOS_HwiDelete(HWI_HANDLE_T hwiNum, HwiIrqParam *irqParam)
332 {
333 UINT32 ret;
334
335 if ((hwiNum > OS_USER_HWI_MAX) || ((INT32)hwiNum < OS_USER_HWI_MIN)) {
336 return OS_ERRNO_HWI_NUM_INVALID;
337 }
338
339 #ifdef LOSCFG_NO_SHARED_IRQ
340 ret = OsHwiDelNoShared(hwiNum);
341 #else
342 ret = OsHwiDelShared(hwiNum, irqParam);
343 #endif
344 return ret;
345 }
346
347