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