xref: /freebsd/sys/contrib/ncsw/Peripherals/BM/bm_portal.c (revision 3fc36ee018bb836bd1796067cf4ef8683f166ebc)
1 /******************************************************************************
2 
3  � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4  All rights reserved.
5 
6  This is proprietary source code of Freescale Semiconductor Inc.,
7  and its use is subject to the NetComm Device Drivers EULA.
8  The copyright notice above does not evidence any actual or intended
9  publication of such source code.
10 
11  ALTERNATIVELY, redistribution and use in source and binary forms, with
12  or without modification, are permitted provided that the following
13  conditions are met:
14      * Redistributions of source code must retain the above copyright
15        notice, this list of conditions and the following disclaimer.
16      * Redistributions in binary form must reproduce the above copyright
17        notice, this list of conditions and the following disclaimer in the
18        documentation and/or other materials provided with the distribution.
19      * Neither the name of Freescale Semiconductor nor the
20        names of its contributors may be used to endorse or promote products
21        derived from this software without specific prior written permission.
22 
23  THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 
35  **************************************************************************/
36 /******************************************************************************
37  @File          bm.c
38 
39  @Description   BM
40 *//***************************************************************************/
41 #include "error_ext.h"
42 #include "std_ext.h"
43 #include "string_ext.h"
44 #include "mem_ext.h"
45 #include "core_ext.h"
46 
47 #include "bm.h"
48 
49 
50 #define __ERR_MODULE__  MODULE_BM
51 
52 
53 /****************************************/
54 /*       static functions               */
55 /****************************************/
56 
57 static uint32_t __poll_portal_slow(t_BmPortal *p);
58 static void __poll_portal_fast(t_BmPortal *p);
59 
60 /* Portal interrupt handler */
61 static void portal_isr(void *ptr)
62 {
63     t_BmPortal *portal = ptr;
64         /* Only do fast-path handling if it's required */
65     if (portal->flags & BMAN_PORTAL_FLAG_IRQ_FAST)
66         __poll_portal_fast(portal);
67     __poll_portal_slow(portal);
68 
69 }
70 
71 /**
72  * bman_create_portal - Manage a Bman s/w portal
73  * @portal: the s/w corenet portal to use
74  * @flags: bit-mask of BMAN_PORTAL_FLAG_*** options
75  * @pools: bit-array of buffer pools available to this portal
76  * @portal_ctx: opaque user-supplied data to be associated with the portal
77  *
78  * Creates a managed portal object. @irq is only used if @flags specifies
79  * BMAN_PORTAL_FLAG_IRQ. @pools is copied, so the caller can do as they please
80  * with it after the function returns. It will only be possible to configure
81  * buffer pool objects as "suppliers" if they are specified in @pools, and the
82  * driver will only track depletion state changes to the same subset of buffer
83  * pools. If @pools is NULL, buffer pool depletion state will not be tracked.
84  * If the BMAN_PORTAL_FLAG_RECOVER flag is specified, then the function will
85  * attempt to expire any existing RCR entries, otherwise the function will fail
86  * if RCR is non-empty. If the BMAN_PORTAL_FLAG_WAIT flag is set, the function
87  * is allowed to block waiting for expiration of RCR. BMAN_PORTAL_FLAG_WAIT_INT
88  * makes any blocking interruptible.
89  */
90 
91 static t_Error bman_create_portal(t_BmPortal *p_BmPortal,
92                                   uint32_t flags,
93                                   const struct bman_depletion *pools)
94 {
95     int                             ret = 0;
96     uint8_t                         bpid = 0;
97     e_BmPortalRcrConsumeMode        rcr_cmode;
98     e_BmPortalProduceMode           pmode;
99 
100     pmode     = e_BmPortalPVB;
101     rcr_cmode = (flags & BMAN_PORTAL_FLAG_CACHE) ? e_BmPortalRcrCCE : e_BmPortalRcrCCI;
102 
103     switch (pmode)
104     {
105         case e_BmPortalPCI:
106             p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pci_commit;
107             break;
108         case e_BmPortalPCE:
109             p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pce_commit;
110             break;
111         case e_BmPortalPVB:
112             p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pvb_commit;
113             break;
114     }
115     switch (rcr_cmode)
116     {
117         case e_BmPortalRcrCCI:
118             p_BmPortal->cbs[BM_RCR_RING].f_BmUpdateCb      = bm_rcr_cci_update;
119             p_BmPortal->cbs[BM_RCR_RING].f_BmPrefetchCb    = NULL;
120             break;
121         case e_BmPortalRcrCCE:
122             p_BmPortal->cbs[BM_RCR_RING].f_BmUpdateCb      = bm_rcr_cce_update;
123             p_BmPortal->cbs[BM_RCR_RING].f_BmPrefetchCb    = bm_rcr_cce_prefetch;
124             break;
125     }
126 
127     if (bm_rcr_init(p_BmPortal->p_BmPortalLow, pmode, rcr_cmode)) {
128         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("RCR initialization failed"));
129         goto fail_rcr;
130     }
131     if (bm_mc_init(p_BmPortal->p_BmPortalLow)) {
132         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed"));
133         goto fail_mc;
134     }
135     p_BmPortal->pools[0] = *pools;
136     bman_depletion_init(&p_BmPortal->pools[1]);
137     while (bpid < BM_MAX_NUM_OF_POOLS) {
138         /* Default to all BPIDs disabled, we enable as required
139          * at run-time. */
140         bm_isr_bscn_mask(p_BmPortal->p_BmPortalLow, bpid, 0);
141         bpid++;
142     }
143     p_BmPortal->flags = flags;
144     p_BmPortal->slowpoll = 0;
145     p_BmPortal->rcrProd = p_BmPortal->rcrCons = 0;
146     memset(&p_BmPortal->depletionPoolsTable, 0, sizeof(p_BmPortal->depletionPoolsTable));
147     /* Write-to-clear any stale interrupt status bits */
148     bm_isr_disable_write(p_BmPortal->p_BmPortalLow, 0xffffffff);
149     bm_isr_status_clear(p_BmPortal->p_BmPortalLow, 0xffffffff);
150     bm_isr_enable_write(p_BmPortal->p_BmPortalLow, BM_PIRQ_RCRI | BM_PIRQ_BSCN);
151     if (flags & BMAN_PORTAL_FLAG_IRQ)
152     {
153         XX_SetIntr(p_BmPortal->irq, portal_isr, p_BmPortal);
154         XX_EnableIntr(p_BmPortal->irq);
155         /* Enable the bits that make sense */
156         bm_isr_uninhibit(p_BmPortal->p_BmPortalLow);
157     } else
158         /* without IRQ, we can't block */
159         flags &= ~BMAN_PORTAL_FLAG_WAIT;
160     /* Need RCR to be empty before continuing */
161     bm_isr_disable_write(p_BmPortal->p_BmPortalLow, (uint32_t)~BM_PIRQ_RCRI);
162     if (!(flags & BMAN_PORTAL_FLAG_RECOVER) ||
163         !(flags & BMAN_PORTAL_FLAG_WAIT))
164         ret = bm_rcr_get_fill(p_BmPortal->p_BmPortalLow);
165     if (ret) {
166         REPORT_ERROR(MAJOR, E_INVALID_STATE, ("RCR unclean, need recovery"));
167         goto fail_rcr_empty;
168     }
169     bm_isr_disable_write(p_BmPortal->p_BmPortalLow, 0);
170     return E_OK;
171 fail_rcr_empty:
172     bm_mc_finish(p_BmPortal->p_BmPortalLow);
173 fail_mc:
174     bm_rcr_finish(p_BmPortal->p_BmPortalLow);
175 fail_rcr:
176     XX_Free(p_BmPortal);
177     return ERROR_CODE(E_INVALID_STATE);
178 }
179 
180 static void bman_destroy_portal(t_BmPortal* p_BmPortal)
181 {
182     BmUpdate(p_BmPortal, BM_RCR_RING);
183     if (p_BmPortal->flags & BMAN_PORTAL_FLAG_IRQ)
184     {
185         XX_DisableIntr(p_BmPortal->irq);
186         XX_FreeIntr(p_BmPortal->irq);
187     }
188     bm_mc_finish(p_BmPortal->p_BmPortalLow);
189     bm_rcr_finish(p_BmPortal->p_BmPortalLow);
190     XX_Free(p_BmPortal->p_BmPortalLow);
191 }
192 
193 /* When release logic waits on available RCR space, we need a global waitqueue
194  * in the case of "affine" use (as the waits wake on different cpus which means
195  * different portals - so we can't wait on any per-portal waitqueue). */
196 
197 static uint32_t __poll_portal_slow(t_BmPortal* p_BmPortal)
198 {
199     struct bman_depletion tmp;
200     t_BmPool              *p_BmPool;
201     uint32_t ret,is = bm_isr_status_read(p_BmPortal->p_BmPortalLow);
202     ret = is;
203 
204     /* There is a gotcha to be aware of. If we do the query before clearing
205      * the status register, we may miss state changes that occur between the
206      * two. If we write to clear the status register before the query, the
207      * cache-enabled query command may overtake the status register write
208      * unless we use a heavyweight sync (which we don't want). Instead, we
209      * write-to-clear the status register then *read it back* before doing
210      * the query, hence the odd while loop with the 'is' accumulation. */
211     if (is & BM_PIRQ_BSCN) {
212         uint32_t i, j;
213         uint32_t __is;
214         bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_BSCN);
215         while ((__is = bm_isr_status_read(p_BmPortal->p_BmPortalLow)) & BM_PIRQ_BSCN) {
216             is |= __is;
217             bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_BSCN);
218         }
219         is &= ~BM_PIRQ_BSCN;
220         BmPortalQuery(p_BmPortal, &tmp, TRUE);
221         for (i = 0; i < 2; i++) {
222             uint32_t idx = i * 32;
223             /* tmp is a mask of currently-depleted pools.
224              * pools[0] is mask of those we care about.
225              * pools[1] is our previous view (we only want to
226              * be told about changes). */
227             tmp.__state[i] &= p_BmPortal->pools[0].__state[i];
228             if (tmp.__state[i] == p_BmPortal->pools[1].__state[i])
229                 /* fast-path, nothing to see, move along */
230                 continue;
231             for (j = 0; j <= 31; j++, idx++) {
232                 int b4 = bman_depletion_get(&p_BmPortal->pools[1], (uint8_t)idx);
233                 int af = bman_depletion_get(&tmp, (uint8_t)idx);
234                 if (b4 == af)
235                     continue;
236                 p_BmPool = p_BmPortal->depletionPoolsTable[idx];
237                 ASSERT_COND(p_BmPool->f_Depletion);
238                 p_BmPool->f_Depletion(p_BmPool->h_App, (bool)af);
239             }
240         }
241         p_BmPortal->pools[1] = tmp;
242     }
243 
244     if (is & BM_PIRQ_RCRI) {
245         NCSW_PLOCK(p_BmPortal);
246         p_BmPortal->rcrCons += BmUpdate(p_BmPortal, BM_RCR_RING);
247         bm_rcr_set_ithresh(p_BmPortal->p_BmPortalLow, 0);
248         PUNLOCK(p_BmPortal);
249         bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_RCRI);
250         is &= ~BM_PIRQ_RCRI;
251     }
252 
253     /* There should be no status register bits left undefined */
254     ASSERT_COND(!is);
255     return ret;
256 }
257 
258 static void __poll_portal_fast(t_BmPortal* p_BmPortal)
259 {
260     UNUSED(p_BmPortal);
261     /* nothing yet, this is where we'll put optimised RCR consumption
262      * tracking */
263 }
264 
265 
266 static __inline__ void rel_set_thresh(t_BmPortal *p_BmPortal, int check)
267 {
268     if (!check || !bm_rcr_get_ithresh(p_BmPortal->p_BmPortalLow))
269         bm_rcr_set_ithresh(p_BmPortal->p_BmPortalLow, RCR_ITHRESH);
270 }
271 
272 /* Used as a wait_event() expression. If it returns non-NULL, any lock will
273  * remain held. */
274 static struct bm_rcr_entry *try_rel_start(t_BmPortal *p_BmPortal)
275 {
276     struct bm_rcr_entry *r;
277 
278     NCSW_PLOCK(p_BmPortal);
279     if (bm_rcr_get_avail((p_BmPortal)->p_BmPortalLow) < RCR_THRESH)
280         BmUpdate(p_BmPortal, BM_RCR_RING);
281     r = bm_rcr_start((p_BmPortal)->p_BmPortalLow);
282     if (!r) {
283         rel_set_thresh(p_BmPortal, 1);
284         PUNLOCK(p_BmPortal);
285     }
286     return r;
287 }
288 
289 static __inline__ t_Error wait_rel_start(t_BmPortal             *p_BmPortal,
290                                          struct bm_rcr_entry    **rel,
291                                          uint32_t               flags)
292 {
293     int tries = 100;
294 
295     UNUSED(flags);
296     do {
297         *rel = try_rel_start(p_BmPortal);
298         XX_Sleep(1);
299     } while (!*rel && --tries);
300 
301     if (!(*rel))
302         return ERROR_CODE(E_BUSY);
303 
304     return E_OK;
305 }
306 
307 /* This copies Qman's eqcr_completed() routine, see that for details */
308 static int rel_completed(t_BmPortal *p_BmPortal, uint32_t rcr_poll)
309 {
310     uint32_t tr_cons = p_BmPortal->rcrCons;
311     if (rcr_poll & 0xc0000000) {
312         rcr_poll &= 0x7fffffff;
313         tr_cons ^= 0x80000000;
314     }
315     if (tr_cons >= rcr_poll)
316         return 1;
317     if ((rcr_poll - tr_cons) > BM_RCR_SIZE)
318         return 1;
319     if (!bm_rcr_get_fill(p_BmPortal->p_BmPortalLow))
320         /* If RCR is empty, we must have completed */
321         return 1;
322     rel_set_thresh(p_BmPortal, 0);
323     return 0;
324 }
325 
326 static __inline__ void rel_commit(t_BmPortal *p_BmPortal, uint32_t flags,uint8_t num)
327 {
328     uint32_t rcr_poll;
329 
330     BmCommit(p_BmPortal, BM_RCR_RING, (uint8_t)(BM_RCR_VERB_CMD_BPID_SINGLE | (num & BM_RCR_VERB_BUFCOUNT_MASK)));
331     /* increment the producer count and capture it for SYNC */
332     rcr_poll = ++p_BmPortal->rcrProd;
333     if ((flags & BMAN_RELEASE_FLAG_WAIT_SYNC) ==
334         BMAN_RELEASE_FLAG_WAIT_SYNC)
335         rel_set_thresh(p_BmPortal, 1);
336     PUNLOCK(p_BmPortal);
337     if ((flags & BMAN_RELEASE_FLAG_WAIT_SYNC) !=
338         BMAN_RELEASE_FLAG_WAIT_SYNC)
339         return;
340     rel_completed(p_BmPortal, rcr_poll);
341 }
342 
343 
344 /****************************************/
345 /*       Inter-Module functions        */
346 /****************************************/
347 
348 /**
349  * bman_release - Release buffer(s) to the buffer pool
350  * @p_BmPool: the buffer pool object to release to
351  * @bufs: an array of buffers to release
352  * @num: the number of buffers in @bufs (1-8)
353  * @flags: bit-mask of BMAN_RELEASE_FLAG_*** options
354  *
355  * Adds the given buffers to RCR entries. If the portal @p_BmPortal was created with the
356  * "COMPACT" flag, then it will be using a compaction algorithm to improve
357  * utilization of RCR. As such, these buffers may join an existing ring entry
358  * and/or it may not be issued right away so as to allow future releases to join
359  * the same ring entry. Use the BMAN_RELEASE_FLAG_NOW flag to override this
360  * behavior by committing the RCR entry (or entries) right away. If the RCR
361  * ring is full, the function will return -EBUSY unless BMAN_RELEASE_FLAG_WAIT
362  * is selected, in which case it will sleep waiting for space to become
363  * available in RCR. If the function receives a signal before such time (and
364  * BMAN_RELEASE_FLAG_WAIT_INT is set), the function returns -EINTR. Otherwise,
365  * it returns zero.
366  */
367 
368 t_Error BmPortalRelease(t_Handle h_BmPortal,
369                         uint8_t bpid,
370                         struct bm_buffer *bufs,
371                         uint8_t num,
372                         uint32_t flags)
373 {
374     t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
375     struct bm_rcr_entry *r;
376     uint8_t i;
377 
378     SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
379     /* TODO: I'm ignoring BMAN_PORTAL_FLAG_COMPACT for now. */
380     r = try_rel_start(p_BmPortal);
381     if (!r) {
382         if (flags & BMAN_RELEASE_FLAG_WAIT) {
383             t_Error ret = wait_rel_start(p_BmPortal, &r, flags);
384             if (ret)
385                 return ret;
386         } else
387             return ERROR_CODE(E_BUSY);
388         ASSERT_COND(r != NULL);
389     }
390     r->bpid = bpid;
391     for (i = 0; i < num; i++) {
392         r->bufs[i].hi = bufs[i].hi;
393         r->bufs[i].lo = bufs[i].lo;
394     }
395     /* Issue the release command and wait for sync if requested. NB: the
396      * commit can't fail, only waiting can. Don't propagate any failure if a
397      * signal arrives, otherwise the caller can't distinguish whether the
398      * release was issued or not. Code for user-space can check
399      * signal_pending() after we return. */
400     rel_commit(p_BmPortal, flags, num);
401     return E_OK;
402 }
403 
404 uint8_t BmPortalAcquire(t_Handle h_BmPortal,
405                         uint8_t  bpid,
406                         struct bm_buffer *bufs,
407                         uint8_t num)
408 {
409     t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
410     struct bm_mc_command *mcc;
411     struct bm_mc_result *mcr;
412     uint8_t ret = 0;
413 
414     SANITY_CHECK_RETURN_VALUE(p_BmPortal, E_INVALID_HANDLE, 0);
415     NCSW_PLOCK(p_BmPortal);
416     mcc = bm_mc_start(p_BmPortal->p_BmPortalLow);
417     mcc->acquire.bpid = bpid;
418     bm_mc_commit(p_BmPortal->p_BmPortalLow,
419                  (uint8_t)(BM_MCC_VERB_CMD_ACQUIRE |
420                            (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)));
421     while (!(mcr = bm_mc_result(p_BmPortal->p_BmPortalLow))) ;
422     ret = num = (uint8_t)(mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT);
423     ASSERT_COND(num <= 8);
424     while (num--) {
425         bufs[num].bpid = bpid;
426         bufs[num].hi = mcr->acquire.bufs[num].hi;
427         bufs[num].lo = mcr->acquire.bufs[num].lo;
428     }
429     PUNLOCK(p_BmPortal);
430     return ret;
431 }
432 
433 t_Error BmPortalQuery(t_Handle h_BmPortal, struct bman_depletion *p_Pools, bool depletion)
434 {
435     t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
436     struct bm_mc_result *mcr;
437 
438     SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
439 
440     NCSW_PLOCK(p_BmPortal);
441     bm_mc_start(p_BmPortal->p_BmPortalLow);
442     bm_mc_commit(p_BmPortal->p_BmPortalLow, BM_MCC_VERB_CMD_QUERY);
443     while (!(mcr = bm_mc_result(p_BmPortal->p_BmPortalLow))) ;
444     if (depletion)
445         *p_Pools = mcr->query.ds.state;
446     else
447         *p_Pools = mcr->query.as.state;
448     PUNLOCK(p_BmPortal);
449     return E_OK;
450 }
451 
452 /****************************************/
453 /*       API Init unit functions        */
454 /****************************************/
455 
456 t_Handle BM_PORTAL_Config(t_BmPortalParam *p_BmPortalParam)
457 {
458     t_BmPortal          *p_BmPortal;
459 
460     SANITY_CHECK_RETURN_VALUE(p_BmPortalParam, E_INVALID_HANDLE, NULL);
461     SANITY_CHECK_RETURN_VALUE(p_BmPortalParam->h_Bm, E_INVALID_HANDLE, NULL);
462 
463     p_BmPortal = (t_BmPortal *)XX_Malloc(sizeof(t_BmPortal));
464     if (!p_BmPortal)
465     {
466         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm Portal obj!!!"));
467         return NULL;
468     }
469     memset(p_BmPortal, 0, sizeof(t_BmPortal));
470 
471     p_BmPortal->p_BmPortalLow = (struct bm_portal *)XX_Malloc(sizeof(struct bm_portal));
472     if (!p_BmPortal->p_BmPortalLow)
473     {
474         XX_Free(p_BmPortal);
475         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low bm portal obj!!!"));
476         return NULL;
477     }
478     memset(p_BmPortal->p_BmPortalLow, 0, sizeof(struct bm_portal));
479 
480     p_BmPortal->p_BmPortalDriverParams = (t_BmPortalDriverParams *)XX_Malloc(sizeof(t_BmPortalDriverParams));
481     if (!p_BmPortal->p_BmPortalDriverParams)
482     {
483         XX_Free(p_BmPortal);
484         XX_Free(p_BmPortal->p_BmPortalLow);
485         REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm Portal driver parameters"));
486         return NULL;
487     }
488     memset(p_BmPortal->p_BmPortalDriverParams, 0, sizeof(t_BmPortalDriverParams));
489 
490     p_BmPortal->p_BmPortalLow->addr.addr_ce = UINT_TO_PTR(p_BmPortalParam->ceBaseAddress);
491     p_BmPortal->p_BmPortalLow->addr.addr_ci = UINT_TO_PTR(p_BmPortalParam->ciBaseAddress);
492     p_BmPortal->cpu   = (int)p_BmPortalParam->swPortalId;
493     p_BmPortal->irq   = p_BmPortalParam->irq;
494 
495     p_BmPortal->h_Bm    = p_BmPortalParam->h_Bm;
496 
497     p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr     = DEFAULT_memAttr;
498     bman_depletion_fill(&p_BmPortal->p_BmPortalDriverParams->mask);
499 
500     return p_BmPortal;
501 }
502 
503 t_Error BM_PORTAL_Init(t_Handle h_BmPortal)
504 {
505     t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
506     uint32_t            flags;
507 
508     SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
509 
510     flags = (uint32_t)((p_BmPortal->irq != NO_IRQ) ? BMAN_PORTAL_FLAG_IRQ : 0);
511     flags |= ((p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE) ?
512            BMAN_PORTAL_FLAG_CACHE : 0);
513 
514     if (bman_create_portal(p_BmPortal,flags,&p_BmPortal->p_BmPortalDriverParams->mask)!=E_OK)
515     {
516         BM_PORTAL_Free(p_BmPortal);
517         RETURN_ERROR(MAJOR, E_NULL_POINTER, ("create portal failed"));
518     }
519     BmSetPortalHandle(p_BmPortal->h_Bm, (t_Handle)p_BmPortal, (e_DpaaSwPortal)p_BmPortal->cpu);
520 
521     XX_Free(p_BmPortal->p_BmPortalDriverParams);
522     p_BmPortal->p_BmPortalDriverParams = NULL;
523 
524     DBG(TRACE,("Bman-Portal (%d) @ %p:%p\n",
525                p_BmPortal->cpu,
526                p_BmPortal->p_BmPortalLow->addr.addr_ce,
527                p_BmPortal->p_BmPortalLow->addr.addr_ci
528                ));
529 
530     DBG(TRACE,("Bman-Portal (%d) @ 0x%016llx:0x%016llx",
531                p_BmPortal->cpu,
532                (uint64_t)XX_VirtToPhys(p_BmPortal->p_BmPortalLow->addr.addr_ce),
533                (uint64_t)XX_VirtToPhys(p_BmPortal->p_BmPortalLow->addr.addr_ci)
534                ));
535 
536     return E_OK;
537 }
538 
539 t_Error BM_PORTAL_Free(t_Handle h_BmPortal)
540 {
541     t_BmPortal  *p_BmPortal = (t_BmPortal *)h_BmPortal;
542 
543     if (!p_BmPortal)
544        return ERROR_CODE(E_INVALID_HANDLE);
545     BmSetPortalHandle(p_BmPortal->h_Bm, NULL, (e_DpaaSwPortal)p_BmPortal->cpu);
546     bman_destroy_portal(p_BmPortal);
547     XX_Free(p_BmPortal);
548     return E_OK;
549 }
550 
551 t_Error BM_PORTAL_ConfigMemAttr(t_Handle h_BmPortal, uint32_t hwExtStructsMemAttr)
552 {
553     t_BmPortal  *p_BmPortal = (t_BmPortal *)h_BmPortal;
554 
555     SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
556     SANITY_CHECK_RETURN_ERROR(p_BmPortal->p_BmPortalDriverParams, E_INVALID_HANDLE);
557 
558     p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr = hwExtStructsMemAttr;
559 
560     return E_OK;
561 }
562