2 * Copyright (c) 2007-2008 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 /* Module Name : performance.c */
20 /* This module performance evaluation functions. */
25 /************************************************************************/
27 #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
30 static struct zsSummary zm_summary
;
31 static struct zsVariation zm_var
;
32 static struct zsThroughput zm_tp
;
34 void zfiPerformanceInit(zdev_t
* dev
)
38 zmw_get_wlan_dev(dev
);
40 zm_summary
.tick_base
= wd
->tick
;
41 zm_summary
.tx_msdu_count
= 0;
42 zm_summary
.tx_mpdu_count
= 0;
43 zm_summary
.rx_msdu_count
= 0;
44 zm_summary
.rx_mpdu_count
= 0;
45 zm_summary
.rx_broken_seq
= 0;
46 zm_summary
.rx_broken_sum
= 0;
47 zm_summary
.rx_seq_base
= 0;
48 zm_summary
.rx_broken_seq_dis
= 0;
49 zm_summary
.rx_duplicate_seq
= 0;
50 zm_summary
.rx_old_seq
= 0;
51 zm_summary
.reset_count
= 0;
52 zm_summary
.reset_sum
= 0;
53 zm_summary
.rx_lost_sum
= 0;
54 zm_summary
.rx_duplicate_error
= 0;
55 zm_summary
.rx_free
= 0;
56 zm_summary
.rx_amsdu_len
= 0;
57 zm_summary
.rx_flush
= 0;
58 zm_summary
.rx_clear
= 0;
59 zm_summary
.rx_reorder
= 0;
63 zm_var
.tx_msdu_tick
[i
] = zm_var
.tx_mpdu_tick
[i
] = 0;
64 zm_var
.rx_msdu_tick
[i
] = zm_var
.rx_mpdu_tick
[i
] = 0;
67 zfTimerSchedule(dev
, ZM_EVENT_TIMEOUT_PERFORMANCE
, 100);
69 zm_tp
.size
= ZM_TP_SIZE
;
70 zm_tp
.head
= zm_tp
.size
- 1;
72 for (i
=0; i
<zm_tp
.size
; i
++)
79 void zfiPerformanceGraph(zdev_t
* dev
)
83 zmw_get_wlan_dev(dev
);
85 for (i
=0; i
<(zm_tp
.size
-1); i
++)
87 zm_tp
.tx
[i
] = zm_tp
.tx
[i
+1];
88 zm_tp
.rx
[i
] = zm_tp
.rx
[i
+1];
90 zm_tp
.tx
[zm_tp
.size
-1] = zm_summary
.tx_mpdu_count
*1500*8/1000000;
91 zm_tp
.rx
[zm_tp
.size
-1] = zm_summary
.rx_msdu_count
*1500*8/1000000;
99 for (j
=0; j
<zm_tp
.size
; j
++)
101 if ((zm_tp
.tx
[j
]/10 == i
) && (zm_tp
.rx
[j
]/10 == i
))
105 else if (zm_tp
.tx
[j
]/10 == i
)
109 else if (zm_tp
.rx
[j
]/10 == i
)
118 s
[zm_tp
.size
+4] = '\0';
121 DbgPrint("000|__________________________________________________");
126 void zfiPerformanceRefresh(zdev_t
* dev
)
130 zmw_get_wlan_dev(dev
);
132 zfiDbgReadReg(dev
, 0x11772c);
134 zm_var
.tx_msdu_mean
= zm_summary
.tx_msdu_count
/ 100;
135 zm_var
.tx_mpdu_mean
= zm_summary
.tx_mpdu_count
/ 100;
136 zm_var
.rx_msdu_mean
= zm_summary
.rx_msdu_count
/ 100;
137 zm_var
.rx_mpdu_mean
= zm_summary
.rx_mpdu_count
/ 100;
139 zm_var
.tx_msdu_sum
= zm_var
.tx_mpdu_sum
= 0;
140 zm_var
.rx_msdu_sum
= zm_var
.rx_mpdu_sum
= 0;
141 zm_summary
.tx_idle_count
= zm_summary
.rx_idle_count
= 0;
142 for (i
=0; i
<100; i
++)
144 zm_var
.tx_msdu_sum
+= (zm_var
.tx_msdu_tick
[i
] * zm_var
.tx_msdu_tick
[i
]);
145 zm_var
.tx_mpdu_sum
+= (zm_var
.tx_mpdu_tick
[i
] * zm_var
.tx_mpdu_tick
[i
]);
146 zm_var
.rx_msdu_sum
+= (zm_var
.rx_msdu_tick
[i
] * zm_var
.rx_msdu_tick
[i
]);
147 zm_var
.rx_mpdu_sum
+= (zm_var
.rx_mpdu_tick
[i
] * zm_var
.rx_mpdu_tick
[i
]);
149 if (!zm_var
.tx_mpdu_tick
[i
]) zm_summary
.tx_idle_count
++;
150 if (!zm_var
.rx_mpdu_tick
[i
]) zm_summary
.rx_idle_count
++;
152 zm_var
.tx_msdu_var
= (zm_var
.tx_msdu_sum
/ 100) - (zm_var
.tx_msdu_mean
* zm_var
.tx_msdu_mean
);
153 zm_var
.tx_mpdu_var
= (zm_var
.tx_mpdu_sum
/ 100) - (zm_var
.tx_mpdu_mean
* zm_var
.tx_mpdu_mean
);
154 zm_var
.rx_msdu_var
= (zm_var
.rx_msdu_sum
/ 100) - (zm_var
.rx_msdu_mean
* zm_var
.rx_msdu_mean
);
155 zm_var
.rx_mpdu_var
= (zm_var
.rx_mpdu_sum
/ 100) - (zm_var
.rx_mpdu_mean
* zm_var
.rx_mpdu_mean
);
157 zm_summary
.tick_base
= wd
->tick
;
158 zm_summary
.rx_broken_sum
+= zm_summary
.rx_broken_seq
;
159 zm_summary
.rx_lost_sum
+= (zm_summary
.rx_broken_seq
- zm_summary
.rx_duplicate_seq
- zm_summary
.rx_old_seq
);
161 zfiPerformanceGraph(dev
);
163 DbgPrint("******************************************************\n");
164 DbgPrint("* TX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary
.tx_msdu_count
,
165 zm_var
.tx_msdu_var
, zm_summary
.tx_mpdu_count
, zm_var
.tx_mpdu_var
);
166 DbgPrint("* TX: idle=%5d,TxRate=%3d, PER=%5d\n", zm_summary
.tx_idle_count
,
167 wd
->CurrentTxRateKbps
/1000,
168 (u16_t
)wd
->PER
[wd
->sta
.oppositeInfo
[0].rcCell
.currentRate
]);
169 DbgPrint("* RX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary
.rx_msdu_count
,
170 zm_var
.rx_msdu_var
, zm_summary
.rx_mpdu_count
, zm_var
.rx_mpdu_var
);
171 DbgPrint("* RX: idle=%5d,RxRate=%3d,AMSDU=%5d\n", zm_summary
.rx_idle_count
,
172 wd
->CurrentRxRateKbps
/1000, zm_summary
.rx_amsdu_len
);
173 DbgPrint("* RX broken seq=%4d, distances=%4d, duplicates=%4d\n", zm_summary
.rx_broken_seq
,
174 zm_summary
.rx_broken_seq_dis
, zm_summary
.rx_duplicate_seq
);
175 DbgPrint("* RX old seq=%4d, lost=%4d, broken sum=%4d\n", zm_summary
.rx_old_seq
,
176 (zm_summary
.rx_broken_seq
- zm_summary
.rx_duplicate_seq
- zm_summary
.rx_old_seq
),
177 zm_summary
.rx_broken_sum
);
178 DbgPrint("* Rx lost sum=%4d,dup. error=%4d, free count=%4d\n", zm_summary
.rx_lost_sum
,
179 zm_summary
.rx_duplicate_error
, zm_summary
.rx_free
);
180 DbgPrint("* Rx flush sum=%4d, clear sum=%4d, reorder=%7d\n", zm_summary
.rx_flush
,
181 zm_summary
.rx_clear
, zm_summary
.rx_reorder
);
182 DbgPrint("* Firmware reset=%3d, reset sum=%4d\n", zm_summary
.reset_count
,
183 zm_summary
.reset_sum
);
184 DbgPrint("******************************************************\n\n");
186 zm_summary
.tx_msdu_count
= 0;
187 zm_summary
.tx_mpdu_count
= 0;
188 zm_summary
.rx_msdu_count
= 0;
189 zm_summary
.rx_mpdu_count
= 0;
190 zm_summary
.rx_broken_seq
= 0;
191 zm_summary
.rx_broken_seq_dis
= 0;
192 zm_summary
.rx_duplicate_seq
= 0;
193 zm_summary
.rx_old_seq
= 0;
194 zm_summary
.reset_count
= 0;
195 zm_summary
.rx_amsdu_len
= 0;
197 for (i
=0; i
<100; i
++)
199 zm_var
.tx_msdu_tick
[i
] = zm_var
.tx_mpdu_tick
[i
] = 0;
200 zm_var
.rx_msdu_tick
[i
] = zm_var
.rx_mpdu_tick
[i
] = 0;
203 zfTimerSchedule(dev
, ZM_EVENT_TIMEOUT_PERFORMANCE
, 100);
206 void zfiTxPerformanceMSDU(zdev_t
* dev
, u32_t tick
)
209 zm_summary
.tx_msdu_count
++;
211 index
= tick
- zm_summary
.tick_base
;
215 zm_var
.tx_msdu_tick
[index
]++;
219 //DbgPrint("wd->tick exceeded tick_base+100!\n");
223 void zfiRxPerformanceMSDU(zdev_t
* dev
, u32_t tick
)
226 zm_summary
.rx_msdu_count
++;
228 index
= tick
- zm_summary
.tick_base
;
232 zm_var
.rx_msdu_tick
[index
]++;
236 //DbgPrint("wd->tick exceeded tick_base+100!\n");
240 void zfiTxPerformanceMPDU(zdev_t
* dev
, u32_t tick
)
243 zm_summary
.tx_mpdu_count
++;
245 index
= tick
- zm_summary
.tick_base
;
249 zm_var
.tx_mpdu_tick
[index
]++;
253 //DbgPrint("wd->tick exceeded tick_base+100!\n");
257 #ifndef ZM_INT_USE_EP2_HEADER_SIZE
258 #define ZM_INT_USE_EP2_HEADER_SIZE 12
260 void zfiRxPerformanceMPDU(zdev_t
* dev
, zbuf_t
* buf
)
269 zmw_get_wlan_dev(dev
);
271 len
= zfwBufGetSize(dev
, buf
);
272 mpduInd
= zmw_rx_buf_readb(dev
, buf
, len
-1);
273 /* First MPDU or Single MPDU */
274 if(((mpduInd
& 0x30) == 0x00) || ((mpduInd
& 0x30) == 0x20))
275 //if ((mpduInd & 0x10) == 0x00)
277 plcpHdrLen
= 12; // PLCP header length
281 if (zmw_rx_buf_readh(dev
, buf
, 4) == wd
->macAddr
[0] &&
282 zmw_rx_buf_readh(dev
, buf
, 6) == wd
->macAddr
[1] &&
283 zmw_rx_buf_readh(dev
, buf
, 8) == wd
->macAddr
[2]) {
286 else if (zmw_rx_buf_readh(dev
, buf
, 16) == wd
->macAddr
[0] &&
287 zmw_rx_buf_readh(dev
, buf
, 18) == wd
->macAddr
[1] &&
288 zmw_rx_buf_readh(dev
, buf
, 20) == wd
->macAddr
[2]){
296 frameCtrl
= zmw_rx_buf_readb(dev
, buf
, plcpHdrLen
+ 0);
297 frameType
= frameCtrl
& 0xf;
299 if (frameType
!= ZM_WLAN_DATA_FRAME
)
304 zm_summary
.rx_mpdu_count
++;
306 index
= wd
->tick
- zm_summary
.tick_base
;
310 zm_var
.rx_mpdu_tick
[index
]++;
314 //DbgPrint("wd->tick exceeded tick_base+100!\n");
318 void zfiRxPerformanceSeq(zdev_t
* dev
, zbuf_t
* buf
)
322 u16_t old_dis
= zm_summary
.rx_broken_seq_dis
;
323 //sys_time = KeQueryPerformanceCounter(&freq);
325 seq_no
= zmw_rx_buf_readh(dev
, buf
, offset
+22) >> 4;
327 ZM_SEQ_DEBUG("Out %5d\n", seq_no
);
329 if (seq_no
< zm_summary
.rx_seq_base
)
333 if (zm_summary
.rx_seq_base
!= 4095)
335 zm_summary
.rx_broken_seq
++;
336 ZM_SEQ_DEBUG("Broken seq");
337 zm_summary
.rx_broken_seq_dis
+=(4096 - zm_summary
.rx_seq_base
);
340 else if ((seq_no
< 300) && (zm_summary
.rx_seq_base
> 3800))
342 zm_summary
.rx_broken_seq
++;
343 ZM_SEQ_DEBUG("Broken seq");
344 zm_summary
.rx_broken_seq_dis
+=(4096 - zm_summary
.rx_seq_base
+ seq_no
);
348 zm_summary
.rx_broken_seq
++;
349 ZM_SEQ_DEBUG("Broken seq");
350 zm_summary
.rx_broken_seq_dis
+=(zm_summary
.rx_seq_base
- seq_no
);
351 zm_summary
.rx_old_seq
++;
356 if (seq_no
!= (zm_summary
.rx_seq_base
+ 1))
358 if ((seq_no
> 3800) && (zm_summary
.rx_seq_base
< 300))
360 zm_summary
.rx_broken_seq
++;
361 ZM_SEQ_DEBUG("Broken seq");
362 zm_summary
.rx_broken_seq_dis
+=(4096 - seq_no
+ zm_summary
.rx_seq_base
);
363 zm_summary
.rx_old_seq
++;
367 zm_summary
.rx_broken_seq
++;
368 ZM_SEQ_DEBUG("Broken seq");
369 zm_summary
.rx_broken_seq_dis
+=(seq_no
- zm_summary
.rx_seq_base
);
373 if (seq_no
== zm_summary
.rx_seq_base
)
375 zm_summary
.rx_duplicate_seq
++;
378 if ((zm_summary
.rx_broken_seq_dis
- old_dis
) > 100)
380 DbgPrint("* seq_no=%4d, base_seq=%4d, dis_diff=%4d", seq_no
,
381 zm_summary
.rx_seq_base
, zm_summary
.rx_broken_seq_dis
- old_dis
);
383 zm_summary
.rx_seq_base
= seq_no
;
386 void zfiRxPerformanceReg(zdev_t
* dev
, u32_t reg
, u32_t rsp
)
388 zm_summary
.reset_count
= (u16_t
)rsp
- zm_summary
.reset_sum
;
389 zm_summary
.reset_sum
= (u16_t
)rsp
;
392 void zfiRxPerformanceDup(zdev_t
* dev
, zbuf_t
* buf1
, zbuf_t
* buf2
)
394 u16_t seq_no1
, seq_no2
;
396 seq_no1
= zmw_rx_buf_readh(dev
, buf1
, 22) >> 4;
397 seq_no2
= zmw_rx_buf_readh(dev
, buf2
, 22) >> 4;
398 if (seq_no1
!= seq_no2
)
400 zm_summary
.rx_duplicate_error
++;
404 void zfiRxPerformanceFree(zdev_t
* dev
, zbuf_t
* buf
)
406 zm_summary
.rx_free
++;
409 void zfiRxPerformanceAMSDU(zdev_t
* dev
, zbuf_t
* buf
, u16_t len
)
411 if (zm_summary
.rx_amsdu_len
< len
)
413 zm_summary
.rx_amsdu_len
= len
;
416 void zfiRxPerformanceFlush(zdev_t
* dev
)
418 zm_summary
.rx_flush
++;
421 void zfiRxPerformanceClear(zdev_t
* dev
)
423 zm_summary
.rx_clear
++;
424 ZM_SEQ_DEBUG("RxClear");
427 void zfiRxPerformanceReorder(zdev_t
* dev
)
429 zm_summary
.rx_reorder
++;
431 #endif /* end of ZM_ENABLE_PERFORMANCE_EVALUATION */