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