From 85cdc98457c31d27a62f3ded31f508a75a95c810 Mon Sep 17 00:00:00 2001 From: David Lin Date: Wed, 22 Apr 2015 16:19:26 +0800 Subject: Report transmit frame rate information. Signed-off-by: David Lin --- mwl_dev.h | 28 ++++++++++++---------------- mwl_tx.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++---------- mwl_tx.h | 4 ++-- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/mwl_dev.h b/mwl_dev.h index 49473fa..c6867f5 100644 --- a/mwl_dev.h +++ b/mwl_dev.h @@ -209,22 +209,18 @@ struct mwl_hw_data { }; struct mwl_rate_info { - u32 format:1; /* 0 = Legacy format, 1 = Hi-throughput format */ - u32 short_gi:1; /* 0 = Use standard guard interval,1 = Use short guard interval */ - u32 bandwidth:1; /* 0 = Use 20 MHz channel,1 = Use 40 MHz channel */ - u32 rate_id_mcs:7; /* = RateID[3:0]; Legacy format,= MCS[5:0]; HT format */ - u32 adv_coding:1; /* AdvCoding 0 = No AdvCoding,1 = LDPC,2 = RS,3 = Reserved */ - u32 ant_select:2; /* Bitmap to select one of the transmit antennae */ - u32 act_sub_chan:2; /* Active subchannel for 40 MHz mode 00:lower, 01= upper, 10= both on lower and upper */ - u32 preamble_type:1; /* Preambletype 0= Long, 1= Short; */ - u32 pid:4; /* Power ID */ - u32 ant2:1; /* bit 2 of antenna selection field */ - u32 ant3:1; - u32 bf:1; /* 0: beam forming off; 1: beam forming on */ - u32 gf:1; /* 0: green field off; 1, green field on */ - u32 count:4; - u32 rsvd2:3; - u32 drop:1; + u32 format:2; /* 0 = Legacy, 1 = 11n, 2 = 11ac */ + u32 stbc:1; + u32 rsvd1:1; + u32 bandwidth:2; /* 0 = 20 MHz, 1 = 40 MHz, 2 = 80 MHz */ + u32 short_gi:1; /* 0 = standard guard interval, 1 = short */ + u32 rsvd2:1; + u32 rate_id_mcs:7; + u32 preamble_type:1; /* Preambletype 0 = Long, 1 = Short; */ + u32 power_id:6; + u32 adv_coding:1; /* ldpc */ + u32 bf:1; + u32 ant_select:8; /* Bitmap to select one of the transmit antenna */ } __packed; struct mwl_tx_desc { diff --git a/mwl_tx.c b/mwl_tx.c index 049b8e2..157bc01 100644 --- a/mwl_tx.c +++ b/mwl_tx.c @@ -50,6 +50,19 @@ #define EXT_IV 0x20 #define INCREASE_IV(iv16, iv32) {(iv16)++; if ((iv16) == 0) (iv32)++; } +/* Transmit rate information constants +*/ +#define TX_RATE_FORMAT_LEGACY 0 +#define TX_RATE_FORMAT_11N 1 +#define TX_RATE_FORMAT_11AC 2 + +#define TX_RATE_BANDWIDTH_20 0 +#define TX_RATE_BANDWIDTH_40 1 +#define TX_RATE_BANDWIDTH_80 2 + +#define TX_RATE_INFO_STD_GI 0 +#define TX_RATE_INFO_SHORT_GI 1 + /* PRIVATE FUNCTION DECLARATION */ @@ -343,6 +356,7 @@ void mwl_tx_done(unsigned long data) unsigned long flags; int num; struct sk_buff *done_skb; + struct mwl_rate_info rate_info; WLDBG_ENTER(DBG_LEVEL_3); @@ -361,6 +375,7 @@ void mwl_tx_done(unsigned long data) STALE_TXD(num)->psk_buff->len, PCI_DMA_TODEVICE); done_skb = STALE_TXD(num)->psk_buff; + rate_info = STALE_TXD(num)->rate_info; STALE_TXD(num)->pkt_len = 0; STALE_TXD(num)->psk_buff = NULL; STALE_TXD(num)->status = ENDIAN_SWAP32(EAGLE_TXD_STATUS_IDLE); @@ -374,6 +389,10 @@ void mwl_tx_done(unsigned long data) int hdrlen; tr = (struct mwl_dma_data *)done_skb->data; + info = IEEE80211_SKB_CB(done_skb); + ieee80211_tx_info_clear_status(info); + + info->status.rates[0].idx = -1; if (ieee80211_is_data(tr->wh.frame_control) || ieee80211_is_data_qos(tr->wh.frame_control)) { @@ -382,6 +401,34 @@ void mwl_tx_done(unsigned long data) if (skb_queue_len(&priv->delay_freeq) > SYSADPT_DELAY_FREE_Q_LIMIT) dev_kfree_skb_any(skb_dequeue(&priv->delay_freeq)); + + /* Prepare rate information + */ + info->status.rates[0].idx = rate_info.rate_id_mcs; + if (rate_info.format == TX_RATE_FORMAT_LEGACY){ + if (hw->conf.chandef.chan->hw_value > + BAND_24_CHANNEL_NUM) { + info->status.rates[0].idx -= 5; + } + } + if (rate_info.format == TX_RATE_FORMAT_11N) + info->status.rates[0].flags |= + IEEE80211_TX_RC_MCS; + if (rate_info.format == TX_RATE_FORMAT_11AC) + info->status.rates[0].flags |= + IEEE80211_TX_RC_VHT_MCS; + if (rate_info.bandwidth == TX_RATE_BANDWIDTH_40) + info->status.rates[0].flags |= + IEEE80211_TX_RC_40_MHZ_WIDTH; + if (rate_info.bandwidth == TX_RATE_BANDWIDTH_80) + info->status.rates[0].flags |= + IEEE80211_TX_RC_80_MHZ_WIDTH; + if (rate_info.short_gi == TX_RATE_INFO_SHORT_GI) + info->status.rates[0].flags |= + IEEE80211_TX_RC_SHORT_GI; + info->status.rates[0].count = 1; + + info->status.rates[1].idx = -1; } /* Remove H/W dma header @@ -390,16 +437,6 @@ void mwl_tx_done(unsigned long data) memmove(tr->data - hdrlen, &tr->wh, hdrlen); skb_pull(done_skb, sizeof(*tr) - hdrlen); - info = IEEE80211_SKB_CB(done_skb); - - ieee80211_tx_info_clear_status(info); - - /* Rate control is happening in the firmware. - * Ensure no tx rate is being reported. - */ - info->status.rates[0].idx = -1; - info->status.rates[0].count = 1; - info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status(hw, done_skb); diff --git a/mwl_tx.h b/mwl_tx.h index 6b2d4bb..c899215 100644 --- a/mwl_tx.h +++ b/mwl_tx.h @@ -30,8 +30,8 @@ int mwl_tx_init(struct ieee80211_hw *hw); void mwl_tx_deinit(struct ieee80211_hw *hw); void mwl_tx_xmit(struct ieee80211_hw *hw, int index, - struct ieee80211_sta *sta, - struct sk_buff *skb); + struct ieee80211_sta *sta, + struct sk_buff *skb); void mwl_tx_done(unsigned long data); #endif /* _mwl_tx_h_ */ -- cgit v1.2.3