26
26
#include <linux/module.h>
27
27
#include <linux/platform_data/b53.h>
28
28
#include <linux/phy.h>
29
+ #include <linux/etherdevice.h>
29
30
#include <net/dsa.h>
31
+ #include <net/switchdev.h>
30
32
31
33
#include "b53_regs.h"
32
34
#include "b53_priv.h"
@@ -777,6 +779,246 @@ static void b53_adjust_link(struct dsa_switch *ds, int port,
777
779
}
778
780
}
779
781
782
+ /* Address Resolution Logic routines */
783
+ static int b53_arl_op_wait (struct b53_device * dev )
784
+ {
785
+ unsigned int timeout = 10 ;
786
+ u8 reg ;
787
+
788
+ do {
789
+ b53_read8 (dev , B53_ARLIO_PAGE , B53_ARLTBL_RW_CTRL , & reg );
790
+ if (!(reg & ARLTBL_START_DONE ))
791
+ return 0 ;
792
+
793
+ usleep_range (1000 , 2000 );
794
+ } while (timeout -- );
795
+
796
+ dev_warn (dev -> dev , "timeout waiting for ARL to finish: 0x%02x\n" , reg );
797
+
798
+ return - ETIMEDOUT ;
799
+ }
800
+
801
+ static int b53_arl_rw_op (struct b53_device * dev , unsigned int op )
802
+ {
803
+ u8 reg ;
804
+
805
+ if (op > ARLTBL_RW )
806
+ return - EINVAL ;
807
+
808
+ b53_read8 (dev , B53_ARLIO_PAGE , B53_ARLTBL_RW_CTRL , & reg );
809
+ reg |= ARLTBL_START_DONE ;
810
+ if (op )
811
+ reg |= ARLTBL_RW ;
812
+ else
813
+ reg &= ~ARLTBL_RW ;
814
+ b53_write8 (dev , B53_ARLIO_PAGE , B53_ARLTBL_RW_CTRL , reg );
815
+
816
+ return b53_arl_op_wait (dev );
817
+ }
818
+
819
+ static int b53_arl_read (struct b53_device * dev , u64 mac ,
820
+ u16 vid , struct b53_arl_entry * ent , u8 * idx ,
821
+ bool is_valid )
822
+ {
823
+ unsigned int i ;
824
+ int ret ;
825
+
826
+ ret = b53_arl_op_wait (dev );
827
+ if (ret )
828
+ return ret ;
829
+
830
+ /* Read the bins */
831
+ for (i = 0 ; i < dev -> num_arl_entries ; i ++ ) {
832
+ u64 mac_vid ;
833
+ u32 fwd_entry ;
834
+
835
+ b53_read64 (dev , B53_ARLIO_PAGE ,
836
+ B53_ARLTBL_MAC_VID_ENTRY (i ), & mac_vid );
837
+ b53_read32 (dev , B53_ARLIO_PAGE ,
838
+ B53_ARLTBL_DATA_ENTRY (i ), & fwd_entry );
839
+ b53_arl_to_entry (ent , mac_vid , fwd_entry );
840
+
841
+ if (!(fwd_entry & ARLTBL_VALID ))
842
+ continue ;
843
+ if ((mac_vid & ARLTBL_MAC_MASK ) != mac )
844
+ continue ;
845
+ * idx = i ;
846
+ }
847
+
848
+ return - ENOENT ;
849
+ }
850
+
851
+ static int b53_arl_op (struct b53_device * dev , int op , int port ,
852
+ const unsigned char * addr , u16 vid , bool is_valid )
853
+ {
854
+ struct b53_arl_entry ent ;
855
+ u32 fwd_entry ;
856
+ u64 mac , mac_vid = 0 ;
857
+ u8 idx = 0 ;
858
+ int ret ;
859
+
860
+ /* Convert the array into a 64-bit MAC */
861
+ mac = b53_mac_to_u64 (addr );
862
+
863
+ /* Perform a read for the given MAC and VID */
864
+ b53_write48 (dev , B53_ARLIO_PAGE , B53_MAC_ADDR_IDX , mac );
865
+ b53_write16 (dev , B53_ARLIO_PAGE , B53_VLAN_ID_IDX , vid );
866
+
867
+ /* Issue a read operation for this MAC */
868
+ ret = b53_arl_rw_op (dev , 1 );
869
+ if (ret )
870
+ return ret ;
871
+
872
+ ret = b53_arl_read (dev , mac , vid , & ent , & idx , is_valid );
873
+ /* If this is a read, just finish now */
874
+ if (op )
875
+ return ret ;
876
+
877
+ /* We could not find a matching MAC, so reset to a new entry */
878
+ if (ret ) {
879
+ fwd_entry = 0 ;
880
+ idx = 1 ;
881
+ }
882
+
883
+ memset (& ent , 0 , sizeof (ent ));
884
+ ent .port = port ;
885
+ ent .is_valid = is_valid ;
886
+ ent .vid = vid ;
887
+ ent .is_static = true;
888
+ memcpy (ent .mac , addr , ETH_ALEN );
889
+ b53_arl_from_entry (& mac_vid , & fwd_entry , & ent );
890
+
891
+ b53_write64 (dev , B53_ARLIO_PAGE ,
892
+ B53_ARLTBL_MAC_VID_ENTRY (idx ), mac_vid );
893
+ b53_write32 (dev , B53_ARLIO_PAGE ,
894
+ B53_ARLTBL_DATA_ENTRY (idx ), fwd_entry );
895
+
896
+ return b53_arl_rw_op (dev , 0 );
897
+ }
898
+
899
+ static int b53_fdb_prepare (struct dsa_switch * ds , int port ,
900
+ const struct switchdev_obj_port_fdb * fdb ,
901
+ struct switchdev_trans * trans )
902
+ {
903
+ struct b53_device * priv = ds_to_priv (ds );
904
+
905
+ /* 5325 and 5365 require some more massaging, but could
906
+ * be supported eventually
907
+ */
908
+ if (is5325 (priv ) || is5365 (priv ))
909
+ return - EOPNOTSUPP ;
910
+
911
+ return 0 ;
912
+ }
913
+
914
+ static void b53_fdb_add (struct dsa_switch * ds , int port ,
915
+ const struct switchdev_obj_port_fdb * fdb ,
916
+ struct switchdev_trans * trans )
917
+ {
918
+ struct b53_device * priv = ds_to_priv (ds );
919
+
920
+ if (b53_arl_op (priv , 0 , port , fdb -> addr , fdb -> vid , true))
921
+ pr_err ("%s: failed to add MAC address\n" , __func__ );
922
+ }
923
+
924
+ static int b53_fdb_del (struct dsa_switch * ds , int port ,
925
+ const struct switchdev_obj_port_fdb * fdb )
926
+ {
927
+ struct b53_device * priv = ds_to_priv (ds );
928
+
929
+ return b53_arl_op (priv , 0 , port , fdb -> addr , fdb -> vid , false);
930
+ }
931
+
932
+ static int b53_arl_search_wait (struct b53_device * dev )
933
+ {
934
+ unsigned int timeout = 1000 ;
935
+ u8 reg ;
936
+
937
+ do {
938
+ b53_read8 (dev , B53_ARLIO_PAGE , B53_ARL_SRCH_CTL , & reg );
939
+ if (!(reg & ARL_SRCH_STDN ))
940
+ return 0 ;
941
+
942
+ if (reg & ARL_SRCH_VLID )
943
+ return 0 ;
944
+
945
+ usleep_range (1000 , 2000 );
946
+ } while (timeout -- );
947
+
948
+ return - ETIMEDOUT ;
949
+ }
950
+
951
+ static void b53_arl_search_rd (struct b53_device * dev , u8 idx ,
952
+ struct b53_arl_entry * ent )
953
+ {
954
+ u64 mac_vid ;
955
+ u32 fwd_entry ;
956
+
957
+ b53_read64 (dev , B53_ARLIO_PAGE ,
958
+ B53_ARL_SRCH_RSTL_MACVID (idx ), & mac_vid );
959
+ b53_read32 (dev , B53_ARLIO_PAGE ,
960
+ B53_ARL_SRCH_RSTL (idx ), & fwd_entry );
961
+ b53_arl_to_entry (ent , mac_vid , fwd_entry );
962
+ }
963
+
964
+ static int b53_fdb_copy (struct net_device * dev , int port ,
965
+ const struct b53_arl_entry * ent ,
966
+ struct switchdev_obj_port_fdb * fdb ,
967
+ int (* cb )(struct switchdev_obj * obj ))
968
+ {
969
+ if (!ent -> is_valid )
970
+ return 0 ;
971
+
972
+ if (port != ent -> port )
973
+ return 0 ;
974
+
975
+ ether_addr_copy (fdb -> addr , ent -> mac );
976
+ fdb -> vid = ent -> vid ;
977
+ fdb -> ndm_state = ent -> is_static ? NUD_NOARP : NUD_REACHABLE ;
978
+
979
+ return cb (& fdb -> obj );
980
+ }
981
+
982
+ static int b53_fdb_dump (struct dsa_switch * ds , int port ,
983
+ struct switchdev_obj_port_fdb * fdb ,
984
+ int (* cb )(struct switchdev_obj * obj ))
985
+ {
986
+ struct b53_device * priv = ds_to_priv (ds );
987
+ struct net_device * dev = ds -> ports [port ].netdev ;
988
+ struct b53_arl_entry results [2 ];
989
+ unsigned int count = 0 ;
990
+ int ret ;
991
+ u8 reg ;
992
+
993
+ /* Start search operation */
994
+ reg = ARL_SRCH_STDN ;
995
+ b53_write8 (priv , B53_ARLIO_PAGE , B53_ARL_SRCH_CTL , reg );
996
+
997
+ do {
998
+ ret = b53_arl_search_wait (priv );
999
+ if (ret )
1000
+ return ret ;
1001
+
1002
+ b53_arl_search_rd (priv , 0 , & results [0 ]);
1003
+ ret = b53_fdb_copy (dev , port , & results [0 ], fdb , cb );
1004
+ if (ret )
1005
+ return ret ;
1006
+
1007
+ if (priv -> num_arl_entries > 2 ) {
1008
+ b53_arl_search_rd (priv , 1 , & results [1 ]);
1009
+ ret = b53_fdb_copy (dev , port , & results [1 ], fdb , cb );
1010
+ if (ret )
1011
+ return ret ;
1012
+
1013
+ if (!results [0 ].is_valid && !results [1 ].is_valid )
1014
+ break ;
1015
+ }
1016
+
1017
+ } while (count ++ < 1024 );
1018
+
1019
+ return 0 ;
1020
+ }
1021
+
780
1022
static struct dsa_switch_driver b53_switch_ops = {
781
1023
.tag_protocol = DSA_TAG_PROTO_NONE ,
782
1024
.setup = b53_setup ,
@@ -789,6 +1031,10 @@ static struct dsa_switch_driver b53_switch_ops = {
789
1031
.adjust_link = b53_adjust_link ,
790
1032
.port_enable = b53_enable_port ,
791
1033
.port_disable = b53_disable_port ,
1034
+ .port_fdb_prepare = b53_fdb_prepare ,
1035
+ .port_fdb_dump = b53_fdb_dump ,
1036
+ .port_fdb_add = b53_fdb_add ,
1037
+ .port_fdb_del = b53_fdb_del ,
792
1038
};
793
1039
794
1040
struct b53_chip_data {
@@ -798,6 +1044,7 @@ struct b53_chip_data {
798
1044
u16 enabled_ports ;
799
1045
u8 cpu_port ;
800
1046
u8 vta_regs [3 ];
1047
+ u8 arl_entries ;
801
1048
u8 duplex_reg ;
802
1049
u8 jumbo_pm_reg ;
803
1050
u8 jumbo_size_reg ;
@@ -816,6 +1063,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
816
1063
.dev_name = "BCM5325" ,
817
1064
.vlans = 16 ,
818
1065
.enabled_ports = 0x1f ,
1066
+ .arl_entries = 2 ,
819
1067
.cpu_port = B53_CPU_PORT_25 ,
820
1068
.duplex_reg = B53_DUPLEX_STAT_FE ,
821
1069
},
@@ -824,6 +1072,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
824
1072
.dev_name = "BCM5365" ,
825
1073
.vlans = 256 ,
826
1074
.enabled_ports = 0x1f ,
1075
+ .arl_entries = 2 ,
827
1076
.cpu_port = B53_CPU_PORT_25 ,
828
1077
.duplex_reg = B53_DUPLEX_STAT_FE ,
829
1078
},
@@ -832,6 +1081,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
832
1081
.dev_name = "BCM5395" ,
833
1082
.vlans = 4096 ,
834
1083
.enabled_ports = 0x1f ,
1084
+ .arl_entries = 4 ,
835
1085
.cpu_port = B53_CPU_PORT ,
836
1086
.vta_regs = B53_VTA_REGS ,
837
1087
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -843,6 +1093,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
843
1093
.dev_name = "BCM5397" ,
844
1094
.vlans = 4096 ,
845
1095
.enabled_ports = 0x1f ,
1096
+ .arl_entries = 4 ,
846
1097
.cpu_port = B53_CPU_PORT ,
847
1098
.vta_regs = B53_VTA_REGS_9798 ,
848
1099
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -854,6 +1105,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
854
1105
.dev_name = "BCM5398" ,
855
1106
.vlans = 4096 ,
856
1107
.enabled_ports = 0x7f ,
1108
+ .arl_entries = 4 ,
857
1109
.cpu_port = B53_CPU_PORT ,
858
1110
.vta_regs = B53_VTA_REGS_9798 ,
859
1111
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -865,6 +1117,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
865
1117
.dev_name = "BCM53115" ,
866
1118
.vlans = 4096 ,
867
1119
.enabled_ports = 0x1f ,
1120
+ .arl_entries = 4 ,
868
1121
.vta_regs = B53_VTA_REGS ,
869
1122
.cpu_port = B53_CPU_PORT ,
870
1123
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -887,6 +1140,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
887
1140
.dev_name = "BCM53128" ,
888
1141
.vlans = 4096 ,
889
1142
.enabled_ports = 0x1ff ,
1143
+ .arl_entries = 4 ,
890
1144
.cpu_port = B53_CPU_PORT ,
891
1145
.vta_regs = B53_VTA_REGS ,
892
1146
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -898,6 +1152,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
898
1152
.dev_name = "BCM63xx" ,
899
1153
.vlans = 4096 ,
900
1154
.enabled_ports = 0 , /* pdata must provide them */
1155
+ .arl_entries = 4 ,
901
1156
.cpu_port = B53_CPU_PORT ,
902
1157
.vta_regs = B53_VTA_REGS_63XX ,
903
1158
.duplex_reg = B53_DUPLEX_STAT_63XX ,
@@ -909,6 +1164,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
909
1164
.dev_name = "BCM53010" ,
910
1165
.vlans = 4096 ,
911
1166
.enabled_ports = 0x1f ,
1167
+ .arl_entries = 4 ,
912
1168
.cpu_port = B53_CPU_PORT_25 , /* TODO: auto detect */
913
1169
.vta_regs = B53_VTA_REGS ,
914
1170
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -920,6 +1176,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
920
1176
.dev_name = "BCM53011" ,
921
1177
.vlans = 4096 ,
922
1178
.enabled_ports = 0x1bf ,
1179
+ .arl_entries = 4 ,
923
1180
.cpu_port = B53_CPU_PORT_25 , /* TODO: auto detect */
924
1181
.vta_regs = B53_VTA_REGS ,
925
1182
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -931,6 +1188,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
931
1188
.dev_name = "BCM53012" ,
932
1189
.vlans = 4096 ,
933
1190
.enabled_ports = 0x1bf ,
1191
+ .arl_entries = 4 ,
934
1192
.cpu_port = B53_CPU_PORT_25 , /* TODO: auto detect */
935
1193
.vta_regs = B53_VTA_REGS ,
936
1194
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -942,6 +1200,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
942
1200
.dev_name = "BCM53018" ,
943
1201
.vlans = 4096 ,
944
1202
.enabled_ports = 0x1f ,
1203
+ .arl_entries = 4 ,
945
1204
.cpu_port = B53_CPU_PORT_25 , /* TODO: auto detect */
946
1205
.vta_regs = B53_VTA_REGS ,
947
1206
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -953,6 +1212,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
953
1212
.dev_name = "BCM53019" ,
954
1213
.vlans = 4096 ,
955
1214
.enabled_ports = 0x1f ,
1215
+ .arl_entries = 4 ,
956
1216
.cpu_port = B53_CPU_PORT_25 , /* TODO: auto detect */
957
1217
.vta_regs = B53_VTA_REGS ,
958
1218
.duplex_reg = B53_DUPLEX_STAT_GE ,
@@ -982,6 +1242,7 @@ static int b53_switch_init(struct b53_device *dev)
982
1242
ds -> drv = & b53_switch_ops ;
983
1243
dev -> cpu_port = chip -> cpu_port ;
984
1244
dev -> num_vlans = chip -> vlans ;
1245
+ dev -> num_arl_entries = chip -> arl_entries ;
985
1246
break ;
986
1247
}
987
1248
}
0 commit comments