Currently we always wait for an ACK even if IEEE80211_TX_CTL_NO_ACK is set, and retry if no ACK is received. This means that if a multicast packet is transmitted, it will always be retransmitted until the excessive retries limit is reached, which AFAIK is against the IEEE 802.11 specification. Fix this by setting the retry limit to 0 if IEEE80211_TX_CTL_NO_ACK is set. This is also required for proper implementation of the proposed TX Flags Radiotap field, specifically the No-ACK flag, which allows userspace to transmit arbitrary packets without retrying or waiting for an ACK. Signed-off-by: Gábor Stefanik <netrolller.3d@xxxxxxxxx> --- Patch is also available as an attachment if Gmail linewraps it. rtl8187_dev.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index fd81884..ec80e0b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -258,7 +258,10 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->flags = cpu_to_le32(flags); hdr->len = 0; hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + if (!info->flags & IEEE80211_TX_CTL_NO_ACK)) + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + else + hdr->retry = 0; buf = hdr; ep = 2; @@ -276,7 +279,10 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) memset(hdr, 0, sizeof(*hdr)); hdr->flags = cpu_to_le32(flags); hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + if (!info->flags & IEEE80211_TX_CTL_NO_ACK)) + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + else + hdr->retry = 0; hdr->tx_duration = ieee80211_generic_frame_duration(dev, priv->vif, skb->len, txrate);
rtl8187_dev.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index fd81884..ec80e0b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -258,7 +258,10 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->flags = cpu_to_le32(flags); hdr->len = 0; hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + if (!info->flags & IEEE80211_TX_CTL_NO_ACK)) + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + else + hdr->retry = 0; buf = hdr; ep = 2; @@ -276,7 +279,10 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) memset(hdr, 0, sizeof(*hdr)); hdr->flags = cpu_to_le32(flags); hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + if (!info->flags & IEEE80211_TX_CTL_NO_ACK)) + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); + else + hdr->retry = 0; hdr->tx_duration = ieee80211_generic_frame_duration(dev, priv->vif, skb->len, txrate);