* [PATCH v2 1/3] mac80211: Add TXQ scheduling API
From: Toke Høiland-Jørgensen @ 2017-10-27 14:14 UTC (permalink / raw)
To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20171016160902.8970-1-toke@toke.dk>
This adds an API to mac80211 to handle scheduling of TXQs and changes the
interface between driver and mac80211 for TXQ handling as follows:
- The wake_tx_queue callback interface no longer includes the TXQ. Instead,
the driver is expected to retrieve that from ieee80211_next_txq()
- Two new mac80211 functions are added: ieee80211_next_txq() and
ieee80211_schedule_txq(). The former returns the next TXQ that should be
scheduled, and is how the driver gets a queue to pull packets from. The
latter is called internally by mac80211 to start scheduling a queue, and
the driver is supposed to call it to re-schedule the TXQ after it is
finished pulling packets from it (unless the queue emptied).
The ath9k and ath10k drivers are changed to use the new API.
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
Changes since v1:
- Also remove artxq->list member from ath10k
- Don't skip ieee80211_schedule_txq() calls due to boolean
short-circuiting
- Some documentation and checkpatch fixes
drivers/net/wireless/ath/ath10k/core.c | 2 -
drivers/net/wireless/ath/ath10k/core.h | 4 -
drivers/net/wireless/ath/ath10k/mac.c | 55 +++------
drivers/net/wireless/ath/ath9k/ath9k.h | 6 +-
drivers/net/wireless/ath/ath9k/main.c | 2 +-
drivers/net/wireless/ath/ath9k/xmit.c | 210 ++++++++-------------------------
include/net/mac80211.h | 37 +++++-
net/mac80211/agg-tx.c | 6 +-
net/mac80211/driver-ops.h | 12 +-
net/mac80211/ieee80211_i.h | 5 +
net/mac80211/main.c | 3 +
net/mac80211/sta_info.c | 7 +-
net/mac80211/trace.h | 32 +----
net/mac80211/tx.c | 49 +++++++-
14 files changed, 173 insertions(+), 257 deletions(-)
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index a4f635820f35..759df3297d48 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -2561,9 +2561,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
- spin_lock_init(&ar->txqs_lock);
- INIT_LIST_HEAD(&ar->txqs);
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 949ebb3e967b..3c3b158cdb20 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -347,7 +347,6 @@ struct ath10k_peer {
};
struct ath10k_txq {
- struct list_head list;
unsigned long num_fw_queued;
unsigned long num_push_allowed;
};
@@ -892,10 +891,7 @@ struct ath10k {
/* protects shared structure data */
spinlock_t data_lock;
- /* protects: ar->txqs, artxq->list */
- spinlock_t txqs_lock;
- struct list_head txqs;
struct list_head arvifs;
struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 5683f1a5330e..f9c70d8c9a09 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3820,12 +3820,10 @@ static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
return;
artxq = (void *)txq->drv_priv;
- INIT_LIST_HEAD(&artxq->list);
}
static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
{
- struct ath10k_txq *artxq;
struct ath10k_skb_cb *cb;
struct sk_buff *msdu;
int msdu_id;
@@ -3833,12 +3831,6 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
if (!txq)
return;
- artxq = (void *)txq->drv_priv;
- spin_lock_bh(&ar->txqs_lock);
- if (!list_empty(&artxq->list))
- list_del_init(&artxq->list);
- spin_unlock_bh(&ar->txqs_lock);
-
spin_lock_bh(&ar->htt.tx_lock);
idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) {
cb = ATH10K_SKB_CB(msdu);
@@ -3968,23 +3960,17 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
void ath10k_mac_tx_push_pending(struct ath10k *ar)
{
struct ieee80211_hw *hw = ar->hw;
- struct ieee80211_txq *txq;
- struct ath10k_txq *artxq;
- struct ath10k_txq *last;
+ struct ieee80211_txq *txq, *first = NULL;
int ret;
int max;
if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
return;
- spin_lock_bh(&ar->txqs_lock);
rcu_read_lock();
- last = list_last_entry(&ar->txqs, struct ath10k_txq, list);
- while (!list_empty(&ar->txqs)) {
- artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
- txq = container_of((void *)artxq, struct ieee80211_txq,
- drv_priv);
+ txq = ieee80211_next_txq(hw);
+ while (txq) {
/* Prevent aggressive sta/tid taking over tx queue */
max = 16;
@@ -3995,18 +3981,21 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
break;
}
- list_del_init(&artxq->list);
if (ret != -ENOENT)
- list_add_tail(&artxq->list, &ar->txqs);
+ ieee80211_schedule_txq(hw, txq);
ath10k_htt_tx_txq_update(hw, txq);
- if (artxq == last || (ret < 0 && ret != -ENOENT))
+ if (first == txq || (ret < 0 && ret != -ENOENT))
break;
+
+ if (!first)
+ first = txq;
+
+ txq = ieee80211_next_txq(hw);
}
rcu_read_unlock();
- spin_unlock_bh(&ar->txqs_lock);
}
/************/
@@ -4240,34 +4229,22 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
}
}
-static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw)
{
- struct ath10k *ar = hw->priv;
- struct ath10k_txq *artxq = (void *)txq->drv_priv;
- struct ieee80211_txq *f_txq;
- struct ath10k_txq *f_artxq;
+ struct ieee80211_txq *txq;
int ret = 0;
int max = 16;
- spin_lock_bh(&ar->txqs_lock);
- if (list_empty(&artxq->list))
- list_add_tail(&artxq->list, &ar->txqs);
-
- f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
- f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv);
- list_del_init(&f_artxq->list);
+ txq = ieee80211_next_txq(hw);
- while (ath10k_mac_tx_can_push(hw, f_txq) && max--) {
- ret = ath10k_mac_tx_push_txq(hw, f_txq);
+ while (ath10k_mac_tx_can_push(hw, txq) && max--) {
+ ret = ath10k_mac_tx_push_txq(hw, txq);
if (ret)
break;
}
if (ret != -ENOENT)
- list_add_tail(&f_artxq->list, &ar->txqs);
- spin_unlock_bh(&ar->txqs_lock);
+ ieee80211_schedule_txq(hw, txq);
- ath10k_htt_tx_txq_update(hw, f_txq);
ath10k_htt_tx_txq_update(hw, txq);
}
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index cf076719c27e..f6c53df78856 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -246,7 +246,6 @@ struct ath_atx_tid {
s8 bar_index;
bool active;
bool clear_ps_filter;
- bool has_queued;
};
void __ath_tx_queue_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
@@ -591,8 +590,7 @@ bool ath_drain_all_txq(struct ath_softc *sc);
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
-void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
-void ath_txq_schedule_all(struct ath_softc *sc);
+void ath_txq_schedule(struct ath_softc *sc);
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);
@@ -618,7 +616,7 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
u16 tids, int nframes,
enum ieee80211_frame_release_type reason,
bool more_data);
-void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue);
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw);
/********/
/* VIFs */
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 8b4ac7f0a09b..7c2ba21fd972 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -265,7 +265,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
}
work:
ath_restart_work(sc);
- ath_txq_schedule_all(sc);
+ ath_txq_schedule(sc);
}
sc->gtt_cnt = 0;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 396bf05c6bf6..bd438062a6db 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -112,62 +112,11 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
ath_tx_status(hw, skb);
}
-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;
- struct list_head *tid_list;
- u8 acno = TID_TO_WME_AC(tid->tidno);
-
- if (!ctx || !list_empty(&tid->list))
- return;
-
-
- 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)
+void ath9k_wake_tx_queue(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv;
- struct ath_txq *txq = tid->txq;
-
- ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n",
- queue->sta ? queue->sta->addr : queue->vif->addr,
- tid->tidno);
-
- ath_txq_lock(sc, txq);
- tid->has_queued = true;
- ath_tx_queue_tid(sc, tid);
- ath_txq_schedule(sc, txq);
-
- ath_txq_unlock(sc, txq);
+ ath_txq_schedule(sc);
}
static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
@@ -230,14 +179,9 @@ ath_tid_pull(struct ath_atx_tid *tid)
struct ath_frame_info *fi;
int q;
- if (!tid->has_queued)
- return NULL;
-
skb = ieee80211_tx_dequeue(hw, txq);
- if (!skb) {
- tid->has_queued = false;
+ if (!skb)
return NULL;
- }
if (ath_tx_prepare(hw, skb, &txctl)) {
ieee80211_free_txskb(hw, skb);
@@ -254,12 +198,6 @@ ath_tid_pull(struct ath_atx_tid *tid)
return skb;
}
-
-static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
-{
- return !skb_queue_empty(&tid->retry_q) || tid->has_queued;
-}
-
static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
{
struct sk_buff *skb;
@@ -671,7 +609,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
skb_queue_splice_tail(&bf_pending, &tid->retry_q);
if (!an->sleeping) {
- ath_tx_queue_tid(sc, tid);
+ struct ieee80211_txq *queue = container_of(
+ (void *)tid, struct ieee80211_txq, drv_priv);
+
+ ieee80211_schedule_txq(sc->hw, queue);
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->clear_ps_filter = true;
@@ -719,8 +660,6 @@ static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
spin_lock_bh(&acq->lock);
an->airtime_deficit[q] -= airtime;
- if (an->airtime_deficit[q] <= 0)
- __ath_tx_queue_tid(sc, tid);
spin_unlock_bh(&acq->lock);
}
ath_debug_airtime(sc, an, 0, airtime);
@@ -770,8 +709,6 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
} else
ath_tx_complete_aggr(sc, txq, bf, bf_head, sta, tid, ts, txok);
- if (!flush)
- ath_txq_schedule(sc, txq);
}
static bool ath_lookup_legacy(struct ath_buf *bf)
@@ -1506,8 +1443,8 @@ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq,
} while (1);
}
-static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid)
+static int ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_atx_tid *tid)
{
struct ath_buf *bf;
struct ieee80211_tx_info *tx_info;
@@ -1515,21 +1452,18 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
int aggr_len = 0;
bool aggr;
- if (!ath_tid_has_buffered(tid))
- return false;
-
INIT_LIST_HEAD(&bf_q);
bf = ath_tx_get_tid_subframe(sc, txq, tid);
if (!bf)
- return false;
+ return -ENOENT;
tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
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);
- return false;
+ return -ENOBUFS;
}
ath_set_rates(tid->an->vif, tid->an->sta, bf);
@@ -1539,7 +1473,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_form_burst(sc, txq, tid, &bf_q, bf);
if (list_empty(&bf_q))
- return false;
+ return -ENOENT;
if (tid->clear_ps_filter || tid->an->no_ps_filter) {
tid->clear_ps_filter = false;
@@ -1548,7 +1482,7 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_fill_desc(sc, bf, txq, aggr_len);
ath_tx_txqaddbuf(sc, txq, &bf_q, false);
- return true;
+ return 0;
}
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -1611,52 +1545,49 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
- struct ath_txq *txq;
+ struct ieee80211_txq *queue;
int tidno;
ath_dbg(common, XMIT, "%s called\n", __func__);
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
tid = ath_node_to_tid(an, tidno);
- txq = tid->txq;
-
- ath_txq_lock(sc, txq);
-
- if (list_empty(&tid->list)) {
- ath_txq_unlock(sc, txq);
- continue;
- }
+ queue = container_of((void *)tid,
+ struct ieee80211_txq, drv_priv);
if (!skb_queue_empty(&tid->retry_q))
ieee80211_sta_set_buffered(sta, tid->tidno, true);
- list_del_init(&tid->list);
-
- ath_txq_unlock(sc, txq);
}
}
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_txq *queue;
struct ath_atx_tid *tid;
struct ath_txq *txq;
int tidno;
+ bool sched, wake = false;
ath_dbg(common, XMIT, "%s called\n", __func__);
for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
tid = ath_node_to_tid(an, tidno);
txq = tid->txq;
+ queue = container_of((void *)tid,
+ struct ieee80211_txq, drv_priv);
ath_txq_lock(sc, txq);
tid->clear_ps_filter = true;
- if (ath_tid_has_buffered(tid)) {
- ath_tx_queue_tid(sc, tid);
- ath_txq_schedule(sc, txq);
- }
- ath_txq_unlock_complete(sc, txq);
+ sched = !skb_queue_empty(&tid->retry_q);
+ ath_txq_unlock(sc, txq);
+
+ if (sched && ieee80211_schedule_txq(sc->hw, queue))
+ wake = true;
}
+ if (wake)
+ ath_txq_schedule(sc);
}
void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
@@ -1948,86 +1879,44 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
/* For each acq entry, for each tid, try to schedule packets
* for transmit until ampdu_depth has reached min Q depth.
*/
-void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
+void ath_txq_schedule(struct ath_softc *sc)
{
+ struct ieee80211_hw *hw = sc->hw;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ieee80211_txq *queue;
struct ath_atx_tid *tid;
- struct list_head *tid_list;
- struct ath_acq *acq;
- bool active = AIRTIME_ACTIVE(sc->airtime_flags);
+ struct ath_txq *txq;
+ int ret = 0;
- if (txq->mac80211_qnum < 0)
+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
return;
- if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+ queue = ieee80211_next_txq(hw);
+ if (!queue)
return;
- spin_lock_bh(&sc->chan_lock);
- rcu_read_lock();
- acq = &sc->cur_chan->acq[txq->mac80211_qnum];
+ tid = (struct ath_atx_tid *)queue->drv_priv;
+ txq = tid->txq;
- if (sc->cur_chan->stopped)
+ ath_txq_lock(sc, txq);
+ if (txq->mac80211_qnum < 0)
goto out;
-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);
-
- 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 (!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;
- }
-
+ spin_lock_bh(&sc->chan_lock);
+ rcu_read_lock();
- /*
- * 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;
- }
+ if (!sc->cur_chan->stopped)
+ ret = ath_tx_sched_aggr(sc, txq, tid);
-out:
rcu_read_unlock();
spin_unlock_bh(&sc->chan_lock);
-}
-void ath_txq_schedule_all(struct ath_softc *sc)
-{
- struct ath_txq *txq;
- int i;
+out:
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- txq = sc->tx.txq_map[i];
+ if (ret != -ENOENT)
+ ieee80211_schedule_txq(hw, queue);
- spin_lock_bh(&txq->axq_lock);
- ath_txq_schedule(sc, txq);
- spin_unlock_bh(&txq->axq_lock);
- }
+ ath_txq_unlock(sc, txq);
}
/***********/
@@ -2645,7 +2534,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
- ath_txq_schedule(sc, txq);
break;
}
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2697,6 +2585,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
}
ath_txq_unlock_complete(sc, txq);
+ ath_txq_schedule(sc);
}
void ath_tx_tasklet(struct ath_softc *sc)
@@ -2711,6 +2600,7 @@ void ath_tx_tasklet(struct ath_softc *sc)
ath_tx_processq(sc, &sc->tx.txq[i]);
}
rcu_read_unlock();
+ ath_txq_schedule(sc);
}
void ath_tx_edma_tasklet(struct ath_softc *sc)
@@ -2796,6 +2686,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
ath_txq_unlock_complete(sc, txq);
}
rcu_read_unlock();
+ ath_txq_schedule(sc);
}
/*****************/
@@ -2875,7 +2766,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->baw_head = tid->baw_tail = 0;
tid->active = false;
tid->clear_ps_filter = true;
- tid->has_queued = false;
__skb_queue_head_init(&tid->retry_q);
INIT_LIST_HEAD(&tid->list);
acno = TID_TO_WME_AC(tidno);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cc9073e45be9..715f45501aff 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -105,9 +105,12 @@
* The driver is expected to initialize its private per-queue data for stations
* and interfaces in the .add_interface and .sta_add ops.
*
- * The driver can't access the queue directly. To dequeue a frame, it calls
- * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it
- * calls the .wake_tx_queue driver op.
+ * The driver can't access the queue directly. To obtain the next queue to pull
+ * frames from, the driver calls ieee80211_next_txq(). To dequeue a frame from a
+ * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
+ * queue, it calls the .wake_tx_queue driver op. The driver is expected to
+ * re-schedule the txq using ieee80211_schedule_txq() if it is still active
+ * after the driver has finished pulling packets from it.
*
* For AP powersave TIM handling, the driver only needs to indicate if it has
* buffered packets in the driver specific data structures by calling
@@ -3723,8 +3726,7 @@ struct ieee80211_ops {
struct ieee80211_vif *vif,
struct ieee80211_tdls_ch_sw_params *params);
- void (*wake_tx_queue)(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq);
+ void (*wake_tx_queue)(struct ieee80211_hw *hw);
void (*sync_rx_queues)(struct ieee80211_hw *hw);
int (*start_nan)(struct ieee80211_hw *hw,
@@ -5869,13 +5871,36 @@ void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);
* ieee80211_tx_dequeue - dequeue a packet from a software tx queue
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
- * @txq: pointer obtained from station or virtual interface
+ * @txq: pointer obtained from ieee80211_next_txq()
*
* Returns the skb if successful, %NULL if no frame was available.
*/
struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
+/**
+ * ieee80211_schedule_txq - add txq to scheduling loop
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @txq: pointer obtained from station or virtual interface
+ *
+ * Returns %true if the txq was actually added to the scheduling,
+ * %false otherwise.
+ */
+bool ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq);
+
+/**
+ * ieee80211_next_txq - get next tx queue to pull packets from
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ *
+ * Returns the next txq if successful, %NULL if no queue is eligible. If a txq
+ * is returned, it will have been removed from the scheduler queue and needs to
+ * be re-scheduled with ieee80211_schedule_txq() to continue to be active.
+ */
+struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw);
+
/**
* ieee80211_txq_get_depth - get pending frame/byte count of given txq
*
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index bef516ec47f9..569b5b5c6d70 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -226,9 +226,13 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags);
clear_bit(IEEE80211_TXQ_STOP, &txqi->flags);
+
+ if (!ieee80211_schedule_txq(&sta->sdata->local->hw, txq))
+ return;
+
local_bh_disable();
rcu_read_lock();
- drv_wake_tx_queue(sta->sdata->local, txqi);
+ drv_wake_tx_queue(sta->sdata->local);
rcu_read_unlock();
local_bh_enable();
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 09f77e4a8a79..e20a9e2acd53 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1157,16 +1157,10 @@ drv_tdls_recv_channel_switch(struct ieee80211_local *local,
trace_drv_return_void(local);
}
-static inline void drv_wake_tx_queue(struct ieee80211_local *local,
- struct txq_info *txq)
+static inline void drv_wake_tx_queue(struct ieee80211_local *local)
{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
-
- if (!check_sdata_in_driver(sdata))
- return;
-
- trace_drv_wake_tx_queue(local, sdata, txq);
- local->ops->wake_tx_queue(&local->hw, &txq->txq);
+ trace_drv_wake_tx_queue(local);
+ local->ops->wake_tx_queue(&local->hw);
}
static inline int drv_start_nan(struct ieee80211_local *local,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9675814f64db..95be548b1d4f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -832,6 +832,7 @@ struct txq_info {
struct codel_vars def_cvars;
struct codel_stats cstats;
struct sk_buff_head frags;
+ struct list_head schedule_order;
unsigned long flags;
/* keep last! */
@@ -1121,6 +1122,10 @@ struct ieee80211_local {
struct codel_vars *cvars;
struct codel_params cparams;
+ /* protects active_txqs and txqi->schedule_order */
+ spinlock_t active_txq_lock;
+ struct list_head active_txqs;
+
const struct ieee80211_ops *ops;
/*
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8aa1f5b6a051..9ad0556aa24b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -616,6 +616,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
spin_lock_init(&local->rx_path_lock);
spin_lock_init(&local->queue_stop_reason_lock);
+ INIT_LIST_HEAD(&local->active_txqs);
+ spin_lock_init(&local->active_txq_lock);
+
INIT_LIST_HEAD(&local->chanctx_list);
mutex_init(&local->chanctx_mtx);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 9673e157bf8f..da3737d4778f 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1246,12 +1246,17 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
if (sta->sta.txq[0]) {
+ bool wake = false;
+
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
if (!txq_has_queue(sta->sta.txq[i]))
continue;
- drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
+ if (ieee80211_schedule_txq(&local->hw, sta->sta.txq[i]))
+ wake = true;
}
+ if (wake)
+ drv_wake_tx_queue(local);
}
skb_queue_head_init(&pending);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 3d9ac17af407..f51eade947ee 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2549,35 +2549,9 @@ TRACE_EVENT(drv_tdls_recv_channel_switch,
)
);
-TRACE_EVENT(drv_wake_tx_queue,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct txq_info *txq),
-
- TP_ARGS(local, sdata, txq),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
- __field(u8, ac)
- __field(u8, tid)
- ),
-
- TP_fast_assign(
- struct ieee80211_sta *sta = txq->txq.sta;
-
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
- __entry->ac = txq->txq.ac;
- __entry->tid = txq->txq.tid;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ac:%d tid:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid
- )
+DEFINE_EVENT(local_only_evt, drv_wake_tx_queue,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
);
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 94826680cf2b..824d87e6d3eb 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1405,6 +1405,7 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
codel_vars_init(&txqi->def_cvars);
codel_stats_init(&txqi->cstats);
__skb_queue_head_init(&txqi->frags);
+ INIT_LIST_HEAD(&txqi->schedule_order);
txqi->txq.vif = &sdata->vif;
@@ -1428,6 +1429,7 @@ void ieee80211_txq_purge(struct ieee80211_local *local,
fq_tin_reset(fq, tin, fq_skb_free_func);
ieee80211_purge_tx_queue(&local->hw, &txqi->frags);
+ list_del_init(&txqi->schedule_order);
}
int ieee80211_txq_setup_flows(struct ieee80211_local *local)
@@ -1524,7 +1526,8 @@ static bool ieee80211_queue_skb(struct ieee80211_local *local,
ieee80211_txq_enqueue(local, txqi, skb);
spin_unlock_bh(&fq->lock);
- drv_wake_tx_queue(local, txqi);
+ if (ieee80211_schedule_txq(&local->hw, &txqi->txq))
+ drv_wake_tx_queue(local);
return true;
}
@@ -3517,6 +3520,50 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_tx_dequeue);
+bool ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct txq_info *txqi = to_txq_info(txq);
+ bool ret = false;
+
+ spin_lock_bh(&local->active_txq_lock);
+
+ if (list_empty(&txqi->schedule_order)) {
+ list_add_tail(&txqi->schedule_order, &local->active_txqs);
+ ret = true;
+ }
+
+ spin_unlock_bh(&local->active_txq_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(ieee80211_schedule_txq);
+
+struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct txq_info *txqi = NULL;
+
+ spin_lock_bh(&local->active_txq_lock);
+
+ if (list_empty(&local->active_txqs))
+ goto out;
+
+ txqi = list_first_entry(&local->active_txqs,
+ struct txq_info, schedule_order);
+ list_del_init(&txqi->schedule_order);
+
+out:
+ spin_unlock_bh(&local->active_txq_lock);
+
+ if (!txqi)
+ return NULL;
+
+ return &txqi->txq;
+}
+EXPORT_SYMBOL(ieee80211_next_txq);
+
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
u32 info_flags)
--
2.14.2
^ permalink raw reply related
* [PATCH v2 2/3] mac80211: Add airtime account and scheduling to TXQs
From: Toke Høiland-Jørgensen @ 2017-10-27 14:14 UTC (permalink / raw)
To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20171016160902.8970-1-toke@toke.dk>
This adds airtime accounting and scheduling to the mac80211 TXQ scheduler. A new
hardware flag, AIRTIME_ACCOUNTING, is added that drivers can set if they support
reporting airtime usage of transmissions. When this flag is set, mac80211 will
expect the actual airtime usage to be reported in the tx_time and rx_time fields
of the respective status structs.
When airtime information is present, mac80211 will schedule TXQs (through
ieee80211_next_txq()) in a way that enforces airtime fairness between active
stations. This scheduling works the same way as the ath9k in-driver airtime
fairness scheduling.
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
Changes since v1:
- Split ath9k changes into separate patch
- Rename RX status variable to 'airtime', add documentation
- Add documentation on usage to the IEEE80211_HW_AIRTIME_ACCOUNTING hw
accounting flag
- Remove HW flag check on RX side, add it where it was missing on TX
side
- Fix checkpatch issues
This still implements the basic fairness that is more or less equivalent
to the previous implementation in ath9k. I figure any changes to a
different mechanism should be made separately anyway, and I don't
believe they will require any changes to the driver/mac80211 API.
include/net/mac80211.h | 24 ++++++++++++++++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/debugfs_sta.c | 29 +++++++++++++++++++++++++++++
net/mac80211/ieee80211_i.h | 9 +++++++--
net/mac80211/main.c | 3 ++-
net/mac80211/rx.c | 8 ++++++++
net/mac80211/sta_info.c | 2 ++
net/mac80211/sta_info.h | 7 +++++++
net/mac80211/status.c | 16 ++++++++++++++++
net/mac80211/tx.c | 31 ++++++++++++++++++++++++++-----
10 files changed, 122 insertions(+), 8 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 715f45501aff..453653d082af 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1188,6 +1188,8 @@ enum mac80211_rx_encoding {
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
* @nss: number of streams (VHT and HE only)
* @flag: %RX_FLAG_\*
+ * @airtime: Duration of frame in usec. See @IEEE80211_HW_AIRTIME_ACCOUNTING for
+ * how to use this.
* @encoding: &enum mac80211_rx_encoding
* @bw: &enum rate_info_bw
* @enc_flags: uses bits from &enum mac80211_rx_encoding_flags
@@ -1202,6 +1204,7 @@ struct ieee80211_rx_status {
u32 device_timestamp;
u32 ampdu_reference;
u32 flag;
+ u16 airtime;
u16 freq;
u8 enc_flags;
u8 encoding:2, bw:3;
@@ -2059,6 +2062,26 @@ struct ieee80211_txq {
* The stack will not do fragmentation.
* The callback for @set_frag_threshold should be set as well.
*
+ * @IEEE80211_HW_AIRTIME_ACCOUNTING: Hardware supports accounting the airtime
+ * usage of other stations and reports it in the @tx_time and/or @airtime
+ * fields of the TX/RX status structs.
+ * When setting this flag, the driver should ensure that the respective
+ * fields in the TX and RX status structs are always either zero or
+ * contains a valid duration for the frame in usec. The driver can choose
+ * to report either or both of TX and RX airtime, but it is recommended to
+ * report both.
+ * The reported airtime should as a minimum include all time that is spent
+ * transmitting to the remote station, including overhead and padding, but
+ * not including time spent waiting for a TXOP. If the time is not reported
+ * by the hardware it can in some cases be calculated from the rate and
+ * known frame composition. When possible, the time should include any
+ * failed transmission attempts.
+ * For aggregated frames, there are two possible strategies to report the
+ * airtime: Either include the airtime of the entire aggregate in the first
+ * (or last) frame and leave the others at zero. Alternatively, include the
+ * overhead of the full aggregate in the first or last frame and report the
+ * time of each frame + padding not including the full aggregate overhead.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2101,6 +2124,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_TX_FRAG_LIST,
IEEE80211_HW_REPORTS_LOW_ACK,
IEEE80211_HW_SUPPORTS_TX_FRAG,
+ IEEE80211_HW_AIRTIME_ACCOUNTING,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 5fae001f286c..20e3aa0e8464 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -211,6 +211,7 @@ static const char *hw_flag_names[] = {
FLAG(TX_FRAG_LIST),
FLAG(REPORTS_LOW_ACK),
FLAG(SUPPORTS_TX_FRAG),
+ FLAG(AIRTIME_ACCOUNTING),
#undef FLAG
};
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index b15412c21ac9..40dba446836f 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -188,6 +188,32 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
}
STA_OPS(aqm);
+static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct sta_info *sta = file->private_data;
+ size_t bufsz = 200;
+ char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
+ ssize_t rv;
+
+ if (!buf)
+ return -ENOMEM;
+
+ spin_lock_bh(&sta->lock);
+
+ p += scnprintf(p, bufsz + buf - p,
+ "RX: %llu us\nTX: %llu us\nDeficit: %lld us\n",
+ sta->airtime_stats.rx_airtime,
+ sta->airtime_stats.tx_airtime,
+ sta->airtime_deficit);
+
+ spin_unlock_bh(&sta->lock);
+ rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+ kfree(buf);
+ return rv;
+}
+STA_OPS(airtime);
+
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -542,6 +568,9 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
if (local->ops->wake_tx_queue)
DEBUGFS_ADD(aqm);
+ if (ieee80211_hw_check(&local->hw, AIRTIME_ACCOUNTING))
+ DEBUGFS_ADD(airtime);
+
if (sizeof(sta->driver_buffered_tids) == sizeof(u32))
debugfs_create_x32("driver_buffered_tids", 0400,
sta->debugfs_dir,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 95be548b1d4f..e74aeff7662a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -90,6 +90,9 @@ extern const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS];
#define IEEE80211_MAX_NAN_INSTANCE_ID 255
+/* How much to increase airtime deficit on each scheduling round */
+#define IEEE80211_AIRTIME_QUANTUM 1000 /* usec */
+
struct ieee80211_fragment_entry {
struct sk_buff_head skb_list;
unsigned long first_frag_time;
@@ -1122,9 +1125,11 @@ struct ieee80211_local {
struct codel_vars *cvars;
struct codel_params cparams;
- /* protects active_txqs and txqi->schedule_order */
+ /* protects active_txqs_{new,old} and txqi->schedule_order */
spinlock_t active_txq_lock;
- struct list_head active_txqs;
+ struct list_head active_txqs_new;
+ struct list_head active_txqs_old;
+
const struct ieee80211_ops *ops;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 9ad0556aa24b..acf73c398d9b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -616,7 +616,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
spin_lock_init(&local->rx_path_lock);
spin_lock_init(&local->queue_stop_reason_lock);
- INIT_LIST_HEAD(&local->active_txqs);
+ INIT_LIST_HEAD(&local->active_txqs_new);
+ INIT_LIST_HEAD(&local->active_txqs_old);
spin_lock_init(&local->active_txq_lock);
INIT_LIST_HEAD(&local->chanctx_list);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 70e9d2ca8bbe..a6166850b971 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1637,6 +1637,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (ieee80211_vif_is_mesh(&rx->sdata->vif))
ieee80211_mps_rx_h_sta_process(sta, hdr);
+ /* airtime accounting */
+ if (status->airtime) {
+ spin_lock_bh(&sta->lock);
+ sta->airtime_stats.rx_airtime += status->airtime;
+ sta->airtime_deficit -= status->airtime;
+ spin_unlock_bh(&sta->lock);
+ }
+
/*
* Drop (qos-)data::nullfunc frames silently, since they
* are used only to control station power saving mode.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index da3737d4778f..e8511922a7c7 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -433,6 +433,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
sta->cparams.interval = MS2TIME(100);
sta->cparams.ecn = true;
+ sta->airtime_deficit = IEEE80211_AIRTIME_QUANTUM;
+
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
return sta;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5c54acd10562..5d1802f22550 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -550,6 +550,13 @@ struct sta_info {
} tx_stats;
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
+ /* Airtime stats and deficit, protected by lock */
+ struct {
+ u64 rx_airtime;
+ u64 tx_airtime;
+ } airtime_stats;
+ s64 airtime_deficit;
+
/*
* Aggregation information, locked with lock.
*/
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index da7427a41529..cf7956f7a040 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -823,6 +823,14 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
ieee80211_lost_packet(sta, info);
}
}
+
+ if (ieee80211_hw_check(&local->hw, AIRTIME_ACCOUNTING) &&
+ info->status.tx_time) {
+ spin_lock_bh(&sta->lock);
+ sta->airtime_stats.tx_airtime += info->status.tx_time;
+ sta->airtime_deficit -= info->status.tx_time;
+ spin_unlock_bh(&sta->lock);
+ }
}
/* SNMP counters
@@ -947,6 +955,14 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
sta->status_stats.retry_failed++;
sta->status_stats.retry_count += retry_count;
+ if (ieee80211_hw_check(&local->hw, AIRTIME_ACCOUNTING) &&
+ info->status.tx_time) {
+ spin_lock_bh(&sta->lock);
+ sta->airtime_stats.tx_airtime += info->status.tx_time;
+ sta->airtime_deficit -= info->status.tx_time;
+ spin_unlock_bh(&sta->lock);
+ }
+
if (acked) {
sta->status_stats.last_ack = jiffies;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 824d87e6d3eb..409e84509625 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3530,7 +3530,7 @@ bool ieee80211_schedule_txq(struct ieee80211_hw *hw,
spin_lock_bh(&local->active_txq_lock);
if (list_empty(&txqi->schedule_order)) {
- list_add_tail(&txqi->schedule_order, &local->active_txqs);
+ list_add_tail(&txqi->schedule_order, &local->active_txqs_new);
ret = true;
}
@@ -3544,14 +3544,35 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = NULL;
+ struct list_head *head;
spin_lock_bh(&local->active_txq_lock);
- if (list_empty(&local->active_txqs))
- goto out;
+begin:
+ head = &local->active_txqs_new;
+ if (list_empty(head)) {
+ head = &local->active_txqs_old;
+ if (list_empty(head))
+ goto out;
+ }
+
+ txqi = list_first_entry(head, struct txq_info, schedule_order);
+
+ if (txqi->txq.sta) {
+ struct sta_info *sta = container_of(txqi->txq.sta,
+ struct sta_info, sta);
+
+ spin_lock_bh(&sta->lock);
+ if (sta->airtime_deficit < 0) {
+ sta->airtime_deficit += IEEE80211_AIRTIME_QUANTUM;
+ list_move_tail(&txqi->schedule_order,
+ &local->active_txqs_old);
+ spin_unlock_bh(&sta->lock);
+ goto begin;
+ }
+ spin_unlock_bh(&sta->lock);
+ }
- txqi = list_first_entry(&local->active_txqs,
- struct txq_info, schedule_order);
list_del_init(&txqi->schedule_order);
out:
--
2.14.2
^ permalink raw reply related
* [PATCH v2 3/3] ath9k: Switch to mac80211 airtime API
From: Toke Høiland-Jørgensen @ 2017-10-27 14:14 UTC (permalink / raw)
To: make-wifi-fast, linux-wireless; +Cc: Toke Høiland-Jørgensen
In-Reply-To: <20171016160902.8970-1-toke@toke.dk>
This removes the in-driver airtime fairness scheduling from ath9k and
switches the driver to use the API introduced in mac80211 in the
previous commit.
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
Changes since v1:
- Split out ath9k changes into separate patch
drivers/net/wireless/ath/ath9k/ath9k.h | 7 +---
drivers/net/wireless/ath/ath9k/debug.h | 8 -----
drivers/net/wireless/ath/ath9k/debug_sta.c | 54 ------------------------------
drivers/net/wireless/ath/ath9k/init.c | 4 +--
drivers/net/wireless/ath/ath9k/recv.c | 11 ++----
drivers/net/wireless/ath/ath9k/xmit.c | 21 ++++--------
6 files changed, 12 insertions(+), 93 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index f6c53df78856..f6e8f9b1b984 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -112,8 +112,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
#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
@@ -215,6 +213,7 @@ struct ath_buf_state {
bool stale;
u16 seqno;
unsigned long bfs_paprd_timestamp;
+ u32 airtime;
};
struct ath_buf {
@@ -262,12 +261,9 @@ struct ath_node {
bool sleeping;
bool no_ps_filter;
- s64 airtime_deficit[IEEE80211_NUM_ACS];
- u32 airtime_rx_start;
#ifdef CONFIG_ATH9K_STATION_STATISTICS
struct ath_rx_rate_stats rx_rate_stats;
- struct ath_airtime_stats airtime_stats;
#endif
u8 key_idx[4];
@@ -986,7 +982,6 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
#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 {
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 249f8141cd00..559d9628f280 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -319,20 +319,12 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause)
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 /* CONFIG_ATH9K_STATION_STATISTICS */
#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index efc692ee67d4..89ba95287a8b 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -242,59 +242,6 @@ static const struct file_operations fops_node_recv = {
.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,
@@ -304,5 +251,4 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw,
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);
}
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index bb7936090b91..b4c6fc49b19e 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -620,8 +620,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
/* 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->airtime_flags = (AIRTIME_USE_TX | AIRTIME_USE_RX);
sc->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
@@ -873,6 +872,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
+ ieee80211_hw_set(hw, AIRTIME_ACCOUNTING);
if (ath9k_ps_enable)
ieee80211_hw_set(hw, SUPPORTS_PS);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 2197aee2bb72..69a4ba5d4013 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1054,14 +1054,9 @@ static void ath_rx_count_airtime(struct ath_softc *sc,
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);
+ if (!!(sc->airtime_flags & AIRTIME_USE_RX))
+ rxs->airtime = airtime;
+
exit:
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index bd438062a6db..5ffd44a4b3de 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -640,11 +640,9 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
-static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
- struct ath_atx_tid *tid, struct ath_buf *bf,
+static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts)
{
- struct ath_txq *txq = tid->txq;
u32 airtime = 0;
int i;
@@ -654,15 +652,9 @@ static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an,
airtime += rate_dur * bf->rates[i].count;
}
- if (sc->airtime_flags & AIRTIME_USE_TX) {
- int q = txq->mac80211_qnum;
- struct ath_acq *acq = &sc->cur_chan->acq[q];
+ if (sc->airtime_flags & AIRTIME_USE_TX)
+ bf->bf_state.airtime = airtime;
- spin_lock_bh(&acq->lock);
- an->airtime_deficit[q] -= airtime;
- spin_unlock_bh(&acq->lock);
- }
- ath_debug_airtime(sc, an, 0, airtime);
}
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
@@ -692,7 +684,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
if (sta) {
struct ath_node *an = (struct ath_node *)sta->drv_priv;
tid = ath_get_skb_tid(sc, an, bf->bf_mpdu);
- ath_tx_count_airtime(sc, an, tid, bf, ts);
+ ath_tx_count_airtime(sc, bf, ts);
if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY))
tid->clear_ps_filter = true;
}
@@ -2428,6 +2420,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
if (ts->ts_status & ATH9K_TXERR_FILT)
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ tx_info->status.tx_time = min_t(u32, 0xffff, bf->bf_state.airtime);
+
dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
bf->bf_buf_addr = 0;
if (sc->tx99_state)
@@ -2754,9 +2748,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
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;
--
2.14.2
^ permalink raw reply related
* Re: wcn36xx: Remove unnecessary rcu_read_unlock in wcn36xx_bss_info_changed
From: Kalle Valo @ 2017-10-27 14:00 UTC (permalink / raw)
To: Jia-Ju Bai
Cc: k.eugene.e, kvalo, wcn36xx, linux-wireless, netdev, linux-kernel,
Jia-Ju Bai
In-Reply-To: <1507467969-24016-1-git-send-email-baijiaju1990@163.com>
Jia-Ju Bai <baijiaju1990@163.com> wrote:
> No rcu_read_lock is called, but rcu_read_unlock is still called.
> Thus rcu_read_unlock should be removed.
>
> Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
> Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-current branch of ath.git, thanks.
c0d5adc35c0b wcn36xx: Remove unnecessary rcu_read_unlock in wcn36xx_bss_info_changed
--
https://patchwork.kernel.org/patch/9991827/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: drivers/wireless: ath: Convert timers to use timer_setup()
From: Kalle Valo @ 2017-10-27 13:55 UTC (permalink / raw)
To: Kees Cook; +Cc: Kalle Valo, linux-wireless, netdev, linux-kernel
In-Reply-To: <20171024092954.GA47365@beast>
Kees Cook <keescook@chromium.org> wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
>
> Cc: Kalle Valo <kvalo@qca.qualcomm.com>
> Cc: linux-wireless@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
7ac767645ab1 ath: Convert timers to use timer_setup()
--
https://patchwork.kernel.org/patch/10023835/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: wil6210: remove SSID debugfs
From: Kalle Valo @ 2017-10-27 13:53 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Maya Erez, Johannes Berg
In-Reply-To: <20171017193355.7351-1-johannes@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> wrote:
> This driver shouldn't be using wdev->ssid to start with, as
> it's more or less an internal field in cfg80211 used for
> various purposes. Reading it is possible through nl80211,
> even if that's not really what we should be doing there
> for anything but AP type interfaces.
>
> It *really* shouldn't allow modifying it!
>
> Remove the whole debugfs entry.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
698dbbf82bbf wil6210: remove SSID debugfs
--
https://patchwork.kernel.org/patch/10012771/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: wil6210: remove wil6210_uapi.h from MAINTAINERS
From: Kalle Valo @ 2017-10-27 13:53 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Maya Erez, Johannes Berg
In-Reply-To: <20171017193458.7473-1-johannes@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> wrote:
> This file doesn't exist.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
6bac0d2cda71 wil6210: remove wil6210_uapi.h from MAINTAINERS
--
https://patchwork.kernel.org/patch/10012773/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: ath9k: debug: Remove redundant check
From: Kalle Valo @ 2017-10-27 13:50 UTC (permalink / raw)
To: Christos Gkekas
Cc: QCA ath9k Development, Kalle Valo, linux-wireless, netdev,
linux-kernel, Christos Gkekas
In-Reply-To: <1507974371-7419-1-git-send-email-chris.gekas@gmail.com>
Christos Gkekas <chris.gekas@gmail.com> wrote:
> Variable val is unsigned, so checking whether it is less than zero is
> redundant.
>
> Signed-off-by: Christos Gkekas <chris.gekas@gmail.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
9d414949a306 ath9k: debug: Remove redundant check
--
https://patchwork.kernel.org/patch/10006341/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: ath10k: spectral: Remove redundant check
From: Kalle Valo @ 2017-10-27 13:49 UTC (permalink / raw)
To: Christos Gkekas
Cc: ath10k, linux-wireless, netdev, linux-kernel, Christos Gkekas
In-Reply-To: <1507974075-6987-1-git-send-email-chris.gekas@gmail.com>
Christos Gkekas <chris.gekas@gmail.com> wrote:
> Variable val is unsigned, so checking whether it is less than zero is
> redundant.
>
> Signed-off-by: Christos Gkekas <chris.gekas@gmail.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
d83c0d3293bb ath10k: spectral: remove redundant check in write_file_spectral_count()
--
https://patchwork.kernel.org/patch/10006335/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: ath10k: fix sending wmi cmd during the tdls teardown
From: Kalle Valo @ 2017-10-27 13:48 UTC (permalink / raw)
To: akolli; +Cc: ath10k, akolli, linux-wireless, Anilkumar Kolli
In-Reply-To: <1507183926-711-1-git-send-email-akolli@qti.qualcomm.com>
akolli@qti.qualcomm.com wrote:
> The current firmware 10.4-3.5.1-00035 on QCA9888 supports
> TDLS explicit mode, it expects WMI_TDLS_ENABLE_PASSIVE
> for tdls setup and WMI_TDLS_DISABLE for tdls teardown.
>
> Signed-off-by: Anilkumar Kolli <akolli@qti.qualcomm.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
e5b6853e9922 ath10k: fix sending wmi cmd during the tdls teardown
--
https://patchwork.kernel.org/patch/9986455/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [1/2] ath10k: move ath10k_mac_tdls_vif*() functions
From: Kalle Valo @ 2017-10-27 13:46 UTC (permalink / raw)
To: akolli; +Cc: ath10k, akolli, linux-wireless, Anilkumar Kolli
In-Reply-To: <1507183709-585-1-git-send-email-akolli@qti.qualcomm.com>
akolli@qti.qualcomm.com wrote:
> To be able to use ath10k_mac_tdls_vif_stations_count() in
> ath10k_hw_scan() in the following patch, move the functions
> earlier in the file.
>
> This commit is pure code move, no functional changes.
>
> Signed-off-by: Anilkumar Kolli <akolli@qti.qualcomm.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
2 patches applied to ath-next branch of ath.git, thanks.
dd0f9cd6bc6a ath10k: move ath10k_mac_tdls_vif*() functions
a60809313b96 ath10k: block offchannel operations if TDLS session is active
--
https://patchwork.kernel.org/patch/9986447/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: wil6210: disallow changing RSN in beacon change
From: Johannes Berg @ 2017-10-27 13:45 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless, Maya Erez
In-Reply-To: <f48cbfcf31204a839d345927f712227f@euamsexm01a.eu.qualcomm.com>
On Fri, 2017-10-27 at 15:42 +0200, Kalle Valo wrote:
> Johannes Berg <johannes@sipsolutions.net> wrote:
>
> > This is a code path that will never really get hit anyway, since
> > it's nonsense to change the beacon of an existing BSS to suddenly
> > include or no longer include the RSN IE. Reject this instead of
> > having the dead code, and get rid of accessing wdev->ssid/_len by
> > way of that.
> >
> > Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> > Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
>
> What's the conclusion, should I take this patch or drop it?
Drop, at least for now. I need to look into this and probably do things
in cfg80211.
johannes
^ permalink raw reply
* Re: ath10k: fix build errors with !CONFIG_PM
From: Kalle Valo @ 2017-10-27 13:44 UTC (permalink / raw)
To: Brian Norris
Cc: Ryan Hsu, Grant Grundler, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org, ath10k@lists.infradead.org,
Arnd Bergmann
In-Reply-To: <20171019184517.GA76422@google.com>
Brian Norris <briannorris@chromium.org> wrote:
> Build errors have been reported with CONFIG_PM=n:
>
> drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit
> declaration of function 'ath10k_pci_suspend'
> [-Werror=implicit-function-declaration]
>
> drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit
> declaration of function 'ath10k_pci_resume'
> [-Werror=implicit-function-declaration]
>
> These are caused by the combination of the following two commits:
>
> 6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
> 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but
> disabled")
>
> Both build fine on their own.
>
> But now that ath10k_pci_pm_{suspend,resume}() is compiled
> unconditionally, we should also compile ath10k_pci_{suspend,resume}()
> unconditionally.
>
> And drop the #ifdef around ath10k_pci_hif_{suspend,resume}() too; they
> are trivial (empty), so we're not saving much space by compiling them
> out. And the alternatives would be to sprinkle more __maybe_unused, or
> spread the #ifdef's further.
>
> Build tested with the following combinations:
> CONFIG_PM=y && CONFIG_PM_SLEEP=y
> CONFIG_PM=y && CONFIG_PM_SLEEP=n
> CONFIG_PM=n
>
> Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but disabled")
> Fixes: 096ad2a15fd8 ("Merge branch 'ath-next'")
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
20665a9076d4 ath10k: fix build errors with !CONFIG_PM
--
https://patchwork.kernel.org/patch/10018169/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: wil6210: disallow changing RSN in beacon change
From: Kalle Valo @ 2017-10-27 13:42 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Maya Erez, Johannes Berg
In-Reply-To: <20171017194253.10212-1-johannes@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> wrote:
> This is a code path that will never really get hit anyway, since
> it's nonsense to change the beacon of an existing BSS to suddenly
> include or no longer include the RSN IE. Reject this instead of
> having the dead code, and get rid of accessing wdev->ssid/_len by
> way of that.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
What's the conclusion, should I take this patch or drop it?
--
https://patchwork.kernel.org/patch/10012789/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [01/12] wil6210: run-time PM when interface down
From: Kalle Valo @ 2017-10-27 13:33 UTC (permalink / raw)
To: Maya Erez; +Cc: Kalle Valo, Lazar Alexei, linux-wireless, wil6210, Maya Erez
In-Reply-To: <1508937247-11890-2-git-send-email-qca_merez@qca.qualcomm.com>
Maya Erez <qca_merez@qca.qualcomm.com> wrote:
> Allow run-time suspend when interface is down, keep card alive when
> interface is up.
> If driver is in wmi only or debug_fw mode run-time PM won't suspend.
>
> Signed-off-by: Lazar Alexei <qca_ailizaro@qca.qualcomm.com>
> pcie_bus.c
> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Kbuild bot found problems:
drivers/net//wireless/ath/wil6210/pcie_bus.c: In function 'wil6210_pm_runtime_resume':
>> drivers/net//wireless/ath/wil6210/pcie_bus.c:511:2: error: implicit
>> declaration of function 'wil6210_resume'
>> [-Werror=implicit-function-declaration]
return wil6210_resume(dev, true);
^
drivers/net//wireless/ath/wil6210/pcie_bus.c: In function
'wil6210_pm_runtime_suspend':
>> drivers/net//wireless/ath/wil6210/pcie_bus.c:524:2: error: implicit
>> declaration of function 'wil6210_suspend'
>> [-Werror=implicit-function-declaration]
return wil6210_suspend(dev, true);
^
--
https://patchwork.kernel.org/patch/10026675/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Submit patches for v4.15 now
From: Kalle Valo @ 2017-10-27 13:13 UTC (permalink / raw)
To: linux-wireless
Hi,
merge window is getting closer, most like it will open in 1-2 weeks. If
there's anything you want to have in v4.15 submit them now so that
there's enough time to get everything ready.
--
Kalle Valo
^ permalink raw reply
* [v3 3/3] rsi: sdio: Add WOWLAN support for S5 shutdown state
From: Amitkumar Karwar @ 2017-10-27 11:25 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, Amitkumar Karwar, Prameela Rani Garnepudi,
Karun Eagalapati
In-Reply-To: <1509103557-6215-1-git-send-email-amitkarwar@gmail.com>
From: Karun Eagalapati <karun256@gmail.com>
Unlike other power states, WoWLAN configuration does not come from
mac80211 for shutdown. Hence configuring the WoWLAN from shut down
callback it self. Remaining steps of disabling SDIO interrupts,
setting 'MMC_PM_KEEP_POWER' flag are same as other power states.
Signed-off-by: Karun Eagalapati <karun256@gmail.com>
Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
---
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 1 +
drivers/net/wireless/rsi/rsi_91x_sdio.c | 31 +++++++++++++++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 95eb5e6..36c63e9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1822,6 +1822,7 @@ int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan)
return 0;
}
+EXPORT_SYMBOL(rsi_config_wowlan);
#ifdef CONFIG_PM
static int rsi_mac80211_suspend(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 3f683d8..3288fb6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1218,12 +1218,11 @@ static int rsi_freeze(struct device *dev)
common = adapter->priv;
sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
-#ifdef CONFIG_RSI_WOW
if ((common->wow_flags & RSI_WOW_ENABLED) &&
(common->wow_flags & RSI_WOW_NO_CONNECTION))
rsi_dbg(ERR_ZONE,
"##### Device can not wake up through WLAN\n");
-#endif
+
ret = rsi_sdio_disable_interrupts(pfunction);
if (sdev->write_fail)
@@ -1257,6 +1256,31 @@ static int rsi_thaw(struct device *dev)
return 0;
}
+static void rsi_shutdown(struct device *dev)
+{
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+ struct rsi_91x_sdiodev *sdev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
+
+ rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n");
+
+ if (rsi_config_wowlan(adapter, wowlan))
+ rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
+
+ rsi_sdio_disable_interrupts(sdev->pfunction);
+
+ if (sdev->write_fail)
+ rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
+
+ if (rsi_set_sdio_pm_caps(adapter))
+ rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
+
+ rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
+}
+
int rsi_sdio_reinit_device(struct rsi_hw *adapter)
{
struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
@@ -1297,9 +1321,7 @@ static int rsi_restore(struct device *dev)
adapter->sc_nvifs = 0;
ieee80211_restart_hw(adapter->hw);
-#ifdef CONFIG_RSI_WOW
common->wow_flags = 0;
-#endif
common->iface_down = false;
rsi_dbg(INFO_ZONE, "RSI module restored\n");
@@ -1331,6 +1353,7 @@ static struct sdio_driver rsi_driver = {
#ifdef CONFIG_PM
.drv = {
.pm = &rsi_pm_ops,
+ .shutdown = rsi_shutdown,
}
#endif
};
--
2.7.4
^ permalink raw reply related
* [v3 2/3] rsi: sdio: Add WOWLAN support for S4 hibernate state
From: Amitkumar Karwar @ 2017-10-27 11:25 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, Amitkumar Karwar, Prameela Rani Garnepudi,
Karun Eagalapati
In-Reply-To: <1509103557-6215-1-git-send-email-amitkarwar@gmail.com>
From: Karun Eagalapati <karun256@gmail.com>
We are disabling of interrupts from firmware in freeze handler.
Also setting power management capability KEEP_MMC_POWER to make
device wakeup for WoWLAN trigger.
At restore, we observed a device reset on some platforms. Hence
reloading of firmware and device initialization is performed.
Signed-off-by: Karun Eagalapati <karun256@gmail.com>
Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 2 +
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 9 +++
drivers/net/wireless/rsi/rsi_91x_main.c | 1 +
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 7 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 111 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_main.h | 4 +
drivers/net/wireless/rsi/rsi_sdio.h | 1 +
7 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index 87e023d..d0d2201 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -276,6 +276,8 @@ void rsi_core_qos_processor(struct rsi_common *common)
rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);
break;
}
+ if (common->hibernate_resume)
+ break;
mutex_lock(&common->tx_lock);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index c3bd3ca..95eb5e6 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -17,6 +17,7 @@
#include <linux/etherdevice.h>
#include "rsi_debugfs.h"
#include "rsi_mgmt.h"
+#include "rsi_sdio.h"
#include "rsi_common.h"
#include "rsi_ps.h"
@@ -325,6 +326,11 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw)
rsi_dbg(ERR_ZONE, "===> Interface UP <===\n");
mutex_lock(&common->mutex);
+ if (common->hibernate_resume) {
+ common->reinit_hw = true;
+ adapter->host_intf_ops->reinit_device(adapter);
+ wait_for_completion(&adapter->priv->wlan_init_completion);
+ }
common->iface_down = false;
wiphy_rfkill_start_polling(hw->wiphy);
rsi_send_rx_filter_frame(common, 0);
@@ -1846,6 +1852,9 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw)
rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
+ if (common->hibernate_resume)
+ return 0;
+
mutex_lock(&common->mutex);
rsi_send_wowlan_request(common, 0, 0);
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 2a1fbb7..0cb8e68 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -263,6 +263,7 @@ struct rsi_hw *rsi_91x_init(void)
rsi_default_ps_params(adapter);
spin_lock_init(&adapter->ps_lock);
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
+ init_completion(&common->wlan_init_completion);
common->init_done = true;
return adapter;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 1446ee3..d38a09f 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1761,7 +1761,11 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
common->bb_rf_prog_count--;
if (!common->bb_rf_prog_count) {
common->fsm_state = FSM_MAC_INIT_DONE;
- return rsi_mac80211_attach(common);
+ if (common->reinit_hw) {
+ complete(&common->wlan_init_completion);
+ } else {
+ return rsi_mac80211_attach(common);
+ }
}
} else {
rsi_dbg(INFO_ZONE,
@@ -1839,6 +1843,7 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
case TA_CONFIRM_TYPE:
return rsi_handle_ta_confirm_type(common, msg);
case CARD_READY_IND:
+ common->hibernate_resume = false;
rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n",
__func__);
return rsi_handle_card_ready(common, msg);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index fa6af7b..3f683d8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -880,6 +880,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = {
.master_reg_read = rsi_sdio_master_reg_read,
.master_reg_write = rsi_sdio_master_reg_write,
.load_data_master_write = rsi_sdio_load_data_master_write,
+ .reinit_device = rsi_sdio_reinit_device,
};
/**
@@ -936,6 +937,8 @@ static int rsi_probe(struct sdio_func *pfunction,
return -EIO;
}
+ adapter->priv->hibernate_resume = false;
+ adapter->priv->reinit_hw = false;
return 0;
fail:
rsi_91x_deinit(adapter);
@@ -1198,9 +1201,117 @@ static int rsi_resume(struct device *dev)
return 0;
}
+static int rsi_freeze(struct device *dev)
+{
+ int ret;
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+ struct rsi_common *common;
+ struct rsi_91x_sdiodev *sdev;
+
+ rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n");
+
+ if (!adapter) {
+ rsi_dbg(ERR_ZONE, "Device is not ready\n");
+ return -ENODEV;
+ }
+ common = adapter->priv;
+ sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
+#ifdef CONFIG_RSI_WOW
+ if ((common->wow_flags & RSI_WOW_ENABLED) &&
+ (common->wow_flags & RSI_WOW_NO_CONNECTION))
+ rsi_dbg(ERR_ZONE,
+ "##### Device can not wake up through WLAN\n");
+#endif
+ ret = rsi_sdio_disable_interrupts(pfunction);
+
+ if (sdev->write_fail)
+ rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
+
+ ret = rsi_set_sdio_pm_caps(adapter);
+ if (ret)
+ rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
+
+ rsi_dbg(INFO_ZONE, "***** RSI module freezed *****\n");
+
+ return 0;
+}
+
+static int rsi_thaw(struct device *dev)
+{
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(ERR_ZONE, "SDIO Bus thaw =====>\n");
+
+ common->hibernate_resume = true;
+ common->fsm_state = FSM_CARD_NOT_READY;
+ common->iface_down = true;
+
+ rsi_sdio_enable_interrupts(pfunction);
+
+ rsi_dbg(INFO_ZONE, "***** RSI module thaw done *****\n");
+
+ return 0;
+}
+
+int rsi_sdio_reinit_device(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
+ struct sdio_func *pfunction = sdev->pfunction;
+ int ii;
+
+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
+ skb_queue_purge(&adapter->priv->tx_queue[ii]);
+
+ /* Initialize device again */
+ sdio_claim_host(pfunction);
+
+ sdio_release_irq(pfunction);
+ rsi_reset_card(pfunction);
+
+ sdio_enable_func(pfunction);
+ rsi_setupcard(adapter);
+ rsi_init_sdio_slave_regs(adapter);
+ sdio_claim_irq(pfunction, rsi_handle_interrupt);
+ rsi_hal_device_init(adapter);
+
+ sdio_release_host(pfunction);
+
+ return 0;
+}
+
+static int rsi_restore(struct device *dev)
+{
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(INFO_ZONE, "SDIO Bus restore ======>\n");
+ common->hibernate_resume = true;
+ common->fsm_state = FSM_FW_NOT_LOADED;
+ common->iface_down = true;
+
+ adapter->sc_nvifs = 0;
+ ieee80211_restart_hw(adapter->hw);
+
+#ifdef CONFIG_RSI_WOW
+ common->wow_flags = 0;
+#endif
+ common->iface_down = false;
+
+ rsi_dbg(INFO_ZONE, "RSI module restored\n");
+
+ return 0;
+}
static const struct dev_pm_ops rsi_pm_ops = {
.suspend = rsi_suspend,
.resume = rsi_resume,
+ .freeze = rsi_freeze,
+ .thaw = rsi_thaw,
+ .restore = rsi_restore,
};
#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 44a199f..8cab630 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -214,6 +214,7 @@ struct rsi_common {
struct rsi_thread tx_thread;
struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 2];
+ struct completion wlan_init_completion;
/* Mutex declaration */
struct mutex mutex;
/* Mutex used for tx thread */
@@ -272,6 +273,8 @@ struct rsi_common {
u8 obm_ant_sel_val;
int tx_power;
u8 ant_in_use;
+ bool hibernate_resume;
+ bool reinit_hw;
u8 wow_flags;
u16 beacon_interval;
u8 dtim_cnt;
@@ -362,5 +365,6 @@ struct rsi_host_intf_ops {
int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
u32 instructions_size, u16 block_size,
u8 *fw);
+ int (*reinit_device)(struct rsi_hw *adapter);
};
#endif
diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h
index 49c549b..8fbf90e 100644
--- a/drivers/net/wireless/rsi/rsi_sdio.h
+++ b/drivers/net/wireless/rsi/rsi_sdio.h
@@ -131,4 +131,5 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word);
void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num);
+int rsi_sdio_reinit_device(struct rsi_hw *adapter);
#endif
--
2.7.4
^ permalink raw reply related
* [v3 1/3] rsi: sdio: add WOWLAN support for S3 suspend state
From: Amitkumar Karwar @ 2017-10-27 11:25 UTC (permalink / raw)
To: Kalle Valo
Cc: linux-wireless, Amitkumar Karwar, Prameela Rani Garnepudi,
Karun Eagalapati
In-Reply-To: <1509103557-6215-1-git-send-email-amitkarwar@gmail.com>
From: Karun Eagalapati <karun256@gmail.com>
WoWLAN is supported in RS9113 device through GPIO pin2.
wowlan config frame is internally sent to firmware in mac80211
suspend handler. Also beacon miss threshold and keep-alive time
values are increased to avoid un-necessary disconnection with AP.
Signed-off-by: Karun Eagalapati <karun256@gmail.com>
Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
---
drivers/net/wireless/rsi/rsi_91x_core.c | 6 ++
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 118 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 60 +++++++++++---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 7 ++
drivers/net/wireless/rsi/rsi_common.h | 1 +
drivers/net/wireless/rsi/rsi_main.h | 8 +-
drivers/net/wireless/rsi/rsi_mgmt.h | 31 +++++++-
7 files changed, 220 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index bc18a19..87e023d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -379,6 +379,12 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
goto xmit_fail;
}
+ if (common->wow_flags & RSI_WOW_ENABLED) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Blocking Tx_packets when WOWLAN is enabled\n",
+ __func__);
+ goto xmit_fail;
+ }
info = IEEE80211_SKB_CB(skb);
tx_params = (struct skb_info *)info->driver_data;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 9427c9d..c3bd3ca 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -1746,6 +1746,119 @@ static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw)
return 0;
}
+static const struct wiphy_wowlan_support rsi_wowlan_support = {
+ .flags = WIPHY_WOWLAN_ANY |
+ WIPHY_WOWLAN_MAGIC_PKT |
+ WIPHY_WOWLAN_DISCONNECT |
+ WIPHY_WOWLAN_GTK_REKEY_FAILURE |
+ WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ |
+ WIPHY_WOWLAN_4WAY_HANDSHAKE,
+};
+
+static u16 rsi_wow_map_triggers(struct rsi_common *common,
+ struct cfg80211_wowlan *wowlan)
+{
+ u16 wow_triggers = 0;
+
+ rsi_dbg(INFO_ZONE, "Mapping wowlan triggers\n");
+
+ if (wowlan->any)
+ wow_triggers |= RSI_WOW_ANY;
+ if (wowlan->magic_pkt)
+ wow_triggers |= RSI_WOW_MAGIC_PKT;
+ if (wowlan->disconnect)
+ wow_triggers |= RSI_WOW_DISCONNECT;
+ if (wowlan->gtk_rekey_failure || wowlan->eap_identity_req ||
+ wowlan->four_way_handshake)
+ wow_triggers |= RSI_WOW_GTK_REKEY;
+
+ return wow_triggers;
+}
+
+int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan)
+{
+ struct rsi_common *common = adapter->priv;
+ u16 triggers = 0;
+ u16 rx_filter_word = 0;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+
+ rsi_dbg(INFO_ZONE, "Config WoWLAN to device\n");
+
+ if (WARN_ON(!wowlan)) {
+ rsi_dbg(ERR_ZONE, "WoW triggers not enabled\n");
+ return -EINVAL;
+ }
+
+ triggers = rsi_wow_map_triggers(common, wowlan);
+ if (!triggers) {
+ rsi_dbg(ERR_ZONE, "%s:No valid WoW triggers\n", __func__);
+ return -EINVAL;
+ }
+ if (!bss->assoc) {
+ rsi_dbg(ERR_ZONE,
+ "Cannot configure WoWLAN (Station not connected)\n");
+ common->wow_flags |= RSI_WOW_NO_CONNECTION;
+ return 0;
+ }
+ rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
+ rsi_send_wowlan_request(common, triggers, 1);
+
+ /**
+ * Increase the beacon_miss threshold & keep-alive timers in
+ * vap_update frame
+ */
+ rsi_send_vap_dynamic_update(common);
+
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER | DISALLOW_BEACONS);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ common->wow_flags |= RSI_WOW_ENABLED;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rsi_mac80211_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(INFO_ZONE, "%s: mac80211 suspend\n", __func__);
+ mutex_lock(&common->mutex);
+ if (rsi_config_wowlan(adapter, wowlan)) {
+ rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
+ mutex_unlock(&common->mutex);
+ return 1;
+ }
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+static int rsi_mac80211_resume(struct ieee80211_hw *hw)
+{
+ u16 rx_filter_word = 0;
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ common->wow_flags = 0;
+
+ rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
+
+ mutex_lock(&common->mutex);
+ rsi_send_wowlan_request(common, 0, 0);
+
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER | ALLOW_CTRL_ASSOC_PEER |
+ ALLOW_MGMT_ASSOC_PEER);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+#endif
+
static const struct ieee80211_ops mac80211_ops = {
.tx = rsi_mac80211_tx,
.start = rsi_mac80211_start,
@@ -1767,6 +1880,10 @@ static const struct ieee80211_ops mac80211_ops = {
.rfkill_poll = rsi_mac80211_rfkill_poll,
.remain_on_channel = rsi_mac80211_roc,
.cancel_remain_on_channel = rsi_mac80211_cancel_roc,
+#ifdef CONFIG_PM
+ .suspend = rsi_mac80211_suspend,
+ .resume = rsi_mac80211_resume,
+#endif
};
/**
@@ -1850,6 +1967,7 @@ int rsi_mac80211_attach(struct rsi_common *common)
wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
wiphy->reg_notifier = rsi_reg_notify;
+ wiphy->wowlan = &rsi_wowlan_support;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
/* Wi-Fi direct parameters */
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 4b94190..1446ee3 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1094,9 +1094,18 @@ int rsi_send_vap_dynamic_update(struct rsi_common *common)
dynamic_frame->desc_dword0.frame_type = VAP_DYNAMIC_UPDATE;
dynamic_frame->desc_dword2.pkt_info =
cpu_to_le32(common->rts_threshold);
- /* Beacon miss threshold */
- dynamic_frame->frame_body.keep_alive_period =
+
+ if (common->wow_flags & RSI_WOW_ENABLED) {
+ /* Beacon miss threshold */
+ dynamic_frame->desc_dword3.token =
+ cpu_to_le16(RSI_BCN_MISS_THRESHOLD);
+ dynamic_frame->frame_body.keep_alive_period =
+ cpu_to_le16(RSI_WOW_KEEPALIVE);
+ } else {
+ dynamic_frame->frame_body.keep_alive_period =
cpu_to_le16(RSI_DEF_KEEPALIVE);
+ }
+
dynamic_frame->desc_dword3.sta_id = 0; /* vap id */
skb_put(skb, sizeof(struct rsi_dynamic_s));
@@ -1340,13 +1349,12 @@ void rsi_inform_bss_status(struct rsi_common *common,
} else {
if (opmode == RSI_OPMODE_STA)
common->hw_data_qs_blocked = true;
- rsi_hal_send_sta_notify_frame(common,
- opmode,
- STA_DISCONNECTED,
- addr,
- qos_enable,
- aid, sta_id,
- vif);
+
+ if (!(common->wow_flags & RSI_WOW_ENABLED))
+ rsi_hal_send_sta_notify_frame(common, opmode,
+ STA_DISCONNECTED, addr,
+ qos_enable, aid, sta_id,
+ vif);
if (opmode == RSI_OPMODE_STA)
rsi_send_block_unblock_frame(common, true);
}
@@ -1589,6 +1597,40 @@ static int rsi_send_beacon(struct rsi_common *common)
return 0;
}
+int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
+ u16 sleep_status)
+{
+ struct rsi_wowlan_req *cmd_frame;
+ struct sk_buff *skb;
+ u8 length;
+
+ rsi_dbg(ERR_ZONE, "%s: Sending wowlan request frame\n", __func__);
+
+ length = sizeof(*cmd_frame);
+ skb = dev_alloc_skb(length);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, length);
+ cmd_frame = (struct rsi_wowlan_req *)skb->data;
+
+ rsi_set_len_qno(&cmd_frame->desc.desc_dword0.len_qno,
+ (length - FRAME_DESC_SZ),
+ RSI_WIFI_MGMT_Q);
+ cmd_frame->desc.desc_dword0.frame_type = WOWLAN_CONFIG_PARAMS;
+ cmd_frame->host_sleep_status = sleep_status;
+ if (common->secinfo.security_enable &&
+ common->secinfo.gtk_cipher)
+ flags |= RSI_WOW_GTK_REKEY;
+ if (sleep_status)
+ cmd_frame->wow_flags = flags;
+ rsi_dbg(INFO_ZONE, "Host_Sleep_Status : %d Flags : %d\n",
+ cmd_frame->host_sleep_status, cmd_frame->wow_flags);
+
+ skb_put(skb, length);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
/**
* rsi_handle_ta_confirm_type() - This function handles the confirm frames.
* @common: Pointer to the driver private structure.
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index b3f8006..fa6af7b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -1124,6 +1124,8 @@ static int rsi_sdio_enable_interrupts(struct sdio_func *pfunc)
{
u8 data;
int ret;
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunc);
+ struct rsi_common *common = adapter->priv;
sdio_claim_host(pfunc);
ret = rsi_cmd52readbyte(pfunc->card, RSI_INT_ENABLE_REGISTER, &data);
@@ -1143,6 +1145,11 @@ static int rsi_sdio_enable_interrupts(struct sdio_func *pfunc)
goto done;
}
+ if ((common->wow_flags & RSI_WOW_ENABLED) &&
+ (common->wow_flags & RSI_WOW_NO_CONNECTION))
+ rsi_dbg(ERR_ZONE,
+ "##### Device can not wake up through WLAN\n");
+
ret = rsi_cmd52readbyte(pfunc->card, RSI_INT_ENABLE_REGISTER, &data);
if (ret < 0) {
rsi_dbg(ERR_ZONE,
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 29acaea..70b8b4b 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -83,6 +83,7 @@ u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
struct rsi_hw *rsi_91x_init(void);
void rsi_91x_deinit(struct rsi_hw *adapter);
int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);
+int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan);
struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac);
void rsi_roc_timeout(struct timer_list *t);
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index a118b7a..44a199f 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -66,6 +66,8 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define FRAME_DESC_SZ 16
#define MIN_802_11_HDR_LEN 24
#define RSI_DEF_KEEPALIVE 90
+#define RSI_WOW_KEEPALIVE 5
+#define RSI_BCN_MISS_THRESHOLD 24
#define DATA_QUEUE_WATER_MARK 400
#define MIN_DATA_QUEUE_WATER_MARK 300
@@ -108,6 +110,10 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
((_q) == VI_Q) ? IEEE80211_AC_VI : \
IEEE80211_AC_VO)
+/* WoWLAN flags */
+#define RSI_WOW_ENABLED BIT(0)
+#define RSI_WOW_NO_CONNECTION BIT(1)
+
#define RSI_DEV_9113 1
struct version_info {
@@ -266,7 +272,7 @@ struct rsi_common {
u8 obm_ant_sel_val;
int tx_power;
u8 ant_in_use;
-
+ u8 wow_flags;
u16 beacon_interval;
u8 dtim_cnt;
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index e217230..76337ce 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -45,6 +45,17 @@
#define MAGIC_WORD 0x5A
#define WLAN_EEPROM_RFTYPE_ADDR 424
+/*WOWLAN RESUME WAKEUP TYPES*/
+#define RSI_UNICAST_MAGIC_PKT BIT(0)
+#define RSI_BROADCAST_MAGICPKT BIT(1)
+#define RSI_EAPOL_PKT BIT(2)
+#define RSI_DISCONNECT_PKT BIT(3)
+#define RSI_HW_BMISS_PKT BIT(4)
+#define RSI_INSERT_SEQ_IN_FW BIT(2)
+
+#define WOW_MAX_FILTERS_PER_LIST 16
+#define WOW_PATTERN_SIZE 256
+
/* Receive Frame Types */
#define TA_CONFIRM_TYPE 0x01
#define RX_DOT11_MGMT 0x02
@@ -201,6 +212,13 @@
#define RSI_DATA_DESC_INSERT_TSF BIT(15)
#define RSI_DATA_DESC_INSERT_SEQ_NO BIT(2)
+#ifdef CONFIG_PM
+#define RSI_WOW_ANY BIT(1)
+#define RSI_WOW_GTK_REKEY BIT(3)
+#define RSI_WOW_MAGIC_PKT BIT(4)
+#define RSI_WOW_DISCONNECT BIT(5)
+#endif
+
enum opmode {
RSI_OPMODE_UNSUPPORTED = -1,
RSI_OPMODE_AP = 0,
@@ -262,7 +280,9 @@ enum cmd_frame_type {
ANT_SEL_FRAME = 0x20,
VAP_DYNAMIC_UPDATE = 0x27,
COMMON_DEV_CONFIG = 0x28,
- RADIO_PARAMS_UPDATE = 0x29
+ RADIO_PARAMS_UPDATE = 0x29,
+ WOWLAN_CONFIG_PARAMS = 0x2B,
+ WOWLAN_WAKEUP_REASON = 0xc5
};
struct rsi_mac_frame {
@@ -581,6 +601,13 @@ struct rsi_request_ps {
__le16 ps_num_dtim_intervals;
} __packed;
+struct rsi_wowlan_req {
+ struct rsi_cmd_desc desc;
+ u8 sourceid[ETH_ALEN];
+ u16 wow_flags;
+ u16 host_sleep_status;
+} __packed;
+
static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
{
return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -641,6 +668,8 @@ int rsi_band_check(struct rsi_common *common, struct ieee80211_channel *chan);
int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
int rsi_send_radio_params_update(struct rsi_common *common);
int rsi_set_antenna(struct rsi_common *common, u8 antenna);
+int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
+ u16 sleep_status);
int rsi_send_ps_request(struct rsi_hw *adapter, bool enable,
struct ieee80211_vif *vif);
#endif
--
2.7.4
^ permalink raw reply related
* [v3 0/3] rsi: WOWLAN support
From: Amitkumar Karwar @ 2017-10-27 11:25 UTC (permalink / raw)
To: Kalle Valo; +Cc: linux-wireless, Amitkumar Karwar, Prameela Rani Garnepudi
From: Amitkumar Karwar <amit.karwar@redpinesignals.com>
This patch series adds WOWLAN support for system's S3, S4 and
S5 power states. wakeup through magic packet has been verified
in these power states.
Changes since v2:
Rebased the patch series to the latest code. Recently below patch
got accepted which causes some conflicts.
"drivers/wireless: rsi: Convert timers to use timer_setup()"
Changes since v1:
1/3 Get rid of CONFIG_RSI_WOW compiler flag (Kalle Valo)
2/3 Use ieee80211_restart_hw() instead of re-registering with mac80211 (Kalle Valo/Brian Norris)
3/3 Get rid of CONFIG_RSI_WOW compiler flag
Karun Eagalapati (3):
rsi: sdio: add WOWLAN support for S3 suspend state
rsi: sdio: Add WOWLAN support for S4 hibernate state
rsi: sdio: Add WOWLAN support for S5 shutdown state
drivers/net/wireless/rsi/rsi_91x_core.c | 8 ++
drivers/net/wireless/rsi/rsi_91x_mac80211.c | 128 +++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_main.c | 1 +
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 67 +++++++++++--
drivers/net/wireless/rsi/rsi_91x_sdio.c | 141 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_common.h | 1 +
drivers/net/wireless/rsi/rsi_main.h | 12 ++-
drivers/net/wireless/rsi/rsi_mgmt.h | 31 +++++-
drivers/net/wireless/rsi/rsi_sdio.h | 1 +
9 files changed, 378 insertions(+), 12 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH] mwifiex: do not transmit in 11N rates when connected in TKIP security
From: Ganapathi Bhat @ 2017-10-27 10:02 UTC (permalink / raw)
To: linux-wireless
Cc: Cathy Luo, Xinming Hu, Zhiyuan Yang, James Cao, Mangesh Malusare,
Ganapathi Bhat
Driver is transmitting in 11N rates, when connected to an AP in
TKIP security mode. Add a check to disable_11n to fix the issue.
Signed-off-by: Ganapathi Bhat <gbhat@marvell.com>
---
drivers/net/wireless/marvell/mwifiex/fw.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 6b765f3..13cd58e9 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -225,7 +225,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \
priv->adapter->config_bands & BAND_AN) && \
- priv->curr_bss_params.bss_descriptor.bcn_ht_cap)
+ priv->curr_bss_params.bss_descriptor.bcn_ht_cap && \
+ !priv->curr_bss_params.bss_descriptor.disable_11n)
#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\
BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS)
--
1.9.1
^ permalink raw reply related
* Re: ath10k-regression due to "ath10k: fix napi_poll budget overflow" c9353bf483d3
From: Kalle Valo @ 2017-10-27 9:40 UTC (permalink / raw)
To: Thorsten Leemhuis
Cc: Ryan Hsu, ath10k@lists.infradead.org,
linux-wireless@vger.kernel.org
In-Reply-To: <fa6e3ee2-91b5-a54b-afe3-87f30aac7a48@leemhuis.info>
KyBsaW51eC13aXJlbGVzcw0KDQpUaG9yc3RlbiBMZWVtaHVpcyA8bGludXhAbGVlbWh1aXMuaW5m
bz4gd3JpdGVzOg0KDQo+IExvISBPbiAwMy4xMC4yMDE3IDAxOjQwLCBSeWFuIEhzdSB3cm90ZToN
Cj4+IE9uIDEwLzAxLzIwMTcgMDE6NTkgQU0sIFRob3JzdGVuIExlZW1odWlzIHdyb3RlOg0KPj4+
IExvISBUaGUgd2lmaSBjb25uZWN0aW9uIG9mIG15IERlbGwgWFBTMTMgKDkzNjApIHdpdGggaXRz
IFFDQTYxNzQNCj4+PiBzb21ldGltZXMgc3VkZGVubHkgc3RvcHMgd29ya2luZyBzaW5jZSBJIHN3
aXRjaGVkIHRvIDQuMTQtcmMyKy4gRXZlcnkNCj4+PiB0aW1lIGl0IGhhcHBlbnMsIHRoZXJlIGlz
IHRoaXMgZXJyb3IgbWVzc2FnZSBpbiBkbWVzZzoNCj4+Pj4gYXRoMTBrX3BjaSAwMDAwOjNhOjAw
LjA6IGZhaWxlZCB0byBleHRyYWN0IGFtc2R1OiAtMTENCj4+PiBJIGhhdmUgdG8gc3dpdGNoIHdp
Zmkgb2ZmIGFuZCBvbiB3aXRoIHRoZSBob3RrZXkgdG8gcmVjb25uZWN0LiBJIGNhbg0KPj4+IHRy
aWdnZXIgdGhlIGFib3J0cyBieSBzdGFydGluZyBhIGJpZyBkb3dubG9hZCBhbmQgd2FpdGluZyBh
IGZldyBtaW51dGVzLg0KPj4+IFNvbWV0aW1lcyB0aGUgY29ubmVjdGlvbnMgYWJvcnRzIGR1cmlu
ZyBub3JtYWwgbG9hZC4gSW5zdGFsbGluZyB0aGUNCj4+PiBsYXRlc3QgZmlybXdhcmUgZGlkbid0
IGhlbHAuIFRoZSB3aWZpIHdvcmtzIGp1c3QgZmluZSB3aXRoIDQuMTMuMy4gV2hpbGUNCj4+PiBp
bnZlc3RpZ2F0aW5nIHRoaXMgSSBub3RpY2VkIGEgZmV3IG1lc3NhZ2VzIGluIGRtZXNnIHRoYXQg
b25seSBhcHBlYXIgaW4NCj4+PiA0LjE0LXJjIChJIHVzZWQgMzVkYmJhMzFiZTUyKToNCj4+IFlv
dSBkbyBydW4gdGhlIDQuMTMuMyB2LnMgNC4xNC1yYyB3aXRoIHRoZSBzYW1lIFFDQTYxNzQgZmly
bXdyYWUsIHJpZ2h0Pw0KPj4gSnVzdCB3YW50IHRvIHVuZGVyc3RhbmQgdGhlIHRlc3Qgc2V0dXAg
aGVyZSBzbyB0aGF0IEkgY291bGQgZ2l2ZSBpdA0KPj4gYSB0cnkgbXlzZWxmLCBhbmQgaW4gMTFh
YyBvciAxMW4gbW9kZSB5b3UncmUgdGVzdGluZz8NCj4NCj4gWXVwLCBzYW1lIGZpcm13YXJlIChy
ZXByb2R1Y2VkIGl0IHdpdGgNCj4gZmlybXdhcmUtNi5iaW5fV0xBTi5STS40LjQuMS0wMDA1OC1R
Q0FSTVNXUC0xIGJlZm9yZSBiaXNlY3RpbmcpLiBBbmQgdGhlDQo+IHByb2JsZW0gc2hvd2VkIHVw
IHdpdGggMmcgYW5kIDVnIG5ldHdvcmtzLiBCdXQgd2hpbGUgaW52ZXN0aWdhdGluZyBpdCBJDQo+
IG5vdGljZWQgdGhlIHByb2JsZW0gZG9lcyBub3Qgc2hvdyB1cCB3aXRoIGFsbCB3aWZpIHJvdXRl
cnMuIEl0IGhhcHBlbnMNCj4gd2l0aCBteSBGcml0eiFCb3ggNjQ5MCBDYWJsZSBhbmQgYW5vdGhl
ciBGcml0eiFCb3ggSSB0cmllZCwgYnV0IG5vdCB3aXRoDQo+IHRoZSB3aWZpIG5ldHdvcmsgYXQg
d29yayAobm8gaWRlYSB3aGF0IGtpbmQgb2Ygcm91dGVycyBhcmUgaW5zdGFsbGVkDQo+IHRoZXJl
OyBJIGNhbiB0cnkgdG8gZmluZCBvdXQgaWYgaXQgbWF0dGVycykuDQo+DQo+Pj4+IDNhOjAwLjAg
TmV0d29yayBjb250cm9sbGVyIFswMjgwXTogUXVhbGNvbW0gQXRoZXJvcyBRQ0E2MTc0DQo+Pj4+
IDgwMi4xMWFjIFdpcmVsZXNzIE5ldHdvcmsgQWRhcHRlciBbMTY4YzowMDNlXSAocmV2IDMyKQ0K
Pj4gW+KApl0gV291bGQgeW91IG1pbmQgZG8gYSBiaXNlY3QgdG8gbG9jYXRlIHRoZSBmYWlsdXJl
LCBwbGVhc2U/DQo+DQo+IERpZCB0aGF0IHllc3RlcmRheSBhbmQgaXQgdHVybmVkIG91dCBpdCdz
IGR1ZSB0byBjb21taXQgYzkzNTNiZjQ4M2QzDQo+IChhdGgxMGs6IGZpeCBuYXBpX3BvbGwgYnVk
Z2V0IG92ZXJmbG93KS4gUmV2ZXJ0aW5nIGl0IG9uIHRvcCBvZiBsaW51eA0KPiBtYXN0ZXIgZnJv
bSB5ZXN0ZXJkYXkgbWFkZSB0aGUgd2lmaSBjb25uZWN0aW9uIHN0YWJsZSBhZ2FpbiBmb3IgbWUu
DQoNClNvcnJ5LCBJIGhhdmUgbm90IGJlZW4gYWJsZSB0byBmb2xsb3cgdGhpcyBkaXNjdXNzaW9u
IHZlcnkgY2xvc2VseSBidXQNCndhcyB0aGUgY29uY2x1c2lvbj8gU2hvdWxkIHdlIHNob3VsZCBy
ZXZlcnQgYzkzNTNiZjQ4M2QzIGZvciA0LjE0IG9yDQp3aGF0PyBJIHNob3VsZCBzdGlsbCBoYXZl
IHRpbWUgdG8gZG8gdGhhdCwgYnV0IG5vdCBtdWNoLg0KDQotLSANCkthbGxlIFZhbG8=
^ permalink raw reply
* Re: [PATCH 2/2] ath10k: search DT for qcom, ath10k-calibration-variant
From: Kalle Valo @ 2017-10-27 9:34 UTC (permalink / raw)
To: Sven Eckelmann
Cc: Adrian Chadd, linux-wireless@vger.kernel.org,
ath10k@lists.infradead.org, Aeolus Yang, Christian Lamparter,
ext.waldemar.rymarkiewicz@tieto.com
In-Reply-To: <3114796.44GtYcDsBs@bentobox>
U3ZlbiBFY2tlbG1hbm4gPHN2ZW4uZWNrZWxtYW5uQG9wZW5tZXNoLmNvbT4gd3JpdGVzOg0KDQo+
IE9uIEZyZWl0YWcsIDEwLiBNw6RyeiAyMDE3IDE5OjIwOjU0IENFU1QgQ2hyaXN0aWFuIExhbXBh
cnRlciB3cm90ZToNCj4gWy4uLl0NCj4+IEBBZW9sdXMgWWFuZyAvIEthbGxlIC8gUUNBOiBXb3Vs
ZCBpdCBiZSBwb3NzaWJsZSB0byBhc3NpZ24gYSB2YXJpYW50IHN0cmluZyB0bw0KPj4gdGhlIEFz
dXMgUlQtQUM1OFU/DQo+PiANCj4+IEkndmUgYXR0YWNoZWQgdGhlIG5lY2Vzc2FyeSBibWktYm9h
cmQtaWQ9MTYgYW5kIGJtaS1ib2FyZC1pZD0xNyBib2FyZCANCj4+IGZpbGVzIHRvIHRoaXMgbWFp
bCBhcyB3ZWxsLiBTbywgYWxsIHRoYXQgbmVlZHMgdG8gYmUgZG9uZSBpcyB0byBhZGQNCj4+IHRo
ZW0gdG8gdGhlIGJvYXJkLTIuYmluIG9uIHlvdXIgY29kZWF1cm9yYSAvIGF0aDEway1maXJtd2Fy
ZSBwcm9qZWN0Lg0KPj4gDQo+PiBLYWxsZTogQ2FuIHlvdSBwbGVhc2UgdXBkYXRlIHRoZSBib2Fy
ZC0yLmJpbiBmb3IgdGhlIElQUTQwWFggb24geW91cg0KPj4gYXRoMTBrLWZpcm13YXJlIHByb2pl
Y3Qgb24gZ2l0aHViPw0KPj4gDQo+PiBodHRwczovL3NvdXJjZS5jb2RlYXVyb3JhLm9yZy9xdWlj
L3FzZGsvb3NzL2Zpcm13YXJlL2F0aDEway1maXJtd2FyZS9wbGFpbi9hdGgxMGsvUUNBNDBYWC9o
dzEuMC9ib2FyZC0yLmJpbg0KPj4gSXQgbG9va3MgbGlrZSB0aGlzIGJvYXJkLTIuYmluIGhhcyBz
dXBwb3J0IGZvciBhIGZldyBtb3JlIGJvYXJkcy4NCj4NCj4gQW55IHVwZGF0ZXMgb24gdGhhdD8N
Cg0KU29ycnksIEkgaGFkIG1pc3NlZCB0aGVzZSBzb21laG93LiBJIHB1dCB0aGVtIG5vdyBiYWNr
IHRvIG15IHF1ZXVlOg0KDQpodHRwczovL3BhdGNod29yay5rZXJuZWwub3JnL3BhdGNoLzk2MTUx
ODMvDQoNCmh0dHBzOi8vcGF0Y2h3b3JrLmtlcm5lbC5vcmcvcGF0Y2gvOTYxNTE4NS8NCg0KLS0g
DQpLYWxsZSBWYWxv
^ permalink raw reply
* Re: drivers/wireless: ath: Convert timers to use timer_setup()
From: Kees Cook @ 2017-10-27 9:29 UTC (permalink / raw)
To: Kalle Valo; +Cc: Kalle Valo, linux-wireless, Network Development, LKML
In-Reply-To: <df4525f9d784450fabe4bf685af6992e@euamsexm01a.eu.qualcomm.com>
On Fri, Oct 27, 2017 at 11:18 AM, Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> Kees Cook <keescook@chromium.org> wrote:
>
>> In preparation for unconditionally passing the struct timer_list pointer to
>> all timer callbacks, switch to using the new timer_setup() and from_timer()
>> to pass the timer pointer explicitly.
>>
>> Cc: Kalle Valo <kvalo@qca.qualcomm.com>
>> Cc: linux-wireless@vger.kernel.org
>> Cc: netdev@vger.kernel.org
>> Signed-off-by: Kees Cook <keescook@chromium.org>
>> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
>
> There were some conflicts but luckily 3-way merge was able to automatically
> solve them. But please do check the patch from my pending branch:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=master-pending&id=dd08329d31a4c150f8aab8274033901baaf3e923
This looks correct to me, thanks for merging!
-Kees
--
Kees Cook
Pixel Security
^ permalink raw reply
* Re: [v7,2/5] ath10k: Enable TDLS peer buffer STA feature
From: Kalle Valo @ 2017-10-27 9:25 UTC (permalink / raw)
To: yintang; +Cc: ath10k, linux-wireless
In-Reply-To: <1508835074-3384-3-git-send-email-yintang@qti.qualcomm.com>
yintang@qti.qualcomm.com wrote:
> From: Yingying Tang <yintang@qti.qualcomm.com>
>
> Enable TDLS peer buffer STA feature.
> QCA6174 firmware(version: WLAN.RM.4.4) support TDLS peer buffer STA,
> it reports this capability through wmi service map in wmi service ready
> event. Set related parameter in TDLS WMI command to enable this feature.
>
> Signed-off-by: Yingying Tang <yintang@qti.qualcomm.com>
Depends on:
a9cd27b34d66 mac80211: enable TDLS peer buffer STA feature
Currently in mac80211-next.
4 patches set to Awaiting Upstream.
10023753 [v7,2/5] ath10k: Enable TDLS peer buffer STA feature
10023743 [v7,3/5] ath10k: Enable TDLS peer inactivity detection
10023725 [v7,4/5] ath10k: Avoid to set WEP key for TDLS peer
10023737 [v7,5/5] ath10k: Fix TDLS peer TX data failure issue on encryped AP
--
https://patchwork.kernel.org/patch/10023753/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox