aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2008-10-05 12:04:24 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-06 18:14:57 -0400
commit870abdf67170daa9f1022e55a35c469239fcc74c (patch)
tree5ca00db880d71149eea2cdaeb67ed20f5281071d
parent76708dee382a69b2f9d0e50f413f99fefb2dc509 (diff)
mac80211: add multi-rate retry support
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>
-rw-r--r--drivers/net/wireless/b43/main.c1
-rw-r--r--drivers/net/wireless/b43/xmit.c2
-rw-r--r--drivers/net/wireless/b43legacy/main.c1
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c2
-rw-r--r--drivers/net/wireless/rtl8180_dev.c5
-rw-r--r--include/net/mac80211.h29
-rw-r--r--net/mac80211/tx.c13
7 files changed, 39 insertions, 14 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 3bf74e236ab..14c44df584d 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4588,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev)
4588 BIT(NL80211_IFTYPE_ADHOC); 4588 BIT(NL80211_IFTYPE_ADHOC);
4589 4589
4590 hw->queues = b43_modparam_qos ? 4 : 1; 4590 hw->queues = b43_modparam_qos ? 4 : 1;
4591 hw->max_altrates = 1;
4591 SET_IEEE80211_DEV(hw, dev->dev); 4592 SET_IEEE80211_DEV(hw, dev->dev);
4592 if (is_valid_ether_addr(sprom->et1mac)) 4593 if (is_valid_ether_addr(sprom->et1mac))
4593 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); 4594 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index e0749c0074c..2fabcf8f047 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -208,7 +208,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
208 txrate = ieee80211_get_tx_rate(dev->wl->hw, info); 208 txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
209 rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; 209 rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
210 rate_ofdm = b43_is_ofdm_rate(rate); 210 rate_ofdm = b43_is_ofdm_rate(rate);
211 fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate; 211 fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate;
212 rate_fb = fbrate->hw_value; 212 rate_fb = fbrate->hw_value;
213 rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); 213 rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
214 214
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 9fb1421cbec..c66d57560e7 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3710,6 +3710,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
3710 BIT(NL80211_IFTYPE_WDS) | 3710 BIT(NL80211_IFTYPE_WDS) |
3711 BIT(NL80211_IFTYPE_ADHOC); 3711 BIT(NL80211_IFTYPE_ADHOC);
3712 hw->queues = 1; /* FIXME: hardware has more queues */ 3712 hw->queues = 1; /* FIXME: hardware has more queues */
3713 hw->max_altrates = 1;
3713 SET_IEEE80211_DEV(hw, dev->dev); 3714 SET_IEEE80211_DEV(hw, dev->dev);
3714 if (is_valid_ether_addr(sprom->et1mac)) 3715 if (is_valid_ether_addr(sprom->et1mac))
3715 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); 3716 SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index a894169411c..65e83378160 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -210,7 +210,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
210 210
211 rate = tx_rate->hw_value; 211 rate = tx_rate->hw_value;
212 rate_ofdm = b43legacy_is_ofdm_rate(rate); 212 rate_ofdm = b43legacy_is_ofdm_rate(rate);
213 rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate; 213 rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
214 rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); 214 rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
215 215
216 txhdr->mac_frame_ctl = wlhdr->frame_control; 216 txhdr->mac_frame_ctl = wlhdr->frame_control;
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
index abcd641c54b..df7e78ee8a8 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -292,8 +292,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
292 entry->plcp_len = cpu_to_le16(plcp_len); 292 entry->plcp_len = cpu_to_le16(plcp_len);
293 entry->tx_buf = cpu_to_le32(mapping); 293 entry->tx_buf = cpu_to_le32(mapping);
294 entry->frame_len = cpu_to_le32(skb->len); 294 entry->frame_len = cpu_to_le32(skb->len);
295 entry->flags2 = info->control.alt_retry_rate_idx >= 0 ? 295 entry->flags2 = info->control.retries[0].rate_idx >= 0 ?
296 ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0; 296 ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
297 entry->retry_limit = info->control.retry_limit; 297 entry->retry_limit = info->control.retry_limit;
298 entry->flags = cpu_to_le32(tx_flags); 298 entry->flags = cpu_to_le32(tx_flags);
299 __skb_queue_tail(&ring->queue, skb); 299 __skb_queue_tail(&ring->queue, skb);
@@ -855,6 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
855 priv = dev->priv; 855 priv = dev->priv;
856 priv->pdev = pdev; 856 priv->pdev = pdev;
857 857
858 dev->max_altrates = 1;
858 SET_IEEE80211_DEV(dev, &pdev->dev); 859 SET_IEEE80211_DEV(dev, &pdev->dev);
859 pci_set_drvdata(pdev, dev); 860 pci_set_drvdata(pdev, dev);
860 861
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index feb3be81dfa..5617a1613c9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -292,6 +292,20 @@ enum mac80211_tx_control_flags {
292#define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ 292#define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \
293 (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) 293 (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *))
294 294
295/* maximum number of alternate rate retry stages */
296#define IEEE80211_TX_MAX_ALTRATE 3
297
298/**
299 * struct ieee80211_tx_altrate - alternate rate selection/status
300 *
301 * @rate_idx: rate index to attempt to send with
302 * @limit: number of retries before fallback
303 */
304struct ieee80211_tx_altrate {
305 s8 rate_idx;
306 u8 limit;
307};
308
295/** 309/**
296 * struct ieee80211_tx_info - skb transmit information 310 * struct ieee80211_tx_info - skb transmit information
297 * 311 *
@@ -335,12 +349,14 @@ struct ieee80211_tx_info {
335 struct ieee80211_key_conf *hw_key; 349 struct ieee80211_key_conf *hw_key;
336 struct ieee80211_sta *sta; 350 struct ieee80211_sta *sta;
337 unsigned long jiffies; 351 unsigned long jiffies;
338 s8 rts_cts_rate_idx, alt_retry_rate_idx; 352 s8 rts_cts_rate_idx;
339 u8 retry_limit; 353 u8 retry_limit;
354 struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE];
340 } control; 355 } control;
341 struct { 356 struct {
342 u64 ampdu_ack_map; 357 u64 ampdu_ack_map;
343 int ack_signal; 358 int ack_signal;
359 struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1];
344 u8 retry_count; 360 u8 retry_count;
345 bool excessive_retries; 361 bool excessive_retries;
346 u8 ampdu_ack_len; 362 u8 ampdu_ack_len;
@@ -828,6 +844,9 @@ enum ieee80211_hw_flags {
828 * within &struct ieee80211_vif. 844 * within &struct ieee80211_vif.
829 * @sta_data_size: size (in bytes) of the drv_priv data area 845 * @sta_data_size: size (in bytes) of the drv_priv data area
830 * within &struct ieee80211_sta. 846 * within &struct ieee80211_sta.
847 *
848 * @max_altrates: maximum number of alternate rate retry stages
849 * @max_altrate_tries: maximum number of tries for each stage
831 */ 850 */
832struct ieee80211_hw { 851struct ieee80211_hw {
833 struct ieee80211_conf conf; 852 struct ieee80211_conf conf;
@@ -844,6 +863,8 @@ struct ieee80211_hw {
844 u16 ampdu_queues; 863 u16 ampdu_queues;
845 u16 max_listen_interval; 864 u16 max_listen_interval;
846 s8 max_signal; 865 s8 max_signal;
866 u8 max_altrates;
867 u8 max_altrate_tries;
847}; 868};
848 869
849struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); 870struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy);
@@ -900,11 +921,11 @@ ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw,
900 921
901static inline struct ieee80211_rate * 922static inline struct ieee80211_rate *
902ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, 923ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
903 const struct ieee80211_tx_info *c) 924 const struct ieee80211_tx_info *c, int idx)
904{ 925{
905 if (c->control.alt_retry_rate_idx < 0) 926 if (c->control.retries[idx].rate_idx < 0)
906 return NULL; 927 return NULL;
907 return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx]; 928 return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx];
908} 929}
909 930
910/** 931/**
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index d7153bbcdb2..1460537faf3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -454,15 +454,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
454 if (unlikely(rsel.probe_idx >= 0)) { 454 if (unlikely(rsel.probe_idx >= 0)) {
455 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 455 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
456 tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; 456 tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
457 info->control.alt_retry_rate_idx = tx->rate_idx; 457 info->control.retries[0].rate_idx = tx->rate_idx;
458 info->control.retries[0].limit = tx->local->hw.max_altrate_tries;
458 tx->rate_idx = rsel.probe_idx; 459 tx->rate_idx = rsel.probe_idx;
459 } else 460 } else if (info->control.retries[0].limit == 0)
460 info->control.alt_retry_rate_idx = -1; 461 info->control.retries[0].rate_idx = -1;
461 462
462 if (unlikely(tx->rate_idx < 0)) 463 if (unlikely(tx->rate_idx < 0))
463 return TX_DROP; 464 return TX_DROP;
464 } else 465 } else
465 info->control.alt_retry_rate_idx = -1; 466 info->control.retries[0].rate_idx = -1;
466 467
467 if (tx->sdata->bss_conf.use_cts_prot && 468 if (tx->sdata->bss_conf.use_cts_prot &&
468 (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { 469 (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
@@ -521,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
521 * frames. 522 * frames.
522 * TODO: The last fragment could still use multiple retry 523 * TODO: The last fragment could still use multiple retry
523 * rates. */ 524 * rates. */
524 info->control.alt_retry_rate_idx = -1; 525 info->control.retries[0].rate_idx = -1;
525 } 526 }
526 527
527 /* Use CTS protection for unicast frames sent using extended rates if 528 /* Use CTS protection for unicast frames sent using extended rates if
@@ -551,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
551 int idx; 552 int idx;
552 553
553 /* Do not use multiple retry rates when using RTS/CTS */ 554 /* Do not use multiple retry rates when using RTS/CTS */
554 info->control.alt_retry_rate_idx = -1; 555 info->control.retries[0].rate_idx = -1;
555 556
556 /* Use min(data rate, max base rate) as CTS/RTS rate */ 557 /* Use min(data rate, max base rate) as CTS/RTS rate */
557 rate = &sband->bitrates[tx->rate_idx]; 558 rate = &sband->bitrates[tx->rate_idx];