* [PATCH 01/10] ath9k: export methods related to ack timeout estimation
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 02/10] ath9k: add duration field to ath_tx_status Lorenzo Bianconi
` (9 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
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
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 fd0158f..e88896c 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] 16+ messages in thread* [PATCH 02/10] ath9k: add duration field to ath_tx_status
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 01/10] ath9k: export methods related to ack timeout estimation Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 03/10] ath9k: add dynamic ack timeout estimation Lorenzo Bianconi
` (8 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
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
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] 16+ messages in thread* [PATCH 03/10] ath9k: add dynamic ack timeout estimation
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 01/10] ath9k: export methods related to ack timeout estimation Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 02/10] ath9k: add duration field to ath_tx_status Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 04/10] ath9k: add config for (en|dis)abling " Lorenzo Bianconi
` (7 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
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 | 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
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index fd9e530..4e51072 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
@@ -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
};
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 7fc13a8..8f2c44d 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -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 {
diff --git a/drivers/net/wireless/ath/ath9k/dynack.c b/drivers/net/wireless/ath/ath9k/dynack.c
new file mode 100644
index 0000000..b4fbe34
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dynack.c
@@ -0,0 +1,345 @@
+/*
+ * 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;
+}
+
+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 based on 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 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 ts 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 ts 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);
+}
+
diff --git a/drivers/net/wireless/ath/ath9k/dynack.h b/drivers/net/wireless/ath/ath9k/dynack.h
new file mode 100644
index 0000000..b1a03fa
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/dynack.h
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+/**
+ * ath_dyn_rxbuf - ack frame ring 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];
+};
+/**
+ * ath_dyn_txbuf - tx frame ring buffer
+ */
+struct ath_dyn_txbuf {
+ u16 h_rb, t_rb;
+ struct haddr_pair addr[ATH_DYN_BUF];
+ struct ts_info ts[ATH_DYN_BUF];
+};
+
+/**
+ * ath_dynack - dyn ack 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_reset(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 e88896c..9a6b113 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] 16+ messages in thread* [PATCH 04/10] ath9k: add config for (en|dis)abling ack timeout estimation
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (2 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 03/10] ath9k: add dynamic ack timeout estimation Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 05/10] ath9k: do not overwrite " Lorenzo Bianconi
` (6 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
Add ack timeout estimation to ath9k Makefile
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
drivers/net/wireless/ath/ath9k/Kconfig | 7 +++++++
drivers/net/wireless/ath/ath9k/Makefile | 3 +++
2 files changed, 10 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 8fcc029..ee61a4c 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -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
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] 16+ messages in thread* [PATCH 05/10] ath9k: do not overwrite ack timeout estimation
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (3 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 04/10] ath9k: add config for (en|dis)abling " Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 06/10] ath9k: add sampling methods for (tx|rx) timestamp Lorenzo Bianconi
` (5 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
Do not overwrite ack timeout estimation in ath9k_hw_init_global_settings() if
dynack processing is 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 9a6b113..b2ca47a 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] 16+ messages in thread* [PATCH 06/10] ath9k: add sampling methods for (tx|rx) timestamp
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (4 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 05/10] ath9k: do not overwrite " Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 07/10] ath9k: enable control frame reception Lorenzo Bianconi
` (4 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
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()
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 74ab1d0..ad317a4 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -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:
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3611529..122ec25 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] 16+ messages in thread* [PATCH 07/10] ath9k: enable control frame reception
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (5 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 06/10] ath9k: add sampling methods for (tx|rx) timestamp Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 08/10] ath9k: add debugfs support for dynack Lorenzo Bianconi
` (3 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
Enable control frame reception if dynamic ack processing is enabled
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
drivers/net/wireless/ath/ath9k/recv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ad317a4..cc5ba4a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -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) &&
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH 08/10] ath9k: add debugfs support for dynack
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (6 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 07/10] ath9k: enable control frame reception Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 12:31 ` [PATCH 09/10] ath9k: add ath9k_enable_dynack() method Lorenzo Bianconi
` (2 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
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 d227936..8d77b7a 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] 16+ messages in thread* [PATCH 09/10] ath9k: add ath9k_enable_dynack() method
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (7 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 08/10] ath9k: add debugfs support for dynack Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-22 18:02 ` John W. Linville
2014-07-20 12:31 ` [PATCH 10/10] ath9k: initialize ath_node linked list Lorenzo Bianconi
2014-07-20 14:05 ` [PATCH 00/10] add support for ack timeout estimation in ath9k driver Philippe DUCHEIN
10 siblings, 1 reply; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm.
Moreover disable dynack if the coverage class has been configured
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
---
drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index e6ac8d2..52ca884 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -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
};
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH 09/10] ath9k: add ath9k_enable_dynack() method
2014-07-20 12:31 ` [PATCH 09/10] ath9k: add ath9k_enable_dynack() method Lorenzo Bianconi
@ 2014-07-22 18:02 ` John W. Linville
2014-07-22 19:52 ` Lorenzo Bianconi
0 siblings, 1 reply; 16+ messages in thread
From: John W. Linville @ 2014-07-22 18:02 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: linux-wireless, ath9k-devel, Philippe Duchein
On Sun, Jul 20, 2014 at 02:31:25PM +0200, Lorenzo Bianconi wrote:
> Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm.
> Moreover disable dynack if the coverage class has been configured
>
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
> ---
> drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> index e6ac8d2..52ca884 100644
> --- a/drivers/net/wireless/ath/ath9k/main.c
> +++ b/drivers/net/wireless/ath/ath9k/main.c
> @@ -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
> };
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
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 09/10] ath9k: add ath9k_enable_dynack() method
2014-07-22 18:02 ` John W. Linville
@ 2014-07-22 19:52 ` Lorenzo Bianconi
2014-07-22 21:23 ` John W. Linville
0 siblings, 1 reply; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-22 19:52 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, ath9k-devel, Philippe Duchein
Hi John,
> On Sun, Jul 20, 2014 at 02:31:25PM +0200, Lorenzo Bianconi wrote:
>> Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm.
>> Moreover disable dynack if the coverage class has been configured
>>
>> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
>> ---
>> drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
>> 1 file changed, 34 insertions(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
>> index e6ac8d2..52ca884 100644
>> --- a/drivers/net/wireless/ath/ath9k/main.c
>> +++ b/drivers/net/wireless/ath/ath9k/main.c
>> @@ -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
>> };
>
> 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?
>
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.
> John
> --
> John W. Linville Someday the world will need a hero, and you
> linville@tuxdriver.com might be all we have. Be ready.
Best 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] 16+ messages in thread* Re: [PATCH 09/10] ath9k: add ath9k_enable_dynack() method
2014-07-22 19:52 ` Lorenzo Bianconi
@ 2014-07-22 21:23 ` John W. Linville
2014-07-22 22:17 ` Lorenzo Bianconi
0 siblings, 1 reply; 16+ messages in thread
From: John W. Linville @ 2014-07-22 21:23 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: linux-wireless, ath9k-devel, Philippe Duchein
On Tue, Jul 22, 2014 at 09:52:04PM +0200, Lorenzo Bianconi wrote:
> Hi John,
>
> > On Sun, Jul 20, 2014 at 02:31:25PM +0200, Lorenzo Bianconi wrote:
> >> Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm.
> >> Moreover disable dynack if the coverage class has been configured
> >>
> >> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
> >> ---
> >> drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
> >> 1 file changed, 34 insertions(+)
> >>
> >> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
> >> index e6ac8d2..52ca884 100644
> >> --- a/drivers/net/wireless/ath/ath9k/main.c
> >> +++ b/drivers/net/wireless/ath/ath9k/main.c
> >> @@ -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
> >> };
> >
> > 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?
> >
>
> 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?
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 09/10] ath9k: add ath9k_enable_dynack() method
2014-07-22 21:23 ` John W. Linville
@ 2014-07-22 22:17 ` Lorenzo Bianconi
0 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-22 22:17 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless, ath9k-devel, Philippe Duchein
> On Tue, Jul 22, 2014 at 09:52:04PM +0200, Lorenzo Bianconi wrote:
>> Hi John,
>>
>> > On Sun, Jul 20, 2014 at 02:31:25PM +0200, Lorenzo Bianconi wrote:
>> >> Add ath9k_enable_dynack() method to enable ack timeout estimation algorithm.
>> >> Moreover disable dynack if the coverage class has been configured
>> >>
>> >> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
>> >> ---
>> >> drivers/net/wireless/ath/ath9k/main.c | 34 ++++++++++++++++++++++++++++++++++
>> >> 1 file changed, 34 insertions(+)
>> >>
>> >> diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
>> >> index e6ac8d2..52ca884 100644
>> >> --- a/drivers/net/wireless/ath/ath9k/main.c
>> >> +++ b/drivers/net/wireless/ath/ath9k/main.c
>> >> @@ -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
>> >> };
>> >
>> > 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?
>> >
>>
>> 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
> --
> John W. Linville Someday the world will need a hero, and you
> linville@tuxdriver.com might be all we have. Be ready.
--
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] 16+ messages in thread
* [PATCH 10/10] ath9k: initialize ath_node linked list
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (8 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 09/10] ath9k: add ath9k_enable_dynack() method Lorenzo Bianconi
@ 2014-07-20 12:31 ` Lorenzo Bianconi
2014-07-20 14:05 ` [PATCH 00/10] add support for ack timeout estimation in ath9k driver Philippe DUCHEIN
10 siblings, 0 replies; 16+ messages in thread
From: Lorenzo Bianconi @ 2014-07-20 12:31 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, linville, Philippe Duchein
Initialize neighbor linked list used by estimation algorithm to compute 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 52ca884..9a7fe6d 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -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)
--
1.9.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH 00/10] add support for ack timeout estimation in ath9k driver
2014-07-20 12:31 [PATCH 00/10] add support for ack timeout estimation in ath9k driver Lorenzo Bianconi
` (9 preceding siblings ...)
2014-07-20 12:31 ` [PATCH 10/10] ath9k: initialize ath_node linked list Lorenzo Bianconi
@ 2014-07-20 14:05 ` Philippe DUCHEIN
10 siblings, 0 replies; 16+ messages in thread
From: Philippe DUCHEIN @ 2014-07-20 14:05 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: linux-wireless, ath9k-devel, linville
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 <lorenzo.bianconi83@gmail.com> a écrit :
> 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
>
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 16+ messages in thread