Skip to contentSkip to conversation

add support for ack timeout estimation in ath9k driver

PATCH Superseded Lorenzo Bianconi 3 participants 16 messages Jul 20, 2014 – Jul 22, 2014

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover add support for ack timeout estimation in ath9k driver

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.16.0-rc5 kernel) and on 9Km PtoP link using AR9280 chipset (running OpenWRT trunk, compat-wireless-2014-05-22)

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: add ath9k_enable_dynack() method
ath9k: initialize ath_node linked list

 drivers/net/wireless/ath/ath.h              |   2 +
 drivers/net/wireless/ath/ath9k/Kconfig      |   7 +
 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     | 345 ++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dynack.h     |  96 ++++++++
 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       |  38 +++
 drivers/net/wireless/ath/ath9k/recv.c       |   7 +-
 drivers/net/wireless/ath/ath9k/xmit.c       |   5 +
 15 files changed, 570 insertions(+), 4 deletions(-)
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.h
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/10 ath9k: export methods related to ack timeout estimation

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 dynamic ack timeout estimation

---
 drivers/net/wireless/ath/ath9k/hw.c | 6 +++---
 drivers/net/wireless/ath/ath9k/hw.h | 4 ++++
 2 files changed, 7 insertions(+), 3 deletions(-)
drivers/net/wireless/ath/ath9k/hw.c +3 -3
index fd0158f..e88896c 100644
@@ -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));
drivers/net/wireless/ath/ath9k/hw.h +4 -0
index 51b4ebe..f36d971 100644
@@ -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)
 {
Signature · 1 line
1.9.1
#2 lore raw

PATCH 2/10 ath9k: add duration field to ath_tx_status

In reply to Lorenzo Bianconi

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 dynamic ack timeout processing

---
 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(+)
drivers/net/wireless/ath/ath9k/ar9002_mac.c +7 -0
index 59af9f9..669cb37 100644
@@ -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;
 }
 
drivers/net/wireless/ath/ath9k/ar9003_mac.c +9 -0
index 71e38e8..e5f7c11 100644
@@ -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;
drivers/net/wireless/ath/ath9k/mac.h +1 -0
index 6c56caf..cd05a77 100644
@@ -121,6 +121,7 @@ struct ath_tx_status {
 	u32 evm0;
 	u32 evm1;
 	u32 evm2;
+	u32 duration[4];
 };
 
 struct ath_rx_status {
Signature · 1 line
1.9.1
#3 lore raw

PATCH 3/10 ath9k: add dynamic ack timeout estimation

In reply to Lorenzo Bianconi

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

---
 drivers/net/wireless/ath/ath.h          |   2 +
 drivers/net/wireless/ath/ath9k/ath9k.h  |   3 +
 drivers/net/wireless/ath/ath9k/dynack.c | 345 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/dynack.h |  96 +++++++++
 drivers/net/wireless/ath/ath9k/hw.c     |   2 +
 drivers/net/wireless/ath/ath9k/hw.h     |   3 +
 6 files changed, 451 insertions(+)
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.c
 create mode 100644 drivers/net/wireless/ath/ath9k/dynack.h
drivers/net/wireless/ath/ath.h +2 -0
index fd9e530..4e51072 100644
@@ -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
@@ -261,6 +262,7 @@ enum ATH_DEBUG {
 	ATH_DBG_MCI		= 0x00008000,
 	ATH_DBG_DFS		= 0x00010000,
 	ATH_DBG_WOW		= 0x00020000,
+	ATH_DBG_DYNACK		= 0x00040000,
 	ATH_DBG_ANY		= 0xffffffff
 };
 
drivers/net/wireless/ath/ath9k/ath9k.h +3 -0
index 7fc13a8..8f2c44d 100644
@@ -273,6 +273,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 {
drivers/net/wireless/ath/ath9k/dynack.c new file +345 -0

345 lines not on this page · raw message

drivers/net/wireless/ath/ath9k/dynack.h new file +96 -0

96 lines not on this page · raw message

drivers/net/wireless/ath/ath9k/hw.c +2 -0
index e88896c..9a6b113 100644
@@ -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);
drivers/net/wireless/ath/ath9k/hw.h +3 -0
index f36d971..b9eef33 100644
@@ -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 {
Signature · 1 line
1.9.1
#4 lore raw

PATCH 4/10 ath9k: add config for (en|dis)abling ack timeout estimation

In reply to Lorenzo Bianconi

Add ack timeout estimation to ath9k Makefile

---
 drivers/net/wireless/ath/ath9k/Kconfig  | 7 +++++++
 drivers/net/wireless/ath/ath9k/Makefile | 3 +++
 2 files changed, 10 insertions(+)
drivers/net/wireless/ath/ath9k/Kconfig +7 -0
index 8fcc029..ee61a4c 100644
@@ -151,3 +151,10 @@ config ATH9K_HTC_DEBUGFS
 	depends on ATH9K_HTC && DEBUG_FS
 	---help---
 	  Say Y, if you need access to ath9k_htc's statistics.
+
+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
drivers/net/wireless/ath/ath9k/Makefile +3 -0
index 6b4020a..73704c1 100644
@@ -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
Signature · 1 line
1.9.1
#5 lore raw

PATCH 5/10 ath9k: do not overwrite ack timeout estimation

In reply to Lorenzo Bianconi

Do not overwrite ack timeout estimation in ath9k_hw_init_global_settings() if dynack processing is enabled

---
 drivers/net/wireless/ath/ath9k/hw.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/net/wireless/ath/ath9k/hw.c +8 -0
index 9a6b113..b2ca47a 100644
@@ -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);
Signature · 1 line
1.9.1
#6 lore raw

PATCH 6/10 ath9k: add sampling methods for (tx|rx) timestamp

In reply to Lorenzo Bianconi

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()

---
 drivers/net/wireless/ath/ath9k/recv.c | 5 +++++
 drivers/net/wireless/ath/ath9k/xmit.c | 5 +++++
 2 files changed, 10 insertions(+)
drivers/net/wireless/ath/ath9k/recv.c +5 -0
index 74ab1d0..ad317a4 100644
@@ -991,6 +991,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;
@@ -1120,6 +1121,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:
drivers/net/wireless/ath/ath9k/xmit.c +5 -0
index 3611529..122ec25 100644
@@ -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
Signature · 1 line
1.9.1
#7 lore raw

PATCH 7/10 ath9k: enable control frame reception

In reply to Lorenzo Bianconi

Enable control frame reception if dynamic ack processing is enabled

---
 drivers/net/wireless/ath/ath9k/recv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/ath9k/recv.c +1 -1
index ad317a4..cc5ba4a 100644
@@ -398,7 +398,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	if (sc->sc_ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
-	if (sc->rx.rxfilter & FIF_CONTROL)
+	if ((sc->rx.rxfilter & FIF_CONTROL) || sc->sc_ah->dynack.enabled)
 		rfilt |= ATH9K_RX_FILTER_CONTROL;
 
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
Signature · 1 line
1.9.1
#8 lore raw

PATCH 8/10 ath9k: add debugfs support for dynack

In reply to Lorenzo Bianconi

Add ack_to entry to debugfs in order to dump current ack timeout value.

---
 drivers/net/wireless/ath/ath9k/debug.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
drivers/net/wireless/ath/ath9k/debug.c +28 -0
index d227936..8d77b7a 100644
@@ -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;
 }
Signature · 1 line
1.9.1
#9 lore raw

PATCH 9/10 ath9k: add ath9k_enable_dynack() method

In reply to Lorenzo Bianconi

Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm. Moreover disable dynack if the coverage class has been configured

---
 drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +34 -0
index e6ac8d2..52ca884 100644
@@ -1970,6 +1970,14 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	mutex_lock(&sc->mutex);
 	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);
@@ -1977,6 +1985,28 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	mutex_unlock(&sc->mutex);
 }
 
+#ifdef CONFIG_ATH9K_DYNACK
+static int ath9k_enable_dynack(struct ieee80211_hw *hw)
+{
+	u32 rfilt;
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+
+	if (config_enabled(CONFIG_ATH9K_TX99))
+		return -EOPNOTSUPP;
+
+	if (!ah->dynack.enabled) {
+		ath_dynack_reset(ah);
+
+		ah->dynack.enabled = true;
+		rfilt = ath_calcrxfilter(sc);
+		ath9k_hw_setrxfilter(ah, rfilt);
+	}
+
+	return 0;
+}
+#endif
+
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
 	int i, npend = 0;
@@ -2651,4 +2681,8 @@ struct ieee80211_ops ath9k_ops = {
 #endif
 	.sw_scan_start	    = ath9k_sw_scan_start,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
+
+#ifdef CONFIG_ATH9K_DYNACK
+	.enable_dynack      = ath9k_enable_dynack,
+#endif
 };
Signature · 1 line
1.9.1
#10 lore raw

PATCH 9/10 ath9k: add ath9k_enable_dynack() method

Quoted 57 lines · Lorenzo Bianconi

Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm. Moreover disable dynack if the coverage class has been configured

---
 drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +30 -0
index e6ac8d2..52ca884 100644
@@ -1970,6 +1970,14 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	mutex_lock(&sc->mutex);
 	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);
@@ -1977,6 +1985,28 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 	mutex_unlock(&sc->mutex);
 }
 
+#ifdef CONFIG_ATH9K_DYNACK
+static int ath9k_enable_dynack(struct ieee80211_hw *hw)
+{
+	u32 rfilt;
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+
+	if (config_enabled(CONFIG_ATH9K_TX99))
+		return -EOPNOTSUPP;
+
+	if (!ah->dynack.enabled) {
+		ath_dynack_reset(ah);
+
+		ah->dynack.enabled = true;
+		rfilt = ath_calcrxfilter(sc);
+		ath9k_hw_setrxfilter(ah, rfilt);
+	}
+
+	return 0;
+}
+#endif
+
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
 	int i, npend = 0;

drivers/net/wireless/ath/ath9k/main.c struct ieee80211_ops ath9k_ops = { · line 2688

Quoted 8 lines
drivers/net/wireless/ath/ath9k/main.c +4 -0
@@ -2651,4 +2681,8 @@ struct ieee80211_ops ath9k_ops = {
 #endif
 	.sw_scan_start	    = ath9k_sw_scan_start,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
+
+#ifdef CONFIG_ATH9K_DYNACK
+	.enable_dynack      = ath9k_enable_dynack,
+#endif
 };

CC drivers/net/wireless/ath/ath9k/main.o
drivers/net/wireless/ath/ath9k/main.c:2690:2: error: unknown field ?enable_dynack? specified in initializer
.enable_dynack = ath9k_enable_dynack,
^
drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: initialization from incompatible pointer type [enabled by default] drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: (near initialization for ?ath9k_ops.get_stats?) [enabled by default] make[3]: *** [drivers/net/wireless/ath/ath9k/main.o] Error 1
make[2]: *** [drivers/net/wireless/ath/ath9k] Error 2
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2

Missing a header file change?

John

Signature · 2 lines
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.
#11 lore raw

PATCH 9/10 ath9k: add ath9k_enable_dynack() method

Hi John,

Quoted 78 lines · Lorenzo Bianconi
Quoted 57 lines

Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm. Moreover disable dynack if the coverage class has been configured

---
 drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +30 -0
index e6ac8d2..52ca884 100644
@@ -1970,6 +1970,14 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_lock(&sc->mutex);
      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);
@@ -1977,6 +1985,28 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_unlock(&sc->mutex);
 }
 
+#ifdef CONFIG_ATH9K_DYNACK
+static int ath9k_enable_dynack(struct ieee80211_hw *hw)
+{
+     u32 rfilt;
+     struct ath_softc *sc = hw->priv;
+     struct ath_hw *ah = sc->sc_ah;
+
+     if (config_enabled(CONFIG_ATH9K_TX99))
+             return -EOPNOTSUPP;
+
+     if (!ah->dynack.enabled) {
+             ath_dynack_reset(ah);
+
+             ah->dynack.enabled = true;
+             rfilt = ath_calcrxfilter(sc);
+             ath9k_hw_setrxfilter(ah, rfilt);
+     }
+
+     return 0;
+}
+#endif
+
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
      int i, npend = 0;

drivers/net/wireless/ath/ath9k/main.c struct ieee80211_ops ath9k_ops = { · line 2688

Quoted 8 lines
drivers/net/wireless/ath/ath9k/main.c +4 -0
@@ -2651,4 +2681,8 @@ struct ieee80211_ops ath9k_ops = {
 #endif
      .sw_scan_start      = ath9k_sw_scan_start,
      .sw_scan_complete   = ath9k_sw_scan_complete,
+
+#ifdef CONFIG_ATH9K_DYNACK
+     .enable_dynack      = ath9k_enable_dynack,
+#endif
 };

CC drivers/net/wireless/ath/ath9k/main.o
drivers/net/wireless/ath/ath9k/main.c:2690:2: error: unknown field ?enable_dynack? specified in initializer
.enable_dynack = ath9k_enable_dynack,
^
drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: initialization from incompatible pointer type [enabled by default] drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: (near initialization for ?ath9k_ops.get_stats?) [enabled by default] make[3]: *** [drivers/net/wireless/ath/ath9k/main.o] Error 1
make[2]: *** [drivers/net/wireless/ath/ath9k] Error 2
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2

Quoted 2 lines

Missing a header file change?

The function pointer is defined in "configure ack timeout estimation algorithm through mac80211 stack" patchset sent on linux-wireless. Anyway I will send patchset v3 to take Johannes's hint.

Quoted 4 lines

John
--
John W. Linville Someday the world will need a hero, and you
linville at tuxdriver.com might be all we have. Be ready.

Best regards,
Lorenzo

Signature · 3 lines
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
#12 lore raw

PATCH 9/10 ath9k: add ath9k_enable_dynack() method

Quoted 80 lines · Lorenzo Bianconi

Hi John,

Quoted 78 lines · Lorenzo Bianconi
Quoted 57 lines

Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm. Moreover disable dynack if the coverage class has been configured

---
 drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +30 -0
index e6ac8d2..52ca884 100644
@@ -1970,6 +1970,14 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_lock(&sc->mutex);
      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);
@@ -1977,6 +1985,28 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_unlock(&sc->mutex);
 }
 
+#ifdef CONFIG_ATH9K_DYNACK
+static int ath9k_enable_dynack(struct ieee80211_hw *hw)
+{
+     u32 rfilt;
+     struct ath_softc *sc = hw->priv;
+     struct ath_hw *ah = sc->sc_ah;
+
+     if (config_enabled(CONFIG_ATH9K_TX99))
+             return -EOPNOTSUPP;
+
+     if (!ah->dynack.enabled) {
+             ath_dynack_reset(ah);
+
+             ah->dynack.enabled = true;
+             rfilt = ath_calcrxfilter(sc);
+             ath9k_hw_setrxfilter(ah, rfilt);
+     }
+
+     return 0;
+}
+#endif
+
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
      int i, npend = 0;

drivers/net/wireless/ath/ath9k/main.c struct ieee80211_ops ath9k_ops = { · line 2688

Quoted 8 lines
drivers/net/wireless/ath/ath9k/main.c +4 -0
@@ -2651,4 +2681,8 @@ struct ieee80211_ops ath9k_ops = {
 #endif
      .sw_scan_start      = ath9k_sw_scan_start,
      .sw_scan_complete   = ath9k_sw_scan_complete,
+
+#ifdef CONFIG_ATH9K_DYNACK
+     .enable_dynack      = ath9k_enable_dynack,
+#endif
 };

CC drivers/net/wireless/ath/ath9k/main.o
drivers/net/wireless/ath/ath9k/main.c:2690:2: error: unknown field ?enable_dynack? specified in initializer
.enable_dynack = ath9k_enable_dynack,
^
drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: initialization from incompatible pointer type [enabled by default] drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: (near initialization for ?ath9k_ops.get_stats?) [enabled by default] make[3]: *** [drivers/net/wireless/ath/ath9k/main.o] Error 1
make[2]: *** [drivers/net/wireless/ath/ath9k] Error 2
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2

Quoted 6 lines
Quoted 2 lines

Missing a header file change?

The function pointer is defined in "configure ack timeout estimation algorithm through mac80211 stack" patchset sent on linux-wireless. Anyway I will send patchset v3 to take Johannes's hint.

Perhaps you should post them all together, or keep this series as RFC until the other one gets merged?

Signature · 2 lines
John W. Linville		Someday the world will need a hero, and you
linville at tuxdriver.com			might be all we have.  Be ready.
#13 lore raw

PATCH 9/10 ath9k: add ath9k_enable_dynack() method

Quoted 84 lines · Lorenzo Bianconi
Quoted 83 lines

Hi John,

Quoted 80 lines · Lorenzo Bianconi
Quoted 57 lines

Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm. Moreover disable dynack if the coverage class has been configured

---
 drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +30 -0
index e6ac8d2..52ca884 100644
@@ -1970,6 +1970,14 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_lock(&sc->mutex);
      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);
@@ -1977,6 +1985,28 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
      mutex_unlock(&sc->mutex);
 }
 
+#ifdef CONFIG_ATH9K_DYNACK
+static int ath9k_enable_dynack(struct ieee80211_hw *hw)
+{
+     u32 rfilt;
+     struct ath_softc *sc = hw->priv;
+     struct ath_hw *ah = sc->sc_ah;
+
+     if (config_enabled(CONFIG_ATH9K_TX99))
+             return -EOPNOTSUPP;
+
+     if (!ah->dynack.enabled) {
+             ath_dynack_reset(ah);
+
+             ah->dynack.enabled = true;
+             rfilt = ath_calcrxfilter(sc);
+             ath9k_hw_setrxfilter(ah, rfilt);
+     }
+
+     return 0;
+}
+#endif
+
 static bool ath9k_has_tx_pending(struct ath_softc *sc)
 {
      int i, npend = 0;

drivers/net/wireless/ath/ath9k/main.c struct ieee80211_ops ath9k_ops = { · line 2688

Quoted 8 lines
drivers/net/wireless/ath/ath9k/main.c +4 -0
@@ -2651,4 +2681,8 @@ struct ieee80211_ops ath9k_ops = {
 #endif
      .sw_scan_start      = ath9k_sw_scan_start,
      .sw_scan_complete   = ath9k_sw_scan_complete,
+
+#ifdef CONFIG_ATH9K_DYNACK
+     .enable_dynack      = ath9k_enable_dynack,
+#endif
 };

CC drivers/net/wireless/ath/ath9k/main.o
drivers/net/wireless/ath/ath9k/main.c:2690:2: error: unknown field ?enable_dynack? specified in initializer
.enable_dynack = ath9k_enable_dynack,
^
drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: initialization from incompatible pointer type [enabled by default] drivers/net/wireless/ath/ath9k/main.c:2690:2: warning: (near initialization for ?ath9k_ops.get_stats?) [enabled by default] make[3]: *** [drivers/net/wireless/ath/ath9k/main.o] Error 1
make[2]: *** [drivers/net/wireless/ath/ath9k] Error 2
make[1]: *** [drivers/net/wireless/ath] Error 2
make: *** [drivers/net/wireless/] Error 2

Missing a header file change?

Quoted 7 lines
Quoted 3 lines

The function pointer is defined in "configure ack timeout estimation algorithm through mac80211 stack" patchset sent on linux-wireless. Anyway I will send patchset v3 to take Johannes's hint.

Perhaps you should post them all together, or keep this series as RFC until the other one gets merged?

Ack. First of all I will include Johannes's hints in "configure ack timeout estimation algorithm through mac80211 stack" in such a way the function pointer is merged and then I will send a new patchset for dynack.

Best regards,
Lorenzo

Quoted 3 lines

--
John W. Linville Someday the world will need a hero, and you
linville at tuxdriver.com might be all we have. Be ready.

Signature · 3 lines
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
#14 lore raw

PATCH 10/10 ath9k: initialize ath_node linked list

In reply to Lorenzo Bianconi

Initialize neighbor linked list used by estimation algorithm to compute maximum sta ack timeout

---
 drivers/net/wireless/ath/ath9k/main.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/ath9k/main.c +4 -0
index 52ca884..9a7fe6d 100644
@@ -358,12 +358,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)
Signature · 1 line
1.9.1
#15 lore raw

cover add support for ack timeout estimation in ath9k driver

In reply to Lorenzo Bianconi

Hi Lorenzo,
Since friday I enable dynack on an AP who serve 35 sta (on 2 MIMO 2x2 5ghz wireless cards 12&23) in outdoor (up to 8 kms) results are good. latency is good for all sta
I?ll take your new patches and make one for openwrt and, recompile
Thanks;
Philippe

Le 20 juil. 2014 ? 14:31, Lorenzo Bianconi <[email protected]> a ?crit :

Quoted 55 lines

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.16.0-rc5 kernel) and on 9Km PtoP link using AR9280 chipset (running OpenWRT trunk, compat-wireless-2014-05-22)

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: add ath9k_enable_dynack() method
ath9k: initialize ath_node linked list

drivers/net/wireless/ath/ath.h              |   2 +
drivers/net/wireless/ath/ath9k/Kconfig      |   7 +
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     | 345 ++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/dynack.h     |  96 ++++++++
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       |  38 +++
drivers/net/wireless/ath/ath9k/recv.c       |   7 +-
drivers/net/wireless/ath/ath9k/xmit.c       |   5 +
15 files changed, 570 insertions(+), 4 deletions(-)

create mode 100644 drivers/net/wireless/ath/ath9k/dynack.c create mode 100644 drivers/net/wireless/ath/ath9k/dynack.h

Signature · 1 line
1.9.1