mac80211: add multi-rate retry support
authorFelix Fietkau <nbd@openwrt.org>
Sun, 5 Oct 2008 16:04:24 +0000 (18:04 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 6 Oct 2008 22:14:57 +0000 (18:14 -0400)
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>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/b43legacy/xmit.c
drivers/net/wireless/rtl8180_dev.c
include/net/mac80211.h
net/mac80211/tx.c

index 3bf74e2..14c44df 100644 (file)
@@ -4588,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev)
                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);
index e0749c0..2fabcf8 100644 (file)
@@ -208,7 +208,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
        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);
 
index 9fb1421..c66d575 100644 (file)
@@ -3710,6 +3710,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
                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);
index a894169..65e8337 100644 (file)
@@ -210,7 +210,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
 
        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;
index abcd641..df7e78e 100644 (file)
@@ -292,8 +292,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
        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 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
        priv = dev->priv;
        priv->pdev = pdev;
 
+       dev->max_altrates = 1;
        SET_IEEE80211_DEV(dev, &pdev->dev);
        pci_set_drvdata(pdev, dev);
 
index feb3be8..5617a16 100644 (file)
@@ -292,6 +292,20 @@ enum mac80211_tx_control_flags {
 #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_tx_info {
                        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 @@ enum ieee80211_hw_flags {
  *     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 @@ struct ieee80211_hw {
        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 @@ ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw,
 
 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];
 }
 
 /**
index d7153bb..1460537 100644 (file)
@@ -454,15 +454,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
                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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
                 * 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 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
                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];