From: Pavel Belous <pavel.bel...@aquantia.com> Signed-off-by: Igor Russkikh <igor.russk...@aquantia.com> --- drivers/net/atlantic/atl_ethdev.c | 156 +++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 2 deletions(-)
diff --git a/drivers/net/atlantic/atl_ethdev.c b/drivers/net/atlantic/atl_ethdev.c index c99d321c9..80b7ac88e 100644 --- a/drivers/net/atlantic/atl_ethdev.c +++ b/drivers/net/atlantic/atl_ethdev.c @@ -84,6 +84,16 @@ static void atl_dev_info_get(struct rte_eth_dev *dev, static const uint32_t *atl_dev_supported_ptypes_get(struct rte_eth_dev *dev); +/* VLAN stuff */ +static int atl_vlan_filter_set(struct rte_eth_dev *dev, + uint16_t vlan_id, int on); + +static int atl_vlan_offload_set(struct rte_eth_dev *dev, int mask); + +static void atl_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue_id, int on); + +static int atl_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type, uint16_t tpid); + /* LEDs */ static int atl_dev_led_on(struct rte_eth_dev *dev); static int atl_dev_led_off(struct rte_eth_dev *dev); @@ -247,6 +257,11 @@ static const struct eth_dev_ops atl_eth_dev_ops = { .xstats_get_names = atl_dev_xstats_get_names, .stats_reset = atl_dev_stats_reset, .xstats_reset = atl_dev_xstats_reset, + /* VLAN */ + .vlan_filter_set = atl_vlan_filter_set, + .vlan_offload_set = atl_vlan_offload_set, + .vlan_tpid_set = atl_vlan_tpid_set, + .vlan_strip_queue_set = atl_vlan_strip_queue_set, /* LEDs */ .dev_led_on = atl_dev_led_on, @@ -525,7 +540,6 @@ atl_dev_start(struct rte_eth_dev *dev) uint32_t intr_vector = 0; uint32_t *link_speeds; uint32_t speed = 0; - int vlan_mask = 0; int status; int err; @@ -582,7 +596,6 @@ atl_dev_start(struct rte_eth_dev *dev) } } - err = hw->aq_fw_ops->update_link_status(hw); if (err) { @@ -1241,6 +1254,145 @@ atl_set_default_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr) return 0; } +static int +atl_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on) +{ + struct aq_hw_cfg_s *cfg = ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private); + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int err = 0; + int i = 0; + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < HW_ATL_B0_MAX_VLAN_IDS; i++) { + if (cfg->vlan_filter[i] == vlan_id) { + if (!on) { + /* Disable VLAN filter. */ + //hw_atl_rpf_vlan_flr_act_set(hw, 1U, i); + //hw_atl_rpf_vlan_id_flr_set(hw, vlan_filter[i], i); + hw_atl_rpf_vlan_flr_en_set(hw, 0U, i); + + /* Clear VLAN filter entry */ + cfg->vlan_filter[i] = 0; + } + break; + } + } + + if (i == HW_ATL_B0_MAX_VLAN_IDS && !on) + goto exit; /* VLAN_ID was not found. So, nothing to delete. */ + + if (i != HW_ATL_B0_MAX_VLAN_IDS) + goto exit; /* VLAN_ID already exist, or already removed above. Nothing to do. */ + + /* Try to found free VLAN filter to add new VLAN_ID */ + for (i = 0; i < HW_ATL_B0_MAX_VLAN_IDS; i++) { + if (cfg->vlan_filter[i] == 0) + break; + } + + if (i == HW_ATL_B0_MAX_VLAN_IDS) { + /* We have no free VLAN filter to add new VLAN_ID*/ + err = -ENOMEM; + goto exit; + } + + cfg->vlan_filter[i] = vlan_id; + hw_atl_rpf_vlan_flr_act_set(hw, 1U, i); + hw_atl_rpf_vlan_id_flr_set(hw, vlan_id, i); + hw_atl_rpf_vlan_flr_en_set(hw, 1U, i); + +exit: + /* Enable VLAN promisc mode if vlan_filter empty */ + for (i = 0; i < HW_ATL_B0_MAX_VLAN_IDS; i++) { + if (cfg->vlan_filter[i] != 0) + break; + } + + hw_atl_rpf_vlan_prom_mode_en_set(hw, i == HW_ATL_B0_MAX_VLAN_IDS); + + return err; +} + +static int +atl_enable_vlan_filter(struct rte_eth_dev *dev, int en) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct aq_hw_cfg_s *cfg = ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private); + int i; + + PMD_INIT_FUNC_TRACE(); + + for (i = 0; i < HW_ATL_B0_MAX_VLAN_IDS; i++) { + if (cfg->vlan_filter[i]) { + hw_atl_rpf_vlan_flr_en_set(hw, en, i); + } + } + return 0; +} + +static int +atl_vlan_offload_set(struct rte_eth_dev *dev, int mask) +{ + struct aq_hw_cfg_s *cfg = ATL_DEV_PRIVATE_TO_CFG(dev->data->dev_private); + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int ret = 0; + int i; + + PMD_INIT_FUNC_TRACE(); + + ret = atl_enable_vlan_filter(dev, mask & ETH_VLAN_FILTER_MASK); + + cfg->vlan_strip = !!(mask & ETH_VLAN_STRIP_MASK); + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + hw_atl_rpo_rx_desc_vlan_stripping_set(hw, cfg->vlan_strip, i); + } + + if (mask & ETH_VLAN_EXTEND_MASK) { + ret = -ENOTSUP; + } + + return ret; +} + +static int +atl_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type, uint16_t tpid) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + int err = 0; + + PMD_INIT_FUNC_TRACE(); + + switch (vlan_type) { + case ETH_VLAN_TYPE_INNER: + hw_atl_rpf_vlan_inner_etht_set(hw, tpid); + break; + case ETH_VLAN_TYPE_OUTER: + hw_atl_rpf_vlan_outer_etht_set(hw, tpid); + break; + default: + PMD_DRV_LOG(ERR, "Unsupported VLAN type"); + err = -ENOTSUP; + } + + return err; +} + +static void +atl_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue_id, int on) +{ + struct aq_hw_s *hw = ATL_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + if (queue_id > dev->data->nb_rx_queues) { + PMD_DRV_LOG(ERR, "Invalid queue id"); + return; + } + + hw_atl_rpo_rx_desc_vlan_stripping_set(hw, on, queue_id); +} static int atl_dev_set_mc_addr_list(struct rte_eth_dev *dev, -- 2.13.3.windows.1