blob: 0cc423acb54503e38fca1f90a72465423e87ac31 [file] [log] [blame]
John Lo55bf5c92016-07-04 23:23:32 -04001From 2040a8f4e47d3bc4b7f0f11faa863a4bd8d8891d Mon Sep 17 00:00:00 2001
2From: Nelson Escobar <neescoba@cisco.com>
3Date: Thu, 23 Jun 2016 16:14:58 -0700
4Subject: [PATCH 23/25] net/enic: fix memory freeing
5
6enic_alloc_consistent() allocated memory, but enic_free_consistent()
7was an empty function, so allocated memory was never freed.
8
9This commit adds a list and lock to the enic structure to keep track
10of the memzones allocated in enic_alloc_consistent(), and
11enic_free_consistent() uses that information to properly free memory.
12
13Fixes: fefed3d1e62c ("enic: new driver")
14
15Signed-off-by: Nelson Escobar <neescoba@cisco.com>
16Reviewed-by: John Daley <johndale@cisco.com>
17---
18 drivers/net/enic/base/vnic_dev.c | 14 +++++------
19 drivers/net/enic/base/vnic_dev.h | 2 +-
20 drivers/net/enic/enic.h | 11 ++++++++
21 drivers/net/enic/enic_main.c | 54 ++++++++++++++++++++++++++++++++++------
22 4 files changed, 65 insertions(+), 16 deletions(-)
23
24diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c
25index e8a5028..fc2e4cc 100644
26--- a/drivers/net/enic/base/vnic_dev.c
27+++ b/drivers/net/enic/base/vnic_dev.c
28@@ -83,7 +83,7 @@ struct vnic_dev {
29 struct vnic_intr_coal_timer_info intr_coal_timer_info;
30 void *(*alloc_consistent)(void *priv, size_t size,
31 dma_addr_t *dma_handle, u8 *name);
32- void (*free_consistent)(struct rte_pci_device *hwdev,
33+ void (*free_consistent)(void *priv,
34 size_t size, void *vaddr,
35 dma_addr_t dma_handle);
36 };
37@@ -101,7 +101,7 @@ void *vnic_dev_priv(struct vnic_dev *vdev)
38 void vnic_register_cbacks(struct vnic_dev *vdev,
39 void *(*alloc_consistent)(void *priv, size_t size,
40 dma_addr_t *dma_handle, u8 *name),
41- void (*free_consistent)(struct rte_pci_device *hwdev,
42+ void (*free_consistent)(void *priv,
43 size_t size, void *vaddr,
44 dma_addr_t dma_handle))
45 {
46@@ -807,7 +807,7 @@ int vnic_dev_notify_unsetcmd(struct vnic_dev *vdev)
47 int vnic_dev_notify_unset(struct vnic_dev *vdev)
48 {
49 if (vdev->notify && !vnic_dev_in_reset(vdev)) {
50- vdev->free_consistent(vdev->pdev,
51+ vdev->free_consistent(vdev->priv,
52 sizeof(struct vnic_devcmd_notify),
53 vdev->notify,
54 vdev->notify_pa);
55@@ -924,16 +924,16 @@ void vnic_dev_unregister(struct vnic_dev *vdev)
56 {
57 if (vdev) {
58 if (vdev->notify)
59- vdev->free_consistent(vdev->pdev,
60+ vdev->free_consistent(vdev->priv,
61 sizeof(struct vnic_devcmd_notify),
62 vdev->notify,
63 vdev->notify_pa);
64 if (vdev->stats)
65- vdev->free_consistent(vdev->pdev,
66+ vdev->free_consistent(vdev->priv,
67 sizeof(struct vnic_stats),
68 vdev->stats, vdev->stats_pa);
69 if (vdev->fw_info)
70- vdev->free_consistent(vdev->pdev,
71+ vdev->free_consistent(vdev->priv,
72 sizeof(struct vnic_devcmd_fw_info),
73 vdev->fw_info, vdev->fw_info_pa);
74 kfree(vdev);
75@@ -1041,7 +1041,7 @@ int vnic_dev_classifier(struct vnic_dev *vdev, u8 cmd, u16 *entry,
76
77 ret = vnic_dev_cmd(vdev, CMD_ADD_FILTER, &a0, &a1, wait);
78 *entry = (u16)a0;
79- vdev->free_consistent(vdev->pdev, tlv_size, tlv_va, tlv_pa);
80+ vdev->free_consistent(vdev->priv, tlv_size, tlv_va, tlv_pa);
81 } else if (cmd == CLSF_DEL) {
82 a0 = *entry;
83 ret = vnic_dev_cmd(vdev, CMD_DEL_FILTER, &a0, &a1, wait);
84diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h
85index 113d6ac..689442f 100644
86--- a/drivers/net/enic/base/vnic_dev.h
87+++ b/drivers/net/enic/base/vnic_dev.h
88@@ -102,7 +102,7 @@ unsigned int vnic_dev_get_res_count(struct vnic_dev *vdev,
89 void vnic_register_cbacks(struct vnic_dev *vdev,
90 void *(*alloc_consistent)(void *priv, size_t size,
91 dma_addr_t *dma_handle, u8 *name),
92- void (*free_consistent)(struct rte_pci_device *hwdev,
93+ void (*free_consistent)(void *priv,
94 size_t size, void *vaddr,
95 dma_addr_t dma_handle));
96 void __iomem *vnic_dev_get_res(struct vnic_dev *vdev, enum vnic_res_type type,
97diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
98index d2de6ee..175adb8 100644
99--- a/drivers/net/enic/enic.h
100+++ b/drivers/net/enic/enic.h
101@@ -46,6 +46,8 @@
102 #include "vnic_rss.h"
103 #include "enic_res.h"
104 #include "cq_enet_desc.h"
105+#include <sys/queue.h>
106+#include <rte_spinlock.h>
107
108 #define DRV_NAME "enic_pmd"
109 #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Poll-mode Driver"
110@@ -96,6 +98,11 @@ struct enic_soft_stats {
111 rte_atomic64_t rx_packet_errors;
112 };
113
114+struct enic_memzone_entry {
115+ const struct rte_memzone *rz;
116+ LIST_ENTRY(enic_memzone_entry) entries;
117+};
118+
119 /* Per-instance private data structure */
120 struct enic {
121 struct enic *next;
122@@ -140,6 +147,10 @@ struct enic {
123 unsigned int intr_count;
124
125 struct enic_soft_stats soft_stats;
126+
127+ /* linked list storing memory allocations */
128+ LIST_HEAD(enic_memzone_list, enic_memzone_entry) memzone_list;
129+ rte_spinlock_t memzone_list_lock;
130 };
131
132 static inline unsigned int enic_sop_rq(__rte_unused struct enic *enic, unsigned int rq)
133diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
134index 43e4af1..0547f3b 100644
135--- a/drivers/net/enic/enic_main.c
136+++ b/drivers/net/enic/enic_main.c
137@@ -356,12 +356,14 @@ enic_alloc_rx_queue_mbufs(struct enic *enic, struct vnic_rq *rq)
138 }
139
140 static void *
141-enic_alloc_consistent(__rte_unused void *priv, size_t size,
142+enic_alloc_consistent(void *priv, size_t size,
143 dma_addr_t *dma_handle, u8 *name)
144 {
145 void *vaddr;
146 const struct rte_memzone *rz;
147 *dma_handle = 0;
148+ struct enic *enic = (struct enic *)priv;
149+ struct enic_memzone_entry *mze;
150
151 rz = rte_memzone_reserve_aligned((const char *)name,
152 size, SOCKET_ID_ANY, 0, ENIC_ALIGN);
153@@ -374,16 +376,49 @@ enic_alloc_consistent(__rte_unused void *priv, size_t size,
154 vaddr = rz->addr;
155 *dma_handle = (dma_addr_t)rz->phys_addr;
156
157+ mze = rte_malloc("enic memzone entry",
158+ sizeof(struct enic_memzone_entry), 0);
159+
160+ if (!mze) {
161+ pr_err("%s : Failed to allocate memory for memzone list\n",
162+ __func__);
163+ rte_memzone_free(rz);
164+ }
165+
166+ mze->rz = rz;
167+
168+ rte_spinlock_lock(&enic->memzone_list_lock);
169+ LIST_INSERT_HEAD(&enic->memzone_list, mze, entries);
170+ rte_spinlock_unlock(&enic->memzone_list_lock);
171+
172 return vaddr;
173 }
174
175 static void
176-enic_free_consistent(__rte_unused struct rte_pci_device *hwdev,
177- __rte_unused size_t size,
178- __rte_unused void *vaddr,
179- __rte_unused dma_addr_t dma_handle)
180+enic_free_consistent(void *priv,
181+ __rte_unused size_t size,
182+ void *vaddr,
183+ dma_addr_t dma_handle)
184 {
185- /* Nothing to be done */
186+ struct enic_memzone_entry *mze;
187+ struct enic *enic = (struct enic *)priv;
188+
189+ rte_spinlock_lock(&enic->memzone_list_lock);
190+ LIST_FOREACH(mze, &enic->memzone_list, entries) {
191+ if (mze->rz->addr == vaddr &&
192+ mze->rz->phys_addr == dma_handle)
193+ break;
194+ }
195+ if (mze == NULL) {
196+ rte_spinlock_unlock(&enic->memzone_list_lock);
197+ dev_warning(enic,
198+ "Tried to free memory, but couldn't find it in the memzone list\n");
199+ return;
200+ }
201+ LIST_REMOVE(mze, entries);
202+ rte_spinlock_unlock(&enic->memzone_list_lock);
203+ rte_memzone_free(mze->rz);
204+ rte_free(mze);
205 }
206
207 static void
208@@ -840,7 +875,7 @@ static int enic_set_rsskey(struct enic *enic)
209 rss_key_buf_pa,
210 sizeof(union vnic_rss_key));
211
212- enic_free_consistent(enic->pdev, sizeof(union vnic_rss_key),
213+ enic_free_consistent(enic, sizeof(union vnic_rss_key),
214 rss_key_buf_va, rss_key_buf_pa);
215
216 return err;
217@@ -867,7 +902,7 @@ static int enic_set_rsscpu(struct enic *enic, u8 rss_hash_bits)
218 rss_cpu_buf_pa,
219 sizeof(union vnic_rss_cpu));
220
221- enic_free_consistent(enic->pdev, sizeof(union vnic_rss_cpu),
222+ enic_free_consistent(enic, sizeof(union vnic_rss_cpu),
223 rss_cpu_buf_va, rss_cpu_buf_pa);
224
225 return err;
226@@ -1049,6 +1084,9 @@ int enic_probe(struct enic *enic)
227 goto err_out;
228 }
229
230+ LIST_INIT(&enic->memzone_list);
231+ rte_spinlock_init(&enic->memzone_list_lock);
232+
233 vnic_register_cbacks(enic->vdev,
234 enic_alloc_consistent,
235 enic_free_consistent);
236--
2372.7.0
238