summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ralink/rt2x00/rt2x00dev.c')
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00dev.c240
1 files changed, 159 insertions, 81 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
index dd6678109b7e..357c0941aaad 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -313,73 +313,14 @@ static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry)
return ret;
}
-void rt2x00lib_txdone(struct queue_entry *entry,
- struct txdone_entry_desc *txdesc)
+static void rt2x00lib_fill_tx_status(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_tx_info *tx_info,
+ struct skb_frame_desc *skbdesc,
+ struct txdone_entry_desc *txdesc,
+ bool success)
{
- struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- unsigned int header_length, i;
u8 rate_idx, rate_flags, retry_rates;
- u8 skbdesc_flags = skbdesc->flags;
- bool success;
-
- /*
- * Unmap the skb.
- */
- rt2x00queue_unmap_skb(entry);
-
- /*
- * Remove the extra tx headroom from the skb.
- */
- skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
-
- /*
- * Signal that the TX descriptor is no longer in the skb.
- */
- skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
-
- /*
- * Determine the length of 802.11 header.
- */
- header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
-
- /*
- * Remove L2 padding which was added during
- */
- if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
- rt2x00queue_remove_l2pad(entry->skb, header_length);
-
- /*
- * If the IV/EIV data was stripped from the frame before it was
- * passed to the hardware, we should now reinsert it again because
- * mac80211 will expect the same data to be present it the
- * frame as it was passed to us.
- */
- if (rt2x00_has_cap_hw_crypto(rt2x00dev))
- rt2x00crypto_tx_insert_iv(entry->skb, header_length);
-
- /*
- * Send frame to debugfs immediately, after this call is completed
- * we are going to overwrite the skb->cb array.
- */
- rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
-
- /*
- * Determine if the frame has been successfully transmitted and
- * remove BARs from our check list while checking for their
- * TX status.
- */
- success =
- rt2x00lib_txdone_bar_status(entry) ||
- test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
- test_bit(TXDONE_UNKNOWN, &txdesc->flags);
-
- /*
- * Update TX statistics.
- */
- rt2x00dev->link.qual.tx_success += success;
- rt2x00dev->link.qual.tx_failed += !success;
+ int i;
rate_idx = skbdesc->tx_rate_idx;
rate_flags = skbdesc->tx_rate_flags;
@@ -416,6 +357,9 @@ void rt2x00lib_txdone(struct queue_entry *entry,
if (i < (IEEE80211_TX_MAX_RATES - 1))
tx_info->status.rates[i].idx = -1; /* terminate */
+ if (test_bit(TXDONE_NO_ACK_REQ, &txdesc->flags))
+ tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
+
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (success)
tx_info->flags |= IEEE80211_TX_STAT_ACK;
@@ -434,7 +378,8 @@ void rt2x00lib_txdone(struct queue_entry *entry,
*/
if (test_bit(TXDONE_AMPDU, &txdesc->flags) ||
tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU |
+ IEEE80211_TX_CTL_AMPDU;
tx_info->status.ampdu_len = 1;
tx_info->status.ampdu_ack_len = success ? 1 : 0;
@@ -448,21 +393,11 @@ void rt2x00lib_txdone(struct queue_entry *entry,
else
rt2x00dev->low_level_stats.dot11RTSFailureCount++;
}
+}
- /*
- * Only send the status report to mac80211 when it's a frame
- * that originated in mac80211. If this was a extra frame coming
- * through a mac80211 library call (RTS/CTS) then we should not
- * send the status report back.
- */
- if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
- if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TASKLET_CONTEXT))
- ieee80211_tx_status(rt2x00dev->hw, entry->skb);
- else
- ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
- } else
- dev_kfree_skb_any(entry->skb);
-
+static void rt2x00lib_clear_entry(struct rt2x00_dev *rt2x00dev,
+ struct queue_entry *entry)
+{
/*
* Make this entry available for reuse.
*/
@@ -485,6 +420,143 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00queue_unpause_queue(entry->queue);
spin_unlock_bh(&entry->queue->tx_lock);
}
+
+void rt2x00lib_txdone_nomatch(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ struct ieee80211_tx_info txinfo = {};
+ bool success;
+
+ /*
+ * Unmap the skb.
+ */
+ rt2x00queue_unmap_skb(entry);
+
+ /*
+ * Signal that the TX descriptor is no longer in the skb.
+ */
+ skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
+ /*
+ * Send frame to debugfs immediately, after this call is completed
+ * we are going to overwrite the skb->cb array.
+ */
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
+
+ /*
+ * Determine if the frame has been successfully transmitted and
+ * remove BARs from our check list while checking for their
+ * TX status.
+ */
+ success =
+ rt2x00lib_txdone_bar_status(entry) ||
+ test_bit(TXDONE_SUCCESS, &txdesc->flags);
+
+ if (!test_bit(TXDONE_UNKNOWN, &txdesc->flags)) {
+ /*
+ * Update TX statistics.
+ */
+ rt2x00dev->link.qual.tx_success += success;
+ rt2x00dev->link.qual.tx_failed += !success;
+
+ rt2x00lib_fill_tx_status(rt2x00dev, &txinfo, skbdesc, txdesc,
+ success);
+ ieee80211_tx_status_noskb(rt2x00dev->hw, skbdesc->sta, &txinfo);
+ }
+
+ dev_kfree_skb_any(entry->skb);
+ rt2x00lib_clear_entry(rt2x00dev, entry);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_txdone_nomatch);
+
+void rt2x00lib_txdone(struct queue_entry *entry,
+ struct txdone_entry_desc *txdesc)
+{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+ u8 skbdesc_flags = skbdesc->flags;
+ unsigned int header_length;
+ bool success;
+
+ /*
+ * Unmap the skb.
+ */
+ rt2x00queue_unmap_skb(entry);
+
+ /*
+ * Remove the extra tx headroom from the skb.
+ */
+ skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);
+
+ /*
+ * Signal that the TX descriptor is no longer in the skb.
+ */
+ skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
+ /*
+ * Determine the length of 802.11 header.
+ */
+ header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+ /*
+ * Remove L2 padding which was added during
+ */
+ if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_L2PAD))
+ rt2x00queue_remove_l2pad(entry->skb, header_length);
+
+ /*
+ * If the IV/EIV data was stripped from the frame before it was
+ * passed to the hardware, we should now reinsert it again because
+ * mac80211 will expect the same data to be present it the
+ * frame as it was passed to us.
+ */
+ if (rt2x00_has_cap_hw_crypto(rt2x00dev))
+ rt2x00crypto_tx_insert_iv(entry->skb, header_length);
+
+ /*
+ * Send frame to debugfs immediately, after this call is completed
+ * we are going to overwrite the skb->cb array.
+ */
+ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry);
+
+ /*
+ * Determine if the frame has been successfully transmitted and
+ * remove BARs from our check list while checking for their
+ * TX status.
+ */
+ success =
+ rt2x00lib_txdone_bar_status(entry) ||
+ test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
+ test_bit(TXDONE_UNKNOWN, &txdesc->flags);
+
+ /*
+ * Update TX statistics.
+ */
+ rt2x00dev->link.qual.tx_success += success;
+ rt2x00dev->link.qual.tx_failed += !success;
+
+ rt2x00lib_fill_tx_status(rt2x00dev, tx_info, skbdesc, txdesc, success);
+
+ /*
+ * Only send the status report to mac80211 when it's a frame
+ * that originated in mac80211. If this was a extra frame coming
+ * through a mac80211 library call (RTS/CTS) then we should not
+ * send the status report back.
+ */
+ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
+ if (rt2x00_has_cap_flag(rt2x00dev, REQUIRE_TASKLET_CONTEXT))
+ ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+ else
+ ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
+ } else {
+ dev_kfree_skb_any(entry->skb);
+ }
+
+ rt2x00lib_clear_entry(rt2x00dev, entry);
+}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)
@@ -753,7 +825,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc);
if (rxdesc.rate_mode == RATE_MODE_HT_MIX ||
rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD)
- rxdesc.flags |= RX_FLAG_HT;
+ rxdesc.encoding = RX_ENC_HT;
/*
* Check if this is a beacon, and more frames have been
@@ -793,6 +865,9 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
rx_status->rate_idx = rate_idx;
rx_status->signal = rxdesc.rssi;
rx_status->flag = rxdesc.flags;
+ rx_status->enc_flags = rxdesc.enc_flags;
+ rx_status->encoding = rxdesc.encoding;
+ rx_status->bw = rxdesc.bw;
rx_status->antenna = rt2x00dev->link.ant.active.rx;
ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
@@ -1384,6 +1459,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+ wiphy_ext_feature_set(rt2x00dev->hw->wiphy,
+ NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
/*
* Initialize ieee80211 structure.
*/