@@ -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 */
@@ -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