Commit 1df90809 authored by Helmut Schaa's avatar Helmut Schaa Committed by John W. Linville

rt2x00: Implement tx mpdu aggregation

In order to implement tx mpdu aggregation we only have to implement
the ampdu_action callback such that mac80211 allows negotiation of
blockack sessions.

The hardware will handle everything on its own as long as the ampdu
flag in the TXWI struct is set up correctly and we translate the tx
status correctly.

For now, refuse requests to start rx aggregation.
Signed-off-by: default avatarHelmut Schaa <helmut.schaa@googlemail.com>
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f35376a4
...@@ -2499,7 +2499,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) ...@@ -2499,7 +2499,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS | 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_DEV(rt2x00dev->hw, rt2x00dev->dev);
SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
...@@ -2751,6 +2752,36 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw) ...@@ -2751,6 +2752,36 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
return tsf; 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 = { const struct ieee80211_ops rt2800_mac80211_ops = {
.tx = rt2x00mac_tx, .tx = rt2x00mac_tx,
.start = rt2x00mac_start, .start = rt2x00mac_start,
...@@ -2768,6 +2799,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = { ...@@ -2768,6 +2799,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = {
.conf_tx = rt2800_conf_tx, .conf_tx = rt2800_conf_tx,
.get_tsf = rt2800_get_tsf, .get_tsf = rt2800_get_tsf,
.rfkill_poll = rt2x00mac_rfkill_poll, .rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
}; };
EXPORT_SYMBOL_GPL(rt2800_mac80211_ops); EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);
......
...@@ -286,6 +286,21 @@ void rt2x00lib_txdone(struct queue_entry *entry, ...@@ -286,6 +286,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->low_level_stats.dot11ACKFailureCount++; 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 (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
if (success) if (success)
rt2x00dev->low_level_stats.dot11RTSSuccessCount++; rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment