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
57static uint32_t __poll_portal_slow(t_BmPortal *p);
58static void __poll_portal_fast(t_BmPortal *p);
59
60/* Portal interrupt handler */
61static 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
91static 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;
171fail_rcr_empty:
172    bm_mc_finish(p_BmPortal->p_BmPortalLow);
173fail_mc:
174    bm_rcr_finish(p_BmPortal->p_BmPortalLow);
175fail_rcr:
176    XX_Free(p_BmPortal);
177    return ERROR_CODE(E_INVALID_STATE);
178}
179
180static 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
197static 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
258static 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
266static __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. */
274static 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
289static __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 */
308static 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
326static __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
368t_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
404uint8_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
433t_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
456t_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
503t_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
539t_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
551t_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