Index: head/sys/contrib/ncsw/Peripherals/BM/bman_low.c =================================================================== --- head/sys/contrib/ncsw/Peripherals/BM/bman_low.c (revision 307541) +++ head/sys/contrib/ncsw/Peripherals/BM/bman_low.c (revision 307542) @@ -1,494 +1,494 @@ /****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File bman_low.c @Description BM low-level implementation *//***************************************************************************/ #include "std_ext.h" #include "core_ext.h" #include "xx_ext.h" #include "error_ext.h" #include "bman_private.h" /***************************/ /* Portal register assists */ /***************************/ /* Cache-inhibited register offsets */ -#define REG_RCR_PI_CINH (void *)0x0000 -#define REG_RCR_CI_CINH (void *)0x0004 -#define REG_RCR_ITR (void *)0x0008 -#define REG_CFG (void *)0x0100 -#define REG_SCN(n) ((void *)(0x0200 + ((n) << 2))) -#define REG_ISR (void *)0x0e00 -#define REG_IER (void *)0x0e04 -#define REG_ISDR (void *)0x0e08 -#define REG_IIR (void *)0x0e0c +#define REG_RCR_PI_CINH 0x0000 +#define REG_RCR_CI_CINH 0x0004 +#define REG_RCR_ITR 0x0008 +#define REG_CFG 0x0100 +#define REG_SCN(n) (0x0200 + ((n) << 2)) +#define REG_ISR 0x0e00 +#define REG_IER 0x0e04 +#define REG_ISDR 0x0e08 +#define REG_IIR 0x0e0c /* Cache-enabled register offsets */ -#define CL_CR (void *)0x0000 -#define CL_RR0 (void *)0x0100 -#define CL_RR1 (void *)0x0140 -#define CL_RCR (void *)0x1000 -#define CL_RCR_PI_CENA (void *)0x3000 -#define CL_RCR_CI_CENA (void *)0x3100 +#define CL_CR 0x0000 +#define CL_RR0 0x0100 +#define CL_RR1 0x0140 +#define CL_RCR 0x1000 +#define CL_RCR_PI_CENA 0x3000 +#define CL_RCR_CI_CENA 0x3100 /* The h/w design requires mappings to be size-aligned so that "add"s can be * reduced to "or"s. The primitives below do the same for s/w. */ -static __inline__ void *ptr_ADD(void *a, void *b) +static __inline__ void *ptr_ADD(void *a, uintptr_t b) { - return (void *)((uintptr_t)a + (uintptr_t)b); + return (void *)((uintptr_t)a + b); } /* Bitwise-OR two pointers */ -static __inline__ void *ptr_OR(void *a, void *b) +static __inline__ void *ptr_OR(void *a, uintptr_t b) { - return (void *)((uintptr_t)a | (uintptr_t)b); + return (void *)((uintptr_t)a | b); } /* Cache-inhibited register access */ -static __inline__ uint32_t __bm_in(struct bm_addr *bm, void *offset) +static __inline__ uint32_t __bm_in(struct bm_addr *bm, uintptr_t offset) { uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset); return GET_UINT32(*tmp); } -static __inline__ void __bm_out(struct bm_addr *bm, void *offset, uint32_t val) +static __inline__ void __bm_out(struct bm_addr *bm, uintptr_t offset, uint32_t val) { uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ci, offset); WRITE_UINT32(*tmp, val); } #define bm_in(reg) __bm_in(&portal->addr, REG_##reg) #define bm_out(reg, val) __bm_out(&portal->addr, REG_##reg, val) /* Convert 'n' cachelines to a pointer value for bitwise OR */ #define bm_cl(n) (void *)((n) << 6) /* Cache-enabled (index) register access */ -static __inline__ void __bm_cl_touch_ro(struct bm_addr *bm, void *offset) +static __inline__ void __bm_cl_touch_ro(struct bm_addr *bm, uintptr_t offset) { dcbt_ro(ptr_ADD(bm->addr_ce, offset)); } -static __inline__ void __bm_cl_touch_rw(struct bm_addr *bm, void *offset) +static __inline__ void __bm_cl_touch_rw(struct bm_addr *bm, uintptr_t offset) { dcbt_rw(ptr_ADD(bm->addr_ce, offset)); } -static __inline__ uint32_t __bm_cl_in(struct bm_addr *bm, void *offset) +static __inline__ uint32_t __bm_cl_in(struct bm_addr *bm, uintptr_t offset) { uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset); return GET_UINT32(*tmp); } -static __inline__ void __bm_cl_out(struct bm_addr *bm, void *offset, uint32_t val) +static __inline__ void __bm_cl_out(struct bm_addr *bm, uintptr_t offset, uint32_t val) { uint32_t *tmp = (uint32_t *)ptr_ADD(bm->addr_ce, offset); WRITE_UINT32(*tmp, val); dcbf(tmp); } -static __inline__ void __bm_cl_invalidate(struct bm_addr *bm, void *offset) +static __inline__ void __bm_cl_invalidate(struct bm_addr *bm, uintptr_t offset) { dcbi(ptr_ADD(bm->addr_ce, offset)); } #define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, CL_##reg##_CENA) #define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, CL_##reg##_CENA) #define bm_cl_in(reg) __bm_cl_in(&portal->addr, CL_##reg##_CENA) #define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, CL_##reg##_CENA, val) #define bm_cl_invalidate(reg) __bm_cl_invalidate(&portal->addr, CL_##reg##_CENA) /* Cyclic helper for rings. TODO: once we are able to do fine-grain perf * analysis, look at using the "extra" bit in the ring index registers to avoid * cyclic issues. */ static __inline__ uint8_t cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last) { /* 'first' is included, 'last' is excluded */ if (first <= last) return (uint8_t)(last - first); return (uint8_t)(ringsize + last - first); } /* --------------- */ /* --- RCR API --- */ /* It's safer to code in terms of the 'rcr' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define RCR_API_START() register struct bm_rcr *rcr = &portal->rcr */ /* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ #define RCR_CARRYCLEAR(p) \ (void *)((uintptr_t)(p) & (~(uintptr_t)(BM_RCR_SIZE << 6))) /* Bit-wise logic to convert a ring pointer to a ring index */ static __inline__ uint8_t RCR_PTR2IDX(struct bm_rcr_entry *e) { - return (uint8_t)(((uint32_t)e >> 6) & (BM_RCR_SIZE - 1)); + return (uint8_t)(((uintptr_t)e >> 6) & (BM_RCR_SIZE - 1)); } /* Increment the 'cursor' ring pointer, taking 'vbit' into account */ static __inline__ void RCR_INC(struct bm_rcr *rcr) { /* NB: this is odd-looking, but experiments show that it generates * fast code with essentially no branching overheads. We increment to * the next RCR pointer and handle overflow and 'vbit'. */ struct bm_rcr_entry *partial = rcr->cursor + 1; rcr->cursor = RCR_CARRYCLEAR(partial); if (partial != rcr->cursor) rcr->vbit ^= BM_RCR_VERB_VBIT; } t_Error bm_rcr_init(struct bm_portal *portal, e_BmPortalProduceMode pmode, e_BmPortalRcrConsumeMode cmode) { register struct bm_rcr *rcr = &portal->rcr; uint32_t cfg; uint8_t pi; rcr->ring = ptr_ADD(portal->addr.addr_ce, CL_RCR); rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1)); rcr->cursor = rcr->ring + pi; rcr->vbit = (uint8_t)((bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0); rcr->available = (uint8_t)(BM_RCR_SIZE - 1 - cyc_diff(BM_RCR_SIZE, rcr->ci, pi)); rcr->ithresh = (uint8_t)bm_in(RCR_ITR); #ifdef BM_CHECKING rcr->busy = 0; rcr->pmode = pmode; rcr->cmode = cmode; #else UNUSED(cmode); #endif /* BM_CHECKING */ cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */ bm_out(CFG, cfg); return 0; } void bm_rcr_finish(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; uint8_t pi = (uint8_t)(bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1)); uint8_t ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); ASSERT_COND(!rcr->busy); if (pi != RCR_PTR2IDX(rcr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("losing uncommitted RCR entries")); if (ci != rcr->ci) REPORT_ERROR(WARNING, E_INVALID_STATE, ("missing existing RCR completions")); if (rcr->ci != RCR_PTR2IDX(rcr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("RCR destroyed unquiesced")); } struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; ASSERT_COND(!rcr->busy); if (!rcr->available) return NULL; #ifdef BM_CHECKING rcr->busy = 1; #endif /* BM_CHECKING */ dcbz_64(rcr->cursor); return rcr->cursor; } void bm_rcr_abort(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; ASSERT_COND(rcr->busy); #ifdef BM_CHECKING rcr->busy = 0; #else UNUSED(rcr); #endif /* BM_CHECKING */ } struct bm_rcr_entry *bm_rcr_pend_and_next(struct bm_portal *portal, uint8_t myverb) { register struct bm_rcr *rcr = &portal->rcr; ASSERT_COND(rcr->busy); ASSERT_COND(rcr->pmode != e_BmPortalPVB); if (rcr->available == 1) return NULL; rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); dcbf_64(rcr->cursor); RCR_INC(rcr); rcr->available--; dcbz_64(rcr->cursor); return rcr->cursor; } void bm_rcr_pci_commit(struct bm_portal *portal, uint8_t myverb) { register struct bm_rcr *rcr = &portal->rcr; ASSERT_COND(rcr->busy); ASSERT_COND(rcr->pmode == e_BmPortalPCI); rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); RCR_INC(rcr); rcr->available--; hwsync(); bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor)); #ifdef BM_CHECKING rcr->busy = 0; #endif /* BM_CHECKING */ } void bm_rcr_pce_prefetch(struct bm_portal *portal) { ASSERT_COND(((struct bm_rcr *)&portal->rcr)->pmode == e_BmPortalPCE); bm_cl_invalidate(RCR_PI); bm_cl_touch_rw(RCR_PI); } void bm_rcr_pce_commit(struct bm_portal *portal, uint8_t myverb) { register struct bm_rcr *rcr = &portal->rcr; ASSERT_COND(rcr->busy); ASSERT_COND(rcr->pmode == e_BmPortalPCE); rcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); RCR_INC(rcr); rcr->available--; lwsync(); bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor)); #ifdef BM_CHECKING rcr->busy = 0; #endif /* BM_CHECKING */ } void bm_rcr_pvb_commit(struct bm_portal *portal, uint8_t myverb) { register struct bm_rcr *rcr = &portal->rcr; struct bm_rcr_entry *rcursor; ASSERT_COND(rcr->busy); ASSERT_COND(rcr->pmode == e_BmPortalPVB); lwsync(); rcursor = rcr->cursor; rcursor->__dont_write_directly__verb = (uint8_t)(myverb | rcr->vbit); dcbf_64(rcursor); RCR_INC(rcr); rcr->available--; #ifdef BM_CHECKING rcr->busy = 0; #endif /* BM_CHECKING */ } uint8_t bm_rcr_cci_update(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; uint8_t diff, old_ci = rcr->ci; ASSERT_COND(rcr->cmode == e_BmPortalRcrCCI); rcr->ci = (uint8_t)(bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1)); diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); rcr->available += diff; return diff; } void bm_rcr_cce_prefetch(struct bm_portal *portal) { ASSERT_COND(((struct bm_rcr *)&portal->rcr)->cmode == e_BmPortalRcrCCE); bm_cl_touch_ro(RCR_CI); } uint8_t bm_rcr_cce_update(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; uint8_t diff, old_ci = rcr->ci; ASSERT_COND(rcr->cmode == e_BmPortalRcrCCE); rcr->ci = (uint8_t)(bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1)); bm_cl_invalidate(RCR_CI); diff = cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); rcr->available += diff; return diff; } uint8_t bm_rcr_get_ithresh(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; return rcr->ithresh; } void bm_rcr_set_ithresh(struct bm_portal *portal, uint8_t ithresh) { register struct bm_rcr *rcr = &portal->rcr; rcr->ithresh = ithresh; bm_out(RCR_ITR, ithresh); } uint8_t bm_rcr_get_avail(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; return rcr->available; } uint8_t bm_rcr_get_fill(struct bm_portal *portal) { register struct bm_rcr *rcr = &portal->rcr; return (uint8_t)(BM_RCR_SIZE - 1 - rcr->available); } /* ------------------------------ */ /* --- Management command API --- */ /* It's safer to code in terms of the 'mc' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define MC_API_START() register struct bm_mc *mc = &portal->mc */ t_Error bm_mc_init(struct bm_portal *portal) { register struct bm_mc *mc = &portal->mc; mc->cr = ptr_ADD(portal->addr.addr_ce, CL_CR); mc->rr = ptr_ADD(portal->addr.addr_ce, CL_RR0); mc->rridx = (uint8_t)((mc->cr->__dont_write_directly__verb & BM_MCC_VERB_VBIT) ? 0 : 1); mc->vbit = (uint8_t)(mc->rridx ? BM_MCC_VERB_VBIT : 0); #ifdef BM_CHECKING mc->state = mc_idle; #endif /* BM_CHECKING */ return 0; } void bm_mc_finish(struct bm_portal *portal) { register struct bm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_idle); #ifdef BM_CHECKING if (mc->state != mc_idle) REPORT_ERROR(WARNING, E_INVALID_STATE, ("Losing incomplete MC command")); #else UNUSED(mc); #endif /* BM_CHECKING */ } struct bm_mc_command *bm_mc_start(struct bm_portal *portal) { register struct bm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_idle); #ifdef BM_CHECKING mc->state = mc_user; #endif /* BM_CHECKING */ dcbz_64(mc->cr); return mc->cr; } void bm_mc_abort(struct bm_portal *portal) { register struct bm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_user); #ifdef BM_CHECKING mc->state = mc_idle; #else UNUSED(mc); #endif /* BM_CHECKING */ } void bm_mc_commit(struct bm_portal *portal, uint8_t myverb) { register struct bm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_user); lwsync(); mc->cr->__dont_write_directly__verb = (uint8_t)(myverb | mc->vbit); dcbf_64(mc->cr); dcbit_ro(mc->rr + mc->rridx); #ifdef BM_CHECKING mc->state = mc_hw; #endif /* BM_CHECKING */ } struct bm_mc_result *bm_mc_result(struct bm_portal *portal) { register struct bm_mc *mc = &portal->mc; struct bm_mc_result *rr = mc->rr + mc->rridx; ASSERT_COND(mc->state == mc_hw); /* The inactive response register's verb byte always returns zero until * its command is submitted and completed. This includes the valid-bit, * in case you were wondering... */ if (!rr->verb) { dcbit_ro(rr); return NULL; } mc->rridx ^= 1; mc->vbit ^= BM_MCC_VERB_VBIT; #ifdef BM_CHECKING mc->state = mc_idle; #endif /* BM_CHECKING */ return rr; } /* ------------------------------------- */ /* --- Portal interrupt register API --- */ #define SCN_REG(bpid) REG_SCN((bpid) / 32) #define SCN_BIT(bpid) (0x80000000 >> (bpid & 31)) void bm_isr_bscn_mask(struct bm_portal *portal, uint8_t bpid, int enable) { uint32_t val; ASSERT_COND(bpid < BM_MAX_NUM_OF_POOLS); /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */ val = __bm_in(&portal->addr, SCN_REG(bpid)); if (enable) val |= SCN_BIT(bpid); else val &= ~SCN_BIT(bpid); __bm_out(&portal->addr, SCN_REG(bpid), val); } uint32_t __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n) { - return __bm_in(&portal->addr, PTR_MOVE(REG_ISR, (n << 2))); + return __bm_in(&portal->addr, REG_ISR + (n << 2)); } void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, uint32_t val) { - __bm_out(&portal->addr, PTR_MOVE(REG_ISR, (n << 2)), val); + __bm_out(&portal->addr, REG_ISR + (n << 2), val); } Index: head/sys/contrib/ncsw/Peripherals/QM/qm_portal_fqr.c =================================================================== --- head/sys/contrib/ncsw/Peripherals/QM/qm_portal_fqr.c (revision 307541) +++ head/sys/contrib/ncsw/Peripherals/QM/qm_portal_fqr.c (revision 307542) @@ -1,2701 +1,2701 @@ /****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File qm.c @Description QM & Portal implementation *//***************************************************************************/ #include "error_ext.h" #include "std_ext.h" #include "string_ext.h" #include "mm_ext.h" #include "qm.h" #include "qman_low.h" /****************************************/ /* static functions */ /****************************************/ #define SLOW_POLL_IDLE 1000 #define SLOW_POLL_BUSY 10 static t_Error qman_volatile_dequeue(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, uint32_t vdqcr) { ASSERT_COND((p_Fq->state == qman_fq_state_parked) || (p_Fq->state == qman_fq_state_retired)); ASSERT_COND(!(vdqcr & QM_VDQCR_FQID_MASK)); ASSERT_COND(!(p_Fq->flags & QMAN_FQ_STATE_VDQCR)); vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | p_Fq->fqid; NCSW_PLOCK(p_QmPortal); FQLOCK(p_Fq); p_Fq->flags |= QMAN_FQ_STATE_VDQCR; qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, vdqcr); FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return E_OK; } static const char *mcr_result_str(uint8_t result) { switch (result) { case QM_MCR_RESULT_NULL: return "QM_MCR_RESULT_NULL"; case QM_MCR_RESULT_OK: return "QM_MCR_RESULT_OK"; case QM_MCR_RESULT_ERR_FQID: return "QM_MCR_RESULT_ERR_FQID"; case QM_MCR_RESULT_ERR_FQSTATE: return "QM_MCR_RESULT_ERR_FQSTATE"; case QM_MCR_RESULT_ERR_NOTEMPTY: return "QM_MCR_RESULT_ERR_NOTEMPTY"; case QM_MCR_RESULT_PENDING: return "QM_MCR_RESULT_PENDING"; } return ""; } static t_Error qman_create_fq(t_QmPortal *p_QmPortal, uint32_t fqid, uint32_t flags, struct qman_fq *p_Fq) { struct qm_fqd fqd; struct qm_mcr_queryfq_np np; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; p_Fq->fqid = fqid; p_Fq->flags = flags; p_Fq->state = qman_fq_state_oos; p_Fq->cgr_groupid = 0; if (!(flags & QMAN_FQ_FLAG_RECOVER) || (flags & QMAN_FQ_FLAG_NO_MODIFY)) return E_OK; /* Everything else is RECOVER support */ NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->queryfq.fqid = fqid; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QUERYFQ failed: %s", mcr_result_str(p_Mcr->result))); } fqd = p_Mcr->queryfq.fqd; p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->queryfq_np.fqid = fqid; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("UERYFQ_NP failed: %s", mcr_result_str(p_Mcr->result))); } np = p_Mcr->queryfq_np; /* Phew, have queryfq and queryfq_np results, stitch together * the FQ object from those. */ p_Fq->cgr_groupid = fqd.cgid; switch (np.state & QM_MCR_NP_STATE_MASK) { case QM_MCR_NP_STATE_OOS: break; case QM_MCR_NP_STATE_RETIRED: p_Fq->state = qman_fq_state_retired; if (np.frm_cnt) p_Fq->flags |= QMAN_FQ_STATE_NE; break; case QM_MCR_NP_STATE_TEN_SCHED: case QM_MCR_NP_STATE_TRU_SCHED: case QM_MCR_NP_STATE_ACTIVE: p_Fq->state = qman_fq_state_sched; if (np.state & QM_MCR_NP_STATE_R) p_Fq->flags |= QMAN_FQ_STATE_CHANGING; break; case QM_MCR_NP_STATE_PARKED: p_Fq->state = qman_fq_state_parked; break; default: ASSERT_COND(FALSE); } if (fqd.fq_ctrl & QM_FQCTRL_CGE) p_Fq->state |= QMAN_FQ_STATE_CGR_EN; PUNLOCK(p_QmPortal); return E_OK; } static void qman_destroy_fq(struct qman_fq *p_Fq, uint32_t flags) { /* We don't need to lock the FQ as it is a pre-condition that the FQ be * quiesced. Instead, run some checks. */ UNUSED(flags); switch (p_Fq->state) { case qman_fq_state_parked: ASSERT_COND(flags & QMAN_FQ_DESTROY_PARKED); case qman_fq_state_oos: return; default: break; } ASSERT_COND(FALSE); } static t_Error qman_init_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, uint32_t flags, struct qm_mcc_initfq *p_Opts) { struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; uint8_t res, myverb = (uint8_t)((flags & QMAN_INITFQ_FLAG_SCHED) ? QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED); SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_oos) || (p_Fq->state == qman_fq_state_parked), E_INVALID_STATE); if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY) return ERROR_CODE(E_INVALID_VALUE); /* Issue an INITFQ_[PARKED|SCHED] management command */ NCSW_PLOCK(p_QmPortal); FQLOCK(p_Fq); if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) || ((p_Fq->state != qman_fq_state_oos) && (p_Fq->state != qman_fq_state_parked))) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return ERROR_CODE(E_BUSY); } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); Mem2IOCpy32((void*)&p_Mcc->initfq, p_Opts, sizeof(struct qm_mcc_initfq)); qm_mc_commit(p_QmPortal->p_LowQmPortal, myverb); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == myverb); res = p_Mcr->result; if (res != QM_MCR_RESULT_OK) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE,("INITFQ failed: %s", mcr_result_str(res))); } if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_FQCTRL) { if (p_Mcc->initfq.fqd.fq_ctrl & QM_FQCTRL_CGE) p_Fq->flags |= QMAN_FQ_STATE_CGR_EN; else p_Fq->flags &= ~QMAN_FQ_STATE_CGR_EN; } if (p_Mcc->initfq.we_mask & QM_INITFQ_WE_CGID) p_Fq->cgr_groupid = p_Mcc->initfq.fqd.cgid; p_Fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ? qman_fq_state_sched : qman_fq_state_parked; FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return E_OK; } static t_Error qman_retire_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, uint32_t *p_Flags, bool drain) { struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; t_Error err = E_OK; uint8_t res; SANITY_CHECK_RETURN_ERROR((p_Fq->state == qman_fq_state_parked) || (p_Fq->state == qman_fq_state_sched), E_INVALID_STATE); if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY) return E_INVALID_VALUE; NCSW_PLOCK(p_QmPortal); FQLOCK(p_Fq); if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) || (p_Fq->state == qman_fq_state_retired) || (p_Fq->state == qman_fq_state_oos)) { err = E_BUSY; goto out; } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->alterfq.fqid = p_Fq->fqid; if (drain) p_Mcc->alterfq.context_b = (uint32_t)PTR_TO_UINT(p_Fq); qm_mc_commit(p_QmPortal->p_LowQmPortal, (uint8_t)((drain)?QM_MCC_VERB_ALTER_RETIRE_CTXB:QM_MCC_VERB_ALTER_RETIRE)); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == (drain)?QM_MCR_VERB_ALTER_RETIRE_CTXB:QM_MCR_VERB_ALTER_RETIRE); res = p_Mcr->result; if (res == QM_MCR_RESULT_OK) { /* Process 'fq' right away, we'll ignore FQRNI */ if (p_Mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY) p_Fq->flags |= QMAN_FQ_STATE_NE; if (p_Mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT) p_Fq->flags |= QMAN_FQ_STATE_ORL; p_Fq->state = qman_fq_state_retired; } else if (res == QM_MCR_RESULT_PENDING) p_Fq->flags |= QMAN_FQ_STATE_CHANGING; else { XX_Print("ALTER_RETIRE failed: %s\n", mcr_result_str(res)); err = E_INVALID_STATE; } if (p_Flags) *p_Flags = p_Fq->flags; out: FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return err; } static t_Error qman_oos_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq) { struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; uint8_t res; ASSERT_COND(p_Fq->state == qman_fq_state_retired); if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY) return ERROR_CODE(E_INVALID_VALUE); NCSW_PLOCK(p_QmPortal); FQLOCK(p_Fq); if ((p_Fq->flags & QMAN_FQ_STATE_BLOCKOOS) || (p_Fq->state != qman_fq_state_retired)) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return ERROR_CODE(E_BUSY); } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->alterfq.fqid = p_Fq->fqid; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_OOS); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS); res = p_Mcr->result; if (res != QM_MCR_RESULT_OK) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_OOS failed: %s\n", mcr_result_str(res))); } p_Fq->state = qman_fq_state_oos; FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return E_OK; } static t_Error qman_schedule_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq) { struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; uint8_t res; ASSERT_COND(p_Fq->state == qman_fq_state_parked); if (p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY) return ERROR_CODE(E_INVALID_VALUE); /* Issue a ALTERFQ_SCHED management command */ NCSW_PLOCK(p_QmPortal); FQLOCK(p_Fq); if ((p_Fq->flags & QMAN_FQ_STATE_CHANGING) || (p_Fq->state != qman_fq_state_parked)) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return ERROR_CODE(E_BUSY); } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->alterfq.fqid = p_Fq->fqid; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_ALTER_SCHED); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED); res = p_Mcr->result; if (res != QM_MCR_RESULT_OK) { FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("ALTER_SCHED failed: %s\n", mcr_result_str(res))); } p_Fq->state = qman_fq_state_sched; FQUNLOCK(p_Fq); PUNLOCK(p_QmPortal); return E_OK; } /* Inline helper to reduce nesting in LoopMessageRing() */ static __inline__ void fq_state_change(struct qman_fq *p_Fq, struct qm_mr_entry *p_Msg, uint8_t verb) { FQLOCK(p_Fq); switch(verb) { case QM_MR_VERB_FQRL: ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_ORL); p_Fq->flags &= ~QMAN_FQ_STATE_ORL; break; case QM_MR_VERB_FQRN: ASSERT_COND((p_Fq->state == qman_fq_state_parked) || (p_Fq->state == qman_fq_state_sched)); ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING); p_Fq->flags &= ~QMAN_FQ_STATE_CHANGING; if (p_Msg->fq.fqs & QM_MR_FQS_NOTEMPTY) p_Fq->flags |= QMAN_FQ_STATE_NE; if (p_Msg->fq.fqs & QM_MR_FQS_ORLPRESENT) p_Fq->flags |= QMAN_FQ_STATE_ORL; p_Fq->state = qman_fq_state_retired; break; case QM_MR_VERB_FQPN: ASSERT_COND(p_Fq->state == qman_fq_state_sched); ASSERT_COND(p_Fq->flags & QMAN_FQ_STATE_CHANGING); p_Fq->state = qman_fq_state_parked; } FQUNLOCK(p_Fq); } static t_Error freeDrainedFq(struct qman_fq *p_Fq) { t_QmFqr *p_QmFqr; uint32_t i; ASSERT_COND(p_Fq); p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr; ASSERT_COND(p_QmFqr); ASSERT_COND(!p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset]); p_QmFqr->p_DrainedFqs[p_Fq->fqidOffset] = TRUE; p_QmFqr->numOfDrainedFqids++; if (p_QmFqr->numOfDrainedFqids == p_QmFqr->numOfFqids) { for (i=0;inumOfFqids;i++) { if ((p_QmFqr->p_Fqs[i]->state == qman_fq_state_retired) && (qman_oos_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]) != E_OK)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!")); qman_destroy_fq(p_QmFqr->p_Fqs[i], 0); XX_FreeSmart(p_QmFqr->p_Fqs[i]); } XX_Free(p_QmFqr->p_DrainedFqs); p_QmFqr->p_DrainedFqs = NULL; if (p_QmFqr->f_CompletionCB) { p_QmFqr->f_CompletionCB(p_QmFqr->h_App, p_QmFqr); XX_Free(p_QmFqr->p_Fqs); if (p_QmFqr->fqidBase) QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase); XX_Free(p_QmFqr); } } return E_OK; } static t_Error drainRetiredFq(struct qman_fq *p_Fq) { t_QmFqr *p_QmFqr; ASSERT_COND(p_Fq); p_QmFqr = (t_QmFqr *)p_Fq->h_QmFqr; ASSERT_COND(p_QmFqr); if (p_Fq->flags & QMAN_FQ_STATE_NE) { if (qman_volatile_dequeue(p_QmFqr->h_QmPortal, p_Fq, (QM_VDQCR_PRECEDENCE_VDQCR | QM_VDQCR_NUMFRAMES_TILLEMPTY)) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("drain with volatile failed")); return E_OK; } else return freeDrainedFq(p_Fq); } static e_RxStoreResponse drainCB(t_Handle h_App, t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame) { UNUSED(h_App); UNUSED(h_QmFqr); UNUSED(h_QmPortal); UNUSED(fqidOffset); UNUSED(p_Frame); DBG(TRACE,("got fd for fqid %d", ((t_QmFqr *)h_QmFqr)->fqidBase + fqidOffset)); return e_RX_STORE_RESPONSE_CONTINUE; } static void cb_ern_dcErn(t_Handle h_App, t_Handle h_QmPortal, struct qman_fq *p_Fq, const struct qm_mr_entry *p_Msg) { static int cnt = 0; UNUSED(p_Fq); UNUSED(p_Msg); UNUSED(h_App); UNUSED(h_QmPortal); XX_Print("cb_ern_dcErn_fqs() unimplemented %d\n", ++cnt); } static void cb_fqs(t_Handle h_App, t_Handle h_QmPortal, struct qman_fq *p_Fq, const struct qm_mr_entry *p_Msg) { UNUSED(p_Msg); UNUSED(h_App); UNUSED(h_QmPortal); if (p_Fq->state == qman_fq_state_retired && !(p_Fq->flags & QMAN_FQ_STATE_ORL)) drainRetiredFq(p_Fq); } static void null_cb_mr(t_Handle h_App, t_Handle h_QmPortal, struct qman_fq *p_Fq, const struct qm_mr_entry *p_Msg) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; UNUSED(p_Fq);UNUSED(h_App); if ((p_Msg->verb & QM_MR_VERB_DC_ERN) == QM_MR_VERB_DC_ERN) XX_Print("Ignoring unowned MR frame on cpu %d, dc-portal 0x%02x.\n", p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->dcern.portal); else XX_Print("Ignoring unowned MR frame on cpu %d, verb 0x%02x.\n", p_QmPortal->p_LowQmPortal->config.cpu,p_Msg->verb); } static uint32_t LoopMessageRing(t_QmPortal *p_QmPortal, uint32_t is) { struct qm_mr_entry *p_Msg; if (is & QM_PIRQ_CSCI) { struct qm_mc_result *p_Mcr; struct qman_cgrs tmp; uint32_t mask; unsigned int i, j; NCSW_PLOCK(p_QmPortal); qm_mc_start(p_QmPortal->p_LowQmPortal); qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCONGESTION); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; /* cgrs[0] is the portal mask for its cg's, cgrs[1] is the previous state of cg's */ for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++) { /* get curent state */ tmp.q.__state[i] = p_Mcr->querycongestion.state.__state[i]; /* keep only cg's that are registered for this portal */ tmp.q.__state[i] &= p_QmPortal->cgrs[0].q.__state[i]; /* handle only cg's that changed their state from previous exception */ tmp.q.__state[i] ^= p_QmPortal->cgrs[1].q.__state[i]; /* update previous */ p_QmPortal->cgrs[1].q.__state[i] = p_Mcr->querycongestion.state.__state[i]; } PUNLOCK(p_QmPortal); /* if in interrupt */ /* call the callback routines for any CG with a changed state */ for (i = 0; i < QM_MAX_NUM_OF_CGS/32; i++) for(j=0, mask = 0x80000000; j<32 ; j++, mask>>=1) { if(tmp.q.__state[i] & mask) { t_QmCg *p_QmCg = (t_QmCg *)(p_QmPortal->cgsHandles[i*32 + j]); if(p_QmCg->f_Exception) p_QmCg->f_Exception(p_QmCg->h_App, e_QM_EX_CG_STATE_CHANGE); } } } if (is & QM_PIRQ_EQRI) { NCSW_PLOCK(p_QmPortal); qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal); qm_eqcr_set_ithresh(p_QmPortal->p_LowQmPortal, 0); PUNLOCK(p_QmPortal); } if (is & QM_PIRQ_MRI) { mr_loop: qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal); if (p_Msg) { - struct qman_fq *p_FqFqs = (void *)p_Msg->fq.contextB; - struct qman_fq *p_FqErn = (void *)p_Msg->ern.tag; + struct qman_fq *p_FqFqs = UINT_TO_PTR(p_Msg->fq.contextB); + struct qman_fq *p_FqErn = UINT_TO_PTR(p_Msg->ern.tag); uint8_t verb =(uint8_t)(p_Msg->verb & QM_MR_VERB_TYPE_MASK); t_QmRejectedFrameInfo rejectedFrameInfo; memset(&rejectedFrameInfo, 0, sizeof(t_QmRejectedFrameInfo)); if (!(verb & QM_MR_VERB_DC_ERN)) { switch(p_Msg->ern.rc) { case(QM_MR_RC_CGR_TAILDROP): rejectedFrameInfo.rejectionCode = e_QM_RC_CG_TAILDROP; rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid; break; case(QM_MR_RC_WRED): rejectedFrameInfo.rejectionCode = e_QM_RC_CG_WRED; rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid; break; case(QM_MR_RC_FQ_TAILDROP): rejectedFrameInfo.rejectionCode = e_QM_RC_FQ_TAILDROP; rejectedFrameInfo.cg.cgId = (uint8_t)p_FqErn->cgr_groupid; break; case(QM_MR_RC_ERROR): break; default: REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Unknown rejection code")); } if (!p_FqErn) p_QmPortal->p_NullCB->ern(p_QmPortal->h_App, NULL, p_QmPortal, 0, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo); else p_FqErn->cb.ern(p_FqErn->h_App, p_FqErn->h_QmFqr, p_QmPortal, p_FqErn->fqidOffset, (t_DpaaFD*)&p_Msg->ern.fd, &rejectedFrameInfo); } else if (verb == QM_MR_VERB_DC_ERN) { if (!p_FqErn) p_QmPortal->p_NullCB->dc_ern(NULL, p_QmPortal, NULL, p_Msg); else p_FqErn->cb.dc_ern(p_FqErn->h_App, p_QmPortal, p_FqErn, p_Msg); } else { if (verb == QM_MR_VERB_FQRNI) ; /* we drop FQRNIs on the floor */ else if (!p_FqFqs) p_QmPortal->p_NullCB->fqs(NULL, p_QmPortal, NULL, p_Msg); else if ((verb == QM_MR_VERB_FQRN) || (verb == QM_MR_VERB_FQRL) || (verb == QM_MR_VERB_FQPN)) { fq_state_change(p_FqFqs, p_Msg, verb); p_FqFqs->cb.fqs(p_FqFqs->h_App, p_QmPortal, p_FqFqs, p_Msg); } } qm_mr_next(p_QmPortal->p_LowQmPortal); qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1); goto mr_loop; } } return is & (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI); } static void LoopDequeueRing(t_Handle h_QmPortal) { struct qm_dqrr_entry *p_Dq; struct qman_fq *p_Fq; enum qman_cb_dqrr_result res = qman_cb_dqrr_consume; e_RxStoreResponse tmpRes; t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; int prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH); while (res != qman_cb_dqrr_pause) { if (prefetch) qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal); qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); if (!p_Dq) break; - p_Fq = (void *)p_Dq->contextB; + p_Fq = UINT_TO_PTR(p_Dq->contextB); if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) { /* We only set QMAN_FQ_STATE_NE when retiring, so we only need * to check for clearing it when doing volatile dequeues. It's * one less thing to check in the critical path (SDQCR). */ tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; /* Check for VDQCR completion */ if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED) p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR; if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY) { p_Fq->flags &= ~QMAN_FQ_STATE_NE; freeDrainedFq(p_Fq); } } else { /* Interpret 'dq' from the owner's perspective. */ /* use portal default handlers */ ASSERT_COND(p_Dq->fqid); if (p_Fq) { tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; else if (p_Fq->state == qman_fq_state_waiting_parked) res = qman_cb_dqrr_park; } else { tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App, NULL, p_QmPortal, p_Dq->fqid, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; } } /* Parking isn't possible unless HELDACTIVE was set. NB, * FORCEELIGIBLE implies HELDACTIVE, so we only need to * check for HELDACTIVE to cover both. */ ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) || (res != qman_cb_dqrr_park)); if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) { /* Defer just means "skip it, I'll consume it myself later on" */ if (res != qman_cb_dqrr_defer) qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal, p_Dq, (res == qman_cb_dqrr_park)); qm_dqrr_next(p_QmPortal->p_LowQmPortal); } else { if (res == qman_cb_dqrr_park) /* The only thing to do for non-DCA is the park-request */ qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal); qm_dqrr_next(p_QmPortal->p_LowQmPortal); qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1); } } } static void LoopDequeueRingDcaOptimized(t_Handle h_QmPortal) { struct qm_dqrr_entry *p_Dq; struct qman_fq *p_Fq; enum qman_cb_dqrr_result res = qman_cb_dqrr_consume; e_RxStoreResponse tmpRes; t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; while (res != qman_cb_dqrr_pause) { qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); if (!p_Dq) break; - p_Fq = (void *)p_Dq->contextB; + p_Fq = UINT_TO_PTR(p_Dq->contextB); if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) { /* We only set QMAN_FQ_STATE_NE when retiring, so we only need * to check for clearing it when doing volatile dequeues. It's * one less thing to check in the critical path (SDQCR). */ tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; /* Check for VDQCR completion */ if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED) p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR; if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY) { p_Fq->flags &= ~QMAN_FQ_STATE_NE; freeDrainedFq(p_Fq); } } else { /* Interpret 'dq' from the owner's perspective. */ /* use portal default handlers */ ASSERT_COND(p_Dq->fqid); if (p_Fq) { tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; else if (p_Fq->state == qman_fq_state_waiting_parked) res = qman_cb_dqrr_park; } else { tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App, NULL, p_QmPortal, p_Dq->fqid, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; } } /* Parking isn't possible unless HELDACTIVE was set. NB, * FORCEELIGIBLE implies HELDACTIVE, so we only need to * check for HELDACTIVE to cover both. */ ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) || (res != qman_cb_dqrr_park)); /* Defer just means "skip it, I'll consume it myself later on" */ if (res != qman_cb_dqrr_defer) qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal, p_Dq, (res == qman_cb_dqrr_park)); qm_dqrr_next(p_QmPortal->p_LowQmPortal); } } static void LoopDequeueRingOptimized(t_Handle h_QmPortal) { struct qm_dqrr_entry *p_Dq; struct qman_fq *p_Fq; enum qman_cb_dqrr_result res = qman_cb_dqrr_consume; e_RxStoreResponse tmpRes; t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; while (res != qman_cb_dqrr_pause) { qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); if (!p_Dq) break; - p_Fq = (void *)p_Dq->contextB; + p_Fq = UINT_TO_PTR(p_Dq->contextB); if (p_Dq->stat & QM_DQRR_STAT_UNSCHEDULED) { /* We only set QMAN_FQ_STATE_NE when retiring, so we only need * to check for clearing it when doing volatile dequeues. It's * one less thing to check in the critical path (SDQCR). */ tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; /* Check for VDQCR completion */ if (p_Dq->stat & QM_DQRR_STAT_DQCR_EXPIRED) p_Fq->flags &= ~QMAN_FQ_STATE_VDQCR; if (p_Dq->stat & QM_DQRR_STAT_FQ_EMPTY) { p_Fq->flags &= ~QMAN_FQ_STATE_NE; freeDrainedFq(p_Fq); } } else { /* Interpret 'dq' from the owner's perspective. */ /* use portal default handlers */ ASSERT_COND(p_Dq->fqid); if (p_Fq) { tmpRes = p_Fq->cb.dqrr(p_Fq->h_App, p_Fq->h_QmFqr, p_QmPortal, p_Fq->fqidOffset, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; else if (p_Fq->state == qman_fq_state_waiting_parked) res = qman_cb_dqrr_park; } else { tmpRes = p_QmPortal->p_NullCB->dqrr(p_QmPortal->h_App, NULL, p_QmPortal, p_Dq->fqid, (t_DpaaFD*)&p_Dq->fd); if (tmpRes == e_RX_STORE_RESPONSE_PAUSE) res = qman_cb_dqrr_pause; } } /* Parking isn't possible unless HELDACTIVE was set. NB, * FORCEELIGIBLE implies HELDACTIVE, so we only need to * check for HELDACTIVE to cover both. */ ASSERT_COND((p_Dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) || (res != qman_cb_dqrr_park)); if (res == qman_cb_dqrr_park) /* The only thing to do for non-DCA is the park-request */ qm_dqrr_park_ci(p_QmPortal->p_LowQmPortal); qm_dqrr_next(p_QmPortal->p_LowQmPortal); qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1); } } /* Portal interrupt handler */ static void portal_isr(void *ptr) { t_QmPortal *p_QmPortal = ptr; uint32_t event = 0; uint32_t enableEvents = qm_isr_enable_read(p_QmPortal->p_LowQmPortal); DBG(TRACE, ("software-portal %d got interrupt", p_QmPortal->p_LowQmPortal->config.cpu)); event |= (qm_isr_status_read(p_QmPortal->p_LowQmPortal) & enableEvents); qm_isr_status_clear(p_QmPortal->p_LowQmPortal, event); /* Only do fast-path handling if it's required */ if (/*(event & QM_PIRQ_DQRI) &&*/ (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_FAST)) p_QmPortal->f_LoopDequeueRingCB(p_QmPortal); if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ_SLOW) LoopMessageRing(p_QmPortal, event); } static t_Error qman_query_fq_np(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq, struct qm_mcr_queryfq_np *p_Np) { struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; uint8_t res; NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->queryfq_np.fqid = p_Fq->fqid; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYFQ_NP); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP); res = p_Mcr->result; if (res == QM_MCR_RESULT_OK) *p_Np = p_Mcr->queryfq_np; PUNLOCK(p_QmPortal); if (res != QM_MCR_RESULT_OK) RETURN_ERROR(MINOR, E_INVALID_STATE, ("QUERYFQ_NP failed: %s\n", mcr_result_str(res))); return E_OK; } static uint8_t QmCgGetCgId(t_Handle h_QmCg) { t_QmCg *p_QmCg = (t_QmCg *)h_QmCg; return p_QmCg->id; } static t_Error qm_new_fq(t_QmPortal *p_QmPortal, uint32_t fqid, uint32_t fqidOffset, uint32_t channel, uint32_t wqid, uint16_t count, uint32_t flags, t_QmFqrCongestionAvoidanceParams *p_CgParams, t_QmContextA *p_ContextA, t_QmContextB *p_ContextB, bool initParked, t_Handle h_QmFqr, struct qman_fq **p_Fqs) { struct qman_fq *p_Fq = NULL; struct qm_mcc_initfq fq_opts; uint32_t i; t_Error err = E_OK; int gap, tmp; uint32_t tmpA, tmpN, ta=0, tn=0, initFqFlag; ASSERT_COND(p_QmPortal); ASSERT_COND(count); for(i=0;icb.dqrr = p_QmPortal->f_DfltFrame; p_Fq->cb.ern = p_QmPortal->f_RejectedFrame; p_Fq->cb.dc_ern = cb_ern_dcErn; p_Fq->cb.fqs = cb_fqs; p_Fq->h_App = p_QmPortal->h_App; p_Fq->h_QmFqr = h_QmFqr; p_Fq->fqidOffset = fqidOffset; p_Fqs[i] = p_Fq; if ((err = qman_create_fq(p_QmPortal,(uint32_t)(fqid + i), 0, p_Fqs[i])) != E_OK) break; } if (err != E_OK) { for(i=0;ih_QmCg); /* CG OAC and FQ TD may not be configured at the same time. if both are required, than we configure CG first, and the FQ TD later - see below. */ fq_opts.fqd.cgid = QmCgGetCgId(p_CgParams->h_QmCg); fq_opts.we_mask |= QM_INITFQ_WE_CGID; if(p_CgParams->overheadAccountingLength) { fq_opts.we_mask |= QM_INITFQ_WE_OAC; fq_opts.we_mask &= ~QM_INITFQ_WE_TDTHRESH; fq_opts.fqd.td_thresh = (uint16_t)(QM_FQD_TD_THRESH_OAC_EN | p_CgParams->overheadAccountingLength); } } if((flags & QM_FQCTRL_TDE) && (!p_CgParams->overheadAccountingLength)) { ASSERT_COND(p_CgParams->fqTailDropThreshold); fq_opts.we_mask |= QM_INITFQ_WE_TDTHRESH; /* express thresh as ta*2^tn */ gap = (int)p_CgParams->fqTailDropThreshold; for (tmpA=0 ; tmpA<256; tmpA++ ) for (tmpN=0 ; tmpN<32; tmpN++ ) { tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<overheadAccountingLength)) initFqFlag = 0; else initFqFlag = (uint32_t)(initParked?0:QMAN_INITFQ_FLAG_SCHED); if ((err = qman_init_fq(p_QmPortal, p_Fqs[0], initFqFlag, &fq_opts)) != E_OK) { for(i=0;ioverheadAccountingLength)) { ASSERT_COND(p_CgParams->fqTailDropThreshold); fq_opts.we_mask = QM_INITFQ_WE_TDTHRESH; /* express thresh as ta*2^tn */ gap = (int)p_CgParams->fqTailDropThreshold; for (tmpA=0 ; tmpA<256; tmpA++ ) for (tmpN=0 ; tmpN<32; tmpN++ ) { tmp = ABS((int)(p_CgParams->fqTailDropThreshold - tmpA*(1<fqid += i; } return err; } static t_Error qm_free_fq(t_QmPortal *p_QmPortal, struct qman_fq *p_Fq) { uint32_t flags=0; if (qman_retire_fq(p_QmPortal, p_Fq, &flags, FALSE) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!")); if (flags & QMAN_FQ_STATE_CHANGING) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("fq %d currently in use, will be retired", p_Fq->fqid)); if (flags & QMAN_FQ_STATE_NE) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed;" \ "Frame Queue Not Empty, Need to dequeue")); if (qman_oos_fq(p_QmPortal, p_Fq) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_oos_fq() failed!")); qman_destroy_fq(p_Fq,0); return E_OK; } static void qman_disable_portal(t_QmPortal *p_QmPortal) { NCSW_PLOCK(p_QmPortal); if (!(p_QmPortal->disable_count++)) qm_dqrr_set_maxfill(p_QmPortal->p_LowQmPortal, 0); PUNLOCK(p_QmPortal); } /* quiesce SDQCR/VDQCR, then drain till h/w wraps up anything it * was doing (5ms is more than enough to ensure it's done). */ static void clean_dqrr_mr(t_QmPortal *p_QmPortal) { struct qm_dqrr_entry *p_Dq; struct qm_mr_entry *p_Msg; int idle = 0; qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, 0); qm_dqrr_vdqcr_set(p_QmPortal->p_LowQmPortal, 0); drain_loop: qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal); qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); qmPortalMrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); p_Msg = qm_mr_current(p_QmPortal->p_LowQmPortal); if (p_Dq) { qm_dqrr_next(p_QmPortal->p_LowQmPortal); qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1); } if (p_Msg) { qm_mr_next(p_QmPortal->p_LowQmPortal); qmPortalMrCciConsume(p_QmPortal->p_LowQmPortal, 1); } if (!p_Dq && !p_Msg) { if (++idle < 5) { XX_UDelay(1000); goto drain_loop; } } else { idle = 0; goto drain_loop; } } static t_Error qman_create_portal(t_QmPortal *p_QmPortal, uint32_t flags, uint32_t sdqcrFlags, uint8_t dqrrSize) { const struct qm_portal_config *p_Config = &(p_QmPortal->p_LowQmPortal->config); int ret = 0; t_Error err; uint32_t isdr; if ((err = qm_eqcr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalEqcrCCE)) != E_OK) RETURN_ERROR(MINOR, err, ("Qman EQCR initialization failed\n")); if (qm_dqrr_init(p_QmPortal->p_LowQmPortal, sdqcrFlags ? e_QmPortalDequeuePushMode : e_QmPortalDequeuePullMode, e_QmPortalPVB, (flags & QMAN_PORTAL_FLAG_DCA) ? e_QmPortalDqrrDCA : e_QmPortalDqrrCCI, dqrrSize, (flags & QMAN_PORTAL_FLAG_RSTASH) ? 1 : 0, (flags & QMAN_PORTAL_FLAG_DSTASH) ? 1 : 0)) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR initialization failed")); goto fail_dqrr; } if (qm_mr_init(p_QmPortal->p_LowQmPortal, e_QmPortalPVB, e_QmPortalMrCCI)) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR initialization failed")); goto fail_mr; } if (qm_mc_init(p_QmPortal->p_LowQmPortal)) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MC initialization failed")); goto fail_mc; } if (qm_isr_init(p_QmPortal->p_LowQmPortal)) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("ISR initialization failed")); goto fail_isr; } /* static interrupt-gating controls */ qm_dqrr_set_ithresh(p_QmPortal->p_LowQmPortal, 12); qm_mr_set_ithresh(p_QmPortal->p_LowQmPortal, 4); qm_isr_set_iperiod(p_QmPortal->p_LowQmPortal, 100); p_QmPortal->options = flags; isdr = 0xffffffff; qm_isr_status_clear(p_QmPortal->p_LowQmPortal, 0xffffffff); qm_isr_enable_write(p_QmPortal->p_LowQmPortal, DEFAULT_portalExceptions); qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr); if (flags & QMAN_PORTAL_FLAG_IRQ) { XX_SetIntr(p_Config->irq, portal_isr, p_QmPortal); XX_EnableIntr(p_Config->irq); qm_isr_uninhibit(p_QmPortal->p_LowQmPortal); } else /* without IRQ, we can't block */ flags &= ~QMAN_PORTAL_FLAG_WAIT; /* Need EQCR to be empty before continuing */ isdr ^= QM_PIRQ_EQCI; qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr); ret = qm_eqcr_get_fill(p_QmPortal->p_LowQmPortal); if (ret) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("EQCR unclean")); goto fail_eqcr_empty; } isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI); qm_isr_disable_write(p_QmPortal->p_LowQmPortal, isdr); if (qm_dqrr_current(p_QmPortal->p_LowQmPortal) != NULL) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("DQRR unclean")); goto fail_dqrr_mr_empty; } if (qm_mr_current(p_QmPortal->p_LowQmPortal) != NULL) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("MR unclean")); goto fail_dqrr_mr_empty; } qm_isr_disable_write(p_QmPortal->p_LowQmPortal, 0); qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags); return E_OK; fail_dqrr_mr_empty: fail_eqcr_empty: qm_isr_finish(p_QmPortal->p_LowQmPortal); fail_isr: qm_mc_finish(p_QmPortal->p_LowQmPortal); fail_mc: qm_mr_finish(p_QmPortal->p_LowQmPortal); fail_mr: qm_dqrr_finish(p_QmPortal->p_LowQmPortal); fail_dqrr: qm_eqcr_finish(p_QmPortal->p_LowQmPortal); return ERROR_CODE(E_INVALID_STATE); } static void qman_destroy_portal(t_QmPortal *p_QmPortal) { /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or * something related to QM_PIRQ_EQCI, this may need fixing. */ qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal); if (p_QmPortal->options & QMAN_PORTAL_FLAG_IRQ) { XX_DisableIntr(p_QmPortal->p_LowQmPortal->config.irq); XX_FreeIntr(p_QmPortal->p_LowQmPortal->config.irq); } qm_isr_finish(p_QmPortal->p_LowQmPortal); qm_mc_finish(p_QmPortal->p_LowQmPortal); qm_mr_finish(p_QmPortal->p_LowQmPortal); qm_dqrr_finish(p_QmPortal->p_LowQmPortal); qm_eqcr_finish(p_QmPortal->p_LowQmPortal); } static inline struct qm_eqcr_entry *try_eq_start(t_QmPortal *p_QmPortal) { struct qm_eqcr_entry *p_Eq; uint8_t avail; avail = qm_eqcr_get_avail(p_QmPortal->p_LowQmPortal); if (avail == EQCR_THRESH) qmPortalEqcrCcePrefetch(p_QmPortal->p_LowQmPortal); else if (avail < EQCR_THRESH) qmPortalEqcrCceUpdate(p_QmPortal->p_LowQmPortal); p_Eq = qm_eqcr_start(p_QmPortal->p_LowQmPortal); return p_Eq; } static t_Error qman_orp_update(t_QmPortal *p_QmPortal, uint32_t orpId, uint16_t orpSeqnum, uint32_t flags) { struct qm_eqcr_entry *p_Eq; NCSW_PLOCK(p_QmPortal); p_Eq = try_eq_start(p_QmPortal); if (!p_Eq) { PUNLOCK(p_QmPortal); return ERROR_CODE(E_BUSY); } if (flags & QMAN_ENQUEUE_FLAG_NESN) orpSeqnum |= QM_EQCR_SEQNUM_NESN; else /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ orpSeqnum &= ~QM_EQCR_SEQNUM_NESN; p_Eq->seqnum = orpSeqnum; p_Eq->orp = orpId; qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)QM_EQCR_VERB_ORP); PUNLOCK(p_QmPortal); return E_OK; } static __inline__ t_Error CheckStashParams(t_QmFqrParams *p_QmFqrParams) { ASSERT_COND(p_QmFqrParams); if (p_QmFqrParams->stashingParams.frameAnnotationSize > QM_CONTEXTA_MAX_STASH_SIZE) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Annotation Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE)); if (p_QmFqrParams->stashingParams.frameDataSize > QM_CONTEXTA_MAX_STASH_SIZE) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Data Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE)); if (p_QmFqrParams->stashingParams.fqContextSize > QM_CONTEXTA_MAX_STASH_SIZE) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Frame Context Size Exceeded Max Stash Size(%d)", QM_CONTEXTA_MAX_STASH_SIZE)); if (p_QmFqrParams->stashingParams.fqContextSize) { if (!p_QmFqrParams->stashingParams.fqContextAddr) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be givven")); if (!IS_ALIGNED(p_QmFqrParams->stashingParams.fqContextAddr, CACHELINE_SIZE)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address Must be aligned to %d", CACHELINE_SIZE)); if (p_QmFqrParams->stashingParams.fqContextAddr & 0xffffff0000000000LL) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FQ Context Address May be up to 40 bit")); } return E_OK; } static t_Error QmPortalRegisterCg(t_Handle h_QmPortal, t_Handle h_QmCg, uint8_t cgId) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; /* cgrs[0] is the mask of registered CG's*/ if(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32))) RETURN_ERROR(MINOR, E_BUSY, ("CG already used")); p_QmPortal->cgrs[0].q.__state[cgId/32] |= 0x80000000 >> (cgId % 32); p_QmPortal->cgsHandles[cgId] = h_QmCg; return E_OK; } static t_Error QmPortalUnregisterCg(t_Handle h_QmPortal, uint8_t cgId) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; /* cgrs[0] is the mask of registered CG's*/ if(!(p_QmPortal->cgrs[0].q.__state[cgId/32] & (0x80000000 >> (cgId % 32)))) RETURN_ERROR(MINOR, E_BUSY, ("CG is not in use")); p_QmPortal->cgrs[0].q.__state[cgId/32] &= ~0x80000000 >> (cgId % 32); p_QmPortal->cgsHandles[cgId] = NULL; return E_OK; } static e_DpaaSwPortal QmPortalGetSwPortalId(t_Handle h_QmPortal) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; return (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu; } static t_Error CalcWredCurve(t_QmCgWredCurve *p_WredCurve, uint32_t *p_CurveWord) { uint32_t maxP, roundDown, roundUp, tmpA, tmpN; uint32_t ma=0, mn=0, slope, sa=0, sn=0, pn; int pres = 1000; int gap, tmp; /* TODO - change maxTh to uint64_t? if(p_WredCurve->maxTh > (1<<39)) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh is not in range"));*/ /* express maxTh as ma*2^mn */ gap = (int)p_WredCurve->maxTh; for (tmpA=0 ; tmpA<256; tmpA++ ) for (tmpN=0 ; tmpN<32; tmpN++ ) { tmp = ABS((int)(p_WredCurve->maxTh - tmpA*(1<maxTh = ma*(1<maxTh <= p_WredCurve->minTh) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("maxTh must be larger than minTh")); if(p_WredCurve->probabilityDenominator > 64) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("probabilityDenominator mustn't be 1-64")); /* first we translate from Cisco probabilityDenominator to 256 fixed denominator, result must be divisible by 4. */ /* we multiply by a fixed value to get better accuracy (without using floating point) */ maxP = (uint32_t)(256*1000/p_WredCurve->probabilityDenominator); if (maxP % 4*pres) { roundDown = maxP + (maxP % (4*pres)); roundUp = roundDown + 4*pres; if((roundUp - maxP) > (maxP - roundDown)) maxP = roundDown; else maxP = roundUp; } maxP = maxP/pres; ASSERT_COND(maxP <= 256); pn = (uint8_t)(maxP/4 - 1); if(maxP >= (p_WredCurve->maxTh - p_WredCurve->minTh)) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Due to probabilityDenominator selected, maxTh-minTh must be larger than %d", maxP)); pres = 1000000; slope = maxP*pres/(p_WredCurve->maxTh - p_WredCurve->minTh); /* express slope as sa/2^sn */ gap = (int)slope; for (tmpA=(uint32_t)(64*pres) ; tmpA<128*pres; tmpA += pres ) for (tmpN=7 ; tmpN<64; tmpN++ ) { tmp = ABS((int)(slope - tmpA/(1<=64); sn = sn; ASSERT_COND(sn<64 && sn>=7); *p_CurveWord = ((ma << 24) | (mn << 19) | (sa << 12) | (sn << 6) | pn); return E_OK; } static t_Error QmPortalPullFrame(t_Handle h_QmPortal, uint32_t pdqcr, t_DpaaFD *p_Frame) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; struct qm_dqrr_entry *p_Dq; struct qman_fq *p_Fq; int prefetch; uint32_t *p_Dst, *p_Src; ASSERT_COND(p_QmPortal); ASSERT_COND(p_Frame); SANITY_CHECK_RETURN_ERROR(p_QmPortal->pullMode, E_INVALID_STATE); NCSW_PLOCK(p_QmPortal); qm_dqrr_pdqcr_set(p_QmPortal->p_LowQmPortal, pdqcr); CORE_MemoryBarrier(); while (qm_dqrr_pdqcr_get(p_QmPortal->p_LowQmPortal)) ; prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH); while(TRUE) { if (prefetch) qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal); qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); if (!p_Dq) continue; - p_Fq = (void *)p_Dq->contextB; + p_Fq = UINT_TO_PTR(p_Dq->contextB); ASSERT_COND(p_Dq->fqid); p_Dst = (uint32_t *)p_Frame; p_Src = (uint32_t *)&p_Dq->fd; p_Dst[0] = p_Src[0]; p_Dst[1] = p_Src[1]; p_Dst[2] = p_Src[2]; p_Dst[3] = p_Src[3]; if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) { qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal, p_Dq, FALSE); qm_dqrr_next(p_QmPortal->p_LowQmPortal); } else { qm_dqrr_next(p_QmPortal->p_LowQmPortal); qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1); } break; } PUNLOCK(p_QmPortal); if (!(p_Dq->stat & QM_DQRR_STAT_FD_VALID)) return ERROR_CODE(E_EMPTY); return E_OK; } /****************************************/ /* API Init unit functions */ /****************************************/ t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam) { t_QmPortal *p_QmPortal; uint32_t i; SANITY_CHECK_RETURN_VALUE(p_QmPortalParam, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_QmPortalParam->swPortalId < DPAA_MAX_NUM_OF_SW_PORTALS, E_INVALID_VALUE, 0); p_QmPortal = (t_QmPortal *)XX_Malloc(sizeof(t_QmPortal)); if (!p_QmPortal) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal obj!!!")); return NULL; } memset(p_QmPortal, 0, sizeof(t_QmPortal)); p_QmPortal->p_LowQmPortal = (struct qm_portal *)XX_Malloc(sizeof(struct qm_portal)); if (!p_QmPortal->p_LowQmPortal) { XX_Free(p_QmPortal); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Low qm p_QmPortal obj!!!")); return NULL; } memset(p_QmPortal->p_LowQmPortal, 0, sizeof(struct qm_portal)); p_QmPortal->p_QmPortalDriverParams = (t_QmPortalDriverParams *)XX_Malloc(sizeof(t_QmPortalDriverParams)); if (!p_QmPortal->p_QmPortalDriverParams) { XX_Free(p_QmPortal->p_LowQmPortal); XX_Free(p_QmPortal); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Qm Portal driver parameters")); return NULL; } memset(p_QmPortal->p_QmPortalDriverParams, 0, sizeof(t_QmPortalDriverParams)); p_QmPortal->p_LowQmPortal->addr.addr_ce = UINT_TO_PTR(p_QmPortalParam->ceBaseAddress); p_QmPortal->p_LowQmPortal->addr.addr_ci = UINT_TO_PTR(p_QmPortalParam->ciBaseAddress); p_QmPortal->p_LowQmPortal->config.irq = p_QmPortalParam->irq; p_QmPortal->p_LowQmPortal->config.bound = 0; p_QmPortal->p_LowQmPortal->config.cpu = (int)p_QmPortalParam->swPortalId; p_QmPortal->p_LowQmPortal->config.channel = (e_QmFQChannel)(e_QM_FQ_CHANNEL_SWPORTAL0 + p_QmPortalParam->swPortalId); p_QmPortal->p_LowQmPortal->bind_lock = XX_InitSpinlock(); p_QmPortal->h_Qm = p_QmPortalParam->h_Qm; p_QmPortal->f_DfltFrame = p_QmPortalParam->f_DfltFrame; p_QmPortal->f_RejectedFrame = p_QmPortalParam->f_RejectedFrame; p_QmPortal->h_App = p_QmPortalParam->h_App; p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset = p_QmPortalParam->fdLiodnOffset; p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = DEFAULT_dequeueDcaMode; p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames = DEFAULT_dequeueUpToThreeFrames; p_QmPortal->p_QmPortalDriverParams->commandType = DEFAULT_dequeueCommandType; p_QmPortal->p_QmPortalDriverParams->userToken = DEFAULT_dequeueUserToken; p_QmPortal->p_QmPortalDriverParams->specifiedWq = DEFAULT_dequeueSpecifiedWq; p_QmPortal->p_QmPortalDriverParams->dedicatedChannel = DEFAULT_dequeueDedicatedChannel; p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels = DEFAULT_dequeueDedicatedChannelHasPrecedenceOverPoolChannels; p_QmPortal->p_QmPortalDriverParams->poolChannelId = DEFAULT_dequeuePoolChannelId; p_QmPortal->p_QmPortalDriverParams->wqId = DEFAULT_dequeueWqId; for (i=0;ip_QmPortalDriverParams->poolChannels[i] = FALSE; p_QmPortal->p_QmPortalDriverParams->dqrrSize = DEFAULT_dqrrSize; p_QmPortal->p_QmPortalDriverParams->pullMode = DEFAULT_pullMode; return p_QmPortal; } t_Error QM_PORTAL_Init(t_Handle h_QmPortal) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; uint32_t i, flags=0, sdqcrFlags=0; t_Error err; t_QmInterModulePortalInitParams qmParams; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE); memset(&qmParams, 0, sizeof(qmParams)); qmParams.portalId = (uint8_t)p_QmPortal->p_LowQmPortal->config.cpu; qmParams.liodn = p_QmPortal->p_QmPortalDriverParams->fdLiodnOffset; qmParams.dqrrLiodn = p_QmPortal->p_QmPortalDriverParams->dqrrLiodn; qmParams.fdFqLiodn = p_QmPortal->p_QmPortalDriverParams->fdFqLiodn; qmParams.stashDestQueue = p_QmPortal->p_QmPortalDriverParams->stashDestQueue; if ((err = QmGetSetPortalParams(p_QmPortal->h_Qm, &qmParams)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); flags = (uint32_t)(((p_QmPortal->p_LowQmPortal->config.irq == NO_IRQ) ? 0 : (QMAN_PORTAL_FLAG_IRQ | QMAN_PORTAL_FLAG_IRQ_FAST | QMAN_PORTAL_FLAG_IRQ_SLOW))); flags |= ((p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode) ? QMAN_PORTAL_FLAG_DCA : 0); flags |= (p_QmPortal->p_QmPortalDriverParams->dqrr)?QMAN_PORTAL_FLAG_RSTASH:0; flags |= (p_QmPortal->p_QmPortalDriverParams->fdFq)?QMAN_PORTAL_FLAG_DSTASH:0; p_QmPortal->pullMode = p_QmPortal->p_QmPortalDriverParams->pullMode; if (!p_QmPortal->pullMode) { sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dequeueUpToThreeFrames) ? QM_SDQCR_COUNT_UPTO3 : QM_SDQCR_COUNT_EXACT1; sdqcrFlags |= QM_SDQCR_TOKEN_SET(p_QmPortal->p_QmPortalDriverParams->userToken); sdqcrFlags |= QM_SDQCR_TYPE_SET(p_QmPortal->p_QmPortalDriverParams->commandType); if (!p_QmPortal->p_QmPortalDriverParams->specifiedWq) { /* sdqcrFlags |= QM_SDQCR_SOURCE_CHANNELS;*/ /* removed as the macro is '0' */ sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannelHasPrecedenceOverPoolChannels) ? QM_SDQCR_DEDICATED_PRECEDENCE : 0; sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_CHANNELS_DEDICATED : 0; for (i=0;ip_QmPortalDriverParams->poolChannels[i]) ? QM_SDQCR_CHANNELS_POOL(i+1) : 0); } else { sdqcrFlags |= QM_SDQCR_SOURCE_SPECIFICWQ; sdqcrFlags |= (p_QmPortal->p_QmPortalDriverParams->dedicatedChannel) ? QM_SDQCR_SPECIFICWQ_DEDICATED : QM_SDQCR_SPECIFICWQ_POOL(p_QmPortal->p_QmPortalDriverParams->poolChannelId); sdqcrFlags |= QM_SDQCR_SPECIFICWQ_WQ(p_QmPortal->p_QmPortalDriverParams->wqId); } } if ((flags & QMAN_PORTAL_FLAG_RSTASH) && (flags & QMAN_PORTAL_FLAG_DCA)) p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingDcaOptimized; else if ((flags & QMAN_PORTAL_FLAG_RSTASH) && !(flags & QMAN_PORTAL_FLAG_DCA)) p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRingOptimized; else p_QmPortal->f_LoopDequeueRingCB = LoopDequeueRing; if ((!p_QmPortal->f_RejectedFrame) || (!p_QmPortal->f_DfltFrame)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_RejectedFrame or f_DfltFrame callback not provided")); p_QmPortal->p_NullCB = (struct qman_fq_cb *)XX_Malloc(sizeof(struct qman_fq_cb)); if (!p_QmPortal->p_NullCB) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FQ Null CB obj!!!")); memset(p_QmPortal->p_NullCB, 0, sizeof(struct qman_fq_cb)); p_QmPortal->p_NullCB->dqrr = p_QmPortal->f_DfltFrame; p_QmPortal->p_NullCB->ern = p_QmPortal->f_RejectedFrame; p_QmPortal->p_NullCB->dc_ern = p_QmPortal->p_NullCB->fqs = null_cb_mr; if (qman_create_portal(p_QmPortal, flags, sdqcrFlags, p_QmPortal->p_QmPortalDriverParams->dqrrSize) != E_OK) { RETURN_ERROR(MAJOR, E_NO_MEMORY, ("create portal failed")); } QmSetPortalHandle(p_QmPortal->h_Qm, (t_Handle)p_QmPortal, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu); XX_Free(p_QmPortal->p_QmPortalDriverParams); p_QmPortal->p_QmPortalDriverParams = NULL; DBG(TRACE, ("Qman-Portal %d @ %p:%p", p_QmPortal->p_LowQmPortal->config.cpu, p_QmPortal->p_LowQmPortal->addr.addr_ce, p_QmPortal->p_LowQmPortal->addr.addr_ci )); DBG(TRACE, ("Qman-Portal %d phys @ 0x%016llx:0x%016llx", p_QmPortal->p_LowQmPortal->config.cpu, (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ce), (uint64_t)XX_VirtToPhys(p_QmPortal->p_LowQmPortal->addr.addr_ci) )); return E_OK; } t_Error QM_PORTAL_Free(t_Handle h_QmPortal) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; if (!p_QmPortal) return ERROR_CODE(E_INVALID_HANDLE); ASSERT_COND(p_QmPortal->p_LowQmPortal); QmSetPortalHandle(p_QmPortal->h_Qm, NULL, (e_DpaaSwPortal)p_QmPortal->p_LowQmPortal->config.cpu); qman_destroy_portal(p_QmPortal); if (p_QmPortal->p_NullCB) XX_Free(p_QmPortal->p_NullCB); if (p_QmPortal->p_LowQmPortal->bind_lock) XX_FreeSpinlock(p_QmPortal->p_LowQmPortal->bind_lock); if(p_QmPortal->p_QmPortalDriverParams) XX_Free(p_QmPortal->p_QmPortalDriverParams); XX_Free(p_QmPortal->p_LowQmPortal); XX_Free(p_QmPortal); return E_OK; } t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_INVALID_HANDLE); p_QmPortal->p_QmPortalDriverParams->dequeueDcaMode = enable; return E_OK; } t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR(p_StashParams, E_NULL_POINTER); p_QmPortal->p_QmPortalDriverParams->stashDestQueue = p_StashParams->stashDestQueue; p_QmPortal->p_QmPortalDriverParams->dqrrLiodn = p_StashParams->dqrrLiodn; p_QmPortal->p_QmPortalDriverParams->fdFqLiodn = p_StashParams->fdFqLiodn; p_QmPortal->p_QmPortalDriverParams->eqcr = p_StashParams->eqcr; p_QmPortal->p_QmPortalDriverParams->eqcrHighPri = p_StashParams->eqcrHighPri; p_QmPortal->p_QmPortalDriverParams->dqrr = p_StashParams->dqrr; p_QmPortal->p_QmPortalDriverParams->dqrrHighPri = p_StashParams->dqrrHighPri; p_QmPortal->p_QmPortalDriverParams->fdFq = p_StashParams->fdFq; p_QmPortal->p_QmPortalDriverParams->fdFqHighPri = p_StashParams->fdFqHighPri; p_QmPortal->p_QmPortalDriverParams->fdFqDrop = p_StashParams->fdFqDrop; return E_OK; } t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_QmPortal->p_QmPortalDriverParams, E_NULL_POINTER); p_QmPortal->p_QmPortalDriverParams->pullMode = pullMode; return E_OK; } t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; uint32_t sdqcrFlags; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((poolChannelId < QM_MAX_NUM_OF_POOL_CHANNELS), E_INVALID_VALUE); sdqcrFlags = qm_dqrr_sdqcr_get(p_QmPortal->p_LowQmPortal); sdqcrFlags |= QM_SDQCR_CHANNELS_POOL(poolChannelId+1); qm_dqrr_sdqcr_set(p_QmPortal->p_LowQmPortal, sdqcrFlags); return E_OK; } t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); NCSW_PLOCK(p_QmPortal); if ((source == e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES) || (source == e_QM_PORTAL_POLL_SOURCE_BOTH)) { uint32_t is = qm_isr_status_read(p_QmPortal->p_LowQmPortal); uint32_t active = LoopMessageRing(p_QmPortal, is); if (active) qm_isr_status_clear(p_QmPortal->p_LowQmPortal, active); } if ((source == e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES) || (source == e_QM_PORTAL_POLL_SOURCE_BOTH)) p_QmPortal->f_LoopDequeueRingCB((t_Handle)p_QmPortal); PUNLOCK(p_QmPortal); return E_OK; } t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo) { t_QmPortal *p_QmPortal = (t_QmPortal *)h_QmPortal; struct qm_dqrr_entry *p_Dq; struct qman_fq *p_Fq; int prefetch; SANITY_CHECK_RETURN_ERROR(p_QmPortal, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_frameInfo, E_NULL_POINTER); NCSW_PLOCK(p_QmPortal); prefetch = !(p_QmPortal->options & QMAN_PORTAL_FLAG_RSTASH); if (prefetch) qmPortalDqrrPvbPrefetch(p_QmPortal->p_LowQmPortal); qmPortalDqrrPvbUpdate(p_QmPortal->p_LowQmPortal); p_Dq = qm_dqrr_current(p_QmPortal->p_LowQmPortal); if (!p_Dq) { PUNLOCK(p_QmPortal); return ERROR_CODE(E_EMPTY); } - p_Fq = (void *)p_Dq->contextB; + p_Fq = UINT_TO_PTR(p_Dq->contextB); ASSERT_COND(p_Dq->fqid); if (p_Fq) { p_frameInfo->h_App = p_Fq->h_App; p_frameInfo->h_QmFqr = p_Fq->h_QmFqr; p_frameInfo->fqidOffset = p_Fq->fqidOffset; memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD)); } else { p_frameInfo->h_App = p_QmPortal->h_App; p_frameInfo->h_QmFqr = NULL; p_frameInfo->fqidOffset = p_Dq->fqid; memcpy((void*)&p_frameInfo->frame, (void*)&p_Dq->fd, sizeof(t_DpaaFD)); } if (p_QmPortal->options & QMAN_PORTAL_FLAG_DCA) { qmPortalDqrrDcaConsume1ptr(p_QmPortal->p_LowQmPortal, p_Dq, FALSE); qm_dqrr_next(p_QmPortal->p_LowQmPortal); } else { qm_dqrr_next(p_QmPortal->p_LowQmPortal); qmPortalDqrrCciConsume(p_QmPortal->p_LowQmPortal, 1); } PUNLOCK(p_QmPortal); return E_OK; } t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams) { t_QmFqr *p_QmFqr; uint32_t i, flags = 0; u_QmFqdContextA cnxtA; SANITY_CHECK_RETURN_VALUE(p_QmFqrParams, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_QmFqrParams->h_Qm, E_INVALID_HANDLE, NULL); if (p_QmFqrParams->shadowMode && (!p_QmFqrParams->useForce || p_QmFqrParams->numOfFqids != 1)) { REPORT_ERROR(MAJOR, E_CONFLICT, ("shadowMode must be use with useForce and numOfFqids==1!!!")); return NULL; } p_QmFqr = (t_QmFqr *)XX_MallocSmart(sizeof(t_QmFqr), 0, 64); if (!p_QmFqr) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQR obj!!!")); return NULL; } memset(p_QmFqr, 0, sizeof(t_QmFqr)); p_QmFqr->h_Qm = p_QmFqrParams->h_Qm; p_QmFqr->h_QmPortal = p_QmFqrParams->h_QmPortal; p_QmFqr->shadowMode = p_QmFqrParams->shadowMode; p_QmFqr->numOfFqids = (p_QmFqrParams->useForce && !p_QmFqrParams->numOfFqids) ? 1 : p_QmFqrParams->numOfFqids; if (!p_QmFqr->h_QmPortal) { p_QmFqr->h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm); SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_QmPortal, E_INVALID_HANDLE, NULL); } p_QmFqr->p_Fqs = (struct qman_fq **)XX_Malloc(sizeof(struct qman_fq *) * p_QmFqr->numOfFqids); if (!p_QmFqr->p_Fqs) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM FQs obj!!!")); QM_FQR_Free(p_QmFqr); return NULL; } memset(p_QmFqr->p_Fqs, 0, sizeof(struct qman_fq *) * p_QmFqr->numOfFqids); if (p_QmFqr->shadowMode) { struct qman_fq *p_Fq = NULL; p_QmFqr->fqidBase = p_QmFqrParams->qs.frcQ.fqid; p_Fq = (struct qman_fq *)XX_MallocSmart(sizeof(struct qman_fq), 0, 64); if (!p_Fq) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!")); QM_FQR_Free(p_QmFqr); return NULL; } memset(p_Fq, 0, sizeof(struct qman_fq)); p_Fq->cb.dqrr = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_DfltFrame; p_Fq->cb.ern = ((t_QmPortal*)p_QmFqr->h_QmPortal)->f_RejectedFrame; p_Fq->cb.dc_ern = cb_ern_dcErn; p_Fq->cb.fqs = cb_fqs; p_Fq->h_App = ((t_QmPortal*)p_QmFqr->h_QmPortal)->h_App; p_Fq->h_QmFqr = p_QmFqr; p_Fq->state = qman_fq_state_sched; p_Fq->fqid = p_QmFqr->fqidBase; p_QmFqr->p_Fqs[0] = p_Fq; } else { p_QmFqr->channel = p_QmFqrParams->channel; p_QmFqr->workQueue = p_QmFqrParams->wq; p_QmFqr->fqidBase = QmFqidGet(p_QmFqr->h_Qm, p_QmFqr->numOfFqids, p_QmFqrParams->qs.nonFrcQs.align, p_QmFqrParams->useForce, p_QmFqrParams->qs.frcQ.fqid); if (p_QmFqr->fqidBase == (uint32_t)ILLEGAL_BASE) { REPORT_ERROR(CRITICAL,E_INVALID_STATE,("can't allocate a fqid")); QM_FQR_Free(p_QmFqr); return NULL; } if(p_QmFqrParams->congestionAvoidanceEnable && (p_QmFqrParams->congestionAvoidanceParams.h_QmCg == NULL) && (p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold == 0)) { REPORT_ERROR(CRITICAL,E_INVALID_STATE,("NULL congestion group handle and no FQ Threshold")); QM_FQR_Free(p_QmFqr); return NULL; } if(p_QmFqrParams->congestionAvoidanceEnable) { if(p_QmFqrParams->congestionAvoidanceParams.h_QmCg) flags |= QM_FQCTRL_CGE; if(p_QmFqrParams->congestionAvoidanceParams.fqTailDropThreshold) flags |= QM_FQCTRL_TDE; } /* flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_ORP : 0; flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_CPCSTASH : 0; flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_FORCESFDR : 0; flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_AVOIDBLOCK : 0; */ flags |= (p_QmFqrParams->holdActive) ? QM_FQCTRL_HOLDACTIVE : 0; flags |= (p_QmFqrParams->preferInCache) ? QM_FQCTRL_LOCKINCACHE : 0; if (p_QmFqrParams->useContextAForStash) { if (CheckStashParams(p_QmFqrParams) != E_OK) { REPORT_ERROR(CRITICAL,E_INVALID_STATE,NO_MSG); QM_FQR_Free(p_QmFqr); return NULL; } memset(&cnxtA, 0, sizeof(cnxtA)); cnxtA.stashing.annotation_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameAnnotationSize, CACHELINE_SIZE); cnxtA.stashing.data_cl = DIV_CEIL(p_QmFqrParams->stashingParams.frameDataSize, CACHELINE_SIZE); cnxtA.stashing.context_cl = DIV_CEIL(p_QmFqrParams->stashingParams.fqContextSize, CACHELINE_SIZE); cnxtA.context_hi = (uint8_t)((p_QmFqrParams->stashingParams.fqContextAddr >> 32) & 0xff); cnxtA.context_lo = (uint32_t)(p_QmFqrParams->stashingParams.fqContextAddr); flags |= QM_FQCTRL_CTXASTASHING; } for(i=0;inumOfFqids;i++) if (qm_new_fq(p_QmFqr->h_QmPortal, p_QmFqr->fqidBase+i, i, p_QmFqr->channel, p_QmFqr->workQueue, 1/*p_QmFqr->numOfFqids*/, flags, (p_QmFqrParams->congestionAvoidanceEnable ? &p_QmFqrParams->congestionAvoidanceParams : NULL), p_QmFqrParams->useContextAForStash ? (t_QmContextA *)&cnxtA : p_QmFqrParams->p_ContextA, p_QmFqrParams->p_ContextB, p_QmFqrParams->initParked, p_QmFqr, &p_QmFqr->p_Fqs[i]) != E_OK) { QM_FQR_Free(p_QmFqr); return NULL; } } return p_QmFqr; } t_Error QM_FQR_Free(t_Handle h_QmFqr) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; uint32_t i; if (!p_QmFqr) return ERROR_CODE(E_INVALID_HANDLE); if (p_QmFqr->p_Fqs) { for (i=0;inumOfFqids;i++) if (p_QmFqr->p_Fqs[i]) { if (!p_QmFqr->shadowMode) qm_free_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i]); XX_FreeSmart(p_QmFqr->p_Fqs[i]); } XX_Free(p_QmFqr->p_Fqs); } if (!p_QmFqr->shadowMode && p_QmFqr->fqidBase) QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase); XX_FreeSmart(p_QmFqr); return E_OK; } t_Error QM_FQR_FreeWDrain(t_Handle h_QmFqr, t_QmFqrDrainedCompletionCB *f_CompletionCB, bool deliverFrame, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; uint32_t i; if (!p_QmFqr) return ERROR_CODE(E_INVALID_HANDLE); if (p_QmFqr->shadowMode) RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("QM_FQR_FreeWDrain can't be called to shadow FQR!!!. call QM_FQR_Free")); p_QmFqr->p_DrainedFqs = (bool *)XX_Malloc(sizeof(bool) * p_QmFqr->numOfFqids); if (!p_QmFqr->p_DrainedFqs) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("QM Drained-FQs obj!!!. Try to Free without draining")); memset(p_QmFqr->p_DrainedFqs, 0, sizeof(bool) * p_QmFqr->numOfFqids); if (f_CompletionCB) { p_QmFqr->f_CompletionCB = f_CompletionCB; p_QmFqr->h_App = h_App; } if (deliverFrame) { if (!f_CallBack) { REPORT_ERROR(MAJOR, E_NULL_POINTER, ("f_CallBack must be given.")); XX_Free(p_QmFqr->p_DrainedFqs); return ERROR_CODE(E_NULL_POINTER); } QM_FQR_RegisterCB(p_QmFqr, f_CallBack, h_App); } else QM_FQR_RegisterCB(p_QmFqr, drainCB, h_App); for (i=0;inumOfFqids;i++) { if (qman_retire_fq(p_QmFqr->h_QmPortal, p_QmFqr->p_Fqs[i], 0, TRUE) != E_OK) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("qman_retire_fq() failed!")); if (p_QmFqr->p_Fqs[i]->flags & QMAN_FQ_STATE_CHANGING) DBG(INFO, ("fq %d currently in use, will be retired", p_QmFqr->p_Fqs[i]->fqid)); else drainRetiredFq(p_QmFqr->p_Fqs[i]); } if (!p_QmFqr->f_CompletionCB) { while(p_QmFqr->p_DrainedFqs) ; DBG(TRACE, ("QM-FQR with base %d completed", p_QmFqr->fqidBase)); XX_FreeSmart(p_QmFqr->p_Fqs); if (p_QmFqr->fqidBase) QmFqidPut(p_QmFqr->h_Qm, p_QmFqr->fqidBase); XX_FreeSmart(p_QmFqr); } return E_OK; } t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; int i; SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE); for (i=0;inumOfFqids;i++) { p_QmFqr->p_Fqs[i]->cb.dqrr = f_CallBack; p_QmFqr->p_Fqs[i]->h_App = h_App; } return E_OK; } t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; t_QmPortal *p_QmPortal; struct qm_eqcr_entry *p_Eq; uint32_t *p_Dst, *p_Src; const struct qman_fq *p_Fq; SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE); if (!h_QmPortal) { SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE); h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm); SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE); } p_QmPortal = (t_QmPortal *)h_QmPortal; p_Fq = p_QmFqr->p_Fqs[fqidOffset]; #ifdef QM_CHECKING if (p_Fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); if ((!(p_Fq->flags & QMAN_FQ_FLAG_NO_MODIFY)) && ((p_Fq->state == qman_fq_state_retired) || (p_Fq->state == qman_fq_state_oos))) return ERROR_CODE(E_BUSY); #endif /* QM_CHECKING */ NCSW_PLOCK(p_QmPortal); p_Eq = try_eq_start(p_QmPortal); if (!p_Eq) { PUNLOCK(p_QmPortal); return ERROR_CODE(E_BUSY); } p_Eq->fqid = p_Fq->fqid; - p_Eq->tag = (uint32_t)p_Fq; + p_Eq->tag = (uintptr_t)p_Fq; /* gcc does a dreadful job of the following; * eq->fd = *fd; * It causes the entire function to save/restore a wider range of * registers, and comes up with instruction-waste galore. This will do * until we can rework the function for better code-generation. */ p_Dst = (uint32_t *)&p_Eq->fd; p_Src = (uint32_t *)p_Frame; p_Dst[0] = p_Src[0]; p_Dst[1] = p_Src[1]; p_Dst[2] = p_Src[2]; p_Dst[3] = p_Src[3]; qmPortalEqcrPvbCommit(p_QmPortal->p_LowQmPortal, (uint8_t)(QM_EQCR_VERB_CMD_ENQUEUE/* | (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))*/)); PUNLOCK(p_QmPortal); return E_OK; } t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; uint32_t pdqcr = 0; SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR(p_Frame, E_NULL_POINTER); SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_oos) || (p_QmFqr->p_Fqs[fqidOffset]->state == qman_fq_state_parked), E_INVALID_STATE); if (!h_QmPortal) { SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE); h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm); SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE); } pdqcr |= QM_PDQCR_MODE_UNSCHEDULED; pdqcr |= QM_PDQCR_FQID(p_QmFqr->p_Fqs[fqidOffset]->fqid); return QmPortalPullFrame(h_QmPortal, pdqcr, p_Frame); } t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE); if (!h_QmPortal) { SANITY_CHECK_RETURN_ERROR(p_QmFqr->h_Qm, E_INVALID_HANDLE); h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm); SANITY_CHECK_RETURN_ERROR(h_QmPortal, E_INVALID_HANDLE); } return qman_schedule_fq(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset]); } t_Error QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; SANITY_CHECK_RETURN_ERROR(p_QmFqr, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE); SANITY_CHECK_RETURN_ERROR((p_QmFqr->p_Fqs[fqidOffset]->flags & QM_FQCTRL_HOLDACTIVE), E_INVALID_STATE); UNUSED(h_QmPortal); p_QmFqr->p_Fqs[fqidOffset]->state = qman_fq_state_waiting_parked; return E_OK; } uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0); return p_QmFqr->fqidBase; } uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter) { t_QmFqr *p_QmFqr = (t_QmFqr *)h_QmFqr; struct qm_mcr_queryfq_np queryfq_np; SANITY_CHECK_RETURN_VALUE(p_QmFqr, E_INVALID_HANDLE, 0); SANITY_CHECK_RETURN_VALUE((fqidOffset < p_QmFqr->numOfFqids), E_INVALID_VALUE, 0); if (!h_QmPortal) { SANITY_CHECK_RETURN_VALUE(p_QmFqr->h_Qm, E_INVALID_HANDLE, 0); h_QmPortal = QmGetPortalHandle(p_QmFqr->h_Qm); SANITY_CHECK_RETURN_VALUE(h_QmPortal, E_INVALID_HANDLE, 0); } if (qman_query_fq_np(h_QmPortal, p_QmFqr->p_Fqs[fqidOffset], &queryfq_np) != E_OK) return 0; switch (counter) { case e_QM_FQR_COUNTERS_FRAME : return queryfq_np.frm_cnt; case e_QM_FQR_COUNTERS_BYTE : return queryfq_np.byte_cnt; default : break; } /* should never get here */ ASSERT_COND(FALSE); return 0; } t_Handle QM_CG_Create(t_QmCgParams *p_CgParams) { t_QmCg *p_QmCg; t_QmPortal *p_QmPortal; t_Error err; uint32_t wredParams; uint32_t tmpA, tmpN, ta=0, tn=0; int gap, tmp; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; SANITY_CHECK_RETURN_VALUE(p_CgParams, E_INVALID_HANDLE, NULL); SANITY_CHECK_RETURN_VALUE(p_CgParams->h_Qm, E_INVALID_HANDLE, NULL); if(p_CgParams->notifyDcPortal && ((p_CgParams->dcPortalId == e_DPAA_DCPORTAL2) || (p_CgParams->dcPortalId == e_DPAA_DCPORTAL3))) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("notifyDcPortal is invalid for this DC Portal")); return NULL; } if (!p_CgParams->h_QmPortal) { p_QmPortal = QmGetPortalHandle(p_CgParams->h_Qm); SANITY_CHECK_RETURN_VALUE(p_QmPortal, E_INVALID_STATE, NULL); } else p_QmPortal = p_CgParams->h_QmPortal; p_QmCg = (t_QmCg *)XX_Malloc(sizeof(t_QmCg)); if (!p_QmCg) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("QM CG obj!!!")); return NULL; } memset(p_QmCg, 0, sizeof(t_QmCg)); /* build CG struct */ p_QmCg->h_Qm = p_CgParams->h_Qm; p_QmCg->h_QmPortal = p_QmPortal; p_QmCg->h_App = p_CgParams->h_App; err = QmGetCgId(p_CgParams->h_Qm, &p_QmCg->id); if (err) { XX_Free(p_QmCg); REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmGetCgId failed")); return NULL; } NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; err = QmPortalRegisterCg(p_QmPortal, p_QmCg, p_QmCg->id); if (err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalRegisterCg failed")); return NULL; } /* Build CGR command */ { #ifdef QM_CGS_NO_FRAME_MODE t_QmRevisionInfo revInfo; QmGetRevision(p_QmCg->h_Qm, &revInfo); if (!((revInfo.majorRev == 1) && (revInfo.minorRev == 0))) #endif /* QM_CGS_NO_FRAME_MODE */ if (p_CgParams->frameCount) { p_Mcc->initcgr.we_mask |= QM_CGR_WE_MODE; p_Mcc->initcgr.cgr.frame_mode = QM_CGR_EN; } } if (p_CgParams->wredEnable) { if (p_CgParams->wredParams.enableGreen) { err = CalcWredCurve(&p_CgParams->wredParams.greenCurve, &wredParams); if(err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MAJOR, err, NO_MSG); return NULL; } p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G; p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams; } if (p_CgParams->wredParams.enableYellow) { err = CalcWredCurve(&p_CgParams->wredParams.yellowCurve, &wredParams); if(err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MAJOR, err, NO_MSG); return NULL; } p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y; p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams; } if (p_CgParams->wredParams.enableRed) { err = CalcWredCurve(&p_CgParams->wredParams.redCurve, &wredParams); if(err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MAJOR, err, NO_MSG); return NULL; } p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R; p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams; } } if (p_CgParams->tailDropEnable) { if (!p_CgParams->threshold) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MINOR, E_INVALID_STATE, ("tailDropThreshold must be configured if tailDropEnable ")); return NULL; } p_Mcc->initcgr.cgr.cstd_en = QM_CGR_EN; p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSTD_EN; } if (p_CgParams->threshold) { p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES; p_QmCg->f_Exception = p_CgParams->f_Exception; if (p_QmCg->f_Exception || p_CgParams->notifyDcPortal) { p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN; p_Mcc->initcgr.we_mask |= QM_CGR_WE_CSCN_EN | QM_CGR_WE_CSCN_TARG; /* if SW - set target, if HW - if FM, set HW target, otherwize, set SW target */ p_Mcc->initcgr.cgr.cscn_targ = 0; if (p_QmCg->f_Exception) p_Mcc->initcgr.cgr.cscn_targ = (uint32_t)QM_CGR_TARGET_SWP(QmPortalGetSwPortalId(p_QmCg->h_QmPortal)); if (p_CgParams->notifyDcPortal) p_Mcc->initcgr.cgr.cscn_targ |= (uint32_t)QM_CGR_TARGET_DCP(p_CgParams->dcPortalId); } /* express thresh as ta*2^tn */ gap = (int)p_CgParams->threshold; for (tmpA=0 ; tmpA<256; tmpA++ ) for (tmpN=0 ; tmpN<32; tmpN++ ) { tmp = ABS((int)(p_CgParams->threshold - tmpA*(1<initcgr.cgr.cs_thres.TA = ta; p_Mcc->initcgr.cgr.cs_thres.Tn = tn; } else if(p_CgParams->f_Exception) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MINOR, E_INVALID_STATE, ("No threshold configured, but f_Exception defined")); return NULL; } qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_INITCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_INITCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); REPORT_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result))); return NULL; } PUNLOCK(p_QmPortal); return p_QmCg; } t_Error QM_CG_Free(t_Handle h_QmCg) { t_QmCg *p_QmCg = (t_QmCg *)h_QmCg; t_Error err; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; t_QmPortal *p_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE); p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal; NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; p_Mcc->initcgr.we_mask = QM_CGR_WE_MASK; err = QmFreeCgId(p_QmCg->h_Qm, p_QmCg->id); if(err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmFreeCgId failed")); } err = QmPortalUnregisterCg(p_QmCg->h_QmPortal, p_QmCg->id); if(err) { XX_Free(p_QmCg); PUNLOCK(p_QmPortal); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("QmPortalUnregisterCg failed")); } qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result))); } PUNLOCK(p_QmPortal); XX_Free(p_QmCg); return E_OK; } t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable) { t_QmCg *p_QmCg = (t_QmCg *)h_QmCg; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; t_QmPortal *p_QmPortal; SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE); p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal; if (!p_QmCg->f_Exception) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Either threshold or exception callback was not configured.")); NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; p_Mcc->initcgr.we_mask = QM_CGR_WE_CSCN_EN; if(exception == e_QM_EX_CG_STATE_CHANGE) { if(enable) p_Mcc->initcgr.cgr.cscn_en = QM_CGR_EN; } else { PUNLOCK(p_QmPortal); RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal exception")); } qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result))); } PUNLOCK(p_QmPortal); return E_OK; } t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams) { t_QmCg *p_QmCg = (t_QmCg *)h_QmCg; uint32_t wredParams; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; t_QmPortal *p_QmPortal; t_Error err = E_OK; SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE); p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal; NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result))); } switch(p_QmCgModifyParams->color) { case(e_QM_CG_COLOR_GREEN): if(!p_Mcr->querycgr.cgr.wr_en_g) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for green")); } break; case(e_QM_CG_COLOR_YELLOW): if(!p_Mcr->querycgr.cgr.wr_en_y) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for yellow")); } break; case(e_QM_CG_COLOR_RED): if(!p_Mcr->querycgr.cgr.wr_en_r) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("WRED is not enabled for red")); } break; } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; switch(p_QmCgModifyParams->color) { case(e_QM_CG_COLOR_GREEN): err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams); p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_G | QM_CGR_WE_WR_PARM_G; p_Mcc->initcgr.cgr.wr_en_g = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_g.word = wredParams; break; case(e_QM_CG_COLOR_YELLOW): err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams); p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_Y | QM_CGR_WE_WR_PARM_Y; p_Mcc->initcgr.cgr.wr_en_y = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_y.word = wredParams; break; case(e_QM_CG_COLOR_RED): err = CalcWredCurve(&p_QmCgModifyParams->wredParams, &wredParams); p_Mcc->initcgr.we_mask |= QM_CGR_WE_WR_EN_R | QM_CGR_WE_WR_PARM_R; p_Mcc->initcgr.cgr.wr_en_r = QM_CGR_EN; p_Mcc->initcgr.cgr.wr_parm_r.word = wredParams; break; } if (err) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, err, NO_MSG); } qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result))); } PUNLOCK(p_QmPortal); return E_OK; } t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold) { t_QmCg *p_QmCg = (t_QmCg *)h_QmCg; struct qm_mc_command *p_Mcc; struct qm_mc_result *p_Mcr; t_QmPortal *p_QmPortal; uint32_t tmpA, tmpN, ta=0, tn=0; int gap, tmp; SANITY_CHECK_RETURN_ERROR(p_QmCg, E_INVALID_HANDLE); p_QmPortal = (t_QmPortal *)p_QmCg->h_QmPortal; NCSW_PLOCK(p_QmPortal); p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_QUERYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("QM_MCC_VERB_QUERYCGR failed: %s", mcr_result_str(p_Mcr->result))); } if(!p_Mcr->querycgr.cgr.cstd_en) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tail Drop is not enabled!")); } p_Mcc = qm_mc_start(p_QmPortal->p_LowQmPortal); p_Mcc->initcgr.cgid = p_QmCg->id; p_Mcc->initcgr.we_mask |= QM_CGR_WE_CS_THRES; /* express thresh as ta*2^tn */ gap = (int)threshold; for (tmpA=0 ; tmpA<256; tmpA++ ) for (tmpN=0 ; tmpN<32; tmpN++ ) { tmp = ABS((int)(threshold - tmpA*(1<initcgr.cgr.cs_thres.TA = ta; p_Mcc->initcgr.cgr.cs_thres.Tn = tn; qm_mc_commit(p_QmPortal->p_LowQmPortal, QM_MCC_VERB_MODIFYCGR); while (!(p_Mcr = qm_mc_result(p_QmPortal->p_LowQmPortal))) ; ASSERT_COND((p_Mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_MODIFYCGR); if (p_Mcr->result != QM_MCR_RESULT_OK) { PUNLOCK(p_QmPortal); RETURN_ERROR(MINOR, E_INVALID_STATE, ("INITCGR failed: %s", mcr_result_str(p_Mcr->result))); } PUNLOCK(p_QmPortal); return E_OK; } Index: head/sys/contrib/ncsw/Peripherals/QM/qman_low.h =================================================================== --- head/sys/contrib/ncsw/Peripherals/QM/qman_low.h (revision 307541) +++ head/sys/contrib/ncsw/Peripherals/QM/qman_low.h (revision 307542) @@ -1,1148 +1,1148 @@ /****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File qman_low.c @Description QM Low-level implementation *//***************************************************************************/ #include "std_ext.h" #include "core_ext.h" #include "xx_ext.h" #include "error_ext.h" #include "qman_private.h" /***************************/ /* Portal register assists */ /***************************/ /* Cache-inhibited register offsets */ -#define REG_EQCR_PI_CINH (void *)0x0000 -#define REG_EQCR_CI_CINH (void *)0x0004 -#define REG_EQCR_ITR (void *)0x0008 -#define REG_DQRR_PI_CINH (void *)0x0040 -#define REG_DQRR_CI_CINH (void *)0x0044 -#define REG_DQRR_ITR (void *)0x0048 -#define REG_DQRR_DCAP (void *)0x0050 -#define REG_DQRR_SDQCR (void *)0x0054 -#define REG_DQRR_VDQCR (void *)0x0058 -#define REG_DQRR_PDQCR (void *)0x005c -#define REG_MR_PI_CINH (void *)0x0080 -#define REG_MR_CI_CINH (void *)0x0084 -#define REG_MR_ITR (void *)0x0088 -#define REG_CFG (void *)0x0100 -#define REG_ISR (void *)0x0e00 -#define REG_IER (void *)0x0e04 -#define REG_ISDR (void *)0x0e08 -#define REG_IIR (void *)0x0e0c -#define REG_ITPR (void *)0x0e14 +#define REG_EQCR_PI_CINH 0x0000 +#define REG_EQCR_CI_CINH 0x0004 +#define REG_EQCR_ITR 0x0008 +#define REG_DQRR_PI_CINH 0x0040 +#define REG_DQRR_CI_CINH 0x0044 +#define REG_DQRR_ITR 0x0048 +#define REG_DQRR_DCAP 0x0050 +#define REG_DQRR_SDQCR 0x0054 +#define REG_DQRR_VDQCR 0x0058 +#define REG_DQRR_PDQCR 0x005c +#define REG_MR_PI_CINH 0x0080 +#define REG_MR_CI_CINH 0x0084 +#define REG_MR_ITR 0x0088 +#define REG_CFG 0x0100 +#define REG_ISR 0x0e00 +#define REG_IER 0x0e04 +#define REG_ISDR 0x0e08 +#define REG_IIR 0x0e0c +#define REG_ITPR 0x0e14 /* Cache-enabled register offsets */ -#define CL_EQCR (void *)0x0000 -#define CL_DQRR (void *)0x1000 -#define CL_MR (void *)0x2000 -#define CL_EQCR_PI_CENA (void *)0x3000 -#define CL_EQCR_CI_CENA (void *)0x3100 -#define CL_DQRR_PI_CENA (void *)0x3200 -#define CL_DQRR_CI_CENA (void *)0x3300 -#define CL_MR_PI_CENA (void *)0x3400 -#define CL_MR_CI_CENA (void *)0x3500 -#define CL_RORI_CENA (void *)0x3600 -#define CL_CR (void *)0x3800 -#define CL_RR0 (void *)0x3900 -#define CL_RR1 (void *)0x3940 +#define CL_EQCR 0x0000 +#define CL_DQRR 0x1000 +#define CL_MR 0x2000 +#define CL_EQCR_PI_CENA 0x3000 +#define CL_EQCR_CI_CENA 0x3100 +#define CL_DQRR_PI_CENA 0x3200 +#define CL_DQRR_CI_CENA 0x3300 +#define CL_MR_PI_CENA 0x3400 +#define CL_MR_CI_CENA 0x3500 +#define CL_RORI_CENA 0x3600 +#define CL_CR 0x3800 +#define CL_RR0 0x3900 +#define CL_RR1 0x3940 -static __inline__ void *ptr_ADD(void *a, void *b) +static __inline__ void *ptr_ADD(void *a, uintptr_t b) { - return (void *)((uintptr_t)a + (uintptr_t)b); + return (void *)((uintptr_t)a + b); } /* The h/w design requires mappings to be size-aligned so that "add"s can be * reduced to "or"s. The primitives below do the same for s/w. */ /* Bitwise-OR two pointers */ -static __inline__ void *ptr_OR(void *a, void *b) +static __inline__ void *ptr_OR(void *a, uintptr_t b) { - return (void *)((uintptr_t)a + (uintptr_t)b); + return (void *)((uintptr_t)a + b); } /* Cache-inhibited register access */ -static __inline__ uint32_t __qm_in(struct qm_addr *qm, void *offset) +static __inline__ uint32_t __qm_in(struct qm_addr *qm, uintptr_t offset) { uint32_t *tmp = (uint32_t *)ptr_ADD(qm->addr_ci, offset); return GET_UINT32(*tmp); } -static __inline__ void __qm_out(struct qm_addr *qm, void *offset, uint32_t val) +static __inline__ void __qm_out(struct qm_addr *qm, uintptr_t offset, uint32_t val) { uint32_t *tmp = (uint32_t *)ptr_ADD(qm->addr_ci, offset); WRITE_UINT32(*tmp, val); } #define qm_in(reg) __qm_in(&portal->addr, REG_##reg) #define qm_out(reg, val) __qm_out(&portal->addr, REG_##reg, (uint32_t)val) /* Convert 'n' cachelines to a pointer value for bitwise OR */ -#define qm_cl(n) (void *)((n) << 6) +#define qm_cl(n) ((n) << 6) /* Cache-enabled (index) register access */ -static __inline__ void __qm_cl_touch_ro(struct qm_addr *qm, void *offset) +static __inline__ void __qm_cl_touch_ro(struct qm_addr *qm, uintptr_t offset) { dcbt_ro(ptr_ADD(qm->addr_ce, offset)); } -static __inline__ void __qm_cl_touch_rw(struct qm_addr *qm, void *offset) +static __inline__ void __qm_cl_touch_rw(struct qm_addr *qm, uintptr_t offset) { dcbt_rw(ptr_ADD(qm->addr_ce, offset)); } -static __inline__ uint32_t __qm_cl_in(struct qm_addr *qm, void *offset) +static __inline__ uint32_t __qm_cl_in(struct qm_addr *qm, uintptr_t offset) { uint32_t *tmp = (uint32_t *)ptr_ADD(qm->addr_ce, offset); return GET_UINT32(*tmp); } -static __inline__ void __qm_cl_out(struct qm_addr *qm, void *offset, uint32_t val) +static __inline__ void __qm_cl_out(struct qm_addr *qm, uintptr_t offset, uint32_t val) { uint32_t *tmp = (uint32_t *)ptr_ADD(qm->addr_ce, offset); WRITE_UINT32(*tmp, val); dcbf(tmp); } -static __inline__ void __qm_cl_invalidate(struct qm_addr *qm, void *offset) +static __inline__ void __qm_cl_invalidate(struct qm_addr *qm, uintptr_t offset) { dcbi(ptr_ADD(qm->addr_ce, offset)); } #define qm_cl_touch_ro(reg) __qm_cl_touch_ro(&portal->addr, CL_##reg##_CENA) #define qm_cl_touch_rw(reg) __qm_cl_touch_rw(&portal->addr, CL_##reg##_CENA) #define qm_cl_in(reg) __qm_cl_in(&portal->addr, CL_##reg##_CENA) #define qm_cl_out(reg, val) __qm_cl_out(&portal->addr, CL_##reg##_CENA, val) #define qm_cl_invalidate(reg) __qm_cl_invalidate(&portal->addr, CL_##reg##_CENA) /* Cyclic helper for rings. TODO: once we are able to do fine-grain perf * analysis, look at using the "extra" bit in the ring index registers to avoid * cyclic issues. */ static __inline__ uint8_t cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last) { /* 'first' is included, 'last' is excluded */ if (first <= last) return (uint8_t)(last - first); return (uint8_t)(ringsize + last - first); } static __inline__ t_Error __qm_portal_bind(struct qm_portal *portal, uint8_t iface) { t_Error ret = E_BUSY; if (!(portal->config.bound & iface)) { portal->config.bound |= iface; ret = E_OK; } return ret; } static __inline__ void __qm_portal_unbind(struct qm_portal *portal, uint8_t iface) { #ifdef QM_CHECKING ASSERT_COND(portal->config.bound & iface); #endif /* QM_CHECKING */ portal->config.bound &= ~iface; } /* ---------------- */ /* --- EQCR API --- */ /* It's safer to code in terms of the 'eqcr' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define EQCR_API_START() register struct qm_eqcr *eqcr = &portal->eqcr */ /* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ #define EQCR_CARRYCLEAR(p) \ (void *)((uintptr_t)(p) & (~(uintptr_t)(QM_EQCR_SIZE << 6))) /* Bit-wise logic to convert a ring pointer to a ring index */ static __inline__ uint8_t EQCR_PTR2IDX(struct qm_eqcr_entry *e) { - return (uint8_t)(((uint32_t)e >> 6) & (QM_EQCR_SIZE - 1)); + return (uint8_t)(((uintptr_t)e >> 6) & (QM_EQCR_SIZE - 1)); } /* Increment the 'cursor' ring pointer, taking 'vbit' into account */ static __inline__ void EQCR_INC(struct qm_eqcr *eqcr) { /* NB: this is odd-looking, but experiments show that it generates fast * code with essentially no branching overheads. We increment to the * next EQCR pointer and handle overflow and 'vbit'. */ struct qm_eqcr_entry *partial = eqcr->cursor + 1; eqcr->cursor = EQCR_CARRYCLEAR(partial); if (partial != eqcr->cursor) eqcr->vbit ^= QM_EQCR_VERB_VBIT; } static __inline__ t_Error qm_eqcr_init(struct qm_portal *portal, e_QmPortalProduceMode pmode, e_QmPortalEqcrConsumeMode cmode) { register struct qm_eqcr *eqcr = &portal->eqcr; uint32_t cfg; uint8_t pi; if (__qm_portal_bind(portal, QM_BIND_EQCR)) return ERROR_CODE(E_BUSY); eqcr->ring = ptr_ADD(portal->addr.addr_ce, CL_EQCR); eqcr->ci = (uint8_t)(qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1)); qm_cl_invalidate(EQCR_CI); pi = (uint8_t)(qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1)); eqcr->cursor = eqcr->ring + pi; eqcr->vbit = (uint8_t)((qm_in(EQCR_PI_CINH) & QM_EQCR_SIZE) ? QM_EQCR_VERB_VBIT : 0); eqcr->available = (uint8_t)(QM_EQCR_SIZE - 1 - cyc_diff(QM_EQCR_SIZE, eqcr->ci, pi)); eqcr->ithresh = (uint8_t)qm_in(EQCR_ITR); #ifdef QM_CHECKING eqcr->busy = 0; eqcr->pmode = pmode; eqcr->cmode = cmode; #else UNUSED(cmode); #endif /* QM_CHECKING */ cfg = (qm_in(CFG) & 0x00ffffff) | ((pmode & 0x3) << 24); /* QCSP_CFG::EPM */ qm_out(CFG, cfg); return 0; } static __inline__ void qm_eqcr_finish(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; uint8_t pi = (uint8_t)(qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1)); uint8_t ci = (uint8_t)(qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1)); #ifdef QM_CHECKING ASSERT_COND(!eqcr->busy); #endif /* QM_CHECKING */ if (pi != EQCR_PTR2IDX(eqcr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("losing uncommitted EQCR entries")); if (ci != eqcr->ci) REPORT_ERROR(WARNING, E_INVALID_STATE, ("missing existing EQCR completions")); if (eqcr->ci != EQCR_PTR2IDX(eqcr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("EQCR destroyed unquiesced")); __qm_portal_unbind(portal, QM_BIND_EQCR); } static __inline__ struct qm_eqcr_entry *qm_eqcr_start(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; #ifdef QM_CHECKING ASSERT_COND(!eqcr->busy); #endif /* QM_CHECKING */ if (!eqcr->available) return NULL; #ifdef QM_CHECKING eqcr->busy = 1; #endif /* QM_CHECKING */ dcbz_64(eqcr->cursor); return eqcr->cursor; } static __inline__ void qm_eqcr_abort(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_eqcr *eqcr = &portal->eqcr; ASSERT_COND(eqcr->busy); eqcr->busy = 0; #else UNUSED(portal); #endif /* QM_CHECKING */ } static __inline__ struct qm_eqcr_entry *qm_eqcr_pend_and_next(struct qm_portal *portal, uint8_t myverb) { register struct qm_eqcr *eqcr = &portal->eqcr; #ifdef QM_CHECKING ASSERT_COND(eqcr->busy); ASSERT_COND(eqcr->pmode != e_QmPortalPVB); #endif /* QM_CHECKING */ if (eqcr->available == 1) return NULL; eqcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | eqcr->vbit); dcbf_64(eqcr->cursor); EQCR_INC(eqcr); eqcr->available--; dcbz_64(eqcr->cursor); return eqcr->cursor; } #ifdef QM_CHECKING #define EQCR_COMMIT_CHECKS(eqcr) \ do { \ ASSERT_COND(eqcr->busy); \ ASSERT_COND(eqcr->cursor->orp == (eqcr->cursor->orp & 0x00ffffff)); \ ASSERT_COND(eqcr->cursor->fqid == (eqcr->cursor->fqid & 0x00ffffff)); \ } while(0) #else #define EQCR_COMMIT_CHECKS(eqcr) #endif /* QM_CHECKING */ static __inline__ void qmPortalEqcrPciCommit(struct qm_portal *portal, uint8_t myverb) { register struct qm_eqcr *eqcr = &portal->eqcr; #ifdef QM_CHECKING EQCR_COMMIT_CHECKS(eqcr); ASSERT_COND(eqcr->pmode == e_QmPortalPCI); #endif /* QM_CHECKING */ eqcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | eqcr->vbit); EQCR_INC(eqcr); eqcr->available--; dcbf_64(eqcr->cursor); hwsync(); qm_out(EQCR_PI_CINH, EQCR_PTR2IDX(eqcr->cursor)); #ifdef QM_CHECKING eqcr->busy = 0; #endif /* QM_CHECKING */ } static __inline__ void qmPortalEqcrPcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_eqcr *eqcr = &portal->eqcr; ASSERT_COND(eqcr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ qm_cl_invalidate(EQCR_PI); qm_cl_touch_rw(EQCR_PI); } static __inline__ void qmPortalEqcrPceCommit(struct qm_portal *portal, uint8_t myverb) { register struct qm_eqcr *eqcr = &portal->eqcr; #ifdef QM_CHECKING EQCR_COMMIT_CHECKS(eqcr); ASSERT_COND(eqcr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ eqcr->cursor->__dont_write_directly__verb = (uint8_t)(myverb | eqcr->vbit); EQCR_INC(eqcr); eqcr->available--; dcbf_64(eqcr->cursor); lwsync(); qm_cl_out(EQCR_PI, EQCR_PTR2IDX(eqcr->cursor)); #ifdef QM_CHECKING eqcr->busy = 0; #endif /* QM_CHECKING */ } static __inline__ void qmPortalEqcrPvbCommit(struct qm_portal *portal, uint8_t myverb) { register struct qm_eqcr *eqcr = &portal->eqcr; struct qm_eqcr_entry *eqcursor; #ifdef QM_CHECKING EQCR_COMMIT_CHECKS(eqcr); ASSERT_COND(eqcr->pmode == e_QmPortalPVB); #endif /* QM_CHECKING */ lwsync(); eqcursor = eqcr->cursor; eqcursor->__dont_write_directly__verb = (uint8_t)(myverb | eqcr->vbit); dcbf_64(eqcursor); EQCR_INC(eqcr); eqcr->available--; #ifdef QM_CHECKING eqcr->busy = 0; #endif /* QM_CHECKING */ } static __inline__ uint8_t qmPortalEqcrCciUpdate(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; uint8_t diff, old_ci = eqcr->ci; #ifdef QM_CHECKING ASSERT_COND(eqcr->cmode == e_QmPortalEqcrCCI); #endif /* QM_CHECKING */ eqcr->ci = (uint8_t)(qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1)); diff = cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); eqcr->available += diff; return diff; } static __inline__ void qmPortalEqcrCcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_eqcr *eqcr = &portal->eqcr; ASSERT_COND(eqcr->cmode == e_QmPortalEqcrCCE); #endif /* QM_CHECKING */ qm_cl_touch_ro(EQCR_CI); } static __inline__ uint8_t qmPortalEqcrCceUpdate(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; uint8_t diff, old_ci = eqcr->ci; #ifdef QM_CHECKING ASSERT_COND(eqcr->cmode == e_QmPortalEqcrCCE); #endif /* QM_CHECKING */ eqcr->ci = (uint8_t)(qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1)); qm_cl_invalidate(EQCR_CI); diff = cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); eqcr->available += diff; return diff; } static __inline__ uint8_t qm_eqcr_get_ithresh(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; return eqcr->ithresh; } static __inline__ void qm_eqcr_set_ithresh(struct qm_portal *portal, uint8_t ithresh) { register struct qm_eqcr *eqcr = &portal->eqcr; eqcr->ithresh = ithresh; qm_out(EQCR_ITR, ithresh); } static __inline__ uint8_t qm_eqcr_get_avail(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; return eqcr->available; } static __inline__ uint8_t qm_eqcr_get_fill(struct qm_portal *portal) { register struct qm_eqcr *eqcr = &portal->eqcr; return (uint8_t)(QM_EQCR_SIZE - 1 - eqcr->available); } /* ---------------- */ /* --- DQRR API --- */ /* TODO: many possible improvements; * - look at changing the API to use pointer rather than index parameters now * that 'cursor' is a pointer, * - consider moving other parameters to pointer if it could help (ci) */ /* It's safer to code in terms of the 'dqrr' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define DQRR_API_START() register struct qm_dqrr *dqrr = &portal->dqrr */ #define DQRR_CARRYCLEAR(p) \ (void *)((uintptr_t)(p) & (~(uintptr_t)(QM_DQRR_SIZE << 6))) static __inline__ uint8_t DQRR_PTR2IDX(struct qm_dqrr_entry *e) { - return (uint8_t)(((uint32_t)e >> 6) & (QM_DQRR_SIZE - 1)); + return (uint8_t)(((uintptr_t)e >> 6) & (QM_DQRR_SIZE - 1)); } static __inline__ struct qm_dqrr_entry *DQRR_INC(struct qm_dqrr_entry *e) { return DQRR_CARRYCLEAR(e + 1); } static __inline__ void qm_dqrr_set_maxfill(struct qm_portal *portal, uint8_t mf) { qm_out(CFG, (qm_in(CFG) & 0xff0fffff) | ((mf & (QM_DQRR_SIZE - 1)) << 20)); } static __inline__ t_Error qm_dqrr_init(struct qm_portal *portal, e_QmPortalDequeueMode dmode, e_QmPortalProduceMode pmode, e_QmPortalDqrrConsumeMode cmode, uint8_t max_fill, int stash_ring, int stash_data) { register struct qm_dqrr *dqrr = &portal->dqrr; const struct qm_portal_config *config = &portal->config; uint32_t cfg; if (__qm_portal_bind(portal, QM_BIND_DQRR)) return ERROR_CODE(E_BUSY); if ((stash_ring || stash_data) && (config->cpu == -1)) return ERROR_CODE(E_INVALID_STATE); /* Make sure the DQRR will be idle when we enable */ qm_out(DQRR_SDQCR, 0); qm_out(DQRR_VDQCR, 0); qm_out(DQRR_PDQCR, 0); dqrr->ring = ptr_ADD(portal->addr.addr_ce, CL_DQRR); dqrr->pi = (uint8_t)(qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1)); dqrr->ci = (uint8_t)(qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1)); dqrr->cursor = dqrr->ring + dqrr->ci; dqrr->fill = cyc_diff(QM_DQRR_SIZE, dqrr->ci, dqrr->pi); dqrr->vbit = (uint8_t)((qm_in(DQRR_PI_CINH) & QM_DQRR_SIZE) ? QM_DQRR_VERB_VBIT : 0); dqrr->ithresh = (uint8_t)qm_in(DQRR_ITR); #ifdef QM_CHECKING dqrr->dmode = dmode; dqrr->pmode = pmode; dqrr->cmode = cmode; dqrr->flags = 0; if (stash_ring) dqrr->flags |= QM_DQRR_FLAG_RE; if (stash_data) dqrr->flags |= QM_DQRR_FLAG_SE; #else UNUSED(pmode); #endif /* QM_CHECKING */ cfg = (qm_in(CFG) & 0xff000f00) | ((max_fill & (QM_DQRR_SIZE - 1)) << 20) | /* DQRR_MF */ ((dmode & 1) << 18) | /* DP */ ((cmode & 3) << 16) | /* DCM */ (stash_ring ? 0x80 : 0) | /* RE */ (0 ? 0x40 : 0) | /* Ignore RP */ (stash_data ? 0x20 : 0) | /* SE */ (0 ? 0x10 : 0); /* Ignore SP */ qm_out(CFG, cfg); return E_OK; } static __inline__ void qm_dqrr_finish(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; if (dqrr->ci != DQRR_PTR2IDX(dqrr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("Ignoring completed DQRR entries")); __qm_portal_unbind(portal, QM_BIND_DQRR); } static __inline__ struct qm_dqrr_entry *qm_dqrr_current(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; if (!dqrr->fill) return NULL; return dqrr->cursor; } static __inline__ uint8_t qm_dqrr_cursor(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; return DQRR_PTR2IDX(dqrr->cursor); } static __inline__ uint8_t qm_dqrr_next(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->fill); #endif dqrr->cursor = DQRR_INC(dqrr->cursor); return --dqrr->fill; } static __inline__ uint8_t qmPortalDqrrPciUpdate(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; uint8_t diff, old_pi = dqrr->pi; #ifdef QM_CHECKING ASSERT_COND(dqrr->pmode == e_QmPortalPCI); #endif /* QM_CHECKING */ dqrr->pi = (uint8_t)(qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1)); diff = cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); dqrr->fill += diff; return diff; } static __inline__ void qmPortalDqrrPcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ qm_cl_invalidate(DQRR_PI); qm_cl_touch_ro(DQRR_PI); } static __inline__ uint8_t qmPortalDqrrPceUpdate(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; uint8_t diff, old_pi = dqrr->pi; #ifdef QM_CHECKING ASSERT_COND(dqrr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ dqrr->pi = (uint8_t)(qm_cl_in(DQRR_PI) & (QM_DQRR_SIZE - 1)); diff = cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); dqrr->fill += diff; return diff; } static __inline__ void qmPortalDqrrPvbPrefetch(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->pmode == e_QmPortalPVB); /* If ring entries get stashed, don't invalidate/prefetch */ if (!(dqrr->flags & QM_DQRR_FLAG_RE)) #endif /*QM_CHECKING */ dcbit_ro(ptr_ADD(dqrr->ring, qm_cl(dqrr->pi))); } static __inline__ uint8_t qmPortalDqrrPvbUpdate(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; struct qm_dqrr_entry *res = ptr_ADD(dqrr->ring, qm_cl(dqrr->pi)); #ifdef QM_CHECKING ASSERT_COND(dqrr->pmode == e_QmPortalPVB); #endif /* QM_CHECKING */ if ((res->verb & QM_DQRR_VERB_VBIT) == dqrr->vbit) { dqrr->pi = (uint8_t)((dqrr->pi + 1) & (QM_DQRR_SIZE - 1)); if (!dqrr->pi) dqrr->vbit ^= QM_DQRR_VERB_VBIT; dqrr->fill++; return 1; } return 0; } static __inline__ void qmPortalDqrrCciConsume(struct qm_portal *portal, uint8_t num) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode == e_QmPortalDqrrCCI); #endif /* QM_CHECKING */ dqrr->ci = (uint8_t)((dqrr->ci + num) & (QM_DQRR_SIZE - 1)); qm_out(DQRR_CI_CINH, dqrr->ci); } static __inline__ void qmPortalDqrrCciConsumeToCurrent(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode == e_QmPortalDqrrCCI); #endif /* QM_CHECKING */ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); qm_out(DQRR_CI_CINH, dqrr->ci); } static __inline__ void qmPortalDqrrCcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrCCE); #endif /* QM_CHECKING */ qm_cl_invalidate(DQRR_CI); qm_cl_touch_rw(DQRR_CI); } static __inline__ void qmPortalDqrrCceConsume(struct qm_portal *portal, uint8_t num) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode == e_QmPortalDqrrCCE); #endif /* QM_CHECKING */ dqrr->ci = (uint8_t)((dqrr->ci + num) & (QM_DQRR_SIZE - 1)); qm_cl_out(DQRR_CI, dqrr->ci); } static __inline__ void qmPortalDqrrCceConsume_to_current(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode == e_QmPortalDqrrCCE); #endif /* QM_CHECKING */ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); qm_cl_out(DQRR_CI, dqrr->ci); } static __inline__ void qmPortalDqrrDcaConsume1(struct qm_portal *portal, uint8_t idx, bool park) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ ASSERT_COND(idx < QM_DQRR_SIZE); qm_out(DQRR_DCAP, (0 << 8) | /* S */ ((uint32_t)(park ? 1 : 0) << 6) | /* PK */ idx); /* DCAP_CI */ } static __inline__ void qmPortalDqrrDcaConsume1ptr(struct qm_portal *portal, struct qm_dqrr_entry *dq, bool park) { uint8_t idx = DQRR_PTR2IDX(dq); #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); ASSERT_COND((dqrr->ring + idx) == dq); ASSERT_COND(idx < QM_DQRR_SIZE); #endif /* QM_CHECKING */ qm_out(DQRR_DCAP, (0 << 8) | /* DQRR_DCAP::S */ ((uint32_t)(park ? 1 : 0) << 6) | /* DQRR_DCAP::PK */ idx); /* DQRR_DCAP::DCAP_CI */ } static __inline__ void qmPortalDqrrDcaConsumeN(struct qm_portal *portal, uint16_t bitmask) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ qm_out(DQRR_DCAP, (1 << 8) | /* DQRR_DCAP::S */ ((uint32_t)bitmask << 16)); /* DQRR_DCAP::DCAP_CI */ } static __inline__ uint8_t qmPortalDqrrDcaCci(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ return (uint8_t)(qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1)); } static __inline__ void qmPortalDqrrDcaCcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ qm_cl_invalidate(DQRR_CI); qm_cl_touch_ro(DQRR_CI); } static __inline__ uint8_t qmPortalDqrrDcaCce(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode == e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ return (uint8_t)(qm_cl_in(DQRR_CI) & (QM_DQRR_SIZE - 1)); } static __inline__ uint8_t qm_dqrr_get_ci(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode != e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ return dqrr->ci; } static __inline__ void qm_dqrr_park(struct qm_portal *portal, uint8_t idx) { #ifdef QM_CHECKING register struct qm_dqrr *dqrr = &portal->dqrr; ASSERT_COND(dqrr->cmode != e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ qm_out(DQRR_DCAP, (0 << 8) | /* S */ (uint32_t)(1 << 6) | /* PK */ (idx & (QM_DQRR_SIZE - 1))); /* DCAP_CI */ } static __inline__ void qm_dqrr_park_ci(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; #ifdef QM_CHECKING ASSERT_COND(dqrr->cmode != e_QmPortalDqrrDCA); #endif /* QM_CHECKING */ qm_out(DQRR_DCAP, (0 << 8) | /* S */ (uint32_t)(1 << 6) | /* PK */ (dqrr->ci & (QM_DQRR_SIZE - 1)));/* DCAP_CI */ } static __inline__ void qm_dqrr_sdqcr_set(struct qm_portal *portal, uint32_t sdqcr) { qm_out(DQRR_SDQCR, sdqcr); } static __inline__ uint32_t qm_dqrr_sdqcr_get(struct qm_portal *portal) { return qm_in(DQRR_SDQCR); } static __inline__ void qm_dqrr_vdqcr_set(struct qm_portal *portal, uint32_t vdqcr) { qm_out(DQRR_VDQCR, vdqcr); } static __inline__ uint32_t qm_dqrr_vdqcr_get(struct qm_portal *portal) { return qm_in(DQRR_VDQCR); } static __inline__ void qm_dqrr_pdqcr_set(struct qm_portal *portal, uint32_t pdqcr) { qm_out(DQRR_PDQCR, pdqcr); } static __inline__ uint32_t qm_dqrr_pdqcr_get(struct qm_portal *portal) { return qm_in(DQRR_PDQCR); } static __inline__ uint8_t qm_dqrr_get_ithresh(struct qm_portal *portal) { register struct qm_dqrr *dqrr = &portal->dqrr; return dqrr->ithresh; } static __inline__ void qm_dqrr_set_ithresh(struct qm_portal *portal, uint8_t ithresh) { qm_out(DQRR_ITR, ithresh); } static __inline__ uint8_t qm_dqrr_get_maxfill(struct qm_portal *portal) { return (uint8_t)((qm_in(CFG) & 0x00f00000) >> 20); } /* -------------- */ /* --- MR API --- */ /* It's safer to code in terms of the 'mr' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define MR_API_START() register struct qm_mr *mr = &portal->mr */ #define MR_CARRYCLEAR(p) \ (void *)((uintptr_t)(p) & (~(uintptr_t)(QM_MR_SIZE << 6))) static __inline__ uint8_t MR_PTR2IDX(struct qm_mr_entry *e) { - return (uint8_t)(((uint32_t)e >> 6) & (QM_MR_SIZE - 1)); + return (uint8_t)(((uintptr_t)e >> 6) & (QM_MR_SIZE - 1)); } static __inline__ struct qm_mr_entry *MR_INC(struct qm_mr_entry *e) { return MR_CARRYCLEAR(e + 1); } static __inline__ t_Error qm_mr_init(struct qm_portal *portal, e_QmPortalProduceMode pmode, e_QmPortalMrConsumeMode cmode) { register struct qm_mr *mr = &portal->mr; uint32_t cfg; if (__qm_portal_bind(portal, QM_BIND_MR)) return ERROR_CODE(E_BUSY); mr->ring = ptr_ADD(portal->addr.addr_ce, CL_MR); mr->pi = (uint8_t)(qm_in(MR_PI_CINH) & (QM_MR_SIZE - 1)); mr->ci = (uint8_t)(qm_in(MR_CI_CINH) & (QM_MR_SIZE - 1)); mr->cursor = mr->ring + mr->ci; mr->fill = cyc_diff(QM_MR_SIZE, mr->ci, mr->pi); mr->vbit = (uint8_t)((qm_in(MR_PI_CINH) & QM_MR_SIZE) ?QM_MR_VERB_VBIT : 0); mr->ithresh = (uint8_t)qm_in(MR_ITR); #ifdef QM_CHECKING mr->pmode = pmode; mr->cmode = cmode; #else UNUSED(pmode); #endif /* QM_CHECKING */ cfg = (qm_in(CFG) & 0xfffff0ff) | ((cmode & 1) << 8); /* QCSP_CFG:MM */ qm_out(CFG, cfg); return E_OK; } static __inline__ void qm_mr_finish(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; if (mr->ci != MR_PTR2IDX(mr->cursor)) REPORT_ERROR(WARNING, E_INVALID_STATE, ("Ignoring completed MR entries")); __qm_portal_unbind(portal, QM_BIND_MR); } static __inline__ void qm_mr_current_prefetch(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; dcbt_ro(mr->cursor); } static __inline__ struct qm_mr_entry *qm_mr_current(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; if (!mr->fill) return NULL; return mr->cursor; } static __inline__ uint8_t qm_mr_cursor(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; return MR_PTR2IDX(mr->cursor); } static __inline__ uint8_t qm_mr_next(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; #ifdef QM_CHECKING ASSERT_COND(mr->fill); #endif /* QM_CHECKING */ mr->cursor = MR_INC(mr->cursor); return --mr->fill; } static __inline__ uint8_t qmPortalMrPciUpdate(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; uint8_t diff, old_pi = mr->pi; #ifdef QM_CHECKING ASSERT_COND(mr->pmode == e_QmPortalPCI); #endif /* QM_CHECKING */ mr->pi = (uint8_t)qm_in(MR_PI_CINH); diff = cyc_diff(QM_MR_SIZE, old_pi, mr->pi); mr->fill += diff; return diff; } static __inline__ void qmPortalMrPcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_mr *mr = &portal->mr; ASSERT_COND(mr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ qm_cl_invalidate(MR_PI); qm_cl_touch_ro(MR_PI); } static __inline__ uint8_t qmPortalMrPceUpdate(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; uint8_t diff, old_pi = mr->pi; #ifdef QM_CHECKING ASSERT_COND(mr->pmode == e_QmPortalPCE); #endif /* QM_CHECKING */ mr->pi = (uint8_t)(qm_cl_in(MR_PI) & (QM_MR_SIZE - 1)); diff = cyc_diff(QM_MR_SIZE, old_pi, mr->pi); mr->fill += diff; return diff; } static __inline__ void qmPortalMrPvbUpdate(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; struct qm_mr_entry *res = ptr_ADD(mr->ring, qm_cl(mr->pi)); #ifdef QM_CHECKING ASSERT_COND(mr->pmode == e_QmPortalPVB); #endif /* QM_CHECKING */ dcbit_ro(ptr_ADD(mr->ring, qm_cl(mr->pi))); if ((res->verb & QM_MR_VERB_VBIT) == mr->vbit) { mr->pi = (uint8_t)((mr->pi + 1) & (QM_MR_SIZE - 1)); if (!mr->pi) mr->vbit ^= QM_MR_VERB_VBIT; mr->fill++; } } static __inline__ void qmPortalMrCciConsume(struct qm_portal *portal, uint8_t num) { register struct qm_mr *mr = &portal->mr; #ifdef QM_CHECKING ASSERT_COND(mr->cmode == e_QmPortalMrCCI); #endif /* QM_CHECKING */ mr->ci = (uint8_t)((mr->ci + num) & (QM_MR_SIZE - 1)); qm_out(MR_CI_CINH, mr->ci); } static __inline__ void qmPortalMrCciConsumeToCurrent(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; #ifdef QM_CHECKING ASSERT_COND(mr->cmode == e_QmPortalMrCCI); #endif /* QM_CHECKING */ mr->ci = MR_PTR2IDX(mr->cursor); qm_out(MR_CI_CINH, mr->ci); } static __inline__ void qmPortalMrCcePrefetch(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_mr *mr = &portal->mr; ASSERT_COND(mr->cmode == e_QmPortalMrCCE); #endif /* QM_CHECKING */ qm_cl_invalidate(MR_CI); qm_cl_touch_rw(MR_CI); } static __inline__ void qmPortalMrCceConsume(struct qm_portal *portal, uint8_t num) { register struct qm_mr *mr = &portal->mr; #ifdef QM_CHECKING ASSERT_COND(mr->cmode == e_QmPortalMrCCE); #endif /* QM_CHECKING */ mr->ci = (uint8_t)((mr->ci + num) & (QM_MR_SIZE - 1)); qm_cl_out(MR_CI, mr->ci); } static __inline__ void qmPortalMrCceConsumeToCurrent(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; #ifdef QM_CHECKING ASSERT_COND(mr->cmode == e_QmPortalMrCCE); #endif /* QM_CHECKING */ mr->ci = MR_PTR2IDX(mr->cursor); qm_cl_out(MR_CI, mr->ci); } static __inline__ uint8_t qm_mr_get_ci(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; return mr->ci; } static __inline__ uint8_t qm_mr_get_ithresh(struct qm_portal *portal) { register struct qm_mr *mr = &portal->mr; return mr->ithresh; } static __inline__ void qm_mr_set_ithresh(struct qm_portal *portal, uint8_t ithresh) { qm_out(MR_ITR, ithresh); } /* ------------------------------ */ /* --- Management command API --- */ /* It's safer to code in terms of the 'mc' object than the 'portal' object, * because the latter runs the risk of copy-n-paste errors from other code where * we could manipulate some other structure within 'portal'. */ /* #define MC_API_START() register struct qm_mc *mc = &portal->mc */ static __inline__ t_Error qm_mc_init(struct qm_portal *portal) { register struct qm_mc *mc = &portal->mc; if (__qm_portal_bind(portal, QM_BIND_MC)) return ERROR_CODE(E_BUSY); mc->cr = ptr_ADD(portal->addr.addr_ce, CL_CR); mc->rr = ptr_ADD(portal->addr.addr_ce, CL_RR0); mc->rridx = (uint8_t)((mc->cr->__dont_write_directly__verb & QM_MCC_VERB_VBIT) ? 0 : 1); mc->vbit = (uint8_t)(mc->rridx ? QM_MCC_VERB_VBIT : 0); #ifdef QM_CHECKING mc->state = mc_idle; #endif /* QM_CHECKING */ return E_OK; } static __inline__ void qm_mc_finish(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_idle); if (mc->state != mc_idle) REPORT_ERROR(WARNING, E_INVALID_STATE, ("Losing incomplete MC command")); #endif /* QM_CHECKING */ __qm_portal_unbind(portal, QM_BIND_MC); } static __inline__ struct qm_mc_command *qm_mc_start(struct qm_portal *portal) { register struct qm_mc *mc = &portal->mc; #ifdef QM_CHECKING ASSERT_COND(mc->state == mc_idle); mc->state = mc_user; #endif /* QM_CHECKING */ dcbz_64(mc->cr); return mc->cr; } static __inline__ void qm_mc_abort(struct qm_portal *portal) { #ifdef QM_CHECKING register struct qm_mc *mc = &portal->mc; ASSERT_COND(mc->state == mc_user); mc->state = mc_idle; #else UNUSED(portal); #endif /* QM_CHECKING */ } static __inline__ void qm_mc_commit(struct qm_portal *portal, uint8_t myverb) { register struct qm_mc *mc = &portal->mc; #ifdef QM_CHECKING ASSERT_COND(mc->state == mc_user); #endif /* QM_CHECKING */ lwsync(); mc->cr->__dont_write_directly__verb = (uint8_t)(myverb | mc->vbit); dcbf_64(mc->cr); dcbit_ro(mc->rr + mc->rridx); #ifdef QM_CHECKING mc->state = mc_hw; #endif /* QM_CHECKING */ } static __inline__ struct qm_mc_result *qm_mc_result(struct qm_portal *portal) { register struct qm_mc *mc = &portal->mc; struct qm_mc_result *rr = mc->rr + mc->rridx; #ifdef QM_CHECKING ASSERT_COND(mc->state == mc_hw); #endif /* QM_CHECKING */ /* The inactive response register's verb byte always returns zero until * its command is submitted and completed. This includes the valid-bit, * in case you were wondering... */ if (!rr->verb) { dcbit_ro(rr); return NULL; } mc->rridx ^= 1; mc->vbit ^= QM_MCC_VERB_VBIT; #ifdef QM_CHECKING mc->state = mc_idle; #endif /* QM_CHECKING */ return rr; } /* ------------------------------------- */ /* --- Portal interrupt register API --- */ static __inline__ t_Error qm_isr_init(struct qm_portal *portal) { if (__qm_portal_bind(portal, QM_BIND_ISR)) return ERROR_CODE(E_BUSY); return E_OK; } static __inline__ void qm_isr_finish(struct qm_portal *portal) { __qm_portal_unbind(portal, QM_BIND_ISR); } static __inline__ void qm_isr_set_iperiod(struct qm_portal *portal, uint16_t iperiod) { qm_out(ITPR, iperiod); } static __inline__ uint32_t __qm_isr_read(struct qm_portal *portal, enum qm_isr_reg n) { - return __qm_in(&portal->addr, PTR_MOVE(REG_ISR, (n << 2))); + return __qm_in(&portal->addr, REG_ISR + (n << 2)); } static __inline__ void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n, uint32_t val) { - __qm_out(&portal->addr, PTR_MOVE(REG_ISR, (n << 2)), val); + __qm_out(&portal->addr, REG_ISR + (n << 2), val); } Index: head/sys/contrib/ncsw/inc/Peripherals/bm_ext.h =================================================================== --- head/sys/contrib/ncsw/inc/Peripherals/bm_ext.h (revision 307541) +++ head/sys/contrib/ncsw/inc/Peripherals/bm_ext.h (revision 307542) @@ -1,688 +1,688 @@ /****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File bm_ext.h @Description BM API *//***************************************************************************/ #ifndef __BM_EXT_H #define __BM_EXT_H #include "error_ext.h" #include "std_ext.h" /**************************************************************************//** @Group BM_grp Buffer Manager API @Description BM API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description This callback type is used when handling pool depletion entry/exit. User provides this function. Driver invokes it. @Param[in] h_App - User's application descriptor. @Param[in] in - TRUE when entered depletion state FALSE when exit the depletion state. *//***************************************************************************/ typedef void (t_BmDepletionCallback)(t_Handle h_App, bool in); /**************************************************************************//** @Group BM_lib_grp BM common API @Description BM common API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description BM Exceptions *//***************************************************************************/ typedef enum e_BmExceptions { e_BM_EX_INVALID_COMMAND = 0 , /**< Invalid Command Verb Interrupt */ e_BM_EX_FBPR_THRESHOLD, /**< FBPR Low Watermark Interrupt. */ e_BM_EX_SINGLE_ECC, /**< Single Bit ECC Error Interrupt. */ e_BM_EX_MULTI_ECC /**< Multi Bit ECC Error Interrupt */ } e_BmExceptions; /**************************************************************************//** @Group BM_init_grp BM (common) Initialization Unit @Description BM (common) Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Function t_BmExceptionsCallback @Description Exceptions user callback routine, will be called upon an exception passing the exception identification. @Param[in] h_App - User's application descriptor. @Param[in] exception - The exception. *//***************************************************************************/ typedef void (t_BmExceptionsCallback) (t_Handle h_App, e_BmExceptions exception); /**************************************************************************//** @Description structure representing BM initialization parameters *//***************************************************************************/ typedef struct { uint8_t guestId; /**< BM Partition Id */ uintptr_t baseAddress; /**< Bm base address (virtual). NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ uint16_t liodn; /**< This value is attached to every transaction initiated by BMan when accessing its private data structures NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ uint32_t totalNumOfBuffers; /**< Total number of buffers NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ uint32_t fbprMemPartitionId; /**< FBPR's mem partition id; NOTE: The memory partition must be non-cacheable and no-coherent area. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ t_BmExceptionsCallback *f_Exception; /**< An application callback routine to handle exceptions. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ t_Handle h_App; /**< A handle to an application layer object; This handle will be passed by the driver upon calling the above callbacks. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ - int errIrq; /**< BM error interrupt line; NO_IRQ if interrupts not used. + uintptr_t errIrq; /**< BM error interrupt line; NO_IRQ if interrupts not used. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ uint8_t partBpidBase; /**< The first buffer-pool-id dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ uint8_t partNumOfPools; /**< Number of Pools dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ } t_BmParam; /**************************************************************************//** @Function BM_Config @Description Creates descriptor for the BM module and initializes the BM module. The routine returns a handle (descriptor) to the BM object. This descriptor must be passed as first parameter to all other BM function calls. @Param[in] p_BmParam - A pointer to data structure of parameters @Return Handle to BM object, or NULL for Failure. *//***************************************************************************/ t_Handle BM_Config(t_BmParam *p_BmParam); /**************************************************************************//** @Function BM_Init @Description Initializes the BM module @Param[in] h_Bm - A handle to the BM module @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_Config(). *//***************************************************************************/ t_Error BM_Init(t_Handle h_Bm); /**************************************************************************//** @Function BM_Free @Description Frees all resources that were assigned to BM module. Calling this routine invalidates the descriptor. @Param[in] h_Bm - A handle to the BM module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_Free(t_Handle h_Bm); /**************************************************************************//** @Group BM_advanced_init_grp BM (common) Advanced Configuration Unit @Description Configuration functions used to change default values. @{ *//***************************************************************************/ /**************************************************************************//** @Function BM_ConfigFbprThreshold @Description Change the fbpr threshold from its default configuration [0]. An interrupt if enables is asserted when the number of FBPRs is below this threshold. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). @Param[in] h_Bm - A handle to the BM module @Param[in] threshold - threshold value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_Config() and before BM_Init(). *//***************************************************************************/ t_Error BM_ConfigFbprThreshold(t_Handle h_Bm, uint32_t threshold); /** @} */ /* end of BM_advanced_init_grp group */ /** @} */ /* end of BM_init_grp group */ /**************************************************************************//** @Group BM_runtime_control_grp BM (common) Runtime Control Unit @Description BM (common) Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description enum for defining BM counters *//***************************************************************************/ typedef enum e_BmCounters { e_BM_COUNTERS_FBPR = 0 /**< Total Free Buffer Proxy Record (FBPR) Free Pool Count in external memory */ } e_BmCounters; /**************************************************************************//** @Description structure for returning revision information *//***************************************************************************/ typedef struct t_BmRevisionInfo { uint8_t majorRev; /**< Major revision */ uint8_t minorRev; /**< Minor revision */ } t_BmRevisionInfo; #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) /**************************************************************************//** @Function BM_DumpRegs @Description Dumps all BM registers NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). @Param[in] h_Bm A handle to an BM Module. @Return E_OK on success; @Cautions Allowed only after BM_Init(). *//***************************************************************************/ t_Error BM_DumpRegs(t_Handle h_Bm); #endif /* (defined(DEBUG_ERRORS) && ... */ /**************************************************************************//** @Function BM_SetException @Description Calling this routine enables/disables the specified exception. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). @Param[in] h_Bm - A handle to the BM Module. @Param[in] exception - The exception to be selected. @Param[in] enable - TRUE to enable interrupt, FALSE to mask it. @Cautions Allowed only following BM_Init(). *//***************************************************************************/ t_Error BM_SetException(t_Handle h_Bm, e_BmExceptions exception, bool enable); /**************************************************************************//** @Function BM_ErrorIsr @Description BM interrupt-service-routine for errors. NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). @Param[in] h_Bm - A handle to the BM Module. @Cautions Allowed only following BM_Init(). *//***************************************************************************/ void BM_ErrorIsr(t_Handle h_Bm); /**************************************************************************//** @Function BM_GetCounter @Description Reads one of the BM counters. @Param[in] h_Bm - A handle to the BM Module. @Param[in] counter - The requested counter. @Return Counter's current value. *//***************************************************************************/ uint32_t BM_GetCounter(t_Handle h_Bm, e_BmCounters counter); /**************************************************************************//** @Function BM_GetRevision @Description Returns the BM revision @Param[in] h_Bm A handle to a BM Module. @Param[out] p_BmRevisionInfo A structure of revision information parameters. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init(). *//***************************************************************************/ t_Error BM_GetRevision(t_Handle h_Bm, t_BmRevisionInfo *p_BmRevisionInfo); /** @} */ /* end of BM_runtime_control_grp group */ /** @} */ /* end of BM_lib_grp group */ /**************************************************************************//** @Group BM_portal_grp BM-Portal API @Description BM-Portal API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group BM_portal_init_grp BM-Portal Initialization Unit @Description BM-Portal Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing BM Portal initialization parameters *//***************************************************************************/ typedef struct { uintptr_t ceBaseAddress; /**< Cache-enabled base address (virtual) */ uintptr_t ciBaseAddress; /**< Cache-inhibited base address (virtual) */ t_Handle h_Bm; /**< Bm Handle */ e_DpaaSwPortal swPortalId; /**< Portal id */ int irq; /**< portal interrupt line; NO_IRQ if interrupts not used */ } t_BmPortalParam; /**************************************************************************//** @Function BM_PORTAL_Config @Description Creates descriptor for the BM Portal; The routine returns a handle (descriptor) to a BM-Portal object; This descriptor must be passed as first parameter to all other BM-Portal function calls. No actual initialization or configuration of QM-Portal hardware is done by this routine. @Param[in] p_BmPortalParam - Pointer to data structure of parameters @Retval Handle to a BM-Portal object, or NULL for Failure. *//***************************************************************************/ t_Handle BM_PORTAL_Config(t_BmPortalParam *p_BmPortalParam); /**************************************************************************//** @Function BM_PORTAL_Init @Description Initializes a BM-Portal module @Param[in] h_BmPortal - A handle to a BM-Portal module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_PORTAL_Init(t_Handle h_BmPortal); /**************************************************************************//** @Function BM_PortalFree @Description Frees all resources that were assigned to BM Portal module. Calling this routine invalidates the descriptor. @Param[in] h_BmPortal - BM Portal module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_PORTAL_Free(t_Handle h_BmPortal); /**************************************************************************//** @Function BM_PORTAL_ConfigMemAttr @Description Change the memory attributes from its default configuration [MEMORY_ATTR_CACHEABLE]. @Param[in] h_BmPortal - A handle to a BM-Portal module @Param[in] hwExtStructsMemAttr - memory attributes (cache/non-cache, etc.) @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_PORTAL_Config() and before BM_PORTAL_Init(). *//***************************************************************************/ t_Error BM_PORTAL_ConfigMemAttr(t_Handle h_BmPortal, uint32_t hwExtStructsMemAttr); /** @} */ /* end of BM_portal_init_grp group */ /** @} */ /* end of BM_portal_grp group */ /**************************************************************************//** @Group BM_pool_grp BM-Pool API @Description BM-Pool API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group BM_pool_init_grp BM-Pool Initialization Unit @Description BM-Pool Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Collection BM Pool Depletion Thresholds macros The thresholds are represent by an array of size MAX_DEPLETION_THRESHOLDS Use the following macros to access the appropriate location in the array. *//***************************************************************************/ #define BM_POOL_DEP_THRESH_SW_ENTRY 0 #define BM_POOL_DEP_THRESH_SW_EXIT 1 #define BM_POOL_DEP_THRESH_HW_ENTRY 2 #define BM_POOL_DEP_THRESH_HW_EXIT 3 #define MAX_DEPLETION_THRESHOLDS 4 /* @} */ /**************************************************************************//** @Description structure representing BM Pool initialization parameters *//***************************************************************************/ typedef struct { t_Handle h_Bm; /**< A handle to a BM Module. */ t_Handle h_BmPortal; /**< A handle to a BM Portal Module. will be used only for Init and Free routines. NOTE: if NULL, assuming affinity */ uint32_t numOfBuffers; /**< Number of buffers use by this pool NOTE: If zero, empty pool buffer is created. */ t_BufferPoolInfo bufferPoolInfo; /**< Data buffers pool information */ t_Handle h_App; /**< opaque user value passed as a parameter to callbacks */ bool shadowMode; /**< If TRUE, numOfBuffers will be set to '0'. */ uint8_t bpid; /**< index of the shadow buffer pool (0-BM_MAX_NUM_OF_POOLS). valid only if shadowMode='TRUE'. */ } t_BmPoolParam; /**************************************************************************//** @Function BM_POOL_Config @Description Creates descriptor for the BM Pool; The routine returns a handle (descriptor) to the BM Pool object. @Param[in] p_BmPoolParam - A pointer to data structure of parameters @Return Handle to BM Portal object, or NULL for Failure. *//***************************************************************************/ t_Handle BM_POOL_Config(t_BmPoolParam *p_BmPoolParam); /**************************************************************************//** @Function BM_POOL_Init @Description Initializes a BM-Pool module @Param[in] h_BmPool - A handle to a BM-Pool module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_POOL_Init(t_Handle h_BmPool); /**************************************************************************//** @Function BM_PoolFree @Description Frees all resources that were assigned to BM Pool module. Calling this routine invalidates the descriptor. @Param[in] h_BmPool - BM Pool module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_POOL_Free(t_Handle h_BmPool); /**************************************************************************//** @Function BM_POOL_ConfigBpid @Description Config a specific pool id rather than dynamic pool id. @Param[in] h_BmPool - A handle to a BM-Pool module @Param[in] bpid - index of the buffer pool (0-BM_MAX_NUM_OF_POOLS). @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_POOL_Config() and before BM_POOL_Init(). *//***************************************************************************/ t_Error BM_POOL_ConfigBpid(t_Handle h_BmPool, uint8_t bpid); /**************************************************************************//** @Function BM_POOL_ConfigDepletion @Description Config depletion-entry/exit thresholds and callback. @Param[in] h_BmPool - A handle to a BM-Pool module @Param[in] f_Depletion - depletion-entry/exit callback. @Param[in] thresholds - depletion-entry/exit thresholds. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_POOL_Config() and before BM_POOL_Init(); Allowed only if shadowMode='FALSE'. Allowed only if BM in master mode ('guestId'=NCSW_MASTER_ID), or the BM is in guest mode BUT than this routine will invoke IPC call to the master. *//***************************************************************************/ t_Error BM_POOL_ConfigDepletion(t_Handle h_BmPool, t_BmDepletionCallback *f_Depletion, uint32_t thresholds[MAX_DEPLETION_THRESHOLDS]); /**************************************************************************//** @Function BM_POOL_ConfigStockpile @Description Config software stockpile. @Param[in] h_BmPool - A handle to a BM-Pool module @Param[in] maxBuffers - the software data structure size saved for stockpile; when reached this value, release to hw command performed. @Param[in] minBuffers - if current capacity is equal or lower then this value, acquire from hw command performed. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_POOL_Config() and before BM_POOL_Init(). *//***************************************************************************/ t_Error BM_POOL_ConfigStockpile(t_Handle h_BmPool, uint16_t maxBuffers, uint16_t minBuffers); /**************************************************************************//** @Function BM_POOL_ConfigBuffContextMode @Description Config the BM pool to set/unset buffer-context @Param[in] h_BmPool - A handle to a BM-Pool module @Param[in] en - enable/disable buffer context mode @Return E_OK on success; Error code otherwise. @Cautions Allowed only following BM_POOL_Config() and before BM_POOL_Init(). *//***************************************************************************/ t_Error BM_POOL_ConfigBuffContextMode(t_Handle h_BmPool, bool en); /** @} */ /* end of BM_pool_init_grp group */ /**************************************************************************//** @Group BM_pool_runtime_control_grp BM-Pool Runtime Control Unit @Description BM-Pool Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description enum for defining BM Pool counters *//***************************************************************************/ typedef enum e_BmPoolCounters { e_BM_POOL_COUNTERS_CONTENT = 0, /**< number of free buffers for a particular pool */ e_BM_POOL_COUNTERS_SW_DEPLETION, /**< number of times pool entered sw depletion */ e_BM_POOL_COUNTERS_HW_DEPLETION /**< number of times pool entered hw depletion */ } e_BmPoolCounters; /**************************************************************************//** @Function BM_POOL_GetId @Description return a buffer pool id. @Param[in] h_BmPool - A handle to a BM-pool @Return Pool ID. *//***************************************************************************/ uint8_t BM_POOL_GetId(t_Handle h_BmPool); /**************************************************************************//** @Function BM_POOL_GetBufferSize @Description returns the pool's buffer size. @Param[in] h_BmPool - A handle to a BM-pool @Return pool's buffer size. *//***************************************************************************/ uint16_t BM_POOL_GetBufferSize(t_Handle h_BmPool); /**************************************************************************//** @Function BM_POOL_GetBufferContext @Description Returns the user's private context that should be associated with the buffer. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] p_Buff - A Pointer to the buffer @Return user's private context. *//***************************************************************************/ t_Handle BM_POOL_GetBufferContext(t_Handle h_BmPool, void *p_Buff); /**************************************************************************//** @Function BM_POOL_PhysToVirt @Description Translates a physical address to the matching virtual address. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] addr - The physical address to translate @Return Virtual address. *//***************************************************************************/ void * BM_POOL_PhysToVirt(t_Handle h_BmPool, physAddress_t addr); /**************************************************************************//** @Function BM_POOL_VirtToPhys @Description Translates a virtual address to the matching physical address. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] addr - The virtual address to translate @Return Physical address. *//***************************************************************************/ physAddress_t BM_POOL_VirtToPhys(t_Handle h_BmPool, void *addr); /**************************************************************************//** @Function BM_POOL_GetCounter @Description Reads one of the BM Pool counters. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] counter - The requested counter. @Return Counter's current value. *//***************************************************************************/ uint32_t BM_POOL_GetCounter(t_Handle h_BmPool, e_BmPoolCounters counter); /** @} */ /* end of BM_pool_runtime_control_grp group */ /**************************************************************************//** @Group BM_pool_runtime_data_grp BM-Pool Runtime Data Unit @Description BM-Pool Runtime data unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Function BM_POOL_GetBuf @Description Allocate buffer from a buffer pool. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] h_BmPortal - A handle to a BM Portal Module; NOTE : if NULL, assuming affinity. @Return A Pointer to the allocated buffer. *//***************************************************************************/ void * BM_POOL_GetBuf(t_Handle h_BmPool, t_Handle h_BmPortal); /**************************************************************************//** @Function BM_POOL_PutBuf @Description Deallocate buffer to a buffer pool. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] h_BmPortal - A handle to a BM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] p_Buff - A Pointer to the buffer. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_POOL_PutBuf(t_Handle h_BmPool, t_Handle h_BmPortal, void *p_Buff); /**************************************************************************//** @Function BM_POOL_FillBufs @Description Fill a BM pool with new buffers. @Param[in] h_BmPool - A handle to a BM-pool @Param[in] h_BmPortal - A handle to a BM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] numBufs - How many buffers to fill into the pool. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error BM_POOL_FillBufs(t_Handle h_BmPool, t_Handle h_BmPortal, uint32_t numBufs); /** @} */ /* end of BM_pool_runtime_data_grp group */ /** @} */ /* end of BM_pool_grp group */ /** @} */ /* end of BM_grp group */ #endif /* __BM_EXT_H */ Index: head/sys/contrib/ncsw/inc/Peripherals/fm_ext.h =================================================================== --- head/sys/contrib/ncsw/inc/Peripherals/fm_ext.h (revision 307541) +++ head/sys/contrib/ncsw/inc/Peripherals/fm_ext.h (revision 307542) @@ -1,1347 +1,1347 @@ /* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Freescale Semiconductor nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************//** @File fm_ext.h @Description FM Application Programming Interface. *//***************************************************************************/ #ifndef __FM_EXT #define __FM_EXT #include "error_ext.h" #include "std_ext.h" #include "dpaa_ext.h" /**************************************************************************//** @Group FM_grp Frame Manager API @Description FM API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group FM_lib_grp FM library @Description FM API functions, definitions and enums The FM module is the main driver module and is a mandatory module for FM driver users. Before any further module initialization, this module must be initialized. The FM is a "singletone" module. It is responsible of the common HW modules: FPM, DMA, common QMI, common BMI initializations and run-time control routines. This module must be initialized always when working with any of the FM modules. NOTE - We assumes that the FML will be initialize only by core No. 0! @{ *//***************************************************************************/ /**************************************************************************//** @Description enum for defining port types *//***************************************************************************/ typedef enum e_FmPortType { e_FM_PORT_TYPE_OH_OFFLINE_PARSING = 0, /**< Offline parsing port (id's: 0-6, share id's with host command, so must have exclusive id) */ e_FM_PORT_TYPE_OH_HOST_COMMAND, /**< Host command port (id's: 0-6, share id's with offline parsing ports, so must have exclusive id) */ e_FM_PORT_TYPE_RX, /**< 1G Rx port (id's: 0-3) */ e_FM_PORT_TYPE_RX_10G, /**< 10G Rx port (id's: 0) */ e_FM_PORT_TYPE_TX, /**< 1G Tx port (id's: 0-3) */ e_FM_PORT_TYPE_TX_10G, /**< 10G Tx port (id's: 0) */ e_FM_PORT_TYPE_DUMMY } e_FmPortType; /**************************************************************************//** @Collection General FM defines *//***************************************************************************/ #define FM_MAX_NUM_OF_PARTITIONS 64 /**< Maximum number of partitions */ #define FM_PHYS_ADDRESS_SIZE 6 /**< FM Physical address size */ /* @} */ #if defined(__MWERKS__) && !defined(__GNUC__) #pragma pack(push,1) #endif /* defined(__MWERKS__) && ... */ #define MEM_MAP_START /**************************************************************************//** @Description FM physical Address *//***************************************************************************/ typedef _Packed struct t_FmPhysAddr { volatile uint8_t high; /**< High part of the physical address */ volatile uint32_t low; /**< Low part of the physical address */ } _PackedType t_FmPhysAddr; /**************************************************************************//** @Description Parse results memory layout *//***************************************************************************/ typedef _Packed struct t_FmPrsResult { volatile uint8_t lpid; /**< Logical port id */ volatile uint8_t shimr; /**< Shim header result */ volatile uint16_t l2r; /**< Layer 2 result */ volatile uint16_t l3r; /**< Layer 3 result */ volatile uint8_t l4r; /**< Layer 4 result */ volatile uint8_t cplan; /**< Classification plan id */ volatile uint16_t nxthdr; /**< Next Header */ volatile uint16_t cksum; /**< Checksum */ volatile uint32_t lcv; /**< LCV */ volatile uint8_t shim_off[3]; /**< Shim offset */ volatile uint8_t eth_off; /**< ETH offset */ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */ volatile uint8_t vlan_off[2]; /**< VLAN offset */ volatile uint8_t etype_off; /**< ETYPE offset */ volatile uint8_t pppoe_off; /**< PPP offset */ volatile uint8_t mpls_off[2]; /**< MPLS offset */ volatile uint8_t ip_off[2]; /**< IP offset */ volatile uint8_t gre_off; /**< GRE offset */ volatile uint8_t l4_off; /**< Layer 4 offset */ volatile uint8_t nxthdr_off; /**< Parser end point */ } _PackedType t_FmPrsResult; /**************************************************************************//** @Collection FM Parser results *//***************************************************************************/ #define FM_PR_L2_VLAN_STACK 0x00000100 /**< Parse Result: VLAN stack */ #define FM_PR_L2_ETHERNET 0x00008000 /**< Parse Result: Ethernet*/ #define FM_PR_L2_VLAN 0x00004000 /**< Parse Result: VLAN */ #define FM_PR_L2_LLC_SNAP 0x00002000 /**< Parse Result: LLC_SNAP */ #define FM_PR_L2_MPLS 0x00001000 /**< Parse Result: MPLS */ #define FM_PR_L2_PPPoE 0x00000800 /**< Parse Result: PPPoE */ /* @} */ /**************************************************************************//** @Collection FM Frame descriptor macros *//***************************************************************************/ #define FM_FD_CMD_FCO 0x80000000 /**< Frame queue Context Override */ #define FM_FD_CMD_RPD 0x40000000 /**< Read Prepended Data */ #define FM_FD_CMD_UPD 0x20000000 /**< Update Prepended Data */ #define FM_FD_CMD_DTC 0x10000000 /**< Do L4 Checksum */ #define FM_FD_CMD_DCL4C 0x10000000 /**< Didn't calculate L4 Checksum */ #define FM_FD_CMD_CFQ 0x00ffffff /**< Confirmation Frame Queue */ #define FM_FD_TX_STATUS_ERR_MASK 0x07000000 /**< TX Error FD bits */ #define FM_FD_RX_STATUS_ERR_MASK 0x070ee3f8 /**< RX Error FD bits */ /* @} */ /**************************************************************************//** @Description Context A *//***************************************************************************/ typedef _Packed struct t_FmContextA { volatile uint32_t command; /**< ContextA Command */ volatile uint8_t res0[4]; /**< ContextA Reserved bits */ } _PackedType t_FmContextA; /**************************************************************************//** @Description Context B *//***************************************************************************/ typedef uint32_t t_FmContextB; /**************************************************************************//** @Collection Context A macros *//***************************************************************************/ #define FM_CONTEXTA_OVERRIDE_MASK 0x80000000 #define FM_CONTEXTA_ICMD_MASK 0x40000000 #define FM_CONTEXTA_A1_VALID_MASK 0x20000000 #define FM_CONTEXTA_MACCMD_MASK 0x00ff0000 #define FM_CONTEXTA_MACCMD_VALID_MASK 0x00800000 #define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000 #define FM_CONTEXTA_MACCMD_SC_MASK 0x000f0000 #define FM_CONTEXTA_A1_MASK 0x0000ffff #define FM_CONTEXTA_GET_OVERRIDE(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_OVERRIDE_MASK) >> (31-0)) #define FM_CONTEXTA_GET_ICMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_ICMD_MASK) >> (31-1)) #define FM_CONTEXTA_GET_A1_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_VALID_MASK) >> (31-2)) #define FM_CONTEXTA_GET_A1(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_MASK) >> (31-31)) #define FM_CONTEXTA_GET_MACCMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_MASK) >> (31-15)) #define FM_CONTEXTA_GET_MACCMD_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_VALID_MASK) >> (31-8)) #define FM_CONTEXTA_GET_MACCMD_SECURED(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31-11)) #define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SC_MASK) >> (31-15)) #define FM_CONTEXTA_SET_OVERRIDE(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31-0)) & FM_CONTEXTA_OVERRIDE_MASK) )) #define FM_CONTEXTA_SET_ICMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_ICMD_MASK) | (((val) << (31-1)) & FM_CONTEXTA_ICMD_MASK) )) #define FM_CONTEXTA_SET_A1_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31-2)) & FM_CONTEXTA_A1_VALID_MASK) )) #define FM_CONTEXTA_SET_A1(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_MASK) | (((val) << (31-31)) & FM_CONTEXTA_A1_MASK) )) #define FM_CONTEXTA_SET_MACCMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_MASK) )) #define FM_CONTEXTA_SET_MACCMD_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31-8)) & FM_CONTEXTA_MACCMD_VALID_MASK) )) #define FM_CONTEXTA_SET_MACCMD_SECURED(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31-11)) & FM_CONTEXTA_MACCMD_SECURED_MASK) )) #define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_SC_MASK) )) /* @} */ /**************************************************************************//** @Collection Context B macros *//***************************************************************************/ #define FM_CONTEXTB_FQID_MASK 0x00ffffff #define FM_CONTEXTB_GET_FQID(contextB) (*((t_FmContextB *)contextB) & FM_CONTEXTB_FQID_MASK) #define FM_CONTEXTB_SET_FQID(contextB,val) (*((t_FmContextB *)contextB) = ((*((t_FmContextB *)contextB) & ~FM_CONTEXTB_FQID_MASK) | ((val) & FM_CONTEXTB_FQID_MASK))) /* @} */ #define MEM_MAP_END #if defined(__MWERKS__) && !defined(__GNUC__) #pragma pack(pop) #endif /* defined(__MWERKS__) && ... */ /**************************************************************************//** @Description FM Exceptions *//***************************************************************************/ typedef enum e_FmExceptions { e_FM_EX_DMA_BUS_ERROR, /**< DMA bus error. */ e_FM_EX_DMA_READ_ECC, /**< Read Buffer ECC error */ e_FM_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC error on system side */ e_FM_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side */ e_FM_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */ e_FM_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */ e_FM_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */ e_FM_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */ e_FM_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */ e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< Dequeu from unknown port id */ e_FM_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */ e_FM_EX_BMI_PIPELINE_ECC, /**< Pipeline Table ECC Error */ e_FM_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics Count RAM ECC Error Enable */ e_FM_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */ e_FM_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/ e_FM_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/ } e_FmExceptions; /**************************************************************************//** @Group FM_init_grp FM Initialization Unit @Description FM Initialization Unit Initialization Flow Initialization of the FM Module will be carried out by the application according to the following sequence: a. Calling the configuration routine with basic parameters. b. Calling the advance initialization routines to change driver's defaults. c. Calling the initialization routine. @{ *//***************************************************************************/ /**************************************************************************//** @Function t_FmExceptionsCallback @Description Exceptions user callback routine, will be called upon an exception passing the exception identification. @Param[in] h_App - User's application descriptor. @Param[in] exception - The exception. *//***************************************************************************/ typedef void (t_FmExceptionsCallback) (t_Handle h_App, e_FmExceptions exception); /**************************************************************************//** @Function t_FmBusErrorCallback @Description Bus error user callback routine, will be called upon a bus error, passing parameters describing the errors and the owner. @Param[in] h_App - User's application descriptor. @Param[in] portType - Port type (e_FmPortType) @Param[in] portId - Port id - relative to type. @Param[in] addr - Address that caused the error @Param[in] tnum - Owner of error @Param[in] liodn - Logical IO device number *//***************************************************************************/ typedef void (t_FmBusErrorCallback) (t_Handle h_App, e_FmPortType portType, uint8_t portId, uint64_t addr, uint8_t tnum, uint16_t liodn); /**************************************************************************//** @Description structure for defining Ucode patch for loading. *//***************************************************************************/ typedef struct t_FmPcdFirmwareParams { uint32_t size; /**< Size of uCode */ uint32_t *p_Code; /**< A pointer to the uCode */ } t_FmPcdFirmwareParams; /**************************************************************************//** @Description structure representing FM initialization parameters *//***************************************************************************/ #define FM_SIZE_OF_LIODN_TABLE 64 typedef struct t_FmParams { uint8_t fmId; /**< Index of the FM */ uint8_t guestId; /**< FM Partition Id */ uintptr_t baseAddr; /**< Relevant when guestId = NCSW_MASSTER_ID only. A pointer to base of memory mapped FM registers (virtual); NOTE that this should include ALL common regs of the FM including the PCD regs area. */ t_Handle h_FmMuram; /**< Relevant when guestId = NCSW_MASSTER_ID only. A handle of an initialized MURAM object, to be used by the FM */ uint16_t fmClkFreq; /**< Relevant when guestId = NCSW_MASSTER_ID only. In Mhz */ #ifdef FM_PARTITION_ARRAY uint16_t liodnBasePerPort[FM_SIZE_OF_LIODN_TABLE]; /**< Relevant when guestId = NCSW_MASSTER_ID only. For each partition, LIODN should be configured here. */ #endif /* FM_PARTITION_ARRAY */ t_FmExceptionsCallback *f_Exception; /**< Relevant when guestId = NCSW_MASSTER_ID only. An application callback routine to handle exceptions.*/ t_FmBusErrorCallback *f_BusError; /**< Relevant when guestId = NCSW_MASSTER_ID only. An application callback routine to handle exceptions.*/ t_Handle h_App; /**< Relevant when guestId = NCSW_MASSTER_ID only. A handle to an application layer object; This handle will be passed by the driver upon calling the above callbacks */ - int irq; /**< Relevant when guestId = NCSW_MASSTER_ID only. + uintptr_t irq; /**< Relevant when guestId = NCSW_MASSTER_ID only. FM interrupt source for normal events */ - int errIrq; /**< Relevant when guestId = NCSW_MASSTER_ID only. + uintptr_t errIrq; /**< Relevant when guestId = NCSW_MASSTER_ID only. FM interrupt source for errors */ t_FmPcdFirmwareParams firmware; /**< Relevant when guestId = NCSW_MASSTER_ID only. Ucode */ } t_FmParams; /**************************************************************************//** @Function FM_Config @Description Creates descriptor for the FM module. The routine returns a handle (descriptor) to the FM object. This descriptor must be passed as first parameter to all other FM function calls. No actual initialization or configuration of FM hardware is done by this routine. @Param[in] p_FmParams - A pointer to data structure of parameters @Return Handle to FM object, or NULL for Failure. *//***************************************************************************/ t_Handle FM_Config(t_FmParams *p_FmParams); /**************************************************************************//** @Function FM_Init @Description Initializes the FM module @Param[in] h_Fm - FM module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error FM_Init(t_Handle h_Fm); /**************************************************************************//** @Function FM_Free @Description Frees all resources that were assigned to FM module. Calling this routine invalidates the descriptor. @Param[in] h_Fm - FM module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error FM_Free(t_Handle h_Fm); /**************************************************************************//** @Group FM_advanced_init_grp FM Advanced Configuration Unit @Description Configuration functions used to change default values; Note: Advanced init routines are not available for guest partition. @{ *//***************************************************************************/ /**************************************************************************//** @Description DMA debug mode *//***************************************************************************/ typedef enum e_FmDmaDbgCntMode { e_FM_DMA_DBG_NO_CNT = 0, /**< No counting */ e_FM_DMA_DBG_CNT_DONE, /**< Count DONE commands */ e_FM_DMA_DBG_CNT_COMM_Q_EM, /**< count command queue emergency signals */ e_FM_DMA_DBG_CNT_INT_READ_EM, /**< Count Internal Read buffer emergency signal */ e_FM_DMA_DBG_CNT_INT_WRITE_EM, /**< Count Internal Write buffer emergency signal */ e_FM_DMA_DBG_CNT_FPM_WAIT, /**< Count FPM WAIT signal */ e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors. */ e_FM_DMA_DBG_CNT_RAW_WAR_PROT /**< Number of times there was a need for RAW & WAR protection. */ } e_FmDmaDbgCntMode; /**************************************************************************//** @Description DMA Cache Override *//***************************************************************************/ typedef enum e_FmDmaCacheOverride { e_FM_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */ e_FM_DMA_NO_STASH_DATA, /**< Data should not be stashed in system level cache */ e_FM_DMA_MAY_STASH_DATA, /**< Data may be stashed in system level cache */ e_FM_DMA_STASH_DATA /**< Data should be stashed in system level cache */ } e_FmDmaCacheOverride; /**************************************************************************//** @Description DMA External Bus Priority *//***************************************************************************/ typedef enum e_FmDmaExtBusPri { e_FM_DMA_EXT_BUS_NORMAL = 0, /**< Normal priority */ e_FM_DMA_EXT_BUS_EBS, /**< AXI extended bus service priority */ e_FM_DMA_EXT_BUS_SOS, /**< AXI sos priority */ e_FM_DMA_EXT_BUS_EBS_AND_SOS /**< AXI ebs + sos priority */ } e_FmDmaExtBusPri; /**************************************************************************//** @Description enum for choosing the field that will be output on AID *//***************************************************************************/ typedef enum e_FmDmaAidMode { e_FM_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */ e_FM_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */ } e_FmDmaAidMode; /**************************************************************************//** @Description FPM Catasrophic error behaviour *//***************************************************************************/ typedef enum e_FmCatastrophicErr { e_FM_CATASTROPHIC_ERR_STALL_PORT = 0, /**< Port_ID is stalled (only reset can release it) */ e_FM_CATASTROPHIC_ERR_STALL_TASK /**< Only errornous task is stalled */ } e_FmCatastrophicErr; /**************************************************************************//** @Description FPM DMA error behaviour *//***************************************************************************/ typedef enum e_FmDmaErr { e_FM_DMA_ERR_CATASTROPHIC = 0, /**< Dma error is treated as a catastrophic error */ e_FM_DMA_ERR_REPORT /**< Dma error is just reported */ } e_FmDmaErr; /**************************************************************************//** @Description DMA Emergency level by BMI emergency signal *//***************************************************************************/ typedef enum e_FmDmaEmergencyLevel { e_FM_DMA_EM_EBS = 0, /**< EBS emergency */ e_FM_DMA_EM_SOS /**< SOS emergency */ } e_FmDmaEmergencyLevel; /**************************************************************************//** @Collection DMA emergency options *//***************************************************************************/ typedef uint32_t fmEmergencyBus_t; /**< DMA emergency options */ #define FM_DMA_MURAM_READ_EMERGENCY 0x00800000 /**< Enable emergency for MURAM1 */ #define FM_DMA_MURAM_WRITE_EMERGENCY 0x00400000 /**< Enable emergency for MURAM2 */ #define FM_DMA_EXT_BUS_EMERGENCY 0x00100000 /**< Enable emergency for external bus */ /* @} */ /**************************************************************************//** @Description A structure for defining DMA emergency level *//***************************************************************************/ typedef struct t_FmDmaEmergency { fmEmergencyBus_t emergencyBusSelect; /**< An OR of the busses where emergency should be enabled */ e_FmDmaEmergencyLevel emergencyLevel; /**< EBS/SOS */ } t_FmDmaEmergency; /**************************************************************************//** @Description structure for defining FM threshold *//***************************************************************************/ typedef struct t_FmThresholds { uint8_t dispLimit; /**< The number of times a frames may be passed in the FM before assumed to be looping. */ uint8_t prsDispTh; /**< This is the number pf packets that may be queued in the parser dispatch queue*/ uint8_t plcrDispTh; /**< This is the number pf packets that may be queued in the policer dispatch queue*/ uint8_t kgDispTh; /**< This is the number pf packets that may be queued in the keygen dispatch queue*/ uint8_t bmiDispTh; /**< This is the number pf packets that may be queued in the BMI dispatch queue*/ uint8_t qmiEnqDispTh; /**< This is the number pf packets that may be queued in the QMI enqueue dispatch queue*/ uint8_t qmiDeqDispTh; /**< This is the number pf packets that may be queued in the QMI dequeue dispatch queue*/ uint8_t fmCtl1DispTh; /**< This is the number pf packets that may be queued in fmCtl1 dispatch queue*/ uint8_t fmCtl2DispTh; /**< This is the number pf packets that may be queued in fmCtl2 dispatch queue*/ } t_FmThresholds; /**************************************************************************//** @Description structure for defining DMA thresholds *//***************************************************************************/ typedef struct t_FmDmaThresholds { uint8_t assertEmergency; /**< When this value is reached, assert emergency (Threshold)*/ uint8_t clearEmergency; /**< After emergency is asserted, it is held until this value is reached (Hystheresis) */ } t_FmDmaThresholds; /**************************************************************************//** @Function FM_ConfigResetOnInit @Description Tell the driver whether to reset the FM before initialization or not. It changes the default configuration [FALSE]. @Param[in] h_Fm A handle to an FM Module. @Param[in] enable When TRUE, FM will be reset before any initialization. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable); /**************************************************************************//** @Function FM_ConfigTotalNumOfTasks @Description Change the total number of tasks from its default configuration [BMI_MAX_NUM_OF_TASKS] @Param[in] h_Fm A handle to an FM Module. @Param[in] totalNumOfTasks The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigTotalNumOfTasks(t_Handle h_Fm, uint8_t totalNumOfTasks); /**************************************************************************//** @Function FM_ConfigTotalFifoSize @Description Change the total Fifo size from its default configuration [BMI_MAX_FIFO_SIZE] @Param[in] h_Fm A handle to an FM Module. @Param[in] totalFifoSize The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize); /**************************************************************************//** @Function FM_ConfigMaxNumOfOpenDmas @Description Change the maximum allowed open DMA's for this FM from its default configuration [BMI_MAX_NUM_OF_DMAS] @Param[in] h_Fm A handle to an FM Module. @Param[in] maxNumOfOpenDmas The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigMaxNumOfOpenDmas(t_Handle h_Fm, uint8_t maxNumOfOpenDmas); /**************************************************************************//** @Function FM_ConfigThresholds @Description Calling this routine changes the internal driver data base from its default FM threshold configuration: dispLimit: [0] prsDispTh: [16] plcrDispTh: [16] kgDispTh: [16] bmiDispTh: [16] qmiEnqDispTh: [16] qmiDeqDispTh: [16] fmCtl1DispTh: [16] fmCtl2DispTh: [16] @Param[in] h_Fm A handle to an FM Module. @Param[in] p_FmThresholds A structure of threshold parameters. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds); /**************************************************************************//** @Function FM_ConfigDmaCacheOverride @Description Calling this routine changes the internal driver data base from its default configuration of cache override mode [e_FM_DMA_NO_CACHE_OR] @Param[in] h_Fm A handle to an FM Module. @Param[in] cacheOverride The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride); /**************************************************************************//** @Function FM_ConfigDmaAidOverride @Description Calling this routine changes the internal driver data base from its default configuration of aid override mode [TRUE] @Param[in] h_Fm A handle to an FM Module. @Param[in] aidOverride The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride); /**************************************************************************//** @Function FM_ConfigDmaAidMode @Description Calling this routine changes the internal driver data base from its default configuration of aid mode [e_FM_DMA_AID_OUT_TNUM] @Param[in] h_Fm A handle to an FM Module. @Param[in] aidMode The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode); /**************************************************************************//** @Function FM_ConfigDmaAxiDbgNumOfBeats @Description Calling this routine changes the internal driver data base from its default configuration of axi debug [1] @Param[in] h_Fm A handle to an FM Module. @Param[in] axiDbgNumOfBeats The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats); /**************************************************************************//** @Function FM_ConfigDmaCamNumOfEntries @Description Calling this routine changes the internal driver data base from its default configuration of number of CAM entries [32] @Param[in] h_Fm A handle to an FM Module. @Param[in] numOfEntries The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries); /**************************************************************************//** @Function FM_ConfigDmaWatchdog @Description Calling this routine changes the internal driver data base from its default watchdog configuration, which is disabled [0]. @Param[in] h_Fm A handle to an FM Module. @Param[in] watchDogValue The selected new value - in microseconds. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchDogValue); /**************************************************************************//** @Function FM_ConfigDmaWriteBufThresholds @Description Calling this routine changes the internal driver data base from its default configuration of DMA write buffer threshold assertEmergency: [DMA_THRESH_MAX_BUF] clearEmergency: [DMA_THRESH_MAX_BUF] @Param[in] h_Fm A handle to an FM Module. @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - When 'assertEmergency' value is reached, emergency is asserted, then it is held until 'clearEmergency' value is reached. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); /**************************************************************************//** @Function FM_ConfigDmaCommQThresholds @Description Calling this routine changes the internal driver data base from its default configuration of DMA command queue threshold assertEmergency: [DMA_THRESH_MAX_COMMQ] clearEmergency: [DMA_THRESH_MAX_COMMQ] @Param[in] h_Fm A handle to an FM Module. @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - When 'assertEmergency' value is reached, emergency is asserted, then it is held until 'clearEmergency' value is reached.. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); /**************************************************************************//** @Function FM_ConfigDmaReadBufThresholds @Description Calling this routine changes the internal driver data base from its default configuration of DMA read buffer threshold assertEmergency: [DMA_THRESH_MAX_BUF] clearEmergency: [DMA_THRESH_MAX_BUF] @Param[in] h_Fm A handle to an FM Module. @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - When 'assertEmergency' value is reached, emergency is asserted, then it is held until 'clearEmergency' value is reached.. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); /**************************************************************************//** @Function FM_ConfigDmaSosEmergencyThreshold @Description Calling this routine changes the internal driver data base from its default dma SOS emergency configuration [0] @Param[in] h_Fm A handle to an FM Module. @Param[in] dmaSosEmergency The selected new value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency); /**************************************************************************//** @Function FM_ConfigEnableCounters @Description Calling this routine changes the internal driver data base from its default counters configuration where counters are disabled. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigEnableCounters(t_Handle h_Fm); /**************************************************************************//** @Function FM_ConfigDmaDbgCounter @Description Calling this routine changes the internal driver data base from its default DMA debug counters configuration [e_FM_DMA_DBG_NO_CNT] @Param[in] h_Fm A handle to an FM Module. @Param[in] fmDmaDbgCntMode An enum selecting the debug counter mode. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode); /**************************************************************************//** @Function FM_ConfigDmaStopOnBusErr @Description Calling this routine changes the internal driver data base from its default selection of bus error behavior [FALSE] @Param[in] h_Fm A handle to an FM Module. @Param[in] stop TRUE to stop on bus error, FALSE to continue. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). Only if bus error is enabled. *//***************************************************************************/ t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop); /**************************************************************************//** @Function FM_ConfigDmaEmergency @Description Calling this routine changes the internal driver data base from its default selection of DMA emergency where's it's disabled. @Param[in] h_Fm A handle to an FM Module. @Param[in] p_Emergency An OR mask of all required options. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency); /**************************************************************************//** @Function FM_ConfigDmaEmergencySmoother @Description sets the minimum amount of DATA beats transferred on the AXI READ and WRITE ports before lowering the emergency level. By default smother is disabled. @Param[in] h_Fm A handle to an FM Module. @Param[in] emergencyCnt emergency switching counter. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt); /**************************************************************************//** @Function FM_ConfigDmaErr @Description Calling this routine changes the internal driver data base from its default DMA error treatment [e_FM_DMA_ERR_CATASTROPHIC] @Param[in] h_Fm A handle to an FM Module. @Param[in] dmaErr The selected new choice. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr); /**************************************************************************//** @Function FM_ConfigCatastrophicErr @Description Calling this routine changes the internal driver data base from its default behavior on catastrophic error [e_FM_CATASTROPHIC_ERR_STALL_PORT] @Param[in] h_Fm A handle to an FM Module. @Param[in] catastrophicErr The selected new choice. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr); /**************************************************************************//** @Function FM_ConfigEnableMuramTestMode @Description Calling this routine changes the internal driver data base from its default selection of test mode where it's disabled. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm); /**************************************************************************//** @Function FM_ConfigEnableIramTestMode @Description Calling this routine changes the internal driver data base from its default selection of test mode where it's disabled. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm); /**************************************************************************//** @Function FM_ConfigHaltOnExternalActivation @Description Calling this routine changes the internal driver data base from its default selection of FM behaviour on external halt activation [FALSE]. @Param[in] h_Fm A handle to an FM Module. @Param[in] enable TRUE to enable halt on external halt activation. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable); /**************************************************************************//** @Function FM_ConfigHaltOnUnrecoverableEccError @Description Calling this routine changes the internal driver data base from its default selection of FM behaviour on unrecoverable Ecc error [FALSE]. @Param[in] h_Fm A handle to an FM Module. @Param[in] enable TRUE to enable halt on unrecoverable Ecc error @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable); /**************************************************************************//** @Function FM_ConfigException @Description Calling this routine changes the internal driver data base from its default selection of exceptions enablement. By default all exceptions are enabled. @Param[in] h_Fm A handle to an FM Module. @Param[in] exception The exception to be selected. @Param[in] enable TRUE to enable interrupt, FALSE to mask it. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable); /**************************************************************************//** @Function FM_ConfigExternalEccRamsEnable @Description Calling this routine changes the internal driver data base from its default [FALSE]. When this option is enabled Rams ECC enable is not effected by the FPM RCR bit, but by a JTAG. @Param[in] h_Fm A handle to an FM Module. @Param[in] enable TRUE to enable this option. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable); /**************************************************************************//** @Function FM_ConfigTnumAgingPeriod @Description Calling this routine changes the internal driver data base from its default configuration for aging of dequeue TNUM's in the QMI.[0] Note that this functionality is not available in all chips. @Param[in] h_Fm A handle to an FM Module. @Param[in] tnumAgingPeriod Tnum Aging Period in microseconds. Note that period is recalculated in units of 64 FM clocks. Driver will pick the closest possible period. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod); /** @} */ /* end of FM_advanced_init_grp group */ /** @} */ /* end of FM_init_grp group */ /**************************************************************************//** @Group FM_runtime_control_grp FM Runtime Control Unit @Description FM Runtime control unit API functions, definitions and enums. The FM driver provides a set of control routines for each module. These routines may only be called after the module was fully initialized (both configuration and initialization routines were called). They are typically used to get information from hardware (status, counters/statistics, revision etc.), to modify a current state or to force/enable a required action. Run-time control may be called whenever necessary and as many times as needed. @{ *//***************************************************************************/ /**************************************************************************//** @Collection General FM defines. *//***************************************************************************/ #define FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ FM_MAX_NUM_OF_1G_RX_PORTS + \ FM_MAX_NUM_OF_10G_RX_PORTS + \ FM_MAX_NUM_OF_1G_TX_PORTS + \ FM_MAX_NUM_OF_10G_TX_PORTS) /* @} */ /**************************************************************************//** @Description Structure for Port bandwidth requirement. Port is identified by type and relative id. *//***************************************************************************/ typedef struct t_FmPortBandwidth { e_FmPortType type; /**< FM port type */ uint8_t relativePortId; /**< Type relative port id */ uint8_t bandwidth; /**< bandwidth - (in term of percents) */ } t_FmPortBandwidth; /**************************************************************************//** @Description A Structure containing an array of Port bandwidth requirements. The user should state the ports requiring bandwidth in terms of percentage - i.e. all port's bandwidths in the array must add up to 100. *//***************************************************************************/ typedef struct t_FmPortsBandwidthParams { uint8_t numOfPorts; /**< num of ports listed in the array below */ t_FmPortBandwidth portsBandwidths[FM_MAX_NUM_OF_VALID_PORTS]; /**< for each port, it's bandwidth (all port's bandwidths must add up to 100.*/ } t_FmPortsBandwidthParams; /**************************************************************************//** @Description DMA Emergency control on MURAM *//***************************************************************************/ typedef enum e_FmDmaMuramPort { e_FM_DMA_MURAM_PORT_WRITE, /**< MURAM write port */ e_FM_DMA_MURAM_PORT_READ /**< MURAM read port */ } e_FmDmaMuramPort; /**************************************************************************//** @Description enum for defining FM counters *//***************************************************************************/ typedef enum e_FmCounters { e_FM_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI total enqueued frames counter */ e_FM_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI total dequeued frames counter */ e_FM_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */ e_FM_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */ e_FM_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */ e_FM_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */ e_FM_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI dequeue from default queue counter */ e_FM_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI dequeue from FQ context counter */ e_FM_COUNTERS_DEQ_FROM_FD, /**< QMI dequeue from FD command field counter */ e_FM_COUNTERS_DEQ_CONFIRM, /**< QMI dequeue confirm counter */ e_FM_COUNTERS_SEMAPHOR_ENTRY_FULL_REJECT, /**< DMA semaphor reject due to full entry counter */ e_FM_COUNTERS_SEMAPHOR_QUEUE_FULL_REJECT, /**< DMA semaphor reject due to full CAM queue counter */ e_FM_COUNTERS_SEMAPHOR_SYNC_REJECT /**< DMA semaphor reject due to sync counter */ } e_FmCounters; /**************************************************************************//** @Description structure for returning revision information *//***************************************************************************/ typedef struct t_FmRevisionInfo { uint8_t majorRev; /**< Major revision */ uint8_t minorRev; /**< Minor revision */ } t_FmRevisionInfo; /**************************************************************************//** @Description struct for defining DMA status *//***************************************************************************/ typedef struct t_FmDmaStatus { bool cmqNotEmpty; /**< Command queue is not empty */ bool busError; /**< Bus error occurred */ bool readBufEccError; /**< Double ECC error on buffer Read */ bool writeBufEccSysError; /**< Double ECC error on buffer write from system side */ bool writeBufEccFmError; /**< Double ECC error on buffer write from FM side */ } t_FmDmaStatus; #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) /**************************************************************************//** @Function FM_DumpRegs @Description Dumps all FM registers @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; @Cautions Allowed only FM_Init(). *//***************************************************************************/ t_Error FM_DumpRegs(t_Handle h_Fm); #endif /* (defined(DEBUG_ERRORS) && ... */ /**************************************************************************//** @Function FM_SetException @Description Calling this routine enables/disables the specified exception. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] exception The exception to be selected. @Param[in] enable TRUE to enable interrupt, FALSE to mask it. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable); /**************************************************************************//** @Function FM_SetPortsBandwidth @Description Sets relative weights between ports when accessing common resources. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] p_PortsBandwidth A structure of ports bandwidths in percentage, i.e. total must equal 100. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth); /**************************************************************************//** @Function FM_EnableRamsEcc @Description Enables ECC mechanism for all the different FM RAM's; E.g. IRAM, MURAM, Parser, Keygen, Policer, etc. Note: If FM_ConfigExternalEccRamsEnable was called to enable external setting of ECC, this routine effects IRAM ECC only. This routine is also called by the driver if an ECC exception is enabled. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_EnableRamsEcc(t_Handle h_Fm); /**************************************************************************//** @Function FM_DisableRamsEcc @Description Disables ECC mechanism for all the different FM RAM's; E.g. IRAM, MURAM, Parser, Keygen, Policer, etc. Note: If FM_ConfigExternalEccRamsEnable was called to enable external setting of ECC, this routine effects IRAM ECC only. In opposed to FM_EnableRamsEcc, this routine must be called explicitly to disable all Rams ECC. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Config() and before FM_Init(). *//***************************************************************************/ t_Error FM_DisableRamsEcc(t_Handle h_Fm); /**************************************************************************//** @Function FM_GetRevision @Description Returns the FM revision @Param[in] h_Fm A handle to an FM Module. @Param[out] p_FmRevisionInfo A structure of revision information parameters. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo); /**************************************************************************//** @Function FM_GetCounter @Description Reads one of the FM counters. @Param[in] h_Fm A handle to an FM Module. @Param[in] counter The requested counter. @Return Counter's current value. @Cautions Allowed only following FM_Init(). Note that it is user's responsibility to call this routine only for enabled counters, and there will be no indication if a disabled counter is accessed. *//***************************************************************************/ uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter); /**************************************************************************//** @Function FM_ModifyCounter @Description Sets a value to an enabled counter. Use "0" to reset the counter. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] counter The requested counter. @Param[in] val The requested value to be written into the counter. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val); /**************************************************************************//** @Function FM_Resume @Description Release FM after halt FM command or after unrecoverable ECC error. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ void FM_Resume(t_Handle h_Fm); /**************************************************************************//** @Function FM_SetDmaEmergency @Description Manual emergency set Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] muramPort MURAM direction select. @Param[in] enable TRUE to manually enable emergency, FALSE to disable. @Return None. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable); /**************************************************************************//** @Function FM_SetDmaExtBusPri @Description Manual emergency set Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] pri External bus priority select @Return None. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri); /**************************************************************************//** @Function FM_ForceIntr @Description Causes an interrupt event on the requested source. Note: Not available for guest partition. @Param[in] h_Fm A handle to an FM Module. @Param[in] exception An exception to be forced. @Return E_OK on success; Error code if the exception is not enabled, or is not able to create interrupt. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception); /**************************************************************************//** @Function FM_GetDmaStatus @Description Reads the DMA current status @Param[in] h_Fm A handle to an FM Module. @Param[out] p_FmDmaStatus A structure of DMA status parameters. @Return None @Cautions Allowed only following FM_Init(). *//***************************************************************************/ void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus); /**************************************************************************//** @Function FM_GetPcdHandle @Description Used by FMC in order to get PCD handle @Param[in] h_Fm A handle to an FM Module. @Return A handle to the PCD module, NULL if uninitialized. @Cautions Allowed only following FM_Init(). *//***************************************************************************/ t_Handle FM_GetPcdHandle(t_Handle h_Fm); /**************************************************************************//** @Function FM_ErrorIsr Note: Not available for guest partition. @Description FM interrupt-service-routine for errors. @Param[in] h_Fm A handle to an FM Module. @Return E_OK on success; E_EMPTY if no errors found in register, other error code otherwise. @Cautions Allowed only following FM_Init(). This routine should NOT be called from guest-partition (i.e. guestId != NCSW_MASTER_ID) *//***************************************************************************/ t_Error FM_ErrorIsr(t_Handle h_Fm); /**************************************************************************//** @Function FM_EventIsr Note: Not available for guest partition. @Description FM interrupt-service-routine for normal events. @Param[in] h_Fm A handle to an FM Module. @Cautions Allowed only following FM_Init(). This routine should NOT be called from guest-partition (i.e. guestId != NCSW_MASTER_ID) *//***************************************************************************/ void FM_EventIsr(t_Handle h_Fm); #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) /**************************************************************************//** @Function FmDumpPortRegs @Description Dumps FM port registers which are part of FM common registers @Param[in] h_Fm A handle to an FM Module. @Param[in] hardwarePortId HW port id. @Return E_OK on success; Error code otherwise. @Cautions Allowed only FM_Init(). *//***************************************************************************/ t_Error FmDumpPortRegs(t_Handle h_Fm,uint8_t hardwarePortId); #endif /* (defined(DEBUG_ERRORS) && ... */ /** @} */ /* end of FM_runtime_control_grp group */ /** @} */ /* end of FM_lib_grp group */ /** @} */ /* end of FM_grp group */ #endif /* __FM_EXT */ Index: head/sys/contrib/ncsw/inc/Peripherals/qm_ext.h =================================================================== --- head/sys/contrib/ncsw/inc/Peripherals/qm_ext.h (revision 307541) +++ head/sys/contrib/ncsw/inc/Peripherals/qm_ext.h (revision 307542) @@ -1,1270 +1,1270 @@ /****************************************************************************** © 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. All rights reserved. This is proprietary source code of Freescale Semiconductor Inc., and its use is subject to the NetComm Device Drivers EULA. The copyright notice above does not evidence any actual or intended publication of such source code. ALTERNATIVELY, redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Freescale Semiconductor nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **************************************************************************/ /****************************************************************************** @File qm_ext.h @Description QM & Portal API *//***************************************************************************/ #ifndef __QM_EXT_H #define __QM_EXT_H #include "error_ext.h" #include "std_ext.h" #include "dpaa_ext.h" #include "part_ext.h" /**************************************************************************//** @Group QM_grp Queue Manager API @Description QM API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description This callback type is used when receiving frame. User provides this function. Driver invokes it. @Param[in] h_App A user argument to the callback @Param[in] h_QmFqr A handle to an QM-FQR Module. @Param[in] fqidOffset fqid offset from the FQR's fqid base. @Param[in] p_Frame The Received Frame @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx operation for all ready data. @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. @Cautions p_Frame is local parameter; i.e. users must NOT access or use this parameter in any means outside this callback context. *//***************************************************************************/ typedef e_RxStoreResponse (t_QmReceivedFrameCallback)(t_Handle h_App, t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame); /**************************************************************************//** @Description This callback type is used when the FQR is completely was drained. User provides this function. Driver invokes it. @Param[in] h_App A user argument to the callback @Param[in] h_QmFqr A handle to an QM-FQR Module. @Retval E_OK on success; Error code otherwise. *//***************************************************************************/ typedef t_Error (t_QmFqrDrainedCompletionCB)(t_Handle h_App, t_Handle h_QmFqr); /**************************************************************************//** @Description QM Rejection code enum *//***************************************************************************/ typedef enum e_QmRejectionCode { e_QM_RC_NONE, e_QM_RC_CG_TAILDROP, /**< This frames was rejected due to congestion group taildrop situation */ e_QM_RC_CG_WRED, /**< This frames was rejected due to congestion group WRED situation */ e_QM_RC_FQ_TAILDROP /**< This frames was rejected due to FQID TD situation */ /* e_QM_RC_ERROR e_QM_RC_ORPWINDOW_EARLY e_QM_RC_ORPWINDOW_LATE e_QM_RC_ORPWINDOW_RETIRED */ } e_QmRejectionCode; /**************************************************************************//** @Description QM Rejected frame information *//***************************************************************************/ typedef struct t_QmRejectedFrameInfo { e_QmRejectionCode rejectionCode; /**< Rejection code */ union { struct { uint8_t cgId; /**< congestion group id*/ } cg; /**< rejection parameters when rejectionCode = e_QM_RC_CG_TAILDROP or e_QM_RC_CG_WRED. */ }; } t_QmRejectedFrameInfo; /**************************************************************************//** @Description This callback type is used when receiving rejected frames. User provides this function. Driver invokes it. @Param[in] h_App A user argument to the callback @Param[in] h_QmFqr A handle to an QM-FQR Module. @Param[in] fqidOffset fqid offset from the FQR's fqid base. @Param[in] p_Frame The Rejected Frame @Param[in] p_QmRejectedFrameInfo Rejected Frame information @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx operation for all ready data. @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. @Cautions p_Frame is local parameter; i.e. users must NOT access or use this parameter in any means outside this callback context. *//***************************************************************************/ typedef e_RxStoreResponse (t_QmRejectedFrameCallback)(t_Handle h_App, t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame, t_QmRejectedFrameInfo *p_QmRejectedFrameInfo); /**************************************************************************//** @Group QM_lib_grp QM common API @Description QM common API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description QM Exceptions *//***************************************************************************/ typedef enum e_QmExceptions { e_QM_EX_CORENET_INITIATOR_DATA = 0, /**< Initiator Data Error */ e_QM_EX_CORENET_TARGET_DATA, /**< CoreNet Target Data Error */ e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION, /**< Invalid Target Transaction */ e_QM_EX_PFDR_THRESHOLD, /**< PFDR Low Watermark Interrupt */ e_QM_EX_PFDR_ENQUEUE_BLOCKED, /**< PFDR Enqueues Blocked Interrupt */ e_QM_EX_SINGLE_ECC, /**< Single Bit ECC Error Interrupt */ e_QM_EX_MULTI_ECC, /**< Multi Bit ECC Error Interrupt */ e_QM_EX_INVALID_COMMAND, /**< Invalid Command Verb Interrupt */ e_QM_EX_DEQUEUE_DCP, /**< Invalid Dequeue Direct Connect Portal Interrupt */ e_QM_EX_DEQUEUE_FQ, /**< Invalid Dequeue FQ Interrupt */ e_QM_EX_DEQUEUE_SOURCE, /**< Invalid Dequeue Source Interrupt */ e_QM_EX_DEQUEUE_QUEUE, /**< Invalid Dequeue Queue Interrupt */ e_QM_EX_ENQUEUE_OVERFLOW, /**< Invalid Enqueue Overflow Interrupt */ e_QM_EX_ENQUEUE_STATE, /**< Invalid Enqueue State Interrupt */ e_QM_EX_ENQUEUE_CHANNEL, /**< Invalid Enqueue Channel Interrupt */ e_QM_EX_ENQUEUE_QUEUE, /**< Invalid Enqueue Queue Interrupt */ e_QM_EX_CG_STATE_CHANGE /**< CG change state notification */ } e_QmExceptions; /**************************************************************************//** @Group QM_init_grp QM (common) Initialization Unit @Description QM (common) Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Function t_QmExceptionsCallback @Description Exceptions user callback routine, will be called upon an exception passing the exception identification. @Param[in] h_App - User's application descriptor. @Param[in] exception - The exception. *//***************************************************************************/ typedef void (t_QmExceptionsCallback) ( t_Handle h_App, e_QmExceptions exception); /**************************************************************************//** @Description Frame's Type to poll *//***************************************************************************/ typedef enum e_QmPortalPollSource { e_QM_PORTAL_POLL_SOURCE_DATA_FRAMES = 0, /**< Poll only data frames */ e_QM_PORTAL_POLL_SOURCE_CONTROL_FRAMES, /**< Poll only control frames */ e_QM_PORTAL_POLL_SOURCE_BOTH /**< Poll both */ } e_QmPortalPollSource; /**************************************************************************//** @Description structure representing QM contextA of FQ initialization parameters Note that this is only "space-holder" for the Context-A. The "real" Context-A is described in each specific driver (E.g. FM driver has its own Context-A API). *//***************************************************************************/ typedef struct { uint32_t res[2]; /**< reserved size for context-a */ } t_QmContextA; /**************************************************************************//** @Description structure representing QM contextB of FQ initialization parameters Note that this is only "space-holder" for the Context-B. The "real" Context-B is described in each specific driver (E.g. FM driver has its own Context-B API). *//***************************************************************************/ typedef uint32_t t_QmContextB; /**************************************************************************//** @Description structure representing QM initialization parameters *//***************************************************************************/ typedef struct { uint8_t guestId; /**< QM Partition Id */ uintptr_t baseAddress; /**< Qm base address (virtual) NOTE: this parameter relevant only for BM in master mode ('guestId'=NCSW_MASTER_ID). */ uintptr_t swPortalsBaseAddress; /**< QM Software Portals Base Address (virtual) */ uint16_t liodn; /**< This value is attached to every transaction initiated by QMan when accessing its private data structures */ uint32_t totalNumOfFqids; /**< Total number of frame-queue-ids in the system */ uint32_t fqdMemPartitionId; /**< FQD's mem partition id; NOTE: The memory partition must be non-cacheable and no-coherent area. */ uint32_t pfdrMemPartitionId; /**< PFDR's mem partition id; NOTE: The memory partition must be non-cacheable and no-coherent area. */ t_QmExceptionsCallback *f_Exception; /**< An application callback routine to handle exceptions.*/ t_Handle h_App; /**< A handle to an application layer object; This handle will be passed by the driver upon calling the above callbacks */ - int errIrq; /**< error interrupt line; NO_IRQ if interrupts not used */ + uintptr_t errIrq; /**< error interrupt line; NO_IRQ if interrupts not used */ uint32_t partFqidBase; /**< The first frame-queue-id dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ uint32_t partNumOfFqids; /**< Number of frame-queue-ids dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ uint16_t partCgsBase; /**< The first cgr dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ uint16_t partNumOfCgs; /**< Number of cgr's dedicated to this partition. NOTE: this parameter relevant only when working with multiple partitions. */ } t_QmParam; /**************************************************************************//** @Function QM_Config @Description Creates descriptor for the QM module. The routine returns a handle (descriptor) to the QM object. This descriptor must be passed as first parameter to all other QM function calls. No actual initialization or configuration of QM hardware is done by this routine. @Param[in] p_QmParam - Pointer to data structure of parameters @Retval Handle to the QM object, or NULL for Failure. *//***************************************************************************/ t_Handle QM_Config(t_QmParam *p_QmParam); /**************************************************************************//** @Function QM_Init @Description Initializes the QM module @Param[in] h_Qm - A handle to the QM module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error QM_Init(t_Handle h_Qm); /**************************************************************************//** @Function QM_Free @Description Frees all resources that were assigned to the QM module. Calling this routine invalidates the descriptor. @Param[in] h_Qm - A handle to the QM module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error QM_Free(t_Handle h_Qm); /**************************************************************************//** @Group QM_advanced_init_grp QM (common) Advanced Configuration Unit @Description Configuration functions used to change default values. @{ *//***************************************************************************/ /**************************************************************************//** @Description structure for defining DC portal ERN destination *//***************************************************************************/ typedef struct t_QmDcPortalParams { bool sendToSw; e_DpaaSwPortal swPortalId; } t_QmDcPortalParams; /**************************************************************************//** @Function QM_ConfigRTFramesDepth @Description Change the run-time frames depth (i.e. the maximum total number of frames that may be inside QM at a certain time) from its default configuration [30000]. @Param[in] h_Qm - A handle to the QM module @Param[in] rtFramesDepth - run-time max num of frames. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Config() and before QM_Init(). *//***************************************************************************/ t_Error QM_ConfigRTFramesDepth(t_Handle h_Qm, uint32_t rtFramesDepth); /**************************************************************************//** @Function QM_ConfigPfdrThreshold @Description Change the pfdr threshold from its default configuration [0]. An interrupt if enables is asserted when the number of PFDRs is below this threshold. @Param[in] h_Qm - A handle to the QM module @Param[in] threshold - threshold value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Config() and before QM_Init(). *//***************************************************************************/ t_Error QM_ConfigPfdrThreshold(t_Handle h_Qm, uint32_t threshold); /**************************************************************************//** @Function QM_ConfigSfdrReservationThreshold @Description Change the sfdr threshold from its default configuration [0]. @Param[in] h_Qm - A handle to the QM module @Param[in] threshold - threshold value. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Config() and before QM_Init(). *//***************************************************************************/ t_Error QM_ConfigSfdrReservationThreshold(t_Handle h_Qm, uint32_t threshold); /**************************************************************************//** @Function QM_ConfigErrorRejectionNotificationDest @Description Change the destination of rejected frames for DC portals. By default, depending on chip, some DC portals are set to reject frames to HW and some to SW. @Param[in] h_Qm - A handle to the QM module @Param[in] id - DC Portal id. @Param[in] p_Params - Destination parameters. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Config() and before QM_Init(). *//***************************************************************************/ t_Error QM_ConfigErrorRejectionNotificationDest(t_Handle h_Qm, e_DpaaDcPortal id, t_QmDcPortalParams *p_Params); /** @} */ /* end of QM_advanced_init_grp group */ /** @} */ /* end of QM_init_grp group */ /**************************************************************************//** @Group QM_runtime_control_grp QM (common) Runtime Control Unit @Description QM (common) Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description enum for defining QM counters *//***************************************************************************/ typedef enum e_QmCounters { e_QM_COUNTERS_SFDR_IN_USE = 0, /**< Total Single Frame Descriptor Record (SFDR) currently in use */ e_QM_COUNTERS_PFDR_IN_USE, /**< Total Packed Frame Descriptor Record (PFDR) currently in use */ e_QM_COUNTERS_PFDR_FREE_POOL /**< Total Packed Frame Descriptor Record (PFDR) Free Pool Count in external memory */ } e_QmCounters; /**************************************************************************//** @Description structure for returning revision information *//***************************************************************************/ typedef struct t_QmRevisionInfo { uint8_t majorRev; /**< Major revision */ uint8_t minorRev; /**< Minor revision */ } t_QmRevisionInfo; /**************************************************************************//** @Description structure representing QM FQ-Range reservation parameters *//***************************************************************************/ typedef struct t_QmRsrvFqrParams { bool useForce; /**< TRUE - force reservation of specific fqids; FALSE - reserve several fqids */ uint32_t numOfFqids; /**< number of fqids to be reserved. */ union{ struct { uint32_t align; /**< alignment. will be used if useForce=FALSE */ } nonFrcQs; struct { uint32_t fqid; /**< the fqid base of the forced fqids. will be used if useForce=TRUE */ } frcQ; } qs; } t_QmRsrvFqrParams; /**************************************************************************//** @Description structure representing QM Error information *//***************************************************************************/ typedef struct t_QmErrorInfo { bool portalValid; bool hwPortal; e_DpaaSwPortal swPortalId; /**< Sw Portal id */ e_DpaaDcPortal dcpId; /**< Dcp (hw Portal) id */ bool fqidValid; uint32_t fqid; } t_QmErrorInfo; /**************************************************************************//** @Function QM_ReserveQueues @Description Request to Reserved queues for future use. @Param[in] h_Qm - A handle to the QM Module. @Param[in] p_QmFqrParams - A structure of parameters for defining the desired queues parameters. @Param[out] p_BaseFqid - base-fqid on success; '0' code otherwise. @Return E_OK on success; @Cautions Allowed only after QM_Init(). *//***************************************************************************/ t_Error QM_ReserveQueues(t_Handle h_Qm, t_QmRsrvFqrParams *p_QmFqrParams, uint32_t *p_BaseFqid); #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) /**************************************************************************//** @Function QM_DumpRegs @Description Dumps all QM registers @Param[in] h_Qm - A handle to the QM Module. @Return E_OK on success; @Cautions Allowed only after QM_Init(). *//***************************************************************************/ t_Error QM_DumpRegs(t_Handle h_Qm); #endif /* (defined(DEBUG_ERRORS) && ... */ /**************************************************************************//** @Function QM_SetException @Description Calling this routine enables/disables the specified exception. @Param[in] h_Qm - A handle to the QM Module. @Param[in] exception - The exception to be selected. @Param[in] enable - TRUE to enable interrupt, FALSE to mask it. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init(). This routine should NOT be called from guest-partition (i.e. guestId != NCSW_MASTER_ID) *//***************************************************************************/ t_Error QM_SetException(t_Handle h_Qm, e_QmExceptions exception, bool enable); /**************************************************************************//** @Function QM_ErrorIsr @Description QM interrupt-service-routine for errors. @Param[in] h_Qm - A handle to the QM module @Cautions Allowed only following QM_Init(). This routine should NOT be called from guest-partition (i.e. guestId != NCSW_MASTER_ID) *//***************************************************************************/ void QM_ErrorIsr(t_Handle h_Qm); /**************************************************************************//** @Function QM_GetErrorInformation @Description Reads the last error information. @Param[in] h_Qm - A handle to the QM Module. @Param[out] p_errInfo - the information will be loaded to this struct. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init(). This routine should NOT be called from guest-partition (i.e. guestId != NCSW_MASTER_ID) *//***************************************************************************/ t_Error QM_GetErrorInformation(t_Handle h_Qm, t_QmErrorInfo *p_errInfo); /**************************************************************************//** @Function QM_GetCounter @Description Reads one of the QM counters. @Param[in] h_Qm - A handle to the QM Module. @Param[in] counter - The requested counter. @Return Counter's current value. @Cautions Allowed only following QM_Init(). *//***************************************************************************/ uint32_t QM_GetCounter(t_Handle h_Qm, e_QmCounters counter); /**************************************************************************//** @Function QM_GetRevision @Description Returns the QM revision @Param[in] h_Qm A handle to a QM Module. @Param[out] p_QmRevisionInfo A structure of revision information parameters. @Return None. @Cautions Allowed only following QM_Init(). *//***************************************************************************/ t_Error QM_GetRevision(t_Handle h_Qm, t_QmRevisionInfo *p_QmRevisionInfo); /** @} */ /* end of QM_runtime_control_grp group */ /**************************************************************************//** @Group QM_runtime_data_grp QM (common) Runtime Data Unit @Description QM (common) Runtime data unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Function QM_Poll @Description Poll frames from QM. @Param[in] h_Qm - A handle to the QM module @Param[in] source - The selected frames type to poll @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init(). *//***************************************************************************/ t_Error QM_Poll(t_Handle h_Qm, e_QmPortalPollSource source); /** @} */ /* end of QM_runtime_data_grp group */ /** @} */ /* end of QM_lib_grp group */ /**************************************************************************//** @Group QM_portal_grp QM-Portal API @Description QM common API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group QM_portal_init_grp QM-Portal Initialization Unit @Description QM-Portal Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing QM-Portal Stash parameters *//***************************************************************************/ typedef struct { uint8_t stashDestQueue; /**< This value is used to direct all stashing transactions initiated on behalf of this software portal to the specific Stashing Request Queues (SRQ) */ uint8_t eqcr; /**< If 0, disabled. If 1, for every EQCR entry consumed by QMan a new stash transaction is performed. If 2-7, after 2-7 EQCR entries being consumed by QMAN a new stash transaction is performed. */ bool eqcrHighPri; /**< EQCR entry stash transactions for this software portal will be signaled with higher priority. */ bool dqrr; /**< DQRR entry stash enable/disable */ uint16_t dqrrLiodn; /**< This value is attached to every transaction initiated by QMan when performing DQRR entry or EQCR_CI stashing on behalf of this software portal */ bool dqrrHighPri; /**< DQRR entry stash transactions for this software portal will be signaled with higher priority. */ bool fdFq; /**< Dequeued Frame Data, Annotation, and FQ Context Stashing enable/disable */ uint16_t fdFqLiodn; /**< This value is attached to every transaction initiated by QMan when performing dequeued frame data and annotation stashing, or FQ context stashing on behalf of this software portal */ bool fdFqHighPri; /**< Dequeued frame data, annotation, and FQ context stash transactions for this software portal will be signaled with higher priority. */ bool fdFqDrop; /**< If True, Dequeued frame data, annotation, and FQ context stash transactions for this software portal will be dropped by QMan if the target SRQ is almost full, to prevent QMan sequencer stalling. Stash transactions that are dropped will result in a fetch from main memory when a core reads the addressed coherency granule. If FALSE, Dequeued frame data, annotation, and FQ context stash transactions for this software portal will never be dropped by QMan. If the target SRQ is full a sequencer will stall until each stash transaction can be completed. */ } t_QmPortalStashParam; /**************************************************************************//** @Description structure representing QM-Portal initialization parameters *//***************************************************************************/ typedef struct { uintptr_t ceBaseAddress; /**< Cache-enabled base address (virtual) */ uintptr_t ciBaseAddress; /**< Cache-inhibited base address (virtual) */ t_Handle h_Qm; /**< Qm Handle */ e_DpaaSwPortal swPortalId; /**< Portal id */ int irq; /**< portal interrupt line; used only if useIrq set to TRUE */ uint16_t fdLiodnOffset; /**< liodn to be used for all frames enqueued via this software portal */ t_QmReceivedFrameCallback *f_DfltFrame; /**< this callback will be called unless specific callback assigned to the FQ*/ t_QmRejectedFrameCallback *f_RejectedFrame; /**< this callback will be called for rejected frames. */ t_Handle h_App; /**< a handle to the upper layer; It will be passed by the driver upon calling the CB */ } t_QmPortalParam; /**************************************************************************//** @Function QM_PORTAL_Config @Description Creates descriptor for a QM-Portal module. The routine returns a handle (descriptor) to a QM-Portal object. This descriptor must be passed as first parameter to all other QM-Portal function calls. No actual initialization or configuration of QM-Portal hardware is done by this routine. @Param[in] p_QmPortalParam - Pointer to data structure of parameters @Retval Handle to a QM-Portal object, or NULL for Failure. *//***************************************************************************/ t_Handle QM_PORTAL_Config(t_QmPortalParam *p_QmPortalParam); /**************************************************************************//** @Function QM_PORTAL_Init @Description Initializes a QM-Portal module @Param[in] h_QmPortal - A handle to a QM-Portal module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error QM_PORTAL_Init(t_Handle h_QmPortal); /**************************************************************************//** @Function QM_PORTAL_Free @Description Frees all resources that were assigned to a QM-Portal module. Calling this routine invalidates the descriptor. @Param[in] h_QmPortal - A handle to a QM-Portal module @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error QM_PORTAL_Free(t_Handle h_QmPortal); /**************************************************************************//** @Group QM_portal_advanced_init_grp QM-Portal Advanced Configuration Unit @Description Configuration functions used to change default values. @{ *//***************************************************************************/ /**************************************************************************//** @Function QM_PORTAL_ConfigDcaMode @Description Change the Discrate Consumption Acknowledge mode from its default configuration [FALSE]. @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[in] enable - Enable/Disable DCA mode @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Config() and before QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_ConfigDcaMode(t_Handle h_QmPortal, bool enable); /**************************************************************************//** @Function QM_PORTAL_ConfigStash @Description Config the portal to active stash mode. @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[in] p_StashParams - Pointer to data structure of parameters @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Config() and before QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_ConfigStash(t_Handle h_QmPortal, t_QmPortalStashParam *p_StashParams); /**************************************************************************//** @Function QM_PORTAL_ConfigPullMode @Description Change the Pull Mode from its default configuration [FALSE]. @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[in] pullMode - When TRUE, the Portal will work in pull mode. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Config() and before QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_ConfigPullMode(t_Handle h_QmPortal, bool pullMode); /** @} */ /* end of QM_portal_advanced_init_grp group */ /** @} */ /* end of QM_portal_init_grp group */ /**************************************************************************//** @Group QM_portal_runtime_control_grp QM-Portal Runtime Control Unit @Description QM-Portal Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Function QM_PORTAL_AddPoolChannel @Description Adding the pool channel to the SW-Portal's scheduler. the sw-portal will get frames that came from the pool channel. @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[in] poolChannelId - Pool channel id. must between '0' to QM_MAX_NUM_OF_POOL_CHANNELS @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_AddPoolChannel(t_Handle h_QmPortal, uint8_t poolChannelId); /** @} */ /* end of QM_portal_runtime_control_grp group */ /**************************************************************************//** @Group QM_portal_runtime_data_grp QM-Portal Runtime Data Unit @Description QM-Portal Runtime data unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing QM Portal Frame Info *//***************************************************************************/ typedef struct t_QmPortalFrameInfo { t_Handle h_App; t_Handle h_QmFqr; uint32_t fqidOffset; t_DpaaFD frame; } t_QmPortalFrameInfo; /**************************************************************************//** @Function QM_PORTAL_Poll @Description Poll frames from the specified sw-portal. @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[in] source - The selected frames type to poll @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_Poll(t_Handle h_QmPortal, e_QmPortalPollSource source); /**************************************************************************//** @Function QM_PORTAL_PollFrame @Description Poll frames from the specified sw-portal. will poll only data frames @Param[in] h_QmPortal - A handle to a QM-Portal module @Param[out] p_frameInfo - A structure to hold the dequeued frame information @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_PORTAL_PollFrame(t_Handle h_QmPortal, t_QmPortalFrameInfo *p_frameInfo); /** @} */ /* end of QM_portal_runtime_data_grp group */ /** @} */ /* end of QM_portal_grp group */ /**************************************************************************//** @Group QM_fqr_grp QM Frame-Queue-Range API @Description QM-FQR API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group QM_fqr_init_grp QM-FQR Initialization Unit @Description QM-FQR Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing QM FQ-Range congestion group parameters *//***************************************************************************/ typedef struct { t_Handle h_QmCg; /**< A handle to the congestion group. */ int8_t overheadAccountingLength; /**< For each frame add this number for CG calculation (may be negative), if 0 - disable feature */ uint32_t fqTailDropThreshold; /**< if not "0" - enable tail drop on this FQR */ } t_QmFqrCongestionAvoidanceParams; /**************************************************************************//** @Description structure representing QM FQ-Range initialization parameters *//***************************************************************************/ typedef struct { t_Handle h_Qm; /**< A handle to a QM module */ t_Handle h_QmPortal; /**< A handle to a QM Portal Module; will be used only for Init and Free routines; NOTE : if NULL, assuming affinity */ bool initParked; /**< This FQ-Range will be initialize in park state (un-schedule) */ bool holdActive; /**< This FQ-Range can be parked (un-schedule); This affects only on queues destined to software portals*/ bool preferInCache; /**< Prefer this FQ-Range to be in QMAN's internal cache for all states */ bool useContextAForStash;/**< This FQ-Range will use context A for stash */ union { struct { uint8_t frameAnnotationSize;/**< Size of Frame Annotation to be stashed */ uint8_t frameDataSize; /**< Size of Frame Data to be stashed. */ uint8_t fqContextSize; /**< Size of FQ context to be stashed. */ uint64_t fqContextAddr; /**< 40 bit memory address containing the FQ context information to be stashed; Must be cacheline-aligned */ } stashingParams; t_QmContextA *p_ContextA; /**< context-A field to be written in the FQ structure */ }; t_QmContextB *p_ContextB; /**< context-B field to be written in the FQ structure; Note that this field may be used for Tx queues only! */ e_QmFQChannel channel; /**< Qm Channel */ uint8_t wq; /**< Work queue within the channel */ bool shadowMode; /**< If TRUE, useForce MUST set to TRUE and numOfFqids MUST set to '1' */ uint32_t numOfFqids; /**< number of fqids to be allocated*/ bool useForce; /**< TRUE - force allocation of specific fqids; FALSE - allocate several fqids */ union{ struct { uint32_t align; /**< alignment. will be used if useForce=FALSE */ } nonFrcQs; struct { uint32_t fqid; /**< the fqid base of the forced fqids. will be used if useForce=TRUE */ } frcQ; } qs; bool congestionAvoidanceEnable; /**< TRUE to enable congestion avoidance mechanism */ t_QmFqrCongestionAvoidanceParams congestionAvoidanceParams; /**< Parameters for congestion avoidance */ } t_QmFqrParams; /**************************************************************************//** @Function QM_FQR_Create @Description Initializing and enabling a Frame-Queue-Range. This routine should be called for adding an FQR. @Param[in] p_QmFqrParams - A structure of parameters for defining the desired queues parameters. @Return A handle to the initialized FQR on success; NULL code otherwise. @Cautions Allowed only following QM_Init(). *//***************************************************************************/ t_Handle QM_FQR_Create(t_QmFqrParams *p_QmFqrParams); /**************************************************************************//** @Function QM_FQR_Free @Description Deleting and free all resources of an initialized FQR. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_FQR_Create() for this FQR. *//***************************************************************************/ t_Error QM_FQR_Free(t_Handle h_QmFqr); /**************************************************************************//** @Function QM_FQR_FreeWDrain @Description Deleting and free all resources of an initialized FQR with the option of draining. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] f_CompletionCB - Pointer to a completion callback to be used in non-blocking mode. @Param[in] deliverFrame - TRUE for deliver the drained frames to the user; FALSE for not deliver the frames. @Param[in] f_CallBack - Pointer to a callback to handle the delivered frames. @Param[in] h_App - User's application descriptor. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_FQR_Create() for this FQR. *//***************************************************************************/ t_Error QM_FQR_FreeWDrain(t_Handle h_QmFqr, t_QmFqrDrainedCompletionCB *f_CompletionCB, bool deliverFrame, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App); /** @} */ /* end of QM_fqr_init_grp group */ /**************************************************************************//** @Group QM_fqr_runtime_control_grp QM-FQR Runtime Control Unit @Description QM-FQR Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description enum for defining QM-FQR counters *//***************************************************************************/ typedef enum e_QmFqrCounters { e_QM_FQR_COUNTERS_FRAME = 0, /**< Total number of frames on this frame queue */ e_QM_FQR_COUNTERS_BYTE /**< Total number of bytes in all frames on this frame queue */ } e_QmFqrCounters; /**************************************************************************//** @Function QM_FQR_RegisterCB @Description Register a callback routine to be called when a frame comes from this FQ-Range @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] f_CallBack - An application callback @Param[in] h_App - User's application descriptor @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ t_Error QM_FQR_RegisterCB(t_Handle h_QmFqr, t_QmReceivedFrameCallback *f_CallBack, t_Handle h_App); /**************************************************************************//** @Function QM_FQR_Resume @Description Request to Re-Schedule this Fqid. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] h_QmPortal - A handle to a QM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] fqidOffset - Fqid offset within the FQ-Range. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ t_Error QM_FQR_Resume(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset); /**************************************************************************//** @Function QM_FQR_Suspend @Description Request to Un-Schedule this Fqid. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] h_QmPortal - A handle to a QM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] fqidOffset - Fqid offset within the FQ-Range. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ t_Error QM_FQR_Suspend(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset); /**************************************************************************//** @Function QM_FQR_GetFqid @Description Returned the Fqid base of the FQ-Range @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Return Fqid base. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ uint32_t QM_FQR_GetFqid(t_Handle h_QmFqr); /**************************************************************************//** @Function QM_FQR_GetCounter @Description Reads one of the QM-FQR counters. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] h_QmPortal - A handle to a QM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] fqidOffset - Fqid offset within the FQ-Range. @Param[in] counter - The requested counter. @Return Counter's current value. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ uint32_t QM_FQR_GetCounter(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, e_QmFqrCounters counter); /** @} */ /* end of QM_fqr_runtime_control_grp group */ /**************************************************************************//** @Group QM_fqr_runtime_data_grp QM-FQR Runtime Data Unit @Description QM-FQR Runtime data unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Function QM_FQR_Enqueue @Description Enqueue the frame into the FQ to be transmitted. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] h_QmPortal - A handle to a QM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] fqidOffset - Fqid offset within the FQ-Range. @Param[in] p_Frame - Pointer to the frame to be enqueued. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_FQR_Create(). *//***************************************************************************/ t_Error QM_FQR_Enqueue(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame); /**************************************************************************//** @Function QM_FQR_PullFrame @Description Perform a Pull command. @Param[in] h_QmFqr - A handle to a QM-FQR Module. @Param[in] h_QmPortal - A handle to a QM Portal Module; NOTE : if NULL, assuming affinity. @Param[in] fqidOffset - Fqid offset within the FQ-Range. @Param[out] p_Frame - The Received Frame @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_PORTAL_Init(). *//***************************************************************************/ t_Error QM_FQR_PullFrame(t_Handle h_QmFqr, t_Handle h_QmPortal, uint32_t fqidOffset, t_DpaaFD *p_Frame); /** @} */ /* end of QM_fqr_runtime_data_grp group */ /** @} */ /* end of QM_fqr_grp group */ /**************************************************************************//** @Group QM_cg_grp QM Congestion Group API @Description QM-CG API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Group QM_cg_init_grp QM-Congestion Group Initialization Unit @Description QM-CG Initialization Unit @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing QM CG WRED curve *//***************************************************************************/ typedef struct t_QmCgWredCurve { uint32_t maxTh; /**< minimum threshold - below this level all packets are rejected (approximated to be expressed as x*2^y due to HW implementation)*/ uint32_t minTh; /**< minimum threshold - below this level all packets are accepted (approximated due to HW implementation)*/ uint8_t probabilityDenominator; /**< 1-64, the fraction of packets dropped when the average queue depth is at the maximum threshold.(approximated due to HW implementation). */ } t_QmCgWredCurve; /**************************************************************************//** @Description structure representing QM CG WRED parameters *//***************************************************************************/ typedef struct t_QmCgWredParams { bool enableGreen; t_QmCgWredCurve greenCurve; bool enableYellow; t_QmCgWredCurve yellowCurve; bool enableRed; t_QmCgWredCurve redCurve; } t_QmCgWredParams; /**************************************************************************//** @Description structure representing QM CG configuration parameters *//***************************************************************************/ typedef struct t_QmCgParams { t_Handle h_Qm; /**< A handle to a QM module */ t_Handle h_QmPortal; /**< A handle to a QM Portal Module; will be used for Init, Free and as an interrupt destination for cg state change (if CgStateChangeEnable = TRUE) */ bool frameCount; /**< TRUE for frame count, FALSE - byte count */ bool wredEnable; /**< if TRUE - WRED enabled. Each color is enabled independently so that some colors may use WRED, but others may use Tail drop - if enabled, or none. */ t_QmCgWredParams wredParams; /**< WRED parameters, relevant if wredEnable = TRUE*/ bool tailDropEnable; /**< if TRUE - Tail drop enabled */ uint32_t threshold; /**< If Tail drop - used as Tail drop threshold, otherwise 'threshold' may still be used to receive notifications when threshold is passed. If threshold and f_Exception are set, interrupts are set defaultly by driver. */ bool notifyDcPortal; /**< Relevant if this CG receives enqueues from a direct portal e_DPAA_DCPORTAL0 or e_DPAA_DCPORTAL1. TRUE to notify the DC portal, FALSE to notify this SW portal. */ e_DpaaDcPortal dcPortalId; /**< relevant if notifyDcPortal=TRUE - DC Portal id */ t_QmExceptionsCallback *f_Exception; /**< relevant and mandatory if threshold is configured and notifyDcPortal = FALSE. If threshold and f_Exception are set, interrupts are set defaultly by driver */ t_Handle h_App; /**< A handle to the application layer, will be passed as argument to f_Exception */ } t_QmCgParams; /**************************************************************************//** @Function QM_CG_Create @Description Create and configure a congestion Group. @Param[in] p_CgParams - CG parameters @Return A handle to the CG module @Cautions Allowed only following QM_Init(). *//***************************************************************************/ t_Handle QM_CG_Create(t_QmCgParams *p_CgParams); /**************************************************************************//** @Function QM_CG_Free @Description Deleting and free all resources of an initialized CG. @Param[in] h_QmCg - A handle to a QM-CG Module. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_CR_Create() for this CG. *//***************************************************************************/ t_Error QM_CG_Free(t_Handle h_QmCg); /** @} */ /* end of QM_cg_init_grp group */ /**************************************************************************//** @Group QM_cg_runtime_control_grp QM-CG Runtime Control Unit @Description QM-CG Runtime control unit API functions, definitions and enums. @{ *//***************************************************************************/ /**************************************************************************//** @Description structure representing QM CG WRED colors *//***************************************************************************/ typedef enum e_QmCgColor { e_QM_CG_COLOR_GREEN, e_QM_CG_COLOR_YELLOW, e_QM_CG_COLOR_RED } e_QmCgColor; /**************************************************************************//** @Description structure representing QM CG modification parameters *//***************************************************************************/ typedef struct t_QmCgModifyWredParams { e_QmCgColor color; bool enable; t_QmCgWredCurve wredParams; } t_QmCgModifyWredParams; /**************************************************************************//** @Function QM_CG_SetException @Description Set CG exception. @Param[in] h_QmCg - A handle to a QM-CG Module. @Param[in] exception - exception enum @Param[in] enable - TRUE to enable, FALSE to disable. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_CG_Create() for this CG. *//***************************************************************************/ t_Error QM_CG_SetException(t_Handle h_QmCg, e_QmExceptions exception, bool enable); /**************************************************************************//** @Function QM_CG_ModifyWredCurve @Description Change WRED curve parameters for a selected color. Note that this routine may be called only for valid CG's that already have been configured for WRED, and only need a change in the WRED parameters. @Param[in] h_QmCg - A handle to a QM-CG Module. @Param[in] p_QmCgModifyParams - A structure of new WRED parameters. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_CG_Create() for this CG. *//***************************************************************************/ t_Error QM_CG_ModifyWredCurve(t_Handle h_QmCg, t_QmCgModifyWredParams *p_QmCgModifyParams); /**************************************************************************//** @Function QM_CG_ModifyTailDropThreshold @Description Change WRED curve parameters for a selected color. Note that this routine may be called only for valid CG's that already have been configured for tail drop, and only need a change in the threshold value. @Param[in] h_QmCg - A handle to a QM-CG Module. @Param[in] threshold - New threshold. @Return E_OK on success; Error code otherwise. @Cautions Allowed only following QM_Init() and QM_CG_Create() for this CG. *//***************************************************************************/ t_Error QM_CG_ModifyTailDropThreshold(t_Handle h_QmCg, uint32_t threshold); /** @} */ /* end of QM_cg_runtime_control_grp group */ /** @} */ /* end of QM_cg_grp group */ /** @} */ /* end of QM_grp group */ #endif /* __QM_EXT_H */ Index: head/sys/contrib/ncsw/inc/error_ext.h =================================================================== --- head/sys/contrib/ncsw/inc/error_ext.h (revision 307541) +++ head/sys/contrib/ncsw/inc/error_ext.h (revision 307542) @@ -1,554 +1,555 @@ /* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Freescale Semiconductor nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @File error_ext.h @Description Error definitions. *//***************************************************************************/ #ifndef __ERROR_EXT_H #define __ERROR_EXT_H #include "std_ext.h" #include "xx_ext.h" #include "core_ext.h" /**************************************************************************//** @Group gen_id General Drivers Utilities @Description External routines. @{ *//***************************************************************************/ /**************************************************************************//** @Group gen_error_id Errors, Events and Debug @Description External routines. @{ *//***************************************************************************/ /****************************************************************************** The scheme below provides the bits description for error codes: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Reserved (should be zero) | Module ID | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Error Type | ******************************************************************************/ #define ERROR_CODE(_err) ((((uint32_t)_err) & 0x0000FFFF) | __ERR_MODULE__) #define GET_ERROR_TYPE(_errcode) ((_errcode) & 0x0000FFFF) /**< Extract module code from error code (#t_Error) */ #define GET_ERROR_MODULE(_errcode) ((_errcode) & 0x00FF0000) /**< Extract error type (#e_ErrorType) from error code (#t_Error) */ /**************************************************************************//** @Description Error Type Enumeration *//***************************************************************************/ typedef enum e_ErrorType /* Comments / Associated Message Strings */ { /* ------------------------------------------------------------ */ E_OK = 0 /* Never use "RETURN_ERROR" with E_OK; Use "return E_OK;" */ /* Invalid Function Calls */ ,E_INVALID_STATE /**< The operation is not allowed in current module state. */ /* String: none. */ ,E_INVALID_OPERATION /**< The operation/command is invalid (unrecognized). */ /* String: none. */ ,E_NOT_SUPPORTED /**< The function is not supported or not implemented. */ /* String: none. */ ,E_NO_DEVICE /**< The associated device is not initialized. */ /* String: none. */ /* Invalid Parameters */ ,E_INVALID_HANDLE /**< Invalid handle of module or object. */ /* String: none, unless the function takes in more than one handle (in this case add the handle description) */ ,E_INVALID_ID /**< Invalid module ID (usually enumeration or index). */ /* String: none, unless the function takes in more than one ID (in this case add the ID description) */ ,E_NULL_POINTER /**< Unexpected NULL pointer. */ /* String: pointer description. */ ,E_INVALID_VALUE /**< Invalid value. */ /* Use for non-enumeration parameters, and only when other error types are not suitable. String: parameter description + "(should be )", e.g: "Maximum Rx buffer length (should be divisible by 8)", "Channel number (should be even)". */ ,E_INVALID_SELECTION /**< Invalid selection or mode. */ /* Use for enumeration values, only when other error types are not suitable. String: parameter description. */ ,E_INVALID_COMM_MODE /**< Invalid communication mode. */ /* String: none, unless the function takes in more than one communication mode indications (in this case add parameter description). */ ,E_INVALID_BYTE_ORDER /**< Invalid byte order. */ /* String: none, unless the function takes in more than one byte order indications (in this case add parameter description). */ ,E_INVALID_MEMORY_TYPE /**< Invalid memory type. */ /* String: none, unless the function takes in more than one memory types (in this case add memory description, e.g: "Data memory", "Buffer descriptors memory"). */ ,E_INVALID_INTR_QUEUE /**< Invalid interrupt queue. */ /* String: none, unless the function takes in more than one interrupt queues (in this case add queue description, e.g: "Rx interrupt queue", "Tx interrupt queue"). */ ,E_INVALID_PRIORITY /**< Invalid priority. */ /* String: none, unless the function takes in more than one priority (in this case add priority description). */ ,E_INVALID_CLOCK /**< Invalid clock. */ /* String: none, unless the function takes in more than one clocks (in this case add clock description, e.g: "Rx clock", "Tx clock"). */ ,E_INVALID_RATE /**< Invalid rate value. */ /* String: none, unless the function takes in more than one rate values (in this case add rate description). */ ,E_INVALID_ADDRESS /**< Invalid address. */ /* String: description of the specific violation. */ ,E_INVALID_BUS /**< Invalid bus type. */ /* String: none, unless the function takes in more than one bus parameters (in this case add bus description). */ ,E_BUS_CONFLICT /**< Bus (or memory) type conflicts with another setting. */ /* String: description of the conflicting buses/memories. */ ,E_CONFLICT /**< Some setting conflicts with another setting. */ /* String: description of the conflicting settings. */ ,E_NOT_ALIGNED /**< Non-aligned address. */ /* String: parameter description + "(should be %d-bytes aligned)", e.g: "Rx data buffer (should be 32-bytes aligned)". */ ,E_NOT_IN_RANGE /**< Parameter value is out of range. */ /* Don't use this error for enumeration parameters. String: parameter description + "(should be %d-%d)", e.g: "Number of pad characters (should be 0-15)". */ /* Frame/Buffer Errors */ ,E_INVALID_FRAME /**< Invalid frame object (NULL handle or missing buffers). */ /* String: none. */ ,E_EMPTY_FRAME /**< Frame object is empty (has no buffers). */ /* String: none. */ ,E_EMPTY_BUFFER /**< Buffer object is empty (no data, or zero data length). */ /* String: none. */ /* Resource Errors */ ,E_NO_MEMORY /**< External memory allocation failed. */ /* String: description of item for which allocation failed. */ ,E_NOT_FOUND /**< Requested resource or item was not found. */ /* Use only when the resource/item is uniquely identified. String: none, unless the operation is not the main goal of the function (in this case add item description). */ ,E_NOT_AVAILABLE /**< Resource is unavailable. */ /* String: none, unless the operation is not the main goal of the function (in this case add resource description). */ ,E_ALREADY_EXISTS /**< Requested resource or item already exists. */ /* Use when resource duplication or sharing are not allowed. String: none, unless the operation is not the main goal of the function (in this case add item description). */ ,E_FULL /**< Resource is full. */ /* String: none, unless the operation is not the main goal of the function (in this case add resource description). */ ,E_EMPTY /**< Resource is empty. */ /* String: none, unless the operation is not the main goal of the function (in this case add resource description). */ ,E_BUSY /**< Resource or module is busy. */ /* String: none, unless the operation is not the main goal of the function (in this case add resource description). */ ,E_ALREADY_FREE /**< Specified resource or item is already free or deleted. */ /* String: none, unless the operation is not the main goal of the function (in this case add item description). */ /* Read/Write Access Errors */ ,E_READ_FAILED /**< Read access failed on memory/device. */ /* String: none, or device name. */ ,E_WRITE_FAILED /**< Write access failed on memory/device. */ /* String: none, or device name. */ /* Send/Receive Failures */ ,E_SEND_FAILED /**< Send operation failed on device. */ /* String: none, or device name. */ ,E_RECEIVE_FAILED /**< Receive operation failed on device. */ /* String: none, or device name. */ /* Operation time-out */ ,E_TIMEOUT /**< The operation timed out. */ /* String: none. */ ,E_DUMMY_LAST /* NEVER USED */ } e_ErrorType; /**************************************************************************//** @Description Event Type Enumeration *//***************************************************************************/ typedef enum e_Event /* Comments / Associated Flags and Message Strings */ { /* ------------------------------------------------------------ */ EV_NO_EVENT = 0 /**< No event; Never used. */ ,EV_RX_DISCARD /**< Received packet discarded (by the driver, and only for complete packets); Flags: error flags in case of error, zero otherwise. */ /* String: reason for discard, e.g: "Error in frame", "Disordered frame", "Incomplete frame", "No frame object". */ ,EV_RX_ERROR /**< Receive error (by hardware/firmware); Flags: usually status flags from the buffer descriptor. */ /* String: none. */ ,EV_TX_ERROR /**< Transmit error (by hardware/firmware); Flags: usually status flags from the buffer descriptor. */ /* String: none. */ ,EV_NO_BUFFERS /**< System ran out of buffer objects; Flags: zero. */ /* String: none. */ ,EV_NO_MB_FRAMES /**< System ran out of multi-buffer frame objects; Flags: zero. */ /* String: none. */ ,EV_NO_SB_FRAMES /**< System ran out of single-buffer frame objects; Flags: zero. */ /* String: none. */ ,EV_TX_QUEUE_FULL /**< Transmit queue is full; Flags: zero. */ /* String: none. */ ,EV_RX_QUEUE_FULL /**< Receive queue is full; Flags: zero. */ /* String: none. */ ,EV_INTR_QUEUE_FULL /**< Interrupt queue overflow; Flags: zero. */ /* String: none. */ ,EV_NO_DATA_BUFFER /**< Data buffer allocation (from higher layer) failed; Flags: zero. */ /* String: none. */ ,EV_OBJ_POOL_EMPTY /**< Objects pool is empty; Flags: zero. */ /* String: object description (name). */ ,EV_BUS_ERROR /**< Illegal access on bus; Flags: the address (if available) or bus identifier */ /* String: bus/address/module description. */ ,EV_PTP_TXTS_QUEUE_FULL /**< PTP Tx timestamps queue is full; Flags: zero. */ /* String: none. */ ,EV_PTP_RXTS_QUEUE_FULL /**< PTP Rx timestamps queue is full; Flags: zero. */ /* String: none. */ ,EV_DUMMY_LAST } e_Event; /**************************************************************************//** @Collection Debug Levels for Errors and Events The level description refers to errors only. For events, classification is done by the user. The TRACE, INFO and WARNING levels are allowed only when using the DBG macro, and are not allowed when using the error macros (RETURN_ERROR or REPORT_ERROR). @{ *//***************************************************************************/ #define REPORT_LEVEL_CRITICAL 1 /**< Crasher: Incorrect flow, NULL pointers/handles. */ #define REPORT_LEVEL_MAJOR 2 /**< Cannot proceed: Invalid operation, parameters or configuration. */ #define REPORT_LEVEL_MINOR 3 /**< Recoverable problem: a repeating call with the same parameters may be successful. */ #define REPORT_LEVEL_WARNING 4 /**< Something is not exactly right, yet it is not an error. */ #define REPORT_LEVEL_INFO 5 /**< Messages which may be of interest to user/programmer. */ #define REPORT_LEVEL_TRACE 6 /**< Program flow messages. */ #define EVENT_DISABLED 0xFF /**< Disabled event (not reported at all) */ /* @} */ #define NO_MSG ("") #ifndef DEBUG_GLOBAL_LEVEL #define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING #endif /* DEBUG_GLOBAL_LEVEL */ #ifndef ERROR_GLOBAL_LEVEL #define ERROR_GLOBAL_LEVEL DEBUG_GLOBAL_LEVEL #endif /* ERROR_GLOBAL_LEVEL */ #ifndef EVENT_GLOBAL_LEVEL #define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR #endif /* EVENT_GLOBAL_LEVEL */ #ifdef EVENT_LOCAL_LEVEL #define EVENT_DYNAMIC_LEVEL EVENT_LOCAL_LEVEL #else #define EVENT_DYNAMIC_LEVEL EVENT_GLOBAL_LEVEL #endif /* EVENT_LOCAL_LEVEL */ #ifndef DEBUG_DYNAMIC_LEVEL #define DEBUG_USING_STATIC_LEVEL #ifdef DEBUG_STATIC_LEVEL #define DEBUG_DYNAMIC_LEVEL DEBUG_STATIC_LEVEL #else #define DEBUG_DYNAMIC_LEVEL DEBUG_GLOBAL_LEVEL #endif /* DEBUG_STATIC_LEVEL */ #else /* DEBUG_DYNAMIC_LEVEL */ #ifdef DEBUG_STATIC_LEVEL #error "Please use either DEBUG_STATIC_LEVEL or DEBUG_DYNAMIC_LEVEL (not both)" #else int DEBUG_DYNAMIC_LEVEL = DEBUG_GLOBAL_LEVEL; #endif /* DEBUG_STATIC_LEVEL */ #endif /* !DEBUG_DYNAMIC_LEVEL */ #ifndef ERROR_DYNAMIC_LEVEL #ifdef ERROR_STATIC_LEVEL #define ERROR_DYNAMIC_LEVEL ERROR_STATIC_LEVEL #else #define ERROR_DYNAMIC_LEVEL ERROR_GLOBAL_LEVEL #endif /* ERROR_STATIC_LEVEL */ #else /* ERROR_DYNAMIC_LEVEL */ #ifdef ERROR_STATIC_LEVEL #error "Please use either ERROR_STATIC_LEVEL or ERROR_DYNAMIC_LEVEL (not both)" #else int ERROR_DYNAMIC_LEVEL = ERROR_GLOBAL_LEVEL; #endif /* ERROR_STATIC_LEVEL */ #endif /* !ERROR_DYNAMIC_LEVEL */ #define PRINT_FORMAT "[CPU%02d, %s:%d %s]" #define PRINT_FMT_PARAMS CORE_GetId(), __FILE__, __LINE__, __FUNCTION__ -#define ERR_STRING(err) #err +#define _ERR_STRING(err) #err +#define ERR_STRING(err) _ERR_STRING(err) #if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) /* No debug/error/event messages at all */ #define DBG(_level, _vmsg) #define REPORT_ERROR(_level, _err, _vmsg) #define RETURN_ERROR(_level, _err, _vmsg) \ return ERROR_CODE(_err) #if (REPORT_EVENTS > 0) #define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ do { \ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ } \ } while (0) #else #define REPORT_EVENT(_ev, _appId, _flg, _vmsg) #endif /* (REPORT_EVENTS > 0) */ #else /* DEBUG_ERRORS > 0 */ extern const char *dbgLevelStrings[]; extern const char *errTypeStrings[]; extern const char *moduleStrings[]; #if (REPORT_EVENTS > 0) extern const char *eventStrings[]; #endif /* (REPORT_EVENTS > 0) */ #if ((defined(DEBUG_USING_STATIC_LEVEL)) && (DEBUG_DYNAMIC_LEVEL < REPORT_LEVEL_WARNING)) /* No need for DBG macro - debug level is higher anyway */ #define DBG(_level, _vmsg) #else #define DBG(_level, _vmsg) \ do { \ if (REPORT_LEVEL_##_level <= DEBUG_DYNAMIC_LEVEL) { \ XX_Print("> %s (%s) " PRINT_FORMAT ": ", \ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ERR_STRING(__ERR_MODULE__), \ PRINT_FMT_PARAMS); \ XX_Print _vmsg; \ XX_Print("\r\n"); \ } \ } while (0) #endif /* (defined(DEBUG_USING_STATIC_LEVEL) && (DEBUG_DYNAMIC_LEVEL < WARNING)) */ #define REPORT_ERROR(_level, _err, _vmsg) \ do { \ if (REPORT_LEVEL_##_level <= ERROR_DYNAMIC_LEVEL) { \ XX_Print("! %s %s Error " PRINT_FORMAT ": %s; ", \ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ERR_STRING(__ERR_MODULE__), \ PRINT_FMT_PARAMS, \ errTypeStrings[(GET_ERROR_TYPE(_err) - E_OK - 1)]); \ XX_Print _vmsg; \ XX_Print("\r\n"); \ } \ } while (0) #define RETURN_ERROR(_level, _err, _vmsg) \ do { \ REPORT_ERROR(_level, (_err), _vmsg); \ return ERROR_CODE(_err); \ } while (0) #if (REPORT_EVENTS > 0) #define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ do { \ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ XX_Print("~ %s %s Event " PRINT_FORMAT ": %s (flags: 0x%04x); ", \ dbgLevelStrings[_ev##_LEVEL - 1], \ ERR_STRING(__ERR_MODULE__), \ PRINT_FMT_PARAMS, \ eventStrings[((_ev) - EV_NO_EVENT - 1)], \ (uint16_t)(_flg)); \ XX_Print _vmsg; \ XX_Print("\r\n"); \ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ } \ } while (0) #else /* not REPORT_EVENTS */ #define REPORT_EVENT(_ev, _appId, _flg, _vmsg) #endif /* (REPORT_EVENTS > 0) */ #endif /* (DEBUG_ERRORS > 0) */ /**************************************************************************//** @Function ASSERT_COND @Description Assertion macro. @Param[in] _cond - The condition being checked, in positive form; Failure of the condition triggers the assert. *//***************************************************************************/ #ifdef DISABLE_ASSERTIONS #define ASSERT_COND(_cond) #else #define ASSERT_COND(_cond) \ do { \ if (!(_cond)) { \ XX_Print("*** ASSERT_COND failed " PRINT_FORMAT "\r\n", \ PRINT_FMT_PARAMS); \ XX_Exit(1); \ } \ } while (0) #endif /* DISABLE_ASSERTIONS */ #ifdef DISABLE_INIT_PARAMETERS_CHECK #define CHECK_INIT_PARAMETERS(handle, f_check) #define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) #else #define CHECK_INIT_PARAMETERS(handle, f_check) \ do { \ t_Error err = f_check(handle); \ if (err != E_OK) { \ RETURN_ERROR(MAJOR, err, NO_MSG); \ } \ } while (0) #define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) \ do { \ t_Error err = f_check(handle); \ if (err != E_OK) { \ REPORT_ERROR(MAJOR, err, NO_MSG); \ return (retval); \ } \ } while (0) #endif /* DISABLE_INIT_PARAMETERS_CHECK */ #ifdef DISABLE_SANITY_CHECKS #define SANITY_CHECK_RETURN_ERROR(_cond, _err) #define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) #define SANITY_CHECK_RETURN(_cond, _err) #define SANITY_CHECK_EXIT(_cond, _err) #else /* DISABLE_SANITY_CHECKS */ #define SANITY_CHECK_RETURN_ERROR(_cond, _err) \ do { \ if (!(_cond)) { \ RETURN_ERROR(CRITICAL, (_err), NO_MSG); \ } \ } while (0) #define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) \ do { \ if (!(_cond)) { \ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ return (retval); \ } \ } while (0) #define SANITY_CHECK_RETURN(_cond, _err) \ do { \ if (!(_cond)) { \ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ return; \ } \ } while (0) #define SANITY_CHECK_EXIT(_cond, _err) \ do { \ if (!(_cond)) { \ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ XX_Exit(1); \ } \ } while (0) #endif /* DISABLE_SANITY_CHECKS */ /** @} */ /* end of Debug/error Utils group */ /** @} */ /* end of General Utils group */ #endif /* __ERROR_EXT_H */ Index: head/sys/contrib/ncsw/inc/xx_ext.h =================================================================== --- head/sys/contrib/ncsw/inc/xx_ext.h (revision 307541) +++ head/sys/contrib/ncsw/inc/xx_ext.h (revision 307542) @@ -1,938 +1,938 @@ /* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Freescale Semiconductor nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /**************************************************************************//** @File xx_ext.h @Description Prototypes, externals and typedefs for system-supplied (external) routines *//***************************************************************************/ #ifndef __XX_EXT_H #define __XX_EXT_H #include "std_ext.h" #include "part_ext.h" #if defined(__MWERKS__) && defined(OPTIMIZED_FOR_SPEED) #include "xx_integration_ext.h" #endif /* defined(__MWERKS__) && defined(OPTIMIZED_FOR_SPEED) */ /**************************************************************************//** @Group xx_id XX Interface (System call hooks) @Description Prototypes, externals and typedefs for system-supplied (external) routines @{ *//***************************************************************************/ #if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0)) /**************************************************************************//** @Function XX_EventById @Description Event reporting routine - executed only when REPORT_EVENTS=1. @Param[in] event - Event code (e_Event). @Param[in] appId - Application identifier. @Param[in] flags - Event flags. @Param[in] msg - Event message. @Return None *//***************************************************************************/ void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg); #else /* not REPORT_EVENTS */ #define XX_EventById(event, appId, flags, msg) #endif /* REPORT_EVENTS */ #ifdef DEBUG_XX_MALLOC void * XX_MallocDebug(uint32_t size, char *fname, int line); void * XX_MallocSmartDebug(uint32_t size, int memPartitionId, uint32_t alignment, char *fname, int line); #define XX_Malloc(sz) \ XX_MallocDebug((sz), __FILE__, __LINE__) #define XX_MallocSmart(sz, memt, al) \ XX_MallocSmartDebug((sz), (memt), (al), __FILE__, __LINE__) #else /* not DEBUG_XX_MALLOC */ /**************************************************************************//** @Function XX_Malloc @Description allocates contiguous block of memory. @Param[in] size - Number of bytes to allocate. @Return The address of the newly allocated block on success, NULL on failure. *//***************************************************************************/ void * XX_Malloc(uint32_t size); /**************************************************************************//** @Function XX_MallocSmartInit @Description Initializes SmartMalloc allocator. @Return E_OK on success, error code otherwise. *//***************************************************************************/ int XX_MallocSmartInit(void); /**************************************************************************//** @Function XX_MallocSmart @Description Allocates contiguous block of memory in a specified alignment and from the specified segment. @Param[in] size - Number of bytes to allocate. @Param[in] memPartitionId - Memory partition ID; The value zero must be mapped to the default heap partition. @Param[in] alignment - Required memory alignment (in bytes). @Return The address of the newly allocated block on success, NULL on failure. *//***************************************************************************/ void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment); #endif /* not DEBUG_XX_MALLOC */ /**************************************************************************//** @Function XX_FreeSmart @Description Frees the memory block pointed to by "p". Only for memory allocated by XX_MallocSmart @Param[in] p_Memory - pointer to the memory block. @Return None. *//***************************************************************************/ void XX_FreeSmart(void *p_Memory); /**************************************************************************//** @Function XX_Free @Description frees the memory block pointed to by "p". @Param[in] p_Memory - pointer to the memory block. @Return None. *//***************************************************************************/ void XX_Free(void *p_Memory); #ifndef NCSW_LINUX /**************************************************************************//** @Function XX_GetMemPartitionBase @Description This routine gets the address of a memory segment according to the memory type. @Param[in] memPartitionId - Memory partition ID; The value zero must be mapped to the default heap partition. @Return The address of the required memory type. *//***************************************************************************/ void * XX_GetMemPartitionBase(int memPartitionId); #endif /**************************************************************************//** @Function XX_Print @Description print a string. @Param[in] str - string to print. @Return None. *//***************************************************************************/ void XX_Print(char *str, ...); /**************************************************************************//** @Function XX_GetChar @Description Get character from console. @Return Character is returned on success. Zero is returned otherwise. *//***************************************************************************/ char XX_GetChar(void); /**************************************************************************//** @Function XX_PreallocAndBindIntr @Description Preallocate and optionally bind it to given CPU. @Param[in] irq - Interrupt ID (system-specific number). @Param[in] cpu - CPU to bind to or -1 if iRQ should be unbound. @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_PreallocAndBindIntr(int irq, unsigned int cpu); +t_Error XX_PreallocAndBindIntr(uintptr_t irq, unsigned int cpu); /**************************************************************************//** @Function XX_DeallocIntr @Description Deallocate preallocated interupt. @Param[in] irq - Interrupt ID (system-specific number). @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_DeallocIntr(int irq); +t_Error XX_DeallocIntr(uintptr_t irq); /**************************************************************************//** @Function XX_SetIntr @Description Set an interrupt service routine for a specific interrupt source. @Param[in] irq - Interrupt ID (system-specific number). @Param[in] f_Isr - Callback routine that will be called when the interrupt occurs. @Param[in] handle - The argument for the user callback routine. @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle); +t_Error XX_SetIntr(uintptr_t irq, t_Isr *f_Isr, t_Handle handle); /**************************************************************************//** @Function XX_FreeIntr @Description Free a specific interrupt and a specific callback routine. @Param[in] irq - Interrupt ID (system-specific number). @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_FreeIntr(int irq); +t_Error XX_FreeIntr(uintptr_t irq); /**************************************************************************//** @Function XX_EnableIntr @Description Enable a specific interrupt. @Param[in] irq - Interrupt ID (system-specific number). @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_EnableIntr(int irq); +t_Error XX_EnableIntr(uintptr_t irq); /**************************************************************************//** @Function XX_DisableIntr @Description Disable a specific interrupt. @Param[in] irq - Interrupt ID (system-specific number). @Return E_OK on success; error code otherwise.. *//***************************************************************************/ -t_Error XX_DisableIntr(int irq); +t_Error XX_DisableIntr(uintptr_t irq); #if !(defined(__MWERKS__) && defined(OPTIMIZED_FOR_SPEED)) /**************************************************************************//** @Function XX_DisableAllIntr @Description Disable all interrupts by masking them at the CPU. @Return A value that represents the interrupts state before the operation, and should be passed to the matching XX_RestoreAllIntr() call. *//***************************************************************************/ uint32_t XX_DisableAllIntr(void); /**************************************************************************//** @Function XX_RestoreAllIntr @Description Restore previous state of interrupts level at the CPU. @Param[in] flags - A value that represents the interrupts state to restore, as returned by the matching call for XX_DisableAllIntr(). @Return None. *//***************************************************************************/ void XX_RestoreAllIntr(uint32_t flags); #endif /* !(defined(__MWERKS__) && defined(OPTIMIZED_FOR_SPEED)) */ /**************************************************************************//** @Function XX_Call @Description Call a service in another task. Activate the routine "f" via the queue identified by "IntrManagerId". The parameter to "f" is Id - the handle of the destination object @Param[in] intrManagerId - Queue ID. @Param[in] f - routine pointer. @Param[in] Id - the parameter to be passed to f(). @Param[in] h_App - Application handle. @Param[in] flags - Unused, @Return E_OK is returned on success. E_FAIL is returned otherwise (usually an operating system level failure). *//***************************************************************************/ t_Error XX_Call( uint32_t intrManagerId, t_Error (* f)(t_Handle), t_Handle Id, t_Handle h_App, uint16_t flags ); /**************************************************************************//** @Function XX_Exit @Description Stop execution and report status (where it is applicable) @Param[in] status - exit status *//***************************************************************************/ void XX_Exit(int status); /*****************************************************************************/ /* Tasklet Service Routines */ /*****************************************************************************/ typedef t_Handle t_TaskletHandle; /**************************************************************************//** @Function XX_InitTasklet @Description Create and initialize a tasklet object. @Param[in] routine - A routine to be ran as a tasklet. @Param[in] data - An argument to pass to the tasklet. @Return Tasklet handle is returned on success. NULL is returned otherwise. *//***************************************************************************/ t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data); /**************************************************************************//** @Function XX_FreeTasklet @Description Free a tasklet object. @Param[in] h_Tasklet - A handle to a tasklet to be free. @Return None. *//***************************************************************************/ void XX_FreeTasklet (t_TaskletHandle h_Tasklet); /**************************************************************************//** @Function XX_ScheduleTask @Description Schedule a tasklet object. @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. @Param[in] immediate - Indicate whether to schedule this tasklet on the immediate queue or on the delayed one. @Return 0 - on success. Error code - otherwise. *//***************************************************************************/ int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate); /**************************************************************************//** @Function XX_FlushScheduledTasks @Description Flush all tasks there are in the scheduled tasks queue. @Return None. *//***************************************************************************/ void XX_FlushScheduledTasks(void); /**************************************************************************//** @Function XX_TaskletIsQueued @Description Check if task is queued. @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. @Return 1 - task is queued. 0 - otherwise. *//***************************************************************************/ int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet); /**************************************************************************//** @Function XX_SetTaskletData @Description Set data to a scheduled task. Used to change data of already scheduled task. @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. @Param[in] data - Data to be set. *//***************************************************************************/ void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data); /**************************************************************************//** @Function XX_GetTaskletData @Description Get the data of scheduled task. @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. @Return handle to the data of the task. *//***************************************************************************/ t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet); /**************************************************************************//** @Function XX_BottomHalf @Description Bottom half implementation, invoked by the interrupt handler. This routine handles all bottom-half tasklets with interrupts enabled. @Return None. *//***************************************************************************/ void XX_BottomHalf(void); /*****************************************************************************/ /* Spinlock Service Routines */ /*****************************************************************************/ /**************************************************************************//** @Function XX_InitSpinlock @Description Creates a spinlock. @Return Spinlock handle is returned on success; NULL otherwise. *//***************************************************************************/ t_Handle XX_InitSpinlock(void); /**************************************************************************//** @Function XX_FreeSpinlock @Description Frees the memory allocated for the spinlock creation. @Param[in] h_Spinlock - A handle to a spinlock. @Return None. *//***************************************************************************/ void XX_FreeSpinlock(t_Handle h_Spinlock); /**************************************************************************//** @Function XX_LockSpinlock @Description Locks a spinlock. @Param[in] h_Spinlock - A handle to a spinlock. @Return None. *//***************************************************************************/ void XX_LockSpinlock(t_Handle h_Spinlock); /**************************************************************************//** @Function XX_UnlockSpinlock @Description Unlocks a spinlock. @Param[in] h_Spinlock - A handle to a spinlock. @Return None. *//***************************************************************************/ void XX_UnlockSpinlock(t_Handle h_Spinlock); /**************************************************************************//** @Function XX_LockIntrSpinlock @Description Locks a spinlock (interrupt safe). @Param[in] h_Spinlock - A handle to a spinlock. @Return A value that represents the interrupts state before the operation, and should be passed to the matching XX_UnlockIntrSpinlock() call. *//***************************************************************************/ uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock); /**************************************************************************//** @Function XX_UnlockIntrSpinlock @Description Unlocks a spinlock (interrupt safe). @Param[in] h_Spinlock - A handle to a spinlock. @Param[in] intrFlags - A value that represents the interrupts state to restore, as returned by the matching call for XX_LockIntrSpinlock(). @Return None. *//***************************************************************************/ void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags); /*****************************************************************************/ /* Timers Service Routines */ /*****************************************************************************/ /**************************************************************************//** @Function XX_CurrentTime @Description Returns current system time. @Return Current system time (in milliseconds). *//***************************************************************************/ uint32_t XX_CurrentTime(void); /**************************************************************************//** @Function XX_CreateTimer @Description Creates a timer. @Return Timer handle is returned on success; NULL otherwise. *//***************************************************************************/ t_Handle XX_CreateTimer(void); /**************************************************************************//** @Function XX_FreeTimer @Description Frees the memory allocated for the timer creation. @Param[in] h_Timer - A handle to a timer. @Return None. *//***************************************************************************/ void XX_FreeTimer(t_Handle h_Timer); /**************************************************************************//** @Function XX_StartTimer @Description Starts a timer. The user can select to start the timer as periodic timer or as one-shot timer. The user should provide a callback routine that will be called when the timer expires. @Param[in] h_Timer - A handle to a timer. @Param[in] msecs - Timer expiration period (in milliseconds). @Param[in] periodic - TRUE for a periodic timer; FALSE for a one-shot timer.. @Param[in] f_TimerExpired - A callback routine to be called when the timer expires. @Param[in] h_Arg - The argument to pass in the timer-expired callback routine. @Return None. *//***************************************************************************/ void XX_StartTimer(t_Handle h_Timer, uint32_t msecs, bool periodic, void (*f_TimerExpired)(t_Handle h_Arg), t_Handle h_Arg); /**************************************************************************//** @Function XX_StopTimer @Description Frees the memory allocated for the timer creation. @Param[in] h_Timer - A handle to a timer. @Return None. *//***************************************************************************/ void XX_StopTimer(t_Handle h_Timer); /**************************************************************************//** @Function XX_GetExpirationTime @Description Returns the time (in milliseconds) remaining until the expiration of a timer. @Param[in] h_Timer - A handle to a timer. @Return The time left until the timer expires. *//***************************************************************************/ uint32_t XX_GetExpirationTime(t_Handle h_Timer); /**************************************************************************//** @Function XX_ModTimer @Description Updates the expiration time of a timer. This routine adds the given time to the current system time, and sets this value as the new expiration time of the timer. @Param[in] h_Timer - A handle to a timer. @Param[in] msecs - The new interval until timer expiration (in milliseconds). @Return None. *//***************************************************************************/ void XX_ModTimer(t_Handle h_Timer, uint32_t msecs); /**************************************************************************//** @Function XX_TimerIsActive @Description Checks whether a timer is active (pending) or not. @Param[in] h_Timer - A handle to a timer. @Return 0 - the timer is inactive; Non-zero value - the timer is active; *//***************************************************************************/ int XX_TimerIsActive(t_Handle h_Timer); /**************************************************************************//** @Function XX_Sleep @Description Non-busy wait until the desired time (in milliseconds) has passed. @Param[in] msecs - The requested sleep time (in milliseconds). @Return None. @Cautions This routine enables interrupts during its wait time. *//***************************************************************************/ uint32_t XX_Sleep(uint32_t msecs); /**************************************************************************//** @Function XX_UDelay @Description Busy-wait until the desired time (in microseconds) has passed. @Param[in] usecs - The requested delay time (in microseconds). @Return None. @Cautions It is highly unrecommended to call this routine during interrupt time, because the system time may not be updated properly during the delay loop. The behavior of this routine during interrupt time is unexpected. *//***************************************************************************/ void XX_UDelay(uint32_t usecs); /*****************************************************************************/ /* Other Service Routines */ /*****************************************************************************/ /**************************************************************************//** @Function XX_PhysToVirt @Description Translates a physical address to the matching virtual address. @Param[in] addr - The physical address to translate. @Return Virtual address. *//***************************************************************************/ void * XX_PhysToVirt(physAddress_t addr); /**************************************************************************//** @Function XX_VirtToPhys @Description Translates a virtual address to the matching physical address. @Param[in] addr - The virtual address to translate. @Return Physical address. *//***************************************************************************/ physAddress_t XX_VirtToPhys(void *addr); /**************************************************************************//** @Function XX_PortalSetInfo @Description Save physical and virtual adresses of the portals. @Param[in] dev - Portals device - either bman or qman. @Return Physical, virtual addresses and size. *//***************************************************************************/ void XX_PortalSetInfo(device_t dev); /**************************************************************************//** @Function XX_FmanSetIntrInfo @Description Workaround for FMan interrupt, which must be binded to one CPU only. @Param[in] irq - Interrupt number. @Return None. *//***************************************************************************/ void XX_FmanFixIntr(int irq); /**************************************************************************//** @Group xx_ipc XX Inter-Partition-Communication API @Description The following API is to be used when working with multiple partitions configuration. @{ *//***************************************************************************/ #define XX_IPC_MAX_ADDR_NAME_LENGTH 16 /**< Maximum length of an endpoint name string; The IPC service can use this constant to limit the storage space for IPC endpoint names. */ /**************************************************************************//** @Function t_IpcMsgCompletion @Description Callback function used upon IPC non-blocking transaction completion to return message buffer to the caller and to forward reply if available. This callback function may be attached by the source endpoint to any outgoing IPC message to indicate a non-blocking send (see also XX_IpcSendMessage() routine). Upon completion of an IPC transaction (consisting of a message and an optional reply), the IPC service invokes this callback routine to return the message buffer to the sender and to provide the received reply, if requested. User provides this function. Driver invokes it. @Param[in] h_Module - Abstract handle to the sending module - the same handle as was passed in the XX_IpcSendMessage() function; This handle is typically used to point to the internal data structure of the source endpoint. @Param[in] p_Msg - Pointer to original (sent) message buffer; The source endpoint can free (or reuse) this buffer when message completion callback is called. @Param[in] p_Reply - Pointer to (received) reply buffer; This pointer is the same as was provided by the source endpoint in XX_IpcSendMessage(). @Param[in] replyLength - Length (in bytes) of actual data in the reply buffer. @Param[in] status - Completion status - E_OK or failure indication, e.g. IPC transaction completion timeout. @Return None *//***************************************************************************/ typedef void (t_IpcMsgCompletion)(t_Handle h_Module, uint8_t *p_Msg, uint8_t *p_Reply, uint32_t replyLength, t_Error status); /**************************************************************************//** @Function t_IpcMsgHandler @Description Callback function used as IPC message handler. The IPC service invokes message handlers for each IPC message received. The actual function pointer should be registered by each destination endpoint via the XX_IpcRegisterMsgHandler() routine. User provides this function. Driver invokes it. @Param[in] h_Module - Abstract handle to the message handling module - the same handle as was passed in the XX_IpcRegisterMsgHandler() function; this handle is typically used to point to the internal data structure of the destination endpoint. @Param[in] p_Msg - Pointer to message buffer with data received from peer. @Param[in] msgLength - Length (in bytes) of message data. @Param[in] p_Reply - Pointer to reply buffer, to be filled by the message handler and then sent by the IPC service; The reply buffer is allocated by the IPC service with size equals to the replyLength parameter provided in message handler registration (see XX_IpcRegisterMsgHandler() function); If replyLength was initially specified as zero during message handler registration, the IPC service may set this pointer to NULL and assume that a reply is not needed; The IPC service is also responsible for freeing the reply buffer after the reply has been sent or dismissed. @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: [In] equals the replyLength parameter provided in message handler registration (see XX_IpcRegisterMsgHandler() function), and [Out] should be updated by message handler to the actual reply length; if this value is set to zero, the IPC service must assume that a reply should not be sent; Note: If p_Reply is not NULL, p_ReplyLength must not be NULL as well. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ typedef t_Error (t_IpcMsgHandler)(t_Handle h_Module, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength); /**************************************************************************//** @Function XX_IpcRegisterMsgHandler @Description IPC mailbox registration. This function is used for registering an IPC message handler in the IPC service. This function is called by each destination endpoint to indicate that it is ready to handle incoming messages. The IPC service invokes the message handler upon receiving a message addressed to the specified destination endpoint. @Param[in] addr - The address name string associated with the destination endpoint; This address must be unique across the IPC service domain to ensure correct message routing. @Param[in] f_MsgHandler - Pointer to the message handler callback for processing incoming message; invoked by the IPC service upon receiving a message addressed to the destination endpoint specified by the addr parameter. @Param[in] h_Module - Abstract handle to the message handling module, passed unchanged to f_MsgHandler callback function. @Param[in] replyLength - The maximal data length (in bytes) of any reply that the specified message handler may generate; the IPC service provides the message handler with buffer for reply according to the length specified here (refer also to the description of #t_IpcMsgHandler callback function type); This size shall be zero if the message handler never generates replies. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], t_IpcMsgHandler *f_MsgHandler, t_Handle h_Module, uint32_t replyLength); /**************************************************************************//** @Function XX_IpcUnregisterMsgHandler @Description Release IPC mailbox routine. This function is used for unregistering an IPC message handler from the IPC service. This function is called by each destination endpoint to indicate that it is no longer capable of handling incoming messages. @Param[in] addr - The address name string associated with the destination endpoint; This address is the same as was used when the message handler was registered via XX_IpcRegisterMsgHandler(). @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]); /**************************************************************************//** @Function XX_IpcInitSession @Description This function is used for creating an IPC session between the source endpoint and the destination endpoint. The actual implementation and representation of a session is left for the IPC service. The function returns an abstract handle to the created session. This handle shall be used by the source endpoint in subsequent calls to XX_IpcSendMessage(). The IPC service assumes that before this function is called, no messages are sent from the specified source endpoint to the specified destination endpoint. The IPC service may use a connection-oriented approach or a connectionless approach (or both) as described below. @par Connection-Oriented Approach The IPC service may implement a session in a connection-oriented approach - when this function is called, the IPC service should take the necessary steps to bring up a source-to-destination channel for messages and a destination-to-source channel for replies. The returned handle should represent the internal representation of these channels. @par Connectionless Approach The IPC service may implement a session in a connectionless approach - when this function is called, the IPC service should not perform any particular steps, but it must store the pair of source and destination addresses in some session representation and return it as a handle. When XX_IpcSendMessage() shall be called, the IPC service may use this handle to provide the necessary identifiers for routing the messages through the connectionless medium. @Param[in] destAddr - The address name string associated with the destination endpoint. @Param[in] srcAddr - The address name string associated with the source endpoint. @Return Abstract handle to the initialized session, or NULL on error. *//***************************************************************************/ t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]); /**************************************************************************//** @Function XX_IpcFreeSession @Description This function is used for terminating an existing IPC session between a source endpoint and a destination endpoint. The IPC service assumes that after this function is called, no messages shall be sent from the associated source endpoint to the associated destination endpoint. @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally returned by the XX_IpcInitSession() function. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error XX_IpcFreeSession(t_Handle h_Session); /**************************************************************************//** @Function XX_IpcSendMessage @Description IPC message send routine. This function may be used by a source endpoint to send an IPC message to a destination endpoint. The source endpoint cannot send a message to the destination endpoint without first initiating a session with that destination endpoint via XX_IpcInitSession() routine. The source endpoint must provide the buffer pointer and length of the outgoing message. Optionally, it may also provide a buffer for an expected reply. In the latter case, the transaction is not considered complete by the IPC service until the reply has been received. If the source endpoint does not provide a reply buffer, the transaction is considered complete after the message has been sent. The source endpoint must keep the message (and optional reply) buffers valid until the transaction is complete. @par Non-blocking mode The source endpoint may request a non-blocking send by providing a non-NULL pointer to a message completion callback function (f_Completion). Upon completion of the IPC transaction (consisting of a message and an optional reply), the IPC service invokes this callback routine to return the message buffer to the sender and to provide the received reply, if requested. @par Blocking mode The source endpoint may request a blocking send by setting f_Completion to NULL. The function is expected to block until the IPC transaction is complete - either the reply has been received or (if no reply was requested) the message has been sent. @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally returned by the XX_IpcInitSession() function. @Param[in] p_Msg - Pointer to message buffer to send. @Param[in] msgLength - Length (in bytes) of actual data in the message buffer. @Param[in] p_Reply - Pointer to reply buffer - if this buffer is not NULL, the IPC service fills this buffer with the received reply data; In blocking mode, the reply data must be valid when the function returns; In non-blocking mode, the reply data is valid when f_Completion is called; If this pointer is NULL, no reply is expected. @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: [In] specifies the maximal length (in bytes) of the reply buffer pointed by p_Reply, and [Out] in non-blocking mode this value is updated by the IPC service to the actual reply length (in bytes). @Param[in] f_Completion - Pointer to a completion callback to be used in non-blocking send mode; The completion callback is invoked by the IPC service upon completion of the IPC transaction (consisting of a message and an optional reply); If this pointer is NULL, the function is expected to block until the IPC transaction is complete. @Param[in] h_Arg - Abstract handle to the sending module; passed unchanged to the f_Completion callback function as the first argument. @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error XX_IpcSendMessage(t_Handle h_Session, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg); /** @} */ /* end of xx_ipc group */ /** @} */ /* end of xx_id group */ /** FreeBSD Specific additions. */ void XX_TrackInit(void); physAddress_t XX_TrackAddress(void *addr); void XX_UntrackAddress(void *addr); #endif /* __XX_EXT_H */ Index: head/sys/contrib/ncsw/user/env/xx.c =================================================================== --- head/sys/contrib/ncsw/user/env/xx.c (revision 307541) +++ head/sys/contrib/ncsw/user/env/xx.c (revision 307542) @@ -1,948 +1,948 @@ /*- * Copyright (c) 2011 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "error_ext.h" #include "std_ext.h" #include "list_ext.h" #include "mm_ext.h" /* Configuration */ /* Define the number of dTSEC ports active in system */ #define MALLOCSMART_DTSEC_IN_USE 4 /* * Calculate malloc's pool size for dTSEC's buffers. * We reserve 1MB pool for each dTSEC port. */ #define MALLOCSMART_POOL_SIZE \ (MALLOCSMART_DTSEC_IN_USE * 1024 * 1024) #define MALLOCSMART_SLICE_SIZE (PAGE_SIZE / 2) /* 2kB */ /* Defines */ #define MALLOCSMART_SIZE_TO_SLICE(x) \ (((x) + MALLOCSMART_SLICE_SIZE - 1) / MALLOCSMART_SLICE_SIZE) #define MALLOCSMART_SLICES \ MALLOCSMART_SIZE_TO_SLICE(MALLOCSMART_POOL_SIZE) /* Malloc Pool for NetCommSW */ MALLOC_DEFINE(M_NETCOMMSW, "NetCommSW", "NetCommSW software stack"); MALLOC_DEFINE(M_NETCOMMSW_MT, "NetCommSWTrack", "NetCommSW software allocation tracker"); /* MallocSmart data structures */ static void *XX_MallocSmartPool; static int XX_MallocSmartMap[MALLOCSMART_SLICES]; static struct mtx XX_MallocSmartLock; static struct mtx XX_MallocTrackLock; MTX_SYSINIT(XX_MallocSmartLockInit, &XX_MallocSmartLock, "NetCommSW MallocSmart Lock", MTX_DEF); MTX_SYSINIT(XX_MallocTrackLockInit, &XX_MallocTrackLock, "NetCommSW MallocTrack Lock", MTX_DEF); /* Interrupt info */ #define XX_INTR_FLAG_PREALLOCATED (1 << 0) #define XX_INTR_FLAG_BOUND (1 << 1) #define XX_INTR_FLAG_FMAN_FIX (1 << 2) struct XX_IntrInfo { driver_intr_t *handler; void *arg; int cpu; int flags; void *cookie; }; static struct XX_IntrInfo XX_IntrInfo[INTR_VECTORS]; /* Portal type identifiers */ enum XX_PortalIdent{ BM_PORTAL = 0, QM_PORTAL, }; /* Structure to store portals' properties */ struct XX_PortalInfo { vm_paddr_t portal_ce_pa[2][MAXCPU]; vm_paddr_t portal_ci_pa[2][MAXCPU]; uint32_t portal_ce_size[2][MAXCPU]; uint32_t portal_ci_size[2][MAXCPU]; vm_offset_t portal_ce_va[2]; vm_offset_t portal_ci_va[2]; uint32_t portal_intr[2][MAXCPU]; }; static struct XX_PortalInfo XX_PInfo; /* The lower 9 bits, through emprical testing, tend to be 0. */ #define XX_MALLOC_TRACK_SHIFT 9 typedef struct XX_MallocTrackStruct { LIST_ENTRY(XX_MallocTrackStruct) entries; physAddress_t pa; void *va; } XX_MallocTrackStruct; LIST_HEAD(XX_MallocTrackerList, XX_MallocTrackStruct) *XX_MallocTracker; u_long XX_MallocHashMask; static XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa); void XX_Exit(int status) { panic("NetCommSW: Exit called with status %i", status); } void XX_Print(char *str, ...) { va_list ap; va_start(ap, str); vprintf(str, ap); va_end(ap); } void * XX_Malloc(uint32_t size) { void *p = (malloc(size, M_NETCOMMSW, M_NOWAIT)); return (p); } static int XX_MallocSmartMapCheck(unsigned int start, unsigned int slices) { unsigned int i; mtx_assert(&XX_MallocSmartLock, MA_OWNED); for (i = start; i < start + slices; i++) if (XX_MallocSmartMap[i]) return (FALSE); return (TRUE); } static void XX_MallocSmartMapSet(unsigned int start, unsigned int slices) { unsigned int i; mtx_assert(&XX_MallocSmartLock, MA_OWNED); for (i = start; i < start + slices; i++) XX_MallocSmartMap[i] = ((i == start) ? slices : -1); } static void XX_MallocSmartMapClear(unsigned int start, unsigned int slices) { unsigned int i; mtx_assert(&XX_MallocSmartLock, MA_OWNED); for (i = start; i < start + slices; i++) XX_MallocSmartMap[i] = 0; } int XX_MallocSmartInit(void) { int error; error = E_OK; mtx_lock(&XX_MallocSmartLock); if (XX_MallocSmartPool) goto out; /* Allocate MallocSmart pool */ XX_MallocSmartPool = contigmalloc(MALLOCSMART_POOL_SIZE, M_NETCOMMSW, M_NOWAIT, 0, 0xFFFFFFFFFull, MALLOCSMART_POOL_SIZE, 0); if (!XX_MallocSmartPool) { error = E_NO_MEMORY; goto out; } out: mtx_unlock(&XX_MallocSmartLock); return (error); } void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) { unsigned int i; vm_offset_t addr; addr = 0; /* Convert alignment and size to number of slices */ alignment = MALLOCSMART_SIZE_TO_SLICE(alignment); size = MALLOCSMART_SIZE_TO_SLICE(size); /* Lock resources */ mtx_lock(&XX_MallocSmartLock); /* Allocate region */ for (i = 0; i + size <= MALLOCSMART_SLICES; i += alignment) { if (XX_MallocSmartMapCheck(i, size)) { XX_MallocSmartMapSet(i, size); addr = (vm_offset_t)XX_MallocSmartPool + (i * MALLOCSMART_SLICE_SIZE); break; } } /* Unlock resources */ mtx_unlock(&XX_MallocSmartLock); return ((void *)addr); } void XX_FreeSmart(void *p) { unsigned int start, slices; /* Calculate first slice of region */ start = MALLOCSMART_SIZE_TO_SLICE((vm_offset_t)(p) - (vm_offset_t)XX_MallocSmartPool); /* Lock resources */ mtx_lock(&XX_MallocSmartLock); KASSERT(XX_MallocSmartMap[start] > 0, ("XX_FreeSmart: Double or mid-block free!\n")); XX_UntrackAddress(p); /* Free region */ slices = XX_MallocSmartMap[start]; XX_MallocSmartMapClear(start, slices); /* Unlock resources */ mtx_unlock(&XX_MallocSmartLock); } void XX_Free(void *p) { if (p != NULL) XX_UntrackAddress(p); free(p, M_NETCOMMSW); } uint32_t XX_DisableAllIntr(void) { return (intr_disable()); } void XX_RestoreAllIntr(uint32_t flags) { intr_restore(flags); } t_Error XX_Call(uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags ) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (E_OK); } static bool XX_IsPortalIntr(int irq) { int cpu, type; /* Check interrupt numbers of all available portals */ for (cpu = 0, type = 0; XX_PInfo.portal_intr[type][cpu] != 0; cpu++) { if (irq == XX_PInfo.portal_intr[type][cpu]) { /* Found it! */ return (1); } if (XX_PInfo.portal_intr[type][cpu + 1] == 0) { type++; cpu = 0; } } return (0); } void XX_FmanFixIntr(int irq) { XX_IntrInfo[irq].flags |= XX_INTR_FLAG_FMAN_FIX; } static bool XX_FmanNeedsIntrFix(int irq) { if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_FMAN_FIX) return (1); return (0); } static void XX_Dispatch(void *arg) { struct XX_IntrInfo *info; info = arg; /* Bind this thread to proper CPU when SMP has been already started. */ if ((info->flags & XX_INTR_FLAG_BOUND) == 0 && smp_started && info->cpu >= 0) { thread_lock(curthread); sched_bind(curthread, info->cpu); thread_unlock(curthread); info->flags |= XX_INTR_FLAG_BOUND; } if (info->handler == NULL) { printf("%s(): IRQ handler is NULL!\n", __func__); return; } info->handler(info->arg); } t_Error -XX_PreallocAndBindIntr(int irq, unsigned int cpu) +XX_PreallocAndBindIntr(uintptr_t irq, unsigned int cpu) { struct resource *r; unsigned int inum; t_Error error; r = (struct resource *)irq; inum = rman_get_start(r); error = XX_SetIntr(irq, XX_Dispatch, &XX_IntrInfo[inum]); if (error != 0) return (error); XX_IntrInfo[inum].flags = XX_INTR_FLAG_PREALLOCATED; XX_IntrInfo[inum].cpu = cpu; return (E_OK); } t_Error -XX_DeallocIntr(int irq) +XX_DeallocIntr(uintptr_t irq) { struct resource *r; unsigned int inum; r = (struct resource *)irq; inum = rman_get_start(r); if ((XX_IntrInfo[inum].flags & XX_INTR_FLAG_PREALLOCATED) == 0) return (E_INVALID_STATE); XX_IntrInfo[inum].flags = 0; return (XX_FreeIntr(irq)); } t_Error -XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) +XX_SetIntr(uintptr_t irq, t_Isr *f_Isr, t_Handle handle) { device_t dev; struct resource *r; unsigned int flags; int err; r = (struct resource *)irq; dev = rman_get_device(r); irq = rman_get_start(r); /* Handle preallocated interrupts */ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) { if (XX_IntrInfo[irq].handler != NULL) return (E_BUSY); XX_IntrInfo[irq].handler = f_Isr; XX_IntrInfo[irq].arg = handle; return (E_OK); } flags = INTR_TYPE_NET | INTR_MPSAFE; /* BMAN/QMAN Portal interrupts must be exlusive */ if (XX_IsPortalIntr(irq)) flags |= INTR_EXCL; err = bus_setup_intr(dev, r, flags, NULL, f_Isr, handle, &XX_IntrInfo[irq].cookie); if (err) goto finish; /* * XXX: Bind FMan IRQ to CPU0. Current interrupt subsystem directs each * interrupt to all CPUs. Race between an interrupt assertion and * masking may occur and interrupt handler may be called multiple times * per one interrupt. FMan doesn't support such a situation. Workaround * is to bind FMan interrupt to one CPU0 only. */ #ifdef SMP if (XX_FmanNeedsIntrFix(irq)) err = powerpc_bind_intr(irq, 0); #endif finish: return (err); } t_Error -XX_FreeIntr(int irq) +XX_FreeIntr(uintptr_t irq) { device_t dev; struct resource *r; r = (struct resource *)irq; dev = rman_get_device(r); irq = rman_get_start(r); /* Handle preallocated interrupts */ if (XX_IntrInfo[irq].flags & XX_INTR_FLAG_PREALLOCATED) { if (XX_IntrInfo[irq].handler == NULL) return (E_INVALID_STATE); XX_IntrInfo[irq].handler = NULL; XX_IntrInfo[irq].arg = NULL; return (E_OK); } return (bus_teardown_intr(dev, r, XX_IntrInfo[irq].cookie)); } t_Error -XX_EnableIntr(int irq) +XX_EnableIntr(uintptr_t irq) { struct resource *r; r = (struct resource *)irq; irq = rman_get_start(r); powerpc_intr_unmask(irq); return (E_OK); } t_Error -XX_DisableIntr(int irq) +XX_DisableIntr(uintptr_t irq) { struct resource *r; r = (struct resource *)irq; irq = rman_get_start(r); powerpc_intr_mask(irq); return (E_OK); } t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (NULL); } void XX_FreeTasklet (t_TaskletHandle h_Tasklet) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (0); } void XX_FlushScheduledTasks(void) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (0); } void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (NULL); } t_Handle XX_InitSpinlock(void) { struct mtx *m; m = malloc(sizeof(*m), M_NETCOMMSW, M_NOWAIT | M_ZERO); if (!m) return (0); mtx_init(m, "NetCommSW Lock", NULL, MTX_DEF | MTX_DUPOK); return (m); } void XX_FreeSpinlock(t_Handle h_Spinlock) { struct mtx *m; m = h_Spinlock; mtx_destroy(m); free(m, M_NETCOMMSW); } void XX_LockSpinlock(t_Handle h_Spinlock) { struct mtx *m; m = h_Spinlock; mtx_lock(m); } void XX_UnlockSpinlock(t_Handle h_Spinlock) { struct mtx *m; m = h_Spinlock; mtx_unlock(m); } uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock) { XX_LockSpinlock(h_Spinlock); return (0); } void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags) { XX_UnlockSpinlock(h_Spinlock); } uint32_t XX_CurrentTime(void) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (0); } t_Handle XX_CreateTimer(void) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (NULL); } void XX_FreeTimer(t_Handle h_Timer) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } void XX_StartTimer(t_Handle h_Timer, uint32_t msecs, bool periodic, void (*f_TimerExpired)(t_Handle), t_Handle h_Arg) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } uint32_t XX_GetExpirationTime(t_Handle h_Timer) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (0); } void XX_StopTimer(t_Handle h_Timer) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } void XX_ModTimer(t_Handle h_Timer, uint32_t msecs) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); } int XX_TimerIsActive(t_Handle h_Timer) { /* Not referenced */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (0); } uint32_t XX_Sleep(uint32_t msecs) { XX_UDelay(1000 * msecs); return (0); } void XX_UDelay(uint32_t usecs) { DELAY(usecs); } t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], t_IpcMsgHandler *f_MsgHandler, t_Handle h_Module, uint32_t replyLength) { /* * This function returns fake E_OK status and does nothing * as NetCommSW IPC is not used by FreeBSD drivers. */ return (E_OK); } t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]) { /* * This function returns fake E_OK status and does nothing * as NetCommSW IPC is not used by FreeBSD drivers. */ return (E_OK); } t_Error XX_IpcSendMessage(t_Handle h_Session, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength, t_IpcMsgCompletion *f_Completion, t_Handle h_Arg) { /* Should not be called */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (E_OK); } t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]) { /* Should not be called */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (E_OK); } t_Error XX_IpcFreeSession(t_Handle h_Session) { /* Should not be called */ printf("NetCommSW: Unimplemented function %s() called!\n", __func__); return (E_OK); } physAddress_t XX_VirtToPhys(void *addr) { vm_paddr_t paddr; int cpu; cpu = PCPU_GET(cpuid); /* Handle NULL address */ if (addr == NULL) return (-1); /* Handle BMAN mappings */ if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[BM_PORTAL]) && ((vm_offset_t)addr < XX_PInfo.portal_ce_va[BM_PORTAL] + XX_PInfo.portal_ce_size[BM_PORTAL][cpu])) return (XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] + (vm_offset_t)addr - XX_PInfo.portal_ce_va[BM_PORTAL]); if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[BM_PORTAL]) && ((vm_offset_t)addr < XX_PInfo.portal_ci_va[BM_PORTAL] + XX_PInfo.portal_ci_size[BM_PORTAL][cpu])) return (XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] + (vm_offset_t)addr - XX_PInfo.portal_ci_va[BM_PORTAL]); /* Handle QMAN mappings */ if (((vm_offset_t)addr >= XX_PInfo.portal_ce_va[QM_PORTAL]) && ((vm_offset_t)addr < XX_PInfo.portal_ce_va[QM_PORTAL] + XX_PInfo.portal_ce_size[QM_PORTAL][cpu])) return (XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] + (vm_offset_t)addr - XX_PInfo.portal_ce_va[QM_PORTAL]); if (((vm_offset_t)addr >= XX_PInfo.portal_ci_va[QM_PORTAL]) && ((vm_offset_t)addr < XX_PInfo.portal_ci_va[QM_PORTAL] + XX_PInfo.portal_ci_size[QM_PORTAL][cpu])) return (XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] + (vm_offset_t)addr - XX_PInfo.portal_ci_va[QM_PORTAL]); paddr = XX_TrackAddress(addr); if (paddr == -1) printf("NetCommSW: " "Unable to translate virtual address 0x%08X!\n", addr); return (paddr); } void * XX_PhysToVirt(physAddress_t addr) { XX_MallocTrackStruct *ts; int cpu; cpu = PCPU_GET(cpuid); /* Handle BMAN mappings */ if ((addr >= XX_PInfo.portal_ce_pa[BM_PORTAL][cpu]) && (addr < XX_PInfo.portal_ce_pa[BM_PORTAL][cpu] + XX_PInfo.portal_ce_size[BM_PORTAL][cpu])) return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] + (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]))); if ((addr >= XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]) && (addr < XX_PInfo.portal_ci_pa[BM_PORTAL][cpu] + XX_PInfo.portal_ci_size[BM_PORTAL][cpu])) return ((void *)(XX_PInfo.portal_ci_va[BM_PORTAL] + (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[BM_PORTAL][cpu]))); /* Handle QMAN mappings */ if ((addr >= XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]) && (addr < XX_PInfo.portal_ce_pa[QM_PORTAL][cpu] + XX_PInfo.portal_ce_size[QM_PORTAL][cpu])) return ((void *)(XX_PInfo.portal_ce_va[QM_PORTAL] + (vm_offset_t)(addr - XX_PInfo.portal_ce_pa[QM_PORTAL][cpu]))); if ((addr >= XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]) && (addr < XX_PInfo.portal_ci_pa[QM_PORTAL][cpu] + XX_PInfo.portal_ci_size[QM_PORTAL][cpu])) return ((void *)(XX_PInfo.portal_ci_va[QM_PORTAL] + (vm_offset_t)(addr - XX_PInfo.portal_ci_pa[QM_PORTAL][cpu]))); mtx_lock(&XX_MallocTrackLock); ts = XX_FindTracker(addr); mtx_unlock(&XX_MallocTrackLock); if (ts != NULL) return ts->va; printf("NetCommSW: " "Unable to translate physical address 0x%08llX!\n", addr); return (NULL); } void XX_PortalSetInfo(device_t dev) { char *dev_name; struct dpaa_portals_softc *sc; int i, type, len; dev_name = malloc(sizeof(*dev_name), M_TEMP, M_WAITOK | M_ZERO); len = strlen("bman-portals"); strncpy(dev_name, device_get_name(dev), len); if (strncmp(dev_name, "bman-portals", len) && strncmp(dev_name, "qman-portals", len)) goto end; if (strncmp(dev_name, "bman-portals", len) == 0) type = BM_PORTAL; else type = QM_PORTAL; sc = device_get_softc(dev); for (i = 0; sc->sc_dp[i].dp_ce_pa != 0; i++) { XX_PInfo.portal_ce_pa[type][i] = sc->sc_dp[i].dp_ce_pa; XX_PInfo.portal_ci_pa[type][i] = sc->sc_dp[i].dp_ci_pa; XX_PInfo.portal_ce_size[type][i] = sc->sc_dp[i].dp_ce_size; XX_PInfo.portal_ci_size[type][i] = sc->sc_dp[i].dp_ci_size; XX_PInfo.portal_intr[type][i] = sc->sc_dp[i].dp_intr_num; } XX_PInfo.portal_ce_va[type] = rman_get_bushandle(sc->sc_rres[0]); XX_PInfo.portal_ci_va[type] = rman_get_bushandle(sc->sc_rres[1]); end: free(dev_name, M_TEMP); } static inline XX_MallocTrackStruct * XX_FindTracker(physAddress_t pa) { struct XX_MallocTrackerList *l; XX_MallocTrackStruct *tp; l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; LIST_FOREACH(tp, l, entries) { if (tp->pa == pa) return tp; } return NULL; } void XX_TrackInit(void) { if (XX_MallocTracker == NULL) { XX_MallocTracker = hashinit(64, M_NETCOMMSW_MT, &XX_MallocHashMask); } } physAddress_t XX_TrackAddress(void *addr) { physAddress_t pa; struct XX_MallocTrackerList *l; XX_MallocTrackStruct *ts; pa = pmap_kextract((vm_offset_t)addr); l = &XX_MallocTracker[(pa >> XX_MALLOC_TRACK_SHIFT) & XX_MallocHashMask]; mtx_lock(&XX_MallocTrackLock); if (XX_FindTracker(pa) == NULL) { ts = malloc(sizeof(*ts), M_NETCOMMSW_MT, M_NOWAIT); if (ts == NULL) return (-1); ts->va = addr; ts->pa = pa; LIST_INSERT_HEAD(l, ts, entries); } mtx_unlock(&XX_MallocTrackLock); return (pa); } void XX_UntrackAddress(void *addr) { physAddress_t pa; XX_MallocTrackStruct *ts; pa = pmap_kextract((vm_offset_t)addr); KASSERT(XX_MallocTracker != NULL, ("Untracking an address before it's even initialized!\n")); mtx_lock(&XX_MallocTrackLock); ts = XX_FindTracker(pa); if (ts != NULL) LIST_REMOVE(ts, entries); mtx_unlock(&XX_MallocTrackLock); free(ts, M_NETCOMMSW_MT); } Index: head/sys/dev/dpaa/bman.c =================================================================== --- head/sys/dev/dpaa/bman.c (revision 307541) +++ head/sys/dev/dpaa/bman.c (revision 307542) @@ -1,370 +1,370 @@ /*- * Copyright (c) 2011-2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include "bman.h" devclass_t bman_devclass; static struct bman_softc *bman_sc; extern t_Handle bman_portal_setup(struct bman_softc *bsc); static void bman_exception(t_Handle h_App, e_BmExceptions exception) { struct bman_softc *sc; const char *message; sc = h_App; switch (exception) { case e_BM_EX_INVALID_COMMAND: message = "Invalid Command Verb"; break; case e_BM_EX_FBPR_THRESHOLD: message = "FBPR pool exhaused. Consider increasing " "BMAN_MAX_BUFFERS"; break; case e_BM_EX_SINGLE_ECC: message = "Single bit ECC error"; break; case e_BM_EX_MULTI_ECC: message = "Multi bit ECC error"; break; default: message = "Unknown error"; } device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message); } int bman_attach(device_t dev) { struct bman_softc *sc; t_BmRevisionInfo rev; t_Error error; t_BmParam bp; sc = device_get_softc(dev); sc->sc_dev = dev; bman_sc = sc; /* Check if MallocSmart allocator is ready */ if (XX_MallocSmartInit() != E_OK) return (ENXIO); /* Allocate resources */ sc->sc_rrid = 0; sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, 0, ~0, BMAN_CCSR_SIZE, RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_ires == NULL) goto err; /* Initialize BMAN */ memset(&bp, 0, sizeof(bp)); bp.guestId = NCSW_MASTER_ID; bp.baseAddress = rman_get_bushandle(sc->sc_rres); bp.totalNumOfBuffers = BMAN_MAX_BUFFERS; bp.f_Exception = bman_exception; bp.h_App = sc; - bp.errIrq = (int)sc->sc_ires; + bp.errIrq = (uintptr_t)sc->sc_ires; bp.partBpidBase = 0; bp.partNumOfPools = BM_MAX_NUM_OF_POOLS; printf("base address: %llx\n", (uint64_t)bp.baseAddress); sc->sc_bh = BM_Config(&bp); if (sc->sc_bh == NULL) goto err; /* Warn if there is less than 5% free FPBR's in pool */ error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20); if (error != E_OK) goto err; error = BM_Init(sc->sc_bh); if (error != E_OK) goto err; error = BM_GetRevision(sc->sc_bh, &rev); if (error != E_OK) goto err; device_printf(dev, "Hardware version: %d.%d.\n", rev.majorRev, rev.minorRev); return (0); err: bman_detach(dev); return (ENXIO); } int bman_detach(device_t dev) { struct bman_softc *sc; sc = device_get_softc(dev); if (sc->sc_bh != NULL) BM_Free(sc->sc_bh); if (sc->sc_ires != NULL) bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); if (sc->sc_rres != NULL) bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); return (0); } int bman_suspend(device_t dev) { return (0); } int bman_resume(device_t dev) { return (0); } int bman_shutdown(device_t dev) { return (0); } /* * BMAN API */ t_Handle bman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers, uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf, t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit, uint32_t dep_hw_entry, uint32_t dep_hw_exit, t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool, t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys) { uint32_t thresholds[MAX_DEPLETION_THRESHOLDS]; struct bman_softc *sc; t_Handle pool, portal; t_BmPoolParam bpp; int error; sc = bman_sc; pool = NULL; sched_pin(); portal = bman_portal_setup(sc); if (portal == NULL) goto err; memset(&bpp, 0, sizeof(bpp)); bpp.h_Bm = sc->sc_bh; bpp.h_BmPortal = portal; bpp.h_App = h_BufferPool; bpp.numOfBuffers = allocBuffers; bpp.bufferPoolInfo.h_BufferPool = h_BufferPool; bpp.bufferPoolInfo.f_GetBuf = f_GetBuf; bpp.bufferPoolInfo.f_PutBuf = f_PutBuf; bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt; bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys; bpp.bufferPoolInfo.bufferSize = bufferSize; pool = BM_POOL_Config(&bpp); if (pool == NULL) goto err; /* * Buffer context must be disabled on FreeBSD * as it could cause memory corruption. */ BM_POOL_ConfigBuffContextMode(pool, 0); if (minBuffers != 0 || maxBuffers != 0) { error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers); if (error != E_OK) goto err; } if (f_Depletion != NULL) { thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry; thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit; thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry; thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit; error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds); if (error != E_OK) goto err; } error = BM_POOL_Init(pool); if (error != E_OK) goto err; *bpid = BM_POOL_GetId(pool); sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid); sched_unpin(); return (pool); err: if (pool != NULL) BM_POOL_Free(pool); sched_unpin(); return (NULL); } int bman_pool_destroy(t_Handle pool) { struct bman_softc *sc; sc = bman_sc; thread_lock(curthread); sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]); thread_unlock(curthread); BM_POOL_Free(pool); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); return (0); } int bman_pool_fill(t_Handle pool, uint16_t nbufs) { struct bman_softc *sc; t_Handle portal; int error; sc = bman_sc; sched_pin(); portal = bman_portal_setup(sc); if (portal == NULL) { sched_unpin(); return (EIO); } error = BM_POOL_FillBufs(pool, portal, nbufs); sched_unpin(); return ((error == E_OK) ? 0 : EIO); } void * bman_get_buffer(t_Handle pool) { struct bman_softc *sc; t_Handle portal; void *buffer; sc = bman_sc; sched_pin(); portal = bman_portal_setup(sc); if (portal == NULL) { sched_unpin(); return (NULL); } buffer = BM_POOL_GetBuf(pool, portal); sched_unpin(); return (buffer); } int bman_put_buffer(t_Handle pool, void *buffer) { struct bman_softc *sc; t_Handle portal; int error; sc = bman_sc; sched_pin(); portal = bman_portal_setup(sc); if (portal == NULL) { sched_unpin(); return (EIO); } error = BM_POOL_PutBuf(pool, portal, buffer); sched_unpin(); return ((error == E_OK) ? 0 : EIO); } uint32_t bman_count(t_Handle pool) { return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT)); } Index: head/sys/dev/dpaa/bman_portals.c =================================================================== --- head/sys/dev/dpaa/bman_portals.c (revision 307541) +++ head/sys/dev/dpaa/bman_portals.c (revision 307542) @@ -1,180 +1,180 @@ /*- * Copyright (c) 2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bman.h" #include "portals.h" t_Handle bman_portal_setup(struct bman_softc *); struct dpaa_portals_softc *bp_sc; int bman_portals_attach(device_t dev) { struct dpaa_portals_softc *sc; sc = bp_sc = device_get_softc(dev); /* Map bman portal to physical address space */ if (law_enable(OCP85XX_TGTIF_BMAN, sc->sc_dp_pa, sc->sc_dp_size)) { bman_portals_detach(dev); return (ENXIO); } /* Set portal properties for XX_VirtToPhys() */ XX_PortalSetInfo(dev); return (bus_generic_attach(dev)); } int bman_portals_detach(device_t dev) { struct dpaa_portals_softc *sc; int i; bp_sc = NULL; sc = device_get_softc(dev); for (i = 0; i < ARRAY_SIZE(sc->sc_dp); i++) { if (sc->sc_dp[i].dp_ph != NULL) { thread_lock(curthread); sched_bind(curthread, i); thread_unlock(curthread); BM_PORTAL_Free(sc->sc_dp[i].dp_ph); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); } if (sc->sc_dp[i].dp_ires != NULL) { - XX_DeallocIntr((int)sc->sc_dp[i].dp_ires); + XX_DeallocIntr((uintptr_t)sc->sc_dp[i].dp_ires); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_dp[i].dp_irid, sc->sc_dp[i].dp_ires); } } for (i = 0; i < ARRAY_SIZE(sc->sc_rres); i++) { if (sc->sc_rres[i] != NULL) bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid[i], sc->sc_rres[i]); } return (0); } t_Handle bman_portal_setup(struct bman_softc *bsc) { struct dpaa_portals_softc *sc; t_BmPortalParam bpp; t_Handle portal; - unsigned int cpu, p; + unsigned int cpu; + uintptr_t p; /* Return NULL if we're not ready or while detach */ if (bp_sc == NULL) return (NULL); sc = bp_sc; sched_pin(); portal = NULL; cpu = PCPU_GET(cpuid); /* Check if portal is ready */ - while (atomic_cmpset_acq_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, + while (atomic_cmpset_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, 0, -1) == 0) { - p = atomic_load_acq_32((uint32_t *)&sc->sc_dp[cpu].dp_ph); + p = atomic_load_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph); /* Return if portal is already initialized */ if (p != 0 && p != -1) { sched_unpin(); return ((t_Handle)p); } /* Not inititialized and "owned" by another thread */ thread_lock(curthread); mi_switch(SW_VOL, NULL); thread_unlock(curthread); } /* Map portal registers */ dpaa_portal_map_registers(sc); /* Configure and initialize portal */ bpp.ceBaseAddress = rman_get_bushandle(sc->sc_rres[0]); bpp.ciBaseAddress = rman_get_bushandle(sc->sc_rres[1]); bpp.h_Bm = bsc->sc_bh; bpp.swPortalId = cpu; - bpp.irq = (int)sc->sc_dp[cpu].dp_ires; + bpp.irq = (uintptr_t)sc->sc_dp[cpu].dp_ires; portal = BM_PORTAL_Config(&bpp); if (portal == NULL) goto err; if (BM_PORTAL_Init(portal) != E_OK) goto err; - atomic_store_rel_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, - (uint32_t)portal); + atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, (uintptr_t)portal); sched_unpin(); return (portal); err: if (portal != NULL) BM_PORTAL_Free(portal); - atomic_store_rel_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, 0); + atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, 0); sched_unpin(); return (NULL); } Index: head/sys/dev/dpaa/fman.c =================================================================== --- head/sys/dev/dpaa/fman.c (revision 307541) +++ head/sys/dev/dpaa/fman.c (revision 307542) @@ -1,357 +1,357 @@ /*- * Copyright (c) 2011-2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "opt_platform.h" #include #include #include #include #include "fman.h" /** * @group FMan private defines. * @{ */ enum fman_irq_enum { FMAN_IRQ_NUM = 0, FMAN_ERR_IRQ_NUM = 1 }; enum fman_mu_ram_map { FMAN_MURAM_OFF = 0x0, FMAN_MURAM_SIZE = 0x28000 }; struct fman_config { device_t fman_device; uintptr_t mem_base_addr; - int irq_num; - int err_irq_num; + uintptr_t irq_num; + uintptr_t err_irq_num; uint8_t fm_id; t_FmExceptionsCallback *exception_callback; t_FmBusErrorCallback *bus_error_callback; }; /** * @group FMan private methods/members. * @{ */ /** * Frame Manager firmware. * We use the same firmware for both P3041 and P2041 devices. */ const uint32_t fman_firmware[] = FMAN_UC_IMG; const uint32_t fman_firmware_size = sizeof(fman_firmware); static struct fman_softc *fm_sc = NULL; static t_Handle fman_init(struct fman_softc *sc, struct fman_config *cfg) { t_FmParams fm_params; t_Handle muram_handle, fm_handle; t_Error error; t_FmRevisionInfo revision_info; uint16_t clock; uint32_t tmp, mod; /* MURAM configuration */ muram_handle = FM_MURAM_ConfigAndInit(cfg->mem_base_addr + FMAN_MURAM_OFF, FMAN_MURAM_SIZE); if (muram_handle == NULL) { device_printf(cfg->fman_device, "couldn't init FM MURAM module" "\n"); return (NULL); } sc->muram_handle = muram_handle; /* Fill in FM configuration */ fm_params.fmId = cfg->fm_id; /* XXX we support only one partition thus each fman has master id */ fm_params.guestId = NCSW_MASTER_ID; fm_params.baseAddr = cfg->mem_base_addr; fm_params.h_FmMuram = muram_handle; /* Get FMan clock in Hz */ if ((tmp = fman_get_clock(sc)) == 0) return (NULL); /* Convert FMan clock to MHz */ clock = (uint16_t)(tmp / 1000000); mod = tmp % 1000000; if (mod >= 500000) ++clock; fm_params.fmClkFreq = clock; fm_params.f_Exception = cfg->exception_callback; fm_params.f_BusError = cfg->bus_error_callback; fm_params.h_App = cfg->fman_device; fm_params.irq = cfg->irq_num; fm_params.errIrq = cfg->err_irq_num; fm_params.firmware.size = fman_firmware_size; fm_params.firmware.p_Code = (uint32_t*)fman_firmware; fm_handle = FM_Config(&fm_params); if (fm_handle == NULL) { device_printf(cfg->fman_device, "couldn't configure FM " "module\n"); goto err; } FM_ConfigResetOnInit(fm_handle, TRUE); error = FM_Init(fm_handle); if (error != E_OK) { device_printf(cfg->fman_device, "couldn't init FM module\n"); goto err2; } error = FM_GetRevision(fm_handle, &revision_info); if (error != E_OK) { device_printf(cfg->fman_device, "couldn't get FM revision\n"); goto err2; } device_printf(cfg->fman_device, "Hardware version: %d.%d.\n", revision_info.majorRev, revision_info.minorRev); return (fm_handle); err2: FM_Free(fm_handle); err: FM_MURAM_Free(muram_handle); return (NULL); } static void fman_exception_callback(t_Handle app_handle, e_FmExceptions exception) { struct fman_softc *sc; sc = app_handle; device_printf(sc->dev, "FMan exception occurred.\n"); } static void fman_error_callback(t_Handle app_handle, e_FmPortType port_type, uint8_t port_id, uint64_t addr, uint8_t tnum, uint16_t liodn) { struct fman_softc *sc; sc = app_handle; device_printf(sc->dev, "FMan error occurred.\n"); } /** @} */ /** * @group FMan driver interface. * @{ */ int fman_get_handle(t_Handle *fmh) { if (fm_sc == NULL) return (ENOMEM); *fmh = fm_sc->fm_handle; return (0); } int fman_get_muram_handle(t_Handle *muramh) { if (fm_sc == NULL) return (ENOMEM); *muramh = fm_sc->muram_handle; return (0); } int fman_get_bushandle(vm_offset_t *fm_base) { if (fm_sc == NULL) return (ENOMEM); *fm_base = rman_get_bushandle(fm_sc->mem_res); return (0); } int fman_attach(device_t dev) { struct fman_softc *sc; struct fman_config cfg; sc = device_get_softc(dev); sc->dev = dev; fm_sc = sc; /* Check if MallocSmart allocator is ready */ if (XX_MallocSmartInit() != E_OK) { device_printf(dev, "could not initialize smart allocator.\n"); return (ENXIO); } XX_TrackInit(); sc->mem_rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, RF_ACTIVE); if (!sc->mem_res) { device_printf(dev, "could not allocate memory.\n"); return (ENXIO); } sc->irq_rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, RF_ACTIVE); if (!sc->irq_res) { device_printf(dev, "could not allocate interrupt.\n"); goto err; } /* * XXX: Fix FMan interrupt. This is workaround for the issue with * interrupts directed to multiple CPUs by the interrupts subsystem. * Workaround is to bind the interrupt to only one CPU0. */ XX_FmanFixIntr(rman_get_start(sc->irq_res)); sc->err_irq_rid = 1; sc->err_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->err_irq_rid, RF_ACTIVE | RF_SHAREABLE); if (!sc->err_irq_res) { device_printf(dev, "could not allocate error interrupt.\n"); goto err; } /* Set FMan configuration */ cfg.fman_device = dev; cfg.fm_id = device_get_unit(dev); cfg.mem_base_addr = rman_get_bushandle(sc->mem_res); - cfg.irq_num = (int)sc->irq_res; - cfg.err_irq_num = (int)sc->err_irq_res; + cfg.irq_num = (uintptr_t)sc->irq_res; + cfg.err_irq_num = (uintptr_t)sc->err_irq_res; cfg.exception_callback = fman_exception_callback; cfg.bus_error_callback = fman_error_callback; sc->fm_handle = fman_init(sc, &cfg); if (sc->fm_handle == NULL) { device_printf(dev, "could not be configured\n"); return (ENXIO); } return (bus_generic_attach(dev)); err: fman_detach(dev); return (ENXIO); } int fman_detach(device_t dev) { struct fman_softc *sc; sc = device_get_softc(dev); if (sc->muram_handle) { FM_MURAM_Free(sc->muram_handle); } if (sc->fm_handle) { FM_Free(sc->fm_handle); } if (sc->mem_res) { bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res); } if (sc->irq_res) { bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq_res); } if (sc->irq_res) { bus_release_resource(dev, SYS_RES_IRQ, sc->err_irq_rid, sc->err_irq_res); } return (0); } int fman_suspend(device_t dev) { return (0); } int fman_resume(device_t dev) { return (0); } int fman_shutdown(device_t dev) { return (0); } /** @} */ Index: head/sys/dev/dpaa/portals_common.c =================================================================== --- head/sys/dev/dpaa/portals_common.c (revision 307541) +++ head/sys/dev/dpaa/portals_common.c (revision 307542) @@ -1,170 +1,170 @@ /*- * Copyright (c) 2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "portals.h" int dpaa_portal_alloc_res(device_t dev, struct dpaa_portals_devinfo *di, int cpu) { struct dpaa_portals_softc *sc = device_get_softc(dev); struct resource_list_entry *rle; int err; struct resource_list *res; /* Check if MallocSmart allocator is ready */ if (XX_MallocSmartInit() != E_OK) return (ENXIO); res = &di->di_res; /* * Allocate memory. * Reserve only one pair of CE/CI virtual memory regions * for all CPUs, in order to save the space. */ if (sc->sc_rres[0] == NULL) { /* Cache enabled area */ rle = resource_list_find(res, SYS_RES_MEMORY, 0); sc->sc_rrid[0] = 0; sc->sc_rres[0] = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid[0], rle->start + sc->sc_dp_pa, rle->end + sc->sc_dp_pa, rle->count, RF_ACTIVE); if (sc->sc_rres[0] == NULL) { device_printf(dev, "Could not allocate cache enabled memory.\n"); return (ENXIO); } tlb1_set_entry(rman_get_bushandle(sc->sc_rres[0]), rle->start + sc->sc_dp_pa, rle->count, _TLB_ENTRY_MEM); /* Cache inhibited area */ rle = resource_list_find(res, SYS_RES_MEMORY, 1); sc->sc_rrid[1] = 1; sc->sc_rres[1] = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid[1], rle->start + sc->sc_dp_pa, rle->end + sc->sc_dp_pa, rle->count, RF_ACTIVE); if (sc->sc_rres[1] == NULL) { device_printf(dev, "Could not allocate cache inhibited memory.\n"); bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid[0], sc->sc_rres[0]); return (ENXIO); } tlb1_set_entry(rman_get_bushandle(sc->sc_rres[1]), rle->start + sc->sc_dp_pa, rle->count, _TLB_ENTRY_IO); sc->sc_dp[cpu].dp_regs_mapped = 1; } /* Acquire portal's CE_PA and CI_PA */ rle = resource_list_find(res, SYS_RES_MEMORY, 0); sc->sc_dp[cpu].dp_ce_pa = rle->start + sc->sc_dp_pa; sc->sc_dp[cpu].dp_ce_size = rle->count; rle = resource_list_find(res, SYS_RES_MEMORY, 1); sc->sc_dp[cpu].dp_ci_pa = rle->start + sc->sc_dp_pa; sc->sc_dp[cpu].dp_ci_size = rle->count; /* Allocate interrupts */ rle = resource_list_find(res, SYS_RES_IRQ, 0); sc->sc_dp[cpu].dp_irid = 0; sc->sc_dp[cpu].dp_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_dp[cpu].dp_irid, rle->start, rle->end, rle->count, RF_ACTIVE); /* Save interrupt number for later use */ sc->sc_dp[cpu].dp_intr_num = rle->start; if (sc->sc_dp[cpu].dp_ires == NULL) { device_printf(dev, "Could not allocate irq.\n"); return (ENXIO); } - err = XX_PreallocAndBindIntr((int)sc->sc_dp[cpu].dp_ires, cpu); + err = XX_PreallocAndBindIntr((uintptr_t)sc->sc_dp[cpu].dp_ires, cpu); if (err != E_OK) { device_printf(dev, "Could not prealloc and bind interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_dp[cpu].dp_irid, sc->sc_dp[cpu].dp_ires); sc->sc_dp[cpu].dp_ires = NULL; return (ENXIO); } #if 0 err = bus_generic_config_intr(dev, rle->start, di->di_intr_trig, di->di_intr_pol); if (err != 0) { device_printf(dev, "Could not configure interrupt\n"); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_dp[cpu].dp_irid, sc->sc_dp[cpu].dp_ires); sc->sc_dp[cpu].dp_ires = NULL; return (err); } #endif return (0); } void dpaa_portal_map_registers(struct dpaa_portals_softc *sc) { unsigned int cpu; sched_pin(); cpu = PCPU_GET(cpuid); if (sc->sc_dp[cpu].dp_regs_mapped) goto out; tlb1_set_entry(rman_get_bushandle(sc->sc_rres[0]), sc->sc_dp[cpu].dp_ce_pa, sc->sc_dp[cpu].dp_ce_size, _TLB_ENTRY_MEM); tlb1_set_entry(rman_get_bushandle(sc->sc_rres[1]), sc->sc_dp[cpu].dp_ci_pa, sc->sc_dp[cpu].dp_ci_size, _TLB_ENTRY_IO); sc->sc_dp[cpu].dp_regs_mapped = 1; out: sched_unpin(); } Index: head/sys/dev/dpaa/qman.c =================================================================== --- head/sys/dev/dpaa/qman.c (revision 307541) +++ head/sys/dev/dpaa/qman.c (revision 307542) @@ -1,555 +1,555 @@ /*- * Copyright (c) 2011-2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qman.h" #include "portals.h" extern struct dpaa_portals_softc *qp_sc; static struct qman_softc *qman_sc; extern t_Handle qman_portal_setup(struct qman_softc *qsc); static void qman_exception(t_Handle app, e_QmExceptions exception) { struct qman_softc *sc; const char *message; sc = app; switch (exception) { case e_QM_EX_CORENET_INITIATOR_DATA: message = "Initiator Data Error"; break; case e_QM_EX_CORENET_TARGET_DATA: message = "CoreNet Target Data Error"; break; case e_QM_EX_CORENET_INVALID_TARGET_TRANSACTION: message = "Invalid Target Transaction"; break; case e_QM_EX_PFDR_THRESHOLD: message = "PFDR Low Watermark Interrupt"; break; case e_QM_EX_PFDR_ENQUEUE_BLOCKED: message = "PFDR Enqueues Blocked Interrupt"; break; case e_QM_EX_SINGLE_ECC: message = "Single Bit ECC Error Interrupt"; break; case e_QM_EX_MULTI_ECC: message = "Multi Bit ECC Error Interrupt"; break; case e_QM_EX_INVALID_COMMAND: message = "Invalid Command Verb Interrupt"; break; case e_QM_EX_DEQUEUE_DCP: message = "Invalid Dequeue Direct Connect Portal Interrupt"; break; case e_QM_EX_DEQUEUE_FQ: message = "Invalid Dequeue FQ Interrupt"; break; case e_QM_EX_DEQUEUE_SOURCE: message = "Invalid Dequeue Source Interrupt"; break; case e_QM_EX_DEQUEUE_QUEUE: message = "Invalid Dequeue Queue Interrupt"; break; case e_QM_EX_ENQUEUE_OVERFLOW: message = "Invalid Enqueue Overflow Interrupt"; break; case e_QM_EX_ENQUEUE_STATE: message = "Invalid Enqueue State Interrupt"; break; case e_QM_EX_ENQUEUE_CHANNEL: message = "Invalid Enqueue Channel Interrupt"; break; case e_QM_EX_ENQUEUE_QUEUE: message = "Invalid Enqueue Queue Interrupt"; break; case e_QM_EX_CG_STATE_CHANGE: message = "CG change state notification"; break; default: message = "Unknown error"; } device_printf(sc->sc_dev, "QMan Exception: %s.\n", message); } /** * General received frame callback. * This is called, when user did not register his own callback for a given * frame queue range (fqr). */ e_RxStoreResponse qman_received_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal, uint32_t fqid_offset, t_DpaaFD *frame) { struct qman_softc *sc; sc = app; device_printf(sc->sc_dev, "dummy callback for received frame.\n"); return (e_RX_STORE_RESPONSE_CONTINUE); } /** * General rejected frame callback. * This is called, when user did not register his own callback for a given * frame queue range (fqr). */ e_RxStoreResponse qman_rejected_frame_callback(t_Handle app, t_Handle qm_fqr, t_Handle qm_portal, uint32_t fqid_offset, t_DpaaFD *frame, t_QmRejectedFrameInfo *qm_rejected_frame_info) { struct qman_softc *sc; sc = app; device_printf(sc->sc_dev, "dummy callback for rejected frame.\n"); return (e_RX_STORE_RESPONSE_CONTINUE); } int qman_attach(device_t dev) { struct qman_softc *sc; t_QmParam qp; t_Error error; t_QmRevisionInfo rev; sc = device_get_softc(dev); sc->sc_dev = dev; qman_sc = sc; if (XX_MallocSmartInit() != E_OK) { device_printf(dev, "could not initialize smart allocator.\n"); return (ENXIO); } sched_pin(); /* Allocate resources */ sc->sc_rrid = 0; sc->sc_rres = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_rrid, 0, ~0, QMAN_CCSR_SIZE, RF_ACTIVE); if (sc->sc_rres == NULL) { device_printf(dev, "could not allocate memory.\n"); goto err; } sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE | RF_SHAREABLE); if (sc->sc_ires == NULL) { device_printf(dev, "could not allocate error interrupt.\n"); goto err; } if (qp_sc == NULL) goto err; dpaa_portal_map_registers(qp_sc); /* Initialize QMan */ qp.guestId = NCSW_MASTER_ID; qp.baseAddress = rman_get_bushandle(sc->sc_rres); qp.swPortalsBaseAddress = rman_get_bushandle(qp_sc->sc_rres[0]); qp.liodn = 0; qp.totalNumOfFqids = QMAN_MAX_FQIDS; qp.fqdMemPartitionId = NCSW_MASTER_ID; qp.pfdrMemPartitionId = NCSW_MASTER_ID; qp.f_Exception = qman_exception; qp.h_App = sc; - qp.errIrq = (int)sc->sc_ires; + qp.errIrq = (uintptr_t)sc->sc_ires; qp.partFqidBase = QMAN_FQID_BASE; qp.partNumOfFqids = QMAN_MAX_FQIDS; qp.partCgsBase = 0; qp.partNumOfCgs = 0; sc->sc_qh = QM_Config(&qp); if (sc->sc_qh == NULL) { device_printf(dev, "could not be configured\n"); goto err; } error = QM_Init(sc->sc_qh); if (error != E_OK) { device_printf(dev, "could not be initialized\n"); goto err; } error = QM_GetRevision(sc->sc_qh, &rev); if (error != E_OK) { device_printf(dev, "could not get QMan revision\n"); goto err; } device_printf(dev, "Hardware version: %d.%d.\n", rev.majorRev, rev.minorRev); sched_unpin(); qman_portal_setup(sc); return (0); err: sched_unpin(); qman_detach(dev); return (ENXIO); } int qman_detach(device_t dev) { struct qman_softc *sc; sc = device_get_softc(dev); if (sc->sc_qh) QM_Free(sc->sc_qh); if (sc->sc_ires != NULL) - XX_DeallocIntr((int)sc->sc_ires); + XX_DeallocIntr((uintptr_t)sc->sc_ires); if (sc->sc_ires != NULL) bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); if (sc->sc_rres != NULL) bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid, sc->sc_rres); return (0); } int qman_suspend(device_t dev) { return (0); } int qman_resume(device_t dev) { return (0); } int qman_shutdown(device_t dev) { return (0); } /** * @group QMan API functions implementation. * @{ */ t_Handle qman_fqr_create(uint32_t fqids_num, e_QmFQChannel channel, uint8_t wq, bool force_fqid, uint32_t fqid_or_align, bool init_parked, bool hold_active, bool prefer_in_cache, bool congst_avoid_ena, t_Handle congst_group, int8_t overhead_accounting_len, uint32_t tail_drop_threshold) { struct qman_softc *sc; t_QmFqrParams fqr; unsigned int cpu; t_Handle fqrh, portal; sc = qman_sc; sched_pin(); cpu = PCPU_GET(cpuid); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); goto err; } fqr.h_Qm = sc->sc_qh; fqr.h_QmPortal = portal; fqr.initParked = init_parked; fqr.holdActive = hold_active; fqr.preferInCache = prefer_in_cache; /* We do not support stashing */ fqr.useContextAForStash = FALSE; fqr.p_ContextA = 0; fqr.p_ContextB = 0; fqr.channel = channel; fqr.wq = wq; fqr.shadowMode = FALSE; fqr.numOfFqids = fqids_num; /* FQID */ fqr.useForce = force_fqid; if (force_fqid) { fqr.qs.frcQ.fqid = fqid_or_align; } else { fqr.qs.nonFrcQs.align = fqid_or_align; } /* Congestion Avoidance */ fqr.congestionAvoidanceEnable = congst_avoid_ena; if (congst_avoid_ena) { fqr.congestionAvoidanceParams.h_QmCg = congst_group; fqr.congestionAvoidanceParams.overheadAccountingLength = overhead_accounting_len; fqr.congestionAvoidanceParams.fqTailDropThreshold = tail_drop_threshold; } else { fqr.congestionAvoidanceParams.h_QmCg = 0; fqr.congestionAvoidanceParams.overheadAccountingLength = 0; fqr.congestionAvoidanceParams.fqTailDropThreshold = 0; } fqrh = QM_FQR_Create(&fqr); if (fqrh == NULL) { device_printf(sc->sc_dev, "could not create Frame Queue Range" "\n"); goto err; } sc->sc_fqr_cpu[QM_FQR_GetFqid(fqrh)] = PCPU_GET(cpuid); sched_unpin(); return (fqrh); err: sched_unpin(); return (NULL); } t_Error qman_fqr_free(t_Handle fqr) { struct qman_softc *sc; t_Error error; sc = qman_sc; thread_lock(curthread); sched_bind(curthread, sc->sc_fqr_cpu[QM_FQR_GetFqid(fqr)]); thread_unlock(curthread); error = QM_FQR_Free(fqr); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); return (error); } t_Error qman_fqr_register_cb(t_Handle fqr, t_QmReceivedFrameCallback *callback, t_Handle app) { struct qman_softc *sc; t_Error error; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (E_NOT_SUPPORTED); } error = QM_FQR_RegisterCB(fqr, callback, app); sched_unpin(); return (error); } t_Error qman_fqr_enqueue(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame) { struct qman_softc *sc; t_Error error; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (E_NOT_SUPPORTED); } error = QM_FQR_Enqueue(fqr, portal, fqid_off, frame); sched_unpin(); return (error); } uint32_t qman_fqr_get_counter(t_Handle fqr, uint32_t fqid_off, e_QmFqrCounters counter) { struct qman_softc *sc; uint32_t val; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (0); } val = QM_FQR_GetCounter(fqr, portal, fqid_off, counter); sched_unpin(); return (val); } t_Error qman_fqr_pull_frame(t_Handle fqr, uint32_t fqid_off, t_DpaaFD *frame) { struct qman_softc *sc; t_Error error; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (E_NOT_SUPPORTED); } error = QM_FQR_PullFrame(fqr, portal, fqid_off, frame); sched_unpin(); return (error); } uint32_t qman_fqr_get_base_fqid(t_Handle fqr) { struct qman_softc *sc; uint32_t val; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (0); } val = QM_FQR_GetFqid(fqr); sched_unpin(); return (val); } t_Error qman_poll(e_QmPortalPollSource source) { struct qman_softc *sc; t_Error error; t_Handle portal; sc = qman_sc; sched_pin(); /* Ensure we have got QMan port initialized */ portal = qman_portal_setup(sc); if (portal == NULL) { device_printf(sc->sc_dev, "could not setup QMan portal\n"); sched_unpin(); return (E_NOT_SUPPORTED); } error = QM_Poll(sc->sc_qh, source); sched_unpin(); return (error); } /* * TODO: add polling and/or congestion support. */ /** @} */ Index: head/sys/dev/dpaa/qman_portals.c =================================================================== --- head/sys/dev/dpaa/qman_portals.c (revision 307541) +++ head/sys/dev/dpaa/qman_portals.c (revision 307542) @@ -1,191 +1,192 @@ /*- * Copyright (c) 2012 Semihalf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "opt_platform.h" #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qman.h" #include "portals.h" extern e_RxStoreResponse qman_received_frame_callback(t_Handle, t_Handle, t_Handle, uint32_t, t_DpaaFD *); extern e_RxStoreResponse qman_rejected_frame_callback(t_Handle, t_Handle, t_Handle, uint32_t, t_DpaaFD *, t_QmRejectedFrameInfo *); t_Handle qman_portal_setup(struct qman_softc *); struct dpaa_portals_softc *qp_sc; int qman_portals_attach(device_t dev) { struct dpaa_portals_softc *sc; sc = qp_sc = device_get_softc(dev); /* Map bman portal to physical address space */ if (law_enable(OCP85XX_TGTIF_QMAN, sc->sc_dp_pa, sc->sc_dp_size)) { qman_portals_detach(dev); return (ENXIO); } /* Set portal properties for XX_VirtToPhys() */ XX_PortalSetInfo(dev); return (bus_generic_attach(dev)); } int qman_portals_detach(device_t dev) { struct dpaa_portals_softc *sc; int i; qp_sc = NULL; sc = device_get_softc(dev); for (i = 0; i < ARRAY_SIZE(sc->sc_dp); i++) { if (sc->sc_dp[i].dp_ph != NULL) { thread_lock(curthread); sched_bind(curthread, i); thread_unlock(curthread); QM_PORTAL_Free(sc->sc_dp[i].dp_ph); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); } if (sc->sc_dp[i].dp_ires != NULL) { - XX_DeallocIntr((int)sc->sc_dp[i].dp_ires); + XX_DeallocIntr((uintptr_t)sc->sc_dp[i].dp_ires); bus_release_resource(dev, SYS_RES_IRQ, sc->sc_dp[i].dp_irid, sc->sc_dp[i].dp_ires); } } for (i = 0; i < ARRAY_SIZE(sc->sc_rres); i++) { if (sc->sc_rres[i] != NULL) bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rrid[i], sc->sc_rres[i]); } return (0); } t_Handle qman_portal_setup(struct qman_softc *qsc) { struct dpaa_portals_softc *sc; t_QmPortalParam qpp; - unsigned int cpu, p; + unsigned int cpu; + uintptr_t p; t_Handle portal; /* Return NULL if we're not ready or while detach */ if (qp_sc == NULL) return (NULL); sc = qp_sc; sched_pin(); portal = NULL; cpu = PCPU_GET(cpuid); /* Check if portal is ready */ - while (atomic_cmpset_acq_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, + while (atomic_cmpset_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, 0, -1) == 0) { - p = atomic_load_acq_32((uint32_t *)&sc->sc_dp[cpu].dp_ph); + p = atomic_load_acq_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph); /* Return if portal is already initialized */ if (p != 0 && p != -1) { sched_unpin(); return ((t_Handle)p); } /* Not inititialized and "owned" by another thread */ thread_lock(curthread); mi_switch(SW_VOL, NULL); thread_unlock(curthread); } /* Map portal registers */ dpaa_portal_map_registers(sc); /* Configure and initialize portal */ qpp.ceBaseAddress = rman_get_bushandle(sc->sc_rres[0]); qpp.ciBaseAddress = rman_get_bushandle(sc->sc_rres[1]); qpp.h_Qm = qsc->sc_qh; qpp.swPortalId = cpu; - qpp.irq = (int)sc->sc_dp[cpu].dp_ires; + qpp.irq = (uintptr_t)sc->sc_dp[cpu].dp_ires; qpp.fdLiodnOffset = 0; qpp.f_DfltFrame = qman_received_frame_callback; qpp.f_RejectedFrame = qman_rejected_frame_callback; qpp.h_App = qsc; portal = QM_PORTAL_Config(&qpp); if (portal == NULL) goto err; if (QM_PORTAL_Init(portal) != E_OK) goto err; if (QM_PORTAL_AddPoolChannel(portal, QMAN_COMMON_POOL_CHANNEL) != E_OK) goto err; - atomic_store_rel_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, - (uint32_t)portal); + atomic_store_rel_ptr((uintptr_t *)&sc->sc_dp[cpu].dp_ph, + (uintptr_t)portal); sched_unpin(); return (portal); err: if (portal != NULL) QM_PORTAL_Free(portal); atomic_store_rel_32((uint32_t *)&sc->sc_dp[cpu].dp_ph, 0); sched_unpin(); return (NULL); }