[U-Boot] [PATCH v3 14/16] drivers/net/vsc9953: Add command for shared/private VLAN learning

Codrin Ciubotariu codrin.ciubotariu at freescale.com
Fri Jul 24 15:55:34 CEST 2015


The command:
ethsw vlan fdb { [help] | show | shared | private }
 - make VLAN learning shared or private"

configures the FDB to share the FDB entries learned on multiple VLANs
or to keep them separated. By default, the FBD uses private VLAN
learning. This command has also been added to the ethsw generic parser
from common/cmd_ethsw.c

Signed-off-by: Johnson Leung <johnson.leung at freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu at freescale.com>
---
		
Changes for v2:
        - removed Change-id field;

Changes for v3:
        - replaced values returned by functions called by the parser with CMD_RET_* macros;
        - removed "CONFIG_" from macros added in vsc9953.h;
        - each variabled is declared on a separate line, with one space instead of tab(s);

 common/cmd_ethsw.c    | 65 +++++++++++++++++++++++++++++++++++
 drivers/net/vsc9953.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/ethsw.h       |  4 +++
 include/vsc9953.h     |  3 ++
 4 files changed, 167 insertions(+)

diff --git a/common/cmd_ethsw.c b/common/cmd_ethsw.c
index 8ba202b..44a7f01 100644
--- a/common/cmd_ethsw.c
+++ b/common/cmd_ethsw.c
@@ -91,6 +91,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;
@@ -415,6 +426,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,
 		},
 };
 
@@ -532,6 +590,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,
 		},
 };
 
@@ -892,4 +956,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 8ba1470..7df321b 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -1399,6 +1399,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;
@@ -1888,6 +1937,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,
@@ -1909,6 +2002,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 cc9708e..18d2b26 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 12b7ace..24a22a3 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
 
-- 
1.9.3



More information about the U-Boot mailing list