1 /****************************************************************************
2 **+-----------------------------------------------------------------------+**
3 **| |**
4 **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
5 **| All rights reserved. |**
6 **| |**
7 **| Redistribution and use in source and binary forms, with or without |**
8 **| modification, are permitted provided that the following conditions |**
9 **| are met: |**
10 **| |**
11 **| * Redistributions of source code must retain the above copyright |**
12 **| notice, this list of conditions and the following disclaimer. |**
13 **| * Redistributions in binary form must reproduce the above copyright |**
14 **| notice, this list of conditions and the following disclaimer in |**
15 **| the documentation and/or other materials provided with the |**
16 **| distribution. |**
17 **| * Neither the name Texas Instruments nor the names of its |**
18 **| contributors may be used to endorse or promote products derived |**
19 **| from this software without specific prior written permission. |**
20 **| |**
21 **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |**
22 **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |**
23 **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
24 **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |**
25 **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
26 **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |**
27 **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
28 **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
29 **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |**
30 **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
31 **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |**
32 **| |**
33 **+-----------------------------------------------------------------------+**
34 ****************************************************************************/
35
36
37
38 #include "esta_drv.h"
39
40
41 static void tiwlan_profile_bus_access_start (void *os, unsigned);
42 static void tiwlan_profile_bus_access_end (void *os, unsigned);
43 static void tiwlan_profile_driver_entry_start (void *os, unsigned);
44 static void tiwlan_profile_driver_entry_end (void *os, unsigned);
45 static void tiwlan_profile_memory_alloc (void *os, unsigned);
46 static void tiwlan_profile_memory_free (void *os, unsigned);
47 static void tiwlan_profile_buf_alloc (void * os, unsigned);
48 static void tiwlan_profile_timer_create (void * os, unsigned);
49 static void tiwlan_profile_timer_destroy (void * os, unsigned);
50
51
tiwlan_profile_create(tiwlan_net_dev_t * drv)52 int tiwlan_profile_create (tiwlan_net_dev_t *drv)
53 {
54 drv->fpro [0] = NULL;
55 drv->fpro [1] = NULL;
56 drv->fpro [2] = NULL;
57 drv->fpro [3] = NULL;
58 drv->fpro [4] = tiwlan_profile_memory_alloc;
59 drv->fpro [5] = tiwlan_profile_memory_free;
60 drv->fpro [6] = tiwlan_profile_timer_create;
61 drv->fpro [7] = tiwlan_profile_timer_destroy;
62 drv->fpro [8] = tiwlan_profile_buf_alloc;
63
64 drv->cpu_usage_estimator_start_time = 0;
65 drv->cpu_usage_estimator_stop_time = 0;
66 drv->max_heap_bytes_allocated = 0;
67 drv->max_buf_bytes_allocated = 0;
68 drv->cur_heap_bytes_allocated = 0;
69 drv->max_number_of_timers = 0;
70 drv->cur_number_of_timers = 0;
71
72 return 0;
73 }
74
75
76 /* Call register profiler banchmark */
tiwlan_profile(tiwlan_net_dev_t * drv,unsigned bm,unsigned par)77 int tiwlan_profile (tiwlan_net_dev_t *drv, unsigned bm, unsigned par)
78 {
79 if (drv && bm < MAX_PROFILE_BM && drv->fpro [bm])
80 {
81 (*drv->fpro [bm]) (drv, par);
82 }
83
84 return 0;
85 }
86
87
88 /* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */
tiwlan_profile_bus_access_start(void * os,unsigned par)89 void tiwlan_profile_bus_access_start (void * os, unsigned par)
90 {
91 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
92
93 if (drv != NULL)
94 {
95 /* Save the current entry's start time */
96 drv->bus_driver_entry_start_time = os_timeStampUs (drv);
97 }
98 }
99
100
101 /* Starts CPU estimation for a bus driver entry */
tiwlan_profile_bus_access_end(void * os,unsigned par)102 void tiwlan_profile_bus_access_end (void * os, unsigned par)
103 {
104 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
105 unsigned current_entry_cpu_usage;
106
107 if (drv != NULL)
108 {
109 /* Save the current entry's start time */
110 current_entry_cpu_usage = os_timeStampUs (drv) - drv->bus_driver_entry_start_time;
111
112 /* Make sure that it is not a negative value */
113 if ((int)current_entry_cpu_usage < 0)
114 {
115 printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_cpu_time = %d\n\n\n",
116 __FUNCTION__, drv->bus_driver_entry_start_time, current_entry_cpu_usage);
117 }
118 /* Update the total time of driver CPU usage */
119 else
120 {
121 drv->total_us_of_bus_access_cpu_time += current_entry_cpu_usage;
122 }
123 }
124 }
125
126
127 /* Starts CPU estimation for a driver entry */
tiwlan_profile_driver_entry_start(void * os,unsigned par)128 void tiwlan_profile_driver_entry_start (void * os, unsigned par)
129 {
130 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
131
132 if (drv != NULL)
133 {
134 drv->driver_entry_start_time = os_timeStampUs (drv);
135 }
136 }
137
138
139 /* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */
tiwlan_profile_driver_entry_end(void * os,unsigned par)140 void tiwlan_profile_driver_entry_end (void * os, unsigned par)
141 {
142 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
143 unsigned current_entry_cpu_usage, driver_entry_end_time;
144
145 if (drv == NULL)
146 return;
147
148 /* Get the current entry's end time */
149 driver_entry_end_time = os_timeStampUs (drv);
150
151 /* Calculate the current entries CPU run time */
152 current_entry_cpu_usage = driver_entry_end_time - drv->driver_entry_start_time;
153
154 /* Make sure that it is not a negative value */
155 if ((int)current_entry_cpu_usage < 0)
156 {
157 printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_end=%u, entry_cpu_time = %d\n\n\n",
158 __FUNCTION__, drv->driver_entry_start_time, driver_entry_end_time, current_entry_cpu_usage);
159 }
160 /* Update the total time of driver CPU usage */
161 else
162 {
163 drv->total_us_of_cpu_time += current_entry_cpu_usage;
164 }
165 }
166
167
tiwlan_profile_memory_alloc(void * os,unsigned size)168 void tiwlan_profile_memory_alloc (void * os, unsigned size)
169 {
170 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
171
172 if (drv != NULL)
173 {
174 /* Increase current heap allocation counter */
175 drv->cur_heap_bytes_allocated += size;
176 /* Update maximum if execceded */
177 if (drv->max_heap_bytes_allocated < drv->cur_heap_bytes_allocated)
178 {
179 drv->max_heap_bytes_allocated = drv->cur_heap_bytes_allocated;
180 }
181 }
182 }
183
184
tiwlan_profile_memory_free(void * os,unsigned size)185 void tiwlan_profile_memory_free (void * os, unsigned size)
186 {
187 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
188
189 if (drv != NULL)
190 {
191 /* Decrease amount from heap allocation counter */
192 drv->cur_heap_bytes_allocated -= size;
193 /* Check for overflow */
194 if ((int)drv->cur_heap_bytes_allocated < 0)
195 {
196 printk("\n\n%s: memory heap allocation calculation corrupted. Size=%u, Current allocation = %d\n\n\n",
197 __FUNCTION__, size, drv->cur_heap_bytes_allocated);
198 drv->cur_heap_bytes_allocated = 0;
199 }
200 }
201 }
202
203
tiwlan_profile_buf_alloc(void * os,unsigned size)204 void tiwlan_profile_buf_alloc (void * os, unsigned size)
205 {
206 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
207
208 if (drv != NULL)
209 {
210 drv->max_buf_bytes_allocated += size;
211 }
212 }
213
214
tiwlan_profile_timer_create(void * os,unsigned par)215 void tiwlan_profile_timer_create (void * os, unsigned par)
216 {
217 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
218
219 if (drv)
220 {
221 /* Increase the current active timer counter */
222 drv->cur_number_of_timers ++;
223 /* Update maximum if execceded */
224 if (drv->max_number_of_timers < drv->cur_number_of_timers)
225 {
226 drv->max_number_of_timers = drv->cur_number_of_timers;
227 }
228 }
229 }
230
231
tiwlan_profile_timer_destroy(void * os,unsigned par)232 void tiwlan_profile_timer_destroy (void * os, unsigned par)
233 {
234 tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
235
236 if (drv)
237 {
238 /* Decrease the current active timer counter */
239 drv->cur_number_of_timers --;
240 }
241 }
242
243
244 /*
245 * Start CPU estimator
246 * NOTE: this function does not run in a driver context
247 */
tiwlan_profile_cpu_usage_estimator_start(tiwlan_net_dev_t * drv,unsigned int resolution)248 int tiwlan_profile_cpu_usage_estimator_start (tiwlan_net_dev_t * drv, unsigned int resolution)
249 {
250 /*
251 * Reset estimation parameters - no need for spin lock since
252 * estimator is not running
253 */
254 drv->total_us_of_cpu_time = 0;
255 drv->total_us_of_bus_access_cpu_time = 0;
256 drv->cpu_usage_estimator_start_time = os_timeStampUs (drv);
257 drv->cpu_usage_estimator_stop_time = 0;
258
259 /* Set the new resolution */
260 drv->cpu_usage_estimator_resolution = resolution;
261
262 /* Register profiler banchmarks */
263 drv->fpro [0] = tiwlan_profile_driver_entry_start;
264 drv->fpro [1] = tiwlan_profile_driver_entry_end;
265 drv->fpro [2] = tiwlan_profile_bus_access_start;
266 drv->fpro [3] = tiwlan_profile_bus_access_end;
267
268 return 0;
269 }
270
271
272 /*
273 * Stop CPU estimator and save the last CPU estimation
274 * NOTE: this function does not run in a driver context
275 */
tiwlan_profile_cpu_usage_estimator_stop(tiwlan_net_dev_t * drv)276 int tiwlan_profile_cpu_usage_estimator_stop (tiwlan_net_dev_t * drv)
277 {
278 drv->cpu_usage_estimator_stop_time = os_timeStampUs (drv);
279
280 /* Unregister profiler banchmarks */
281 drv->fpro [0] = NULL;
282 drv->fpro [1] = NULL;
283 drv->fpro [2] = NULL;
284 drv->fpro [3] = NULL;
285
286 return 0;
287 }
288
289
290 /*
291 * Reset CPU estimation
292 * NOTE: this function is not run in a driver context
293 */
tiwlan_profile_cpu_usage_estimator_reset(tiwlan_net_dev_t * drv)294 int tiwlan_profile_cpu_usage_estimator_reset (tiwlan_net_dev_t * drv)
295 {
296 /* Reset accumulated driver time and the last estimation */
297 drv->total_us_of_cpu_time = 0;
298 drv->total_us_of_bus_access_cpu_time = 0;
299 drv->cpu_usage_estimator_start_time = 0;
300 drv->cpu_usage_estimator_stop_time = 0;
301
302 return 0;
303 }
304
305
306 /* Print to the screen the latest resource usage and CPU estimation */
tiwlan_profile_report(tiwlan_net_dev_t * drv)307 int tiwlan_profile_report (tiwlan_net_dev_t *drv)
308 {
309 unsigned total_time, drv_cpu_usage = 0, bus_cpu_usage = 0;
310
311 printk ("\nDriver Resource Usage");
312 printk ("\n=====================");
313 printk ("\nMaximum Heap Memory Allocated: %u (bytes)", drv->max_heap_bytes_allocated);
314 printk ("\nCurrent Heap Memory Allocated: %u (bytes)", drv->cur_heap_bytes_allocated);
315 printk ("\nBuffer Memory Allocated: %u (bytes)", drv->max_buf_bytes_allocated);
316 printk ("\nFirmware Image Memory Allocated: %u (bytes)", (unsigned)drv->firmware_image.size);
317 printk ("\nEEPROM Image Memory Allocated: %u (bytes)", (unsigned)drv->eeprom_image.size);
318 printk ("\nMaximum Active Timers: %u", drv->max_number_of_timers);
319 printk ("\nCurrent Active Timers: %u", drv->cur_number_of_timers);
320
321 /* Check that the estimation has been started and stopped stopped */
322 if (drv->cpu_usage_estimator_stop_time != 0)
323 {
324 total_time = drv->cpu_usage_estimator_stop_time - drv->cpu_usage_estimator_start_time;
325
326 total_time /= 100;
327
328 if ((int)total_time > 0)
329 {
330 drv_cpu_usage = drv->total_us_of_cpu_time / total_time;
331 bus_cpu_usage = drv->total_us_of_bus_access_cpu_time / total_time;
332
333 printk ("\nTotal Test Run Time: %u (usec)", total_time);
334 printk ("\nTotal Driver Run Time: %u (usec)", drv->total_us_of_cpu_time);
335 printk ("\nTotal Bus Access Time: %u (usec)", drv->total_us_of_bus_access_cpu_time);
336 printk ("\nTotal CPU Usage: %u%%", drv_cpu_usage);
337 printk ("\nBus Access CPU Usage: %u%%", bus_cpu_usage);
338 printk ("\n");
339 }
340 }
341
342 return 0;
343 }
344
345