1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "can/can_manager.h"
10 #include "osal_time.h"
11 #include "securec.h"
12 #include "can/can_core.h"
13
14 #define HDF_LOG_TAG can_manager
15
16 #define CAN_NUMBER_MAX 32
17 #define CAN_MSG_POOL_SIZE_DFT 8
18 #define CAN_IRQ_STACK_SIZE (1024 * 8)
19
20 static struct PlatformManager *g_manager;
21
CanManagerGet(void)22 static struct PlatformManager *CanManagerGet(void)
23 {
24 int32_t ret;
25
26 if (g_manager == NULL) {
27 ret = PlatformManagerCreate("CAN_BUS_MANAGER", &g_manager);
28 if (ret != HDF_SUCCESS) {
29 HDF_LOGE("CanManagerGet: create can manager fail, ret: %d!", ret);
30 }
31 }
32 return g_manager;
33 }
34
CanManagerDestroyIfNeed(void)35 static void CanManagerDestroyIfNeed(void)
36 {
37 if (g_manager != NULL && DListIsEmpty(&g_manager->devices)) {
38 PlatformManagerDestroy(g_manager);
39 g_manager = NULL;
40 }
41 }
42
CanIrqThreadWorker(void * data)43 static int32_t CanIrqThreadWorker(void *data)
44 {
45 int32_t ret;
46 struct CanCntlr *cntlr = (struct CanCntlr *)data;
47
48 if (cntlr == NULL) {
49 HDF_LOGE("CanIrqThreadWorker: cntlr is null!");
50 return HDF_ERR_INVALID_OBJECT;
51 }
52
53 cntlr->threadStatus |= CAN_THREAD_RUNNING;
54 while ((cntlr->threadStatus & CAN_THREAD_RUNNING) != 0) {
55 /* wait event */
56 ret = OsalSemWait(&cntlr->sem, HDF_WAIT_FOREVER);
57 if (ret != HDF_SUCCESS) {
58 continue;
59 }
60 if ((cntlr->threadStatus & CAN_THREAD_RUNNING) == 0) {
61 break; // exit thread
62 }
63 ret = CanCntlrOnNewMsg(cntlr, cntlr->irqMsg);
64 if (ret != HDF_SUCCESS) {
65 HDF_LOGE("CanIrqThreadWorker: CanCntlrOnNewMsg fail!");
66 }
67 cntlr->irqMsg = NULL;
68 cntlr->threadStatus &= ~CAN_THREAD_PENDING;
69 }
70
71 cntlr->threadStatus |= CAN_THREAD_STOPPED;
72 return HDF_SUCCESS;
73 }
74
CanCntlrCreateThread(struct CanCntlr * cntlr)75 static int32_t CanCntlrCreateThread(struct CanCntlr *cntlr)
76 {
77 int32_t ret;
78 struct OsalThreadParam config;
79
80 if (memset_s(&config, sizeof(config), 0, sizeof(config)) != EOK) {
81 HDF_LOGE("CanCntlrCreateThread: memset_s fail!");
82 return HDF_ERR_IO;
83 }
84 ret = OsalSemInit(&cntlr->sem, 0);
85 if (ret != HDF_SUCCESS) {
86 HDF_LOGE("CanCntlrCreateThread: sem init fail!");
87 return ret;
88 }
89
90 ret = OsalThreadCreate(&cntlr->thread, (OsalThreadEntry)CanIrqThreadWorker, cntlr);
91 if (ret != HDF_SUCCESS) {
92 HDF_LOGE("CanCntlrCreateThread: thread create fail!");
93 (void)OsalSemDestroy(&cntlr->sem);
94 return ret;
95 }
96
97 config.name = "CanIrqThread";
98 config.priority = OSAL_THREAD_PRI_HIGH;
99 config.stackSize = CAN_IRQ_STACK_SIZE;
100 cntlr->threadStatus = 0;
101 ret = OsalThreadStart(&cntlr->thread, &config);
102 if (ret != HDF_SUCCESS) {
103 HDF_LOGE("CanCntlrCreateThread: thread start fail!");
104 OsalThreadDestroy(&cntlr->thread);
105 (void)OsalSemDestroy(&cntlr->sem);
106 return ret;
107 }
108
109 return HDF_SUCCESS;
110 }
111
CanCntlrCheckAndInit(struct CanCntlr * cntlr)112 static int32_t CanCntlrCheckAndInit(struct CanCntlr *cntlr)
113 {
114 if (cntlr == NULL || cntlr->ops == NULL) {
115 return HDF_ERR_INVALID_OBJECT;
116 }
117
118 if (cntlr->number < 0 || cntlr->number >= CAN_NUMBER_MAX) {
119 HDF_LOGE("CanCntlrCheckAndInit: invlaid can num:%d!", cntlr->number);
120 return HDF_ERR_INVALID_OBJECT;
121 }
122
123 DListHeadInit(&cntlr->rxBoxList);
124
125 if (CanCntlrCreateThread(cntlr) != HDF_SUCCESS) {
126 HDF_LOGE("CanCntlrCheckAndInit: create thread fail!");
127 return HDF_FAILURE;
128 }
129 if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
130 HDF_LOGE("CanCntlrCheckAndInit: init lock fail!");
131 return HDF_FAILURE;
132 }
133
134 if (OsalMutexInit(&cntlr->rboxListLock) != HDF_SUCCESS) {
135 HDF_LOGE("CanCntlrCheckAndInit: init rx box list lock fail!");
136 (void)OsalMutexDestroy(&cntlr->lock);
137 return HDF_FAILURE;
138 }
139
140 if (cntlr->msgPoolSize <= 0) {
141 cntlr->msgPoolSize = CAN_MSG_POOL_SIZE_DFT;
142 }
143
144 cntlr->msgPool = CanMsgPoolCreate(cntlr->msgPoolSize);
145 if (cntlr->msgPool == NULL) {
146 HDF_LOGE("CanCntlrCheckAndInit: create can msg pool fail!");
147 (void)OsalMutexDestroy(&cntlr->rboxListLock);
148 (void)OsalMutexDestroy(&cntlr->lock);
149 return HDF_FAILURE;
150 }
151
152 return HDF_SUCCESS;
153 }
154
CanCntlrDestroyThread(struct CanCntlr * cntlr)155 static void CanCntlrDestroyThread(struct CanCntlr *cntlr)
156 {
157 int t = 0;
158
159 cntlr->threadStatus &= ~CAN_THREAD_RUNNING;
160 cntlr->irqMsg = NULL;
161 (void)OsalSemPost(&cntlr->sem);
162 while ((cntlr->threadStatus & CAN_THREAD_STOPPED) == 0) {
163 OsalMSleep(1);
164 if (t++ > THREAD_EXIT_TIMEOUT) {
165 break;
166 }
167 }
168 (void)OsalThreadDestroy(&cntlr->thread);
169 (void)OsalSemDestroy(&cntlr->sem);
170 }
171
CanCntlrDeInit(struct CanCntlr * cntlr)172 static void CanCntlrDeInit(struct CanCntlr *cntlr)
173 {
174 HDF_LOGD("CanCntlrDeInit: enter!");
175 CanCntlrDestroyThread(cntlr);
176 CanMsgPoolDestroy(cntlr->msgPool);
177 cntlr->msgPool = NULL;
178 (void)OsalMutexDestroy(&cntlr->rboxListLock);
179 (void)OsalMutexDestroy(&cntlr->lock);
180 HDF_LOGD("CanCntlrDeInit: exit!");
181 }
182
CanCntlrAdd(struct CanCntlr * cntlr)183 int32_t CanCntlrAdd(struct CanCntlr *cntlr)
184 {
185 int32_t ret;
186
187 ret = CanCntlrCheckAndInit(cntlr);
188 if (ret != HDF_SUCCESS) {
189 HDF_LOGE("CanCntlrAdd: can cntlr check and init fail!");
190 return ret;
191 }
192
193 cntlr->device.number = cntlr->number;
194 ret = PlatformDeviceSetName(&cntlr->device, "CAN%d", cntlr->number);
195 if (ret != HDF_SUCCESS) {
196 CanCntlrDeInit(cntlr);
197 HDF_LOGE("CanCntlrAdd: set name for platform device fail!");
198 return ret;
199 }
200
201 cntlr->device.manager = CanManagerGet();
202 if (cntlr->device.manager == NULL) {
203 PlatformDeviceClearName(&cntlr->device);
204 CanCntlrDeInit(cntlr);
205 HDF_LOGE("CanCntlrAdd: get can manager fail!");
206 return HDF_PLT_ERR_DEV_GET;
207 }
208
209 if ((ret = PlatformDeviceAdd(&cntlr->device)) != HDF_SUCCESS) {
210 PlatformDeviceClearName(&cntlr->device);
211 CanCntlrDeInit(cntlr);
212 HDF_LOGE("CanCntlrAdd: add platform device fail!");
213 return ret;
214 }
215
216 HDF_LOGI("CanCntlrAdd: add controller %d success!", cntlr->number);
217 return HDF_SUCCESS;
218 }
219
CanCntlrDel(struct CanCntlr * cntlr)220 int32_t CanCntlrDel(struct CanCntlr *cntlr)
221 {
222 if (cntlr == NULL) {
223 HDF_LOGE("CanCntlrDel: cntlr is null!");
224 return HDF_ERR_INVALID_OBJECT;
225 }
226
227 PlatformDeviceDel(&cntlr->device);
228 PlatformDeviceClearName(&cntlr->device);
229
230 CanCntlrDeInit(cntlr);
231
232 CanManagerDestroyIfNeed();
233 HDF_LOGI("CanCntlrDel: del controller %d success!", cntlr->number);
234 return HDF_SUCCESS;
235 }
236
CanCntlrFromPlatformDevice(const struct PlatformDevice * pdevice)237 static struct CanCntlr *CanCntlrFromPlatformDevice(const struct PlatformDevice *pdevice)
238 {
239 return CONTAINER_OF(pdevice, struct CanCntlr, device);
240 }
241
CanCntlrGetByName(const char * name)242 struct CanCntlr *CanCntlrGetByName(const char *name)
243 {
244 static struct PlatformManager *manager = NULL;
245 struct PlatformDevice *pdevice = NULL;
246
247 manager = CanManagerGet();
248 if (manager == NULL) {
249 HDF_LOGE("CanCntlrGetByName: get can manager fail!");
250 return NULL;
251 }
252
253 pdevice = PlatformManagerGetDeviceByName(manager, name);
254 if (pdevice == NULL) {
255 HDF_LOGE("CanCntlrGetByName: get platform device fail!");
256 return NULL;
257 }
258
259 return CanCntlrFromPlatformDevice(pdevice);
260 }
261
CanCntlrGetByNumber(int32_t number)262 struct CanCntlr *CanCntlrGetByNumber(int32_t number)
263 {
264 static struct PlatformManager *manager = NULL;
265 struct PlatformDevice *pdevice = NULL;
266
267 manager = CanManagerGet();
268 if (manager == NULL) {
269 HDF_LOGE("CanCntlrGetByNumber: get can manager fail!");
270 return NULL;
271 }
272
273 pdevice = PlatformManagerGetDeviceByNumber(manager, number);
274 if (pdevice == NULL) {
275 HDF_LOGE("CanCntlrGetByNumber: get platform device fail!");
276 return NULL;
277 }
278
279 return CanCntlrFromPlatformDevice(pdevice);
280 }
281
CanCntlrPut(struct CanCntlr * cntlr)282 void CanCntlrPut(struct CanCntlr *cntlr)
283 {
284 if (cntlr != NULL) {
285 PlatformDevicePut(&cntlr->device);
286 }
287 }
288