/* Ring the doorbell and wait for result */
rvu_write64(rvu, block->addr, NPA_AF_AQ_DOOR, 1); while (result->compcode == NPA_AQ_COMP_NOTDONE) {
cpu_relax();
udelay(1);
timeout--; if (!timeout) return -EBUSY;
}
if (result->compcode != NPA_AQ_COMP_GOOD) { /* TODO: Replace this with some error code */ if (result->compcode == NPA_AQ_COMP_CTX_FAULT ||
result->compcode == NPA_AQ_COMP_LOCKERR ||
result->compcode == NPA_AQ_COMP_CTX_POISON) { if (rvu_ndc_fix_locked_cacheline(rvu, BLKADDR_NDC_NPA0))
dev_err(rvu->dev, "%s: Not able to unlock cachelines\n", __func__);
}
memset(&inst, 0, sizeof(struct npa_aq_inst_s));
inst.cindex = req->aura_id;
inst.lf = npalf;
inst.ctype = req->ctype;
inst.op = req->op; /* Currently we are not supporting enqueuing multiple instructions, *soalwayschoosefirstentryinresultmemory.
*/
inst.res_addr = (u64)aq->res->iova;
/* Hardware uses same aq->res->base for updating result of *previousinstructionhencewaitheretillitisdone.
*/
spin_lock(&aq->lock);
/* Clean result + context memory */
memset(aq->res->base, 0, aq->res->entry_sz); /* Context needs to be written at RES_ADDR + 128 */
ctx = aq->res->base + 128; /* Mask needs to be written at RES_ADDR + 256 */
mask = aq->res->base + 256;
switch (req->op) { case NPA_AQ_INSTOP_WRITE: /* Copy context and write mask */ if (req->ctype == NPA_AQ_CTYPE_AURA) {
memcpy(mask, &req->aura_mask, sizeof(struct npa_aura_s));
memcpy(ctx, &req->aura, sizeof(struct npa_aura_s));
} else {
memcpy(mask, &req->pool_mask, sizeof(struct npa_pool_s));
memcpy(ctx, &req->pool, sizeof(struct npa_pool_s));
} break; case NPA_AQ_INSTOP_INIT: if (req->ctype == NPA_AQ_CTYPE_AURA) { if (req->aura.pool_addr >= pfvf->pool_ctx->qsize) {
rc = NPA_AF_ERR_AQ_FULL; break;
} /* Set pool's context address */
req->aura.pool_addr = pfvf->pool_ctx->iova +
(req->aura.pool_addr * pfvf->pool_ctx->entry_sz);
memcpy(ctx, &req->aura, sizeof(struct npa_aura_s));
} else { /* POOL's context */
memcpy(ctx, &req->pool, sizeof(struct npa_pool_s));
} break; case NPA_AQ_INSTOP_NOP: case NPA_AQ_INSTOP_READ: case NPA_AQ_INSTOP_LOCK: case NPA_AQ_INSTOP_UNLOCK: break; default:
rc = NPA_AF_ERR_AQ_FULL; break;
}
if (rc) {
spin_unlock(&aq->lock); return rc;
}
/* Submit the instruction to AQ */
rc = npa_aq_enqueue_wait(rvu, block, &inst); if (rc) {
spin_unlock(&aq->lock); return rc;
}
/* Set aura bitmap if aura hw context is enabled */ if (req->ctype == NPA_AQ_CTYPE_AURA) { if (req->op == NPA_AQ_INSTOP_INIT && req->aura.ena)
__set_bit(req->aura_id, pfvf->aura_bmap); if (req->op == NPA_AQ_INSTOP_WRITE) {
ena = (req->aura.ena & req->aura_mask.ena) |
(test_bit(req->aura_id, pfvf->aura_bmap) &
~req->aura_mask.ena); if (ena)
__set_bit(req->aura_id, pfvf->aura_bmap); else
__clear_bit(req->aura_id, pfvf->aura_bmap);
}
}
/* Set pool bitmap if pool hw context is enabled */ if (req->ctype == NPA_AQ_CTYPE_POOL) { if (req->op == NPA_AQ_INSTOP_INIT && req->pool.ena)
__set_bit(req->aura_id, pfvf->pool_bmap); if (req->op == NPA_AQ_INSTOP_WRITE) {
ena = (req->pool.ena & req->pool_mask.ena) |
(test_bit(req->aura_id, pfvf->pool_bmap) &
~req->pool_mask.ena); if (ena)
__set_bit(req->aura_id, pfvf->pool_bmap); else
__clear_bit(req->aura_id, pfvf->pool_bmap);
}
}
spin_unlock(&aq->lock);
if (rsp) { /* Copy read context into mailbox */ if (req->op == NPA_AQ_INSTOP_READ) { if (req->ctype == NPA_AQ_CTYPE_AURA)
memcpy(&rsp->aura, ctx, sizeof(struct npa_aura_s)); else
memcpy(&rsp->pool, ctx, sizeof(struct npa_pool_s));
}
}
/* Disable all auras */
ctx_req.ctype = NPA_AQ_CTYPE_AURA;
npa_lf_hwctx_disable(rvu, &ctx_req);
npa_ctx_free(rvu, pfvf);
}
/* Due to an Hardware errata, in some corner cases, AQ context lock *operationscanresultinaNDCwaygettingintoanillegalstate *ofnotvalidbutlocked. * *ThisAPIsolvestheproblembyclearingthelockbitoftheNDCblock. *TheoperationneedstobedoneforeachlineofalltheNDCbanks.
*/ int rvu_ndc_fix_locked_cacheline(struct rvu *rvu, int blkaddr)
{ int bank, max_bank, line, max_line, err;
u64 reg, ndc_af_const;
/* Set the ENABLE bit(63) to '0' */
reg = rvu_read64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL);
rvu_write64(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, reg & GENMASK_ULL(62, 0));
/* Poll until the BUSY bits(47:32) are set to '0' */
err = rvu_poll_reg(rvu, blkaddr, NDC_AF_CAMS_RD_INTERVAL, GENMASK_ULL(47, 32), true); if (err) {
dev_err(rvu->dev, "Timed out while polling for NDC CAM busy bits.\n"); return err;
}
ndc_af_const = rvu_read64(rvu, blkaddr, NDC_AF_CONST);
max_bank = FIELD_GET(NDC_AF_BANK_MASK, ndc_af_const);
max_line = FIELD_GET(NDC_AF_BANK_LINE_MASK, ndc_af_const); for (bank = 0; bank < max_bank; bank++) { for (line = 0; line < max_line; line++) { /* Check if 'cache line valid bit(63)' is not set *but'cachelinelockbit(60)'issetandon *success,resetthelockbit(60).
*/
reg = rvu_read64(rvu, blkaddr,
NDC_AF_BANKX_LINEX_METADATA(bank, line)); if (!(reg & BIT_ULL(63)) && (reg & BIT_ULL(60))) {
rvu_write64(rvu, blkaddr,
NDC_AF_BANKX_LINEX_METADATA(bank, line),
reg & ~BIT_ULL(60));
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.