summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/cmd_ethsw.c65
-rw-r--r--drivers/net/vsc9953.c95
-rw-r--r--include/ethsw.h4
-rw-r--r--include/vsc9953.h3
4 files changed, 167 insertions, 0 deletions
diff --git a/common/cmd_ethsw.c b/common/cmd_ethsw.c
index 1fa93effdb..8cc2a19fe1 100644
--- a/common/cmd_ethsw.c
+++ b/common/cmd_ethsw.c
@@ -92,6 +92,17 @@ static int ethsw_egr_tag_help_key_func(struct ethsw_command_def *parsed_cmd)
return CMD_RET_SUCCESS;
}
+#define ETHSW_VLAN_FDB_HELP "ethsw vlan fdb " \
+"{ [help] | show | shared | private } " \
+"- make VLAN learning shared or private"
+
+static int ethsw_vlan_learn_help_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ printf(ETHSW_VLAN_FDB_HELP"\n");
+
+ return CMD_RET_SUCCESS;
+}
+
static struct keywords_to_function {
enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS];
int cmd_func_offset;
@@ -416,6 +427,53 @@ static struct keywords_to_function {
.cmd_func_offset = offsetof(struct ethsw_command_func,
port_egr_vlan_set),
.keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_help,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = -1,
+ .keyword_function = &ethsw_vlan_learn_help_key_func,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_show,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_show),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_shared,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_set),
+ .keyword_function = NULL,
+ }, {
+ .cmd_keyword = {
+ ethsw_id_vlan,
+ ethsw_id_fdb,
+ ethsw_id_private,
+ ethsw_id_key_end,
+ },
+ .cmd_func_offset = offsetof(struct ethsw_command_func,
+ vlan_learn_set),
+ .keyword_function = NULL,
},
};
@@ -533,6 +591,12 @@ struct keyword_def {
}, {
.keyword_name = "classified",
.match = &keyword_match_gen,
+ }, {
+ .keyword_name = "shared",
+ .match = &keyword_match_gen,
+ }, {
+ .keyword_name = "private",
+ .match = &keyword_match_gen,
},
};
@@ -894,4 +958,5 @@ U_BOOT_CMD(ethsw, ETHSW_MAX_CMD_PARAMS, 0, do_ethsw,
ETHSW_VLAN_HELP"\n"
ETHSW_PORT_UNTAG_HELP"\n"
ETHSW_EGR_VLAN_TAG_HELP"\n"
+ ETHSW_VLAN_FDB_HELP"\n"
);
diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c
index c5c0e5c60f..f8f52334b9 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -1398,6 +1398,55 @@ static void vsc9953_port_vlan_egress_tag_get(int port_no,
*mode = EGR_TAG_CLASS;
}
+/* VSC9953 VLAN learning modes */
+enum vlan_learning_mode {
+ SHARED_VLAN_LEARNING,
+ PRIVATE_VLAN_LEARNING,
+};
+
+/* Set VLAN learning mode for VSC9953 */
+static void vsc9953_vlan_learning_set(enum vlan_learning_mode lrn_mode)
+{
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ switch (lrn_mode) {
+ case SHARED_VLAN_LEARNING:
+ setbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
+ break;
+ case PRIVATE_VLAN_LEARNING:
+ clrbits_le32(&l2ana_reg->ana.agen_ctrl, VSC9953_FID_MASK_ALL);
+ break;
+ default:
+ printf("Unknown VLAN learn mode\n");
+ }
+}
+
+/* Get VLAN learning mode for VSC9953 */
+static int vsc9953_vlan_learning_get(enum vlan_learning_mode *lrn_mode)
+{
+ u32 val;
+ struct vsc9953_analyzer *l2ana_reg;
+
+ l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
+ VSC9953_ANA_OFFSET);
+
+ val = in_le32(&l2ana_reg->ana.agen_ctrl);
+
+ if (!(val & VSC9953_FID_MASK_ALL)) {
+ *lrn_mode = PRIVATE_VLAN_LEARNING;
+ } else if ((val & VSC9953_FID_MASK_ALL) == VSC9953_FID_MASK_ALL) {
+ *lrn_mode = SHARED_VLAN_LEARNING;
+ } else {
+ printf("Unknown VLAN learning mode\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int vsc9953_port_status_key_func(struct ethsw_command_def *parsed_cmd)
{
int i;
@@ -1887,6 +1936,50 @@ static int vsc9953_egr_vlan_tag_set_key_func(
return CMD_RET_SUCCESS;
}
+static int vsc9953_vlan_learn_show_key_func(
+ struct ethsw_command_def *parsed_cmd)
+{
+ int rc;
+ enum vlan_learning_mode mode;
+
+ rc = vsc9953_vlan_learning_get(&mode);
+ if (rc)
+ return CMD_RET_FAILURE;
+
+ switch (mode) {
+ case SHARED_VLAN_LEARNING:
+ printf("VLAN learning mode: shared\n");
+ break;
+ case PRIVATE_VLAN_LEARNING:
+ printf("VLAN learning mode: private\n");
+ break;
+ default:
+ printf("Unknown VLAN learning mode\n");
+ rc = CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int vsc9953_vlan_learn_set_key_func(struct ethsw_command_def *parsed_cmd)
+{
+ enum vlan_learning_mode mode;
+
+ /* keywords for shared/private are the last in the array */
+ if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_shared)
+ mode = SHARED_VLAN_LEARNING;
+ else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+ ethsw_id_private)
+ mode = PRIVATE_VLAN_LEARNING;
+ else
+ return CMD_RET_USAGE;
+
+ vsc9953_vlan_learning_set(mode);
+
+ return CMD_RET_SUCCESS;
+}
+
static struct ethsw_command_func vsc9953_cmd_func = {
.ethsw_name = "L2 Switch VSC9953",
.port_enable = &vsc9953_port_status_key_func,
@@ -1908,6 +2001,8 @@ static struct ethsw_command_func vsc9953_cmd_func = {
.port_untag_set = &vsc9953_port_untag_set_key_func,
.port_egr_vlan_show = &vsc9953_egr_vlan_tag_show_key_func,
.port_egr_vlan_set = &vsc9953_egr_vlan_tag_set_key_func,
+ .vlan_learn_show = &vsc9953_vlan_learn_show_key_func,
+ .vlan_learn_set = &vsc9953_vlan_learn_set_key_func,
};
#endif /* CONFIG_CMD_ETHSW */
diff --git a/include/ethsw.h b/include/ethsw.h
index cc9708e9ac..18d2b26b4b 100644
--- a/include/ethsw.h
+++ b/include/ethsw.h
@@ -37,6 +37,8 @@ enum ethsw_keyword_id {
ethsw_id_egress,
ethsw_id_tag,
ethsw_id_classified,
+ ethsw_id_shared,
+ ethsw_id_private,
ethsw_id_count, /* keep last */
};
@@ -80,6 +82,8 @@ struct ethsw_command_func {
int (*port_untag_set)(struct ethsw_command_def *parsed_cmd);
int (*port_egr_vlan_show)(struct ethsw_command_def *parsed_cmd);
int (*port_egr_vlan_set)(struct ethsw_command_def *parsed_cmd);
+ int (*vlan_learn_show)(struct ethsw_command_def *parsed_cmd);
+ int (*vlan_learn_set)(struct ethsw_command_def *parsed_cmd);
};
int ethsw_define_functions(const struct ethsw_command_func *cmd_func);
diff --git a/include/vsc9953.h b/include/vsc9953.h
index 12b7acecad..24a22a3925 100644
--- a/include/vsc9953.h
+++ b/include/vsc9953.h
@@ -135,6 +135,9 @@
/* Macros for vsc9953_qsys_sys.switch_port_mode register */
#define VSC9953_PORT_ENA 0x00002000
+/* Macros for vsc9953_ana_ana.agen_ctrl register */
+#define VSC9953_FID_MASK_ALL 0x00fff000
+
/* Macros for vsc9953_ana_ana.adv_learn register */
#define VSC9953_VLAN_CHK 0x00000400
OpenPOWER on IntegriCloud