diff mbox

[U-Boot,09/10] drivers/net/vsc9953: Add command for shared/private VLAN learning

Message ID 1434035420-1663-11-git-send-email-codrin.ciubotariu@freescale.com
State Changes Requested
Delegated to: York Sun
Headers show

Commit Message

Codrin Ciubotariu June 11, 2015, 3:10 p.m. UTC
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.

Signed-off-by: Johnson Leung <johnson.leung@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@freescale.com>
Change-Id: I6b2ac706ff9ef7bb9d873402b293455366cf5034
---
 drivers/net/vsc9953.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/vsc9953.h     |   3 +
 2 files changed, 158 insertions(+)
diff mbox

Patch

diff --git a/drivers/net/vsc9953.c b/drivers/net/vsc9953.c
index b78a941..3129b03 100644
--- a/drivers/net/vsc9953.c
+++ b/drivers/net/vsc9953.c
@@ -1503,6 +1503,58 @@  static void vsc9953_mac_table_flush(int port, int vid)
 	vsc9953_mac_table_age(port, vid);
 }
 
+/* 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,
+			     CONFIG_VSC9953_FID_MASK_ALL);
+		break;
+	case PRIVATE_VLAN_LEARNING:
+		clrbits_le32(&l2ana_reg->ana.agen_ctrl,
+			     CONFIG_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 & CONFIG_VSC9953_FID_MASK_ALL)) {
+		*lrn_mode = PRIVATE_VLAN_LEARNING;
+	} else if ((val & CONFIG_VSC9953_FID_MASK_ALL) ==
+			CONFIG_VSC9953_FID_MASK_ALL) {
+		*lrn_mode = SHARED_VLAN_LEARNING;
+	} else {
+		printf("Unknown VLAN learning mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 enum egress_vlan_tag {
 	EGR_TAG_CLASS = 0,
 	EGR_TAG_PVID,
@@ -1572,6 +1624,8 @@  enum keyword_id {
 	id_egress,
 	id_tag,
 	id_classified,
+	id_shared,
+	id_private,
 	id_count,	/* keep last */
 };
 
@@ -1868,6 +1922,61 @@  static int vsc9953_vlan_set_key_func(struct command_def *parsed_cmd)
 	return 0;
 }
 
+#define VSC9953_VLAN_FDB_HELP "ethsw vlan fdb " \
+"{ [help] | show | shared | private } " \
+"- make VLAN learning shared or private"
+
+static int vsc9953_vlan_learn_help_key_func(struct command_def *parsed_cmd)
+{
+	printf(VSC9953_VLAN_FDB_HELP"\n");
+
+	return 0;
+}
+
+static int vsc9953_vlan_learn_show_key_func(struct command_def *parsed_cmd)
+{
+	int				rc;
+	enum vlan_learning_mode		mode;
+
+	rc = vsc9953_vlan_learning_get(&mode);
+	if (rc)
+		goto __out_return;
+
+	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 = -EINVAL;
+	}
+
+__out_return:
+	return rc;
+}
+
+static int vsc9953_vlan_learn_set_key_func(struct 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] ==
+	    id_shared)
+		mode = SHARED_VLAN_LEARNING;
+	else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] ==
+		 id_private)
+		mode = PRIVATE_VLAN_LEARNING;
+	else
+		return -1;
+
+	vsc9953_vlan_learning_set(mode);
+
+	return 0;
+}
+
 #define VSC9953_PORT_UNTAG_HELP "ethsw [port <port_no>] untagged " \
 "{ [help] | show | all | none | pvid } " \
 " - set egress tagging mod for a port"
@@ -2331,6 +2440,45 @@  struct keywords_to_function {
 					id_key_end,
 			},
 			.keyword_function = &vsc9953_fdb_entry_del_key_func,
+		}, {
+			.cmd_keyword = {
+					id_vlan,
+					id_fdb,
+					id_key_end,
+			},
+			.keyword_function = &vsc9953_vlan_learn_help_key_func,
+		}, {
+			.cmd_keyword = {
+					id_vlan,
+					id_fdb,
+					id_help,
+					id_key_end,
+			},
+			.keyword_function = &vsc9953_vlan_learn_help_key_func,
+		}, {
+			.cmd_keyword = {
+					id_vlan,
+					id_fdb,
+					id_show,
+					id_key_end,
+			},
+			.keyword_function = &vsc9953_vlan_learn_show_key_func,
+		}, {
+			.cmd_keyword = {
+					id_vlan,
+					id_fdb,
+					id_shared,
+					id_key_end,
+			},
+			.keyword_function = &vsc9953_vlan_learn_set_key_func,
+		}, {
+			.cmd_keyword = {
+					id_vlan,
+					id_fdb,
+					id_private,
+					id_key_end,
+			},
+			.keyword_function = &vsc9953_vlan_learn_set_key_func,
 		},
 };
 
@@ -2447,6 +2595,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,
 		},
 };
 
@@ -2770,6 +2924,7 @@  U_BOOT_CMD(ethsw, VSC9953_MAX_CMD_PARAMS, 0, do_ethsw,
 	   VSC9953_PVID_HELP"\n"
 	   VSC9953_PORT_UNTAG_HELP"\n"
 	   VSC9953_EGR_VLAN_TAG_HELP"\n"
+	   VSC9953_VLAN_FDB_HELP"\n"
 );
 
 #endif /* CONFIG_VSC9953_CMD */
diff --git a/include/vsc9953.h b/include/vsc9953.h
index 6eb22a9..26a08aa 100644
--- a/include/vsc9953.h
+++ b/include/vsc9953.h
@@ -142,6 +142,9 @@ 
 /* Macros for vsc9953_qsys_sys.switch_port_mode register */
 #define CONFIG_VSC9953_PORT_ENA		0x00002000
 
+/* Macros for vsc9953_ana_ana.agen_ctrl register */
+#define CONFIG_VSC9953_FID_MASK_ALL	0x00fff000
+
 /* Macros for vsc9953_ana_ana.adv_learn register */
 #define CONFIG_VSC9953_VLAN_CHK		0x00000400