/*
 * 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_atx_ac *ac;
	struct ath_txq *txq;
	u32 len = 0, size = 4096;
	char *buf;
	size_t retval;
	int tidno, acno;

	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,
			 "%2s%7s\n", "AC", "SCHED");

	for (acno = 0, ac = &an->ac[acno];
	     acno < IEEE80211_NUM_ACS; acno++, ac++) {
		txq = ac->txq;
		ath_txq_lock(sc, txq);
		len += scnprintf(buf + len, size - len,
				 "%2d%7d\n",
				 acno, ac->sched);
		ath_txq_unlock(sc, txq);
	}

	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, tid = &an->tid[tidno];
	     tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
		txq = tid->ac->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,
					 tid->sched);
		}
		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->flag & RX_FLAG_40MHZ)
			rstats->ht_stats[rxs->rate_idx].ht40_cnt++;
		else
			rstats->ht_stats[rxs->rate_idx].ht20_cnt++;

		if (rxs->flag & RX_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->flag & RX_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 == IEEE80211_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 ieee80211_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 == IEEE80211_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 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", S_IRUGO, dir, an, &fops_node_aggr);
	debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
}
