summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lin <dlin@marvell.com>2015-04-22 16:19:26 +0800
committerDavid Lin <dlin@marvell.com>2015-04-22 16:19:26 +0800
commit85cdc98457c31d27a62f3ded31f508a75a95c810 (patch)
tree371e3cde0505686f11c9254c9188e78235691704
parent07df0cf2f71dec9c8b51d4707492540773b9944d (diff)
Report transmit frame rate information.
Signed-off-by: David Lin <dlin@marvell.com>
-rw-r--r--mwl_dev.h28
-rw-r--r--mwl_tx.c57
-rw-r--r--mwl_tx.h4
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_ */