}
}
+static uint32_t bitrev32(uint32_t x)
+{
+ x = (x >> 16) | (x << 16);
+ x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
+ x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
+ x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
+ x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
+ return x;
+}
+
+static uint32_t crc32_le(uint32_t crc, uint8_t *p, uint32_t len)
+{
+ int i;
+ while (len--) {
+ crc ^= *p++;
+ for (i = 0; i < 8; i++)
+ crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+ }
+ return crc;
+}
+
+void axgbe_set_mac_hash_table(struct axgbe_port *pdata, u8 *addr, bool add)
+{
+ uint32_t crc, htable_index, htable_bitmask;
+
+ crc = bitrev32(~crc32_le(~0, addr, RTE_ETHER_ADDR_LEN));
+ crc >>= pdata->hash_table_shift;
+ htable_index = crc >> 5;
+ htable_bitmask = 1 << (crc & 0x1f);
+
+ if (add) {
+ pdata->uc_hash_table[htable_index] |= htable_bitmask;
+ pdata->uc_hash_mac_addr++;
+ } else {
+ pdata->uc_hash_table[htable_index] &= ~htable_bitmask;
+ pdata->uc_hash_mac_addr--;
+ }
+ PMD_DRV_LOG(DEBUG, "%s MAC hash table Bit %d at Index %#x\n",
+ add ? "set" : "clear", (crc & 0x1f), htable_index);
+
+ AXGMAC_IOWRITE(pdata, MAC_HTR(htable_index),
+ pdata->uc_hash_table[htable_index]);
+}
+
void axgbe_set_mac_addn_addr(struct axgbe_port *pdata, u8 *addr, uint32_t index)
{
unsigned int mac_addr_hi, mac_addr_lo;
return 0;
}
+static void axgbe_config_mac_hash_table(struct axgbe_port *pdata)
+{
+ struct axgbe_hw_features *hw_feat = &pdata->hw_feat;
+
+ pdata->hash_table_shift = 0;
+ pdata->hash_table_count = 0;
+ pdata->uc_hash_mac_addr = 0;
+ memset(pdata->uc_hash_table, 0, sizeof(pdata->uc_hash_table));
+
+ if (hw_feat->hash_table_size) {
+ pdata->hash_table_shift = 26 - (hw_feat->hash_table_size >> 7);
+ pdata->hash_table_count = hw_feat->hash_table_size / 32;
+ }
+}
+
static void axgbe_config_mac_address(struct axgbe_port *pdata)
{
axgbe_set_mac_address(pdata, pdata->mac_addr.addr_bytes);
axgbe_enable_mtl_interrupts(pdata);
/* Initialize MAC related features */
+ axgbe_config_mac_hash_table(pdata);
axgbe_config_mac_address(pdata);
axgbe_config_jumbo_enable(pdata);
axgbe_config_flow_control(pdata);
static int axgbe_dev_set_mc_addr_list(struct rte_eth_dev *dev,
struct rte_ether_addr *mc_addr_set,
uint32_t nb_mc_addr);
+static int axgbe_dev_uc_hash_table_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr,
+ uint8_t add);
+static int axgbe_dev_uc_all_hash_table_set(struct rte_eth_dev *dev,
+ uint8_t add);
static int axgbe_dev_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
static int axgbe_dev_get_regs(struct rte_eth_dev *dev,
.mac_addr_add = axgbe_dev_mac_addr_add,
.mac_addr_remove = axgbe_dev_mac_addr_remove,
.set_mc_addr_list = axgbe_dev_set_mc_addr_list,
+ .uc_hash_table_set = axgbe_dev_uc_hash_table_set,
+ .uc_all_hash_table_set = axgbe_dev_uc_all_hash_table_set,
.link_update = axgbe_dev_link_update,
.get_reg = axgbe_dev_get_regs,
.stats_get = axgbe_dev_stats_get,
return 0;
}
+static int
+axgbe_dev_uc_hash_table_set(struct rte_eth_dev *dev,
+ struct rte_ether_addr *mac_addr, uint8_t add)
+{
+ struct axgbe_port *pdata = dev->data->dev_private;
+ struct axgbe_hw_features *hw_feat = &pdata->hw_feat;
+
+ if (!hw_feat->hash_table_size) {
+ PMD_DRV_LOG(ERR, "MAC Hash Table not supported\n");
+ return -ENOTSUP;
+ }
+
+ axgbe_set_mac_hash_table(pdata, (u8 *)mac_addr, add);
+
+ if (pdata->uc_hash_mac_addr > 0) {
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1);
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 1);
+ } else {
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 0);
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 0);
+ }
+ return 0;
+}
+
+static int
+axgbe_dev_uc_all_hash_table_set(struct rte_eth_dev *dev, uint8_t add)
+{
+ struct axgbe_port *pdata = dev->data->dev_private;
+ struct axgbe_hw_features *hw_feat = &pdata->hw_feat;
+ uint32_t index;
+
+ if (!hw_feat->hash_table_size) {
+ PMD_DRV_LOG(ERR, "MAC Hash Table not supported\n");
+ return -ENOTSUP;
+ }
+
+ for (index = 0; index < pdata->hash_table_count; index++) {
+ if (add)
+ pdata->uc_hash_table[index] = ~0;
+ else
+ pdata->uc_hash_table[index] = 0;
+
+ PMD_DRV_LOG(DEBUG, "%s MAC hash table at Index %#x\n",
+ add ? "set" : "clear", index);
+
+ AXGMAC_IOWRITE(pdata, MAC_HTR(index),
+ pdata->uc_hash_table[index]);
+ }
+
+ if (add) {
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 1);
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 1);
+ } else {
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HPF, 0);
+ AXGMAC_IOWRITE_BITS(pdata, MAC_PFR, HUC, 0);
+ }
+ return 0;
+}
+
/* return 0 means link status changed, -1 means not changed */
static int
axgbe_dev_link_update(struct rte_eth_dev *dev,
dev_info->min_rx_bufsize = AXGBE_RX_MIN_BUF_SIZE;
dev_info->max_rx_pktlen = AXGBE_RX_MAX_BUF_SIZE;
dev_info->max_mac_addrs = pdata->hw_feat.addn_mac + 1;
+ dev_info->max_hash_mac_addrs = pdata->hw_feat.hash_table_size;
dev_info->speed_capa = ETH_LINK_SPEED_10G;
dev_info->rx_offload_capa =
return -ENOMEM;
}
+ /* Allocate memory for storing hash filter MAC addresses */
+ len = RTE_ETHER_ADDR_LEN * AXGBE_MAX_HASH_MAC_ADDRS;
+ eth_dev->data->hash_mac_addrs = rte_zmalloc("axgbe_hash_mac_addr",
+ len, 0);
+
+ if (eth_dev->data->hash_mac_addrs == NULL) {
+ PMD_INIT_LOG(ERR,
+ "Failed to allocate %d bytes needed to "
+ "store MAC addresses", len);
+ return -ENOMEM;
+ }
+
if (!rte_is_valid_assigned_ether_addr(&pdata->mac_addr))
rte_eth_random_addr(pdata->mac_addr.addr_bytes);
#define AXGBE_RX_MAX_BUF_SIZE (0x3fff & ~(64 - 1))
#define AXGBE_RX_MIN_BUF_SIZE (RTE_ETHER_MAX_LEN + VLAN_HLEN)
#define AXGBE_MAX_MAC_ADDRS 32
+#define AXGBE_MAX_HASH_MAC_ADDRS 256
#define AXGBE_RX_BUF_ALIGN 64
(((_x) < 1024) ? 0 : ((_x) / AXGMAC_FLOW_CONTROL_UNIT) - 2)
#define AXGMAC_FLOW_CONTROL_MAX 33280
-/* Maximum MAC address hash table size (256 bits = 8 bytes) */
+/* Maximum MAC address hash table size (256 bits = 8 dword) */
#define AXGBE_MAC_HASH_TABLE_SIZE 8
/* Receive Side Scaling */
uint32_t rx_csum_enable;
struct axgbe_mmc_stats mmc_stats;
+
+ /* Hash filtering */
+ unsigned int hash_table_shift;
+ unsigned int hash_table_count;
+ unsigned int uc_hash_mac_addr;
+ unsigned int uc_hash_table[AXGBE_MAC_HASH_TABLE_SIZE];
};
void axgbe_init_function_ptrs_dev(struct axgbe_hw_if *hw_if);
void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if);
void axgbe_set_mac_addn_addr(struct axgbe_port *pdata, u8 *addr,
uint32_t index);
+void axgbe_set_mac_hash_table(struct axgbe_port *pdata, u8 *addr, bool add);
#endif /* RTE_ETH_AXGBE_H_ */