1 /*
2 * Copyright (c) 2020-2021 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 "dmac_core.h"
10 #include <string.h>
11 #include "hdf_log.h"
12 #include "osal_io.h"
13 #include "osal_irq.h"
14 #include "osal_mem.h"
15
16 #define HDF_LOG_TAG dmac_core
17
18 #define DMA_ALIGN_SIZE 256
19 #define DMA_MAX_TRANS_SIZE_DEFAULT 256
20
DmacCntlrCheckOps(struct DmaCntlr * cntlr)21 static int32_t DmacCntlrCheckOps(struct DmaCntlr *cntlr)
22 {
23 if (cntlr->getChanInfo == NULL) {
24 HDF_LOGE("%s: getChanInfo is null", __func__);
25 return HDF_ERR_INVALID_OBJECT;
26 }
27 if (cntlr->dmaChanEnable == NULL) {
28 HDF_LOGE("%s: dmaChanEnable is null", __func__);
29 return HDF_ERR_INVALID_OBJECT;
30 }
31 if (cntlr->dmaM2mChanEnable == NULL) {
32 HDF_LOGE("%s: dmaM2mChanEnable is null", __func__);
33 return HDF_ERR_INVALID_OBJECT;
34 }
35 if (cntlr->dmacChanDisable == NULL) {
36 HDF_LOGE("%s: dmacChanDisable is null", __func__);
37 return HDF_ERR_INVALID_OBJECT;
38 }
39 if (cntlr->dmacCacheInv == NULL) {
40 HDF_LOGE("%s: dmacCacheInv null", __func__);
41 return HDF_ERR_INVALID_OBJECT;
42 }
43 if (cntlr->dmacCacheFlush == NULL) {
44 HDF_LOGE("%s: dmacCacheFlush null", __func__);
45 return HDF_ERR_INVALID_OBJECT;
46 }
47 if (cntlr->dmacPaddrToVaddr == NULL) {
48 HDF_LOGE("%s: dmacPaddrToVaddr null", __func__);
49 return HDF_ERR_INVALID_OBJECT;
50 }
51 if (cntlr->dmacVaddrToPaddr == NULL) {
52 HDF_LOGE("%s: dmacVaddrToPaddr null", __func__);
53 return HDF_ERR_INVALID_OBJECT;
54 }
55 if (cntlr->dmacGetChanStatus == NULL) {
56 HDF_LOGE("%s: dmacGetChanStatus null", __func__);
57 return HDF_ERR_INVALID_OBJECT;
58 }
59 if (cntlr->dmacGetCurrDestAddr == NULL) {
60 HDF_LOGE("%s: dmacGetCurrDestAddr null", __func__);
61 return HDF_ERR_INVALID_OBJECT;
62 }
63 return HDF_SUCCESS;
64 }
65
DmacCntlrCheckParam(struct DmaCntlr * cntlr)66 static int32_t DmacCntlrCheckParam(struct DmaCntlr *cntlr)
67 {
68 if (cntlr == NULL) {
69 HDF_LOGE("%s: cntlr is null", __func__);
70 return HDF_ERR_INVALID_OBJECT;
71 }
72 if (cntlr->maxTransSize == 0) {
73 HDF_LOGE("%s: cntlr is null", __func__);
74 return HDF_ERR_INVALID_OBJECT;
75 }
76 if (cntlr->channelNum == 0 || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
77 HDF_LOGE("%s: invalid channelNum:%u", __func__, cntlr->channelNum);
78 return HDF_ERR_INVALID_OBJECT;
79 }
80 return HDF_SUCCESS;
81 }
82
DmacCntlrCheckInit(struct DmaCntlr * cntlr)83 static int32_t DmacCntlrCheckInit(struct DmaCntlr *cntlr)
84 {
85 int32_t ret;
86
87 ret = DmacCntlrCheckParam(cntlr);
88 if (ret != HDF_SUCCESS) {
89 return ret;
90 }
91 ret = DmacCntlrCheckOps(cntlr);
92 if (ret != HDF_SUCCESS) {
93 return ret;
94 }
95 return HDF_SUCCESS;
96 }
97
DmacCntlrCheck(struct DmaCntlr * cntlr)98 static int32_t DmacCntlrCheck(struct DmaCntlr *cntlr)
99 {
100 int32_t ret;
101
102 ret = DmacCntlrCheckInit(cntlr);
103 if (ret != HDF_SUCCESS) {
104 return ret;
105 }
106 if (cntlr->channelList == NULL) {
107 HDF_LOGE("%s: channelList is null", __func__);
108 return HDF_ERR_INVALID_OBJECT;
109 }
110 return HDF_SUCCESS;
111 }
112
DmaCntlrCreate(struct HdfDeviceObject * device)113 struct DmaCntlr *DmaCntlrCreate(struct HdfDeviceObject *device)
114 {
115 struct DmaCntlr *cntlr = NULL;
116
117 if (device == NULL) {
118 return NULL;
119 }
120 cntlr = (struct DmaCntlr *)OsalMemCalloc(sizeof(struct DmaCntlr));
121 if (cntlr == NULL) {
122 return NULL;
123 }
124 cntlr->device = device;
125 return cntlr;
126 }
127
DmacFreeLli(struct DmacChanInfo * chanInfo)128 static void DmacFreeLli(struct DmacChanInfo *chanInfo)
129 {
130 if (chanInfo != NULL && chanInfo->lli != NULL) {
131 OsalMemFree(chanInfo->lli);
132 chanInfo->lli = NULL;
133 chanInfo->lliCnt = 0;
134 }
135 }
136
137 /*
138 * If private is allocated, release private before calling this function
139 */
DmaCntlrDestroy(struct DmaCntlr * cntlr)140 void DmaCntlrDestroy(struct DmaCntlr *cntlr)
141 {
142 uint16_t i;
143
144 if (cntlr == NULL || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
145 HDF_LOGE("dma cntlr null or channel invalid!");
146 return;
147 }
148 if (cntlr->channelList != NULL) {
149 for (i = 0; i < cntlr->channelNum; i++) {
150 DmacFreeLli(&(cntlr->channelList[i]));
151 }
152 OsalMemFree(cntlr->channelList);
153 cntlr->channelList = NULL;
154 cntlr->channelNum = 0;
155 }
156 /* Private is released by the caller */
157 cntlr->private = NULL;
158 OsalMemFree(cntlr);
159 }
160
DmacEventCallback(struct DmacChanInfo * chanInfo)161 static void DmacEventCallback(struct DmacChanInfo *chanInfo)
162 {
163 if (chanInfo->status == DMAC_CHN_ERROR) {
164 DmaEventSignal(&chanInfo->waitEvent, DMAC_EVENT_ERROR);
165 } else {
166 DmaEventSignal(&chanInfo->waitEvent, DMAC_EVENT_DONE);
167 }
168 }
169
DmacCallbackHandle(struct DmacChanInfo * chanInfo)170 static void DmacCallbackHandle(struct DmacChanInfo *chanInfo)
171 {
172 if (chanInfo->transType == TRASFER_TYPE_M2M) {
173 DmacEventCallback(chanInfo);
174 return;
175 }
176 if (chanInfo->callback != NULL) {
177 chanInfo->callback(chanInfo->callbackData, chanInfo->status);
178 }
179 }
180
DmacWaitM2mSendComplete(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo)181 static int32_t DmacWaitM2mSendComplete(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo)
182 {
183 uint32_t ret;
184
185 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
186 return HDF_ERR_INVALID_OBJECT;
187 }
188
189 ret = DmaEventWait(&chanInfo->waitEvent, DMAC_EVENT_DONE | DMAC_EVENT_ERROR, DMA_EVENT_WAIT_DEF_TIME);
190 if (ret == DMAC_EVENT_ERROR) {
191 HDF_LOGE("%s: wait event error", __func__);
192 return DMAC_CHN_ERROR;
193 } else if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) {
194 HDF_LOGE("%s: wait event timeout", __func__);
195 return DMAC_CHN_TIMEOUT;
196 }
197
198 cntlr->dmacChanDisable(cntlr, chanInfo->channel);
199 return DMAC_CHN_SUCCESS;
200 }
201
DmacAllocateChannel(struct DmaCntlr * cntlr)202 static int32_t DmacAllocateChannel(struct DmaCntlr *cntlr)
203 {
204 uint16_t i;
205 uint32_t flags;
206
207 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
208 return HDF_ERR_INVALID_OBJECT;
209 }
210
211 OsalSpinLockIrqSave(&cntlr->lock, &flags);
212 for (i = 0; i < cntlr->channelNum; i++) {
213 if (cntlr->channelList[i].useStatus == DMAC_CHN_VACANCY) {
214 cntlr->channelList[i].useStatus = DMAC_CHN_ALLOCAT;
215 OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
216 return (int32_t)i;
217 }
218 }
219 OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
220 return HDF_FAILURE;
221 }
222
DmacFreeChannel(struct DmaCntlr * cntlr,uint16_t channel)223 static void DmacFreeChannel(struct DmaCntlr *cntlr, uint16_t channel)
224 {
225 uint32_t flags;
226
227 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
228 return;
229 }
230
231 OsalSpinLockIrqSave(&cntlr->lock, &flags);
232 DmacFreeLli(&cntlr->channelList[channel]);
233 cntlr->channelList[channel].useStatus = DMAC_CHN_VACANCY;
234 OsalSpinUnlockIrqRestore(&cntlr->lock, &flags);
235 }
236
DmacRequestChannel(struct DmaCntlr * cntlr,struct DmacMsg * msg)237 static struct DmacChanInfo *DmacRequestChannel(struct DmaCntlr *cntlr, struct DmacMsg *msg)
238 {
239 int32_t ret;
240 int32_t chan;
241 struct DmacChanInfo *chanInfo = NULL;
242
243 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS || msg == NULL) {
244 HDF_LOGE("%s: cntlr check failed or msg invalid", __func__);
245 return NULL;
246 }
247
248 chan = DmacAllocateChannel(cntlr);
249 if (chan < 0) {
250 HDF_LOGE("%s: allocate channel failed", __func__);
251 return NULL;
252 }
253 chanInfo = &(cntlr->channelList[chan]);
254 chanInfo->channel = (unsigned int)chan;
255 chanInfo->transType = msg->transType;
256 ret = cntlr->getChanInfo(cntlr, chanInfo, msg);
257 if (ret < 0) {
258 DmacFreeChannel(cntlr, chan);
259 HDF_LOGE("%s: get channel info failed ret = %d", __func__, ret);
260 return NULL;
261 }
262 #ifdef DMA_CORE_DEBUG
263 HDF_LOGD("chan = %d, type = %d srcWidth = %u, destWidth = %u, config = 0x%x, lliEnflag = 0x%x",
264 chan, chanInfo->transType, chanInfo->srcWidth, chanInfo->destWidth, chanInfo->config, chanInfo->lliEnFlag);
265 #endif
266 return chanInfo;
267 }
268
DmacGetDummyBuf(struct DmaCntlr * cntlr,struct DmacChanInfo * chan)269 static uintptr_t DmacGetDummyBuf(struct DmaCntlr *cntlr, struct DmacChanInfo *chan)
270 {
271 if (chan->dummyPage == NULL) {
272 chan->dummyPage = OsalMemCalloc(sizeof(cntlr->maxTransSize));
273 }
274
275 return (chan->dummyPage == NULL) ? 0 : (uintptr_t)LOS_PaddrQuery(chan->dummyPage);
276 }
277
DmacAlignedTransMax(size_t maxSize,uint8_t srcWidth,uint8_t destWidth)278 static inline size_t DmacAlignedTransMax(size_t maxSize, uint8_t srcWidth, uint8_t destWidth)
279 {
280 size_t ret;
281 uint8_t maxWidth = (srcWidth >= destWidth) ? srcWidth : destWidth;
282
283 ret = ((maxWidth == 0) ? maxSize : (maxSize - (maxSize % maxWidth)));
284 #ifdef DMA_CORE_DEBUG
285 HDF_LOGD("%s: max:%zu, srcwidth:%u, dstwidth:%hhu, alignedmax:%zu", __func__, maxSize, srcWidth, destWidth, ret);
286 #endif
287 return ret;
288 }
289
DmacFillLli(struct DmaCntlr * cntlr,struct DmacChanInfo * chanInfo,uintptr_t srcaddr,uintptr_t dstaddr,size_t length)290 static int32_t DmacFillLli(struct DmaCntlr *cntlr, struct DmacChanInfo *chanInfo,
291 uintptr_t srcaddr, uintptr_t dstaddr, size_t length)
292 {
293 int32_t ret = HDF_SUCCESS;
294 uint16_t i;
295 uint16_t lliNum;
296 struct DmacLli *plli = NULL;
297 size_t alignedMax;
298 uintptr_t srcDummy = 0;
299 uintptr_t dstDummy = 0;
300
301 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
302 return HDF_ERR_INVALID_OBJECT;
303 }
304 if (chanInfo == NULL || chanInfo->lli == NULL) {
305 HDF_LOGE("%s: chanInfo or lli is null", __func__);
306 return HDF_ERR_INVALID_PARAM;
307 }
308 alignedMax = DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth);
309 if (alignedMax == 0) {
310 HDF_LOGE("%s: maxTransSize:%zu srcWidth:%u dstWidth:%u", __func__,
311 cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth);
312 return HDF_ERR_INVALID_PARAM;
313 }
314 plli = chanInfo->lli;
315
316 if (srcaddr == 0) {
317 srcaddr = srcDummy = DmacGetDummyBuf(cntlr, chanInfo);
318 }
319 if (dstaddr == 0) {
320 dstaddr = dstDummy = DmacGetDummyBuf(cntlr, chanInfo);
321 }
322 if (srcaddr == 0 || dstaddr == 0) {
323 return HDF_ERR_MALLOC_FAIL;
324 }
325
326 for (i = 0, lliNum = chanInfo->lliCnt; i < lliNum; i++, plli++) {
327 plli->nextLli = (uintptr_t)cntlr->dmacVaddrToPaddr((void *)plli) + (uintptr_t)sizeof(struct DmacLli);
328 plli->nextLli = (i < lliNum - 1) ? (plli->nextLli + chanInfo->lliEnFlag) : 0;
329 plli->count = ((i < lliNum - 1) || ((length % alignedMax) == 0)) ? alignedMax : (length % alignedMax);
330
331 plli->srcAddr = srcaddr;
332 plli->destAddr = dstaddr;
333 plli->config = chanInfo->config;
334
335 #ifdef DMA_CORE_DEBUG
336 HDF_LOGD("plli=0x%lx, next=0x%lx, count=0x%lx, src=0x%lx, dst=0x%lx, cfg=0x%lx",
337 (uintptr_t)cntlr->dmacVaddrToPaddr(plli), plli->nextLli,
338 plli->count, plli->srcAddr, plli->destAddr, plli->config);
339 #endif
340 dstaddr += (chanInfo->transType == TRASFER_TYPE_P2M && dstDummy == 0) ? plli->count : 0;
341 srcaddr += (chanInfo->transType == TRASFER_TYPE_M2P && srcDummy == 0) ? plli->count : 0;
342 }
343 plli = chanInfo->lli;
344 cntlr->dmacCacheFlush((uintptr_t)plli, (uintptr_t)plli + (uintptr_t)(sizeof(struct DmacLli) * lliNum));
345 return ret;
346 }
347
DmacAllocLli(struct DmacChanInfo * chanInfo,size_t length,size_t maxSize)348 static int32_t DmacAllocLli(struct DmacChanInfo *chanInfo, size_t length, size_t maxSize)
349 {
350 size_t lliNum;
351 size_t allocLength;
352 void *allocAddr = NULL;
353
354 if (chanInfo == NULL || maxSize == 0) {
355 return HDF_ERR_INVALID_PARAM;
356 }
357 lliNum = (length / maxSize) + ((length % maxSize) > 0 ? 1 : 0);
358 if (lliNum > 2048) { /* 2048: lliNum is not more than 2048 */
359 HDF_LOGE("%s: lliNum %zu is bigger than 2048", __func__, lliNum);
360 return HDF_ERR_INVALID_PARAM;
361 }
362
363 allocLength = lliNum * sizeof(struct DmacLli);
364 allocLength = ALIGN(allocLength, CACHE_ALIGNED_SIZE);
365 allocAddr = OsalMemAllocAlign(DMA_ALIGN_SIZE, allocLength);
366 if (allocAddr == NULL) {
367 HDF_LOGE("%s: alloc lli mem failed", __func__);
368 return HDF_FAILURE;
369 }
370 if (memset_s(allocAddr, allocLength, 0, allocLength) != EOK) {
371 OsalMemFree(allocAddr);
372 return HDF_FAILURE;
373 }
374
375 chanInfo->lliCnt = (uint16_t)lliNum;
376 chanInfo->lli = (struct DmacLli *)allocAddr;
377 return HDF_SUCCESS;
378 }
379
DmacPeriphTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)380 static int32_t DmacPeriphTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
381 {
382 int32_t ret;
383 struct DmacChanInfo *chanInfo = NULL;
384
385 chanInfo = DmacRequestChannel(cntlr, msg);
386 if (chanInfo == NULL) {
387 HDF_LOGE("%s: request channel failed", __func__);
388 return HDF_ERR_INVALID_PARAM;
389 }
390 if (msg->srcAddr == 0 && msg->destAddr == 0) {
391 HDF_LOGE("%s: src addr & dest addr both null", __func__);
392 return HDF_ERR_INVALID_PARAM;
393 }
394 chanInfo->callbackData = msg->para;
395 chanInfo->callback = (DmacCallback *)msg->cb;
396 ret = DmacAllocLli(chanInfo, msg->transLen,
397 DmacAlignedTransMax(cntlr->maxTransSize, chanInfo->srcWidth, chanInfo->destWidth));
398 if (ret != HDF_SUCCESS) {
399 DmacFreeChannel(cntlr, chanInfo->channel);
400 return ret;
401 }
402 ret = DmacFillLli(cntlr, chanInfo, msg->srcAddr, msg->destAddr, msg->transLen);
403 if (ret != HDF_SUCCESS) {
404 DmacFreeLli(chanInfo);
405 DmacFreeChannel(cntlr, chanInfo->channel);
406 return ret;
407 }
408 ret = cntlr->dmaChanEnable(cntlr, chanInfo);
409 if (ret != HDF_SUCCESS) {
410 HDF_LOGE("%s: enable channel failed", __func__);
411 DmacFreeLli(chanInfo);
412 DmacFreeChannel(cntlr, chanInfo->channel);
413 return HDF_FAILURE;
414 }
415 return HDF_SUCCESS;
416 }
417
DmacM2mTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)418 static int32_t DmacM2mTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
419 {
420 int32_t ret;
421 size_t leftSize;
422 size_t dmaSize;
423 size_t dmaCount = 0;
424 struct DmacChanInfo *chanInfo = NULL;
425
426 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
427 return HDF_ERR_INVALID_OBJECT;
428 }
429
430 chanInfo = DmacRequestChannel(cntlr, msg);
431 if (chanInfo == NULL) {
432 HDF_LOGE("%s: request channel failed", __func__);
433 return HDF_FAILURE;
434 }
435 chanInfo->callback = msg->cb;
436 chanInfo->callbackData = msg->para;
437 cntlr->dmacCacheFlush((uintptr_t)msg->srcAddr, (uintptr_t)(msg->srcAddr + msg->transLen));
438 cntlr->dmacCacheInv((uintptr_t)msg->destAddr, (uintptr_t)(msg->destAddr + msg->transLen));
439 leftSize = msg->transLen;
440 while (leftSize > 0) {
441 dmaSize = (leftSize >= cntlr->maxTransSize) ? cntlr->maxTransSize : leftSize;
442 ret = cntlr->dmaM2mChanEnable(cntlr, chanInfo, msg->srcAddr + dmaCount * cntlr->maxTransSize,
443 msg->destAddr + dmaCount * cntlr->maxTransSize, dmaSize);
444 if (ret != HDF_SUCCESS) {
445 HDF_LOGE("%s: enable channel m2m failed", __func__);
446 DmacFreeChannel(cntlr, chanInfo->channel);
447 if (chanInfo->callback != NULL) {
448 chanInfo->callback(chanInfo->callbackData, DMAC_CHN_ERROR);
449 }
450 return ret;
451 }
452 ret = DmacWaitM2mSendComplete(cntlr, chanInfo);
453 if (ret != DMAC_CHN_SUCCESS) {
454 HDF_LOGE("%s: m2m transfer failed, ret = %d", __func__, ret);
455 DmacFreeChannel(cntlr, chanInfo->channel);
456 if (chanInfo->callback != NULL) {
457 chanInfo->callback(chanInfo->callbackData, ret);
458 }
459 return HDF_FAILURE;
460 }
461 leftSize -= dmaSize;
462 dmaCount++;
463 }
464 DmacFreeChannel(cntlr, chanInfo->channel);
465 if (chanInfo->callback != NULL) {
466 chanInfo->callback(chanInfo->callbackData, DMAC_CHN_SUCCESS);
467 }
468 return HDF_SUCCESS;
469 }
470
DmaCntlrTransfer(struct DmaCntlr * cntlr,struct DmacMsg * msg)471 int32_t DmaCntlrTransfer(struct DmaCntlr *cntlr, struct DmacMsg *msg)
472 {
473 uintptr_t phyAddr;
474
475 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
476 return HDF_ERR_INVALID_OBJECT;
477 }
478 if (msg == NULL) {
479 return HDF_ERR_INVALID_PARAM;
480 }
481 if (msg->transType == TRASFER_TYPE_P2M) {
482 if (msg->destAddr != 0) {
483 phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->destAddr);
484 cntlr->dmacCacheInv(phyAddr, (uintptr_t)(phyAddr + msg->transLen));
485 }
486 } else if (msg->transType == TRASFER_TYPE_M2P) {
487 if (msg->srcAddr != 0) {
488 phyAddr = (uintptr_t)cntlr->dmacPaddrToVaddr((paddr_t)msg->srcAddr);
489 cntlr->dmacCacheFlush(phyAddr, (uintptr_t)(phyAddr + msg->transLen));
490 }
491 } else if (msg->transType == TRASFER_TYPE_M2M) {
492 return DmacM2mTransfer(cntlr, msg);
493 } else {
494 HDF_LOGE("%s: invalid transType %d", __func__, msg->transType);
495 return HDF_FAILURE;
496 }
497 return DmacPeriphTransfer(cntlr, msg);
498 }
499
DmaGetCurrChanDestAddr(struct DmaCntlr * cntlr,uint16_t chan)500 uintptr_t DmaGetCurrChanDestAddr(struct DmaCntlr *cntlr, uint16_t chan)
501 {
502 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
503 return HDF_ERR_INVALID_OBJECT;
504 }
505 return cntlr->dmacGetCurrDestAddr(cntlr, chan);
506 }
507
DmacIsr(uint32_t irq,void * dev)508 static uint32_t DmacIsr(uint32_t irq, void *dev)
509 {
510 uint16_t i;
511 int channelStatus;
512 struct DmaCntlr *cntlr = (struct DmaCntlr *)dev;
513
514 if (DmacCntlrCheck(cntlr) != HDF_SUCCESS) {
515 return HDF_ERR_INVALID_OBJECT;
516 }
517
518 if (irq != cntlr->irq || cntlr->channelNum > DMAC_CHAN_NUM_MAX) {
519 HDF_LOGE("%s: cntlr parm err! irq:%d, channel:%u", __func__, cntlr->irq, cntlr->channelNum);
520 return HDF_ERR_INVALID_OBJECT;
521 }
522 for (i = 0; i < cntlr->channelNum; i++) {
523 channelStatus = cntlr->dmacGetChanStatus(cntlr, i);
524 if (channelStatus == DMAC_CHN_SUCCESS || channelStatus == DMAC_CHN_ERROR) {
525 cntlr->channelList[i].status = channelStatus;
526 DmacCallbackHandle(&(cntlr->channelList[i]));
527 DmacFreeChannel(cntlr, cntlr->channelList[i].channel);
528 }
529 }
530 return HDF_SUCCESS;
531 }
532
DmacCntlrAdd(struct DmaCntlr * cntlr)533 int32_t DmacCntlrAdd(struct DmaCntlr *cntlr)
534 {
535 int32_t ret;
536 uint16_t i;
537
538 ret = DmacCntlrCheckInit(cntlr);
539 if (ret != HDF_SUCCESS) {
540 return ret;
541 }
542
543 (void)OsalSpinInit(&cntlr->lock);
544 ret = OsalRegisterIrq(cntlr->irq, 0, (OsalIRQHandle)DmacIsr, "PlatDmac", cntlr);
545 if (ret != HDF_SUCCESS) {
546 HDF_LOGE("%s: request irq %u failed, ret = %d", __func__, cntlr->irq, ret);
547 (void)OsalSpinDestroy(&cntlr->lock);
548 return ret;
549 }
550 cntlr->channelList = (struct DmacChanInfo *)OsalMemCalloc(sizeof(struct DmacChanInfo) * cntlr->channelNum);
551 if (cntlr->channelList == NULL) {
552 HDF_LOGE("%s: alloc channel list failed", __func__);
553 (void)OsalUnregisterIrq(cntlr->irq, cntlr);
554 (void)OsalSpinDestroy(&cntlr->lock);
555 return HDF_ERR_MALLOC_FAIL;
556 }
557 for (i = 0; i < cntlr->channelNum; i++) {
558 cntlr->dmacChanDisable(cntlr, i);
559 DmaEventInit(&(cntlr->channelList[i].waitEvent));
560 cntlr->channelList[i].useStatus = DMAC_CHN_VACANCY;
561 }
562 return HDF_SUCCESS;
563 }
564
DmacCntlrRemove(struct DmaCntlr * cntlr)565 void DmacCntlrRemove(struct DmaCntlr *cntlr)
566 {
567 (void)cntlr;
568 }
569