diff options
Diffstat (limited to 'package/mac80211/patches/210-mrr.patch')
-rw-r--r-- | package/mac80211/patches/210-mrr.patch | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/package/mac80211/patches/210-mrr.patch b/package/mac80211/patches/210-mrr.patch new file mode 100644 index 0000000000..3894788245 --- /dev/null +++ b/package/mac80211/patches/210-mrr.patch @@ -0,0 +1,183 @@ +This patch adjusts the rate control API to allow multi-rate retry +if supported by the driver. The ieee80211_hw struct specifies how +many alternate rate selections the driver supports. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -292,6 +292,20 @@ + #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ + (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) + ++/* maximum number of alternate rate retry stages */ ++#define IEEE80211_TX_MAX_ALTRATE 3 ++ ++/** ++ * struct ieee80211_tx_altrate - alternate rate selection/status ++ * ++ * @rate_idx: rate index to attempt to send with ++ * @limit: number of retries before fallback ++ */ ++struct ieee80211_tx_altrate { ++ s8 rate_idx; ++ u8 limit; ++}; ++ + /** + * struct ieee80211_tx_info - skb transmit information + * +@@ -335,12 +349,14 @@ + struct ieee80211_key_conf *hw_key; + struct ieee80211_sta *sta; + unsigned long jiffies; +- s8 rts_cts_rate_idx, alt_retry_rate_idx; ++ s8 rts_cts_rate_idx; + u8 retry_limit; ++ struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE]; + } control; + struct { + u64 ampdu_ack_map; + int ack_signal; ++ struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1]; + u8 retry_count; + bool excessive_retries; + u8 ampdu_ack_len; +@@ -828,6 +844,9 @@ + * within &struct ieee80211_vif. + * @sta_data_size: size (in bytes) of the drv_priv data area + * within &struct ieee80211_sta. ++ * ++ * @max_altrates: maximum number of alternate rate retry stages ++ * @max_altrate_tries: maximum number of tries for each stage + */ + struct ieee80211_hw { + struct ieee80211_conf conf; +@@ -844,6 +863,8 @@ + u16 ampdu_queues; + u16 max_listen_interval; + s8 max_signal; ++ u8 max_altrates; ++ u8 max_altrate_tries; + }; + + struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); +@@ -900,11 +921,11 @@ + + static inline struct ieee80211_rate * + ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, +- const struct ieee80211_tx_info *c) ++ const struct ieee80211_tx_info *c, int idx) + { +- if (c->control.alt_retry_rate_idx < 0) ++ if (c->control.retries[idx].rate_idx < 0) + return NULL; +- return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx]; ++ return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx]; + } + + /** +--- a/drivers/net/wireless/b43/xmit.c ++++ b/drivers/net/wireless/b43/xmit.c +@@ -208,7 +208,7 @@ + txrate = ieee80211_get_tx_rate(dev->wl->hw, info); + rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; + rate_ofdm = b43_is_ofdm_rate(rate); +- fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate; ++ fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; + rate_fb = fbrate->hw_value; + rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); + +--- a/drivers/net/wireless/b43legacy/xmit.c ++++ b/drivers/net/wireless/b43legacy/xmit.c +@@ -210,7 +210,7 @@ + + rate = tx_rate->hw_value; + rate_ofdm = b43legacy_is_ofdm_rate(rate); +- rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate; ++ rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate; + rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); + + txhdr->mac_frame_ctl = wlhdr->frame_control; +--- a/drivers/net/wireless/rtl8180_dev.c ++++ b/drivers/net/wireless/rtl8180_dev.c +@@ -292,8 +292,8 @@ + entry->plcp_len = cpu_to_le16(plcp_len); + entry->tx_buf = cpu_to_le32(mapping); + entry->frame_len = cpu_to_le32(skb->len); +- entry->flags2 = info->control.alt_retry_rate_idx >= 0 ? +- ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0; ++ entry->flags2 = info->control.retries[0].rate_idx >= 0 ? ++ ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; + entry->retry_limit = info->control.retry_limit; + entry->flags = cpu_to_le32(tx_flags); + __skb_queue_tail(&ring->queue, skb); +@@ -855,6 +855,7 @@ + priv = dev->priv; + priv->pdev = pdev; + ++ dev->max_altrates = 1; + SET_IEEE80211_DEV(dev, &pdev->dev); + pci_set_drvdata(pdev, dev); + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -454,15 +454,16 @@ + if (unlikely(rsel.probe_idx >= 0)) { + info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; + tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; +- info->control.alt_retry_rate_idx = tx->rate_idx; ++ info->control.retries[0].rate_idx = tx->rate_idx; ++ info->control.retries[0].limit = tx->local->hw.max_altrate_tries; + tx->rate_idx = rsel.probe_idx; +- } else +- info->control.alt_retry_rate_idx = -1; ++ } else if (info->control.retries[0].limit == 0) ++ info->control.retries[0].rate_idx = -1; + + if (unlikely(tx->rate_idx < 0)) + return TX_DROP; + } else +- info->control.alt_retry_rate_idx = -1; ++ info->control.retries[0].rate_idx = -1; + + if (tx->sdata->bss_conf.use_cts_prot && + (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { +@@ -521,7 +522,7 @@ + * frames. + * TODO: The last fragment could still use multiple retry + * rates. */ +- info->control.alt_retry_rate_idx = -1; ++ info->control.retries[0].rate_idx = -1; + } + + /* Use CTS protection for unicast frames sent using extended rates if +@@ -551,7 +552,7 @@ + int idx; + + /* Do not use multiple retry rates when using RTS/CTS */ +- info->control.alt_retry_rate_idx = -1; ++ info->control.retries[0].rate_idx = -1; + + /* Use min(data rate, max base rate) as CTS/RTS rate */ + rate = &sband->bitrates[tx->rate_idx]; +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -4588,6 +4588,7 @@ + BIT(NL80211_IFTYPE_ADHOC); + + hw->queues = b43_modparam_qos ? 4 : 1; ++ hw->max_altrates = 1; + SET_IEEE80211_DEV(hw, dev->dev); + if (is_valid_ether_addr(sprom->et1mac)) + SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); +--- a/drivers/net/wireless/b43legacy/main.c ++++ b/drivers/net/wireless/b43legacy/main.c +@@ -3710,6 +3710,7 @@ + BIT(NL80211_IFTYPE_WDS) | + BIT(NL80211_IFTYPE_ADHOC); + hw->queues = 1; /* FIXME: hardware has more queues */ ++ hw->max_altrates = 1; + SET_IEEE80211_DEV(hw, dev->dev); + if (is_valid_ether_addr(sprom->et1mac)) + SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |