drivers/net/vsc9953: Add command for shared/private VLAN learning
authorCodrin Ciubotariu <codrin.ciubotariu@freescale.com>
Fri, 24 Jul 2015 13:55:34 +0000 (16:55 +0300)
committerYork Sun <yorksun@freescale.com>
Mon, 21 Sep 2015 15:29:48 +0000 (08:29 -0700)
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@freescale.com>
Signed-off-by: Codrin Ciubotariu <codrin.ciubotariu@freescale.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Reviewed-by: York Sun <yorksun@freescale.com>
common/cmd_ethsw.c
drivers/net/vsc9953.c
include/ethsw.h
include/vsc9953.h

index 1fa93effdbc99babe15bfe8caff70d9294e24f23..8cc2a19fe17a2f35786112759c2eb074956804e4 100644 (file)
@@ -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"
 );
index c5c0e5c60fef937ff1d497bba1f4730b7b06aea0..f8f52334b9a7772885476d7d8deb0e7d2b867954 100644 (file)
@@ -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 */
index cc9708e9ac4c75e88d9d91b3b517215d7bc6a884..18d2b26b4bd304fb81b573b0f6e736a04e5bb8ee 100644 (file)
@@ -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);
index 12b7acecad1c46e5409498f44eb330bd36c879f5..24a22a39258dc7eb62ac776d1f7fd3e9b6486c26 100644 (file)
 /* 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