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 6BCE43B2B6 for ; Fri, 3 Jun 2016 12:52:33 -0400 (EDT) X-Virus-Scanned: amavisd-new at mail2.tohojo.dk DKIM-Filter: OpenDKIM Filter v2.10.3 mail2.tohojo.dk 6B00A3F459 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=toke.dk; s=201310; t=1464972748; bh=8Tq0zyWYm2vhsTDATR7F973tocjUjK2T7x22Z+H8OBw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qfrn4Rg3qd/4MqwYM7Ah7feNQSozRDtK8fWxAM4erqzwBoQrFHp+5t7K/ZoPX3DAi V9vRbQU2MRNCwF8/YdgeUA/G1DUgSqjH+cmSBi0yDLKg5zKqWfp4ZMmaBKLRC3X2oo bY+P5hh44/20wj6sQqspFH8hpcv0NjioE3EG0egE= Received: by alrua-kau.kau.toke.dk (Postfix, from userid 1000) id 4E13FC40168; Fri, 3 Jun 2016 18:52:25 +0200 (CEST) From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= To: linux-wireless@vger.kernel.org, make-wifi-fast@lists.bufferbloat.net, ath9k-devel@lists.ath9k.org Date: Fri, 3 Jun 2016 18:51:42 +0200 Message-Id: <20160603165144.17356-4-toke@toke.dk> In-Reply-To: <20160603165144.17356-1-toke@toke.dk> References: <20160603165144.17356-1-toke@toke.dk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: [Make-wifi-fast] [RFC/RFT 3/5] ath9k: Add airstame stats to per-station debugfs 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, 03 Jun 2016 16:52:33 -0000 Uses the ts->duration + retry-chain information to account for time spent transmitting to a station. Calculates the RX airtime from the rate and packet length. Hopefully these figures are not too inaccurate. Signed-off-by: Toke H=C3=B8iland-J=C3=B8rgensen --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 + drivers/net/wireless/ath/ath9k/debug.h | 21 +++++ drivers/net/wireless/ath/ath9k/debug_sta.c | 125 +++++++++++++++++++++++= ++++++ drivers/net/wireless/ath/ath9k/recv.c | 1 + drivers/net/wireless/ath/ath9k/xmit.c | 6 +- 5 files changed, 154 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireles= s/ath/ath9k/ath9k.h index caeae10..3fbb0ad 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -264,6 +264,7 @@ struct ath_node { =20 #ifdef CONFIG_ATH9K_STATION_STATISTICS struct ath_rx_rate_stats rx_rate_stats; + struct ath_airtime_stats airtime_stats; #endif u8 key_idx[4]; =20 @@ -573,6 +574,8 @@ void ath_txq_schedule_all(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); +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble); void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int t= xop); void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireles= s/ath/ath9k/debug.h index cd68c5f..4f78495 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -223,6 +223,11 @@ struct ath_rx_rate_stats { } cck_stats[4]; }; =20 +struct ath_airtime_stats { + u32 rx_airtime; + u32 tx_airtime; +}; + #define ANT_MAIN 0 #define ANT_ALT 1 =20 @@ -316,12 +321,28 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sy= nc_cause) void ath_debug_rate_stats(struct ath_softc *sc, struct ath_rx_status *rs, struct sk_buff *skb); +void ath_debug_tx_airtime(struct ath_softc *sc, + struct ath_buf *bf, + struct ath_tx_status *ts); +void ath_debug_rx_airtime(struct ath_softc *sc, + struct ath_rx_status *rs, + struct sk_buff *skb); #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_tx_airtime(struct ath_softc *sc, + struct ath_buf *bf, + struct ath_tx_status *ts) +{ +} +static inline void ath_debug_rx_airtime(struct ath_softc *sc, + struct ath_rx_status *rs, + struct sk_buff *skb) +{ +} #endif /* CONFIG_ATH9K_STATION_STATISTICS */ =20 #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wir= eless/ath/ath9k/debug_sta.c index 0e7f6b5..56aba3a 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c @@ -245,6 +245,130 @@ static const struct file_operations fops_node_recv = =3D { .llseek =3D default_llseek, }; =20 +void ath_debug_tx_airtime(struct ath_softc *sc, + struct ath_buf *bf, + struct ath_tx_status *ts) +{ + struct ath_node *an; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct ath_airtime_stats *astats; + struct ieee80211_hw *hw =3D sc->hw; + struct ieee80211_tx_rate rates[4]; + struct ieee80211_sta *sta; + int i; + + skb =3D bf->bf_mpdu; + if(!skb) + return; + + hdr =3D (struct ieee80211_hdr *)skb->data; + memcpy(rates, bf->rates, sizeof(rates)); + + rcu_read_lock(); + + sta =3D ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); + if(!sta) + goto exit; + + + an =3D (struct ath_node *) sta->drv_priv; + astats =3D &an->airtime_stats; + + astats->tx_airtime +=3D ts->duration * (ts->ts_longretry + 1); + + for(i=3D0; i < ts->ts_rateindex; i++) + astats->tx_airtime +=3D ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, = i) * rates[i].count; + + + +exit: + rcu_read_unlock(); +} + +void ath_debug_rx_airtime(struct ath_softc *sc, + struct ath_rx_status *rs, + struct sk_buff *skb) +{ + struct ath_airtime_stats *astats; + struct ath_node *an; + struct ieee80211_hdr *hdr =3D (struct ieee80211_hdr *) skb->data; + struct ath_hw *ah =3D sc->sc_ah; + struct ath_common *common =3D ath9k_hw_common(ah); + struct ieee80211_sta *sta; + struct ieee80211_rx_status *rxs; + const struct ieee80211_rate *rate; + bool is_sgi, is_40, is_sp; + int phy; + + if (!ieee80211_is_data(hdr->frame_control)) + return; + + rcu_read_lock(); + + sta =3D ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); + if (!sta) + goto exit; + an =3D (struct ath_node *) sta->drv_priv; + rxs =3D IEEE80211_SKB_RXCB(skb); + astats =3D &an->airtime_stats; + + is_sgi =3D !!(rxs->flag & RX_FLAG_SHORT_GI); + is_40 =3D !!(rxs->flag & RX_FLAG_40MHZ); + is_sp =3D !!(rxs->flag & RX_FLAG_SHORTPRE); + + if (!!(rxs->flag & RX_FLAG_HT)) { + /* MCS rates */ + + astats->rx_airtime +=3D ath_pkt_duration(sc, rxs->rate_idx, rs->rs_dat= alen, + is_40, is_sgi, is_sp); + goto exit; + } + + phy =3D IS_CCK_RATE(rs->rs_rate) ? WLAN_RC_PHY_CCK : WLAN_RC_PHY_OFDM; + rate =3D &common->sbands[rxs->band].bitrates[rxs->rate_idx]; + astats->rx_airtime +=3D ath9k_hw_computetxtime(ah, phy, rate->bitrate *= 100, + rs->rs_datalen, rxs->rate_idx, is_sp); + + +exit: + rcu_read_unlock(); +} + + +static ssize_t read_airtime(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_node *an =3D file->private_data; + struct ath_airtime_stats *astats; + u32 len =3D 0, size =3D 128; + char *buf; + size_t retval; + + buf =3D kzalloc(size, GFP_KERNEL); + if (buf =3D=3D NULL) + return -ENOMEM; + + astats =3D &an->airtime_stats; + + len +=3D scnprintf(buf + len, size - len, "RX: %u us\n", astats->rx_air= time); + len +=3D scnprintf(buf + len, size - len, "TX: %u us\n", astats->tx_air= time); + + retval =3D simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + + return retval; +} + + +static const struct file_operations fops_airtime =3D { + .read =3D read_airtime, + .open =3D simple_open, + .owner =3D THIS_MODULE, + .llseek =3D default_llseek, +}; + + void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -254,4 +378,5 @@ void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, =20 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/recv.c b/drivers/net/wireless= /ath/ath9k/recv.c index 32160fc..7eb8980 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -1137,6 +1137,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush,= bool hp) ath9k_antenna_check(sc, &rs); ath9k_apply_ampdu_details(sc, &rs, rxs); ath_debug_rate_stats(sc, &rs, skb); + ath_debug_rx_airtime(sc, &rs, skb); =20 hdr =3D (struct ieee80211_hdr *)skb->data; if (ieee80211_is_ack(hdr->frame_control)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless= /ath/ath9k/xmit.c index cdc8684..07d32e7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -739,6 +739,8 @@ static void ath_tx_process_buffer(struct ath_softc *s= c, struct ath_txq *txq, =20 ts->duration =3D ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, ts->ts_rateindex); + ath_debug_tx_airtime(sc, bf, ts); + if (!bf_isampdu(bf)) { if (!flush) { info =3D IEEE80211_SKB_CB(bf->bf_mpdu); @@ -1090,8 +1093,8 @@ ath_tx_form_aggr(struct ath_softc *sc, struct ath_t= xq *txq, * width - 0 for 20 MHz, 1 for 40 MHz * half_gi - to use 4us v/s 3.6 us for symbol time */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, - int width, int half_gi, bool shortPreamble) +u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, + int width, int half_gi, bool shortPreamble) { u32 nbits, nsymbits, duration, nsymbols; int streams; --=20 2.7.4