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