Commit 68c929da6bf754ace639b2159e2d5b9e22323aaa
Committed by
York Sun
1 parent
86719f0cd5
Exists in
v2017.01-smarct4x
and in
30 other branches
drivers/net/vsc9953: Add commands to enable/disable HW learning
The command: ethsw [port <port_no>] learning { [help] | show | auto | disable } can be used to enable/disable HW learning on a port. This patch also adds this command to the generic ethsw parser from cmd_ethsw. 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>
Showing 4 changed files with 211 additions and 0 deletions Side-by-side Diff
common/cmd_ethsw.c
... | ... | @@ -23,6 +23,17 @@ |
23 | 23 | return CMD_RET_SUCCESS; |
24 | 24 | } |
25 | 25 | |
26 | +#define ETHSW_LEARN_HELP "ethsw [port <port_no>] learning " \ | |
27 | +"{ [help] | show | auto | disable } " \ | |
28 | +"- enable/disable/show learning configuration on a port" | |
29 | + | |
30 | +static int ethsw_learn_help_key_func(struct ethsw_command_def *parsed_cmd) | |
31 | +{ | |
32 | + printf(ETHSW_LEARN_HELP"\n"); | |
33 | + | |
34 | + return CMD_RET_SUCCESS; | |
35 | +} | |
36 | + | |
26 | 37 | static struct keywords_to_function { |
27 | 38 | enum ethsw_keyword_id cmd_keyword[ETHSW_MAX_CMD_PARAMS]; |
28 | 39 | int cmd_func_offset; |
... | ... | @@ -77,6 +88,48 @@ |
77 | 88 | .cmd_func_offset = offsetof(struct ethsw_command_func, |
78 | 89 | port_stats_clear), |
79 | 90 | .keyword_function = NULL, |
91 | + }, { | |
92 | + .cmd_keyword = { | |
93 | + ethsw_id_learning, | |
94 | + ethsw_id_key_end, | |
95 | + }, | |
96 | + .cmd_func_offset = -1, | |
97 | + .keyword_function = ðsw_learn_help_key_func, | |
98 | + }, { | |
99 | + .cmd_keyword = { | |
100 | + ethsw_id_learning, | |
101 | + ethsw_id_help, | |
102 | + ethsw_id_key_end, | |
103 | + }, | |
104 | + .cmd_func_offset = -1, | |
105 | + .keyword_function = ðsw_learn_help_key_func, | |
106 | + }, { | |
107 | + .cmd_keyword = { | |
108 | + ethsw_id_learning, | |
109 | + ethsw_id_show, | |
110 | + ethsw_id_key_end, | |
111 | + }, | |
112 | + .cmd_func_offset = offsetof(struct ethsw_command_func, | |
113 | + port_learn_show), | |
114 | + .keyword_function = NULL, | |
115 | + }, { | |
116 | + .cmd_keyword = { | |
117 | + ethsw_id_learning, | |
118 | + ethsw_id_auto, | |
119 | + ethsw_id_key_end, | |
120 | + }, | |
121 | + .cmd_func_offset = offsetof(struct ethsw_command_func, | |
122 | + port_learn), | |
123 | + .keyword_function = NULL, | |
124 | + }, { | |
125 | + .cmd_keyword = { | |
126 | + ethsw_id_learning, | |
127 | + ethsw_id_disable, | |
128 | + ethsw_id_key_end, | |
129 | + }, | |
130 | + .cmd_func_offset = offsetof(struct ethsw_command_func, | |
131 | + port_learn), | |
132 | + .keyword_function = NULL, | |
80 | 133 | }, |
81 | 134 | }; |
82 | 135 | |
... | ... | @@ -129,6 +182,12 @@ |
129 | 182 | }, { |
130 | 183 | .keyword_name = "clear", |
131 | 184 | .match = &keyword_match_gen, |
185 | + }, { | |
186 | + .keyword_name = "learning", | |
187 | + .match = &keyword_match_gen, | |
188 | + }, { | |
189 | + .keyword_name = "auto", | |
190 | + .match = &keyword_match_gen, | |
132 | 191 | }, |
133 | 192 | }; |
134 | 193 | |
... | ... | @@ -386,5 +445,6 @@ |
386 | 445 | "Ethernet l2 switch commands", |
387 | 446 | ETHSW_PORT_CONF_HELP"\n" |
388 | 447 | ETHSW_PORT_STATS_HELP"\n" |
448 | + ETHSW_LEARN_HELP"\n" | |
389 | 449 | ); |
drivers/net/vsc9953.c
... | ... | @@ -717,6 +717,72 @@ |
717 | 717 | VSC9953_STAT_CLEAR_DR); |
718 | 718 | } |
719 | 719 | |
720 | +enum port_learn_mode { | |
721 | + PORT_LEARN_NONE, | |
722 | + PORT_LEARN_AUTO | |
723 | +}; | |
724 | + | |
725 | +/* Set learning configuration for a VSC9953 port */ | |
726 | +static void vsc9953_port_learn_mode_set(int port_no, enum port_learn_mode mode) | |
727 | +{ | |
728 | + struct vsc9953_analyzer *l2ana_reg; | |
729 | + | |
730 | + /* Administrative down */ | |
731 | + if (!vsc9953_l2sw.port[port_no].enabled) { | |
732 | + printf("Port %d is administrative down\n", port_no); | |
733 | + return; | |
734 | + } | |
735 | + | |
736 | + l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET + | |
737 | + VSC9953_ANA_OFFSET); | |
738 | + | |
739 | + switch (mode) { | |
740 | + case PORT_LEARN_NONE: | |
741 | + clrbits_le32(&l2ana_reg->port[port_no].port_cfg, | |
742 | + VSC9953_PORT_CFG_LEARN_DROP | | |
743 | + VSC9953_PORT_CFG_LEARN_CPU | | |
744 | + VSC9953_PORT_CFG_LEARN_AUTO | | |
745 | + VSC9953_PORT_CFG_LEARN_ENA); | |
746 | + break; | |
747 | + case PORT_LEARN_AUTO: | |
748 | + clrsetbits_le32(&l2ana_reg->port[port_no].port_cfg, | |
749 | + VSC9953_PORT_CFG_LEARN_DROP | | |
750 | + VSC9953_PORT_CFG_LEARN_CPU, | |
751 | + VSC9953_PORT_CFG_LEARN_ENA | | |
752 | + VSC9953_PORT_CFG_LEARN_AUTO); | |
753 | + break; | |
754 | + default: | |
755 | + printf("Unknown learn mode for port %d\n", port_no); | |
756 | + } | |
757 | +} | |
758 | + | |
759 | +/* Get learning configuration for a VSC9953 port */ | |
760 | +static int vsc9953_port_learn_mode_get(int port_no, enum port_learn_mode *mode) | |
761 | +{ | |
762 | + u32 val; | |
763 | + struct vsc9953_analyzer *l2ana_reg; | |
764 | + | |
765 | + /* Administrative down */ | |
766 | + if (!vsc9953_l2sw.port[port_no].enabled) { | |
767 | + printf("Port %d is administrative down\n", port_no); | |
768 | + return -1; | |
769 | + } | |
770 | + | |
771 | + l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET + | |
772 | + VSC9953_ANA_OFFSET); | |
773 | + | |
774 | + /* For now we only support HW learning (auto) and no learning */ | |
775 | + val = in_le32(&l2ana_reg->port[port_no].port_cfg); | |
776 | + if ((val & (VSC9953_PORT_CFG_LEARN_ENA | | |
777 | + VSC9953_PORT_CFG_LEARN_AUTO)) == | |
778 | + (VSC9953_PORT_CFG_LEARN_ENA | VSC9953_PORT_CFG_LEARN_AUTO)) | |
779 | + *mode = PORT_LEARN_AUTO; | |
780 | + else | |
781 | + *mode = PORT_LEARN_NONE; | |
782 | + | |
783 | + return 0; | |
784 | +} | |
785 | + | |
720 | 786 | static int vsc9953_port_status_key_func(struct ethsw_command_def *parsed_cmd) |
721 | 787 | { |
722 | 788 | int i; |
... | ... | @@ -810,6 +876,79 @@ |
810 | 876 | return CMD_RET_SUCCESS; |
811 | 877 | } |
812 | 878 | |
879 | +static int vsc9953_learn_show_key_func(struct ethsw_command_def *parsed_cmd) | |
880 | +{ | |
881 | + int i; | |
882 | + enum port_learn_mode mode; | |
883 | + | |
884 | + if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) { | |
885 | + if (!VSC9953_PORT_CHECK(parsed_cmd->port)) { | |
886 | + printf("Invalid port number: %d\n", parsed_cmd->port); | |
887 | + return CMD_RET_FAILURE; | |
888 | + } | |
889 | + if (vsc9953_port_learn_mode_get(parsed_cmd->port, &mode)) | |
890 | + return CMD_RET_FAILURE; | |
891 | + printf("%7s %11s\n", "Port", "Learn mode"); | |
892 | + switch (mode) { | |
893 | + case PORT_LEARN_NONE: | |
894 | + printf("%7d %11s\n", parsed_cmd->port, "disable"); | |
895 | + break; | |
896 | + case PORT_LEARN_AUTO: | |
897 | + printf("%7d %11s\n", parsed_cmd->port, "auto"); | |
898 | + break; | |
899 | + default: | |
900 | + printf("%7d %11s\n", parsed_cmd->port, "-"); | |
901 | + } | |
902 | + } else { | |
903 | + printf("%7s %11s\n", "Port", "Learn mode"); | |
904 | + for (i = 0; i < VSC9953_MAX_PORTS; i++) { | |
905 | + if (vsc9953_port_learn_mode_get(i, &mode)) | |
906 | + continue; | |
907 | + switch (mode) { | |
908 | + case PORT_LEARN_NONE: | |
909 | + printf("%7d %11s\n", i, "disable"); | |
910 | + break; | |
911 | + case PORT_LEARN_AUTO: | |
912 | + printf("%7d %11s\n", i, "auto"); | |
913 | + break; | |
914 | + default: | |
915 | + printf("%7d %11s\n", i, "-"); | |
916 | + } | |
917 | + } | |
918 | + } | |
919 | + | |
920 | + return CMD_RET_SUCCESS; | |
921 | +} | |
922 | + | |
923 | +static int vsc9953_learn_set_key_func(struct ethsw_command_def *parsed_cmd) | |
924 | +{ | |
925 | + int i; | |
926 | + enum port_learn_mode mode; | |
927 | + | |
928 | + /* Last keyword should tell us the learn mode */ | |
929 | + if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] == | |
930 | + ethsw_id_auto) | |
931 | + mode = PORT_LEARN_AUTO; | |
932 | + else if (parsed_cmd->cmd_to_keywords[parsed_cmd->cmd_keywords_nr - 1] == | |
933 | + ethsw_id_disable) | |
934 | + mode = PORT_LEARN_NONE; | |
935 | + else | |
936 | + return CMD_RET_USAGE; | |
937 | + | |
938 | + if (parsed_cmd->port != ETHSW_CMD_PORT_ALL) { | |
939 | + if (!VSC9953_PORT_CHECK(parsed_cmd->port)) { | |
940 | + printf("Invalid port number: %d\n", parsed_cmd->port); | |
941 | + return CMD_RET_FAILURE; | |
942 | + } | |
943 | + vsc9953_port_learn_mode_set(parsed_cmd->port, mode); | |
944 | + } else { | |
945 | + for (i = 0; i < VSC9953_MAX_PORTS; i++) | |
946 | + vsc9953_port_learn_mode_set(i, mode); | |
947 | + } | |
948 | + | |
949 | + return CMD_RET_SUCCESS; | |
950 | +} | |
951 | + | |
813 | 952 | static struct ethsw_command_func vsc9953_cmd_func = { |
814 | 953 | .ethsw_name = "L2 Switch VSC9953", |
815 | 954 | .port_enable = &vsc9953_port_status_key_func, |
... | ... | @@ -817,6 +956,8 @@ |
817 | 956 | .port_show = &vsc9953_port_config_key_func, |
818 | 957 | .port_stats = &vsc9953_port_stats_key_func, |
819 | 958 | .port_stats_clear = &vsc9953_port_stats_clear_key_func, |
959 | + .port_learn = &vsc9953_learn_set_key_func, | |
960 | + .port_learn_show = &vsc9953_learn_show_key_func, | |
820 | 961 | }; |
821 | 962 | |
822 | 963 | #endif /* CONFIG_CMD_ETHSW */ |
include/ethsw.h
... | ... | @@ -22,6 +22,8 @@ |
22 | 22 | ethsw_id_disable, |
23 | 23 | ethsw_id_statistics, |
24 | 24 | ethsw_id_clear, |
25 | + ethsw_id_learning, | |
26 | + ethsw_id_auto, | |
25 | 27 | ethsw_id_count, /* keep last */ |
26 | 28 | }; |
27 | 29 | |
... | ... | @@ -45,6 +47,8 @@ |
45 | 47 | int (*port_show)(struct ethsw_command_def *parsed_cmd); |
46 | 48 | int (*port_stats)(struct ethsw_command_def *parsed_cmd); |
47 | 49 | int (*port_stats_clear)(struct ethsw_command_def *parsed_cmd); |
50 | + int (*port_learn)(struct ethsw_command_def *parsed_cmd); | |
51 | + int (*port_learn_show)(struct ethsw_command_def *parsed_cmd); | |
48 | 52 | }; |
49 | 53 | |
50 | 54 | int ethsw_define_functions(const struct ethsw_command_func *cmd_func); |
include/vsc9953.h
... | ... | @@ -105,6 +105,12 @@ |
105 | 105 | #define VSC9953_VLAN_CMD_WRITE 0x00000002 |
106 | 106 | #define VSC9953_VLAN_CMD_INIT 0x00000003 |
107 | 107 | |
108 | +/* Macros for vsc9953_ana_port.port_cfg register */ | |
109 | +#define VSC9953_PORT_CFG_LEARN_ENA 0x00000080 | |
110 | +#define VSC9953_PORT_CFG_LEARN_AUTO 0x00000100 | |
111 | +#define VSC9953_PORT_CFG_LEARN_CPU 0x00000200 | |
112 | +#define VSC9953_PORT_CFG_LEARN_DROP 0x00000400 | |
113 | + | |
108 | 114 | /* Macros for vsc9953_qsys_sys.switch_port_mode register */ |
109 | 115 | #define VSC9953_PORT_ENA 0x00002000 |
110 | 116 |