int nfp_target_pushpull(u32 cpp_id, u64 address)
{ switch (NFP_CPP_ID_TARGET_of(cpp_id)) { case NFP_CPP_TARGET_NBI: return nfp6000_nbi(cpp_id, address); case NFP_CPP_TARGET_QDR: return target_rw(cpp_id, P32, 24, 4); case NFP_CPP_TARGET_ILA: return nfp6000_ila(cpp_id); case NFP_CPP_TARGET_MU: return nfp6000_mu(cpp_id, address); case NFP_CPP_TARGET_PCIE: return nfp6000_pci(cpp_id); case NFP_CPP_TARGET_ARM: if (address < 0x10000) return target_rw(cpp_id, P64, 1, 1); else return target_rw(cpp_id, P32, 1, 1); case NFP_CPP_TARGET_CRYPTO: return nfp6000_crypto(cpp_id); case NFP_CPP_TARGET_CT_XPB: return nfp6000_cap_xpb(cpp_id); case NFP_CPP_TARGET_CLS: return nfp6000_cls(cpp_id); case 0: return target_rw(cpp_id, P32, 4, 4); default: return -EINVAL;
}
}
#undef AT #undef P32 #undef P64
/* All magic NFP-6xxx IMB 'mode' numbers here are from: * Databook (1 August 2013) * - System Overview and Connectivity * -- Internal Connectivity * --- Distributed Switch Fabric - Command Push/Pull (DSF-CPP) Bus * ---- CPP addressing * ----- Table 3.6. CPP Address Translation Mode Commands
*/
#define _NIC_NFP6000_MU_LOCALITY_DIRECT 2
staticint nfp_decode_basic(u64 addr, int *dest_island, int cpp_tgt, int mode, bool addr40, int isld1, int isld0)
{ int iid_lsb, idx_lsb;
/* This function doesn't handle MU or CTXBP */ if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB) return -EINVAL;
switch (mode) { case 0: /* For VQDR, in this mode for 32-bit addressing * it would be islands 0, 16, 32 and 48 depending on channel * and upper address bits. * Since those are not all valid islands, most decode * cases would result in bad island IDs, but we do them * anyway since this is decoding an address that is already * assumed to be used as-is to get to sram.
*/
iid_lsb = addr40 ? 34 : 26;
*dest_island = (addr >> iid_lsb) & 0x3F; return 0; case 1: /* For VQDR 32-bit, this would decode as: * Channel 0: island#0 * Channel 1: island#0 * Channel 2: island#1 * Channel 3: island#1 * That would be valid as long as both islands * have VQDR. Let's allow this.
*/
idx_lsb = addr40 ? 39 : 31; if (addr & BIT_ULL(idx_lsb))
*dest_island = isld1; else
*dest_island = isld0;
return 0; case 2: /* For VQDR 32-bit: * Channel 0: (island#0 | 0) * Channel 1: (island#0 | 1) * Channel 2: (island#1 | 0) * Channel 3: (island#1 | 1) * * Make sure we compare against isldN values * by clearing the LSB. * This is what the silicon does.
*/
isld0 &= ~1;
isld1 &= ~1;
return 0; case 3: /* In this mode the data address starts to affect the island ID * so rather not allow it. In some really specific case * one could use this to send the upper half of the * VQDR channel to another MU, but this is getting very * specific. * However, as above for mode 0, this is the decoder * and the caller should validate the resulting IID. * This blindly does what the silicon would do.
*/
isld0 &= ~3;
isld1 &= ~3;
staticint nfp_encode_basic_qdr(u64 addr, int dest_island, int cpp_tgt, int mode, bool addr40, int isld1, int isld0)
{ int v, ret;
/* Full Island ID and channel bits overlap? */
ret = nfp_decode_basic(addr, &v, cpp_tgt, mode, addr40, isld1, isld0); if (ret) return ret;
/* The current address won't go where expected? */ if (dest_island != -1 && dest_island != v) return -EINVAL;
/* If dest_island was -1, we don't care where it goes. */ return 0;
}
/* Try each option, take first one that fits. * Not sure if we would want to do some smarter * searching and prefer 0 or non-0 island IDs.
*/ staticint nfp_encode_basic_search(u64 *addr, int dest_island, int *isld, int iid_lsb, int idx_lsb, int v_max)
{ int i, v;
for (i = 0; i < 2; i++) for (v = 0; v < v_max; v++) { if (dest_island != (isld[i] | v)) continue;
/* For VQDR, we may not modify the Channel bits, which might overlap * with the Index bit. When it does, we need to ensure that isld0 == isld1.
*/ staticint nfp_encode_basic(u64 *addr, int dest_island, int cpp_tgt, int mode, bool addr40, int isld1, int isld0)
{ int iid_lsb, idx_lsb; int isld[2];
u64 v64;
isld[0] = isld0;
isld[1] = isld1;
/* This function doesn't handle MU or CTXBP */ if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB) return -EINVAL;
switch (mode) { case 0: if (cpp_tgt == NFP_CPP_TARGET_QDR && !addr40) /* In this specific mode we'd rather not modify * the address but we can verify if the existing * contents will point to a valid island.
*/ return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
mode, addr40, isld1, isld0);
idx_lsb = addr40 ? 39 : 31; if (dest_island == isld0) { /* Only need to clear the Index bit */
*addr &= ~BIT_ULL(idx_lsb); return 0;
}
if (dest_island == isld1) { /* Only need to set the Index bit */
*addr |= BIT_ULL(idx_lsb); return 0;
}
return -ENODEV; case 2: /* iid<0> = addr<30> = channel<0> * channel<1> = addr<31> = Index
*/ if (cpp_tgt == NFP_CPP_TARGET_QDR && !addr40) /* Special case where we allow channel bits to * be set before hand and with them select an island. * So we need to confirm that it's at least plausible.
*/ return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
mode, addr40, isld1, isld0);
/* Make sure we compare against isldN values * by clearing the LSB. * This is what the silicon does.
*/
isld[0] &= ~1;
isld[1] &= ~1;
staticint nfp_encode_mu(u64 *addr, int dest_island, int mode, bool addr40, int isld1, int isld0)
{ int iid_lsb, idx_lsb, locality_lsb; int isld[2];
u64 v64; int da;
return nfp_encode_basic_search(addr, dest_island, isld,
iid_lsb, idx_lsb, 2); case 3: /* Only the EMU will use 40 bit addressing. Silently * set the direct locality bit for everyone else. * The SDK toolchain uses dest_island <= 0 to test * for atypical address encodings to support access * to local-island CTM with a 32-but address (high-locality * is effewctively ignored and just used for * routing to island #0).
*/ if (dest_island > 0 && (dest_island < 24 || dest_island > 26)) {
*addr |= ((u64)_NIC_NFP6000_MU_LOCALITY_DIRECT)
<< locality_lsb;
da = 1;
}
staticint nfp_cppat_addr_encode(u64 *addr, int dest_island, int cpp_tgt, int mode, bool addr40, int isld1, int isld0)
{ switch (cpp_tgt) { case NFP_CPP_TARGET_NBI: case NFP_CPP_TARGET_QDR: case NFP_CPP_TARGET_ILA: case NFP_CPP_TARGET_PCIE: case NFP_CPP_TARGET_ARM: case NFP_CPP_TARGET_CRYPTO: case NFP_CPP_TARGET_CLS: return nfp_encode_basic(addr, dest_island, cpp_tgt, mode,
addr40, isld1, isld0);
case NFP_CPP_TARGET_MU: return nfp_encode_mu(addr, dest_island, mode,
addr40, isld1, isld0);
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.