diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 14c361ae87be..14ff706419e4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2499,7 +2499,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_AMPDU_AGGREGATION; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, @@ -2751,6 +2752,36 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw) return tsf; } +static int rt2800_ampdu_action(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum ieee80211_ampdu_mlme_action action, + struct ieee80211_sta *sta, + u16 tid, u16 *ssn) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + int ret = 0; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + case IEEE80211_AMPDU_RX_STOP: + /* we don't support RX aggregation yet */ + ret = -ENOTSUPP; + break; + case IEEE80211_AMPDU_TX_START: + ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_STOP: + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + break; + case IEEE80211_AMPDU_TX_OPERATIONAL: + break; + default: + WARNING(rt2x00dev, "Unknown AMPDU action\n"); + } + + return ret; +} + const struct ieee80211_ops rt2800_mac80211_ops = { .tx = rt2x00mac_tx, .start = rt2x00mac_start, @@ -2768,6 +2799,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = { .conf_tx = rt2800_conf_tx, .get_tsf = rt2800_get_tsf, .rfkill_poll = rt2x00mac_rfkill_poll, + .ampdu_action = rt2800_ampdu_action, }; EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 339cc84bf4fb..a914855099b7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -286,6 +286,21 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->low_level_stats.dot11ACKFailureCount++; } + /* + * Every single frame has it's own tx status, hence report + * every frame as ampdu of size 1. + * + * TODO: if we can find out how many frames were aggregated + * by the hw we could provide the real ampdu_len to mac80211 + * which would allow the rc algorithm to better decide on + * which rates are suitable. + */ + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { + tx_info->flags |= IEEE80211_TX_STAT_AMPDU; + tx_info->status.ampdu_len = 1; + tx_info->status.ampdu_ack_len = success ? 1 : 0; + } + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { if (success) rt2x00dev->low_level_stats.dot11RTSSuccessCount++;