/*
 * Copyright (c) 2013 Qualcomm Atheros, Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "ath9k.h"

/*************/
/* node_aggr */
/*************/

static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
				   size_t count, loff_t *ppos)
{
	struct ath_node *an = file->private_data;
	struct ath_softc *sc = an->sc;
	struct ath_atx_tid *tid;
	struct ath_txq *txq;
	u32 len = 0, size = 4096;
	char *buf;
	size_t retval;
	int tidno;

	buf = kzalloc(size, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	if (!an->sta->ht_cap.ht_supported) {
		len = scnprintf(buf, size, "%s\n",
				"HT not supported");
		goto exit;
	}

	len = scnprintf(buf, size, "Max-AMPDU: %d\n",
			an->maxampdu);
	len += scnprintf(buf + len, size - len, "MPDU Density: %d\n\n",
			 an->mpdudensity);

	len += scnprintf(buf + len, size - len,
			 "\n%3s%11s%10s%10s%10s%10s%9s%6s%8s\n",
			 "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE",
			 "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED");

	for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
		tid = ath_node_to_tid(an, tidno);
		txq = tid->txq;
		ath_txq_lock(sc, txq);
		if (tid->active) {
			len += scnprintf(buf + len, size - len,
					 "%3d%11d%10d%10d%10d%10d%9d%6d\n",
					 tid->tidno,
					 tid->seq_start,
					 tid->seq_next,
					 tid->baw_size,
					 tid->baw_head,
					 tid->baw_tail,
					 tid->bar_index,
					 !list_empty(&tid->list));
		}
		ath_txq_unlock(sc, txq);
	}
exit:
	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
	kfree(buf);

	return retval;
}

static const struct file_operations fops_node_aggr = {
	.read = read_file_node_aggr,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

/*************/
/* node_recv */
/*************/

void ath_debug_rate_stats(struct ath_softc *sc,
			  struct ath_rx_status *rs,
			  struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ath_hw *ah = sc->sc_ah;
	struct ieee80211_rx_status *rxs;
	struct ath_rx_rate_stats *rstats;
	struct ieee80211_sta *sta;
	struct ath_node *an;

	if (!ieee80211_is_data(hdr->frame_control))
		return;

	rcu_read_lock();

	sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
	if (!sta)
		goto exit;

	an = (struct ath_node *) sta->drv_priv;
	rstats = &an->rx_rate_stats;
	rxs = IEEE80211_SKB_RXCB(skb);

	if (IS_HT_RATE(rs->rs_rate)) {
		if (rxs->rate_idx >= ARRAY_SIZE(rstats->ht_stats))
			goto exit;

		if ((rxs->bw == RATE_INFO_BW_40))
			rstats->ht_stats[rxs->rate_idx].ht40_cnt++;
		else
			rstats->ht_stats[rxs->rate_idx].ht20_cnt++;

		if (rxs->enc_flags & RX_ENC_FLAG_SHORT_GI)
			rstats->ht_stats[rxs->rate_idx].sgi_cnt++;
		else
			rstats->ht_stats[rxs->rate_idx].lgi_cnt++;

		goto exit;
	}

	if (IS_CCK_RATE(rs->rs_rate)) {
		if (rxs->enc_flags & RX_ENC_FLAG_SHORTPRE)
			rstats->cck_stats[rxs->rate_idx].cck_sp_cnt++;
		else
			rstats->cck_stats[rxs->rate_idx].cck_lp_cnt++;

		goto exit;
	}

	if (IS_OFDM_RATE(rs->rs_rate)) {
		if (ah->curchan->chan->band == NL80211_BAND_2GHZ)
			rstats->ofdm_stats[rxs->rate_idx - 4].ofdm_cnt++;
		else
			rstats->ofdm_stats[rxs->rate_idx].ofdm_cnt++;
	}
exit:
	rcu_read_unlock();
}

#define PRINT_CCK_RATE(str, i, sp)					\
	do {								\
		len += scnprintf(buf + len, size - len,			\
			 "%11s : %10u\n",				\
			 str,						\
			 (sp) ? rstats->cck_stats[i].cck_sp_cnt :	\
			 rstats->cck_stats[i].cck_lp_cnt);		\
	} while (0)

#define PRINT_OFDM_RATE(str, i)					\
	do {							\
		len += scnprintf(buf + len, size - len,		\
			 "%11s : %10u\n",			\
			 str,					\
			 rstats->ofdm_stats[i].ofdm_cnt);	\
	} while (0)

static ssize_t read_file_node_recv(struct file *file, char __user *user_buf,
				   size_t count, loff_t *ppos)
{
	struct ath_node *an = file->private_data;
	struct ath_softc *sc = an->sc;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_rx_rate_stats *rstats;
	struct ieee80211_sta *sta = an->sta;
	enum nl80211_band band;
	u32 len = 0, size = 4096;
	char *buf;
	size_t retval;
	int i;

	buf = kzalloc(size, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	band = ah->curchan->chan->band;
	rstats = &an->rx_rate_stats;

	if (!sta->ht_cap.ht_supported)
		goto legacy;

	len += scnprintf(buf + len, size - len,
			 "%24s%10s%10s%10s\n",
			 "HT20", "HT40", "SGI", "LGI");

	for (i = 0; i < 24; i++) {
		len += scnprintf(buf + len, size - len,
				 "%8s%3u : %10u%10u%10u%10u\n",
				 "MCS", i,
				 rstats->ht_stats[i].ht20_cnt,
				 rstats->ht_stats[i].ht40_cnt,
				 rstats->ht_stats[i].sgi_cnt,
				 rstats->ht_stats[i].lgi_cnt);
	}

	len += scnprintf(buf + len, size - len, "\n");

legacy:
	if (band == NL80211_BAND_2GHZ) {
		PRINT_CCK_RATE("CCK-1M/LP", 0, false);
		PRINT_CCK_RATE("CCK-2M/LP", 1, false);
		PRINT_CCK_RATE("CCK-5.5M/LP", 2, false);
		PRINT_CCK_RATE("CCK-11M/LP", 3, false);

		PRINT_CCK_RATE("CCK-2M/SP", 1, true);
		PRINT_CCK_RATE("CCK-5.5M/SP", 2, true);
		PRINT_CCK_RATE("CCK-11M/SP", 3, true);
	}

	PRINT_OFDM_RATE("OFDM-6M", 0);
	PRINT_OFDM_RATE("OFDM-9M", 1);
	PRINT_OFDM_RATE("OFDM-12M", 2);
	PRINT_OFDM_RATE("OFDM-18M", 3);
	PRINT_OFDM_RATE("OFDM-24M", 4);
	PRINT_OFDM_RATE("OFDM-36M", 5);
	PRINT_OFDM_RATE("OFDM-48M", 6);
	PRINT_OFDM_RATE("OFDM-54M", 7);

	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
	kfree(buf);

	return retval;
}

#undef PRINT_OFDM_RATE
#undef PRINT_CCK_RATE

static const struct file_operations fops_node_recv = {
	.read = read_file_node_recv,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};

void ath_debug_airtime(struct ath_softc *sc,
		struct ath_node *an,
		u32 rx,
		u32 tx)
{
	struct ath_airtime_stats *astats = &an->airtime_stats;

	astats->rx_airtime += rx;
	astats->tx_airtime += tx;
}

static ssize_t read_airtime(struct file *file, char __user *user_buf,
			size_t count, loff_t *ppos)
{
	struct ath_node *an = file->private_data;
	struct ath_airtime_stats *astats;
	static const char *qname[4] = {
		"VO", "VI", "BE", "BK"
	};
	u32 len = 0, size = 256;
	char *buf;
	size_t retval;
	int i;

	buf = kzalloc(size, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	astats = &an->airtime_stats;

	len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
	len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
	len += scnprintf(buf + len, size - len, "Deficit: ");
	for (i = 0; i < 4; i++)
		len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
	if (len < size)
		buf[len++] = '\n';

	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
	kfree(buf);

	return retval;
}


static const struct file_operations fops_airtime = {
	.read = read_airtime,
	.open = simple_open,
	.owner = THIS_MODULE,
	.llseek = default_llseek,
};


void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
			   struct ieee80211_vif *vif,
			   struct ieee80211_sta *sta,
			   struct dentry *dir)
{
	struct ath_node *an = (struct ath_node *)sta->drv_priv;

	debugfs_create_file("node_aggr", 0444, dir, an, &fops_node_aggr);
	debugfs_create_file("node_recv", 0444, dir, an, &fops_node_recv);
	debugfs_create_file("airtime", 0444, dir, an, &fops_airtime);
}
