117
117
#include <linux/phy.h>
118
118
#include <linux/clk.h>
119
119
#include <linux/bitrev.h>
120
+ #include <linux/crc32.h>
120
121
121
122
#include "xgbe.h"
122
123
#include "xgbe-common.h"
@@ -548,24 +549,16 @@ static int xgbe_set_all_multicast_mode(struct xgbe_prv_data *pdata,
548
549
return 0 ;
549
550
}
550
551
551
- static int xgbe_set_addn_mac_addrs (struct xgbe_prv_data * pdata ,
552
- unsigned int am_mode )
552
+ static void xgbe_set_mac_reg (struct xgbe_prv_data * pdata ,
553
+ struct netdev_hw_addr * ha , unsigned int * mac_reg )
553
554
{
554
- struct netdev_hw_addr * ha ;
555
- unsigned int mac_reg ;
556
555
unsigned int mac_addr_hi , mac_addr_lo ;
557
556
u8 * mac_addr ;
558
- unsigned int i ;
559
557
560
- XGMAC_IOWRITE_BITS (pdata , MAC_PFR , HUC , 0 );
561
- XGMAC_IOWRITE_BITS (pdata , MAC_PFR , HMC , 0 );
562
-
563
- i = 0 ;
564
- mac_reg = MAC_MACA1HR ;
558
+ mac_addr_lo = 0 ;
559
+ mac_addr_hi = 0 ;
565
560
566
- netdev_for_each_uc_addr (ha , pdata -> netdev ) {
567
- mac_addr_lo = 0 ;
568
- mac_addr_hi = 0 ;
561
+ if (ha ) {
569
562
mac_addr = (u8 * )& mac_addr_lo ;
570
563
mac_addr [0 ] = ha -> addr [0 ];
571
564
mac_addr [1 ] = ha -> addr [1 ];
@@ -575,54 +568,93 @@ static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata,
575
568
mac_addr [0 ] = ha -> addr [4 ];
576
569
mac_addr [1 ] = ha -> addr [5 ];
577
570
578
- DBGPR (" adding unicast address %pM at 0x%04x\n" ,
579
- ha -> addr , mac_reg );
571
+ DBGPR (" adding mac address %pM at 0x%04x\n" , ha -> addr ,
572
+ * mac_reg );
580
573
581
574
XGMAC_SET_BITS (mac_addr_hi , MAC_MACA1HR , AE , 1 );
575
+ }
582
576
583
- XGMAC_IOWRITE (pdata , mac_reg , mac_addr_hi );
584
- mac_reg += MAC_MACA_INC ;
585
- XGMAC_IOWRITE (pdata , mac_reg , mac_addr_lo );
586
- mac_reg += MAC_MACA_INC ;
577
+ XGMAC_IOWRITE (pdata , * mac_reg , mac_addr_hi );
578
+ * mac_reg += MAC_MACA_INC ;
579
+ XGMAC_IOWRITE (pdata , * mac_reg , mac_addr_lo );
580
+ * mac_reg += MAC_MACA_INC ;
581
+ }
587
582
588
- i ++ ;
589
- }
583
+ static void xgbe_set_mac_addn_addrs (struct xgbe_prv_data * pdata )
584
+ {
585
+ struct net_device * netdev = pdata -> netdev ;
586
+ struct netdev_hw_addr * ha ;
587
+ unsigned int mac_reg ;
588
+ unsigned int addn_macs ;
589
+
590
+ mac_reg = MAC_MACA1HR ;
591
+ addn_macs = pdata -> hw_feat .addn_mac ;
590
592
591
- if (!am_mode ) {
592
- netdev_for_each_mc_addr (ha , pdata -> netdev ) {
593
- mac_addr_lo = 0 ;
594
- mac_addr_hi = 0 ;
595
- mac_addr = (u8 * )& mac_addr_lo ;
596
- mac_addr [0 ] = ha -> addr [0 ];
597
- mac_addr [1 ] = ha -> addr [1 ];
598
- mac_addr [2 ] = ha -> addr [2 ];
599
- mac_addr [3 ] = ha -> addr [3 ];
600
- mac_addr = (u8 * )& mac_addr_hi ;
601
- mac_addr [0 ] = ha -> addr [4 ];
602
- mac_addr [1 ] = ha -> addr [5 ];
603
-
604
- DBGPR (" adding multicast address %pM at 0x%04x\n" ,
605
- ha -> addr , mac_reg );
606
-
607
- XGMAC_SET_BITS (mac_addr_hi , MAC_MACA1HR , AE , 1 );
608
-
609
- XGMAC_IOWRITE (pdata , mac_reg , mac_addr_hi );
610
- mac_reg += MAC_MACA_INC ;
611
- XGMAC_IOWRITE (pdata , mac_reg , mac_addr_lo );
612
- mac_reg += MAC_MACA_INC ;
613
-
614
- i ++ ;
593
+ if (netdev_uc_count (netdev ) > addn_macs ) {
594
+ xgbe_set_promiscuous_mode (pdata , 1 );
595
+ } else {
596
+ netdev_for_each_uc_addr (ha , netdev ) {
597
+ xgbe_set_mac_reg (pdata , ha , & mac_reg );
598
+ addn_macs -- ;
599
+ }
600
+
601
+ if (netdev_mc_count (netdev ) > addn_macs ) {
602
+ xgbe_set_all_multicast_mode (pdata , 1 );
603
+ } else {
604
+ netdev_for_each_mc_addr (ha , netdev ) {
605
+ xgbe_set_mac_reg (pdata , ha , & mac_reg );
606
+ addn_macs -- ;
607
+ }
615
608
}
616
609
}
617
610
618
611
/* Clear remaining additional MAC address entries */
619
- for (; i < pdata -> hw_feat .addn_mac ; i ++ ) {
620
- XGMAC_IOWRITE (pdata , mac_reg , 0 );
621
- mac_reg += MAC_MACA_INC ;
622
- XGMAC_IOWRITE (pdata , mac_reg , 0 );
623
- mac_reg += MAC_MACA_INC ;
612
+ while (addn_macs -- )
613
+ xgbe_set_mac_reg (pdata , NULL , & mac_reg );
614
+ }
615
+
616
+ static void xgbe_set_mac_hash_table (struct xgbe_prv_data * pdata )
617
+ {
618
+ struct net_device * netdev = pdata -> netdev ;
619
+ struct netdev_hw_addr * ha ;
620
+ unsigned int hash_reg ;
621
+ unsigned int hash_table_shift , hash_table_count ;
622
+ u32 hash_table [XGBE_MAC_HASH_TABLE_SIZE ];
623
+ u32 crc ;
624
+ unsigned int i ;
625
+
626
+ hash_table_shift = 26 - (pdata -> hw_feat .hash_table_size >> 7 );
627
+ hash_table_count = pdata -> hw_feat .hash_table_size / 32 ;
628
+ memset (hash_table , 0 , sizeof (hash_table ));
629
+
630
+ /* Build the MAC Hash Table register values */
631
+ netdev_for_each_uc_addr (ha , netdev ) {
632
+ crc = bitrev32 (~crc32_le (~0 , ha -> addr , ETH_ALEN ));
633
+ crc >>= hash_table_shift ;
634
+ hash_table [crc >> 5 ] |= (1 << (crc & 0x1f ));
635
+ }
636
+
637
+ netdev_for_each_mc_addr (ha , netdev ) {
638
+ crc = bitrev32 (~crc32_le (~0 , ha -> addr , ETH_ALEN ));
639
+ crc >>= hash_table_shift ;
640
+ hash_table [crc >> 5 ] |= (1 << (crc & 0x1f ));
624
641
}
625
642
643
+ /* Set the MAC Hash Table registers */
644
+ hash_reg = MAC_HTR0 ;
645
+ for (i = 0 ; i < hash_table_count ; i ++ ) {
646
+ XGMAC_IOWRITE (pdata , hash_reg , hash_table [i ]);
647
+ hash_reg += MAC_HTR_INC ;
648
+ }
649
+ }
650
+
651
+ static int xgbe_add_mac_addresses (struct xgbe_prv_data * pdata )
652
+ {
653
+ if (pdata -> hw_feat .hash_table_size )
654
+ xgbe_set_mac_hash_table (pdata );
655
+ else
656
+ xgbe_set_mac_addn_addrs (pdata );
657
+
626
658
return 0 ;
627
659
}
628
660
@@ -1606,6 +1638,13 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
1606
1638
static void xgbe_config_mac_address (struct xgbe_prv_data * pdata )
1607
1639
{
1608
1640
xgbe_set_mac_address (pdata , pdata -> netdev -> dev_addr );
1641
+
1642
+ /* Filtering is done using perfect filtering and hash filtering */
1643
+ if (pdata -> hw_feat .hash_table_size ) {
1644
+ XGMAC_IOWRITE_BITS (pdata , MAC_PFR , HPF , 1 );
1645
+ XGMAC_IOWRITE_BITS (pdata , MAC_PFR , HUC , 1 );
1646
+ XGMAC_IOWRITE_BITS (pdata , MAC_PFR , HMC , 1 );
1647
+ }
1609
1648
}
1610
1649
1611
1650
static void xgbe_config_jumbo_enable (struct xgbe_prv_data * pdata )
@@ -2202,7 +2241,7 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
2202
2241
2203
2242
hw_if -> set_promiscuous_mode = xgbe_set_promiscuous_mode ;
2204
2243
hw_if -> set_all_multicast_mode = xgbe_set_all_multicast_mode ;
2205
- hw_if -> set_addn_mac_addrs = xgbe_set_addn_mac_addrs ;
2244
+ hw_if -> add_mac_addresses = xgbe_add_mac_addresses ;
2206
2245
hw_if -> set_mac_address = xgbe_set_mac_address ;
2207
2246
2208
2247
hw_if -> enable_rx_csum = xgbe_enable_rx_csum ;
0 commit comments