Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: add max lossless throughput per rate

This patch adds the new statistic "maximum possible lossless
throughput" to Minstrels and Minstrel-HTs rc_stats (in debugfs). This
enables comprehensive comparison between current per-rate throughput
and max. achievable per-rate throughput.

Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Acked-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Thomas Huehn and committed by
Johannes Berg
50e55a8e 6a27b2c4

+93 -69
+19 -8
net/mac80211/rc80211_minstrel.c
··· 70 70 } 71 71 72 72 /* return current EMWA throughput */ 73 - int minstrel_get_tp_avg(struct minstrel_rate *mr) 73 + int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma) 74 74 { 75 75 int usecs; 76 76 ··· 81 81 /* reset thr. below 10% success */ 82 82 if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) 83 83 return 0; 84 + 85 + if (prob_ewma > MINSTREL_FRAC(90, 100)) 86 + return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); 84 87 else 85 - return MINSTREL_TRUNC(mr->stats.prob_ewma * (100000 / usecs)); 88 + return MINSTREL_TRUNC(100000 * (prob_ewma / usecs)); 86 89 } 87 90 88 91 /* find & sort topmost throughput rates */ ··· 93 90 minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) 94 91 { 95 92 int j = MAX_THR_RATES; 93 + struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats; 94 + struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; 96 95 97 - while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) > 98 - minstrel_get_tp_avg(&mi->r[tp_list[j - 1]]))) 96 + while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) > 97 + minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) { 99 98 j--; 99 + tmp_mrs = &mi->r[tp_list[j - 1]].stats; 100 + } 100 101 101 102 if (j < MAX_THR_RATES - 1) 102 103 memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); ··· 191 184 for (i = 0; i < mi->n_rates; i++) { 192 185 struct minstrel_rate *mr = &mi->r[i]; 193 186 struct minstrel_rate_stats *mrs = &mi->r[i].stats; 187 + struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; 194 188 195 189 /* Update success probabilities per rate */ 196 190 minstrel_calc_rate_stats(mrs); ··· 220 212 * (2) if all success probabilities < 95%, the rate with 221 213 * highest success probability is chosen as max_prob_rate */ 222 214 if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { 223 - tmp_cur_tp = minstrel_get_tp_avg(mr); 224 - tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate]); 215 + tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma); 216 + tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate], 217 + tmp_mrs->prob_ewma); 225 218 if (tmp_cur_tp >= tmp_prob_tp) 226 219 tmp_prob_rate = i; 227 220 } else { 228 - if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma) 221 + if (mrs->prob_ewma >= tmp_mrs->prob_ewma) 229 222 tmp_prob_rate = i; 230 223 } 231 224 } ··· 693 684 static u32 minstrel_get_expected_throughput(void *priv_sta) 694 685 { 695 686 struct minstrel_sta_info *mi = priv_sta; 687 + struct minstrel_rate_stats *tmp_mrs; 696 688 int idx = mi->max_tp_rate[0]; 697 689 int tmp_cur_tp; 698 690 699 691 /* convert pkt per sec in kbps (1200 is the average pkt size used for 700 692 * computing cur_tp 701 693 */ 702 - tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx]); 694 + tmp_mrs = &mi->r[idx].stats; 695 + tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma); 703 696 tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; 704 697 705 698 return tmp_cur_tp;
+1 -1
net/mac80211/rc80211_minstrel.h
··· 134 134 135 135 /* Recalculate success probabilities and counters for a given rate using EWMA */ 136 136 void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); 137 - int minstrel_get_tp_avg(struct minstrel_rate *mr); 137 + int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma); 138 138 139 139 /* debugfs */ 140 140 int minstrel_stats_open(struct inode *inode, struct file *file);
+13 -9
net/mac80211/rc80211_minstrel_debugfs.c
··· 75 75 { 76 76 struct minstrel_sta_info *mi = inode->i_private; 77 77 struct minstrel_debugfs_info *ms; 78 - unsigned int i, tp_avg, prob, eprob; 78 + unsigned int i, tp_max, tp_avg, prob, eprob; 79 79 char *p; 80 80 81 81 ms = kmalloc(2048, GFP_KERNEL); ··· 85 85 file->private_data = ms; 86 86 p = ms->buf; 87 87 p += sprintf(p, "\n"); 88 - p += sprintf(p, "best _______rate_____ __statistics__ " 88 + p += sprintf(p, "best __________rate_________ __statistics__ " 89 89 "________last_______ ______sum-of________\n"); 90 - p += sprintf(p, "rate [name idx airtime] [ ø(tp) ø(prob)] " 90 + p += sprintf(p, "rate [name idx airtime max_tp] [ ø(tp) ø(prob)] " 91 91 "[prob.|retry|suc|att] [#success | #attempts]\n"); 92 92 93 93 for (i = 0; i < mi->n_rates; i++) { ··· 103 103 p += sprintf(p, " %3u%s ", mr->bitrate / 2, 104 104 (mr->bitrate & 1 ? ".5" : " ")); 105 105 p += sprintf(p, "%3u ", i); 106 - p += sprintf(p, "%6u ", mr->perfect_tx_time); 106 + p += sprintf(p, "%6u ", mr->perfect_tx_time); 107 107 108 - tp_avg = minstrel_get_tp_avg(mr); 108 + tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 109 + tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); 109 110 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 110 111 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 111 112 112 - p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u %3u" 113 + p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u %3u" 113 114 " %3u %-3u %9llu %-9llu\n", 115 + tp_max / 10, tp_max % 10, 114 116 tp_avg / 10, tp_avg % 10, 115 117 eprob / 10, eprob % 10, 116 118 prob / 10, prob % 10, ··· 146 144 { 147 145 struct minstrel_sta_info *mi = inode->i_private; 148 146 struct minstrel_debugfs_info *ms; 149 - unsigned int i, tp_avg, prob, eprob; 147 + unsigned int i, tp_max, tp_avg, prob, eprob; 150 148 char *p; 151 149 152 150 ms = kmalloc(2048, GFP_KERNEL); ··· 171 169 p += sprintf(p, "%u,", i); 172 170 p += sprintf(p, "%u,",mr->perfect_tx_time); 173 171 174 - tp_avg = minstrel_get_tp_avg(mr); 172 + tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 173 + tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); 175 174 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 176 175 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 177 176 178 - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," 177 + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," 179 178 "%llu,%llu,%d,%d\n", 179 + tp_max / 10, tp_max % 10, 180 180 tp_avg / 10, tp_avg % 10, 181 181 eprob / 10, eprob % 10, 182 182 prob / 10, prob % 10,
+44 -40
net/mac80211/rc80211_minstrel_ht.c
··· 318 318 * account the expected number of retransmissions and their expected length 319 319 */ 320 320 int 321 - minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate) 321 + minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, 322 + int prob_ewma) 322 323 { 323 - struct minstrel_rate_stats *mrs; 324 324 unsigned int nsecs = 0; 325 - unsigned int tmp_prob_ewma; 326 - 327 - mrs = &mi->groups[group].rates[rate]; 328 - tmp_prob_ewma = mrs->prob_ewma; 329 325 330 326 /* do not account throughput if sucess prob is below 10% */ 331 - if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) 327 + if (prob_ewma < MINSTREL_FRAC(10, 100)) 332 328 return 0; 333 - 334 - /* 335 - * For the throughput calculation, limit the probability value to 90% to 336 - * account for collision related packet error rate fluctuation 337 - */ 338 - if (mrs->prob_ewma > MINSTREL_FRAC(90, 100)) 339 - tmp_prob_ewma = MINSTREL_FRAC(90, 100); 340 329 341 330 if (group != MINSTREL_CCK_GROUP) 342 331 nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); 343 332 344 333 nsecs += minstrel_mcs_groups[group].duration[rate]; 345 334 346 - /* prob is scaled - see MINSTREL_FRAC above */ 347 - return MINSTREL_TRUNC(100000 * ((tmp_prob_ewma * 1000) / nsecs)); 335 + /* 336 + * For the throughput calculation, limit the probability value to 90% to 337 + * account for collision related packet error rate fluctuation 338 + * (prob is scaled - see MINSTREL_FRAC above) 339 + */ 340 + if (prob_ewma > MINSTREL_FRAC(90, 100)) 341 + return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000) 342 + / nsecs)); 343 + else 344 + return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs)); 348 345 } 349 346 350 347 /* ··· 361 364 362 365 cur_group = index / MCS_GROUP_RATES; 363 366 cur_idx = index % MCS_GROUP_RATES; 364 - cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx); 365 367 cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma; 368 + cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob); 366 369 367 370 do { 368 371 tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; 369 372 tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; 370 - tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx); 371 373 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 374 + tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, 375 + tmp_prob); 372 376 if (cur_tp_avg < tmp_tp_avg || 373 377 (cur_tp_avg == tmp_tp_avg && cur_prob <= tmp_prob)) 374 378 break; ··· 394 396 struct minstrel_rate_stats *mrs; 395 397 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; 396 398 int max_tp_group, cur_tp_avg, cur_group, cur_idx; 397 - int max_group_prob_rate_group, max_group_prob_rate_idx; 398 - int max_group_prob_rate_tp_avg; 399 + int max_gpr_group, max_gpr_idx; 400 + int max_gpr_tp_avg, max_gpr_prob; 399 401 400 402 cur_group = index / MCS_GROUP_RATES; 401 403 cur_idx = index % MCS_GROUP_RATES; ··· 404 406 405 407 tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; 406 408 tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; 407 - tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx); 408 409 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 410 + tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 409 411 410 412 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from 411 413 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ ··· 415 417 return; 416 418 417 419 if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { 418 - cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx); 420 + cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, 421 + mrs->prob_ewma); 419 422 if (cur_tp_avg > tmp_tp_avg) 420 423 mi->max_prob_rate = index; 421 424 422 - max_group_prob_rate_group = mg->max_group_prob_rate / 423 - MCS_GROUP_RATES; 424 - max_group_prob_rate_idx = mg->max_group_prob_rate % 425 - MCS_GROUP_RATES; 426 - max_group_prob_rate_tp_avg = minstrel_ht_get_tp_avg(mi, 427 - max_group_prob_rate_group, 428 - max_group_prob_rate_idx); 429 - if (cur_tp_avg > max_group_prob_rate_tp_avg) 425 + max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; 426 + max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; 427 + max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma; 428 + max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group, 429 + max_gpr_idx, 430 + max_gpr_prob); 431 + if (cur_tp_avg > max_gpr_tp_avg) 430 432 mg->max_group_prob_rate = index; 431 433 } else { 432 434 if (mrs->prob_ewma > tmp_prob) ··· 448 450 u16 tmp_mcs_tp_rate[MAX_THR_RATES], 449 451 u16 tmp_cck_tp_rate[MAX_THR_RATES]) 450 452 { 451 - unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp; 453 + unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob; 452 454 int i; 453 455 454 456 tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; 455 457 tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; 456 - tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx); 458 + tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 459 + tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 457 460 458 461 tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; 459 462 tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; 460 - tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx); 463 + tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; 464 + tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 461 465 462 466 if (tmp_cck_tp > tmp_mcs_tp) { 463 467 for(i = 0; i < MAX_THR_RATES; i++) { ··· 478 478 minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi) 479 479 { 480 480 struct minstrel_mcs_group_data *mg; 481 - int tmp_max_streams, group, tmp_idx; 481 + int tmp_max_streams, group, tmp_idx, tmp_prob; 482 482 int tmp_tp = 0; 483 483 484 484 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / ··· 489 489 continue; 490 490 491 491 tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; 492 + tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma; 492 493 493 - if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx) && 494 + if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && 494 495 (minstrel_mcs_groups[group].streams < tmp_max_streams)) { 495 496 mi->max_prob_rate = mg->max_group_prob_rate; 496 497 tmp_tp = minstrel_ht_get_tp_avg(mi, group, 497 - tmp_idx); 498 + tmp_idx, 499 + tmp_prob); 498 500 } 499 501 } 500 502 } ··· 515 513 { 516 514 struct minstrel_mcs_group_data *mg; 517 515 struct minstrel_rate_stats *mrs; 518 - int group, i, j; 516 + int group, i, j, cur_prob; 519 517 u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; 520 518 u16 tmp_cck_tp_rate[MAX_THR_RATES], index; 521 519 ··· 557 555 mrs = &mg->rates[i]; 558 556 mrs->retry_updated = false; 559 557 minstrel_calc_rate_stats(mrs); 558 + cur_prob = mrs->prob_ewma; 560 559 561 - if (minstrel_ht_get_tp_avg(mi, group, i) == 0) 560 + if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) 562 561 continue; 563 562 564 563 /* Find max throughput rate set */ ··· 1318 1315 { 1319 1316 struct minstrel_ht_sta_priv *msp = priv_sta; 1320 1317 struct minstrel_ht_sta *mi = &msp->ht; 1321 - int i, j, tp_avg; 1318 + int i, j, prob, tp_avg; 1322 1319 1323 1320 if (!msp->is_ht) 1324 1321 return mac80211_minstrel.get_expected_throughput(priv_sta); 1325 1322 1326 1323 i = mi->max_tp_rate[0] / MCS_GROUP_RATES; 1327 1324 j = mi->max_tp_rate[0] % MCS_GROUP_RATES; 1325 + prob = mi->groups[i].rates[j].prob_ewma; 1328 1326 1329 1327 /* convert tp_avg from pkt per second in kbps */ 1330 - tp_avg = minstrel_ht_get_tp_avg(mi, i, j) * AVG_PKT_SIZE * 8 / 1024; 1328 + tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * AVG_PKT_SIZE * 8 / 1024; 1331 1329 1332 1330 return tp_avg; 1333 1331 }
+2 -1
net/mac80211/rc80211_minstrel_ht.h
··· 121 121 122 122 void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 123 123 void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta); 124 - int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate); 124 + int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, 125 + int prob_ewma); 125 126 126 127 #endif
+14 -10
net/mac80211/rc80211_minstrel_ht_debugfs.c
··· 19 19 minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) 20 20 { 21 21 const struct mcs_group *mg; 22 - unsigned int j, tp_avg, prob, eprob, tx_time; 22 + unsigned int j, tp_max, tp_avg, prob, eprob, tx_time; 23 23 char htmode = '2'; 24 24 char gimode = 'L'; 25 25 u32 gflags; ··· 79 79 80 80 /* tx_time[rate(i)] in usec */ 81 81 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); 82 - p += sprintf(p, "%6u ", tx_time); 82 + p += sprintf(p, "%6u ", tx_time); 83 83 84 - tp_avg = minstrel_ht_get_tp_avg(mi, i, j); 84 + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); 85 + tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); 85 86 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 86 87 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 87 88 88 - p += sprintf(p, "%4u.%1u %3u.%1u %3u.%1u " 89 + p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u " 89 90 "%3u %3u %-3u %9llu %-9llu\n", 91 + tp_max / 10, tp_max % 10, 90 92 tp_avg / 10, tp_avg % 10, 91 93 eprob / 10, eprob % 10, 92 94 prob / 10, prob % 10, ··· 127 125 p = ms->buf; 128 126 129 127 p += sprintf(p, "\n"); 130 - p += sprintf(p, " best ________rate______ " 128 + p += sprintf(p, " best ____________rate__________ " 131 129 "__statistics__ ________last_______ " 132 130 "______sum-of________\n"); 133 - p += sprintf(p, "mode guard # rate [name idx airtime] [ ø(tp) " 134 - "ø(prob)] [prob.|retry|suc|att] [#success | " 131 + p += sprintf(p, "mode guard # rate [name idx airtime max_tp] " 132 + "[ ø(tp) ø(prob)] [prob.|retry|suc|att] [#success | " 135 133 "#attempts]\n"); 136 134 137 135 p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p); ··· 165 163 minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p) 166 164 { 167 165 const struct mcs_group *mg; 168 - unsigned int j, tp_avg, prob, eprob, tx_time; 166 + unsigned int j, tp_max, tp_avg, prob, eprob, tx_time; 169 167 char htmode = '2'; 170 168 char gimode = 'L'; 171 169 u32 gflags; ··· 224 222 tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); 225 223 p += sprintf(p, "%u,", tx_time); 226 224 227 - tp_avg = minstrel_ht_get_tp_avg(mi, i, j); 225 + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); 226 + tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); 228 227 prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); 229 228 eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); 230 229 231 - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,", 230 + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,", 231 + tp_max / 10, tp_max % 10, 232 232 tp_avg / 10, tp_avg % 10, 233 233 eprob / 10, eprob % 10, 234 234 prob / 10, prob % 10,