net/txgbe: add unicast hash bitmap
authorJiawen Wu <jiawenwu@trustnetic.com>
Mon, 19 Oct 2020 08:53:36 +0000 (16:53 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 3 Nov 2020 22:24:27 +0000 (23:24 +0100)
Add unicast hash bitmap.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Reviewed-by: Ferruh Yigit <ferruh.yigit@intel.com>
drivers/net/txgbe/base/txgbe_type.h
drivers/net/txgbe/txgbe_ethdev.c
drivers/net/txgbe/txgbe_ethdev.h

index ac3aae9..8a8ca96 100644 (file)
@@ -8,7 +8,9 @@
 #define TXGBE_LINK_UP_TIME     90 /* 9.0 Seconds */
 #define TXGBE_AUTO_NEG_TIME    45 /* 4.5 Seconds */
 
-#define TXGBE_ALIGN                            128 /* as intel did */
+#define TXGBE_MAX_UTA          128
+
+#define TXGBE_ALIGN            128 /* as intel did */
 
 #include "txgbe_status.h"
 #include "txgbe_osdep.h"
index 89209fe..81a89a7 100644 (file)
@@ -1080,6 +1080,124 @@ txgbe_set_default_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
        return 0;
 }
 
+static uint32_t
+txgbe_uta_vector(struct txgbe_hw *hw, struct rte_ether_addr *uc_addr)
+{
+       uint32_t vector = 0;
+
+       switch (hw->mac.mc_filter_type) {
+       case 0:   /* use bits [47:36] of the address */
+               vector = ((uc_addr->addr_bytes[4] >> 4) |
+                       (((uint16_t)uc_addr->addr_bytes[5]) << 4));
+               break;
+       case 1:   /* use bits [46:35] of the address */
+               vector = ((uc_addr->addr_bytes[4] >> 3) |
+                       (((uint16_t)uc_addr->addr_bytes[5]) << 5));
+               break;
+       case 2:   /* use bits [45:34] of the address */
+               vector = ((uc_addr->addr_bytes[4] >> 2) |
+                       (((uint16_t)uc_addr->addr_bytes[5]) << 6));
+               break;
+       case 3:   /* use bits [43:32] of the address */
+               vector = ((uc_addr->addr_bytes[4]) |
+                       (((uint16_t)uc_addr->addr_bytes[5]) << 8));
+               break;
+       default:  /* Invalid mc_filter_type */
+               break;
+       }
+
+       /* vector can only be 12-bits or boundary will be exceeded */
+       vector &= 0xFFF;
+       return vector;
+}
+
+static int
+txgbe_uc_hash_table_set(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mac_addr, uint8_t on)
+{
+       uint32_t vector;
+       uint32_t uta_idx;
+       uint32_t reg_val;
+       uint32_t uta_mask;
+       uint32_t psrctl;
+
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_uta_info *uta_info = TXGBE_DEV_UTA_INFO(dev);
+
+       /* The UTA table only exists on pf hardware */
+       if (hw->mac.type < txgbe_mac_raptor)
+               return -ENOTSUP;
+
+       vector = txgbe_uta_vector(hw, mac_addr);
+       uta_idx = (vector >> 5) & 0x7F;
+       uta_mask = 0x1UL << (vector & 0x1F);
+
+       if (!!on == !!(uta_info->uta_shadow[uta_idx] & uta_mask))
+               return 0;
+
+       reg_val = rd32(hw, TXGBE_UCADDRTBL(uta_idx));
+       if (on) {
+               uta_info->uta_in_use++;
+               reg_val |= uta_mask;
+               uta_info->uta_shadow[uta_idx] |= uta_mask;
+       } else {
+               uta_info->uta_in_use--;
+               reg_val &= ~uta_mask;
+               uta_info->uta_shadow[uta_idx] &= ~uta_mask;
+       }
+
+       wr32(hw, TXGBE_UCADDRTBL(uta_idx), reg_val);
+
+       psrctl = rd32(hw, TXGBE_PSRCTL);
+       if (uta_info->uta_in_use > 0)
+               psrctl |= TXGBE_PSRCTL_UCHFENA;
+       else
+               psrctl &= ~TXGBE_PSRCTL_UCHFENA;
+
+       psrctl &= ~TXGBE_PSRCTL_ADHF12_MASK;
+       psrctl |= TXGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);
+       wr32(hw, TXGBE_PSRCTL, psrctl);
+
+       return 0;
+}
+
+static int
+txgbe_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t on)
+{
+       struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+       struct txgbe_uta_info *uta_info = TXGBE_DEV_UTA_INFO(dev);
+       uint32_t psrctl;
+       int i;
+
+       /* The UTA table only exists on pf hardware */
+       if (hw->mac.type < txgbe_mac_raptor)
+               return -ENOTSUP;
+
+       if (on) {
+               for (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) {
+                       uta_info->uta_shadow[i] = ~0;
+                       wr32(hw, TXGBE_UCADDRTBL(i), ~0);
+               }
+       } else {
+               for (i = 0; i < ETH_VMDQ_NUM_UC_HASH_ARRAY; i++) {
+                       uta_info->uta_shadow[i] = 0;
+                       wr32(hw, TXGBE_UCADDRTBL(i), 0);
+               }
+       }
+
+       psrctl = rd32(hw, TXGBE_PSRCTL);
+       if (on)
+               psrctl |= TXGBE_PSRCTL_UCHFENA;
+       else
+               psrctl &= ~TXGBE_PSRCTL_UCHFENA;
+
+       psrctl &= ~TXGBE_PSRCTL_ADHF12_MASK;
+       psrctl |= TXGBE_PSRCTL_ADHF12(hw->mac.mc_filter_type);
+       wr32(hw, TXGBE_PSRCTL, psrctl);
+
+       return 0;
+}
+
 /**
  * set the IVAR registers, mapping interrupt causes to vectors
  * @param hw
@@ -1205,6 +1323,8 @@ static const struct eth_dev_ops txgbe_eth_dev_ops = {
        .mac_addr_add               = txgbe_add_rar,
        .mac_addr_remove            = txgbe_remove_rar,
        .mac_addr_set               = txgbe_set_default_mac_addr,
+       .uc_hash_table_set          = txgbe_uc_hash_table_set,
+       .uc_all_hash_table_set      = txgbe_uc_all_hash_table_set,
        .set_mc_addr_list           = txgbe_dev_set_mc_addr_list,
 };
 
index 9dd5d47..8fd7a06 100644 (file)
@@ -48,12 +48,19 @@ struct txgbe_interrupt {
        uint32_t mask[2];
 };
 
+struct txgbe_uta_info {
+       uint8_t  uc_filter_type;
+       uint16_t uta_in_use;
+       uint32_t uta_shadow[TXGBE_MAX_UTA];
+};
+
 /*
  * Structure to store private data for each driver instance (for each port).
  */
 struct txgbe_adapter {
        struct txgbe_hw             hw;
        struct txgbe_interrupt      intr;
+       struct txgbe_uta_info       uta_info;
        bool rx_bulk_alloc_allowed;
 };
 
@@ -66,6 +73,9 @@ struct txgbe_adapter {
 #define TXGBE_DEV_INTR(dev) \
        (&((struct txgbe_adapter *)(dev)->data->dev_private)->intr)
 
+#define TXGBE_DEV_UTA_INFO(dev) \
+       (&((struct txgbe_adapter *)(dev)->data->dev_private)->uta_info)
+
 void txgbe_set_ivar_map(struct txgbe_hw *hw, int8_t direction,
                               uint8_t queue, uint8_t msix_vector);