diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2020-02-29 17:31:12 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-04 05:57:49 +0300 |
commit | 8551cdeb2ad1711e3ae85799ad9cc41c0bc64e0b (patch) | |
tree | 5f445880e0c192c26aa2813ebdb9ed955870bd52 | |
parent | 1ba8f6561a3ba3a4ac4becadb691667645fe73d2 (diff) | |
download | linux-8551cdeb2ad1711e3ae85799ad9cc41c0bc64e0b.tar.xz |
net: mscc: ocelot: parameterize the vcap_is2 properties
Remove the definitions for the VCAP IS2 table from ocelot_ace.c, since
it is specific to VSC7514.
The VSC9959 VCAP IS2 table supports more rules (1024 instead of 64) and
has a different width for the action (89 bits instead of 99).
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot_ace.c | 134 | ||||
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot_board.c | 30 | ||||
-rw-r--r-- | include/soc/mscc/ocelot.h | 1 | ||||
-rw-r--r-- | include/soc/mscc/ocelot_vcap.h | 37 |
4 files changed, 114 insertions, 88 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index 9922033a2aaf..906b54025b17 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -11,53 +11,7 @@ #include "ocelot_s2.h" #define OCELOT_POLICER_DISCARD 0x17f - -struct vcap_props { - const char *name; /* Symbolic name */ - u16 tg_width; /* Type-group width (in bits) */ - u16 sw_count; /* Sub word count */ - u16 entry_count; /* Entry count */ - u16 entry_words; /* Number of entry words */ - u16 entry_width; /* Entry width (in bits) */ - u16 action_count; /* Action count */ - u16 action_words; /* Number of action words */ - u16 action_width; /* Action width (in bits) */ - u16 action_type_width; /* Action type width (in bits) */ - struct { - u16 width; /* Action type width (in bits) */ - u16 count; /* Action type sub word count */ - } action_table[2]; - u16 counter_words; /* Number of counter words */ - u16 counter_width; /* Counter width (in bits) */ -}; - #define ENTRY_WIDTH 32 -#define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH)) - -static const struct vcap_props vcap_is2 = { - .name = "IS2", - .tg_width = 2, - .sw_count = 4, - .entry_count = VCAP_IS2_CNT, - .entry_words = BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH), - .entry_width = VCAP_IS2_ENTRY_WIDTH, - .action_count = (VCAP_IS2_CNT + VCAP_PORT_CNT + 2), - .action_words = BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH), - .action_width = (VCAP_IS2_ACTION_WIDTH), - .action_type_width = 1, - .action_table = { - { - .width = 49, - .count = 2 - }, - { - .width = 6, - .count = 4 - }, - }, - .counter_words = BITS_TO_32BIT(4 * ENTRY_WIDTH), - .counter_width = ENTRY_WIDTH, -}; enum vcap_sel { VCAP_SEL_ENTRY = 0x1, @@ -100,11 +54,13 @@ static u32 vcap_s2_read_update_ctrl(struct ocelot *ocelot) static void vcap_cmd(struct ocelot *ocelot, u16 ix, int cmd, int sel) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 value = (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) | S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) | S2_CORE_UPDATE_CTRL_UPDATE_SHOT); - if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2.entry_count) + if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2->entry_count) return; if (!(sel & VCAP_SEL_ENTRY)) @@ -125,14 +81,19 @@ static void vcap_cmd(struct ocelot *ocelot, u16 ix, int cmd, int sel) /* Convert from 0-based row to VCAP entry row and run command */ static void vcap_row_cmd(struct ocelot *ocelot, u32 row, int cmd, int sel) { - vcap_cmd(ocelot, vcap_is2.entry_count - row - 1, cmd, sel); + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + + vcap_cmd(ocelot, vcap_is2->entry_count - row - 1, cmd, sel); } static void vcap_entry2cache(struct ocelot *ocelot, struct vcap_data *data) { - u32 i; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 entry_words, i; + + entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.entry_words; i++) { + for (i = 0; i < entry_words; i++) { ocelot_write_rix(ocelot, data->entry[i], S2_CACHE_ENTRY_DAT, i); ocelot_write_rix(ocelot, ~data->mask[i], S2_CACHE_MASK_DAT, i); } @@ -141,9 +102,12 @@ static void vcap_entry2cache(struct ocelot *ocelot, struct vcap_data *data) static void vcap_cache2entry(struct ocelot *ocelot, struct vcap_data *data) { - u32 i; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 entry_words, i; + + entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.entry_words; i++) { + for (i = 0; i < entry_words; i++) { data->entry[i] = ocelot_read_rix(ocelot, S2_CACHE_ENTRY_DAT, i); // Invert mask data->mask[i] = ~ocelot_read_rix(ocelot, S2_CACHE_MASK_DAT, i); @@ -153,49 +117,56 @@ static void vcap_cache2entry(struct ocelot *ocelot, struct vcap_data *data) static void vcap_action2cache(struct ocelot *ocelot, struct vcap_data *data) { - u32 i, width, mask; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 action_words, i, width, mask; /* Encode action type */ - width = vcap_is2.action_type_width; + width = vcap_is2->action_type_width; if (width) { mask = GENMASK(width, 0); data->action[0] = ((data->action[0] & ~mask) | data->type); } - for (i = 0; i < vcap_is2.action_words; i++) - ocelot_write_rix(ocelot, data->action[i], - S2_CACHE_ACTION_DAT, i); + action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.counter_words; i++) - ocelot_write_rix(ocelot, data->counter[i], - S2_CACHE_CNT_DAT, i); + for (i = 0; i < action_words; i++) + ocelot_write_rix(ocelot, data->action[i], S2_CACHE_ACTION_DAT, + i); + + for (i = 0; i < vcap_is2->counter_words; i++) + ocelot_write_rix(ocelot, data->counter[i], S2_CACHE_CNT_DAT, i); } static void vcap_cache2action(struct ocelot *ocelot, struct vcap_data *data) { - u32 i, width; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 action_words, i, width; + + action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.action_words; i++) + for (i = 0; i < action_words; i++) data->action[i] = ocelot_read_rix(ocelot, S2_CACHE_ACTION_DAT, i); - for (i = 0; i < vcap_is2.counter_words; i++) + for (i = 0; i < vcap_is2->counter_words; i++) data->counter[i] = ocelot_read_rix(ocelot, S2_CACHE_CNT_DAT, i); /* Extract action type */ - width = vcap_is2.action_type_width; + width = vcap_is2->action_type_width; data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0); } /* Calculate offsets for entry */ -static void is2_data_get(struct vcap_data *data, int ix) +static void is2_data_get(struct ocelot *ocelot, struct vcap_data *data, int ix) { - u32 i, col, offset, count, cnt, base, width = vcap_is2.tg_width; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 i, col, offset, count, cnt, base; + u32 width = vcap_is2->tg_width; count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4); col = (ix % 2); - cnt = (vcap_is2.sw_count / count); - base = (vcap_is2.sw_count - col * cnt - cnt); + cnt = (vcap_is2->sw_count / count); + base = (vcap_is2->sw_count - col * cnt - cnt); data->tg_value = 0; data->tg_mask = 0; for (i = 0; i < cnt; i++) { @@ -206,13 +177,13 @@ static void is2_data_get(struct vcap_data *data, int ix) /* Calculate key/action/counter offsets */ col = (count - col - 1); - data->key_offset = (base * vcap_is2.entry_width) / vcap_is2.sw_count; - data->counter_offset = (cnt * col * vcap_is2.counter_width); + data->key_offset = (base * vcap_is2->entry_width) / vcap_is2->sw_count; + data->counter_offset = (cnt * col * vcap_is2->counter_width); i = data->type; - width = vcap_is2.action_table[i].width; - cnt = vcap_is2.action_table[i].count; + width = vcap_is2->action_table[i].width; + cnt = vcap_is2->action_table[i].count; data->action_offset = - (((cnt * col * width) / count) + vcap_is2.action_type_width); + (((cnt * col * width) / count) + vcap_is2->action_type_width); } static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value) @@ -354,6 +325,7 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, static void is2_entry_set(struct ocelot *ocelot, int ix, struct ocelot_ace_rule *ace) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; u32 val, msk, type, type_mask = 0xf, i, count; struct ocelot_ace_vlan *tag = &ace->vlan; struct ocelot_vcap_u64 payload; @@ -369,7 +341,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, vcap_cache2action(ocelot, &data); data.tg_sw = VCAP_TG_HALF; - is2_data_get(&data, ix); + is2_data_get(ocelot, &data, ix); data.tg = (data.tg & ~data.tg_mask); if (ace->prio != 0) data.tg |= data.tg_value; @@ -627,7 +599,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, default: type = 0; type_mask = 0; - count = (vcap_is2.entry_width / 2); + count = vcap_is2->entry_width / 2; /* Iterate over the non-common part of the key and * clear entry data */ @@ -641,7 +613,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, vcap_key_set(ocelot, &data, VCAP_IS2_TYPE, type, type_mask); is2_action_set(ocelot, &data, ace->action); vcap_data_set(data.counter, data.counter_offset, - vcap_is2.counter_width, ace->stats.pkts); + vcap_is2->counter_width, ace->stats.pkts); /* Write row */ vcap_entry2cache(ocelot, &data); @@ -652,6 +624,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, int ix) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; struct vcap_data data; int row = (ix / 2); u32 cnt; @@ -659,9 +632,9 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER); vcap_cache2action(ocelot, &data); data.tg_sw = VCAP_TG_HALF; - is2_data_get(&data, ix); + is2_data_get(ocelot, &data, ix); cnt = vcap_data_get(data.counter, data.counter_offset, - vcap_is2.counter_width); + vcap_is2->counter_width); rule->stats.pkts = cnt; } @@ -805,16 +778,17 @@ int ocelot_ace_rule_stats_update(struct ocelot *ocelot, int ocelot_ace_init(struct ocelot *ocelot) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; struct vcap_data data; memset(&data, 0, sizeof(data)); vcap_entry2cache(ocelot, &data); - ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG); + ocelot_write(ocelot, vcap_is2->entry_count, S2_CORE_MV_CFG); vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY); vcap_action2cache(ocelot, &data); - ocelot_write(ocelot, vcap_is2.action_count, S2_CORE_MV_CFG); + ocelot_write(ocelot, vcap_is2->action_count, S2_CORE_MV_CFG); vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ACTION | VCAP_SEL_COUNTER); diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index c9257a828d91..c343ca5276ef 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -18,6 +18,10 @@ #include "ocelot.h" #define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) +#define VSC7514_VCAP_IS2_CNT 64 +#define VSC7514_VCAP_IS2_ENTRY_WIDTH 376 +#define VSC7514_VCAP_IS2_ACTION_WIDTH 99 +#define VSC7514_VCAP_PORT_CNT 11 static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info) { @@ -337,6 +341,31 @@ static const struct vcap_field vsc7514_vcap_is2_actions[] = { [VCAP_IS2_ACT_HIT_CNT] = { 49, 32}, }; +static const struct vcap_props vsc7514_vcap_props[] = { + [VCAP_IS2] = { + .tg_width = 2, + .sw_count = 4, + .entry_count = VSC7514_VCAP_IS2_CNT, + .entry_width = VSC7514_VCAP_IS2_ENTRY_WIDTH, + .action_count = VSC7514_VCAP_IS2_CNT + + VSC7514_VCAP_PORT_CNT + 2, + .action_width = 99, + .action_type_width = 1, + .action_table = { + [IS2_ACTION_TYPE_NORMAL] = { + .width = 49, + .count = 2 + }, + [IS2_ACTION_TYPE_SMAC_SIP] = { + .width = 6, + .count = 4 + }, + }, + .counter_words = 4, + .counter_width = 32, + }, +}; + static int mscc_ocelot_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -439,6 +468,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys; ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions; + ocelot->vcap = vsc7514_vcap_props; ocelot_init(ocelot); ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 45630bee8ed2..30270571fb71 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -463,6 +463,7 @@ struct ocelot { const struct vcap_field *vcap_is2_keys; const struct vcap_field *vcap_is2_actions; + const struct vcap_props *vcap; /* Workqueue to check statistics for overflow with its lock */ struct mutex stats_lock; diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 0783f0ffc813..5748373ab4d3 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -11,6 +11,30 @@ * ================================================================= */ +enum { + /* VCAP_IS1, */ + VCAP_IS2, + /* VCAP_ES0, */ +}; + +struct vcap_props { + u16 tg_width; /* Type-group width (in bits) */ + u16 sw_count; /* Sub word count */ + u16 entry_count; /* Entry count */ + u16 entry_words; /* Number of entry words */ + u16 entry_width; /* Entry width (in bits) */ + u16 action_count; /* Action count */ + u16 action_words; /* Number of action words */ + u16 action_width; /* Action width (in bits) */ + u16 action_type_width; /* Action type width (in bits) */ + struct { + u16 width; /* Action type width (in bits) */ + u16 count; /* Action type sub word count */ + } action_table[2]; + u16 counter_words; /* Number of counter words */ + u16 counter_width; /* Counter width (in bits) */ +}; + /* VCAP Type-Group values */ #define VCAP_TG_NONE 0 /* Entry is invalid */ #define VCAP_TG_FULL 1 /* Full entry */ @@ -22,11 +46,6 @@ * ================================================================= */ -#define VCAP_IS2_CNT 64 -#define VCAP_IS2_ENTRY_WIDTH 376 -#define VCAP_IS2_ACTION_WIDTH 99 -#define VCAP_PORT_CNT 11 - /* IS2 half key types */ #define IS2_TYPE_ETYPE 0 #define IS2_TYPE_LLC 1 @@ -42,9 +61,11 @@ /* IS2 half key type mask for matching any IP */ #define IS2_TYPE_MASK_IP_ANY 0xe -/* IS2 action types */ -#define IS2_ACTION_TYPE_NORMAL 0 -#define IS2_ACTION_TYPE_SMAC_SIP 1 +enum { + IS2_ACTION_TYPE_NORMAL, + IS2_ACTION_TYPE_SMAC_SIP, + IS2_ACTION_TYPE_MAX, +}; /* IS2 MASK_MODE values */ #define IS2_ACT_MASK_MODE_NONE 0 |