All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver
@ 2014-09-16  0:13 Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 01/10] ath9k: export methods related to ACK timeout estimation Lorenzo Bianconi
                   ` (9 more replies)
  0 siblings, 10 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

This patchset adds support for estimation of the ACK timeout (dynack) in ath9k
driver. Ath9k dynack computes the ACK timeout based on ACK frame RX timestamp,
TX frame timestamp and frame duration.

Ath9k dynack has been tested in indoor environment using AR9223/AR9280 chipset
(running 3.17.0-rc5 kernel), on 9Km PtoP link using AR9280 chipset
(running OpenWRT trunk, compat-wireless-2014-05-22) and on an AP using AR9280
chipset (running OpenWRT trunk, compat-wireless-2014-05-22) serving 35 STA with
links up to 8Km

Changes since v1:
- rebase on top of "configure dynack through mac80211/cfg80211 stack" patchset
- improve documentation

Changes since RFCv2:
- disable dynack by default
- add ath9k_enable_dynack() method to enable ack timeout estimation algorithm
- remove dynack entry from ath9k debugfs

Changes since RFCv1:
- use ISC license instead of GPLv2 one
- use an inline method instead of a macro for EWMA calculation
- use powers of two weights in EWMA calculation
- fix typos
- add ath_dynack_node_init/ath_dynack_node_deinit methods
- use different logic to enable/disable dynack processing

Lorenzo Bianconi (10):
  ath9k: export methods related to ACK timeout estimation
  ath9k: add duration field to ath_tx_status
  ath9k: add dynamic ACK timeout estimation
  ath9k: add config for (en|dis)abling ACK timeout estimation
  ath9k: do not overwrite ACK timeout estimation
  ath9k: add sampling methods for (tx|rx) timestamp
  ath9k: enable control frame reception
  ath9k: add debugfs support for dynack
  ath9k: enable dynack using set_coverage_class codepath
  ath9k: initialize ath_node linked list

 drivers/net/wireless/ath/ath.h              |   2 +
 drivers/net/wireless/ath/ath9k/Kconfig      |   9 +
 drivers/net/wireless/ath/ath9k/Makefile     |   3 +
 drivers/net/wireless/ath/ath9k/ar9002_mac.c |   7 +
 drivers/net/wireless/ath/ath9k/ar9003_mac.c |   9 +
 drivers/net/wireless/ath/ath9k/ath9k.h      |   3 +
 drivers/net/wireless/ath/ath9k/debug.c      |  28 +++
 drivers/net/wireless/ath/ath9k/dynack.c     | 352 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dynack.h     | 103 ++++++++
 drivers/net/wireless/ath/ath9k/hw.c         |  16 +-
 drivers/net/wireless/ath/ath9k/hw.h         |   7 +
 drivers/net/wireless/ath/ath9k/mac.h        |   1 +
 drivers/net/wireless/ath/ath9k/main.c       |  37 ++-
 drivers/net/wireless/ath/ath9k/recv.c       |   8 +-
 drivers/net/wireless/ath/ath9k/xmit.c       |   5 +
 15 files changed, 582 insertions(+), 8 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.h

-- 
1.9.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCHv2 01/10] ath9k: export methods related to ACK timeout estimation
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 02/10] ath9k: add duration field to ath_tx_status Lorenzo Bianconi
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Remove static keyword and export ath9k_hw_setslottime(),
ath9k_hw_set_ack_timeout() and ath9k_hw_set_cts_timeout() in hw.h.
These methods will be used in ACK timeout estimation algorithm (dynack)

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/hw.c | 6 +++---
 drivers/net/wireless/ath/ath9k/hw.h | 4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ef5f5a6..ce395e2 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -935,21 +935,21 @@ static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
 	REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
 }
 
-static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
+void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
 {
 	u32 val = ath9k_hw_mac_to_clks(ah, us);
 	val = min(val, (u32) 0xFFFF);
 	REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val);
 }
 
-static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
+void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us)
 {
 	u32 val = ath9k_hw_mac_to_clks(ah, us);
 	val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK));
 	REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val);
 }
 
-static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
+void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us)
 {
 	u32 val = ath9k_hw_mac_to_clks(ah, us);
 	val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS));
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 51b4ebe..f36d971 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -1080,6 +1080,10 @@ void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
 void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
 
+void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us);
+void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us);
+void ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
+
 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
 static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah)
 {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 02/10] ath9k: add duration field to ath_tx_status
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 01/10] ath9k: export methods related to ACK timeout estimation Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 03/10] ath9k: add dynamic ACK timeout estimation Lorenzo Bianconi
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Add duration field to ath_tx_status in order to report frame duration for each
entry in multi-retry chain. These fields will be used in ACK timeout estimation
algorithm (dynack)

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/ar9002_mac.c | 7 +++++++
 drivers/net/wireless/ath/ath9k/ar9003_mac.c | 9 +++++++++
 drivers/net/wireless/ath/ath9k/mac.h        | 1 +
 3 files changed, 17 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index 59af9f9..669cb37 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -381,6 +381,13 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 	ts->evm1 = ads->AR_TxEVM1;
 	ts->evm2 = ads->AR_TxEVM2;
 
+	status = ACCESS_ONCE(ads->ds_ctl4);
+	ts->duration[0] = MS(status, AR_PacketDur0);
+	ts->duration[1] = MS(status, AR_PacketDur1);
+	status = ACCESS_ONCE(ads->ds_ctl5);
+	ts->duration[2] = MS(status, AR_PacketDur2);
+	ts->duration[3] = MS(status, AR_PacketDur3);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 71e38e8..e5f7c11 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -355,9 +355,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 				 struct ath_tx_status *ts)
 {
 	struct ar9003_txs *ads;
+	struct ar9003_txc *adc;
 	u32 status;
 
 	ads = &ah->ts_ring[ah->ts_tail];
+	adc = (struct ar9003_txc *)ads;
 
 	status = ACCESS_ONCE(ads->status8);
 	if ((status & AR_TxDone) == 0)
@@ -426,6 +428,13 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
 	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
+	status = ACCESS_ONCE(adc->ctl15);
+	ts->duration[0] = MS(status, AR_PacketDur0);
+	ts->duration[1] = MS(status, AR_PacketDur1);
+	status = ACCESS_ONCE(adc->ctl16);
+	ts->duration[2] = MS(status, AR_PacketDur2);
+	ts->duration[3] = MS(status, AR_PacketDur3);
+
 	memset(ads, 0, sizeof(*ads));
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 6c56caf..cd05a77 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -121,6 +121,7 @@ struct ath_tx_status {
 	u32 evm0;
 	u32 evm1;
 	u32 evm2;
+	u32 duration[4];
 };
 
 struct ath_rx_status {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 03/10] ath9k: add dynamic ACK timeout estimation
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 01/10] ath9k: export methods related to ACK timeout estimation Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 02/10] ath9k: add duration field to ath_tx_status Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 04/10] ath9k: add config for (en|dis)abling " Lorenzo Bianconi
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Add dynamic ACK timeout estimation algorithm based on ACK frame RX timestamp,
TX frame timestamp and frame duration.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
Tested-by: Philippe Duchein <wireless-dev@duchein.net>
---
 drivers/net/wireless/ath/ath.h          |   2 +
 drivers/net/wireless/ath/ath9k/ath9k.h  |   3 +
 drivers/net/wireless/ath/ath9k/dynack.c | 352 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dynack.h | 103 ++++++++++
 drivers/net/wireless/ath/ath9k/hw.c     |   2 +
 drivers/net/wireless/ath/ath9k/hw.h     |   3 +
 6 files changed, 465 insertions(+)
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.h

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index c1a4ade..a3b6e27 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -234,6 +234,7 @@ void ath_printk(const char *level, const struct ath_common *common,
  *	AR9462.
  * @ATH_DBG_DFS: radar datection
  * @ATH_DBG_WOW: Wake on Wireless
+ * @ATH_DBG_DYNACK: dynack handling
  * @ATH_DBG_ANY: enable all debugging
  *
  * The debug level is used to control the amount and type of debugging output
@@ -262,6 +263,7 @@ enum ATH_DEBUG {
 	ATH_DBG_DFS		= 0x00010000,
 	ATH_DBG_WOW		= 0x00020000,
 	ATH_DBG_CHAN_CTX	= 0x00040000,
+	ATH_DBG_DYNACK		= 0x00080000,
 	ATH_DBG_ANY		= 0xffffffff
 };
 
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index dd0f97f..8cd116e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -274,6 +274,9 @@ struct ath_node {
 	struct ath_rx_rate_stats rx_rate_stats;
 #endif
 	u8 key_idx[4];
+
+	u32 ackto;
+	struct list_head list;
 };
 
 struct ath_tx_control {
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
new file mode 100644
index 0000000..ceca509
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2014, Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * 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"
+#include "hw.h"
+#include "dynack.h"
+
+#define COMPUTE_TO		(5 * HZ)
+#define LATEACK_DELAY		(10 * HZ)
+#define LATEACK_TO		256
+#define MAX_DELAY		300
+#define EWMA_LEVEL		96
+#define EWMA_DIV		128
+
+/**
+ * ath_dynack_ewma - EWMA (Exponentially Weighted Moving Average) calculation
+ *
+ */
+static inline u32 ath_dynack_ewma(u32 old, u32 new)
+{
+	return (new * (EWMA_DIV - EWMA_LEVEL) + old * EWMA_LEVEL) / EWMA_DIV;
+}
+
+/**
+ * ath_dynack_get_sifs - get sifs time based on phy used
+ * @ah: ath hw
+ * @phy: phy used
+ *
+ */
+static inline u32 ath_dynack_get_sifs(struct ath_hw *ah, int phy)
+{
+	u32 sifs = CCK_SIFS_TIME;
+
+	if (phy == WLAN_RC_PHY_OFDM) {
+		if (IS_CHAN_QUARTER_RATE(ah->curchan))
+			sifs = OFDM_SIFS_TIME_QUARTER;
+		else if (IS_CHAN_HALF_RATE(ah->curchan))
+			sifs = OFDM_SIFS_TIME_HALF;
+		else
+			sifs = OFDM_SIFS_TIME;
+	}
+	return sifs;
+}
+
+/**
+ * ath_dynack_bssidmask - filter out ACK frames based on BSSID mask
+ * @ah: ath hw
+ * @mac: receiver address
+ */
+static inline bool ath_dynack_bssidmask(struct ath_hw *ah, const u8 *mac)
+{
+	int i;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		if ((common->macaddr[i] & common->bssidmask[i]) !=
+		    (mac[i] & common->bssidmask[i]))
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * ath_dynack_compute_ackto - compute ACK timeout as the maximum STA timeout
+ * @ah: ath hw
+ *
+ * should be called while holding qlock
+ */
+static void ath_dynack_compute_ackto(struct ath_hw *ah)
+{
+	struct ath_node *an;
+	u32 to = 0;
+	struct ath_dynack *da = &ah->dynack;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	list_for_each_entry(an, &da->nodes, list)
+		if (an->ackto > to)
+			to = an->ackto;
+
+	if (to && da->ackto != to) {
+		u32 slottime;
+
+		slottime = (to - 3) / 2;
+		da->ackto = to;
+		ath_dbg(common, DYNACK, "ACK timeout %u slottime %u\n",
+			da->ackto, slottime);
+		ath9k_hw_setslottime(ah, slottime);
+		ath9k_hw_set_ack_timeout(ah, da->ackto);
+		ath9k_hw_set_cts_timeout(ah, da->ackto);
+	}
+}
+
+/**
+ * ath_dynack_compute_to - compute STA ACK timeout
+ * @ah: ath hw
+ *
+ * should be called while holding qlock
+ */
+static void ath_dynack_compute_to(struct ath_hw *ah)
+{
+	u32 ackto, ack_ts;
+	u8 *dst, *src;
+	struct ieee80211_sta *sta;
+	struct ath_node *an;
+	struct ts_info *st_ts;
+	struct ath_dynack *da = &ah->dynack;
+
+	rcu_read_lock();
+
+	while (da->st_rbf.h_rb != da->st_rbf.t_rb &&
+	       da->ack_rbf.h_rb != da->ack_rbf.t_rb) {
+		ack_ts = da->ack_rbf.tstamp[da->ack_rbf.h_rb];
+		st_ts = &da->st_rbf.ts[da->st_rbf.h_rb];
+		dst = da->st_rbf.addr[da->st_rbf.h_rb].h_dest;
+		src = da->st_rbf.addr[da->st_rbf.h_rb].h_src;
+
+		ath_dbg(ath9k_hw_common(ah), DYNACK,
+			"ack_ts %u st_ts %u st_dur %u [%u-%u]\n",
+			ack_ts, st_ts->tstamp, st_ts->dur,
+			da->ack_rbf.h_rb, da->st_rbf.h_rb);
+
+		if (ack_ts > st_ts->tstamp + st_ts->dur) {
+			ackto = ack_ts - st_ts->tstamp - st_ts->dur;
+
+			if (ackto < MAX_DELAY) {
+				sta = ieee80211_find_sta_by_ifaddr(ah->hw, dst,
+								   src);
+				if (sta) {
+					an = (struct ath_node *)sta->drv_priv;
+					an->ackto = ath_dynack_ewma(an->ackto,
+								    ackto);
+					ath_dbg(ath9k_hw_common(ah), DYNACK,
+						"%pM to %u\n", dst, an->ackto);
+					if (time_is_before_jiffies(da->lto)) {
+						ath_dynack_compute_ackto(ah);
+						da->lto = jiffies + COMPUTE_TO;
+					}
+				}
+				INCR(da->ack_rbf.h_rb, ATH_DYN_BUF);
+			}
+			INCR(da->st_rbf.h_rb, ATH_DYN_BUF);
+		} else {
+			INCR(da->ack_rbf.h_rb, ATH_DYN_BUF);
+		}
+	}
+
+	rcu_read_unlock();
+}
+
+/**
+ * ath_dynack_sample_tx_ts - status timestamp sampling method
+ * @ah: ath hw
+ * @skb: socket buffer
+ * @ts: tx status info
+ *
+ */
+void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
+			     struct ath_tx_status *ts)
+{
+	u8 ridx;
+	struct ieee80211_hdr *hdr;
+	struct ath_dynack *da = &ah->dynack;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	if ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !da->enabled)
+		return;
+
+	spin_lock_bh(&da->qlock);
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+
+	/* late ACK */
+	if (ts->ts_status & ATH9K_TXERR_XRETRY) {
+		if (ieee80211_is_assoc_req(hdr->frame_control) ||
+		    ieee80211_is_assoc_resp(hdr->frame_control)) {
+			ath_dbg(common, DYNACK, "late ack\n");
+			ath9k_hw_setslottime(ah, (LATEACK_TO - 3) / 2);
+			ath9k_hw_set_ack_timeout(ah, LATEACK_TO);
+			ath9k_hw_set_cts_timeout(ah, LATEACK_TO);
+			da->lto = jiffies + LATEACK_DELAY;
+		}
+
+		spin_unlock_bh(&da->qlock);
+		return;
+	}
+
+	ridx = ts->ts_rateindex;
+
+	da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
+	da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex];
+	ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
+	ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
+
+	if (!(info->status.rates[ridx].flags & IEEE80211_TX_RC_MCS)) {
+		u32 phy, sifs;
+		const struct ieee80211_rate *rate;
+		struct ieee80211_tx_rate *rates = info->status.rates;
+
+		rate = &common->sbands[info->band].bitrates[rates[ridx].idx];
+		if (info->band == IEEE80211_BAND_2GHZ &&
+		    !(rate->flags & IEEE80211_RATE_ERP_G))
+			phy = WLAN_RC_PHY_CCK;
+		else
+			phy = WLAN_RC_PHY_OFDM;
+
+		sifs = ath_dynack_get_sifs(ah, phy);
+		da->st_rbf.ts[da->st_rbf.t_rb].dur -= sifs;
+	}
+
+	ath_dbg(common, DYNACK, "{%pM} tx sample %u [dur %u][h %u-t %u]\n",
+		hdr->addr1, da->st_rbf.ts[da->st_rbf.t_rb].tstamp,
+		da->st_rbf.ts[da->st_rbf.t_rb].dur, da->st_rbf.h_rb,
+		(da->st_rbf.t_rb + 1) % ATH_DYN_BUF);
+
+	INCR(da->st_rbf.t_rb, ATH_DYN_BUF);
+	if (da->st_rbf.t_rb == da->st_rbf.h_rb)
+		INCR(da->st_rbf.h_rb, ATH_DYN_BUF);
+
+	ath_dynack_compute_to(ah);
+
+	spin_unlock_bh(&da->qlock);
+}
+EXPORT_SYMBOL(ath_dynack_sample_tx_ts);
+
+/**
+ * ath_dynack_sample_ack_ts - ACK timestamp sampling method
+ * @ah: ath hw
+ * @skb: socket buffer
+ * @ts: rx timestamp
+ *
+ */
+void ath_dynack_sample_ack_ts(struct ath_hw *ah, struct sk_buff *skb,
+			      u32 ts)
+{
+	struct ath_dynack *da = &ah->dynack;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+	if (!ath_dynack_bssidmask(ah, hdr->addr1) || !da->enabled)
+		return;
+
+	spin_lock_bh(&da->qlock);
+	da->ack_rbf.tstamp[da->ack_rbf.t_rb] = ts;
+
+	ath_dbg(common, DYNACK, "rx sample %u [h %u-t %u]\n",
+		da->ack_rbf.tstamp[da->ack_rbf.t_rb],
+		da->ack_rbf.h_rb, (da->ack_rbf.t_rb + 1) % ATH_DYN_BUF);
+
+	INCR(da->ack_rbf.t_rb, ATH_DYN_BUF);
+	if (da->ack_rbf.t_rb == da->ack_rbf.h_rb)
+		INCR(da->ack_rbf.h_rb, ATH_DYN_BUF);
+
+	ath_dynack_compute_to(ah);
+
+	spin_unlock_bh(&da->qlock);
+}
+EXPORT_SYMBOL(ath_dynack_sample_ack_ts);
+
+/**
+ * ath_dynack_node_init - init ath_node related info
+ * @ah: ath hw
+ * @an: ath node
+ *
+ */
+void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an)
+{
+	/* ackto = slottime + sifs + air delay */
+	u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+	struct ath_dynack *da = &ah->dynack;
+
+	an->ackto = ackto;
+
+	spin_lock(&da->qlock);
+	list_add_tail(&an->list, &da->nodes);
+	spin_unlock(&da->qlock);
+}
+EXPORT_SYMBOL(ath_dynack_node_init);
+
+/**
+ * ath_dynack_node_deinit - deinit ath_node related info
+ * @ah: ath hw
+ * @an: ath node
+ *
+ */
+void ath_dynack_node_deinit(struct ath_hw *ah, struct ath_node *an)
+{
+	struct ath_dynack *da = &ah->dynack;
+
+	spin_lock(&da->qlock);
+	list_del(&an->list);
+	spin_unlock(&da->qlock);
+}
+EXPORT_SYMBOL(ath_dynack_node_deinit);
+
+/**
+ * ath_dynack_reset - reset dynack processing
+ * @ah: ath hw
+ *
+ */
+void ath_dynack_reset(struct ath_hw *ah)
+{
+	/* ackto = slottime + sifs + air delay */
+	u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
+	struct ath_dynack *da = &ah->dynack;
+
+	da->lto = jiffies;
+	da->ackto = ackto;
+
+	da->st_rbf.t_rb = 0;
+	da->st_rbf.h_rb = 0;
+	da->ack_rbf.t_rb = 0;
+	da->ack_rbf.h_rb = 0;
+
+	/* init acktimeout */
+	ath9k_hw_setslottime(ah, (ackto - 3) / 2);
+	ath9k_hw_set_ack_timeout(ah, ackto);
+	ath9k_hw_set_cts_timeout(ah, ackto);
+}
+EXPORT_SYMBOL(ath_dynack_reset);
+
+/**
+ * ath_dynack_init - init dynack data structure
+ * @ah: ath hw
+ *
+ */
+void ath_dynack_init(struct ath_hw *ah)
+{
+	struct ath_dynack *da = &ah->dynack;
+
+	memset(da, 0, sizeof(struct ath_dynack));
+
+	spin_lock_init(&da->qlock);
+	INIT_LIST_HEAD(&da->nodes);
+
+	ah->hw->wiphy->features |= NL80211_FEATURE_ACKTO_ESTIMATION;
+}
+
diff --git a/drivers/net/wireless/ath/ath9k/dynack.h b/drivers/net/wireless/ath/ath9k/dynack.h
new file mode 100644
index 0000000..6d7bef9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dynack.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef DYNACK_H
+#define DYNACK_H
+
+#define ATH_DYN_BUF	64
+
+struct ath_hw;
+struct ath_node;
+
+/**
+ * struct ath_dyn_rxbuf - ACK frame ring buffer
+ * @h_rb: ring buffer head
+ * @t_rb: ring buffer tail
+ * @tstamp: ACK RX timestamp buffer
+ */
+struct ath_dyn_rxbuf {
+	u16 h_rb, t_rb;
+	u32 tstamp[ATH_DYN_BUF];
+};
+
+struct ts_info {
+	u32 tstamp;
+	u32 dur;
+};
+
+struct haddr_pair {
+	u8 h_dest[ETH_ALEN];
+	u8 h_src[ETH_ALEN];
+};
+
+/**
+ * struct ath_dyn_txbuf - tx frame ring buffer
+ * @h_rb: ring buffer head
+ * @t_rb: ring buffer tail
+ * @addr: dest/src address pair for a given TX frame
+ * @ts: TX frame timestamp buffer
+ */
+struct ath_dyn_txbuf {
+	u16 h_rb, t_rb;
+	struct haddr_pair addr[ATH_DYN_BUF];
+	struct ts_info ts[ATH_DYN_BUF];
+};
+
+/**
+ * struct ath_dynack - dynack processing info
+ * @enabled: enable dyn ack processing
+ * @ackto: current ACK timeout
+ * @lto: last ACK timeout computation
+ * @nodes: ath_node linked list
+ * @qlock: ts queue spinlock
+ * @ack_rbf: ACK ts ring buffer
+ * @st_rbf: status ts ring buffer
+ */
+struct ath_dynack {
+	bool enabled;
+	int ackto;
+	unsigned long lto;
+
+	struct list_head nodes;
+
+	/* protect timestamp queue access */
+	spinlock_t qlock;
+	struct ath_dyn_rxbuf ack_rbf;
+	struct ath_dyn_txbuf st_rbf;
+};
+
+#if defined(CONFIG_ATH9K_DYNACK)
+void ath_dynack_reset(struct ath_hw *ah);
+void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an);
+void ath_dynack_node_deinit(struct ath_hw *ah, struct ath_node *an);
+void ath_dynack_init(struct ath_hw *ah);
+void ath_dynack_sample_ack_ts(struct ath_hw *ah, struct sk_buff *skb, u32 ts);
+void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
+			     struct ath_tx_status *ts);
+#else
+static inline void ath_dynack_init(struct ath_hw *ah) {}
+static inline void ath_dynack_node_init(struct ath_hw *ah,
+					struct ath_node *an) {}
+static inline void ath_dynack_node_deinit(struct ath_hw *ah,
+					  struct ath_node *an) {}
+static inline void ath_dynack_sample_ack_ts(struct ath_hw *ah,
+					    struct sk_buff *skb, u32 ts) {}
+static inline void ath_dynack_sample_tx_ts(struct ath_hw *ah,
+					   struct sk_buff *skb,
+					   struct ath_tx_status *ts) {}
+#endif
+
+#endif /* DYNACK_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index ce395e2..e71f824 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -647,6 +647,8 @@ int ath9k_hw_init(struct ath_hw *ah)
 		return ret;
 	}
 
+	ath_dynack_init(ah);
+
 	return 0;
 }
 EXPORT_SYMBOL(ath9k_hw_init);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index f36d971..b9eef33 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -29,6 +29,7 @@
 #include "reg.h"
 #include "phy.h"
 #include "btcoex.h"
+#include "dynack.h"
 
 #include "../regd.h"
 
@@ -924,6 +925,8 @@ struct ath_hw {
 	int (*external_reset)(void);
 
 	const struct firmware *eeprom_blob;
+
+	struct ath_dynack dynack;
 };
 
 struct ath_bus_ops {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 04/10] ath9k: add config for (en|dis)abling ACK timeout estimation
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (2 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 03/10] ath9k: add dynamic ACK timeout estimation Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 05/10] ath9k: do not overwrite " Lorenzo Bianconi
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Add ACK timeout estimation algorithm to ath9k Makefile and Kconfig

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/Kconfig  | 9 +++++++++
 drivers/net/wireless/ath/ath9k/Makefile | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index b8f570e..896e632 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -92,6 +92,15 @@ config ATH9K_DFS_CERTIFIED
 	  developed. At this point enabling this option won't do anything
 	  except increase code size.
 
+config ATH9K_DYNACK
+	bool "Atheros ath9k ACK timeout estimation algorithm (EXPERIMENTAL)"
+	depends on ATH9K
+	default n
+	---help---
+	  This option enables ath9k dynamic ACK timeout estimation algorithm
+	  based on ACK frame RX timestamp, TX frame timestamp and frame
+	  duration
+
 config ATH9K_TX99
 	bool "Atheros ath9k TX99 testing support"
 	depends on ATH9K_DEBUGFS && CFG80211_CERTIFICATION_ONUS
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 6b4020a..73704c1 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -49,6 +49,9 @@ ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o
 
 ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
 					   ar9003_mci.o
+
+ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o
+
 obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
 
 obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 05/10] ath9k: do not overwrite ACK timeout estimation
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (3 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 04/10] ath9k: add config for (en|dis)abling " Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 06/10] ath9k: add sampling methods for (tx|rx) timestamp Lorenzo Bianconi
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Do not overwrite ACK timeout estimation in ath9k_hw_init_global_settings() if
dynack processing has been enabled

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/hw.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index e71f824..949d5d6 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1055,6 +1055,14 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
 		ctstimeout += 48 - sifstime - ah->slottime;
 	}
 
+	if (ah->dynack.enabled) {
+		acktimeout = ah->dynack.ackto;
+		ctstimeout = acktimeout;
+		slottime = (acktimeout - 3) / 2;
+	} else {
+		ah->dynack.ackto = acktimeout;
+	}
+
 	ath9k_hw_set_sifs_time(ah, sifstime);
 	ath9k_hw_setslottime(ah, slottime);
 	ath9k_hw_set_ack_timeout(ah, acktimeout);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 06/10] ath9k: add sampling methods for (tx|rx) timestamp
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (4 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 05/10] ath9k: do not overwrite " Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 07/10] ath9k: enable control frame reception Lorenzo Bianconi
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Add sampling methods for ACK RX timestamp in ath_rx_tasklet() and for TX frame
timestamp in ath_tx_complete_aggr() and in ath_tx_process_buffer(). These
samples will be used in dynack processing for ACK timeout estimation

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/recv.c | 5 +++++
 drivers/net/wireless/ath/ath9k/xmit.c | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 0b53b74..66c5fe8 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1007,6 +1007,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 	unsigned long flags;
 	dma_addr_t new_buf_addr;
 	unsigned int budget = 512;
+	struct ieee80211_hdr *hdr;
 
 	if (edma)
 		dma_type = DMA_BIDIRECTIONAL;
@@ -1136,6 +1137,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		ath9k_apply_ampdu_details(sc, &rs, rxs);
 		ath_debug_rate_stats(sc, &rs, skb);
 
+		hdr = (struct ieee80211_hdr *)skb->data;
+		if (ieee80211_is_ack(hdr->frame_control))
+			ath_dynack_sample_ack_ts(sc->sc_ah, skb, rs.rs_tstamp);
+
 		ieee80211_rx(hw, skb);
 
 requeue_drop_frag:
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 2819866..93ad31b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -587,6 +587,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 				memcpy(tx_info->control.rates, rates, sizeof(rates));
 				ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
 				rc_update = false;
+				if (bf == bf->bf_lastbf)
+					ath_dynack_sample_tx_ts(sc->sc_ah,
+								bf->bf_mpdu,
+								ts);
 			}
 
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
@@ -687,6 +691,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
 			memcpy(info->control.rates, bf->rates,
 			       sizeof(info->control.rates));
 			ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+			ath_dynack_sample_tx_ts(sc->sc_ah, bf->bf_mpdu, ts);
 		}
 		ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
 	} else
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 07/10] ath9k: enable control frame reception
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (5 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 06/10] ath9k: add sampling methods for (tx|rx) timestamp Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 08/10] ath9k: add debugfs support for dynack Lorenzo Bianconi
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Set control frame bit in rx filter if dynack processing has been activated
in order to enable ACK frame reception

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/recv.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 66c5fe8..42108f0 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -400,7 +400,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	if (sc->sc_ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
-	if (sc->cur_chan->rxfilter & FIF_CONTROL)
+	if ((sc->cur_chan->rxfilter & FIF_CONTROL) ||
+	    sc->sc_ah->dynack.enabled)
 		rfilt |= ATH9K_RX_FILTER_CONTROL;
 
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 08/10] ath9k: add debugfs support for dynack
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (6 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 07/10] ath9k: enable control frame reception Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 09/10] ath9k: enable dynack using set_coverage_class codepath Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 10/10] ath9k: initialize ath_node linked list Lorenzo Bianconi
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Add ack_to entry to debugfs in order to dump current ACK timeout value

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/debug.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 5d8b5ea..46f20a3 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1169,6 +1169,29 @@ static const struct file_operations fops_btcoex = {
 };
 #endif
 
+#ifdef CONFIG_ATH9K_DYNACK
+static ssize_t read_file_ackto(struct file *file, char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_hw *ah = sc->sc_ah;
+	char buf[32];
+	unsigned int len;
+
+	len = sprintf(buf, "%u %c\n", ah->dynack.ackto,
+		      (ah->dynack.enabled) ? 'A' : 'S');
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_ackto = {
+	.read = read_file_ackto,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+#endif
+
 /* Ethtool support for get-stats */
 
 #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
@@ -1374,5 +1397,10 @@ int ath9k_init_debug(struct ath_hw *ah)
 			    &fops_btcoex);
 #endif
 
+#ifdef CONFIG_ATH9K_DYNACK
+	debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+			    sc, &fops_ackto);
+#endif
+
 	return 0;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 09/10] ath9k: enable dynack using set_coverage_class codepath
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (7 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 08/10] ath9k: add debugfs support for dynack Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  2014-09-16  0:13 ` [PATCHv2 10/10] ath9k: initialize ath_node linked list Lorenzo Bianconi
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Enable ACK timeout estimation algorithm if set_coverage_class routine has been
called with negative coverage_class parameter. Dynack is automatically disabled
setting valid value for coverage class

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/main.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6083359..6969aba 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1876,6 +1876,20 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
 	return 0;
 }
 
+static void ath9k_enable_dynack(struct ath_softc *sc)
+{
+#ifdef CONFIG_ATH9K_DYNACK
+	u32 rfilt;
+	struct ath_hw *ah = sc->sc_ah;
+
+	ath_dynack_reset(ah);
+
+	ah->dynack.enabled = true;
+	rfilt = ath_calcrxfilter(sc);
+	ath9k_hw_setrxfilter(ah, rfilt);
+#endif
+}
+
 static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
 				     s16 coverage_class)
 {
@@ -1886,11 +1900,22 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
 		return;
 
 	mutex_lock(&sc->mutex);
-	ah->coverage_class = coverage_class;
 
-	ath9k_ps_wakeup(sc);
-	ath9k_hw_init_global_settings(ah);
-	ath9k_ps_restore(sc);
+	if (coverage_class >= 0) {
+		ah->coverage_class = coverage_class;
+		if (ah->dynack.enabled) {
+			u32 rfilt;
+
+			ah->dynack.enabled = false;
+			rfilt = ath_calcrxfilter(sc);
+			ath9k_hw_setrxfilter(ah, rfilt);
+		}
+		ath9k_ps_wakeup(sc);
+		ath9k_hw_init_global_settings(ah);
+		ath9k_ps_restore(sc);
+	} else if (!ah->dynack.enabled) {
+		ath9k_enable_dynack(sc);
+	}
 
 	mutex_unlock(&sc->mutex);
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCHv2 10/10] ath9k: initialize ath_node linked list
  2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
                   ` (8 preceding siblings ...)
  2014-09-16  0:13 ` [PATCHv2 09/10] ath9k: enable dynack using set_coverage_class codepath Lorenzo Bianconi
@ 2014-09-16  0:13 ` Lorenzo Bianconi
  9 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-16  0:13 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Initialize neighbor linked list used by dynack to compute ACK timeout
as the maximum STA ACK timeout

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
 drivers/net/wireless/ath/ath9k/main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6969aba..3e485f7 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -345,12 +345,16 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
 	memset(&an->key_idx, 0, sizeof(an->key_idx));
 
 	ath_tx_node_init(sc, an);
+
+	ath_dynack_node_init(sc->sc_ah, an);
 }
 
 static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	ath_tx_node_cleanup(sc, an);
+
+	ath_dynack_node_deinit(sc->sc_ah, an);
 }
 
 void ath9k_tasklet(unsigned long data)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver
  2014-09-18  9:59 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Cedric Debarge
@ 2014-09-18 18:47 ` Lorenzo Bianconi
  0 siblings, 0 replies; 13+ messages in thread
From: Lorenzo Bianconi @ 2014-09-18 18:47 UTC (permalink / raw)
  To: Cedric Debarge; +Cc: linux-wireless

> On Tue, Sept 16, 2014 at 02:13:25AM +0200, Lorenzo Bianconi wrote:
>
> Hi,
>

Hi,

>> This patchset adds support for estimation of the ACK timeout (dynack) in ath9k driver. Ath9k dynack computes the > ACK timeout based on ACK frame RX timestamp, TX frame timestamp and frame duration.
>>
>> Ath9k dynack has been tested in indoor environment using AR9223/AR9280 chipset (running 3.17.0-rc5 kernel), on
>> 9Km PtoP link using AR9280 chipset (running OpenWRT trunk, compat-wireless-2014-05-22) and on an AP using AR9280 > chipset (running OpenWRT trunk, compat-wireless-2014-05-22) serving 35 STA with links up to 8Km
>
> During your indoor tests, did you managed to get precise enough timestamps to compute a significant ACK to (despite of short distances and multipaths)?
>

Dynack tx/rx timestamps are snapshots of PCU's timestamps (expressed
in TSF value).

> Previous tests have shown impressive bandwith gains (10% on a 9Km P2P link). Did you also get improvements in indoor environment?
>

In indoor environment I got the same performance obtained with a
static ACK timeout since LER was roughly 0%. Anyway I guess dynack
should be enabled just on outdoor "long" links (like ones tested by
Philippe) since that environment is really sensitive to ACK timeout.

> Thanks,
>
> Cédric DEBARGE

Regards,
Lorenzo

-- 
UNIX is Sexy: who | grep -i blonde | talk; cd ~; wine; talk; touch;
unzip; touch; strip; gasp; finger; gasp; mount; fsck; more; yes; gasp;
umount; make clean; sleep

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver
@ 2014-09-18  9:59 Cedric Debarge
  2014-09-18 18:47 ` Lorenzo Bianconi
  0 siblings, 1 reply; 13+ messages in thread
From: Cedric Debarge @ 2014-09-18  9:59 UTC (permalink / raw)
  To: lorenzo.bianconi83; +Cc: linux-wireless

On Tue, Sept 16, 2014 at 02:13:25AM +0200, Lorenzo Bianconi wrote:

Hi,

> This patchset adds support for estimation of the ACK timeout (dynack) in ath9k driver. Ath9k dynack computes the > ACK timeout based on ACK frame RX timestamp, TX frame timestamp and frame duration.
> 
> Ath9k dynack has been tested in indoor environment using AR9223/AR9280 chipset (running 3.17.0-rc5 kernel), on
> 9Km PtoP link using AR9280 chipset (running OpenWRT trunk, compat-wireless-2014-05-22) and on an AP using AR9280 > chipset (running OpenWRT trunk, compat-wireless-2014-05-22) serving 35 STA with links up to 8Km

During your indoor tests, did you managed to get precise enough timestamps to compute a significant ACK to (despite of short distances and multipaths)?

Previous tests have shown impressive bandwith gains (10% on a 9Km P2P link). Did you also get improvements in indoor environment?
 
Thanks,

Cédric DEBARGE

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2014-09-18 18:47 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-16  0:13 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 01/10] ath9k: export methods related to ACK timeout estimation Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 02/10] ath9k: add duration field to ath_tx_status Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 03/10] ath9k: add dynamic ACK timeout estimation Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 04/10] ath9k: add config for (en|dis)abling " Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 05/10] ath9k: do not overwrite " Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 06/10] ath9k: add sampling methods for (tx|rx) timestamp Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 07/10] ath9k: enable control frame reception Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 08/10] ath9k: add debugfs support for dynack Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 09/10] ath9k: enable dynack using set_coverage_class codepath Lorenzo Bianconi
2014-09-16  0:13 ` [PATCHv2 10/10] ath9k: initialize ath_node linked list Lorenzo Bianconi
2014-09-18  9:59 [PATCHv2 00/10] add support for ACK timeout estimation in ath9k driver Cedric Debarge
2014-09-18 18:47 ` Lorenzo Bianconi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.