Skip to content

Commit b85e4d8

Browse files
tlendackydavem330
authored andcommitted
amd-xgbe: Change destination address filtering support
Currently the driver makes use of the additional mac address registers in the hardware to provide perfect filtering. The hardware can also have a set of hash table registers that can be used for imperfect filtering. By using imperfect filtering the additional mac address registers can be used for layer 2 filtering support. Use the hash table registers if the device has them. Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 801c62d commit b85e4d8

File tree

6 files changed

+116
-69
lines changed

6 files changed

+116
-69
lines changed

drivers/net/ethernet/amd/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ config AMD_XGBE
183183
select PHYLIB
184184
select AMD_XGBE_PHY
185185
select BITREVERSE
186+
select CRC32
186187
---help---
187188
This driver supports the AMD 10GbE Ethernet device found on an
188189
AMD SoC.

drivers/net/ethernet/amd/xgbe/xgbe-common.h

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,6 @@
276276
#define MAC_PFR 0x0008
277277
#define MAC_WTR 0x000c
278278
#define MAC_HTR0 0x0010
279-
#define MAC_HTR1 0x0014
280-
#define MAC_HTR2 0x0018
281-
#define MAC_HTR3 0x001c
282-
#define MAC_HTR4 0x0020
283-
#define MAC_HTR5 0x0024
284-
#define MAC_HTR6 0x0028
285-
#define MAC_HTR7 0x002c
286279
#define MAC_VLANTR 0x0050
287280
#define MAC_VLANHTR 0x0058
288281
#define MAC_VLANIR 0x0060
@@ -315,6 +308,7 @@
315308

316309
#define MAC_QTFCR_INC 4
317310
#define MAC_MACA_INC 4
311+
#define MAC_HTR_INC 4
318312

319313
/* MAC register entry bit positions and sizes */
320314
#define MAC_HWF0R_ADDMACADRSEL_INDEX 18
@@ -387,6 +381,8 @@
387381
#define MAC_MACA1HR_AE_WIDTH 1
388382
#define MAC_PFR_HMC_INDEX 2
389383
#define MAC_PFR_HMC_WIDTH 1
384+
#define MAC_PFR_HPF_INDEX 10
385+
#define MAC_PFR_HPF_WIDTH 1
390386
#define MAC_PFR_HUC_INDEX 1
391387
#define MAC_PFR_HUC_WIDTH 1
392388
#define MAC_PFR_PM_INDEX 4

drivers/net/ethernet/amd/xgbe/xgbe-dev.c

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@
117117
#include <linux/phy.h>
118118
#include <linux/clk.h>
119119
#include <linux/bitrev.h>
120+
#include <linux/crc32.h>
120121

121122
#include "xgbe.h"
122123
#include "xgbe-common.h"
@@ -548,24 +549,16 @@ static int xgbe_set_all_multicast_mode(struct xgbe_prv_data *pdata,
548549
return 0;
549550
}
550551

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)
553554
{
554-
struct netdev_hw_addr *ha;
555-
unsigned int mac_reg;
556555
unsigned int mac_addr_hi, mac_addr_lo;
557556
u8 *mac_addr;
558-
unsigned int i;
559557

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;
565560

566-
netdev_for_each_uc_addr(ha, pdata->netdev) {
567-
mac_addr_lo = 0;
568-
mac_addr_hi = 0;
561+
if (ha) {
569562
mac_addr = (u8 *)&mac_addr_lo;
570563
mac_addr[0] = ha->addr[0];
571564
mac_addr[1] = ha->addr[1];
@@ -575,54 +568,93 @@ static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata,
575568
mac_addr[0] = ha->addr[4];
576569
mac_addr[1] = ha->addr[5];
577570

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);
580573

581574
XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1);
575+
}
582576

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+
}
587582

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;
590592

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+
}
615608
}
616609
}
617610

618611
/* 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));
624641
}
625642

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+
626658
return 0;
627659
}
628660

@@ -1606,6 +1638,13 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
16061638
static void xgbe_config_mac_address(struct xgbe_prv_data *pdata)
16071639
{
16081640
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+
}
16091648
}
16101649

16111650
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)
22022241

22032242
hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode;
22042243
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;
22062245
hw_if->set_mac_address = xgbe_set_mac_address;
22072246

22082247
hw_if->enable_rx_csum = xgbe_enable_rx_csum;

drivers/net/ethernet/amd/xgbe/xgbe-drv.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
378378
hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM);
379379
hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM);
380380

381+
/* Translate the Hash Table size into actual number */
382+
switch (hw_feat->hash_table_size) {
383+
case 0:
384+
break;
385+
case 1:
386+
hw_feat->hash_table_size = 64;
387+
break;
388+
case 2:
389+
hw_feat->hash_table_size = 128;
390+
break;
391+
case 3:
392+
hw_feat->hash_table_size = 256;
393+
break;
394+
}
395+
381396
/* The Queue and Channel counts are zero based so increment them
382397
* to get the actual number
383398
*/
@@ -912,18 +927,10 @@ static void xgbe_set_rx_mode(struct net_device *netdev)
912927
pr_mode = ((netdev->flags & IFF_PROMISC) != 0);
913928
am_mode = ((netdev->flags & IFF_ALLMULTI) != 0);
914929

915-
if (netdev_uc_count(netdev) > pdata->hw_feat.addn_mac)
916-
pr_mode = 1;
917-
if (netdev_mc_count(netdev) > pdata->hw_feat.addn_mac)
918-
am_mode = 1;
919-
if ((netdev_uc_count(netdev) + netdev_mc_count(netdev)) >
920-
pdata->hw_feat.addn_mac)
921-
pr_mode = 1;
922-
923930
hw_if->set_promiscuous_mode(pdata, pr_mode);
924931
hw_if->set_all_multicast_mode(pdata, am_mode);
925-
if (!pr_mode)
926-
hw_if->set_addn_mac_addrs(pdata, am_mode);
932+
933+
hw_if->add_mac_addresses(pdata);
927934

928935
DBGPR("<--xgbe_set_rx_mode\n");
929936
}

drivers/net/ethernet/amd/xgbe/xgbe-main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ static int xgbe_probe(struct platform_device *pdev)
397397
netdev->features |= netdev->hw_features;
398398
pdata->netdev_features = netdev->features;
399399

400+
netdev->priv_flags |= IFF_UNICAST_FLT;
401+
400402
xgbe_init_rx_coalesce(pdata);
401403
xgbe_init_tx_coalesce(pdata);
402404

drivers/net/ethernet/amd/xgbe/xgbe.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@
191191
/* Flow control queue count */
192192
#define XGMAC_MAX_FLOW_CONTROL_QUEUES 8
193193

194+
/* Maximum MAC address hash table size (256 bits = 8 bytes) */
195+
#define XGBE_MAC_HASH_TABLE_SIZE 8
194196

195197
struct xgbe_prv_data;
196198

@@ -387,7 +389,7 @@ struct xgbe_hw_if {
387389

388390
int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int);
389391
int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int);
390-
int (*set_addn_mac_addrs)(struct xgbe_prv_data *, unsigned int);
392+
int (*add_mac_addresses)(struct xgbe_prv_data *);
391393
int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr);
392394

393395
int (*enable_rx_csum)(struct xgbe_prv_data *);

0 commit comments

Comments
 (0)