/* Flushing the AP interceptor cache to make APR_LMT_MAP_ENTRY_S * changes effective. Write 1 for flush and read is being used as a * barrier and sets up a data dependency. Write to 0 after a write * to 1 to complete the flush.
*/
rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, BIT_ULL(0));
rvu_read64(rvu, BLKADDR_APR, APR_AF_LMT_CTL);
rvu_write64(rvu, BLKADDR_APR, APR_AF_LMT_CTL, 0x00);
}
/* Read the current lmt addr of pcifunc */
tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc);
err = lmtst_map_table_ops(rvu, tbl_idx, &val, LMT_TBL_OP_READ); if (err) {
dev_err(rvu->dev, "Failed to read LMT map table: index 0x%x err %d\n",
tbl_idx, err); return err;
}
/* Storing the seondary's lmt base address as this needs to be * reverted in FLR. Also making sure this default value doesn't * get overwritten on multiple calls to this mailbox.
*/ if (!pfvf->lmt_base_addr)
pfvf->lmt_base_addr = val;
/* Update the LMT table with new addr */
err = lmtst_map_table_ops(rvu, tbl_idx, &lmt_addr, LMT_TBL_OP_WRITE); if (err) {
dev_err(rvu->dev, "Failed to update LMT map table: index 0x%x err %d\n",
tbl_idx, err); return err;
} return 0;
}
/* Check if PF_FUNC wants to use its own local memory as LMTLINE * region, if so, convert that IOVA to physical address and * populate LMT table with that address
*/ if (req->use_local_lmt_region) {
err = rvu_get_lmtaddr(rvu, req->hdr.pcifunc,
req->lmt_iova, &lmt_addr); if (err < 0) return err;
/* Update the lmt addr for this PFFUNC in the LMT table */
err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, lmt_addr); if (err) return err;
}
/* Reconfiguring lmtst map table in lmt region shared mode i.e. make * multiple PF_FUNCs to share an LMTLINE region, so primary/base * pcifunc (which is passed as an argument to mailbox) is the one * whose lmt base address will be shared among other secondary * pcifunc (will be the one who is calling this mailbox).
*/ if (req->base_pcifunc) { /* Calculating the LMT table index equivalent to primary * pcifunc.
*/
pri_tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->base_pcifunc);
/* Read the base lmt addr of the primary pcifunc */
err = lmtst_map_table_ops(rvu, pri_tbl_idx, &val,
LMT_TBL_OP_READ); if (err) {
dev_err(rvu->dev, "Failed to read LMT map table: index 0x%x err %d\n",
pri_tbl_idx, err); goto error;
}
/* Update the base lmt addr of secondary with primary's base * lmt addr.
*/
err = rvu_update_lmtaddr(rvu, req->hdr.pcifunc, val); if (err) return err;
}
/* This mailbox can also be used to update word1 of APR_LMT_MAP_ENTRY_S * like enabling scheduled LMTST, disable LMTLINE prefetch, disable * early completion for ordered LMTST.
*/ if (req->sch_ena || req->dis_sched_early_comp || req->dis_line_pref) {
tbl_idx = rvu_get_lmtst_tbl_index(rvu, req->hdr.pcifunc);
err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
&val, LMT_TBL_OP_READ); if (err) {
dev_err(rvu->dev, "Failed to read LMT map table: index 0x%x err %d\n",
tbl_idx + LMT_MAP_TBL_W1_OFF, err); goto error;
}
/* Storing lmt map table entry word1 default value as this needs * to be reverted in FLR. Also making sure this default value * doesn't get overwritten on multiple calls to this mailbox.
*/ if (!pfvf->lmt_map_ent_w1)
pfvf->lmt_map_ent_w1 = val;
/* Disable early completion for Ordered LMTSTs. */ if (req->dis_sched_early_comp)
val |= (req->dis_sched_early_comp <<
APR_LMT_MAP_ENT_DIS_SCH_CMP_SHIFT); /* Enable scheduled LMTST */ if (req->sch_ena)
val |= (req->sch_ena << APR_LMT_MAP_ENT_SCH_ENA_SHIFT) |
req->ssow_pf_func; /* Disables LMTLINE prefetch before receiving store data. */ if (req->dis_line_pref)
val |= (req->dis_line_pref <<
APR_LMT_MAP_ENT_DIS_LINE_PREF_SHIFT);
err = lmtst_map_table_ops(rvu, tbl_idx + LMT_MAP_TBL_W1_OFF,
&val, LMT_TBL_OP_WRITE); if (err) {
dev_err(rvu->dev, "Failed to update LMT map table: index 0x%x err %d\n",
tbl_idx + LMT_MAP_TBL_W1_OFF, err); goto error;
}
}
error: return err;
}
/* Resetting the lmtst map table to original base addresses */ void rvu_reset_lmt_map_tbl(struct rvu *rvu, u16 pcifunc)
{ struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
u32 tbl_idx; int err;
if (is_rvu_otx2(rvu)) return;
if (pfvf->lmt_base_addr || pfvf->lmt_map_ent_w1) { /* This corresponds to lmt map table index */
tbl_idx = rvu_get_lmtst_tbl_index(rvu, pcifunc); /* Reverting back original lmt base addr for respective * pcifunc.
*/ if (pfvf->lmt_base_addr) {
err = lmtst_map_table_ops(rvu, tbl_idx,
&pfvf->lmt_base_addr,
LMT_TBL_OP_WRITE); if (err)
dev_err(rvu->dev, "Failed to update LMT map table: index 0x%x err %d\n",
tbl_idx, err);
pfvf->lmt_base_addr = 0;
} /* Reverting back to orginal word1 val of lmtst map table entry * which underwent changes.
*/ if (pfvf->lmt_map_ent_w1) {
err = lmtst_map_table_ops(rvu,
tbl_idx + LMT_MAP_TBL_W1_OFF,
&pfvf->lmt_map_ent_w1,
LMT_TBL_OP_WRITE); if (err)
dev_err(rvu->dev, "Failed to update LMT map table: index 0x%x err %d\n",
tbl_idx + LMT_MAP_TBL_W1_OFF, err);
pfvf->lmt_map_ent_w1 = 0;
}
}
}
/* No Programmable channels */ if (!(nix_const & BIT_ULL(60))) return 0;
hw->cap.programmable_chans = true;
/* If programmable channels are present then configure * channels such that all channel numbers are contiguous * leaving no holes. This way the new CPT channels can be * accomodated. The order of channel numbers assigned is * LBK, SDP, CGX and CPT. Also the base channel number * of a block must be multiple of number of channels * of the block.
*/
nr_lbk_chans = (nix_const >> 16) & 0xFFULL;
nr_sdp_chans = nix_const1 & 0xFFFULL;
nr_cgx_chans = nix_const & 0xFFULL;
nr_cpt_chans = (nix_const >> 32) & 0xFFFULL;
sdp_chan_base = hw->lbk_chan_base + hw->lbk_links * nr_lbk_chans; /* Round up base channel to multiple of number of channels */
hw->sdp_chan_base = ALIGN(sdp_chan_base, nr_sdp_chans);
/* Out of 4096 channels start CPT from 2048 so * that MSB for CPT channels is always set
*/ if (cpt_chan_base <= NIX_CHAN_CPT_CH_START) {
hw->cpt_chan_base = NIX_CHAN_CPT_CH_START;
} else {
dev_err(rvu->dev, "CPT channels could not fit in the range 2048-4095\n"); return -EINVAL;
}
/* To loopback packets between multiple NIX blocks * mutliple LBK blocks are needed. With two NIX blocks, * four LBK blocks are needed and each LBK block * source and destination are as follows: * LBK0 - source NIX0 and destination NIX1 * LBK1 - source NIX0 and destination NIX1 * LBK2 - source NIX1 and destination NIX0 * LBK3 - source NIX1 and destination NIX1 * As per the HRM channel numbers should be programmed as: * P2X and X2P of LBK0 as same * P2X and X2P of LBK3 as same * P2X of LBK1 and X2P of LBK2 as same * P2X of LBK2 and X2P of LBK1 as same
*/ while (true) {
pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
PCI_DEVID_OCTEONTX2_LBK, pdev); if (!pdev) return;
base = pci_ioremap_bar(pdev, 0); if (!base) goto err_put;
/* There is no read-only constant register to read * the number of channels for LMAC and it is always 16.
*/
cfg |= FIELD_PREP(RPMX_CMRX_LINK_RANGE_MASK, ilog2(16));
cfg |= FIELD_PREP(RPMX_CMRX_LINK_BASE_MASK, base);
cgx_lmac_write(cgxid, lmacid, RPMX_CMRX_LINK_CFG, cfg);
}
staticvoid rvu_rpm_set_channels(struct rvu *rvu)
{ struct rvu_hwinfo *hw = rvu->hw;
u16 base = hw->cgx_chan_base; int cgx, lmac;
for (cgx = 0; cgx < rvu->cgx_cnt_max; cgx++) { for (lmac = 0; lmac < hw->lmac_per_cgx; lmac++) {
__rvu_rpm_set_channels(cgx, lmac, base);
base += 16;
}
}
}
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.