From: Harish Patil Date: Wed, 19 Oct 2016 04:11:34 +0000 (-0700) Subject: net/qede: fix VLAN filters X-Git-Tag: spdx-start~5446 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=d6cb17535f88;p=dpdk.git net/qede: fix VLAN filters - fix to prevent duplicate VLAN filters librte_ether does not keep track of VLAN filters configured, so it becomes driver's responsibility to keep track of it and prevent duplicate filter programming. The fix is to use a singly linked list for tracking the entries and there by prevent duplicates. - fix num vlan filters Fix num vlan filter when filling Ethernet device information. Fixes: 2ea6f76aff40 ("qede: add core driver") Signed-off-by: Harish Patil --- diff --git a/drivers/net/qede/qede_eth_if.h b/drivers/net/qede/qede_eth_if.h index 7840a3702e..5a7fdc9192 100644 --- a/drivers/net/qede/qede_eth_if.h +++ b/drivers/net/qede/qede_eth_if.h @@ -46,7 +46,7 @@ struct qed_dev_eth_info { uint8_t num_tc; struct ether_addr port_mac; - uint8_t num_vlan_filters; + uint16_t num_vlan_filters; uint32_t num_mac_addrs; }; diff --git a/drivers/net/qede/qede_ethdev.c b/drivers/net/qede/qede_ethdev.c index f7cc31348a..b97e3be3de 100644 --- a/drivers/net/qede/qede_ethdev.c +++ b/drivers/net/qede/qede_ethdev.c @@ -406,10 +406,11 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev, struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev); struct ecore_dev *edev = QEDE_INIT_EDEV(qdev); struct qed_dev_eth_info *dev_info = &qdev->dev_info; + struct qede_vlan_entry *tmp = NULL; + struct qede_vlan_entry *vlan; int rc; - if (vlan_id != 0 && - qdev->configured_vlans == dev_info->num_vlan_filters) { + if (qdev->configured_vlans == dev_info->num_vlan_filters) { DP_NOTICE(edev, false, "Reached max VLAN filter limit" " enabling accept_any_vlan\n"); qede_config_accept_any_vlan(qdev, true); @@ -417,28 +418,66 @@ static int qede_vlan_filter_set(struct rte_eth_dev *eth_dev, } if (on) { + SLIST_FOREACH(tmp, &qdev->vlan_list_head, list) { + if (tmp->vid == vlan_id) { + DP_ERR(edev, "VLAN %u already configured\n", + vlan_id); + return -EEXIST; + } + } + + vlan = rte_malloc(NULL, sizeof(struct qede_vlan_entry), + RTE_CACHE_LINE_SIZE); + + if (!vlan) { + DP_ERR(edev, "Did not allocate memory for VLAN\n"); + return -ENOMEM; + } + rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_ADD, vlan_id); - if (rc) + if (rc) { DP_ERR(edev, "Failed to add VLAN %u rc %d\n", vlan_id, rc); - else - if (vlan_id != 0) - qdev->configured_vlans++; + rte_free(vlan); + } else { + vlan->vid = vlan_id; + SLIST_INSERT_HEAD(&qdev->vlan_list_head, vlan, list); + qdev->configured_vlans++; + DP_INFO(edev, "VLAN %u added, configured_vlans %u\n", + vlan_id, qdev->configured_vlans); + } } else { + SLIST_FOREACH(tmp, &qdev->vlan_list_head, list) { + if (tmp->vid == vlan_id) + break; + } + + if (!tmp) { + if (qdev->configured_vlans == 0) { + DP_INFO(edev, + "No VLAN filters configured yet\n"); + return 0; + } + + DP_ERR(edev, "VLAN %u not configured\n", vlan_id); + return -EINVAL; + } + + SLIST_REMOVE(&qdev->vlan_list_head, tmp, qede_vlan_entry, list); + rc = qede_set_ucast_rx_vlan(qdev, QED_FILTER_XCAST_TYPE_DEL, vlan_id); - if (rc) + if (rc) { DP_ERR(edev, "Failed to delete VLAN %u rc %d\n", vlan_id, rc); - else - if (vlan_id != 0) - qdev->configured_vlans--; + } else { + qdev->configured_vlans--; + DP_INFO(edev, "VLAN %u removed configured_vlans %u\n", + vlan_id, qdev->configured_vlans); + } } - DP_INFO(edev, "vlan_id %u on %u rc %d configured_vlans %u\n", - vlan_id, on, rc, qdev->configured_vlans); - return rc; } @@ -517,6 +556,8 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev) DP_INFO(edev, "IP/UDP/TCP checksum offload is always enabled " "in hw\n"); + SLIST_INIT(&qdev->vlan_list_head); + /* Check for the port restart case */ if (qdev->state != QEDE_DEV_INIT) { rc = qdev->ops->vport_stop(edev, 0); diff --git a/drivers/net/qede/qede_ethdev.h b/drivers/net/qede/qede_ethdev.h index f2e908c896..ed2d41cf53 100644 --- a/drivers/net/qede/qede_ethdev.h +++ b/drivers/net/qede/qede_ethdev.h @@ -10,6 +10,8 @@ #ifndef _QEDE_ETHDEV_H_ #define _QEDE_ETHDEV_H_ +#include + #include #include #include @@ -116,6 +118,11 @@ enum qede_dev_state { QEDE_DEV_STOP, /* Deactivate vport and stop traffic */ }; +struct qede_vlan_entry { + SLIST_ENTRY(qede_vlan_entry) list; + uint16_t vid; +}; + /* * Structure to store private data for each port. */ @@ -136,16 +143,10 @@ struct qede_dev { uint16_t num_queues; uint8_t fp_num_tx; uint8_t fp_num_rx; - enum qede_dev_state state; - - /* Vlans */ - osal_list_t vlan_list; + SLIST_HEAD(vlan_list_head, qede_vlan_entry)vlan_list_head; uint16_t configured_vlans; - uint16_t non_configured_vlans; bool accept_any_vlan; - uint16_t vxlan_dst_port; - struct ether_addr primary_mac; bool handle_hw_err; char drv_ver[QED_DRV_VER_STR_SIZE]; diff --git a/drivers/net/qede/qede_main.c b/drivers/net/qede/qede_main.c index 60655b7e1a..c83893d4b0 100644 --- a/drivers/net/qede/qede_main.c +++ b/drivers/net/qede/qede_main.c @@ -391,12 +391,18 @@ qed_fill_eth_dev_info(struct ecore_dev *edev, struct qed_dev_eth_info *info) info->num_tc = 1 /* @@@TBD aelior MULTI_COS */; if (IS_PF(edev)) { + int max_vf_vlan_filters = 0; + info->num_queues = 0; for_each_hwfn(edev, i) info->num_queues += FEAT_NUM(&edev->hwfns[i], ECORE_PF_L2_QUE); - info->num_vlan_filters = RESC_NUM(&edev->hwfns[0], ECORE_VLAN); + if (edev->p_iov_info) + max_vf_vlan_filters = edev->p_iov_info->total_vfs * + ECORE_ETH_VF_NUM_VLAN_FILTERS; + info->num_vlan_filters = RESC_NUM(&edev->hwfns[0], ECORE_VLAN) - + max_vf_vlan_filters; rte_memcpy(&info->port_mac, &edev->hwfns[0].hw_info.hw_mac_addr, ETHER_ADDR_LEN); @@ -404,7 +410,7 @@ qed_fill_eth_dev_info(struct ecore_dev *edev, struct qed_dev_eth_info *info) ecore_vf_get_num_rxqs(&edev->hwfns[0], &info->num_queues); ecore_vf_get_num_vlan_filters(&edev->hwfns[0], - &info->num_vlan_filters); + (u8 *)&info->num_vlan_filters); ecore_vf_get_port_mac(&edev->hwfns[0], (uint8_t *)&info->port_mac);