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>
This commit is contained in:
parent
1ba8f6561a
commit
8551cdeb2a
|
@ -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;
|
||||
|
||||
for (i = 0; i < vcap_is2.entry_words; i++) {
|
||||
entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < vcap_is2.entry_words; i++) {
|
||||
entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH);
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < vcap_is2.action_words; i++)
|
||||
action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue