USB: fix Coding Style.
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / common_port / dwc_mem.c
1 /* Memory Debugging */
2 #ifdef DWC_DEBUG_MEMORY
3
4 #include "dwc_os.h"
5 #include "dwc_list.h"
6
7 struct allocation {
8         void *addr;
9         void *ctx;
10         char *func;
11         int line;
12         uint32_t size;
13         int dma;
14         DWC_CIRCLEQ_ENTRY(allocation) entry;
15 };
16
17 DWC_CIRCLEQ_HEAD(allocation_queue, allocation);
18
19 struct allocation_manager {
20         void *mem_ctx;
21         struct allocation_queue allocations;
22
23         /* statistics */
24         int num;
25         int num_freed;
26         int num_active;
27         uint32_t total;
28         uint32_t cur;
29         uint32_t max;
30 };
31
32 static struct allocation_manager *manager;
33
34 static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr,
35                           int dma)
36 {
37         struct allocation *a;
38
39         DWC_ASSERT(manager != NULL, "manager not allocated");
40
41         a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a));
42         if (!a) {
43                 return -DWC_E_NO_MEMORY;
44         }
45
46         a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1);
47         if (!a->func) {
48                 __DWC_FREE(manager->mem_ctx, a);
49                 return -DWC_E_NO_MEMORY;
50         }
51
52         DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1);
53         a->addr = addr;
54         a->ctx = ctx;
55         a->line = line;
56         a->size = size;
57         a->dma = dma;
58         DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry);
59
60         /* Update stats */
61         manager->num++;
62         manager->num_active++;
63         manager->total += size;
64         manager->cur += size;
65
66         if (manager->max < manager->cur) {
67                 manager->max = manager->cur;
68         }
69
70         return 0;
71 }
72
73 static struct allocation *find_allocation(void *ctx, void *addr)
74 {
75         struct allocation *a;
76
77         DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
78                 if (a->ctx == ctx && a->addr == addr) {
79                         return a;
80                 }
81         }
82
83         return NULL;
84 }
85
86 static void free_allocation(void *ctx, void *addr, char const *func, int line)
87 {
88         struct allocation *a = find_allocation(ctx, addr);
89
90         if (!a) {
91                 DWC_ASSERT(0,
92                            "Free of address %p that was never allocated or already freed %s:%d",
93                            addr, func, line);
94                 return;
95         }
96
97         DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry);
98
99         manager->num_active--;
100         manager->num_freed++;
101         manager->cur -= a->size;
102         __DWC_FREE(manager->mem_ctx, a->func);
103         __DWC_FREE(manager->mem_ctx, a);
104 }
105
106 int dwc_memory_debug_start(void *mem_ctx)
107 {
108         DWC_ASSERT(manager == NULL, "Memory debugging has already started\n");
109
110         if (manager) {
111                 return -DWC_E_BUSY;
112         }
113
114         manager = __DWC_ALLOC(mem_ctx, sizeof(*manager));
115         if (!manager) {
116                 return -DWC_E_NO_MEMORY;
117         }
118
119         DWC_CIRCLEQ_INIT(&manager->allocations);
120         manager->mem_ctx = mem_ctx;
121         manager->num = 0;
122         manager->num_freed = 0;
123         manager->num_active = 0;
124         manager->total = 0;
125         manager->cur = 0;
126         manager->max = 0;
127
128         return 0;
129 }
130
131 void dwc_memory_debug_stop(void)
132 {
133         struct allocation *a;
134
135         dwc_memory_debug_report();
136
137         DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
138                 DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line);
139                 free_allocation(a->ctx, a->addr, NULL, -1);
140         }
141
142         __DWC_FREE(manager->mem_ctx, manager);
143 }
144
145 void dwc_memory_debug_report(void)
146 {
147         struct allocation *a;
148
149         DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n");
150         DWC_PRINTF("Num Allocations = %d\n", manager->num);
151         DWC_PRINTF("Freed = %d\n", manager->num_freed);
152         DWC_PRINTF("Active = %d\n", manager->num_active);
153         DWC_PRINTF("Current Memory Used = %d\n", manager->cur);
154         DWC_PRINTF("Total Memory Used = %d\n", manager->total);
155         DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max);
156         DWC_PRINTF("Unfreed allocations:\n");
157
158         DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) {
159                 DWC_PRINTF("    addr=%p, size=%d from %s:%d, DMA=%d\n",
160                            a->addr, a->size, a->func, a->line, a->dma);
161         }
162 }
163
164 /* The replacement functions */
165 void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line)
166 {
167         void *addr = __DWC_ALLOC(mem_ctx, size);
168
169         if (!addr) {
170                 return NULL;
171         }
172
173         if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
174                 __DWC_FREE(mem_ctx, addr);
175                 return NULL;
176         }
177
178         return addr;
179 }
180
181 void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func,
182                              int line)
183 {
184         void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size);
185
186         if (!addr) {
187                 return NULL;
188         }
189
190         if (add_allocation(mem_ctx, size, func, line, addr, 0)) {
191                 __DWC_FREE(mem_ctx, addr);
192                 return NULL;
193         }
194
195         return addr;
196 }
197
198 void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line)
199 {
200         free_allocation(mem_ctx, addr, func, line);
201         __DWC_FREE(mem_ctx, addr);
202 }
203
204 void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr,
205                           char const *func, int line)
206 {
207         void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr);
208
209         if (!addr) {
210                 return NULL;
211         }
212
213         if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
214                 __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
215                 return NULL;
216         }
217
218         return addr;
219 }
220
221 void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size,
222                                  dwc_dma_t *dma_addr, char const *func, int line)
223 {
224         void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr);
225
226         if (!addr) {
227                 return NULL;
228         }
229
230         if (add_allocation(dma_ctx, size, func, line, addr, 1)) {
231                 __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr);
232                 return NULL;
233         }
234
235         return addr;
236 }
237
238 void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr,
239                         dwc_dma_t dma_addr, char const *func, int line)
240 {
241         free_allocation(dma_ctx, virt_addr, func, line);
242         __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr);
243 }
244
245 #endif /* DWC_DEBUG_MEMORY */