diff options
Diffstat (limited to 'dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch')
-rw-r--r-- | dpdk/dpdk-16.04_patches/0023-net-enic-fix-memory-freeing.patch | 238 |
1 files changed, 238 insertions, 0 deletions
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 00000000000..0cc423acb54 --- /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 <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 + |