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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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