0cc423acb54503e38fca1f90a72465423e87ac31
[vpp.git] / dpdk / dpdk-16.04_patches / 0023-net-enic-fix-memory-freeing.patch
1 From 2040a8f4e47d3bc4b7f0f11faa863a4bd8d8891d Mon Sep 17 00:00:00 2001
2 From: Nelson Escobar <neescoba@cisco.com>
3 Date: Thu, 23 Jun 2016 16:14:58 -0700
4 Subject: [PATCH 23/25] net/enic: fix memory freeing
5
6 enic_alloc_consistent() allocated memory, but enic_free_consistent()
7 was an empty function, so allocated memory was never freed.
8
9 This commit adds a list and lock to the enic structure to keep track
10 of the memzones allocated in enic_alloc_consistent(), and
11 enic_free_consistent() uses that information to properly free memory.
12
13 Fixes: fefed3d1e62c ("enic: new driver")
14
15 Signed-off-by: Nelson Escobar <neescoba@cisco.com>
16 Reviewed-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
24 diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c
25 index 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);
84 diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h
85 index 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,
97 diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
98 index 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)
133 diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
134 index 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 -- 
237 2.7.0
238