22/* Copyright (c) 2015 - 2022 Beijing WangXun Technology Co., Ltd. */
33
44#include <linux/etherdevice.h>
5+ #include <linux/netdevice.h>
56#include <linux/if_ether.h>
67#include <linux/iopoll.h>
78#include <linux/pci.h>
@@ -536,8 +537,8 @@ EXPORT_SYMBOL(wx_get_mac_addr);
536537 *
537538 * Puts an ethernet address into a receive address register.
538539 **/
539- int wx_set_rar (struct wx_hw * wxhw , u32 index , u8 * addr , u64 pools ,
540- u32 enable_addr )
540+ static int wx_set_rar (struct wx_hw * wxhw , u32 index , u8 * addr , u64 pools ,
541+ u32 enable_addr )
541542{
542543 u32 rar_entries = wxhw -> mac .num_rar_entries ;
543544 u32 rar_low , rar_high ;
@@ -581,7 +582,6 @@ int wx_set_rar(struct wx_hw *wxhw, u32 index, u8 *addr, u64 pools,
581582
582583 return 0 ;
583584}
584- EXPORT_SYMBOL (wx_set_rar );
585585
586586/**
587587 * wx_clear_rar - Remove Rx address register
@@ -590,7 +590,7 @@ EXPORT_SYMBOL(wx_set_rar);
590590 *
591591 * Clears an ethernet address from a receive address register.
592592 **/
593- int wx_clear_rar (struct wx_hw * wxhw , u32 index )
593+ static int wx_clear_rar (struct wx_hw * wxhw , u32 index )
594594{
595595 u32 rar_entries = wxhw -> mac .num_rar_entries ;
596596
@@ -618,7 +618,6 @@ int wx_clear_rar(struct wx_hw *wxhw, u32 index)
618618
619619 return 0 ;
620620}
621- EXPORT_SYMBOL (wx_clear_rar );
622621
623622/**
624623 * wx_clear_vmdq - Disassociate a VMDq pool index from a rx address
@@ -722,6 +721,105 @@ void wx_init_rx_addrs(struct wx_hw *wxhw)
722721}
723722EXPORT_SYMBOL (wx_init_rx_addrs );
724723
724+ static void wx_sync_mac_table (struct wx_hw * wxhw )
725+ {
726+ int i ;
727+
728+ for (i = 0 ; i < wxhw -> mac .num_rar_entries ; i ++ ) {
729+ if (wxhw -> mac_table [i ].state & WX_MAC_STATE_MODIFIED ) {
730+ if (wxhw -> mac_table [i ].state & WX_MAC_STATE_IN_USE ) {
731+ wx_set_rar (wxhw , i ,
732+ wxhw -> mac_table [i ].addr ,
733+ wxhw -> mac_table [i ].pools ,
734+ WX_PSR_MAC_SWC_AD_H_AV );
735+ } else {
736+ wx_clear_rar (wxhw , i );
737+ }
738+ wxhw -> mac_table [i ].state &= ~(WX_MAC_STATE_MODIFIED );
739+ }
740+ }
741+ }
742+
743+ /* this function destroys the first RAR entry */
744+ void wx_mac_set_default_filter (struct wx_hw * wxhw , u8 * addr )
745+ {
746+ memcpy (& wxhw -> mac_table [0 ].addr , addr , ETH_ALEN );
747+ wxhw -> mac_table [0 ].pools = 1ULL ;
748+ wxhw -> mac_table [0 ].state = (WX_MAC_STATE_DEFAULT | WX_MAC_STATE_IN_USE );
749+ wx_set_rar (wxhw , 0 , wxhw -> mac_table [0 ].addr ,
750+ wxhw -> mac_table [0 ].pools ,
751+ WX_PSR_MAC_SWC_AD_H_AV );
752+ }
753+ EXPORT_SYMBOL (wx_mac_set_default_filter );
754+
755+ void wx_flush_sw_mac_table (struct wx_hw * wxhw )
756+ {
757+ u32 i ;
758+
759+ for (i = 0 ; i < wxhw -> mac .num_rar_entries ; i ++ ) {
760+ if (!(wxhw -> mac_table [i ].state & WX_MAC_STATE_IN_USE ))
761+ continue ;
762+
763+ wxhw -> mac_table [i ].state |= WX_MAC_STATE_MODIFIED ;
764+ wxhw -> mac_table [i ].state &= ~WX_MAC_STATE_IN_USE ;
765+ memset (wxhw -> mac_table [i ].addr , 0 , ETH_ALEN );
766+ wxhw -> mac_table [i ].pools = 0 ;
767+ }
768+ wx_sync_mac_table (wxhw );
769+ }
770+ EXPORT_SYMBOL (wx_flush_sw_mac_table );
771+
772+ static int wx_del_mac_filter (struct wx_hw * wxhw , u8 * addr , u16 pool )
773+ {
774+ u32 i ;
775+
776+ if (is_zero_ether_addr (addr ))
777+ return - EINVAL ;
778+
779+ /* search table for addr, if found, set to 0 and sync */
780+ for (i = 0 ; i < wxhw -> mac .num_rar_entries ; i ++ ) {
781+ if (!ether_addr_equal (addr , wxhw -> mac_table [i ].addr ))
782+ continue ;
783+
784+ wxhw -> mac_table [i ].state |= WX_MAC_STATE_MODIFIED ;
785+ wxhw -> mac_table [i ].pools &= ~(1ULL << pool );
786+ if (!wxhw -> mac_table [i ].pools ) {
787+ wxhw -> mac_table [i ].state &= ~WX_MAC_STATE_IN_USE ;
788+ memset (wxhw -> mac_table [i ].addr , 0 , ETH_ALEN );
789+ }
790+ wx_sync_mac_table (wxhw );
791+ return 0 ;
792+ }
793+ return - ENOMEM ;
794+ }
795+
796+ /**
797+ * wx_set_mac - Change the Ethernet Address of the NIC
798+ * @netdev: network interface device structure
799+ * @p: pointer to an address structure
800+ *
801+ * Returns 0 on success, negative on failure
802+ **/
803+ int wx_set_mac (struct net_device * netdev , void * p )
804+ {
805+ struct wx_hw * wxhw = container_of (& netdev , struct wx_hw , netdev );
806+ struct sockaddr * addr = p ;
807+ int retval ;
808+
809+ retval = eth_prepare_mac_addr_change (netdev , addr );
810+ if (retval )
811+ return retval ;
812+
813+ wx_del_mac_filter (wxhw , wxhw -> mac .addr , 0 );
814+ eth_hw_addr_set (netdev , addr -> sa_data );
815+ memcpy (wxhw -> mac .addr , addr -> sa_data , netdev -> addr_len );
816+
817+ wx_mac_set_default_filter (wxhw , wxhw -> mac .addr );
818+
819+ return 0 ;
820+ }
821+ EXPORT_SYMBOL (wx_set_mac );
822+
725823void wx_disable_rx (struct wx_hw * wxhw )
726824{
727825 u32 pfdtxgswc ;
@@ -929,6 +1027,14 @@ int wx_sw_init(struct wx_hw *wxhw)
9291027 return err ;
9301028 }
9311029
1030+ wxhw -> mac_table = kcalloc (wxhw -> mac .num_rar_entries ,
1031+ sizeof (struct wx_mac_addr ),
1032+ GFP_KERNEL );
1033+ if (!wxhw -> mac_table ) {
1034+ wx_err (wxhw , "mac_table allocation failed\n" );
1035+ return - ENOMEM ;
1036+ }
1037+
9321038 return 0 ;
9331039}
9341040EXPORT_SYMBOL (wx_sw_init );
0 commit comments