[dpdk-dev] [PATCH 1/3] net/enic: cleanup interrupt setup when stopping port
enic_disable() wasn't calling rte_intr_disable() or rte_intr_callback_unregister(). If stopping/starting a port, the latter omission would result in the same interrupt callback being registered multiple times, which would then cause it to be called multiple times on every interrupt. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index b4ca371..aec24d2 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -798,6 +798,10 @@ int enic_disable(struct enic *enic) vnic_intr_mask(&enic->intr); (void)vnic_intr_masked(&enic->intr); /* flush write */ + rte_intr_disable(&enic->pdev->intr_handle); + rte_intr_callback_unregister(&enic->pdev->intr_handle, +enic_intr_handler, +(void *)enic->rte_dev); vnic_dev_disable(enic->vdev); -- 2.7.0
[dpdk-dev] [PATCH 2/3] net/enic: move code checking link status
Move link check code so that it can be used by interrupt handler. Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic.h| 1 + drivers/net/enic/enic_ethdev.c | 10 +- drivers/net/enic/enic_main.c | 15 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 4c16ef1..5c9345f 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -273,4 +273,5 @@ uint16_t enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t enic_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); int enic_set_mtu(struct enic *enic, uint16_t new_mtu); +int enic_link_update(struct enic *enic); #endif /* _ENIC_H_ */ diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index 6cbecb1..e10c824 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -403,17 +403,9 @@ static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete) { struct enic *enic = pmd_priv(eth_dev); - int ret; - int link_status = 0; ENICPMD_FUNC_TRACE(); - link_status = enic_get_link_status(enic); - ret = (link_status == enic->link_status); - enic->link_status = link_status; - eth_dev->data->dev_link.link_status = link_status; - eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; - eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); - return ret; + return enic_link_update(enic); } static void enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev, diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index aec24d2..aaf47e6 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -411,6 +411,21 @@ enic_free_consistent(void *priv, rte_free(mze); } +int enic_link_update(struct enic *enic) +{ + struct rte_eth_dev *eth_dev = enic->rte_dev; + int ret; + int link_status = 0; + + link_status = enic_get_link_status(enic); + ret = (link_status == enic->link_status); + enic->link_status = link_status; + eth_dev->data->dev_link.link_status = link_status; + eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; + eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); + return ret; +} + static void enic_intr_handler(__rte_unused struct rte_intr_handle *handle, void *arg) -- 2.7.0
[dpdk-dev] [PATCH 3/3] net/enic: enable link check interrupts
Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- doc/guides/nics/enic.rst | 3 ++- drivers/net/enic/enic_ethdev.c | 2 +- drivers/net/enic/enic_main.c | 19 ++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/guides/nics/enic.rst b/doc/guides/nics/enic.rst index 42e781e..8170286 100644 --- a/doc/guides/nics/enic.rst +++ b/doc/guides/nics/enic.rst @@ -76,7 +76,8 @@ Configuration information Only one interrupt per vNIC interface should be configured in the UCS manager regardless of the number receive/transmit queues. The ENIC PMD -uses this interrupt to get information about errors in the fast path. +uses this interrupt to get information about link status and errors +in the fast path. Limitations --- diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index e10c824..44105d6 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -607,7 +607,7 @@ static struct eth_driver rte_enic_pmd = { .pci_drv = { .name = "rte_enic_pmd", .id_table = pci_id_enic_map, - .drv_flags = RTE_PCI_DRV_NEED_MAPPING, + .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC, }, .eth_dev_init = eth_enicpmd_dev_init, .dev_private_size = sizeof(struct enic), diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index aaf47e6..55c7217 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -430,10 +430,13 @@ static void enic_intr_handler(__rte_unused struct rte_intr_handle *handle, void *arg) { - struct enic *enic = pmd_priv((struct rte_eth_dev *)arg); + struct rte_eth_dev *dev = (struct rte_eth_dev *)arg; + struct enic *enic = pmd_priv(dev); vnic_intr_return_all_credits(&enic->intr); + enic_link_update(enic); + _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC); enic_log_q_error(enic); } @@ -447,6 +450,13 @@ int enic_enable(struct enic *enic) eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */ + /* vnic notification of link status has already been turned on in +* enic_dev_init() which is called during probe time. Here we are +* just turning on interrupt vector 0 if needed. +*/ + if (eth_dev->data->dev_conf.intr_conf.lsc) + vnic_dev_notify_set(enic->vdev, 0); + if (enic_clsf_init(enic)) dev_warning(enic, "Init of hash table for clsf failed."\ "Flow director feature will not work\n"); @@ -838,6 +848,13 @@ int enic_disable(struct enic *enic) } } + /* If we were using interrupts, set the interrupt vector to -1 +* to disable interrupts. We are not disabling link notifcations, +* though, as we want the polling of link status to continue working. +*/ + if (enic->rte_dev->data->dev_conf.intr_conf.lsc) + vnic_dev_notify_set(enic->vdev, -1); + vnic_dev_set_reset_flag(enic->vdev, 1); vnic_dev_notify_unset(enic->vdev); -- 2.7.0
[dpdk-dev] [PATCH] net/enic: add support for Rx queue count function
Add support to enic for rte_eth_rx_queue_count(). Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_ethdev.c | 31 ++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index 44105d6..d20637f 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -260,6 +260,35 @@ static void enicpmd_dev_rx_queue_release(void *rxq) enic_free_rq(rxq); } +static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev, + uint16_t rx_queue_id) +{ + struct enic *enic = pmd_priv(dev); + uint32_t queue_count = 0; + struct vnic_cq *cq; + uint32_t cq_tail; + uint16_t cq_idx; + int rq_num; + + if (rx_queue_id >= dev->data->nb_rx_queues) { + dev_err(enic, "Invalid RX queue id=%d", rx_queue_id); + return 0; + } + + rq_num = enic_sop_rq(rx_queue_id); + cq = &enic->cq[enic_cq_rq(enic, rq_num)]; + cq_idx = cq->to_clean; + + cq_tail = ioread32(&cq->ctrl->cq_tail); + + if (cq_tail < cq_idx) + cq_tail += cq->ring.desc_count; + + queue_count = cq_tail - cq_idx; + + return queue_count; +} + static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t queue_idx, uint16_t nb_desc, @@ -560,7 +589,7 @@ static const struct eth_dev_ops enicpmd_eth_dev_ops = { .tx_queue_stop= enicpmd_dev_tx_queue_stop, .rx_queue_setup = enicpmd_dev_rx_queue_setup, .rx_queue_release = enicpmd_dev_rx_queue_release, - .rx_queue_count = NULL, + .rx_queue_count = enicpmd_dev_rx_queue_count, .rx_descriptor_done = NULL, .tx_queue_setup = enicpmd_dev_tx_queue_setup, .tx_queue_release = enicpmd_dev_tx_queue_release, -- 2.7.0
[dpdk-dev] [PATCH] enic: fix name of hash table used for enic classifiers
The enic_clsf_init() function is called once per enic instance, but it used a static name to create the hash table. Consequently when using more than one enic instance, there was a name collision which caused errors: EAL: memzone_reserve_aligned_thread_unsafe(): memzone already exists RING: Cannot reserve memory HASH: memory allocation failed PMD: rte_enic_pmd: Init of hash table for clsf failed. Flow director feature will not work This patch changes the name to be unique per enic instance. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_clsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_clsf.c b/drivers/net/enic/enic_clsf.c index edb56e1..2ec77f5 100644 --- a/drivers/net/enic/enic_clsf.c +++ b/drivers/net/enic/enic_clsf.c @@ -239,15 +239,16 @@ void enic_clsf_destroy(struct enic *enic) int enic_clsf_init(struct enic *enic) { + char clsf_name[RTE_HASH_NAMESIZE]; struct rte_hash_parameters hash_params = { - .name = "enicpmd_clsf_hash", + .name = clsf_name, .entries = ENICPMD_CLSF_HASH_ENTRIES, .key_len = sizeof(struct rte_eth_fdir_filter), .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, .socket_id = SOCKET_ID_ANY, }; - + sprintf(clsf_name, "enic_clsf_%s", enic->bdf_name); enic->fdir.hash = rte_hash_create(&hash_params); memset(&enic->fdir.stats, 0, sizeof(enic->fdir.stats)); enic->fdir.stats.free = ENICPMD_FDIR_MAX; -- 2.7.0
[dpdk-dev] [PATCH] enic: improve ptype handling
- add l4 ptypes to the ones we report as supporting - report/use RTE_PTYPE_L3_IPV4_EXT_UNKNOWN and RTE_PTYPE_L3_IPV6_EXT_UNKNOWN instead of RTE_PTYPE_L3_IPV4 and RTE_PTYPE_L3_IPV6 as vic can't distinguish between packets with extentions and those without extentions. - correctly set the ptype bits set on packets that are both tcp/udp and a frag - set RTE_PTYPE_L4_NONFRAG on ip packets we know are not udp, tcp, or fragments. Fixes: 947d860c821f ("enic: improve Rx performance") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_ethdev.c | 8 ++-- drivers/net/enic/enic_rxtx.c | 39 +-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index 697ff82..003dec0 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -455,8 +455,12 @@ static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev) { static const uint32_t ptypes[] = { - RTE_PTYPE_L3_IPV4, - RTE_PTYPE_L3_IPV6, + RTE_PTYPE_L3_IPV4_EXT_UNKNOWN, + RTE_PTYPE_L3_IPV6_EXT_UNKNOWN, + RTE_PTYPE_L4_TCP, + RTE_PTYPE_L4_UDP, + RTE_PTYPE_L4_FRAG, + RTE_PTYPE_L4_NONFRAG, RTE_PTYPE_UNKNOWN }; diff --git a/drivers/net/enic/enic_rxtx.c b/drivers/net/enic/enic_rxtx.c index 8fe334f..972eae2 100644 --- a/drivers/net/enic/enic_rxtx.c +++ b/drivers/net/enic/enic_rxtx.c @@ -148,20 +148,31 @@ enic_cq_rx_flags_to_pkt_type(struct cq_desc *cqd) struct cq_enet_rq_desc *cqrd = (struct cq_enet_rq_desc *)cqd; uint8_t cqrd_flags = cqrd->flags; static const uint32_t cq_type_table[128] __rte_cache_aligned = { - [32] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4, - [34] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 - | RTE_PTYPE_L4_UDP, - [36] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 - | RTE_PTYPE_L4_TCP, - [96] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4 - | RTE_PTYPE_L4_FRAG, - [16] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6, - [18] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 - | RTE_PTYPE_L4_UDP, - [20] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 - | RTE_PTYPE_L4_TCP, - [80] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6 - | RTE_PTYPE_L4_FRAG, + [0x00] = RTE_PTYPE_UNKNOWN, + [0x20] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_NONFRAG, + [0x22] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_UDP, + [0x24] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_TCP, + [0x60] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_FRAG, + [0x62] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_UDP, + [0x64] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN + | RTE_PTYPE_L4_TCP, + [0x10] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_NONFRAG, + [0x12] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_UDP, + [0x14] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_TCP, + [0x50] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_FRAG, + [0x52] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_UDP, + [0x54] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN + | RTE_PTYPE_L4_TCP, /* All others reserved */ }; cqrd_flags &= CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT -- 2.7.0
[dpdk-dev] [PATCH] enic: fix free function to actually free memory
enic_alloc_consistent() allocated memory, but enic_free_consistent() was an empty function, so allocated memory was never freed. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/base/vnic_dev.c | 14 +- drivers/net/enic/base/vnic_dev.h | 2 +- drivers/net/enic/enic.h | 12 + drivers/net/enic/enic_main.c | 56 +--- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c index e8a5028..fc2e4cc 100644 --- a/drivers/net/enic/base/vnic_dev.c +++ b/drivers/net/enic/base/vnic_dev.c @@ -83,7 +83,7 @@ struct vnic_dev { struct vnic_intr_coal_timer_info intr_coal_timer_info; void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name); - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle); }; @@ -101,7 +101,7 @@ void *vnic_dev_priv(struct vnic_dev *vdev) void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)) { @@ -807,7 +807,7 @@ int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) int vnic_dev_notify_unset(struct vnic_dev *vdev) { if (vdev->notify && !vnic_dev_in_reset(vdev)) { - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); @@ -924,16 +924,16 @@ void vnic_dev_unregister(struct vnic_dev *vdev) { if (vdev) { if (vdev->notify) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); if (vdev->stats) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_stats), vdev->stats, vdev->stats_pa); if (vdev->fw_info) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_fw_info), vdev->fw_info, vdev->fw_info_pa); kfree(vdev); @@ -1041,7 +1041,7 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait); *entry = (u16)a0; - vdev->free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa); + vdev->free_consistent(vdev->priv, tlv_size, tlv_va, tlv_pa); } else if (cmd == CLSF_DEL) { a0 = *entry; ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait); diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h index 113d6ac..689442f 100644 --- a/drivers/net/enic/base/vnic_dev.h +++ b/drivers/net/enic/base/vnic_dev.h @@ -102,7 +102,7 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)); void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 1e6914e..9f94afb 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -46,6 +46,8 @@ #include "vnic_rss.h" #include "enic_res.h" #include "cq_enet_desc.h" +#include +#include #define DRV_NAME "enic_pmd" #define DRV_DESCRIPTION"Cisco VIC Ethernet NIC Poll-mode Driver" @@ -95,6 +97,11 @@ struct enic_soft_stats { rte_atomic64_t rx_packet_errors; }; +struct enic_memzone_entry { + const struct rte_memzone *rz; + LIST_ENTRY(enic_memzone_entry) entries; +}; + /* Per-instance private data structure */ struct enic { struct enic *next; @@ -140,6 +147,11 @@
[dpdk-dev] [PATCH] enic: fix releasing of mbufs when tearing down rq
When trying to release the mbufs, the function was incorrectly iterating over the max size configured instead of the actual size of the ring. Fixes: cbb44dddcade ("enic: receive path performance improvements") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 0576a6e..9b6fe36 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -80,7 +80,7 @@ static int is_eth_addr_valid(uint8_t *addr) } static void -enic_rxmbuf_queue_release(struct enic *enic, struct vnic_rq *rq) +enic_rxmbuf_queue_release(__rte_unused struct enic *enic, struct vnic_rq *rq) { uint16_t i; @@ -89,7 +89,7 @@ enic_rxmbuf_queue_release(struct enic *enic, struct vnic_rq *rq) return; } - for (i = 0; i < enic->config.rq_desc_count; i++) { + for (i = 0; i < rq->ring.desc_count; i++) { if (rq->mbuf_ring[i]) { rte_pktmbuf_free_seg(rq->mbuf_ring[i]); rq->mbuf_ring[i] = NULL; -- 2.7.0
[dpdk-dev] [PATCH] enic: scattered Rx
For performance reasons, this patch uses 2 VIC RQs per RQ presented to DPDK. The VIC requires that each descriptor be marked as either a start of packet (SOP) descriptor or a non-SOP descriptor. A one RQ solution requires skipping descriptors when receiving small packets and results in bad performance when receiving many small packets. The 2 RQ solution makes use of the VIC feature that allows a receive on primary queue to 'spill over' into another queue if the receive is too large to fit in the buffer assigned to the descriptor on the primary queue. This means that there is no skipping of descriptors when receiving small packets and results in much better performance. Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- doc/guides/nics/overview.rst | 2 +- drivers/net/enic/base/rq_enet_desc.h | 2 +- drivers/net/enic/base/vnic_rq.c | 8 +- drivers/net/enic/base/vnic_rq.h | 18 ++- drivers/net/enic/enic.h | 22 ++- drivers/net/enic/enic_ethdev.c | 10 +- drivers/net/enic/enic_main.c | 277 +++ drivers/net/enic/enic_res.c | 5 +- drivers/net/enic/enic_rxtx.c | 137 +++-- 9 files changed, 358 insertions(+), 123 deletions(-) diff --git a/doc/guides/nics/overview.rst b/doc/guides/nics/overview.rst index 2200171..d0ae847 100644 --- a/doc/guides/nics/overview.rst +++ b/doc/guides/nics/overview.rst @@ -94,7 +94,7 @@ Most of these differences are summarized below. Queue start/stop Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y MTU update Y Y Y Y Y Y Y Y Y Y Jumbo frame Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y - Scattered Rx Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y + Scattered Rx Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y LRO Y Y Y Y TSO Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Promiscuous mode Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y diff --git a/drivers/net/enic/base/rq_enet_desc.h b/drivers/net/enic/base/rq_enet_desc.h index 7292d9d..13e24b4 100644 --- a/drivers/net/enic/base/rq_enet_desc.h +++ b/drivers/net/enic/base/rq_enet_desc.h @@ -55,7 +55,7 @@ enum rq_enet_type_types { #define RQ_ENET_TYPE_BITS 2 #define RQ_ENET_TYPE_MASK ((1 << RQ_ENET_TYPE_BITS) - 1) -static inline void rq_enet_desc_enc(struct rq_enet_desc *desc, +static inline void rq_enet_desc_enc(volatile struct rq_enet_desc *desc, u64 address, u8 type, u16 length) { desc->address = cpu_to_le64(address); diff --git a/drivers/net/enic/base/vnic_rq.c b/drivers/net/enic/base/vnic_rq.c index cb62c5e..0e700a1 100644 --- a/drivers/net/enic/base/vnic_rq.c +++ b/drivers/net/enic/base/vnic_rq.c @@ -84,11 +84,12 @@ void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, iowrite32(cq_index, &rq->ctrl->cq_index); iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable); iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset); - iowrite32(0, &rq->ctrl->dropped_packet_count); iowrite32(0, &rq->ctrl->error_status); iowrite32(fetch_index, &rq->ctrl->fetch_index); iowrite32(posted_index, &rq->ctrl->posted_index); - + if (rq->is_sop) + iowrite32(((rq->is_sop << 10) | rq->data_queue_idx), + &rq->ctrl->data_ring); } void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, @@ -96,6 +97,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, unsigned int error_interrupt_offset) { u32 fetch_index = 0; + /* Use current fetch_index as the ring starting point */ fetch_index = ioread32(&rq->ctrl->fetch_index); @@ -110,6 +112,8 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, error_interrupt_offset); rq->rxst_idx = 0; rq->tot_pkts = 0; + rq->pkt_first_seg = NULL; + rq->pkt_last_seg = NULL; } void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error) diff --git a/drivers/net/enic/base/vnic_rq.h b/drivers/net/enic/base/vnic_rq.h index e083ccc..fd9e170 100644 --- a/drivers/net/enic/base/vnic_rq.h +++ b/drivers/net/enic/base/vnic_rq.h @@ -60,10 +60,18 @@ struct vnic_rq_ctrl { u32 pad7; u32 error_status; /* 0x48 */ u32 pad8; - u32 dropped_packet_count; /* 0x50 */ + u32 tcp_sn; /* 0x50 */ u32 pad9; - u32 dropped_packet_count_rc;/* 0x58 */ + u32 unused; /* 0x58 */ u32 pad10; + u32 dca_select;
[dpdk-dev] [PATCH v2] enic: scattered Rx
For performance reasons, this patch uses 2 VIC RQs per RQ presented to DPDK. The VIC requires that each descriptor be marked as either a start of packet (SOP) descriptor or a non-SOP descriptor. A one RQ solution requires skipping descriptors when receiving small packets and results in bad performance when receiving many small packets. The 2 RQ solution makes use of the VIC feature that allows a receive on primary queue to 'spill over' into another queue if the receive is too large to fit in the buffer assigned to the descriptor on the primary queue. This means that there is no skipping of descriptors when receiving small packets and results in much better performance. Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- v2: - fixes upstream checkpatch complaint - fixes bug where packet type and flags were set on last mbuf instead of first mbuf of scattered receive - adds ethernet hdr length to mtu when calculating the number of mbufs it would take to receive maximum sized packet doc/guides/nics/overview.rst | 2 +- drivers/net/enic/base/rq_enet_desc.h | 2 +- drivers/net/enic/base/vnic_rq.c | 8 +- drivers/net/enic/base/vnic_rq.h | 18 ++- drivers/net/enic/enic.h | 22 ++- drivers/net/enic/enic_ethdev.c | 10 +- drivers/net/enic/enic_main.c | 277 +++ drivers/net/enic/enic_res.c | 5 +- drivers/net/enic/enic_rxtx.c | 140 -- 9 files changed, 361 insertions(+), 123 deletions(-) diff --git a/doc/guides/nics/overview.rst b/doc/guides/nics/overview.rst index 2200171..d0ae847 100644 --- a/doc/guides/nics/overview.rst +++ b/doc/guides/nics/overview.rst @@ -94,7 +94,7 @@ Most of these differences are summarized below. Queue start/stop Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y MTU update Y Y Y Y Y Y Y Y Y Y Jumbo frame Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y - Scattered Rx Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y + Scattered Rx Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y LRO Y Y Y Y TSO Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Promiscuous mode Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y diff --git a/drivers/net/enic/base/rq_enet_desc.h b/drivers/net/enic/base/rq_enet_desc.h index 7292d9d..13e24b4 100644 --- a/drivers/net/enic/base/rq_enet_desc.h +++ b/drivers/net/enic/base/rq_enet_desc.h @@ -55,7 +55,7 @@ enum rq_enet_type_types { #define RQ_ENET_TYPE_BITS 2 #define RQ_ENET_TYPE_MASK ((1 << RQ_ENET_TYPE_BITS) - 1) -static inline void rq_enet_desc_enc(struct rq_enet_desc *desc, +static inline void rq_enet_desc_enc(volatile struct rq_enet_desc *desc, u64 address, u8 type, u16 length) { desc->address = cpu_to_le64(address); diff --git a/drivers/net/enic/base/vnic_rq.c b/drivers/net/enic/base/vnic_rq.c index cb62c5e..0e700a1 100644 --- a/drivers/net/enic/base/vnic_rq.c +++ b/drivers/net/enic/base/vnic_rq.c @@ -84,11 +84,12 @@ void vnic_rq_init_start(struct vnic_rq *rq, unsigned int cq_index, iowrite32(cq_index, &rq->ctrl->cq_index); iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable); iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset); - iowrite32(0, &rq->ctrl->dropped_packet_count); iowrite32(0, &rq->ctrl->error_status); iowrite32(fetch_index, &rq->ctrl->fetch_index); iowrite32(posted_index, &rq->ctrl->posted_index); - + if (rq->is_sop) + iowrite32(((rq->is_sop << 10) | rq->data_queue_idx), + &rq->ctrl->data_ring); } void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, @@ -96,6 +97,7 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, unsigned int error_interrupt_offset) { u32 fetch_index = 0; + /* Use current fetch_index as the ring starting point */ fetch_index = ioread32(&rq->ctrl->fetch_index); @@ -110,6 +112,8 @@ void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index, error_interrupt_offset); rq->rxst_idx = 0; rq->tot_pkts = 0; + rq->pkt_first_seg = NULL; + rq->pkt_last_seg = NULL; } void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error) diff --git a/drivers/net/enic/base/vnic_rq.h b/drivers/net/enic/base/vnic_rq.h index e083ccc..fd9e170 100644 --- a/drivers/net/enic/base/vnic_rq.h +++ b/drivers/net/enic/base/vnic_rq.h @@ -60,10 +60,18 @@ struct vnic_rq_ctrl { u32 pad7; u32 error_status; /* 0x48 */ u32 p
[dpdk-dev] [PATCH v2] enic: fix name of hash table used for enic classifiers
The enic_clsf_init() function is called once per enic instance, but it used a static name to create the hash table. Consequently when using more than one enic instance, there was a name collision which caused errors: EAL: memzone_reserve_aligned_thread_unsafe(): memzone already exists RING: Cannot reserve memory HASH: memory allocation failed PMD: rte_enic_pmd: Init of hash table for clsf failed. Flow director feature will not work This patch changes the name to be unique per enic instance. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- v2: - use snprintf instead of sprintf drivers/net/enic/enic_clsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_clsf.c b/drivers/net/enic/enic_clsf.c index edb56e1..2050818 100644 --- a/drivers/net/enic/enic_clsf.c +++ b/drivers/net/enic/enic_clsf.c @@ -239,15 +239,16 @@ void enic_clsf_destroy(struct enic *enic) int enic_clsf_init(struct enic *enic) { + char clsf_name[RTE_HASH_NAMESIZE]; struct rte_hash_parameters hash_params = { - .name = "enicpmd_clsf_hash", + .name = clsf_name, .entries = ENICPMD_CLSF_HASH_ENTRIES, .key_len = sizeof(struct rte_eth_fdir_filter), .hash_func = DEFAULT_HASH_FUNC, .hash_func_init_val = 0, .socket_id = SOCKET_ID_ANY, }; - + snprintf(clsf_name, RTE_HASH_NAMESIZE, "enic_clsf_%s", enic->bdf_name); enic->fdir.hash = rte_hash_create(&hash_params); memset(&enic->fdir.stats, 0, sizeof(enic->fdir.stats)); enic->fdir.stats.free = ENICPMD_FDIR_MAX; -- 2.7.0
[dpdk-dev] [PATCH v2] enic: fix free function to actually free memory
enic_alloc_consistent() allocated memory, but enic_free_consistent() was an empty function, so allocated memory was never freed. This commit adds a list and lock to the enic structure to keep track of the memzones allocated in enic_alloc_consistent(), and enic_free_consistent() uses that information to properly free memory. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- v2: - updated commit message to mention memzone tracking drivers/net/enic/base/vnic_dev.c | 14 +- drivers/net/enic/base/vnic_dev.h | 2 +- drivers/net/enic/enic.h | 12 + drivers/net/enic/enic_main.c | 56 +--- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c index e8a5028..fc2e4cc 100644 --- a/drivers/net/enic/base/vnic_dev.c +++ b/drivers/net/enic/base/vnic_dev.c @@ -83,7 +83,7 @@ struct vnic_dev { struct vnic_intr_coal_timer_info intr_coal_timer_info; void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name); - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle); }; @@ -101,7 +101,7 @@ void *vnic_dev_priv(struct vnic_dev *vdev) void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)) { @@ -807,7 +807,7 @@ int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev) int vnic_dev_notify_unset(struct vnic_dev *vdev) { if (vdev->notify && !vnic_dev_in_reset(vdev)) { - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); @@ -924,16 +924,16 @@ void vnic_dev_unregister(struct vnic_dev *vdev) { if (vdev) { if (vdev->notify) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_notify), vdev->notify, vdev->notify_pa); if (vdev->stats) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_stats), vdev->stats, vdev->stats_pa); if (vdev->fw_info) - vdev->free_consistent(vdev->pdev, + vdev->free_consistent(vdev->priv, sizeof(struct vnic_devcmd_fw_info), vdev->fw_info, vdev->fw_info_pa); kfree(vdev); @@ -1041,7 +1041,7 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry, ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait); *entry = (u16)a0; - vdev->free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa); + vdev->free_consistent(vdev->priv, tlv_size, tlv_va, tlv_pa); } else if (cmd == CLSF_DEL) { a0 = *entry; ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait); diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h index 113d6ac..689442f 100644 --- a/drivers/net/enic/base/vnic_dev.h +++ b/drivers/net/enic/base/vnic_dev.h @@ -102,7 +102,7 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev, void vnic_register_cbacks(struct vnic_dev *vdev, void *(*alloc_consistent)(void *priv, size_t size, dma_addr_t *dma_handle, u8 *name), - void (*free_consistent)(struct rte_pci_device *hwdev, + void (*free_consistent)(void *priv, size_t size, void *vaddr, dma_addr_t dma_handle)); void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type, diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 1e6914e..9f94afb 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -46,6 +46,8 @@ #include "vnic_rss.h" #include "enic_res.h" #include "cq_enet_desc.h" +#include +#include #define DRV_NAME "enic_pmd" #define DRV_DESCRIPTION"Cisco VIC Ethernet NIC Poll-mode Driver" @@ -95,6 +97,11 @@ struct enic_soft_stats { rte_atom
[dpdk-dev] [PATCH] enic: fix issues when using Rx scatter with multiple RQs
The Rx scatter patch failed to make a few changes and resulted in problems when using multiple RQs since the wrong RQ or CQ was being used. Fixes: 14a261bf0520 ("enic: add scattered Rx support") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic.h | 2 +- drivers/net/enic/enic_main.c | 10 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index ed5f18d..15b1d45 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -174,7 +174,7 @@ static inline unsigned int enic_vnic_rq_count(struct enic *enic) static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq) { - return rq; + return rq / 2; } static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 15389e5..68dbe40 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -238,19 +238,20 @@ void enic_init_vnic_resources(struct enic *enic) struct vnic_rq *data_rq; for (index = 0; index < enic->rq_count; index++) { + cq_idx = enic_cq_rq(enic, enic_sop_rq(index)); + vnic_rq_init(&enic->rq[enic_sop_rq(index)], - enic_cq_rq(enic, index), + cq_idx, error_interrupt_enable, error_interrupt_offset); data_rq = &enic->rq[enic_data_rq(index)]; if (data_rq->in_use) vnic_rq_init(data_rq, -enic_cq_rq(enic, index), +cq_idx, error_interrupt_enable, error_interrupt_offset); - cq_idx = enic_cq_rq(enic, index); vnic_cq_init(&enic->cq[cq_idx], 0 /* flow_control_enable */, 1 /* color_enable */, @@ -899,7 +900,8 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) return -ENOMEM; for (i = 0; i < (1 << rss_hash_bits); i++) - (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; + (*rss_cpu_buf_va).cpu[i / 4].b[i % 4] = + enic_sop_rq(i % enic->rq_count); err = enic_set_rss_cpu(enic, rss_cpu_buf_pa, -- 2.7.0
[dpdk-dev] [PATCH v2] enic: fix issues when using Rx scatter with multiple RQs
The Rx scatter patch failed to make a few changes and resulted in problems when using multiple receive queues in dpdk (ie RSS) since the wrong adapter resources were being used. - get and use the correct completion queue index associated with a receive queue. - set the correct receive queue index when using RSS Fixes: 14a261bf0520 ("enic: add scattered Rx support") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic.h | 6 +- drivers/net/enic/enic_main.c | 10 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index ed5f18d..1dd8aee 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -174,7 +174,11 @@ static inline unsigned int enic_vnic_rq_count(struct enic *enic) static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq) { - return rq; + /* Scatter rx uses two receive queues together with one +* completion queue, so the completion queue number is no +* longer the same as the rq number. +*/ + return rq / 2; } static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 15389e5..68dbe40 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -238,19 +238,20 @@ void enic_init_vnic_resources(struct enic *enic) struct vnic_rq *data_rq; for (index = 0; index < enic->rq_count; index++) { + cq_idx = enic_cq_rq(enic, enic_sop_rq(index)); + vnic_rq_init(&enic->rq[enic_sop_rq(index)], - enic_cq_rq(enic, index), + cq_idx, error_interrupt_enable, error_interrupt_offset); data_rq = &enic->rq[enic_data_rq(index)]; if (data_rq->in_use) vnic_rq_init(data_rq, -enic_cq_rq(enic, index), +cq_idx, error_interrupt_enable, error_interrupt_offset); - cq_idx = enic_cq_rq(enic, index); vnic_cq_init(&enic->cq[cq_idx], 0 /* flow_control_enable */, 1 /* color_enable */, @@ -899,7 +900,8 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) return -ENOMEM; for (i = 0; i < (1 << rss_hash_bits); i++) - (*rss_cpu_buf_va).cpu[i/4].b[i%4] = i % enic->rq_count; + (*rss_cpu_buf_va).cpu[i / 4].b[i % 4] = + enic_sop_rq(i % enic->rq_count); err = enic_set_rss_cpu(enic, rss_cpu_buf_pa, -- 2.7.0
[dpdk-dev] [PATCH] net/enic: fix checking for sufficient resources
The enic PMD was using the same variables in the enic structure to track two different things. Initially rq_count, wq_count, cq_count, and intr_count were set to the values obtained from the VIC adapters as the maximum resources allocated on the VIC, then in enic_set_vnic_res(), they were set to the counts of resources actually used, discarding the initial values. The checks in enic_set_vnic_res() were technically incorrect if it is called more than once on a port, which happens when using bonding, but were harmless in practice as the checks couldn't fail on the second call. The enic rx-scatter patch misunderstood the subtleties of enic_set_vnic_res(), and naively added a multiply by two to the rq_count check. This resulted in the rq_count check failing when enic_set_vnic_res() was called a second time, ie when using bonding. This patch adds new variables to the enic structure to track the maximum resources the VIC is configured to provide so that the information isn't later lost and calls to enic_set_vnic_res() do the expected thing. Fixes: 856d7ba7ed22 ("net/enic: support scattered Rx") Signed-off-by: Nelson Escobar --- drivers/net/enic/enic.h| 6 ++ drivers/net/enic/enic_ethdev.c | 5 +++-- drivers/net/enic/enic_main.c | 14 -- drivers/net/enic/enic_res.c| 12 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index 53fed0b..33057d4 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -152,6 +152,12 @@ struct enic { /* software counters */ struct enic_soft_stats soft_stats; + /* configured resources on vic */ + unsigned int conf_rq_count; + unsigned int conf_wq_count; + unsigned int conf_cq_count; + unsigned int conf_intr_count; + /* linked list storing memory allocations */ LIST_HEAD(enic_memzone_list, enic_memzone_entry) memzone_list; rte_spinlock_t memzone_list_lock; diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c index a7ce064..66b81a2 100644 --- a/drivers/net/enic/enic_ethdev.c +++ b/drivers/net/enic/enic_ethdev.c @@ -436,8 +436,9 @@ static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev, struct enic *enic = pmd_priv(eth_dev); ENICPMD_FUNC_TRACE(); - device_info->max_rx_queues = enic->rq_count; - device_info->max_tx_queues = enic->wq_count; + /* Scattered Rx uses two receive queues per rx queue exposed to dpdk */ + device_info->max_rx_queues = enic->conf_rq_count / 2; + device_info->max_tx_queues = enic->conf_wq_count; device_info->min_rx_bufsize = ENIC_MIN_MTU; device_info->max_rx_pktlen = enic->rte_dev->data->mtu + ETHER_HDR_LEN + 4; diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 0475cc1..d4e43b5 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -1016,21 +1016,23 @@ int enic_set_vnic_res(struct enic *enic) /* With Rx scatter support, two RQs are now used per RQ used by * the application. */ - if (enic->rq_count < (eth_dev->data->nb_rx_queues * 2)) { + if (enic->conf_rq_count < eth_dev->data->nb_rx_queues) { dev_err(dev, "Not enough Receive queues. Requested:%u which uses %d RQs on VIC, Configured:%u\n", eth_dev->data->nb_rx_queues, - eth_dev->data->nb_rx_queues * 2, enic->rq_count); + eth_dev->data->nb_rx_queues * 2, enic->conf_rq_count); rc = -EINVAL; } - if (enic->wq_count < eth_dev->data->nb_tx_queues) { + if (enic->conf_wq_count < eth_dev->data->nb_tx_queues) { dev_err(dev, "Not enough Transmit queues. Requested:%u, Configured:%u\n", - eth_dev->data->nb_tx_queues, enic->wq_count); + eth_dev->data->nb_tx_queues, enic->conf_wq_count); rc = -EINVAL; } - if (enic->cq_count < (enic->rq_count + enic->wq_count)) { + if (enic->conf_cq_count < (eth_dev->data->nb_rx_queues + + eth_dev->data->nb_tx_queues)) { dev_err(dev, "Not enough Completion queues. Required:%u, Configured:%u\n", - enic->rq_count + enic->wq_count, enic->cq_count); + (eth_dev->data->nb_rx_queues + +eth_dev->data->nb_tx_queues), enic->conf_cq_count); rc = -EINVAL; } diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index b271d34..84c5d33 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net
[dpdk-dev] [PATCH 1/2] net/enic: fix setting MAC address when a port is restarted
enic_disable() removed the MAC address when a port was shut down but enic_enable() didn't add the MAC address back when the port was started again. Move where we set the MAC address for the adapter from enic_setup_finish() to a enic_enable() so that port restarting works properly. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 8eacf2d..1f3d14e 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -455,6 +455,8 @@ int enic_enable(struct enic *enic) for (index = 0; index < enic->rq_count; index++) enic_start_rq(enic, index); + vnic_dev_add_addr(enic->vdev, enic->mac_addr); + vnic_dev_enable_wait(enic->vdev); /* Register and enable error interrupt */ @@ -971,8 +973,6 @@ int enic_setup_finish(struct enic *enic) return -1; } - vnic_dev_add_addr(enic->vdev, enic->mac_addr); - /* Default conf */ vnic_dev_packet_filter(enic->vdev, 1 /* directed */, -- 2.7.0
[dpdk-dev] [PATCH 2/2] net/enic: fix removing old MAC address when setting new one
enic_set_mac_address() meant to remove the old MAC address before setting the new one, but accidentally tried removing the new MAC address before setting the new MAC address. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 1f3d14e..c3b1e87 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -203,7 +203,7 @@ void enic_set_mac_address(struct enic *enic, uint8_t *mac_addr) return; } - err = vnic_dev_del_addr(enic->vdev, mac_addr); + err = vnic_dev_del_addr(enic->vdev, enic->mac_addr); if (err) { dev_err(enic, "del mac addr failed\n"); return; -- 2.7.0
[dpdk-dev] [PATCH] net/enic: fix calculation of truncated packets
The calculation of truncated packets didn't take into account packet errors due to the adapter not having buffers, causing both the ipackets, and imissed counts to be wrong if such errors occurred. In order to properly calculate the number of packets truncated, we need to subtract the count of errors due to no buffers. Fixes: c44d9f01adf3 ("net/enic: count truncated packets") Signed-off-by: Nelson Escobar --- drivers/net/enic/enic_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index d8669cc..9ec2a2d 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -172,7 +172,8 @@ void enic_dev_stats_get(struct enic *enic, struct rte_eth_stats *r_stats) * which can make ibytes be slightly higher than it should be. */ rx_packet_errors = rte_atomic64_read(&soft_stats->rx_packet_errors); - rx_truncated = rx_packet_errors - stats->rx.rx_errors; + rx_truncated = rx_packet_errors - stats->rx.rx_errors - + stats->rx.rx_no_bufs; r_stats->ipackets = stats->rx.rx_frames_ok - rx_truncated; r_stats->opackets = stats->tx.tx_frames_ok; -- 2.7.0
[dpdk-dev] [PATCH] net/enic: fix segfault after receiving error interrupt
When enic's interrupt handler is called indicating an error, it scans through the receive queues (RQs) on the adapter looking for errors. But since the inclusion of rx scatter, some of the RQs may not be in use, and you shouldn't check them for errors. Fixes: 856d7ba7ed22 ("net/enic: support scattered Rx") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 9ec2a2d..fbd4089 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -123,6 +123,8 @@ static void enic_log_q_error(struct enic *enic) } for (i = 0; i < enic_vnic_rq_count(enic); i++) { + if (!enic->rq[i].in_use) + continue; error_status = vnic_rq_error_status(&enic->rq[i]); if (error_status) dev_err(enic, "RQ[%d] error_status %d\n", i, -- 2.7.0
[dpdk-dev] [PATCH] bonding: fix bond link detect in non-interrupt mode
Thomas, Sorry, I should have included the following fixes line: Fixes: a45b288ef21a("bond: support link status polling") Please add it to the commit message when applying if there are no other problems with the patch. Nelson. On 3/31/2016 6:40 AM, Thomas Monjalon wrote: > 2016-03-25 17:44, John Daley: >> From: Nelson Escobar >> >> Stopping then re-starting a bond interface containing slaves that >> used polling for link detection caused the bond to think all slave >> links were down and inactive. >> >> Move the start of the polling for link from slave_add() to >> bond_ethdev_start() and in bond_ethdev_stop() make sure we clear >> the last_link_status of the slaves. >> >> Signed-off-by: Nelson Escobar >> Signed-off-by: John Daley > > A "Fixes:" line would be appreciated to know the origin of the bug. > Thanks >
[dpdk-dev] [PATCH] net/enic: move link checking init to probe time
The enic DMAs link status information to the host and this requires a little setup. This setup was being done as a result of calling rte_eth_dev_start(). But applications expect to be able to check link status before calling rte_eth_dev_start(). This patch moves he link status setup to enic_init() which is called at device probe time so that link status can be checked anytime. Fixes: fefed3d1e62c ("enic: new driver") Signed-off-by: Nelson Escobar Reviewed-by: John Daley --- drivers/net/enic/enic_main.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index b4ca371..eb32ac1 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -430,7 +430,6 @@ int enic_enable(struct enic *enic) eth_dev->data->dev_link.link_speed = vnic_dev_port_speed(enic->vdev); eth_dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX; - vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */ if (enic_clsf_init(enic)) dev_warning(enic, "Init of hash table for clsf failed."\ @@ -820,7 +819,6 @@ int enic_disable(struct enic *enic) } vnic_dev_set_reset_flag(enic->vdev, 1); - vnic_dev_notify_unset(enic->vdev); for (i = 0; i < enic->wq_count; i++) vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); @@ -1022,6 +1020,9 @@ static void enic_dev_deinit(struct enic *enic) { struct rte_eth_dev *eth_dev = enic->rte_dev; + /* stop link status checking */ + vnic_dev_notify_unset(enic->vdev); + rte_free(eth_dev->data->mac_addrs); } @@ -1137,6 +1138,9 @@ static int enic_dev_init(struct enic *enic) vnic_dev_set_reset_flag(enic->vdev, 0); + /* set up link status checking */ + vnic_dev_notify_set(enic->vdev, -1); /* No Intr for notify */ + return 0; } -- 2.7.0