Revert "ath9k: Add airtime fairness scheduler"
This reverts commit 528f46d082
.
After this commit, several users reported stability issues. Revert it
now so it doesn't cause issues for the upcoming release
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
10f91525bc
commit
c296ba834d
9 changed files with 15 additions and 728 deletions
|
@ -1,651 +0,0 @@
|
||||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
|
|
||||||
Date: Mon, 5 Dec 2016 13:27:37 +0200
|
|
||||||
Subject: [PATCH] ath9k: Introduce airtime fairness scheduling between stations
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
This reworks the ath9k driver to schedule transmissions to connected
|
|
||||||
stations in a way that enforces airtime fairness between them. It
|
|
||||||
accomplishes this by measuring the time spent transmitting to or
|
|
||||||
receiving from a station at TX and RX completion, and accounting this to
|
|
||||||
a per-station, per-QoS level airtime deficit. Then, an FQ-CoDel based
|
|
||||||
deficit scheduler is employed at packet dequeue time, to control which
|
|
||||||
station gets the next transmission opportunity.
|
|
||||||
|
|
||||||
Airtime fairness can significantly improve the efficiency of the network
|
|
||||||
when station rates vary. The following throughput values are from a
|
|
||||||
simple three-station test scenario, where two stations operate at the
|
|
||||||
highest HT20 rate, and one station at the lowest, and the scheduler is
|
|
||||||
employed at the access point:
|
|
||||||
|
|
||||||
Before / After
|
|
||||||
Fast station 1: 19.17 / 25.09 Mbps
|
|
||||||
Fast station 2: 19.83 / 25.21 Mbps
|
|
||||||
Slow station: 2.58 / 1.77 Mbps
|
|
||||||
Total: 41.58 / 52.07 Mbps
|
|
||||||
|
|
||||||
The benefit of airtime fairness goes up the more stations are present.
|
|
||||||
In a 30-station test with one station artificially limited to 1 Mbps,
|
|
||||||
we have seen aggregate throughput go from 2.14 to 17.76 Mbps.
|
|
||||||
|
|
||||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
|
||||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
|
||||||
---
|
|
||||||
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
||||||
@@ -112,6 +112,8 @@ int ath_descdma_setup(struct ath_softc *
|
|
||||||
#define ATH_TXFIFO_DEPTH 8
|
|
||||||
#define ATH_TX_ERROR 0x01
|
|
||||||
|
|
||||||
+#define ATH_AIRTIME_QUANTUM 300 /* usec */
|
|
||||||
+
|
|
||||||
/* Stop tx traffic 1ms before the GO goes away */
|
|
||||||
#define ATH_P2P_PS_STOP_TIME 1000
|
|
||||||
|
|
||||||
@@ -247,6 +249,9 @@ struct ath_atx_tid {
|
|
||||||
bool has_queued;
|
|
||||||
};
|
|
||||||
|
|
||||||
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
|
|
||||||
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
|
|
||||||
+
|
|
||||||
struct ath_node {
|
|
||||||
struct ath_softc *sc;
|
|
||||||
struct ieee80211_sta *sta; /* station struct we're part of */
|
|
||||||
@@ -258,9 +263,12 @@ struct ath_node {
|
|
||||||
|
|
||||||
bool sleeping;
|
|
||||||
bool no_ps_filter;
|
|
||||||
+ s64 airtime_deficit[IEEE80211_NUM_ACS];
|
|
||||||
+ u32 airtime_rx_start;
|
|
||||||
|
|
||||||
#ifdef CPTCFG_ATH9K_STATION_STATISTICS
|
|
||||||
struct ath_rx_rate_stats rx_rate_stats;
|
|
||||||
+ struct ath_airtime_stats airtime_stats;
|
|
||||||
#endif
|
|
||||||
u8 key_idx[4];
|
|
||||||
|
|
||||||
@@ -317,10 +325,16 @@ struct ath_rx {
|
|
||||||
/* Channel Context */
|
|
||||||
/*******************/
|
|
||||||
|
|
||||||
+struct ath_acq {
|
|
||||||
+ struct list_head acq_new;
|
|
||||||
+ struct list_head acq_old;
|
|
||||||
+ spinlock_t lock;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
struct ath_chanctx {
|
|
||||||
struct cfg80211_chan_def chandef;
|
|
||||||
struct list_head vifs;
|
|
||||||
- struct list_head acq[IEEE80211_NUM_ACS];
|
|
||||||
+ struct ath_acq acq[IEEE80211_NUM_ACS];
|
|
||||||
int hw_queue_base;
|
|
||||||
|
|
||||||
/* do not dereference, use for comparison only */
|
|
||||||
@@ -575,6 +589,8 @@ void ath_txq_schedule_all(struct ath_sof
|
|
||||||
int ath_tx_init(struct ath_softc *sc, int nbufs);
|
|
||||||
int ath_txq_update(struct ath_softc *sc, int qnum,
|
|
||||||
struct ath9k_tx_queue_info *q);
|
|
||||||
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
|
||||||
+ int width, int half_gi, bool shortPreamble);
|
|
||||||
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
|
|
||||||
void ath_assign_seq(struct ath_common *common, struct sk_buff *skb);
|
|
||||||
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
|
||||||
@@ -963,6 +979,11 @@ void ath_ant_comb_scan(struct ath_softc
|
|
||||||
|
|
||||||
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
|
||||||
|
|
||||||
+#define AIRTIME_USE_TX BIT(0)
|
|
||||||
+#define AIRTIME_USE_RX BIT(1)
|
|
||||||
+#define AIRTIME_USE_NEW_QUEUES BIT(2)
|
|
||||||
+#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
|
|
||||||
+
|
|
||||||
struct ath_softc {
|
|
||||||
struct ieee80211_hw *hw;
|
|
||||||
struct device *dev;
|
|
||||||
@@ -1005,6 +1026,8 @@ struct ath_softc {
|
|
||||||
short nbcnvifs;
|
|
||||||
unsigned long ps_usecount;
|
|
||||||
|
|
||||||
+ u16 airtime_flags; /* AIRTIME_* */
|
|
||||||
+
|
|
||||||
struct ath_rx rx;
|
|
||||||
struct ath_tx tx;
|
|
||||||
struct ath_beacon beacon;
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/channel.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/channel.c
|
|
||||||
@@ -118,8 +118,11 @@ void ath_chanctx_init(struct ath_softc *
|
|
||||||
INIT_LIST_HEAD(&ctx->vifs);
|
|
||||||
ctx->txpower = ATH_TXPOWER_MAX;
|
|
||||||
ctx->flush_timeout = HZ / 5; /* 200ms */
|
|
||||||
- for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
|
|
||||||
- INIT_LIST_HEAD(&ctx->acq[j]);
|
|
||||||
+ for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) {
|
|
||||||
+ INIT_LIST_HEAD(&ctx->acq[j].acq_new);
|
|
||||||
+ INIT_LIST_HEAD(&ctx->acq[j].acq_old);
|
|
||||||
+ spin_lock_init(&ctx->acq[j].lock);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1345,8 +1348,11 @@ void ath9k_offchannel_init(struct ath_so
|
|
||||||
ctx->txpower = ATH_TXPOWER_MAX;
|
|
||||||
cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
|
|
||||||
|
|
||||||
- for (i = 0; i < ARRAY_SIZE(ctx->acq); i++)
|
|
||||||
- INIT_LIST_HEAD(&ctx->acq[i]);
|
|
||||||
+ for (i = 0; i < ARRAY_SIZE(ctx->acq); i++) {
|
|
||||||
+ INIT_LIST_HEAD(&ctx->acq[i].acq_new);
|
|
||||||
+ INIT_LIST_HEAD(&ctx->acq[i].acq_old);
|
|
||||||
+ spin_lock_init(&ctx->acq[i].lock);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
sc->offchannel.chan.offchannel = true;
|
|
||||||
}
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
|
||||||
@@ -1399,5 +1399,8 @@ int ath9k_init_debug(struct ath_hw *ah)
|
|
||||||
debugfs_create_file("tpc", S_IRUSR | S_IWUSR,
|
|
||||||
sc->debug.debugfs_phy, sc, &fops_tpc);
|
|
||||||
|
|
||||||
+ debugfs_create_u16("airtime_flags", S_IRUSR | S_IWUSR,
|
|
||||||
+ sc->debug.debugfs_phy, &sc->airtime_flags);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/debug.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/debug.h
|
|
||||||
@@ -221,6 +221,11 @@ struct ath_rx_rate_stats {
|
|
||||||
} cck_stats[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct ath_airtime_stats {
|
|
||||||
+ u32 rx_airtime;
|
|
||||||
+ u32 tx_airtime;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
#define ANT_MAIN 0
|
|
||||||
#define ANT_ALT 1
|
|
||||||
|
|
||||||
@@ -314,12 +319,20 @@ ath9k_debug_sync_cause(struct ath_softc
|
|
||||||
void ath_debug_rate_stats(struct ath_softc *sc,
|
|
||||||
struct ath_rx_status *rs,
|
|
||||||
struct sk_buff *skb);
|
|
||||||
+void ath_debug_airtime(struct ath_softc *sc,
|
|
||||||
+ struct ath_node *an,
|
|
||||||
+ u32 rx, u32 tx);
|
|
||||||
#else
|
|
||||||
static inline void ath_debug_rate_stats(struct ath_softc *sc,
|
|
||||||
struct ath_rx_status *rs,
|
|
||||||
struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
+static inline void ath_debug_airtime(struct ath_softc *sc,
|
|
||||||
+ struct ath_node *an,
|
|
||||||
+ u32 rx, u32 tx)
|
|
||||||
+{
|
|
||||||
+}
|
|
||||||
#endif /* CPTCFG_ATH9K_STATION_STATISTICS */
|
|
||||||
|
|
||||||
#endif /* DEBUG_H */
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
|
|
||||||
@@ -242,6 +242,59 @@ static const struct file_operations fops
|
|
||||||
.llseek = default_llseek,
|
|
||||||
};
|
|
||||||
|
|
||||||
+void ath_debug_airtime(struct ath_softc *sc,
|
|
||||||
+ struct ath_node *an,
|
|
||||||
+ u32 rx,
|
|
||||||
+ u32 tx)
|
|
||||||
+{
|
|
||||||
+ struct ath_airtime_stats *astats = &an->airtime_stats;
|
|
||||||
+
|
|
||||||
+ astats->rx_airtime += rx;
|
|
||||||
+ astats->tx_airtime += tx;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t read_airtime(struct file *file, char __user *user_buf,
|
|
||||||
+ size_t count, loff_t *ppos)
|
|
||||||
+{
|
|
||||||
+ struct ath_node *an = file->private_data;
|
|
||||||
+ struct ath_airtime_stats *astats;
|
|
||||||
+ static const char *qname[4] = {
|
|
||||||
+ "VO", "VI", "BE", "BK"
|
|
||||||
+ };
|
|
||||||
+ u32 len = 0, size = 256;
|
|
||||||
+ char *buf;
|
|
||||||
+ size_t retval;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ buf = kzalloc(size, GFP_KERNEL);
|
|
||||||
+ if (buf == NULL)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ astats = &an->airtime_stats;
|
|
||||||
+
|
|
||||||
+ len += scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_airtime);
|
|
||||||
+ len += scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_airtime);
|
|
||||||
+ len += scnprintf(buf + len, size - len, "Deficit: ");
|
|
||||||
+ for (i = 0; i < 4; i++)
|
|
||||||
+ len += scnprintf(buf+len, size - len, "%s: %lld us ", qname[i], an->airtime_deficit[i]);
|
|
||||||
+ if (len < size)
|
|
||||||
+ buf[len++] = '\n';
|
|
||||||
+
|
|
||||||
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
|
||||||
+ kfree(buf);
|
|
||||||
+
|
|
||||||
+ return retval;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static const struct file_operations fops_airtime = {
|
|
||||||
+ .read = read_airtime,
|
|
||||||
+ .open = simple_open,
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+ .llseek = default_llseek,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
|
|
||||||
struct ieee80211_vif *vif,
|
|
||||||
struct ieee80211_sta *sta,
|
|
||||||
@@ -251,4 +304,5 @@ void ath9k_sta_add_debugfs(struct ieee80
|
|
||||||
|
|
||||||
debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr);
|
|
||||||
debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv);
|
|
||||||
+ debugfs_create_file("airtime", S_IRUGO, dir, an, &fops_airtime);
|
|
||||||
}
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
|
||||||
@@ -620,6 +620,8 @@ static int ath9k_init_softc(u16 devid, s
|
|
||||||
|
|
||||||
/* Will be cleared in ath9k_start() */
|
|
||||||
set_bit(ATH_OP_INVALID, &common->op_flags);
|
|
||||||
+ sc->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX |
|
|
||||||
+ AIRTIME_USE_NEW_QUEUES);
|
|
||||||
|
|
||||||
sc->sc_ah = ah;
|
|
||||||
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
@@ -70,10 +70,10 @@ static bool ath9k_has_pending_frames(str
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (txq->mac80211_qnum >= 0) {
|
|
||||||
- struct list_head *list;
|
|
||||||
+ struct ath_acq *acq;
|
|
||||||
|
|
||||||
- list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
|
||||||
- if (!list_empty(list))
|
|
||||||
+ acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
|
||||||
+ if (!list_empty(&acq->acq_new) || !list_empty(&acq->acq_old))
|
|
||||||
pending = true;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/recv.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/recv.c
|
|
||||||
@@ -991,6 +991,70 @@ static void ath9k_apply_ampdu_details(st
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void ath_rx_count_airtime(struct ath_softc *sc,
|
|
||||||
+ struct ath_rx_status *rs,
|
|
||||||
+ struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ struct ath_node *an;
|
|
||||||
+ struct ath_acq *acq;
|
|
||||||
+ struct ath_vif *avp;
|
|
||||||
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
||||||
+ struct ath_hw *ah = sc->sc_ah;
|
|
||||||
+ struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
+ struct ieee80211_sta *sta;
|
|
||||||
+ struct ieee80211_rx_status *rxs;
|
|
||||||
+ const struct ieee80211_rate *rate;
|
|
||||||
+ bool is_sgi, is_40, is_sp;
|
|
||||||
+ int phy;
|
|
||||||
+ u16 len = rs->rs_datalen;
|
|
||||||
+ u32 airtime = 0;
|
|
||||||
+ u8 tidno, acno;
|
|
||||||
+
|
|
||||||
+ if (!ieee80211_is_data(hdr->frame_control))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ rcu_read_lock();
|
|
||||||
+
|
|
||||||
+ sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL);
|
|
||||||
+ if (!sta)
|
|
||||||
+ goto exit;
|
|
||||||
+ an = (struct ath_node *) sta->drv_priv;
|
|
||||||
+ avp = (struct ath_vif *) an->vif->drv_priv;
|
|
||||||
+ tidno = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
|
||||||
+ acno = TID_TO_WME_AC(tidno);
|
|
||||||
+ acq = &avp->chanctx->acq[acno];
|
|
||||||
+
|
|
||||||
+ rxs = IEEE80211_SKB_RXCB(skb);
|
|
||||||
+
|
|
||||||
+ is_sgi = !!(rxs->flag & RX_FLAG_SHORT_GI);
|
|
||||||
+ is_40 = !!(rxs->flag & RX_FLAG_40MHZ);
|
|
||||||
+ is_sp = !!(rxs->flag & RX_FLAG_SHORTPRE);
|
|
||||||
+
|
|
||||||
+ if (!!(rxs->flag & RX_FLAG_HT)) {
|
|
||||||
+ /* MCS rates */
|
|
||||||
+
|
|
||||||
+ airtime += ath_pkt_duration(sc, rxs->rate_idx, len,
|
|
||||||
+ is_40, is_sgi, is_sp);
|
|
||||||
+ } else {
|
|
||||||
+
|
|
||||||
+ phy = IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM;
|
|
||||||
+ rate = &common->sbands[rxs->band].bitrates[rxs->rate_idx];
|
|
||||||
+ airtime += ath9k_hw_computetxtime(ah, phy, rate->bitrate * 100,
|
|
||||||
+ len, rxs->rate_idx, is_sp);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!!(sc->airtime_flags & AIRTIME_USE_RX)) {
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ an->airtime_deficit[acno] -= airtime;
|
|
||||||
+ if (an->airtime_deficit[acno] <= 0)
|
|
||||||
+ __ath_tx_queue_tid(sc, ATH_AN_2_TID(an, tidno));
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
+ }
|
|
||||||
+ ath_debug_airtime(sc, an, airtime, 0);
|
|
||||||
+exit:
|
|
||||||
+ rcu_read_unlock();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|
||||||
{
|
|
||||||
struct ath_rxbuf *bf;
|
|
||||||
@@ -1137,6 +1201,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
|
|
||||||
ath9k_antenna_check(sc, &rs);
|
|
||||||
ath9k_apply_ampdu_details(sc, &rs, rxs);
|
|
||||||
ath_debug_rate_stats(sc, &rs, skb);
|
|
||||||
+ ath_rx_count_airtime(sc, &rs, skb);
|
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *)skb->data;
|
|
||||||
if (ieee80211_is_ack(hdr->frame_control))
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
@@ -125,21 +125,44 @@ void ath_txq_unlock_complete(struct ath_
|
|
||||||
ath_tx_status(hw, skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq,
|
|
||||||
- struct ath_atx_tid *tid)
|
|
||||||
+void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
|
||||||
{
|
|
||||||
- struct list_head *list;
|
|
||||||
struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
|
|
||||||
struct ath_chanctx *ctx = avp->chanctx;
|
|
||||||
+ struct ath_acq *acq;
|
|
||||||
+ struct list_head *tid_list;
|
|
||||||
+ u8 acno = TID_TO_WME_AC(tid->tidno);
|
|
||||||
|
|
||||||
- if (!ctx)
|
|
||||||
+ if (!ctx || !list_empty(&tid->list))
|
|
||||||
return;
|
|
||||||
|
|
||||||
- list = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
|
||||||
- if (list_empty(&tid->list))
|
|
||||||
- list_add_tail(&tid->list, list);
|
|
||||||
+
|
|
||||||
+ acq = &ctx->acq[acno];
|
|
||||||
+ if ((sc->airtime_flags & AIRTIME_USE_NEW_QUEUES) &&
|
|
||||||
+ tid->an->airtime_deficit[acno] > 0)
|
|
||||||
+ tid_list = &acq->acq_new;
|
|
||||||
+ else
|
|
||||||
+ tid_list = &acq->acq_old;
|
|
||||||
+
|
|
||||||
+ list_add_tail(&tid->list, tid_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
|
||||||
+{
|
|
||||||
+ struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv;
|
|
||||||
+ struct ath_chanctx *ctx = avp->chanctx;
|
|
||||||
+ struct ath_acq *acq;
|
|
||||||
+
|
|
||||||
+ if (!ctx || !list_empty(&tid->list))
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ acq = &ctx->acq[TID_TO_WME_AC(tid->tidno)];
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ __ath_tx_queue_tid(sc, tid);
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue)
|
|
||||||
{
|
|
||||||
struct ath_softc *sc = hw->priv;
|
|
||||||
@@ -154,7 +177,7 @@ void ath9k_wake_tx_queue(struct ieee8021
|
|
||||||
ath_txq_lock(sc, txq);
|
|
||||||
|
|
||||||
tid->has_queued = true;
|
|
||||||
- ath_tx_queue_tid(sc, txq, tid);
|
|
||||||
+ ath_tx_queue_tid(sc, tid);
|
|
||||||
ath_txq_schedule(sc, txq);
|
|
||||||
|
|
||||||
ath_txq_unlock(sc, txq);
|
|
||||||
@@ -684,7 +707,7 @@ static void ath_tx_complete_aggr(struct
|
|
||||||
|
|
||||||
skb_queue_splice_tail(&bf_pending, &tid->retry_q);
|
|
||||||
if (!an->sleeping) {
|
|
||||||
- ath_tx_queue_tid(sc, txq, tid);
|
|
||||||
+ ath_tx_queue_tid(sc, tid);
|
|
||||||
|
|
||||||
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
|
|
||||||
tid->clear_ps_filter = true;
|
|
||||||
@@ -712,6 +735,53 @@ static bool bf_is_ampdu_not_probing(stru
|
|
||||||
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq,
|
|
||||||
+ struct ath_buf *bf, struct ath_tx_status *ts)
|
|
||||||
+{
|
|
||||||
+ struct ath_node *an;
|
|
||||||
+ struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ struct ieee80211_hdr *hdr;
|
|
||||||
+ struct ieee80211_hw *hw = sc->hw;
|
|
||||||
+ struct ieee80211_tx_rate rates[4];
|
|
||||||
+ struct ieee80211_sta *sta;
|
|
||||||
+ int i;
|
|
||||||
+ u32 airtime = 0;
|
|
||||||
+
|
|
||||||
+ skb = bf->bf_mpdu;
|
|
||||||
+ if(!skb)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ hdr = (struct ieee80211_hdr *)skb->data;
|
|
||||||
+ memcpy(rates, bf->rates, sizeof(rates));
|
|
||||||
+
|
|
||||||
+ rcu_read_lock();
|
|
||||||
+
|
|
||||||
+ sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
|
|
||||||
+ if(!sta)
|
|
||||||
+ goto exit;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ an = (struct ath_node *) sta->drv_priv;
|
|
||||||
+
|
|
||||||
+ airtime += ts->duration * (ts->ts_longretry + 1);
|
|
||||||
+
|
|
||||||
+ for(i=0; i < ts->ts_rateindex; i++)
|
|
||||||
+ airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count;
|
|
||||||
+
|
|
||||||
+ if (!!(sc->airtime_flags & AIRTIME_USE_TX)) {
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ an->airtime_deficit[txq->mac80211_qnum] -= airtime;
|
|
||||||
+ if (an->airtime_deficit[txq->mac80211_qnum] <= 0)
|
|
||||||
+ __ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb));
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
+ }
|
|
||||||
+ ath_debug_airtime(sc, an, 0, airtime);
|
|
||||||
+
|
|
||||||
+exit:
|
|
||||||
+ rcu_read_unlock();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
|
|
||||||
struct ath_tx_status *ts, struct ath_buf *bf,
|
|
||||||
struct list_head *bf_head)
|
|
||||||
@@ -733,6 +803,7 @@ static void ath_tx_process_buffer(struct
|
|
||||||
|
|
||||||
ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc,
|
|
||||||
ts->ts_rateindex);
|
|
||||||
+ ath_tx_count_airtime(sc, txq, bf, ts);
|
|
||||||
|
|
||||||
hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
|
|
||||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
|
|
||||||
@@ -1094,8 +1165,8 @@ finish:
|
|
||||||
* width - 0 for 20 MHz, 1 for 40 MHz
|
|
||||||
* half_gi - to use 4us v/s 3.6 us for symbol time
|
|
||||||
*/
|
|
||||||
-static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
|
||||||
- int width, int half_gi, bool shortPreamble)
|
|
||||||
+u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
|
|
||||||
+ int width, int half_gi, bool shortPreamble)
|
|
||||||
{
|
|
||||||
u32 nbits, nsymbits, duration, nsymbols;
|
|
||||||
int streams;
|
|
||||||
@@ -1493,7 +1564,7 @@ ath_tx_form_burst(struct ath_softc *sc,
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
|
||||||
- struct ath_atx_tid *tid, bool *stop)
|
|
||||||
+ struct ath_atx_tid *tid)
|
|
||||||
{
|
|
||||||
struct ath_buf *bf;
|
|
||||||
struct ieee80211_tx_info *tx_info;
|
|
||||||
@@ -1515,7 +1586,6 @@ static bool ath_tx_sched_aggr(struct ath
|
|
||||||
if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) ||
|
|
||||||
(!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) {
|
|
||||||
__skb_queue_tail(&tid->retry_q, bf->bf_mpdu);
|
|
||||||
- *stop = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1639,7 +1709,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
|
|
||||||
ath_txq_lock(sc, txq);
|
|
||||||
tid->clear_ps_filter = true;
|
|
||||||
if (ath_tid_has_buffered(tid)) {
|
|
||||||
- ath_tx_queue_tid(sc, txq, tid);
|
|
||||||
+ ath_tx_queue_tid(sc, tid);
|
|
||||||
ath_txq_schedule(sc, txq);
|
|
||||||
}
|
|
||||||
ath_txq_unlock_complete(sc, txq);
|
|
||||||
@@ -1956,9 +2026,10 @@ void ath_tx_cleanupq(struct ath_softc *s
|
|
||||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
{
|
|
||||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
|
||||||
- struct ath_atx_tid *tid, *last_tid;
|
|
||||||
+ struct ath_atx_tid *tid;
|
|
||||||
struct list_head *tid_list;
|
|
||||||
- bool sent = false;
|
|
||||||
+ struct ath_acq *acq;
|
|
||||||
+ bool active = AIRTIME_ACTIVE(sc->airtime_flags);
|
|
||||||
|
|
||||||
if (txq->mac80211_qnum < 0)
|
|
||||||
return;
|
|
||||||
@@ -1967,48 +2038,55 @@ void ath_txq_schedule(struct ath_softc *
|
|
||||||
return;
|
|
||||||
|
|
||||||
spin_lock_bh(&sc->chan_lock);
|
|
||||||
- tid_list = &sc->cur_chan->acq[txq->mac80211_qnum];
|
|
||||||
-
|
|
||||||
- if (list_empty(tid_list)) {
|
|
||||||
- spin_unlock_bh(&sc->chan_lock);
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
rcu_read_lock();
|
|
||||||
+ acq = &sc->cur_chan->acq[txq->mac80211_qnum];
|
|
||||||
|
|
||||||
- last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list);
|
|
||||||
- while (!list_empty(tid_list)) {
|
|
||||||
- bool stop = false;
|
|
||||||
-
|
|
||||||
- if (sc->cur_chan->stopped)
|
|
||||||
- break;
|
|
||||||
-
|
|
||||||
- tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
|
||||||
- list_del_init(&tid->list);
|
|
||||||
+ if (sc->cur_chan->stopped)
|
|
||||||
+ goto out;
|
|
||||||
|
|
||||||
- if (ath_tx_sched_aggr(sc, txq, tid, &stop))
|
|
||||||
- sent = true;
|
|
||||||
+begin:
|
|
||||||
+ tid_list = &acq->acq_new;
|
|
||||||
+ if (list_empty(tid_list)) {
|
|
||||||
+ tid_list = &acq->acq_old;
|
|
||||||
+ if (list_empty(tid_list))
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ tid = list_first_entry(tid_list, struct ath_atx_tid, list);
|
|
||||||
|
|
||||||
- /*
|
|
||||||
- * add tid to round-robin queue if more frames
|
|
||||||
- * are pending for the tid
|
|
||||||
- */
|
|
||||||
- if (ath_tid_has_buffered(tid))
|
|
||||||
- ath_tx_queue_tid(sc, txq, tid);
|
|
||||||
+ if (active && tid->an->airtime_deficit[txq->mac80211_qnum] <= 0) {
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ tid->an->airtime_deficit[txq->mac80211_qnum] += ATH_AIRTIME_QUANTUM;
|
|
||||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
+ goto begin;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (stop)
|
|
||||||
- break;
|
|
||||||
+ if (!ath_tid_has_buffered(tid)) {
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ if ((tid_list == &acq->acq_new) && !list_empty(&acq->acq_old))
|
|
||||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
|
||||||
+ else {
|
|
||||||
+ list_del_init(&tid->list);
|
|
||||||
+ }
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
+ goto begin;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (tid == last_tid) {
|
|
||||||
- if (!sent)
|
|
||||||
- break;
|
|
||||||
|
|
||||||
- sent = false;
|
|
||||||
- last_tid = list_entry(tid_list->prev,
|
|
||||||
- struct ath_atx_tid, list);
|
|
||||||
+ /*
|
|
||||||
+ * If we succeed in scheduling something, immediately restart to make
|
|
||||||
+ * sure we keep the HW busy.
|
|
||||||
+ */
|
|
||||||
+ if(ath_tx_sched_aggr(sc, txq, tid)) {
|
|
||||||
+ if (!active) {
|
|
||||||
+ spin_lock_bh(&acq->lock);
|
|
||||||
+ list_move_tail(&tid->list, &acq->acq_old);
|
|
||||||
+ spin_unlock_bh(&acq->lock);
|
|
||||||
}
|
|
||||||
+ goto begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
+out:
|
|
||||||
rcu_read_unlock();
|
|
||||||
spin_unlock_bh(&sc->chan_lock);
|
|
||||||
}
|
|
||||||
@@ -2862,6 +2940,9 @@ void ath_tx_node_init(struct ath_softc *
|
|
||||||
struct ath_atx_tid *tid;
|
|
||||||
int tidno, acno;
|
|
||||||
|
|
||||||
+ for (acno = 0; acno < IEEE80211_NUM_ACS; acno++)
|
|
||||||
+ an->airtime_deficit[acno] = ATH_AIRTIME_QUANTUM;
|
|
||||||
+
|
|
||||||
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
|
|
||||||
tid = ath_node_to_tid(an, tidno);
|
|
||||||
tid->an = an;
|
|
|
@ -1,62 +0,0 @@
|
||||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
|
|
||||||
Date: Mon, 5 Dec 2016 13:27:38 +0200
|
|
||||||
Subject: [PATCH] ath9k: Turn ath_txq_lock/unlock() into static inlines.
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
These are one-line functions that just call spin_lock/unlock_bh(); turn
|
|
||||||
them into static inlines to avoid the function call overhead.
|
|
||||||
|
|
||||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
|
||||||
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
|
|
||||||
---
|
|
||||||
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
|
||||||
@@ -569,6 +569,15 @@ static inline void ath_chanctx_check_act
|
|
||||||
|
|
||||||
#endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
|
|
||||||
|
|
||||||
+static inline void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
+{
|
|
||||||
+ spin_lock_bh(&txq->axq_lock);
|
|
||||||
+}
|
|
||||||
+static inline void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
+{
|
|
||||||
+ spin_unlock_bh(&txq->axq_lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void ath_startrecv(struct ath_softc *sc);
|
|
||||||
bool ath_stoprecv(struct ath_softc *sc);
|
|
||||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
|
||||||
@@ -576,8 +585,6 @@ int ath_rx_init(struct ath_softc *sc, in
|
|
||||||
void ath_rx_cleanup(struct ath_softc *sc);
|
|
||||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
|
|
||||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
|
|
||||||
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq);
|
|
||||||
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq);
|
|
||||||
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
|
|
||||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
|
|
||||||
bool ath_drain_all_txq(struct ath_softc *sc);
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
|
||||||
@@ -98,18 +98,6 @@ static void ath_tx_status(struct ieee802
|
|
||||||
dev_kfree_skb(skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
-void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
- __acquires(&txq->axq_lock)
|
|
||||||
-{
|
|
||||||
- spin_lock_bh(&txq->axq_lock);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
- __releases(&txq->axq_lock)
|
|
||||||
-{
|
|
||||||
- spin_unlock_bh(&txq->axq_lock);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
|
|
||||||
__releases(&txq->axq_lock)
|
|
||||||
{
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -775,6 +775,7 @@ static const struct ieee80211_iface_limi
|
@@ -773,6 +773,7 @@ static const struct ieee80211_iface_limi
|
||||||
BIT(NL80211_IFTYPE_AP) },
|
BIT(NL80211_IFTYPE_AP) },
|
||||||
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||||
BIT(NL80211_IFTYPE_P2P_GO) },
|
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -1078,23 +1078,23 @@ static int __init ath9k_init(void)
|
@@ -1076,23 +1076,23 @@ static int __init ath9k_init(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
@@ -850,6 +850,9 @@ static inline int ath9k_dump_btcoex(stru
|
@@ -827,6 +827,9 @@ static inline int ath9k_dump_btcoex(stru
|
||||||
#ifdef CPTCFG_MAC80211_LEDS
|
#ifdef CPTCFG_MAC80211_LEDS
|
||||||
void ath_init_leds(struct ath_softc *sc);
|
void ath_init_leds(struct ath_softc *sc);
|
||||||
void ath_deinit_leds(struct ath_softc *sc);
|
void ath_deinit_leds(struct ath_softc *sc);
|
||||||
|
@ -10,9 +10,9 @@
|
||||||
#else
|
#else
|
||||||
static inline void ath_init_leds(struct ath_softc *sc)
|
static inline void ath_init_leds(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
@@ -991,6 +994,13 @@ void ath_ant_comb_scan(struct ath_softc
|
@@ -963,6 +966,13 @@ void ath_ant_comb_scan(struct ath_softc
|
||||||
#define AIRTIME_USE_NEW_QUEUES BIT(2)
|
|
||||||
#define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
|
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
|
||||||
|
|
||||||
+struct ath_led {
|
+struct ath_led {
|
||||||
+ struct list_head list;
|
+ struct list_head list;
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
struct ath_softc {
|
struct ath_softc {
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -1045,9 +1055,8 @@ struct ath_softc {
|
@@ -1015,9 +1025,8 @@ struct ath_softc {
|
||||||
spinlock_t chan_lock;
|
spinlock_t chan_lock;
|
||||||
|
|
||||||
#ifdef CPTCFG_MAC80211_LEDS
|
#ifdef CPTCFG_MAC80211_LEDS
|
||||||
|
@ -181,7 +181,7 @@
|
||||||
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -990,7 +990,7 @@ int ath9k_init_device(u16 devid, struct
|
@@ -988,7 +988,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
|
||||||
#ifdef CPTCFG_MAC80211_LEDS
|
#ifdef CPTCFG_MAC80211_LEDS
|
||||||
/* must be initialized before ieee80211_register_hw */
|
/* must be initialized before ieee80211_register_hw */
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
|
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -763,7 +763,8 @@ static void ath9k_init_txpower_limits(st
|
@@ -761,7 +761,8 @@ static void ath9k_init_txpower_limits(st
|
||||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||||
ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
|
ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ieee80211_iface_limit if_limits[] = {
|
static const struct ieee80211_iface_limit if_limits[] = {
|
||||||
@@ -950,6 +951,18 @@ static void ath9k_set_hw_capab(struct at
|
@@ -948,6 +949,18 @@ static void ath9k_set_hw_capab(struct at
|
||||||
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||||
const struct ath_bus_ops *bus_ops)
|
const struct ath_bus_ops *bus_ops)
|
||||||
{
|
{
|
||||||
@@ -995,6 +1008,8 @@ int ath9k_init_device(u16 devid, struct
|
@@ -993,6 +1006,8 @@ int ath9k_init_device(u16 devid, struct
|
||||||
ARRAY_SIZE(ath9k_tpt_blink));
|
ARRAY_SIZE(ath9k_tpt_blink));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@@ -1001,6 +1002,14 @@ struct ath_led {
|
@@ -973,6 +974,14 @@ struct ath_led {
|
||||||
struct led_classdev cdev;
|
struct led_classdev cdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
struct ath_softc {
|
struct ath_softc {
|
||||||
struct ieee80211_hw *hw;
|
struct ieee80211_hw *hw;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -1057,6 +1066,9 @@ struct ath_softc {
|
@@ -1027,6 +1036,9 @@ struct ath_softc {
|
||||||
#ifdef CPTCFG_MAC80211_LEDS
|
#ifdef CPTCFG_MAC80211_LEDS
|
||||||
const char *led_default_trigger;
|
const char *led_default_trigger;
|
||||||
struct list_head leds;
|
struct list_head leds;
|
||||||
|
|
|
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
---
|
---
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
@@ -1068,6 +1068,7 @@ struct ath_softc {
|
@@ -1038,6 +1038,7 @@ struct ath_softc {
|
||||||
struct list_head leds;
|
struct list_head leds;
|
||||||
#ifdef CONFIG_GPIOLIB
|
#ifdef CONFIG_GPIOLIB
|
||||||
struct ath9k_gpio_chip *gpiochip;
|
struct ath9k_gpio_chip *gpiochip;
|
||||||
|
|
|
@ -329,7 +329,7 @@ Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||||
&ratesArray[0], cfgCtl,
|
&ratesArray[0], cfgCtl,
|
||||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
@@ -1236,8 +1236,9 @@ static u8 ath_get_rate_txpower(struct at
|
@@ -1177,8 +1177,9 @@ static u8 ath_get_rate_txpower(struct at
|
||||||
if (is_40) {
|
if (is_40) {
|
||||||
u8 power_ht40delta;
|
u8 power_ht40delta;
|
||||||
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
|
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
|
||||||
|
|
Loading…
Reference in a new issue