summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/netronome/nfp/nfp_asm.c
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2017-10-09 07:04:11 +0300
committerDavid S. Miller <davem@davemloft.net>2017-10-09 19:51:03 +0300
commit9f15d0f438372986b0f9de36f805fe2dd83f9c27 (patch)
tree68a16e5a2f224e225e21df8e013b2f7827b83b4b /drivers/net/ethernet/netronome/nfp/nfp_asm.c
parent8afd9c961e95b1529cbc2b2b9c063a488659b337 (diff)
downloadlinux-9f15d0f438372986b0f9de36f805fe2dd83f9c27.tar.xz
nfp: bpf: encode LMEM accesses
NFP LMEM is a large, indirectly accessed register file. There are two basic indirect access registers. Each access operation may either use offset (up to 8 or 16 words) or perform post decrement/increment. Add encodings of LMEM indexes as instruction operands. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/netronome/nfp/nfp_asm.c')
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_asm.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_asm.c b/drivers/net/ethernet/netronome/nfp/nfp_asm.c
index 4c9201bf9331..4bcab43da16d 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_asm.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_asm.c
@@ -48,6 +48,7 @@ const struct cmd_tgt_act cmd_tgt_act[__CMD_TGT_MAP_SIZE] = {
static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
{
+ bool lm_id, lm_dec = false;
u16 val = swreg_value(reg);
switch (swreg_type(reg)) {
@@ -59,6 +60,33 @@ static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst)
return UR_REG_NN | val;
case NN_REG_XFER:
return UR_REG_XFR | val;
+ case NN_REG_LMEM:
+ lm_id = swreg_lm_idx(reg);
+
+ switch (swreg_lm_mode(reg)) {
+ case NN_LM_MOD_NONE:
+ if (val & ~UR_REG_LM_IDX_MAX) {
+ pr_err("LM offset too large\n");
+ return 0;
+ }
+ return UR_REG_LM | FIELD_PREP(UR_REG_LM_IDX, lm_id) |
+ val;
+ case NN_LM_MOD_DEC:
+ lm_dec = true;
+ /* fall through */
+ case NN_LM_MOD_INC:
+ if (val) {
+ pr_err("LM offset in inc/dev mode\n");
+ return 0;
+ }
+ return UR_REG_LM | UR_REG_LM_POST_MOD |
+ FIELD_PREP(UR_REG_LM_IDX, lm_id) |
+ FIELD_PREP(UR_REG_LM_POST_MOD_DEC, lm_dec);
+ default:
+ pr_err("bad LM mode for unrestricted operands %d\n",
+ swreg_lm_mode(reg));
+ return 0;
+ }
case NN_REG_IMM:
if (val & ~0xff) {
pr_err("immediate too large\n");
@@ -108,6 +136,7 @@ int swreg_to_unrestricted(swreg dst, swreg lreg, swreg rreg,
static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
{
u16 val = swreg_value(reg);
+ bool lm_id;
switch (swreg_type(reg)) {
case NN_REG_GPR_A:
@@ -116,6 +145,21 @@ static u16 nfp_swreg_to_rereg(swreg reg, bool is_dst, bool has_imm8, bool *i8)
return val;
case NN_REG_XFER:
return RE_REG_XFR | val;
+ case NN_REG_LMEM:
+ lm_id = swreg_lm_idx(reg);
+
+ if (swreg_lm_mode(reg) != NN_LM_MOD_NONE) {
+ pr_err("bad LM mode for restricted operands %d\n",
+ swreg_lm_mode(reg));
+ return 0;
+ }
+
+ if (val & ~RE_REG_LM_IDX_MAX) {
+ pr_err("LM offset too large\n");
+ return 0;
+ }
+
+ return RE_REG_LM | FIELD_PREP(RE_REG_LM_IDX, lm_id) | val;
case NN_REG_IMM:
if (val & ~(0x7f | has_imm8 << 7)) {
pr_err("immediate too large\n");