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