diff options
author | Lendacky, Thomas <Thomas.Lendacky@amd.com> | 2014-06-24 17:19:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-26 20:14:04 -0400 |
commit | b85e4d8960f10e4b28613a3e7b76f8889a2089e3 (patch) | |
tree | 240e74511042f9bdd930dcb41c030f0eb910c4b1 /drivers/net/ethernet/amd | |
parent | 801c62d945c6121c0262924732e430f0553bfb37 (diff) |
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 <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/amd')
-rw-r--r-- | drivers/net/ethernet/amd/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-common.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 141 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 4 |
6 files changed, 116 insertions, 69 deletions
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig index 8e83e4c8fff0..6e314dbba805 100644 --- a/drivers/net/ethernet/amd/Kconfig +++ b/drivers/net/ethernet/amd/Kconfig | |||
@@ -183,6 +183,7 @@ config AMD_XGBE | |||
183 | select PHYLIB | 183 | select PHYLIB |
184 | select AMD_XGBE_PHY | 184 | select AMD_XGBE_PHY |
185 | select BITREVERSE | 185 | select BITREVERSE |
186 | select CRC32 | ||
186 | ---help--- | 187 | ---help--- |
187 | This driver supports the AMD 10GbE Ethernet device found on an | 188 | This driver supports the AMD 10GbE Ethernet device found on an |
188 | AMD SoC. | 189 | AMD SoC. |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 1de9d0fc594a..ccbceba553e5 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h | |||
@@ -276,13 +276,6 @@ | |||
276 | #define MAC_PFR 0x0008 | 276 | #define MAC_PFR 0x0008 |
277 | #define MAC_WTR 0x000c | 277 | #define MAC_WTR 0x000c |
278 | #define MAC_HTR0 0x0010 | 278 | #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 | ||
286 | #define MAC_VLANTR 0x0050 | 279 | #define MAC_VLANTR 0x0050 |
287 | #define MAC_VLANHTR 0x0058 | 280 | #define MAC_VLANHTR 0x0058 |
288 | #define MAC_VLANIR 0x0060 | 281 | #define MAC_VLANIR 0x0060 |
@@ -315,6 +308,7 @@ | |||
315 | 308 | ||
316 | #define MAC_QTFCR_INC 4 | 309 | #define MAC_QTFCR_INC 4 |
317 | #define MAC_MACA_INC 4 | 310 | #define MAC_MACA_INC 4 |
311 | #define MAC_HTR_INC 4 | ||
318 | 312 | ||
319 | /* MAC register entry bit positions and sizes */ | 313 | /* MAC register entry bit positions and sizes */ |
320 | #define MAC_HWF0R_ADDMACADRSEL_INDEX 18 | 314 | #define MAC_HWF0R_ADDMACADRSEL_INDEX 18 |
@@ -387,6 +381,8 @@ | |||
387 | #define MAC_MACA1HR_AE_WIDTH 1 | 381 | #define MAC_MACA1HR_AE_WIDTH 1 |
388 | #define MAC_PFR_HMC_INDEX 2 | 382 | #define MAC_PFR_HMC_INDEX 2 |
389 | #define MAC_PFR_HMC_WIDTH 1 | 383 | #define MAC_PFR_HMC_WIDTH 1 |
384 | #define MAC_PFR_HPF_INDEX 10 | ||
385 | #define MAC_PFR_HPF_WIDTH 1 | ||
390 | #define MAC_PFR_HUC_INDEX 1 | 386 | #define MAC_PFR_HUC_INDEX 1 |
391 | #define MAC_PFR_HUC_WIDTH 1 | 387 | #define MAC_PFR_HUC_WIDTH 1 |
392 | #define MAC_PFR_PM_INDEX 4 | 388 | #define MAC_PFR_PM_INDEX 4 |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 2c7d582e0859..a56069c91fc4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c | |||
@@ -117,6 +117,7 @@ | |||
117 | #include <linux/phy.h> | 117 | #include <linux/phy.h> |
118 | #include <linux/clk.h> | 118 | #include <linux/clk.h> |
119 | #include <linux/bitrev.h> | 119 | #include <linux/bitrev.h> |
120 | #include <linux/crc32.h> | ||
120 | 121 | ||
121 | #include "xgbe.h" | 122 | #include "xgbe.h" |
122 | #include "xgbe-common.h" | 123 | #include "xgbe-common.h" |
@@ -548,24 +549,16 @@ static int xgbe_set_all_multicast_mode(struct xgbe_prv_data *pdata, | |||
548 | return 0; | 549 | return 0; |
549 | } | 550 | } |
550 | 551 | ||
551 | static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata, | 552 | static void xgbe_set_mac_reg(struct xgbe_prv_data *pdata, |
552 | unsigned int am_mode) | 553 | struct netdev_hw_addr *ha, unsigned int *mac_reg) |
553 | { | 554 | { |
554 | struct netdev_hw_addr *ha; | ||
555 | unsigned int mac_reg; | ||
556 | unsigned int mac_addr_hi, mac_addr_lo; | 555 | unsigned int mac_addr_hi, mac_addr_lo; |
557 | u8 *mac_addr; | 556 | u8 *mac_addr; |
558 | unsigned int i; | ||
559 | 557 | ||
560 | XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 0); | 558 | mac_addr_lo = 0; |
561 | XGMAC_IOWRITE_BITS(pdata, MAC_PFR, HMC, 0); | 559 | mac_addr_hi = 0; |
562 | |||
563 | i = 0; | ||
564 | mac_reg = MAC_MACA1HR; | ||
565 | 560 | ||
566 | netdev_for_each_uc_addr(ha, pdata->netdev) { | 561 | if (ha) { |
567 | mac_addr_lo = 0; | ||
568 | mac_addr_hi = 0; | ||
569 | mac_addr = (u8 *)&mac_addr_lo; | 562 | mac_addr = (u8 *)&mac_addr_lo; |
570 | mac_addr[0] = ha->addr[0]; | 563 | mac_addr[0] = ha->addr[0]; |
571 | mac_addr[1] = ha->addr[1]; | 564 | mac_addr[1] = ha->addr[1]; |
@@ -575,54 +568,93 @@ static int xgbe_set_addn_mac_addrs(struct xgbe_prv_data *pdata, | |||
575 | mac_addr[0] = ha->addr[4]; | 568 | mac_addr[0] = ha->addr[4]; |
576 | mac_addr[1] = ha->addr[5]; | 569 | mac_addr[1] = ha->addr[5]; |
577 | 570 | ||
578 | DBGPR(" adding unicast address %pM at 0x%04x\n", | 571 | DBGPR(" adding mac address %pM at 0x%04x\n", ha->addr, |
579 | ha->addr, mac_reg); | 572 | *mac_reg); |
580 | 573 | ||
581 | XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1); | 574 | XGMAC_SET_BITS(mac_addr_hi, MAC_MACA1HR, AE, 1); |
575 | } | ||
582 | 576 | ||
583 | XGMAC_IOWRITE(pdata, mac_reg, mac_addr_hi); | 577 | XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_hi); |
584 | mac_reg += MAC_MACA_INC; | 578 | *mac_reg += MAC_MACA_INC; |
585 | XGMAC_IOWRITE(pdata, mac_reg, mac_addr_lo); | 579 | XGMAC_IOWRITE(pdata, *mac_reg, mac_addr_lo); |
586 | mac_reg += MAC_MACA_INC; | 580 | *mac_reg += MAC_MACA_INC; |
581 | } | ||
587 | 582 | ||
588 | i++; | 583 | static void xgbe_set_mac_addn_addrs(struct xgbe_prv_data *pdata) |
589 | } | 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) { | 593 | if (netdev_uc_count(netdev) > addn_macs) { |
592 | netdev_for_each_mc_addr(ha, pdata->netdev) { | 594 | xgbe_set_promiscuous_mode(pdata, 1); |
593 | mac_addr_lo = 0; | 595 | } else { |
594 | mac_addr_hi = 0; | 596 | netdev_for_each_uc_addr(ha, netdev) { |
595 | mac_addr = (u8 *)&mac_addr_lo; | 597 | xgbe_set_mac_reg(pdata, ha, &mac_reg); |
596 | mac_addr[0] = ha->addr[0]; | 598 | addn_macs--; |
597 | mac_addr[1] = ha->addr[1]; | 599 | } |
598 | mac_addr[2] = ha->addr[2]; | 600 | |
599 | mac_addr[3] = ha->addr[3]; | 601 | if (netdev_mc_count(netdev) > addn_macs) { |
600 | mac_addr = (u8 *)&mac_addr_hi; | 602 | xgbe_set_all_multicast_mode(pdata, 1); |
601 | mac_addr[0] = ha->addr[4]; | 603 | } else { |
602 | mac_addr[1] = ha->addr[5]; | 604 | netdev_for_each_mc_addr(ha, netdev) { |
603 | 605 | xgbe_set_mac_reg(pdata, ha, &mac_reg); | |
604 | DBGPR(" adding multicast address %pM at 0x%04x\n", | 606 | addn_macs--; |
605 | ha->addr, mac_reg); | 607 | } |
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++; | ||
615 | } | 608 | } |
616 | } | 609 | } |
617 | 610 | ||
618 | /* Clear remaining additional MAC address entries */ | 611 | /* Clear remaining additional MAC address entries */ |
619 | for (; i < pdata->hw_feat.addn_mac; i++) { | 612 | while (addn_macs--) |
620 | XGMAC_IOWRITE(pdata, mac_reg, 0); | 613 | xgbe_set_mac_reg(pdata, NULL, &mac_reg); |
621 | mac_reg += MAC_MACA_INC; | 614 | } |
622 | XGMAC_IOWRITE(pdata, mac_reg, 0); | 615 | |
623 | mac_reg += MAC_MACA_INC; | 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 | return 0; | 658 | return 0; |
627 | } | 659 | } |
628 | 660 | ||
@@ -1606,6 +1638,13 @@ static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata) | |||
1606 | static void xgbe_config_mac_address(struct xgbe_prv_data *pdata) | 1638 | static void xgbe_config_mac_address(struct xgbe_prv_data *pdata) |
1607 | { | 1639 | { |
1608 | xgbe_set_mac_address(pdata, pdata->netdev->dev_addr); | 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 | static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata) | 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 | hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode; | 2242 | hw_if->set_promiscuous_mode = xgbe_set_promiscuous_mode; |
2204 | hw_if->set_all_multicast_mode = xgbe_set_all_multicast_mode; | 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 | hw_if->set_mac_address = xgbe_set_mac_address; | 2245 | hw_if->set_mac_address = xgbe_set_mac_address; |
2207 | 2246 | ||
2208 | hw_if->enable_rx_csum = xgbe_enable_rx_csum; | 2247 | hw_if->enable_rx_csum = xgbe_enable_rx_csum; |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 2acc37c07d9b..72dd61166a1c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c | |||
@@ -378,6 +378,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) | |||
378 | hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM); | 378 | hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM); |
379 | hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM); | 379 | hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM); |
380 | 380 | ||
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 | |||
381 | /* The Queue and Channel counts are zero based so increment them | 396 | /* The Queue and Channel counts are zero based so increment them |
382 | * to get the actual number | 397 | * to get the actual number |
383 | */ | 398 | */ |
@@ -912,18 +927,10 @@ static void xgbe_set_rx_mode(struct net_device *netdev) | |||
912 | pr_mode = ((netdev->flags & IFF_PROMISC) != 0); | 927 | pr_mode = ((netdev->flags & IFF_PROMISC) != 0); |
913 | am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); | 928 | am_mode = ((netdev->flags & IFF_ALLMULTI) != 0); |
914 | 929 | ||
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 | |||
923 | hw_if->set_promiscuous_mode(pdata, pr_mode); | 930 | hw_if->set_promiscuous_mode(pdata, pr_mode); |
924 | hw_if->set_all_multicast_mode(pdata, am_mode); | 931 | hw_if->set_all_multicast_mode(pdata, am_mode); |
925 | if (!pr_mode) | 932 | |
926 | hw_if->set_addn_mac_addrs(pdata, am_mode); | 933 | hw_if->add_mac_addresses(pdata); |
927 | 934 | ||
928 | DBGPR("<--xgbe_set_rx_mode\n"); | 935 | DBGPR("<--xgbe_set_rx_mode\n"); |
929 | } | 936 | } |
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index c3a48b7c2aed..b411ac557c47 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c | |||
@@ -397,6 +397,8 @@ static int xgbe_probe(struct platform_device *pdev) | |||
397 | netdev->features |= netdev->hw_features; | 397 | netdev->features |= netdev->hw_features; |
398 | pdata->netdev_features = netdev->features; | 398 | pdata->netdev_features = netdev->features; |
399 | 399 | ||
400 | netdev->priv_flags |= IFF_UNICAST_FLT; | ||
401 | |||
400 | xgbe_init_rx_coalesce(pdata); | 402 | xgbe_init_rx_coalesce(pdata); |
401 | xgbe_init_tx_coalesce(pdata); | 403 | xgbe_init_tx_coalesce(pdata); |
402 | 404 | ||
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 3cb911f39b60..a2d5f5f5d8b7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h | |||
@@ -191,6 +191,8 @@ | |||
191 | /* Flow control queue count */ | 191 | /* Flow control queue count */ |
192 | #define XGMAC_MAX_FLOW_CONTROL_QUEUES 8 | 192 | #define XGMAC_MAX_FLOW_CONTROL_QUEUES 8 |
193 | 193 | ||
194 | /* Maximum MAC address hash table size (256 bits = 8 bytes) */ | ||
195 | #define XGBE_MAC_HASH_TABLE_SIZE 8 | ||
194 | 196 | ||
195 | struct xgbe_prv_data; | 197 | struct xgbe_prv_data; |
196 | 198 | ||
@@ -387,7 +389,7 @@ struct xgbe_hw_if { | |||
387 | 389 | ||
388 | int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int); | 390 | int (*set_promiscuous_mode)(struct xgbe_prv_data *, unsigned int); |
389 | int (*set_all_multicast_mode)(struct xgbe_prv_data *, unsigned int); | 391 | 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 *); |
391 | int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr); | 393 | int (*set_mac_address)(struct xgbe_prv_data *, u8 *addr); |
392 | 394 | ||
393 | int (*enable_rx_csum)(struct xgbe_prv_data *); | 395 | int (*enable_rx_csum)(struct xgbe_prv_data *); |