18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 58c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 68c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on minstrel.c: 98c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> 108c2ecf20Sopenharmony_ci * Sponsored by Indranet Technologies Ltd 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Based on sample.c: 138c2ecf20Sopenharmony_ci * Copyright (c) 2005 John Bicket 148c2ecf20Sopenharmony_ci * All rights reserved. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 178c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 188c2ecf20Sopenharmony_ci * are met: 198c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 208c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer, 218c2ecf20Sopenharmony_ci * without modification. 228c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 238c2ecf20Sopenharmony_ci * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 248c2ecf20Sopenharmony_ci * redistribution must be conditioned upon including a substantially 258c2ecf20Sopenharmony_ci * similar Disclaimer requirement for further binary redistribution. 268c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 278c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 288c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 318c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 328c2ecf20Sopenharmony_ci * Software Foundation. 338c2ecf20Sopenharmony_ci * 348c2ecf20Sopenharmony_ci * NO WARRANTY 358c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 368c2ecf20Sopenharmony_ci * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 378c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 388c2ecf20Sopenharmony_ci * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 398c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 408c2ecf20Sopenharmony_ci * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 418c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 428c2ecf20Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 438c2ecf20Sopenharmony_ci * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 448c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 458c2ecf20Sopenharmony_ci * THE POSSIBILITY OF SUCH DAMAGES. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 488c2ecf20Sopenharmony_ci#include <linux/types.h> 498c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 508c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 518c2ecf20Sopenharmony_ci#include <linux/ieee80211.h> 528c2ecf20Sopenharmony_ci#include <linux/slab.h> 538c2ecf20Sopenharmony_ci#include <linux/export.h> 548c2ecf20Sopenharmony_ci#include <net/mac80211.h> 558c2ecf20Sopenharmony_ci#include "rc80211_minstrel.h" 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint 588c2ecf20Sopenharmony_ciminstrel_stats_open(struct inode *inode, struct file *file) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct minstrel_sta_info *mi = inode->i_private; 618c2ecf20Sopenharmony_ci struct minstrel_debugfs_info *ms; 628c2ecf20Sopenharmony_ci unsigned int i, tp_max, tp_avg, eprob; 638c2ecf20Sopenharmony_ci char *p; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci ms = kmalloc(2048, GFP_KERNEL); 668c2ecf20Sopenharmony_ci if (!ms) 678c2ecf20Sopenharmony_ci return -ENOMEM; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci file->private_data = ms; 708c2ecf20Sopenharmony_ci p = ms->buf; 718c2ecf20Sopenharmony_ci p += sprintf(p, "\n"); 728c2ecf20Sopenharmony_ci p += sprintf(p, 738c2ecf20Sopenharmony_ci "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n"); 748c2ecf20Sopenharmony_ci p += sprintf(p, 758c2ecf20Sopenharmony_ci "rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n"); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci for (i = 0; i < mi->n_rates; i++) { 788c2ecf20Sopenharmony_ci struct minstrel_rate *mr = &mi->r[i]; 798c2ecf20Sopenharmony_ci struct minstrel_rate_stats *mrs = &mi->r[i].stats; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; 828c2ecf20Sopenharmony_ci *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; 838c2ecf20Sopenharmony_ci *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; 848c2ecf20Sopenharmony_ci *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; 858c2ecf20Sopenharmony_ci *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci p += sprintf(p, " %3u%s ", mr->bitrate / 2, 888c2ecf20Sopenharmony_ci (mr->bitrate & 1 ? ".5" : " ")); 898c2ecf20Sopenharmony_ci p += sprintf(p, "%3u ", i); 908c2ecf20Sopenharmony_ci p += sprintf(p, "%6u ", mr->perfect_tx_time); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 938c2ecf20Sopenharmony_ci tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); 948c2ecf20Sopenharmony_ci eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u" 978c2ecf20Sopenharmony_ci " %3u %3u %-3u " 988c2ecf20Sopenharmony_ci "%9llu %-9llu\n", 998c2ecf20Sopenharmony_ci tp_max / 10, tp_max % 10, 1008c2ecf20Sopenharmony_ci tp_avg / 10, tp_avg % 10, 1018c2ecf20Sopenharmony_ci eprob / 10, eprob % 10, 1028c2ecf20Sopenharmony_ci mrs->retry_count, 1038c2ecf20Sopenharmony_ci mrs->last_success, 1048c2ecf20Sopenharmony_ci mrs->last_attempts, 1058c2ecf20Sopenharmony_ci (unsigned long long)mrs->succ_hist, 1068c2ecf20Sopenharmony_ci (unsigned long long)mrs->att_hist); 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci p += sprintf(p, "\nTotal packet count:: ideal %d " 1098c2ecf20Sopenharmony_ci "lookaround %d\n\n", 1108c2ecf20Sopenharmony_ci mi->total_packets - mi->sample_packets, 1118c2ecf20Sopenharmony_ci mi->sample_packets); 1128c2ecf20Sopenharmony_ci ms->len = p - ms->buf; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci WARN_ON(ms->len + sizeof(*ms) > 2048); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci return 0; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ciint 1208c2ecf20Sopenharmony_ciminstrel_stats_csv_open(struct inode *inode, struct file *file) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct minstrel_sta_info *mi = inode->i_private; 1238c2ecf20Sopenharmony_ci struct minstrel_debugfs_info *ms; 1248c2ecf20Sopenharmony_ci unsigned int i, tp_max, tp_avg, eprob; 1258c2ecf20Sopenharmony_ci char *p; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci ms = kmalloc(2048, GFP_KERNEL); 1288c2ecf20Sopenharmony_ci if (!ms) 1298c2ecf20Sopenharmony_ci return -ENOMEM; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci file->private_data = ms; 1328c2ecf20Sopenharmony_ci p = ms->buf; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci for (i = 0; i < mi->n_rates; i++) { 1358c2ecf20Sopenharmony_ci struct minstrel_rate *mr = &mi->r[i]; 1368c2ecf20Sopenharmony_ci struct minstrel_rate_stats *mrs = &mi->r[i].stats; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); 1398c2ecf20Sopenharmony_ci p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); 1408c2ecf20Sopenharmony_ci p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : "")); 1418c2ecf20Sopenharmony_ci p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : "")); 1428c2ecf20Sopenharmony_ci p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : "")); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci p += sprintf(p, ",%u%s", mr->bitrate / 2, 1458c2ecf20Sopenharmony_ci (mr->bitrate & 1 ? ".5," : ",")); 1468c2ecf20Sopenharmony_ci p += sprintf(p, "%u,", i); 1478c2ecf20Sopenharmony_ci p += sprintf(p, "%u,",mr->perfect_tx_time); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 1508c2ecf20Sopenharmony_ci tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); 1518c2ecf20Sopenharmony_ci eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," 1548c2ecf20Sopenharmony_ci "%llu,%llu,%d,%d\n", 1558c2ecf20Sopenharmony_ci tp_max / 10, tp_max % 10, 1568c2ecf20Sopenharmony_ci tp_avg / 10, tp_avg % 10, 1578c2ecf20Sopenharmony_ci eprob / 10, eprob % 10, 1588c2ecf20Sopenharmony_ci mrs->retry_count, 1598c2ecf20Sopenharmony_ci mrs->last_success, 1608c2ecf20Sopenharmony_ci mrs->last_attempts, 1618c2ecf20Sopenharmony_ci (unsigned long long)mrs->succ_hist, 1628c2ecf20Sopenharmony_ci (unsigned long long)mrs->att_hist, 1638c2ecf20Sopenharmony_ci mi->total_packets - mi->sample_packets, 1648c2ecf20Sopenharmony_ci mi->sample_packets); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci ms->len = p - ms->buf; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci WARN_ON(ms->len + sizeof(*ms) > 2048); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 173