From: Codrin Ciubotariu Date: Fri, 24 Jul 2015 13:55:34 +0000 (+0300) Subject: drivers/net/vsc9953: Add command for shared/private VLAN learning X-Git-Tag: v2015.10-rc4~23^2~2 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=21d214fcd0a12c75ebb9c675f0f07b8e69f6cb44;p=u-boot drivers/net/vsc9953: Add command for shared/private VLAN learning 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 Signed-off-by: Codrin Ciubotariu Acked-by: Joe Hershberger Reviewed-by: York Sun --- 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 = ðsw_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 = ðsw_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