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
.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,
};