• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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