From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail2.tohojo.dk (mail2.tohojo.dk [77.235.48.147]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.bufferbloat.net (Postfix) with ESMTPS id D244D3B2A3 for ; Fri, 17 Jun 2016 05:17:54 -0400 (EDT) X-Virus-Scanned: amavisd-new at mail2.tohojo.dk DKIM-Filter: OpenDKIM Filter v2.10.3 mail2.tohojo.dk 6F51940A4C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=toke.dk; s=201310; t=1466155072; bh=PFOT13XlJm+DFeRAZYzwGswdnWlhQT9mLETd9v8xVK0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YqVI3cgRX6qur927PwzhZ2MNuMlZD6AfAnlmaYcPNNCFOBzxDHadM8nMlGVCbUOxJ AzqaQKxf1G3LjuIBxXrU0WswuG9yTG5vE1nI8rQqY/dJxXXxp4l1Z4ricR3PWvHuyk nFfn7E0Phs6cVO9XkmzjxZr5LbSBcBQvE3WbKycA= Received: by alrua-kau.kau.toke.dk (Postfix, from userid 1000) id C7960C40139; Fri, 17 Jun 2016 11:17:51 +0200 (CEST) From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= To: make-wifi-fast@lists.bufferbloat.net Cc: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= , Tim Shepard Date: Fri, 17 Jun 2016 11:17:35 +0200 Message-Id: <20160617091736.4730-2-toke@toke.dk> In-Reply-To: <20160617091736.4730-1-toke@toke.dk> References: <20160617091736.4730-1-toke@toke.dk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Make-wifi-fast] [PATCH 1/2] ath9k: use mac80211 intermediate software queues X-BeenThere: make-wifi-fast@lists.bufferbloat.net X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Jun 2016 09:17:55 -0000 This patch leaves the code for ath9k's internal per-node per-tid queues in place and just modifies the driver to also pull from the new mac80211 intermediate software queues, and implements the .wake_tx_queue method, which will cause mac80211 to deliver packets to be sent via the new intermediate queue. Signed-off-by: Tim Shepard Reworked to not require the global variable renaming in ath9k. Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen --- drivers/net/wireless/ath/ath9k/ath9k.h | 16 +++- drivers/net/wireless/ath/ath9k/debug_sta.c | 7 +- drivers/net/wireless/ath/ath9k/init.c | 1 + drivers/net/wireless/ath/ath9k/main.c | 1 + drivers/net/wireless/ath/ath9k/xmit.c | 119 +++++++++++++++++++++++= ++---- 5 files changed, 125 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireles= s/ath/ath9k/ath9k.h index 93b3793..caeae10 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -145,8 +145,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct at= h_descdma *dd, #define BAW_WITHIN(_start, _bawsz, _seqno) \ ((((_seqno) - (_start)) & 4095) < (_bawsz)) =20 -#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) - #define IS_HT_RATE(rate) (rate & 0x80) #define IS_CCK_RATE(rate) ((rate >=3D 0x18) && (rate <=3D 0x1e)) #define IS_OFDM_RATE(rate) ((rate >=3D 0x8) && (rate <=3D 0xf)) @@ -232,8 +230,10 @@ struct ath_buf { =20 struct ath_atx_tid { struct list_head list; + struct sk_buff_head i_q; struct sk_buff_head buf_q; struct sk_buff_head retry_q; + struct ieee80211_txq *swq; struct ath_node *an; struct ath_txq *txq; unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; @@ -247,13 +247,13 @@ struct ath_atx_tid { s8 bar_index; bool active; bool clear_ps_filter; + bool swq_nonempty; }; =20 struct ath_node { struct ath_softc *sc; struct ieee80211_sta *sta; /* station struct we're part of */ struct ieee80211_vif *vif; /* interface with which we're associated */ - struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; =20 u16 maxampdu; u8 mpdudensity; @@ -271,6 +271,15 @@ struct ath_node { struct list_head list; }; =20 +static inline +struct ath_atx_tid *ath_an_2_tid(struct ath_node *an, u8 tidno) +{ + struct ieee80211_sta *sta =3D an->sta; + struct ieee80211_vif *vif =3D an->vif; + struct ieee80211_txq *swq =3D sta ? sta->txq[tidno] : vif->txq; + return (struct ath_atx_tid *) swq->drv_priv; +} + struct ath_tx_control { struct ath_txq *txq; struct ath_node *an; @@ -585,6 +594,7 @@ void ath9k_release_buffered_frames(struct ieee80211_h= w *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 *= swq); =20 /********/ /* VIFs */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wir= eless/ath/ath9k/debug_sta.c index b66cfa9..0e7f6b5 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -25,6 +25,7 @@ static ssize_t read_file_node_aggr(struct file *file, c= har __user *user_buf, { struct ath_node *an =3D file->private_data; struct ath_softc *sc =3D an->sc; + struct ieee80211_txq *swq; struct ath_atx_tid *tid; struct ath_txq *txq; u32 len =3D 0, size =3D 4096; @@ -52,8 +53,10 @@ static ssize_t read_file_node_aggr(struct file *file, = char __user *user_buf, "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); =20 - for (tidno =3D 0, tid =3D &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + for (tidno =3D 0; + tidno < IEEE80211_NUM_TIDS; tidno++) { + swq =3D an->sta->txq[tidno]; + tid =3D (struct ath_atx_tid *) swq->drv_priv; txq =3D tid->txq; ath_txq_lock(sc, txq); if (tid->active) { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless= /ath/ath9k/init.c index 2ee8624..211736c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -873,6 +873,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, = struct ieee80211_hw *hw) hw->max_rate_tries =3D 10; hw->sta_data_size =3D sizeof(struct ath_node); hw->vif_data_size =3D sizeof(struct ath_vif); + hw->txq_data_size =3D sizeof(struct ath_atx_tid); hw->extra_tx_headroom =3D 4; =20 hw->wiphy->available_antennas_rx =3D BIT(ah->caps.max_rxchains) - 1; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless= /ath/ath9k/main.c index 8b63988..6ab56e5 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -2668,4 +2668,5 @@ struct ieee80211_ops ath9k_ops =3D { .sw_scan_start =3D ath9k_sw_scan_start, .sw_scan_complete =3D ath9k_sw_scan_complete, .get_txpower =3D ath9k_get_txpower, + .wake_tx_queue =3D ath9k_wake_tx_queue, }; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless= /ath/ath9k/xmit.c index 8ddd604..cdc8684 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -65,6 +65,8 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_s= oftc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, struct sk_buff *skb); +static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ath_tx_control *txctl); =20 enum { MCS_HT20, @@ -118,6 +120,21 @@ static void ath_tx_queue_tid(struct ath_softc *sc, s= truct ath_txq *txq, list_add_tail(&tid->list, list); } =20 +void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *= swq) +{ + struct ath_softc *sc =3D hw->priv; + struct ath_atx_tid *tid =3D (struct ath_atx_tid *) swq->drv_priv; + struct ath_txq *txq =3D tid->txq; + + spin_lock_bh(&txq->axq_lock); + + tid->swq_nonempty =3D true; + ath_tx_queue_tid(sc, txq, tid); + ath_txq_schedule(sc, txq); + + spin_unlock_bh(&txq->axq_lock); +} + static struct ath_frame_info *get_frame_info(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info =3D IEEE80211_SKB_CB(skb); @@ -170,12 +187,51 @@ static struct ath_atx_tid * ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buf= f *skb) { u8 tidno =3D skb->priority & IEEE80211_QOS_CTL_TID_MASK; - return ATH_AN_2_TID(an, tidno); + return ath_an_2_tid(an, tidno); } =20 +static void ath_swq_pull(struct ath_atx_tid *tid) +{ + struct sk_buff *skb; + struct ath_tx_control txctl; + struct ath_frame_info *fi; + int r; + + if (!skb_queue_empty(&tid->i_q)) + return; + + if (!tid->swq_nonempty) + return; + + skb =3D ieee80211_tx_dequeue(tid->an->sc->hw, tid->swq); + if (!skb) { + tid->swq_nonempty =3D false; + } else { + /* sad to do all this with axq_lock held */ + memset(&txctl, 0, sizeof txctl); + txctl.txq =3D tid->txq; + txctl.sta =3D tid->an->sta; + r =3D ath_tx_prepare(tid->an->sc->hw, skb, &txctl); + if (WARN_ON(r !=3D 0)) { + /** should not happen ??? */ + } else { + /* perhaps not needed here ??? */ + fi =3D get_frame_info(skb); + fi->txq =3D skb_get_queue_mapping(skb); + + __skb_queue_tail(&tid->i_q, skb); + ++tid->txq->pending_frames; + } + } + } + + static bool ath_tid_has_buffered(struct ath_atx_tid *tid) { - return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q)= ; + if (!skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q) ||= !skb_queue_empty(&tid->i_q)) + return true; + ath_swq_pull(tid); + return !skb_queue_empty(&tid->i_q); } =20 static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) @@ -185,6 +241,12 @@ static struct sk_buff *ath_tid_dequeue(struct ath_at= x_tid *tid) skb =3D __skb_dequeue(&tid->retry_q); if (!skb) skb =3D __skb_dequeue(&tid->buf_q); + if (!skb) + skb =3D __skb_dequeue(&tid->i_q); + if (!skb) { + ath_swq_pull(tid); + skb =3D __skb_dequeue(&tid->i_q); + } =20 return skb; } @@ -870,6 +932,10 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct= ath_txq *txq, *q =3D &tid->retry_q; if (skb_queue_empty(*q)) *q =3D &tid->buf_q; + if (skb_queue_empty(*q)) + *q =3D &tid->i_q; + if (skb_queue_empty(*q)) + ath_swq_pull(tid); =20 skb =3D skb_peek(*q); if (!skb) @@ -1482,7 +1548,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct = ieee80211_sta *sta, ath_dbg(common, XMIT, "%s called\n", __func__); =20 an =3D (struct ath_node *)sta->drv_priv; - txtid =3D ATH_AN_2_TID(an, tid); + txtid =3D ath_an_2_tid(an, tid); txq =3D txtid->txq; =20 ath_txq_lock(sc, txq); @@ -1517,7 +1583,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct = ieee80211_sta *sta, u16 tid) { struct ath_common *common =3D ath9k_hw_common(sc->sc_ah); struct ath_node *an =3D (struct ath_node *)sta->drv_priv; - struct ath_atx_tid *txtid =3D ATH_AN_2_TID(an, tid); + struct ath_atx_tid *txtid =3D ath_an_2_tid(an, tid); struct ath_txq *txq =3D txtid->txq; =20 ath_dbg(common, XMIT, "%s called\n", __func__); @@ -1533,6 +1599,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, s= truct ath_softc *sc, struct ath_node *an) { struct ath_common *common =3D ath9k_hw_common(sc->sc_ah); + struct ieee80211_txq *swq; struct ath_atx_tid *tid; struct ath_txq *txq; bool buffered; @@ -1540,9 +1607,11 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, = struct ath_softc *sc, =20 ath_dbg(common, XMIT, "%s called\n", __func__); =20 - for (tidno =3D 0, tid =3D &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + for (tidno =3D 0; + tidno < IEEE80211_NUM_TIDS; tidno++) { =20 + swq =3D an->sta->txq[tidno]; + tid =3D (struct ath_atx_tid *) swq->drv_priv; txq =3D tid->txq; =20 ath_txq_lock(sc, txq); @@ -1565,15 +1634,18 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta,= struct ath_softc *sc, void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) { struct ath_common *common =3D ath9k_hw_common(sc->sc_ah); + struct ieee80211_txq *swq; struct ath_atx_tid *tid; struct ath_txq *txq; int tidno; =20 ath_dbg(common, XMIT, "%s called\n", __func__); =20 - for (tidno =3D 0, tid =3D &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + for (tidno =3D 0; + tidno < IEEE80211_NUM_TIDS; tidno++) { =20 + swq =3D an->sta->txq[tidno]; + tid =3D (struct ath_atx_tid *) swq->drv_priv; txq =3D tid->txq; =20 ath_txq_lock(sc, txq); @@ -1599,7 +1671,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struc= t ieee80211_sta *sta, ath_dbg(common, XMIT, "%s called\n", __func__); =20 an =3D (struct ath_node *)sta->drv_priv; - tid =3D ATH_AN_2_TID(an, tidno); + tid =3D ath_an_2_tid(an, tidno); txq =3D tid->txq; =20 ath_txq_lock(sc, txq); @@ -1637,7 +1709,7 @@ void ath9k_release_buffered_frames(struct ieee80211= _hw *hw, if (!(tids & 1)) continue; =20 - tid =3D ATH_AN_2_TID(an, i); + tid =3D ath_an_2_tid(an, i); =20 ath_txq_lock(sc, tid->txq); while (nframes > 0) { @@ -2853,12 +2925,18 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) =20 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) { + struct ieee80211_txq *swq; + struct ieee80211_sta *sta =3D an->sta; + struct ieee80211_vif *vif =3D an->vif; struct ath_atx_tid *tid; int tidno, acno; =20 - for (tidno =3D 0, tid =3D &an->tid[tidno]; + for (tidno =3D 0; tidno < IEEE80211_NUM_TIDS; - tidno++, tid++) { + tidno++) { + swq =3D sta ? sta->txq[tidno] : vif->txq; + tid =3D (struct ath_atx_tid *) swq->drv_priv; + tid->swq =3D swq; tid->an =3D an; tid->tidno =3D tidno; tid->seq_start =3D tid->seq_next =3D 0; @@ -2866,23 +2944,33 @@ void ath_tx_node_init(struct ath_softc *sc, struc= t ath_node *an) tid->baw_head =3D tid->baw_tail =3D 0; tid->active =3D false; tid->clear_ps_filter =3D true; + tid->swq_nonempty =3D false; + __skb_queue_head_init(&tid->i_q); __skb_queue_head_init(&tid->buf_q); __skb_queue_head_init(&tid->retry_q); INIT_LIST_HEAD(&tid->list); acno =3D TID_TO_WME_AC(tidno); tid->txq =3D sc->tx.txq_map[acno]; + + if (!sta) + break; /* just one multicast ath_atx_tid */ } } =20 void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) { + struct ieee80211_txq *swq; + struct ieee80211_sta *sta =3D an->sta; + struct ieee80211_vif *vif =3D an->vif; struct ath_atx_tid *tid; struct ath_txq *txq; int tidno; =20 - for (tidno =3D 0, tid =3D &an->tid[tidno]; - tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { + for (tidno =3D 0; + tidno < IEEE80211_NUM_TIDS; tidno++) { =20 + swq =3D sta ? sta->txq[tidno] : vif->txq; + tid =3D (struct ath_atx_tid *) swq->drv_priv; txq =3D tid->txq; =20 ath_txq_lock(sc, txq); @@ -2894,6 +2982,9 @@ void ath_tx_node_cleanup(struct ath_softc *sc, stru= ct ath_node *an) tid->active =3D false; =20 ath_txq_unlock(sc, txq); + + if (!sta) + break; /* just one multicast ath_atx_tid */ } } =20 --=20 2.8.3