1919#include <linux/mii.h>
2020#include <linux/phy.h>
2121#include <linux/if_bridge.h>
22+ #include <linux/etherdevice.h>
2223
2324#include "lan9303.h"
2425
@@ -497,6 +498,37 @@ static int lan9303_detect_phy_setup(struct lan9303 *chip)
497498static const int alrport_2_portmap [] = {1 , 2 , 4 , 0 , 3 , 5 , 6 , 7 };
498499static const int portmap_2_alrport [] = {3 , 0 , 1 , 4 , 2 , 5 , 6 , 7 };
499500
501+ /* Return pointer to first free ALR cache entry, return NULL if none */
502+ static struct lan9303_alr_cache_entry *
503+ lan9303_alr_cache_find_free (struct lan9303 * chip )
504+ {
505+ int i ;
506+ struct lan9303_alr_cache_entry * entr = chip -> alr_cache ;
507+
508+ for (i = 0 ; i < LAN9303_NUM_ALR_RECORDS ; i ++ , entr ++ )
509+ if (entr -> port_map == 0 )
510+ return entr ;
511+
512+ return NULL ;
513+ }
514+
515+ /* Return pointer to ALR cache entry matching MAC address */
516+ static struct lan9303_alr_cache_entry *
517+ lan9303_alr_cache_find_mac (struct lan9303 * chip , const u8 * mac_addr )
518+ {
519+ int i ;
520+ struct lan9303_alr_cache_entry * entr = chip -> alr_cache ;
521+
522+ BUILD_BUG_ON_MSG (sizeof (struct lan9303_alr_cache_entry ) & 1 ,
523+ "ether_addr_equal require u16 alignment" );
524+
525+ for (i = 0 ; i < LAN9303_NUM_ALR_RECORDS ; i ++ , entr ++ )
526+ if (ether_addr_equal (entr -> mac_addr , mac_addr ))
527+ return entr ;
528+
529+ return NULL ;
530+ }
531+
500532/* Wait a while until mask & reg == value. Otherwise return timeout. */
501533static int lan9303_csr_reg_wait (struct lan9303 * chip , int regno ,
502534 int mask , char value )
@@ -609,6 +641,73 @@ static void alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
609641 dump_ctx -> cb (mac , 0 , is_static , dump_ctx -> data );
610642}
611643
644+ /* Set a static ALR entry. Delete entry if port_map is zero */
645+ static void lan9303_alr_set_entry (struct lan9303 * chip , const u8 * mac ,
646+ u8 port_map , bool stp_override )
647+ {
648+ u32 dat0 , dat1 , alr_port ;
649+
650+ dev_dbg (chip -> dev , "%s(%pM, %d)\n" , __func__ , mac , port_map );
651+ dat1 = LAN9303_ALR_DAT1_STATIC ;
652+ if (port_map )
653+ dat1 |= LAN9303_ALR_DAT1_VALID ;
654+ /* otherwise no ports: delete entry */
655+ if (stp_override )
656+ dat1 |= LAN9303_ALR_DAT1_AGE_OVERRID ;
657+
658+ alr_port = portmap_2_alrport [port_map & 7 ];
659+ dat1 &= ~LAN9303_ALR_DAT1_PORT_MASK ;
660+ dat1 |= alr_port << LAN9303_ALR_DAT1_PORT_BITOFFS ;
661+
662+ dat0 = 0 ;
663+ dat0 |= (mac [0 ] << 0 );
664+ dat0 |= (mac [1 ] << 8 );
665+ dat0 |= (mac [2 ] << 16 );
666+ dat0 |= (mac [3 ] << 24 );
667+
668+ dat1 |= (mac [4 ] << 0 );
669+ dat1 |= (mac [5 ] << 8 );
670+
671+ lan9303_alr_make_entry_raw (chip , dat0 , dat1 );
672+ }
673+
674+ /* Add port to static ALR entry, create new static entry if needed */
675+ static int lan9303_alr_add_port (struct lan9303 * chip , const u8 * mac , int port ,
676+ bool stp_override )
677+ {
678+ struct lan9303_alr_cache_entry * entr ;
679+
680+ entr = lan9303_alr_cache_find_mac (chip , mac );
681+ if (!entr ) { /*New entry */
682+ entr = lan9303_alr_cache_find_free (chip );
683+ if (!entr )
684+ return - ENOSPC ;
685+ ether_addr_copy (entr -> mac_addr , mac );
686+ }
687+ entr -> port_map |= BIT (port );
688+ entr -> stp_override = stp_override ;
689+ lan9303_alr_set_entry (chip , mac , entr -> port_map , stp_override );
690+
691+ return 0 ;
692+ }
693+
694+ /* Delete static port from ALR entry, delete entry if last port */
695+ static int lan9303_alr_del_port (struct lan9303 * chip , const u8 * mac , int port )
696+ {
697+ struct lan9303_alr_cache_entry * entr ;
698+
699+ entr = lan9303_alr_cache_find_mac (chip , mac );
700+ if (!entr )
701+ return 0 ; /* no static entry found */
702+
703+ entr -> port_map &= ~BIT (port );
704+ if (entr -> port_map == 0 ) /* zero means its free again */
705+ eth_zero_addr (& entr -> port_map );
706+ lan9303_alr_set_entry (chip , mac , entr -> port_map , entr -> stp_override );
707+
708+ return 0 ;
709+ }
710+
612711static int lan9303_disable_processing_port (struct lan9303 * chip ,
613712 unsigned int port )
614713{
@@ -1065,6 +1164,32 @@ static void lan9303_port_fast_age(struct dsa_switch *ds, int port)
10651164 lan9303_alr_loop (chip , alr_loop_cb_del_port_learned , & del_ctx );
10661165}
10671166
1167+ static int lan9303_port_fdb_add (struct dsa_switch * ds , int port ,
1168+ const unsigned char * addr , u16 vid )
1169+ {
1170+ struct lan9303 * chip = ds -> priv ;
1171+
1172+ dev_dbg (chip -> dev , "%s(%d, %pM, %d)\n" , __func__ , port , addr , vid );
1173+ if (vid )
1174+ return - EOPNOTSUPP ;
1175+
1176+ return lan9303_alr_add_port (chip , addr , port , false);
1177+ }
1178+
1179+ static int lan9303_port_fdb_del (struct dsa_switch * ds , int port ,
1180+ const unsigned char * addr , u16 vid )
1181+
1182+ {
1183+ struct lan9303 * chip = ds -> priv ;
1184+
1185+ dev_dbg (chip -> dev , "%s(%d, %pM, %d)\n" , __func__ , port , addr , vid );
1186+ if (vid )
1187+ return - EOPNOTSUPP ;
1188+ lan9303_alr_del_port (chip , addr , port );
1189+
1190+ return 0 ;
1191+ }
1192+
10681193static int lan9303_port_fdb_dump (struct dsa_switch * ds , int port ,
10691194 dsa_fdb_dump_cb_t * cb , void * data )
10701195{
@@ -1081,6 +1206,49 @@ static int lan9303_port_fdb_dump(struct dsa_switch *ds, int port,
10811206 return 0 ;
10821207}
10831208
1209+ static int lan9303_port_mdb_prepare (struct dsa_switch * ds , int port ,
1210+ const struct switchdev_obj_port_mdb * mdb ,
1211+ struct switchdev_trans * trans )
1212+ {
1213+ struct lan9303 * chip = ds -> priv ;
1214+
1215+ dev_dbg (chip -> dev , "%s(%d, %pM, %d)\n" , __func__ , port , mdb -> addr ,
1216+ mdb -> vid );
1217+ if (mdb -> vid )
1218+ return - EOPNOTSUPP ;
1219+ if (lan9303_alr_cache_find_mac (chip , mdb -> addr ))
1220+ return 0 ;
1221+ if (!lan9303_alr_cache_find_free (chip ))
1222+ return - ENOSPC ;
1223+
1224+ return 0 ;
1225+ }
1226+
1227+ static void lan9303_port_mdb_add (struct dsa_switch * ds , int port ,
1228+ const struct switchdev_obj_port_mdb * mdb ,
1229+ struct switchdev_trans * trans )
1230+ {
1231+ struct lan9303 * chip = ds -> priv ;
1232+
1233+ dev_dbg (chip -> dev , "%s(%d, %pM, %d)\n" , __func__ , port , mdb -> addr ,
1234+ mdb -> vid );
1235+ lan9303_alr_add_port (chip , mdb -> addr , port , false);
1236+ }
1237+
1238+ static int lan9303_port_mdb_del (struct dsa_switch * ds , int port ,
1239+ const struct switchdev_obj_port_mdb * mdb )
1240+ {
1241+ struct lan9303 * chip = ds -> priv ;
1242+
1243+ dev_dbg (chip -> dev , "%s(%d, %pM, %d)\n" , __func__ , port , mdb -> addr ,
1244+ mdb -> vid );
1245+ if (mdb -> vid )
1246+ return - EOPNOTSUPP ;
1247+ lan9303_alr_del_port (chip , mdb -> addr , port );
1248+
1249+ return 0 ;
1250+ }
1251+
10841252static const struct dsa_switch_ops lan9303_switch_ops = {
10851253 .get_tag_protocol = lan9303_get_tag_protocol ,
10861254 .setup = lan9303_setup ,
@@ -1096,7 +1264,12 @@ static const struct dsa_switch_ops lan9303_switch_ops = {
10961264 .port_bridge_leave = lan9303_port_bridge_leave ,
10971265 .port_stp_state_set = lan9303_port_stp_state_set ,
10981266 .port_fast_age = lan9303_port_fast_age ,
1267+ .port_fdb_add = lan9303_port_fdb_add ,
1268+ .port_fdb_del = lan9303_port_fdb_del ,
10991269 .port_fdb_dump = lan9303_port_fdb_dump ,
1270+ .port_mdb_prepare = lan9303_port_mdb_prepare ,
1271+ .port_mdb_add = lan9303_port_mdb_add ,
1272+ .port_mdb_del = lan9303_port_mdb_del ,
11001273};
11011274
11021275static int lan9303_register_switch (struct lan9303 * chip )
0 commit comments