ENIC driver patches to address various issues 54/1854/2
authorJohn Lo <loj@cisco.com>
Tue, 5 Jul 2016 03:23:32 +0000 (23:23 -0400)
committerDamjan Marion <dmarion.lists@gmail.com>
Tue, 5 Jul 2016 16:21:35 +0000 (16:21 +0000)
Also clear x-bit for old patch files 0013-xxx and 0014-xxx.

Change-Id: I217fdbfb32cef1ae575c668270d3baf593e688c6
Signed-off-by: John Lo <loj@cisco.com>
dpdk/dpdk-16.04_patches/0013-Revert-ixgbe-fix-packet-type-from-vector-Rx.patch [changed mode: 0755->0644]
dpdk/dpdk-16.04_patches/0014-enic-Set-PKT_RX_VLAN_PKT-iff-returned-packet-has-VLA.patch [changed mode: 0755->0644]
dpdk/dpdk-16.04_patches/0018-enic-fix-segfault-on-Tx-path-after-restarting-a-devi.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0019-enic-fix-Rx-queue-initialization-after-restarting-a-.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0020-net-enic-fix-releasing-mbufs-when-tearing-down-Rx-qu.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0021-net-enic-fix-crash-when-releasing-queues.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0022-net-enic-improve-out-of-resources-error-handling.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0024-net-enic-fix-Rx-scatter-with-multiple-queues.patch [new file with mode: 0644]
dpdk/dpdk-16.04_patches/0025-enic-fixup-of-Rx-Scatter-patch.patch [new file with mode: 0644]

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 (file)
index 0000000..10b6637
--- /dev/null
@@ -0,0 +1,46 @@
+From 60971e62dcbb50a7ef1c3839e8b33b5aef6a48fe Mon Sep 17 00:00:00 2001
+From: John Daley <johndale@cisco.com>
+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 <neescoba@cisco.com>
+Reviewed-by: John Daley <johndale@cisco.com>
+---
+ 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 <rte_memzone.h>
+ /* 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 (file)
index 0000000..3e10748
--- /dev/null
@@ -0,0 +1,37 @@
+From 8d336ba9cbcb4832b992201497afe07afcd4f2e1 Mon Sep 17 00:00:00 2001
+From: John Daley <johndale@cisco.com>
+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 <johndale@cisco.com>
+Reviewed-by: Nelson Escobar <neescoba@cisco.com>
+---
+ 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 (file)
index 0000000..47bcda2
--- /dev/null
@@ -0,0 +1,43 @@
+From 3f276178609472585a85fe440b549013a64d9327 Mon Sep 17 00:00:00 2001
+From: Nelson Escobar <neescoba@cisco.com>
+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 <neescoba@cisco.com>
+Reviewed-by: John Daley <johndale@cisco.com>
+---
+ 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 (file)
index 0000000..56d2c67
--- /dev/null
@@ -0,0 +1,61 @@
+From 38e154305ee5fd2ee454c19218ca144ffd1535f1 Mon Sep 17 00:00:00 2001
+From: John Daley <johndale@cisco.com>
+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 <johndale@cisco.com>
+---
+ 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 (file)
index 0000000..bf6df81
--- /dev/null
@@ -0,0 +1,67 @@
+From db0a30a2e61a3bf2f6cb8e74203dab84280b0419 Mon Sep 17 00:00:00 2001
+From: John Daley <johndale@cisco.com>
+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 <johndale@cisco.com>
+---
+ 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 (file)
index 0000000..0cc423a
--- /dev/null
@@ -0,0 +1,238 @@
+From 2040a8f4e47d3bc4b7f0f11faa863a4bd8d8891d Mon Sep 17 00:00:00 2001
+From: Nelson Escobar <neescoba@cisco.com>
+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 <neescoba@cisco.com>
+Reviewed-by: John Daley <johndale@cisco.com>
+---
+ 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 <sys/queue.h>
++#include <rte_spinlock.h>
+ #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 (file)
index 0000000..d581702
--- /dev/null
@@ -0,0 +1,80 @@
+From 658069b0c5994e260cd7d0a7dfc7f03d78dd4f5a Mon Sep 17 00:00:00 2001
+From: Nelson Escobar <neescoba@cisco.com>
+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 <neescoba@cisco.com>
+Reviewed-by: John Daley <johndale@cisco.com>
+---
+ 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 (file)
index 0000000..e4e9f43
--- /dev/null
@@ -0,0 +1,169 @@
+From 3131adb7f4195771bf54b294b2ee496055c3e65d Mon Sep 17 00:00:00 2001
+From: Nelson Escobar <neescoba@cisco.com>
+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 <neescoba@cisco.com>
+---
+ 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
+