1296177Sjhibbits/******************************************************************************
2296177Sjhibbits
3296177Sjhibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc.
4296177Sjhibbits All rights reserved.
5296177Sjhibbits
6296177Sjhibbits This is proprietary source code of Freescale Semiconductor Inc.,
7296177Sjhibbits and its use is subject to the NetComm Device Drivers EULA.
8296177Sjhibbits The copyright notice above does not evidence any actual or intended
9296177Sjhibbits publication of such source code.
10296177Sjhibbits
11296177Sjhibbits ALTERNATIVELY, redistribution and use in source and binary forms, with
12296177Sjhibbits or without modification, are permitted provided that the following
13296177Sjhibbits conditions are met:
14296177Sjhibbits     * Redistributions of source code must retain the above copyright
15296177Sjhibbits       notice, this list of conditions and the following disclaimer.
16296177Sjhibbits     * Redistributions in binary form must reproduce the above copyright
17296177Sjhibbits       notice, this list of conditions and the following disclaimer in the
18296177Sjhibbits       documentation and/or other materials provided with the distribution.
19296177Sjhibbits     * Neither the name of Freescale Semiconductor nor the
20296177Sjhibbits       names of its contributors may be used to endorse or promote products
21296177Sjhibbits       derived from this software without specific prior written permission.
22296177Sjhibbits
23296177Sjhibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24296177Sjhibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25296177Sjhibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26296177Sjhibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27296177Sjhibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28296177Sjhibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29296177Sjhibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30296177Sjhibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31296177Sjhibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32296177Sjhibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33296177Sjhibbits *
34296177Sjhibbits
35296177Sjhibbits **************************************************************************/
36296177Sjhibbits/******************************************************************************
37296177Sjhibbits @File          bm.c
38296177Sjhibbits
39296177Sjhibbits @Description   BM
40296177Sjhibbits*//***************************************************************************/
41296177Sjhibbits#include "error_ext.h"
42296177Sjhibbits#include "std_ext.h"
43296177Sjhibbits#include "string_ext.h"
44296177Sjhibbits#include "mem_ext.h"
45296177Sjhibbits#include "core_ext.h"
46296177Sjhibbits
47296177Sjhibbits#include "bm.h"
48296177Sjhibbits
49296177Sjhibbits
50296177Sjhibbits#define __ERR_MODULE__  MODULE_BM
51296177Sjhibbits
52296177Sjhibbits
53296177Sjhibbits/****************************************/
54296177Sjhibbits/*       static functions               */
55296177Sjhibbits/****************************************/
56296177Sjhibbits
57296177Sjhibbitsstatic uint32_t __poll_portal_slow(t_BmPortal *p);
58296177Sjhibbitsstatic void __poll_portal_fast(t_BmPortal *p);
59296177Sjhibbits
60296177Sjhibbits/* Portal interrupt handler */
61296177Sjhibbitsstatic void portal_isr(void *ptr)
62296177Sjhibbits{
63296177Sjhibbits    t_BmPortal *portal = ptr;
64296177Sjhibbits        /* Only do fast-path handling if it's required */
65296177Sjhibbits    if (portal->flags & BMAN_PORTAL_FLAG_IRQ_FAST)
66296177Sjhibbits        __poll_portal_fast(portal);
67296177Sjhibbits    __poll_portal_slow(portal);
68296177Sjhibbits
69296177Sjhibbits}
70296177Sjhibbits
71296177Sjhibbits/**
72296177Sjhibbits * bman_create_portal - Manage a Bman s/w portal
73296177Sjhibbits * @portal: the s/w corenet portal to use
74296177Sjhibbits * @flags: bit-mask of BMAN_PORTAL_FLAG_*** options
75296177Sjhibbits * @pools: bit-array of buffer pools available to this portal
76296177Sjhibbits * @portal_ctx: opaque user-supplied data to be associated with the portal
77296177Sjhibbits *
78296177Sjhibbits * Creates a managed portal object. @irq is only used if @flags specifies
79296177Sjhibbits * BMAN_PORTAL_FLAG_IRQ. @pools is copied, so the caller can do as they please
80296177Sjhibbits * with it after the function returns. It will only be possible to configure
81296177Sjhibbits * buffer pool objects as "suppliers" if they are specified in @pools, and the
82296177Sjhibbits * driver will only track depletion state changes to the same subset of buffer
83296177Sjhibbits * pools. If @pools is NULL, buffer pool depletion state will not be tracked.
84296177Sjhibbits * If the BMAN_PORTAL_FLAG_RECOVER flag is specified, then the function will
85296177Sjhibbits * attempt to expire any existing RCR entries, otherwise the function will fail
86296177Sjhibbits * if RCR is non-empty. If the BMAN_PORTAL_FLAG_WAIT flag is set, the function
87296177Sjhibbits * is allowed to block waiting for expiration of RCR. BMAN_PORTAL_FLAG_WAIT_INT
88296177Sjhibbits * makes any blocking interruptible.
89296177Sjhibbits */
90296177Sjhibbits
91296177Sjhibbitsstatic t_Error bman_create_portal(t_BmPortal *p_BmPortal,
92296177Sjhibbits                                  uint32_t flags,
93296177Sjhibbits                                  const struct bman_depletion *pools)
94296177Sjhibbits{
95296177Sjhibbits    int                             ret = 0;
96296177Sjhibbits    uint8_t                         bpid = 0;
97296177Sjhibbits    e_BmPortalRcrConsumeMode        rcr_cmode;
98296177Sjhibbits    e_BmPortalProduceMode           pmode;
99296177Sjhibbits
100296177Sjhibbits    pmode     = e_BmPortalPVB;
101296177Sjhibbits    rcr_cmode = (flags & BMAN_PORTAL_FLAG_CACHE) ? e_BmPortalRcrCCE : e_BmPortalRcrCCI;
102296177Sjhibbits
103296177Sjhibbits    switch (pmode)
104296177Sjhibbits    {
105296177Sjhibbits        case e_BmPortalPCI:
106296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pci_commit;
107296177Sjhibbits            break;
108296177Sjhibbits        case e_BmPortalPCE:
109296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pce_commit;
110296177Sjhibbits            break;
111296177Sjhibbits        case e_BmPortalPVB:
112296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmCommitCb = bm_rcr_pvb_commit;
113296177Sjhibbits            break;
114296177Sjhibbits    }
115296177Sjhibbits    switch (rcr_cmode)
116296177Sjhibbits    {
117296177Sjhibbits        case e_BmPortalRcrCCI:
118296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmUpdateCb      = bm_rcr_cci_update;
119296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmPrefetchCb    = NULL;
120296177Sjhibbits            break;
121296177Sjhibbits        case e_BmPortalRcrCCE:
122296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmUpdateCb      = bm_rcr_cce_update;
123296177Sjhibbits            p_BmPortal->cbs[BM_RCR_RING].f_BmPrefetchCb    = bm_rcr_cce_prefetch;
124296177Sjhibbits            break;
125296177Sjhibbits    }
126296177Sjhibbits
127296177Sjhibbits    if (bm_rcr_init(p_BmPortal->p_BmPortalLow, pmode, rcr_cmode)) {
128296177Sjhibbits        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("RCR initialization failed"));
129296177Sjhibbits        goto fail_rcr;
130296177Sjhibbits    }
131296177Sjhibbits    if (bm_mc_init(p_BmPortal->p_BmPortalLow)) {
132296177Sjhibbits        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed"));
133296177Sjhibbits        goto fail_mc;
134296177Sjhibbits    }
135296177Sjhibbits    p_BmPortal->pools[0] = *pools;
136296177Sjhibbits    bman_depletion_init(&p_BmPortal->pools[1]);
137296177Sjhibbits    while (bpid < BM_MAX_NUM_OF_POOLS) {
138296177Sjhibbits        /* Default to all BPIDs disabled, we enable as required
139296177Sjhibbits         * at run-time. */
140296177Sjhibbits        bm_isr_bscn_mask(p_BmPortal->p_BmPortalLow, bpid, 0);
141296177Sjhibbits        bpid++;
142296177Sjhibbits    }
143296177Sjhibbits    p_BmPortal->flags = flags;
144296177Sjhibbits    p_BmPortal->slowpoll = 0;
145296177Sjhibbits    p_BmPortal->rcrProd = p_BmPortal->rcrCons = 0;
146296177Sjhibbits    memset(&p_BmPortal->depletionPoolsTable, 0, sizeof(p_BmPortal->depletionPoolsTable));
147296177Sjhibbits    /* Write-to-clear any stale interrupt status bits */
148296177Sjhibbits    bm_isr_disable_write(p_BmPortal->p_BmPortalLow, 0xffffffff);
149296177Sjhibbits    bm_isr_status_clear(p_BmPortal->p_BmPortalLow, 0xffffffff);
150296177Sjhibbits    bm_isr_enable_write(p_BmPortal->p_BmPortalLow, BM_PIRQ_RCRI | BM_PIRQ_BSCN);
151296177Sjhibbits    if (flags & BMAN_PORTAL_FLAG_IRQ)
152296177Sjhibbits    {
153296177Sjhibbits        XX_SetIntr(p_BmPortal->irq, portal_isr, p_BmPortal);
154296177Sjhibbits        XX_EnableIntr(p_BmPortal->irq);
155296177Sjhibbits        /* Enable the bits that make sense */
156296177Sjhibbits        bm_isr_uninhibit(p_BmPortal->p_BmPortalLow);
157296177Sjhibbits    } else
158296177Sjhibbits        /* without IRQ, we can't block */
159296177Sjhibbits        flags &= ~BMAN_PORTAL_FLAG_WAIT;
160296177Sjhibbits    /* Need RCR to be empty before continuing */
161296177Sjhibbits    bm_isr_disable_write(p_BmPortal->p_BmPortalLow, (uint32_t)~BM_PIRQ_RCRI);
162296177Sjhibbits    if (!(flags & BMAN_PORTAL_FLAG_RECOVER) ||
163296177Sjhibbits        !(flags & BMAN_PORTAL_FLAG_WAIT))
164296177Sjhibbits        ret = bm_rcr_get_fill(p_BmPortal->p_BmPortalLow);
165296177Sjhibbits    if (ret) {
166296177Sjhibbits        REPORT_ERROR(MAJOR, E_INVALID_STATE, ("RCR unclean, need recovery"));
167296177Sjhibbits        goto fail_rcr_empty;
168296177Sjhibbits    }
169296177Sjhibbits    bm_isr_disable_write(p_BmPortal->p_BmPortalLow, 0);
170296177Sjhibbits    return E_OK;
171296177Sjhibbitsfail_rcr_empty:
172296177Sjhibbits    bm_mc_finish(p_BmPortal->p_BmPortalLow);
173296177Sjhibbitsfail_mc:
174296177Sjhibbits    bm_rcr_finish(p_BmPortal->p_BmPortalLow);
175296177Sjhibbitsfail_rcr:
176296177Sjhibbits    XX_Free(p_BmPortal);
177296177Sjhibbits    return ERROR_CODE(E_INVALID_STATE);
178296177Sjhibbits}
179296177Sjhibbits
180296177Sjhibbitsstatic void bman_destroy_portal(t_BmPortal* p_BmPortal)
181296177Sjhibbits{
182296177Sjhibbits    BmUpdate(p_BmPortal, BM_RCR_RING);
183296177Sjhibbits    if (p_BmPortal->flags & BMAN_PORTAL_FLAG_IRQ)
184296177Sjhibbits    {
185296177Sjhibbits        XX_DisableIntr(p_BmPortal->irq);
186296177Sjhibbits        XX_FreeIntr(p_BmPortal->irq);
187296177Sjhibbits    }
188296177Sjhibbits    bm_mc_finish(p_BmPortal->p_BmPortalLow);
189296177Sjhibbits    bm_rcr_finish(p_BmPortal->p_BmPortalLow);
190296177Sjhibbits    XX_Free(p_BmPortal->p_BmPortalLow);
191296177Sjhibbits}
192296177Sjhibbits
193296177Sjhibbits/* When release logic waits on available RCR space, we need a global waitqueue
194296177Sjhibbits * in the case of "affine" use (as the waits wake on different cpus which means
195296177Sjhibbits * different portals - so we can't wait on any per-portal waitqueue). */
196296177Sjhibbits
197296177Sjhibbitsstatic uint32_t __poll_portal_slow(t_BmPortal* p_BmPortal)
198296177Sjhibbits{
199296177Sjhibbits    struct bman_depletion tmp;
200296177Sjhibbits    t_BmPool              *p_BmPool;
201296177Sjhibbits    uint32_t ret,is = bm_isr_status_read(p_BmPortal->p_BmPortalLow);
202296177Sjhibbits    ret = is;
203296177Sjhibbits
204296177Sjhibbits    /* There is a gotcha to be aware of. If we do the query before clearing
205296177Sjhibbits     * the status register, we may miss state changes that occur between the
206296177Sjhibbits     * two. If we write to clear the status register before the query, the
207296177Sjhibbits     * cache-enabled query command may overtake the status register write
208296177Sjhibbits     * unless we use a heavyweight sync (which we don't want). Instead, we
209296177Sjhibbits     * write-to-clear the status register then *read it back* before doing
210296177Sjhibbits     * the query, hence the odd while loop with the 'is' accumulation. */
211296177Sjhibbits    if (is & BM_PIRQ_BSCN) {
212296177Sjhibbits        uint32_t i, j;
213296177Sjhibbits        uint32_t __is;
214296177Sjhibbits        bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_BSCN);
215296177Sjhibbits        while ((__is = bm_isr_status_read(p_BmPortal->p_BmPortalLow)) & BM_PIRQ_BSCN) {
216296177Sjhibbits            is |= __is;
217296177Sjhibbits            bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_BSCN);
218296177Sjhibbits        }
219296177Sjhibbits        is &= ~BM_PIRQ_BSCN;
220296177Sjhibbits        BmPortalQuery(p_BmPortal, &tmp, TRUE);
221296177Sjhibbits        for (i = 0; i < 2; i++) {
222296177Sjhibbits            uint32_t idx = i * 32;
223296177Sjhibbits            /* tmp is a mask of currently-depleted pools.
224296177Sjhibbits             * pools[0] is mask of those we care about.
225296177Sjhibbits             * pools[1] is our previous view (we only want to
226296177Sjhibbits             * be told about changes). */
227296177Sjhibbits            tmp.__state[i] &= p_BmPortal->pools[0].__state[i];
228296177Sjhibbits            if (tmp.__state[i] == p_BmPortal->pools[1].__state[i])
229296177Sjhibbits                /* fast-path, nothing to see, move along */
230296177Sjhibbits                continue;
231296177Sjhibbits            for (j = 0; j <= 31; j++, idx++) {
232296177Sjhibbits                int b4 = bman_depletion_get(&p_BmPortal->pools[1], (uint8_t)idx);
233296177Sjhibbits                int af = bman_depletion_get(&tmp, (uint8_t)idx);
234296177Sjhibbits                if (b4 == af)
235296177Sjhibbits                    continue;
236296177Sjhibbits                p_BmPool = p_BmPortal->depletionPoolsTable[idx];
237296177Sjhibbits                ASSERT_COND(p_BmPool->f_Depletion);
238296177Sjhibbits                p_BmPool->f_Depletion(p_BmPool->h_App, (bool)af);
239296177Sjhibbits            }
240296177Sjhibbits        }
241296177Sjhibbits        p_BmPortal->pools[1] = tmp;
242296177Sjhibbits    }
243296177Sjhibbits
244296177Sjhibbits    if (is & BM_PIRQ_RCRI) {
245296177Sjhibbits        NCSW_PLOCK(p_BmPortal);
246296177Sjhibbits        p_BmPortal->rcrCons += BmUpdate(p_BmPortal, BM_RCR_RING);
247296177Sjhibbits        bm_rcr_set_ithresh(p_BmPortal->p_BmPortalLow, 0);
248296177Sjhibbits        PUNLOCK(p_BmPortal);
249296177Sjhibbits        bm_isr_status_clear(p_BmPortal->p_BmPortalLow, BM_PIRQ_RCRI);
250296177Sjhibbits        is &= ~BM_PIRQ_RCRI;
251296177Sjhibbits    }
252296177Sjhibbits
253296177Sjhibbits    /* There should be no status register bits left undefined */
254296177Sjhibbits    ASSERT_COND(!is);
255296177Sjhibbits    return ret;
256296177Sjhibbits}
257296177Sjhibbits
258296177Sjhibbitsstatic void __poll_portal_fast(t_BmPortal* p_BmPortal)
259296177Sjhibbits{
260296177Sjhibbits    UNUSED(p_BmPortal);
261296177Sjhibbits    /* nothing yet, this is where we'll put optimised RCR consumption
262296177Sjhibbits     * tracking */
263296177Sjhibbits}
264296177Sjhibbits
265296177Sjhibbits
266296177Sjhibbitsstatic __inline__ void rel_set_thresh(t_BmPortal *p_BmPortal, int check)
267296177Sjhibbits{
268296177Sjhibbits    if (!check || !bm_rcr_get_ithresh(p_BmPortal->p_BmPortalLow))
269296177Sjhibbits        bm_rcr_set_ithresh(p_BmPortal->p_BmPortalLow, RCR_ITHRESH);
270296177Sjhibbits}
271296177Sjhibbits
272296177Sjhibbits/* Used as a wait_event() expression. If it returns non-NULL, any lock will
273296177Sjhibbits * remain held. */
274296177Sjhibbitsstatic struct bm_rcr_entry *try_rel_start(t_BmPortal *p_BmPortal)
275296177Sjhibbits{
276296177Sjhibbits    struct bm_rcr_entry *r;
277296177Sjhibbits
278296177Sjhibbits    NCSW_PLOCK(p_BmPortal);
279296177Sjhibbits    if (bm_rcr_get_avail((p_BmPortal)->p_BmPortalLow) < RCR_THRESH)
280296177Sjhibbits        BmUpdate(p_BmPortal, BM_RCR_RING);
281296177Sjhibbits    r = bm_rcr_start((p_BmPortal)->p_BmPortalLow);
282296177Sjhibbits    if (!r) {
283296177Sjhibbits        rel_set_thresh(p_BmPortal, 1);
284296177Sjhibbits        PUNLOCK(p_BmPortal);
285296177Sjhibbits    }
286296177Sjhibbits    return r;
287296177Sjhibbits}
288296177Sjhibbits
289296177Sjhibbitsstatic __inline__ t_Error wait_rel_start(t_BmPortal             *p_BmPortal,
290296177Sjhibbits                                         struct bm_rcr_entry    **rel,
291296177Sjhibbits                                         uint32_t               flags)
292296177Sjhibbits{
293296177Sjhibbits    int tries = 100;
294296177Sjhibbits
295296177Sjhibbits    UNUSED(flags);
296296177Sjhibbits    do {
297296177Sjhibbits        *rel = try_rel_start(p_BmPortal);
298296177Sjhibbits        XX_Sleep(1);
299296177Sjhibbits    } while (!*rel && --tries);
300296177Sjhibbits
301296177Sjhibbits    if (!(*rel))
302296177Sjhibbits        return ERROR_CODE(E_BUSY);
303296177Sjhibbits
304296177Sjhibbits    return E_OK;
305296177Sjhibbits}
306296177Sjhibbits
307296177Sjhibbits/* This copies Qman's eqcr_completed() routine, see that for details */
308296177Sjhibbitsstatic int rel_completed(t_BmPortal *p_BmPortal, uint32_t rcr_poll)
309296177Sjhibbits{
310296177Sjhibbits    uint32_t tr_cons = p_BmPortal->rcrCons;
311296177Sjhibbits    if (rcr_poll & 0xc0000000) {
312296177Sjhibbits        rcr_poll &= 0x7fffffff;
313296177Sjhibbits        tr_cons ^= 0x80000000;
314296177Sjhibbits    }
315296177Sjhibbits    if (tr_cons >= rcr_poll)
316296177Sjhibbits        return 1;
317296177Sjhibbits    if ((rcr_poll - tr_cons) > BM_RCR_SIZE)
318296177Sjhibbits        return 1;
319296177Sjhibbits    if (!bm_rcr_get_fill(p_BmPortal->p_BmPortalLow))
320296177Sjhibbits        /* If RCR is empty, we must have completed */
321296177Sjhibbits        return 1;
322296177Sjhibbits    rel_set_thresh(p_BmPortal, 0);
323296177Sjhibbits    return 0;
324296177Sjhibbits}
325296177Sjhibbits
326296177Sjhibbitsstatic __inline__ void rel_commit(t_BmPortal *p_BmPortal, uint32_t flags,uint8_t num)
327296177Sjhibbits{
328296177Sjhibbits    uint32_t rcr_poll;
329296177Sjhibbits
330296177Sjhibbits    BmCommit(p_BmPortal, BM_RCR_RING, (uint8_t)(BM_RCR_VERB_CMD_BPID_SINGLE | (num & BM_RCR_VERB_BUFCOUNT_MASK)));
331296177Sjhibbits    /* increment the producer count and capture it for SYNC */
332296177Sjhibbits    rcr_poll = ++p_BmPortal->rcrProd;
333296177Sjhibbits    if ((flags & BMAN_RELEASE_FLAG_WAIT_SYNC) ==
334296177Sjhibbits        BMAN_RELEASE_FLAG_WAIT_SYNC)
335296177Sjhibbits        rel_set_thresh(p_BmPortal, 1);
336296177Sjhibbits    PUNLOCK(p_BmPortal);
337296177Sjhibbits    if ((flags & BMAN_RELEASE_FLAG_WAIT_SYNC) !=
338296177Sjhibbits        BMAN_RELEASE_FLAG_WAIT_SYNC)
339296177Sjhibbits        return;
340296177Sjhibbits    rel_completed(p_BmPortal, rcr_poll);
341296177Sjhibbits}
342296177Sjhibbits
343296177Sjhibbits
344296177Sjhibbits/****************************************/
345296177Sjhibbits/*       Inter-Module functions        */
346296177Sjhibbits/****************************************/
347296177Sjhibbits
348296177Sjhibbits/**
349296177Sjhibbits * bman_release - Release buffer(s) to the buffer pool
350296177Sjhibbits * @p_BmPool: the buffer pool object to release to
351296177Sjhibbits * @bufs: an array of buffers to release
352296177Sjhibbits * @num: the number of buffers in @bufs (1-8)
353296177Sjhibbits * @flags: bit-mask of BMAN_RELEASE_FLAG_*** options
354296177Sjhibbits *
355296177Sjhibbits * Adds the given buffers to RCR entries. If the portal @p_BmPortal was created with the
356296177Sjhibbits * "COMPACT" flag, then it will be using a compaction algorithm to improve
357296177Sjhibbits * utilization of RCR. As such, these buffers may join an existing ring entry
358296177Sjhibbits * and/or it may not be issued right away so as to allow future releases to join
359296177Sjhibbits * the same ring entry. Use the BMAN_RELEASE_FLAG_NOW flag to override this
360296177Sjhibbits * behavior by committing the RCR entry (or entries) right away. If the RCR
361296177Sjhibbits * ring is full, the function will return -EBUSY unless BMAN_RELEASE_FLAG_WAIT
362296177Sjhibbits * is selected, in which case it will sleep waiting for space to become
363296177Sjhibbits * available in RCR. If the function receives a signal before such time (and
364296177Sjhibbits * BMAN_RELEASE_FLAG_WAIT_INT is set), the function returns -EINTR. Otherwise,
365296177Sjhibbits * it returns zero.
366296177Sjhibbits */
367296177Sjhibbits
368296177Sjhibbitst_Error BmPortalRelease(t_Handle h_BmPortal,
369296177Sjhibbits                        uint8_t bpid,
370296177Sjhibbits                        struct bm_buffer *bufs,
371296177Sjhibbits                        uint8_t num,
372296177Sjhibbits                        uint32_t flags)
373296177Sjhibbits{
374296177Sjhibbits    t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
375296177Sjhibbits    struct bm_rcr_entry *r;
376296177Sjhibbits    uint8_t i;
377296177Sjhibbits
378296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
379296177Sjhibbits    /* TODO: I'm ignoring BMAN_PORTAL_FLAG_COMPACT for now. */
380296177Sjhibbits    r = try_rel_start(p_BmPortal);
381296177Sjhibbits    if (!r) {
382296177Sjhibbits        if (flags & BMAN_RELEASE_FLAG_WAIT) {
383296177Sjhibbits            t_Error ret = wait_rel_start(p_BmPortal, &r, flags);
384296177Sjhibbits            if (ret)
385296177Sjhibbits                return ret;
386296177Sjhibbits        } else
387296177Sjhibbits            return ERROR_CODE(E_BUSY);
388296177Sjhibbits        ASSERT_COND(r != NULL);
389296177Sjhibbits    }
390296177Sjhibbits    r->bpid = bpid;
391296177Sjhibbits    for (i = 0; i < num; i++) {
392296177Sjhibbits        r->bufs[i].hi = bufs[i].hi;
393296177Sjhibbits        r->bufs[i].lo = bufs[i].lo;
394296177Sjhibbits    }
395296177Sjhibbits    /* Issue the release command and wait for sync if requested. NB: the
396296177Sjhibbits     * commit can't fail, only waiting can. Don't propagate any failure if a
397296177Sjhibbits     * signal arrives, otherwise the caller can't distinguish whether the
398296177Sjhibbits     * release was issued or not. Code for user-space can check
399296177Sjhibbits     * signal_pending() after we return. */
400296177Sjhibbits    rel_commit(p_BmPortal, flags, num);
401296177Sjhibbits    return E_OK;
402296177Sjhibbits}
403296177Sjhibbits
404296177Sjhibbitsuint8_t BmPortalAcquire(t_Handle h_BmPortal,
405296177Sjhibbits                        uint8_t  bpid,
406296177Sjhibbits                        struct bm_buffer *bufs,
407296177Sjhibbits                        uint8_t num)
408296177Sjhibbits{
409296177Sjhibbits    t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
410296177Sjhibbits    struct bm_mc_command *mcc;
411296177Sjhibbits    struct bm_mc_result *mcr;
412296177Sjhibbits    uint8_t ret = 0;
413296177Sjhibbits
414296177Sjhibbits    SANITY_CHECK_RETURN_VALUE(p_BmPortal, E_INVALID_HANDLE, 0);
415296177Sjhibbits    NCSW_PLOCK(p_BmPortal);
416296177Sjhibbits    mcc = bm_mc_start(p_BmPortal->p_BmPortalLow);
417296177Sjhibbits    mcc->acquire.bpid = bpid;
418296177Sjhibbits    bm_mc_commit(p_BmPortal->p_BmPortalLow,
419296177Sjhibbits                 (uint8_t)(BM_MCC_VERB_CMD_ACQUIRE |
420296177Sjhibbits                           (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)));
421296177Sjhibbits    while (!(mcr = bm_mc_result(p_BmPortal->p_BmPortalLow))) ;
422296177Sjhibbits    ret = num = (uint8_t)(mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT);
423296177Sjhibbits    ASSERT_COND(num <= 8);
424296177Sjhibbits    while (num--) {
425296177Sjhibbits        bufs[num].bpid = bpid;
426296177Sjhibbits        bufs[num].hi = mcr->acquire.bufs[num].hi;
427296177Sjhibbits        bufs[num].lo = mcr->acquire.bufs[num].lo;
428296177Sjhibbits    }
429296177Sjhibbits    PUNLOCK(p_BmPortal);
430296177Sjhibbits    return ret;
431296177Sjhibbits}
432296177Sjhibbits
433296177Sjhibbitst_Error BmPortalQuery(t_Handle h_BmPortal, struct bman_depletion *p_Pools, bool depletion)
434296177Sjhibbits{
435296177Sjhibbits    t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
436296177Sjhibbits    struct bm_mc_result *mcr;
437296177Sjhibbits
438296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
439296177Sjhibbits
440296177Sjhibbits    NCSW_PLOCK(p_BmPortal);
441296177Sjhibbits    bm_mc_start(p_BmPortal->p_BmPortalLow);
442296177Sjhibbits    bm_mc_commit(p_BmPortal->p_BmPortalLow, BM_MCC_VERB_CMD_QUERY);
443296177Sjhibbits    while (!(mcr = bm_mc_result(p_BmPortal->p_BmPortalLow))) ;
444296177Sjhibbits    if (depletion)
445296177Sjhibbits        *p_Pools = mcr->query.ds.state;
446296177Sjhibbits    else
447296177Sjhibbits        *p_Pools = mcr->query.as.state;
448296177Sjhibbits    PUNLOCK(p_BmPortal);
449296177Sjhibbits    return E_OK;
450296177Sjhibbits}
451296177Sjhibbits
452296177Sjhibbits/****************************************/
453296177Sjhibbits/*       API Init unit functions        */
454296177Sjhibbits/****************************************/
455296177Sjhibbits
456296177Sjhibbitst_Handle BM_PORTAL_Config(t_BmPortalParam *p_BmPortalParam)
457296177Sjhibbits{
458296177Sjhibbits    t_BmPortal          *p_BmPortal;
459296177Sjhibbits
460296177Sjhibbits    SANITY_CHECK_RETURN_VALUE(p_BmPortalParam, E_INVALID_HANDLE, NULL);
461296177Sjhibbits    SANITY_CHECK_RETURN_VALUE(p_BmPortalParam->h_Bm, E_INVALID_HANDLE, NULL);
462296177Sjhibbits
463296177Sjhibbits    p_BmPortal = (t_BmPortal *)XX_Malloc(sizeof(t_BmPortal));
464296177Sjhibbits    if (!p_BmPortal)
465296177Sjhibbits    {
466296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm Portal obj!!!"));
467296177Sjhibbits        return NULL;
468296177Sjhibbits    }
469296177Sjhibbits    memset(p_BmPortal, 0, sizeof(t_BmPortal));
470296177Sjhibbits
471296177Sjhibbits    p_BmPortal->p_BmPortalLow = (struct bm_portal *)XX_Malloc(sizeof(struct bm_portal));
472296177Sjhibbits    if (!p_BmPortal->p_BmPortalLow)
473296177Sjhibbits    {
474296177Sjhibbits        XX_Free(p_BmPortal);
475296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low bm portal obj!!!"));
476296177Sjhibbits        return NULL;
477296177Sjhibbits    }
478296177Sjhibbits    memset(p_BmPortal->p_BmPortalLow, 0, sizeof(struct bm_portal));
479296177Sjhibbits
480296177Sjhibbits    p_BmPortal->p_BmPortalDriverParams = (t_BmPortalDriverParams *)XX_Malloc(sizeof(t_BmPortalDriverParams));
481296177Sjhibbits    if (!p_BmPortal->p_BmPortalDriverParams)
482296177Sjhibbits    {
483296177Sjhibbits        XX_Free(p_BmPortal);
484296177Sjhibbits        XX_Free(p_BmPortal->p_BmPortalLow);
485296177Sjhibbits        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Bm Portal driver parameters"));
486296177Sjhibbits        return NULL;
487296177Sjhibbits    }
488296177Sjhibbits    memset(p_BmPortal->p_BmPortalDriverParams, 0, sizeof(t_BmPortalDriverParams));
489296177Sjhibbits
490296177Sjhibbits    p_BmPortal->p_BmPortalLow->addr.addr_ce = UINT_TO_PTR(p_BmPortalParam->ceBaseAddress);
491296177Sjhibbits    p_BmPortal->p_BmPortalLow->addr.addr_ci = UINT_TO_PTR(p_BmPortalParam->ciBaseAddress);
492296177Sjhibbits    p_BmPortal->cpu   = (int)p_BmPortalParam->swPortalId;
493296177Sjhibbits    p_BmPortal->irq   = p_BmPortalParam->irq;
494296177Sjhibbits
495296177Sjhibbits    p_BmPortal->h_Bm    = p_BmPortalParam->h_Bm;
496296177Sjhibbits
497296177Sjhibbits    p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr     = DEFAULT_memAttr;
498296177Sjhibbits    bman_depletion_fill(&p_BmPortal->p_BmPortalDriverParams->mask);
499296177Sjhibbits
500296177Sjhibbits    return p_BmPortal;
501296177Sjhibbits}
502296177Sjhibbits
503296177Sjhibbitst_Error BM_PORTAL_Init(t_Handle h_BmPortal)
504296177Sjhibbits{
505296177Sjhibbits    t_BmPortal          *p_BmPortal = (t_BmPortal *)h_BmPortal;
506296177Sjhibbits    uint32_t            flags;
507296177Sjhibbits
508296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
509296177Sjhibbits
510296177Sjhibbits    flags = (uint32_t)((p_BmPortal->irq != NO_IRQ) ? BMAN_PORTAL_FLAG_IRQ : 0);
511296177Sjhibbits    flags |= ((p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE) ?
512296177Sjhibbits           BMAN_PORTAL_FLAG_CACHE : 0);
513296177Sjhibbits
514296177Sjhibbits    if (bman_create_portal(p_BmPortal,flags,&p_BmPortal->p_BmPortalDriverParams->mask)!=E_OK)
515296177Sjhibbits    {
516296177Sjhibbits        BM_PORTAL_Free(p_BmPortal);
517296177Sjhibbits        RETURN_ERROR(MAJOR, E_NULL_POINTER, ("create portal failed"));
518296177Sjhibbits    }
519296177Sjhibbits    BmSetPortalHandle(p_BmPortal->h_Bm, (t_Handle)p_BmPortal, (e_DpaaSwPortal)p_BmPortal->cpu);
520296177Sjhibbits
521296177Sjhibbits    XX_Free(p_BmPortal->p_BmPortalDriverParams);
522296177Sjhibbits    p_BmPortal->p_BmPortalDriverParams = NULL;
523296177Sjhibbits
524296177Sjhibbits    DBG(TRACE,("Bman-Portal (%d) @ %p:%p\n",
525296177Sjhibbits               p_BmPortal->cpu,
526296177Sjhibbits               p_BmPortal->p_BmPortalLow->addr.addr_ce,
527296177Sjhibbits               p_BmPortal->p_BmPortalLow->addr.addr_ci
528296177Sjhibbits               ));
529296177Sjhibbits
530296177Sjhibbits    DBG(TRACE,("Bman-Portal (%d) @ 0x%016llx:0x%016llx",
531296177Sjhibbits               p_BmPortal->cpu,
532296177Sjhibbits               (uint64_t)XX_VirtToPhys(p_BmPortal->p_BmPortalLow->addr.addr_ce),
533296177Sjhibbits               (uint64_t)XX_VirtToPhys(p_BmPortal->p_BmPortalLow->addr.addr_ci)
534296177Sjhibbits               ));
535296177Sjhibbits
536296177Sjhibbits    return E_OK;
537296177Sjhibbits}
538296177Sjhibbits
539296177Sjhibbitst_Error BM_PORTAL_Free(t_Handle h_BmPortal)
540296177Sjhibbits{
541296177Sjhibbits    t_BmPortal  *p_BmPortal = (t_BmPortal *)h_BmPortal;
542296177Sjhibbits
543296177Sjhibbits    if (!p_BmPortal)
544296177Sjhibbits       return ERROR_CODE(E_INVALID_HANDLE);
545296177Sjhibbits    BmSetPortalHandle(p_BmPortal->h_Bm, NULL, (e_DpaaSwPortal)p_BmPortal->cpu);
546296177Sjhibbits    bman_destroy_portal(p_BmPortal);
547296177Sjhibbits    XX_Free(p_BmPortal);
548296177Sjhibbits    return E_OK;
549296177Sjhibbits}
550296177Sjhibbits
551296177Sjhibbitst_Error BM_PORTAL_ConfigMemAttr(t_Handle h_BmPortal, uint32_t hwExtStructsMemAttr)
552296177Sjhibbits{
553296177Sjhibbits    t_BmPortal  *p_BmPortal = (t_BmPortal *)h_BmPortal;
554296177Sjhibbits
555296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_BmPortal, E_INVALID_HANDLE);
556296177Sjhibbits    SANITY_CHECK_RETURN_ERROR(p_BmPortal->p_BmPortalDriverParams, E_INVALID_HANDLE);
557296177Sjhibbits
558296177Sjhibbits    p_BmPortal->p_BmPortalDriverParams->hwExtStructsMemAttr = hwExtStructsMemAttr;
559296177Sjhibbits
560296177Sjhibbits    return E_OK;
561296177Sjhibbits}
562