From 55bf5c938585f0cc91b848ec37a5abfaf01f9515 Mon Sep 17 00:00:00 2001 From: John Lo Date: Mon, 4 Jul 2016 23:23:32 -0400 Subject: ENIC driver patches to address various issues Also clear x-bit for old patch files 0013-xxx and 0014-xxx. Change-Id: I217fdbfb32cef1ae575c668270d3baf593e688c6 Signed-off-by: John Lo --- ...vert-ixgbe-fix-packet-type-from-vector-Rx.patch | 0 ...T_RX_VLAN_PKT-iff-returned-packet-has-VLA.patch | 0 ...gfault-on-Tx-path-after-restarting-a-devi.patch | 46 ++++ ...-queue-initialization-after-restarting-a-.patch | 37 ++++ ...x-releasing-mbufs-when-tearing-down-Rx-qu.patch | 43 ++++ ...-net-enic-fix-crash-when-releasing-queues.patch | 61 ++++++ ...c-improve-out-of-resources-error-handling.patch | 67 ++++++ .../0023-net-enic-fix-memory-freeing.patch | 238 +++++++++++++++++++++ ...-enic-fix-Rx-scatter-with-multiple-queues.patch | 80 +++++++ .../0025-enic-fixup-of-Rx-Scatter-patch.patch | 169 +++++++++++++++ 10 files changed, 741 insertions(+) mode change 100755 => 100644 dpdk/dpdk-16.04_patches/0013-Revert-ixgbe-fix-packet-type-from-vector-Rx.patch mode change 100755 => 100644 dpdk/dpdk-16.04_patches/0014-enic-Set-PKT_RX_VLAN_PKT-iff-returned-packet-has-VLA.patch create mode 100644 dpdk/dpdk-16.04_patches/0018-enic-fix-segfault-on-Tx-path-after-restarting-a-devi.patch create mode 100644 dpdk/dpdk-16.04_patches/0019-enic-fix-Rx-queue-initialization-after-restarting-a-.patch create mode 100644 dpdk/dpdk-16.04_patches/0020-net-enic-fix-releasing-mbufs-when-tearing-down-Rx-qu.patch create mode 100644 dpdk/dpdk-16.04_patches/0021-net-enic-fix-crash-when-releasing-queues.patch create mode 100644 dpdk/dpdk-16.04_patches/0022-net-enic-improve-out-of-resources-error-handling.patch create mode 100644 dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch create mode 100644 dpdk/dpdk-16.04_patches/0024-net-enic-fix-Rx-scatter-with-multiple-queues.patch create mode 100644 dpdk/dpdk-16.04_patches/0025-enic-fixup-of-Rx-Scatter-patch.patch (limited to 'dpdk') diff --git a/dpdk/dpdk-16.04_patches/0013-Revert-ixgbe-fix-packet-type-from-vector-Rx.patch b/dpdk/dpdk-16.04_patches/0013-Revert-ixgbe-fix-packet-type-from-vector-Rx.patch old mode 100755 new mode 100644 diff --git a/dpdk/dpdk-16.04_patches/0014-enic-Set-PKT_RX_VLAN_PKT-iff-returned-packet-has-VLA.patch b/dpdk/dpdk-16.04_patches/0014-enic-Set-PKT_RX_VLAN_PKT-iff-returned-packet-has-VLA.patch old mode 100755 new mode 100644 diff --git a/dpdk/dpdk-16.04_patches/0018-enic-fix-segfault-on-Tx-path-after-restarting-a-devi.patch b/dpdk/dpdk-16.04_patches/0018-enic-fix-segfault-on-Tx-path-after-restarting-a-devi.patch new file mode 100644 index 00000000..10b66375 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0018-enic-fix-segfault-on-Tx-path-after-restarting-a-devi.patch @@ -0,0 +1,46 @@ +From 60971e62dcbb50a7ef1c3839e8b33b5aef6a48fe Mon Sep 17 00:00:00 2001 +From: John Daley +Date: Fri, 1 Jul 2016 12:24:45 -0700 +Subject: [PATCH 18/25] enic: fix segfault on Tx path after restarting a device + +If you stop then start a port that had already sent some packets, +there was a segfault due to not resetting the number of completed +sends to zero. + +Fixes: d5d882fe1a11 ("Tx path rewrite to reduce Host CPU overhead") + +Signed-off-by: Nelson Escobar +Reviewed-by: John Daley +--- + drivers/net/enic/base/vnic_wq.c | 2 ++ + drivers/net/enic/base/vnic_wq.h | 1 + + 2 files changed, 3 insertions(+) + +diff --git a/drivers/net/enic/base/vnic_wq.c b/drivers/net/enic/base/vnic_wq.c +index ccbbd61..7026bfe 100644 +--- a/drivers/net/enic/base/vnic_wq.c ++++ b/drivers/net/enic/base/vnic_wq.c +@@ -206,6 +206,8 @@ void vnic_wq_clean(struct vnic_wq *wq, + + wq->head_idx = 0; + wq->tail_idx = 0; ++ wq->last_completed_index = 0; ++ *((uint32_t *)wq->cqmsg_rz->addr) = 0; + + iowrite32(0, &wq->ctrl->fetch_index); + iowrite32(0, &wq->ctrl->posted_index); +diff --git a/drivers/net/enic/base/vnic_wq.h b/drivers/net/enic/base/vnic_wq.h +index 37c3ff9..faf3bfa 100644 +--- a/drivers/net/enic/base/vnic_wq.h ++++ b/drivers/net/enic/base/vnic_wq.h +@@ -38,6 +38,7 @@ + + #include "vnic_dev.h" + #include "vnic_cq.h" ++#include + + /* Work queue control */ + struct vnic_wq_ctrl { +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0019-enic-fix-Rx-queue-initialization-after-restarting-a-.patch b/dpdk/dpdk-16.04_patches/0019-enic-fix-Rx-queue-initialization-after-restarting-a-.patch new file mode 100644 index 00000000..3e107486 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0019-enic-fix-Rx-queue-initialization-after-restarting-a-.patch @@ -0,0 +1,37 @@ +From 8d336ba9cbcb4832b992201497afe07afcd4f2e1 Mon Sep 17 00:00:00 2001 +From: John Daley +Date: Fri, 1 Jul 2016 12:32:45 -0700 +Subject: [PATCH 19/25] enic: fix Rx queue initialization after restarting a + device + +If you stop then start a port that had already received some packets, +the NIC could fetch discriptors from the wrong location. This could +effectivly reduce the size of the Rx queue by a random amount and +cause packet drop or reduced performance. + +Reset the NIC fetch index to 0 when allocating and posting mbuf +addresses to the NIC. + +Fixes: 947d860c821f ("enic: improve Rx performance") + +Signed-off-by: John Daley +Reviewed-by: Nelson Escobar +--- + drivers/net/enic/enic_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c +index be17707..68532d3 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -346,6 +346,7 @@ enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq) + dev_debug(enic, "port=%u, qidx=%u, Write %u posted idx, %u sw held\n", + enic->port_id, rq->index, rq->posted_index, rq->rx_nb_hold); + iowrite32(rq->posted_index, &rq->ctrl->posted_index); ++ iowrite32(0, &rq->ctrl->fetch_index); + rte_rmb(); + + // printf("posted %d buffers to %s rq\n", rq->ring.desc_count, +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0020-net-enic-fix-releasing-mbufs-when-tearing-down-Rx-qu.patch b/dpdk/dpdk-16.04_patches/0020-net-enic-fix-releasing-mbufs-when-tearing-down-Rx-qu.patch new file mode 100644 index 00000000..47bcda23 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0020-net-enic-fix-releasing-mbufs-when-tearing-down-Rx-qu.patch @@ -0,0 +1,43 @@ +From 3f276178609472585a85fe440b549013a64d9327 Mon Sep 17 00:00:00 2001 +From: Nelson Escobar +Date: Tue, 14 Jun 2016 16:55:34 -0700 +Subject: [PATCH 20/25] net/enic: fix releasing mbufs when tearing down Rx + queue + +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: 947d860c821f ("enic: improve Rx performance") + +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 68532d3..56ec96e 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -91,7 +91,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; + +@@ -100,7 +100,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 + diff --git a/dpdk/dpdk-16.04_patches/0021-net-enic-fix-crash-when-releasing-queues.patch b/dpdk/dpdk-16.04_patches/0021-net-enic-fix-crash-when-releasing-queues.patch new file mode 100644 index 00000000..56d2c677 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0021-net-enic-fix-crash-when-releasing-queues.patch @@ -0,0 +1,61 @@ +From 38e154305ee5fd2ee454c19218ca144ffd1535f1 Mon Sep 17 00:00:00 2001 +From: John Daley +Date: Sat, 11 Jun 2016 10:27:04 -0700 +Subject: [PATCH 21/25] net/enic: fix crash when releasing queues + +If device configuration failed due to a lack of resources, such as +if more queues are requested than are available, the queue release +functions are called with NULL pointers which were being dereferenced. + +Skip releasing queues if they are NULL pointers. + +Fixes: fefed3d1e62c ("enic: new driver") + +Signed-off-by: John Daley +--- + drivers/net/enic/enic_main.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c +index 56ec96e..4e5594f 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -462,9 +462,15 @@ int enic_alloc_intr_resources(struct enic *enic) + + void enic_free_rq(void *rxq) + { +- struct vnic_rq *rq_sop = (struct vnic_rq *)rxq; +- struct enic *enic = vnic_dev_priv(rq_sop->vdev); +- struct vnic_rq *rq_data = &enic->rq[rq_sop->data_queue_idx]; ++ struct vnic_rq *rq_sop, *rq_data; ++ struct enic *enic; ++ ++ if (rxq == NULL) ++ return; ++ ++ rq_sop = (struct vnic_rq *)rxq; ++ enic = vnic_dev_priv(rq_sop->vdev); ++ rq_data = &enic->rq[rq_sop->data_queue_idx]; + + enic_rxmbuf_queue_release(enic, rq_sop); + if (rq_data->in_use) +@@ -657,9 +663,14 @@ err_exit: + + void enic_free_wq(void *txq) + { +- struct vnic_wq *wq = (struct vnic_wq *)txq; +- struct enic *enic = vnic_dev_priv(wq->vdev); ++ struct vnic_wq *wq; ++ struct enic *enic; ++ ++ if (txq == NULL) ++ return; + ++ wq = (struct vnic_wq *)txq; ++ enic = vnic_dev_priv(wq->vdev); + rte_memzone_free(wq->cqmsg_rz); + vnic_wq_free(wq); + vnic_cq_free(&enic->cq[enic->rq_count + wq->index]); +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0022-net-enic-improve-out-of-resources-error-handling.patch b/dpdk/dpdk-16.04_patches/0022-net-enic-improve-out-of-resources-error-handling.patch new file mode 100644 index 00000000..bf6df811 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0022-net-enic-improve-out-of-resources-error-handling.patch @@ -0,0 +1,67 @@ +From db0a30a2e61a3bf2f6cb8e74203dab84280b0419 Mon Sep 17 00:00:00 2001 +From: John Daley +Date: Sat, 11 Jun 2016 10:27:05 -0700 +Subject: [PATCH 22/25] net/enic: improve out of resources error handling + +If configuration fails due to lack of resources, be more specific +about which resources are lacking - work queues, read queues or +completion queues. Return -EINVAL instead of -1 if more queeues +are requested than are available. + +Fixes: fefed3d1e62c ("enic: new driver") + +Signed-off-by: John Daley +--- + drivers/net/enic/enic_main.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c +index 4e5594f..43e4af1 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -970,22 +970,32 @@ static void enic_dev_deinit(struct enic *enic) + int enic_set_vnic_res(struct enic *enic) + { + struct rte_eth_dev *eth_dev = enic->rte_dev; ++ int rc = 0; + +- if ((enic->rq_count < eth_dev->data->nb_rx_queues) || +- (enic->wq_count < eth_dev->data->nb_tx_queues)) { +- dev_err(dev, "Not enough resources configured, aborting\n"); +- return -1; ++ if (enic->rq_count < eth_dev->data->nb_rx_queues) { ++ dev_err(dev, "Not enough Receive queues. Requested:%u, Configured:%u\n", ++ eth_dev->data->nb_rx_queues, enic->rq_count); ++ rc = -EINVAL; ++ } ++ if (enic->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); ++ rc = -EINVAL; + } + +- enic->rq_count = eth_dev->data->nb_rx_queues; +- enic->wq_count = eth_dev->data->nb_tx_queues; + if (enic->cq_count < (enic->rq_count + enic->wq_count)) { +- dev_err(dev, "Not enough resources configured, aborting\n"); +- return -1; ++ dev_err(dev, "Not enough Completion queues. Required:%u, Configured:%u\n", ++ enic->rq_count + enic->wq_count, enic->cq_count); ++ rc = -EINVAL; + } + +- enic->cq_count = enic->rq_count + enic->wq_count; +- return 0; ++ if (rc == 0) { ++ enic->rq_count = eth_dev->data->nb_rx_queues; ++ enic->wq_count = eth_dev->data->nb_tx_queues; ++ enic->cq_count = enic->rq_count + enic->wq_count; ++ } ++ ++ return rc; + } + + static int enic_dev_init(struct enic *enic) +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch b/dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch new file mode 100644 index 00000000..0cc423ac --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch @@ -0,0 +1,238 @@ +From 2040a8f4e47d3bc4b7f0f11faa863a4bd8d8891d Mon Sep 17 00:00:00 2001 +From: Nelson Escobar +Date: Thu, 23 Jun 2016 16:14:58 -0700 +Subject: [PATCH 23/25] net/enic: fix memory freeing + +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 +--- + drivers/net/enic/base/vnic_dev.c | 14 +++++------ + drivers/net/enic/base/vnic_dev.h | 2 +- + drivers/net/enic/enic.h | 11 ++++++++ + drivers/net/enic/enic_main.c | 54 ++++++++++++++++++++++++++++++++++------ + 4 files changed, 65 insertions(+), 16 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 d2de6ee..175adb8 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" +@@ -96,6 +98,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,10 @@ struct enic { + unsigned int intr_count; + + struct enic_soft_stats soft_stats; ++ ++ /* linked list storing memory allocations */ ++ LIST_HEAD(enic_memzone_list, enic_memzone_entry) memzone_list; ++ rte_spinlock_t memzone_list_lock; + }; + + static inline unsigned int enic_sop_rq(__rte_unused struct enic *enic, unsigned int rq) +diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c +index 43e4af1..0547f3b 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -356,12 +356,14 @@ enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq) + } + + static void * +-enic_alloc_consistent(__rte_unused void *priv, size_t size, ++enic_alloc_consistent(void *priv, size_t size, + dma_addr_t *dma_handle, u8 *name) + { + void *vaddr; + const struct rte_memzone *rz; + *dma_handle = 0; ++ struct enic *enic = (struct enic *)priv; ++ struct enic_memzone_entry *mze; + + rz = rte_memzone_reserve_aligned((const char *)name, + size, SOCKET_ID_ANY, 0, ENIC_ALIGN); +@@ -374,16 +376,49 @@ enic_alloc_consistent(__rte_unused void *priv, size_t size, + vaddr = rz->addr; + *dma_handle = (dma_addr_t)rz->phys_addr; + ++ mze = rte_malloc("enic memzone entry", ++ sizeof(struct enic_memzone_entry), 0); ++ ++ if (!mze) { ++ pr_err("%s : Failed to allocate memory for memzone list\n", ++ __func__); ++ rte_memzone_free(rz); ++ } ++ ++ mze->rz = rz; ++ ++ rte_spinlock_lock(&enic->memzone_list_lock); ++ LIST_INSERT_HEAD(&enic->memzone_list, mze, entries); ++ rte_spinlock_unlock(&enic->memzone_list_lock); ++ + return vaddr; + } + + static void +-enic_free_consistent(__rte_unused struct rte_pci_device *hwdev, +- __rte_unused size_t size, +- __rte_unused void *vaddr, +- __rte_unused dma_addr_t dma_handle) ++enic_free_consistent(void *priv, ++ __rte_unused size_t size, ++ void *vaddr, ++ dma_addr_t dma_handle) + { +- /* Nothing to be done */ ++ struct enic_memzone_entry *mze; ++ struct enic *enic = (struct enic *)priv; ++ ++ rte_spinlock_lock(&enic->memzone_list_lock); ++ LIST_FOREACH(mze, &enic->memzone_list, entries) { ++ if (mze->rz->addr == vaddr && ++ mze->rz->phys_addr == dma_handle) ++ break; ++ } ++ if (mze == NULL) { ++ rte_spinlock_unlock(&enic->memzone_list_lock); ++ dev_warning(enic, ++ "Tried to free memory, but couldn't find it in the memzone list\n"); ++ return; ++ } ++ LIST_REMOVE(mze, entries); ++ rte_spinlock_unlock(&enic->memzone_list_lock); ++ rte_memzone_free(mze->rz); ++ rte_free(mze); + } + + static void +@@ -840,7 +875,7 @@ static int enic_set_rsskey(struct enic *enic) + rss_key_buf_pa, + sizeof(union vnic_rss_key)); + +- enic_free_consistent(enic->pdev, sizeof(union vnic_rss_key), ++ enic_free_consistent(enic, sizeof(union vnic_rss_key), + rss_key_buf_va, rss_key_buf_pa); + + return err; +@@ -867,7 +902,7 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits) + rss_cpu_buf_pa, + sizeof(union vnic_rss_cpu)); + +- enic_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu), ++ enic_free_consistent(enic, sizeof(union vnic_rss_cpu), + rss_cpu_buf_va, rss_cpu_buf_pa); + + return err; +@@ -1049,6 +1084,9 @@ int enic_probe(struct enic *enic) + goto err_out; + } + ++ LIST_INIT(&enic->memzone_list); ++ rte_spinlock_init(&enic->memzone_list_lock); ++ + vnic_register_cbacks(enic->vdev, + enic_alloc_consistent, + enic_free_consistent); +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0024-net-enic-fix-Rx-scatter-with-multiple-queues.patch b/dpdk/dpdk-16.04_patches/0024-net-enic-fix-Rx-scatter-with-multiple-queues.patch new file mode 100644 index 00000000..d581702d --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0024-net-enic-fix-Rx-scatter-with-multiple-queues.patch @@ -0,0 +1,80 @@ +From 658069b0c5994e260cd7d0a7dfc7f03d78dd4f5a Mon Sep 17 00:00:00 2001 +From: Nelson Escobar +Date: Tue, 28 Jun 2016 11:49:11 -0700 +Subject: [PATCH 24/25] net/enic: fix Rx scatter with multiple queues + +The Rx scatter patch failed to make a few changes and resulted in +problems when using multiple receive queues (RQs) 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: 856d7ba7ed22 ("net/enic: support scattered Rx") + +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 175adb8..8b0fa05 100644 +--- a/drivers/net/enic/enic.h ++++ b/drivers/net/enic/enic.h +@@ -165,7 +165,11 @@ static inline unsigned int enic_data_rq(__rte_unused struct enic *enic, unsigned + + 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 0547f3b..976c9da 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -252,19 +252,20 @@ void enic_init_vnic_resources(struct enic *enic) + vnic_dev_stats_clear(enic->vdev); + + for (index = 0; index < enic->rq_count; index++) { ++ cq_idx = enic_cq_rq(enic, enic_sop_rq(enic, index)); ++ + vnic_rq_init(&enic->rq[enic_sop_rq(enic, index)], +- enic_cq_rq(enic, index), ++ cq_idx, + error_interrupt_enable, + error_interrupt_offset); + + data_rq = &enic->rq[enic_data_rq(enic, 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 */, +@@ -896,7 +897,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(enic, i % enic->rq_count); + + err = enic_set_rss_cpu(enic, + rss_cpu_buf_pa, +-- +2.7.0 + diff --git a/dpdk/dpdk-16.04_patches/0025-enic-fixup-of-Rx-Scatter-patch.patch b/dpdk/dpdk-16.04_patches/0025-enic-fixup-of-Rx-Scatter-patch.patch new file mode 100644 index 00000000..e4e9f430 --- /dev/null +++ b/dpdk/dpdk-16.04_patches/0025-enic-fixup-of-Rx-Scatter-patch.patch @@ -0,0 +1,169 @@ +From 3131adb7f4195771bf54b294b2ee496055c3e65d Mon Sep 17 00:00:00 2001 +From: Nelson Escobar +Date: Tue, 14 Jun 2016 11:54:01 -0700 +Subject: [PATCH 25/25] enic: fixup of Rx Scatter patch + +A version of the Rx Scatter patch was used by VPP before the +patch was accepted in dpdk.org. This patch contains the change +made to the patch before it was accepted. + +Composed of internal dpdk devel patches: +enic: fixup rq count usage in wake of rx scatter +enic: update checks since RX scatter uses 2 VIC RQs per app RQ. +enic: fix packet type and flags when doing scatter Rx + +fixes: ENIC scatter RX + +Signed-off-by: Nelson Escobar +--- + drivers/net/enic/enic.h | 12 ++++++++++-- + drivers/net/enic/enic_ethdev.c | 7 +++++-- + drivers/net/enic/enic_main.c | 19 +++++++++++-------- + drivers/net/enic/enic_res.c | 5 +++-- + drivers/net/enic/enic_rxtx.c | 7 +++++-- + 5 files changed, 34 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h +index 8b0fa05..9cc9f0b 100644 +--- a/drivers/net/enic/enic.h ++++ b/drivers/net/enic/enic.h +@@ -55,8 +55,11 @@ + #define DRV_COPYRIGHT "Copyright 2008-2015 Cisco Systems, Inc" + + #define ENIC_WQ_MAX 8 +-#define ENIC_RQ_MAX 8 +-#define ENIC_CQ_MAX (ENIC_WQ_MAX + ENIC_RQ_MAX) ++/* With Rx scatter support, we use two RQs on VIC per RQ used by app. Both ++ * RQs use the same CQ. ++ */ ++#define ENIC_RQ_MAX 16 ++#define ENIC_CQ_MAX (ENIC_WQ_MAX + (ENIC_RQ_MAX / 2)) + #define ENIC_INTR_MAX (ENIC_CQ_MAX + 2) + + #define VLAN_ETH_HLEN 18 +@@ -163,6 +166,11 @@ static inline unsigned int enic_data_rq(__rte_unused struct enic *enic, unsigned + return rq * 2 + 1; + } + ++static inline unsigned int enic_vnic_rq_count(struct enic *enic) ++{ ++ return (enic->rq_count * 2); ++} ++ + static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq) + { + /* Scatter rx uses two receive queues together with one +diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c +index 697ff82..e5b84e1 100644 +--- a/drivers/net/enic/enic_ethdev.c ++++ b/drivers/net/enic/enic_ethdev.c +@@ -269,9 +269,12 @@ static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev, + struct enic *enic = pmd_priv(eth_dev); + + ENICPMD_FUNC_TRACE(); +- if (queue_idx >= ENIC_RQ_MAX) { ++ /* With Rx scatter support, two RQs are now used on VIC per RQ used ++ * by the application. ++ */ ++ if (queue_idx * 2 >= ENIC_RQ_MAX) { + dev_err(enic, +- "Max number of RX queues exceeded. Max is %d\n", ++ "Max number of RX queues exceeded. Max is %d. This PMD uses 2 RQs on VIC per RQ used by DPDK.\n", + ENIC_RQ_MAX); + return -EINVAL; + } +diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c +index 976c9da..ff94ee2 100644 +--- a/drivers/net/enic/enic_main.c ++++ b/drivers/net/enic/enic_main.c +@@ -133,7 +133,7 @@ static void enic_log_q_error(struct enic *enic) + error_status); + } + +- for (i = 0; i < enic->rq_count; i++) { ++ for (i = 0; i < enic_vnic_rq_count(enic); i++) { + error_status = vnic_rq_error_status(&enic->rq[i]); + if (error_status) + dev_err(enic, "RQ[%d] error_status %d\n", i, +@@ -486,7 +486,7 @@ int enic_alloc_intr_resources(struct enic *enic) + + dev_info(enic, "vNIC resources used: "\ + "wq %d rq %d cq %d intr %d\n", +- enic->wq_count, enic->rq_count, ++ enic->wq_count, enic_vnic_rq_count(enic), + enic->cq_count, enic->intr_count); + + err = vnic_intr_alloc(enic->vdev, &enic->intr, 0); +@@ -790,10 +790,12 @@ int enic_disable(struct enic *enic) + if (err) + return err; + } +- for (i = 0; i < enic->rq_count; i++) { +- err = vnic_rq_disable(&enic->rq[i]); +- if (err) +- return err; ++ for (i = 0; i < enic_vnic_rq_count(enic); i++) { ++ if (enic->rq[i].in_use) { ++ err = vnic_rq_disable(&enic->rq[i]); ++ if (err) ++ return err; ++ } + } + + vnic_dev_set_reset_flag(enic->vdev, 1); +@@ -802,8 +804,9 @@ int enic_disable(struct enic *enic) + for (i = 0; i < enic->wq_count; i++) + vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); + +- for (i = 0; i < enic->rq_count; i++) +- vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); ++ for (i = 0; i < enic_vnic_rq_count(enic); i++) ++ if (enic->rq[i].in_use) ++ vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); + for (i = 0; i < enic->cq_count; i++) + vnic_cq_clean(&enic->cq[i]); + vnic_intr_clean(&enic->intr); +diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c +index ebe379d..42edd84 100644 +--- a/drivers/net/enic/enic_res.c ++++ b/drivers/net/enic/enic_res.c +@@ -196,8 +196,9 @@ void enic_free_vnic_resources(struct enic *enic) + + for (i = 0; i < enic->wq_count; i++) + vnic_wq_free(&enic->wq[i]); +- for (i = 0; i < enic->rq_count; i++) +- vnic_rq_free(&enic->rq[i]); ++ for (i = 0; i < enic_vnic_rq_count(enic); i++) ++ if (enic->rq[i].in_use) ++ vnic_rq_free(&enic->rq[i]); + for (i = 0; i < enic->cq_count; i++) + vnic_cq_free(&enic->cq[i]); + vnic_intr_free(&enic->intr); +diff --git a/drivers/net/enic/enic_rxtx.c b/drivers/net/enic/enic_rxtx.c +index 463b954..c68bbfb 100644 +--- a/drivers/net/enic/enic_rxtx.c ++++ b/drivers/net/enic/enic_rxtx.c +@@ -326,8 +326,7 @@ enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, + + /* Fill in the rest of the mbuf */ + seg_length = enic_cq_rx_desc_n_bytes(&cqd); +- rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd); +- enic_cq_rx_to_pkt_flags(&cqd, rxmb); ++ + if (rq->is_sop) { + first_seg = rxmb; + first_seg->nb_segs = 1; +@@ -350,6 +349,10 @@ enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, + continue; + } + ++ /* cq rx flags are only valid if eop bit is set */ ++ first_seg->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd); ++ enic_cq_rx_to_pkt_flags(&cqd, first_seg); ++ + if (unlikely(packet_error)) { + rte_pktmbuf_free(first_seg); + rte_atomic64_inc(&enic->soft_stats.rx_packet_errors); +-- +2.7.0 + -- cgit 1.2.3-korg