diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-10-14 10:56:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:24 -0400 |
commit | c12abae333ac550acacf9d324ed54b7d17ead0c0 (patch) | |
tree | c138e2fdfab8a25c583bb4371d528e6fa5beec4e /drivers/net/wireless/p54 | |
parent | e6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (diff) |
p54: implement MRR
This implements multi-rate retry in p54. With lots of help
and testing from Christian and the limiting idea from nbd.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Christian Lamparter <chunkeey@web.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/p54')
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 130 |
1 files changed, 108 insertions, 22 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 65be5eca2340..237090140243 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -1,9 +1,9 @@ | |||
1 | |||
2 | /* | 1 | /* |
3 | * Common code for mac80211 Prism54 drivers | 2 | * Common code for mac80211 Prism54 drivers |
4 | * | 3 | * |
5 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> | 4 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> |
6 | * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de> | 5 | * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de> |
6 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | 7 | * |
8 | * Based on the islsm (softmac prism54) driver, which is: | 8 | * Based on the islsm (softmac prism54) driver, which is: |
9 | * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. | 9 | * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. |
@@ -544,6 +544,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
544 | u32 freed = 0; | 544 | u32 freed = 0; |
545 | u32 last_addr = priv->rx_start; | 545 | u32 last_addr = priv->rx_start; |
546 | unsigned long flags; | 546 | unsigned long flags; |
547 | int count, idx; | ||
547 | 548 | ||
548 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 549 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
549 | while (entry != (struct sk_buff *)&priv->tx_queue) { | 550 | while (entry != (struct sk_buff *)&priv->tx_queue) { |
@@ -568,18 +569,39 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
568 | __skb_unlink(entry, &priv->tx_queue); | 569 | __skb_unlink(entry, &priv->tx_queue); |
569 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 570 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
570 | 571 | ||
571 | ieee80211_tx_info_clear_status(info); | 572 | /* |
573 | * Clear manually, ieee80211_tx_info_clear_status would | ||
574 | * clear the counts too and we need them. | ||
575 | */ | ||
576 | memset(&info->status.ampdu_ack_len, 0, | ||
577 | sizeof(struct ieee80211_tx_info) - | ||
578 | offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); | ||
579 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, | ||
580 | status.ampdu_ack_len) != 23); | ||
581 | |||
572 | entry_hdr = (struct p54_control_hdr *) entry->data; | 582 | entry_hdr = (struct p54_control_hdr *) entry->data; |
573 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; | 583 | entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; |
574 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) | 584 | if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) |
575 | pad = entry_data->align[0]; | 585 | pad = entry_data->align[0]; |
576 | 586 | ||
577 | priv->tx_stats[entry_data->hw_queue].len--; | 587 | /* walk through the rates array and adjust the counts */ |
578 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 588 | count = payload->retries; |
579 | if (!(payload->status & 0x01)) | 589 | for (idx = 0; idx < 4; idx++) { |
580 | info->flags |= IEEE80211_TX_STAT_ACK; | 590 | if (count >= info->status.rates[idx].count) { |
591 | count -= info->status.rates[idx].count; | ||
592 | } else if (count > 0) { | ||
593 | info->status.rates[idx].count = count; | ||
594 | count = 0; | ||
595 | } else { | ||
596 | info->status.rates[idx].idx = -1; | ||
597 | info->status.rates[idx].count = 0; | ||
598 | } | ||
581 | } | 599 | } |
582 | info->status.rates[0].count = payload->retries; | 600 | |
601 | priv->tx_stats[entry_data->hw_queue].len--; | ||
602 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
603 | !(payload->status & 0x01)) | ||
604 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
583 | info->status.ack_signal = p54_rssi_to_dbm(dev, | 605 | info->status.ack_signal = p54_rssi_to_dbm(dev, |
584 | le16_to_cpu(payload->ack_rssi)); | 606 | le16_to_cpu(payload->ack_rssi)); |
585 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); | 607 | skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); |
@@ -802,9 +824,12 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
802 | struct p54_control_hdr *hdr; | 824 | struct p54_control_hdr *hdr; |
803 | struct p54_tx_control_allocdata *txhdr; | 825 | struct p54_tx_control_allocdata *txhdr; |
804 | size_t padding, len; | 826 | size_t padding, len; |
827 | int i, j, ridx; | ||
805 | u8 rate; | 828 | u8 rate; |
806 | u8 cts_rate = 0x20; | 829 | u8 cts_rate = 0x20; |
807 | u8 rc_flags; | 830 | u8 rc_flags; |
831 | u8 calculated_tries[4]; | ||
832 | u8 nrates = 0, nremaining = 8; | ||
808 | 833 | ||
809 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; | 834 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; |
810 | if (unlikely(current_queue->len > current_queue->limit)) | 835 | if (unlikely(current_queue->len > current_queue->limit)) |
@@ -827,23 +852,74 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
827 | hdr->magic1 = cpu_to_le16(0x0010); | 852 | hdr->magic1 = cpu_to_le16(0x0010); |
828 | hdr->len = cpu_to_le16(len); | 853 | hdr->len = cpu_to_le16(len); |
829 | hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); | 854 | hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); |
830 | hdr->retry1 = hdr->retry2 = info->control.rates[0].count; | 855 | hdr->retry1 = info->control.rates[0].count; |
831 | 856 | ||
832 | /* TODO: add support for alternate retry TX rates */ | 857 | /* |
833 | rate = ieee80211_get_tx_rate(dev, info)->hw_value; | 858 | * we register the rates in perfect order, and |
834 | rc_flags = info->control.rates[0].flags; | 859 | * RTS/CTS won't happen on 5 GHz |
835 | if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { | 860 | */ |
836 | rate |= 0x10; | 861 | cts_rate = info->control.rts_cts_rate_idx; |
837 | cts_rate |= 0x10; | 862 | |
863 | memset(&txhdr->rateset, 0, sizeof(txhdr->rateset)); | ||
864 | |||
865 | /* see how many rates got used */ | ||
866 | for (i = 0; i < 4; i++) { | ||
867 | if (info->control.rates[i].idx < 0) | ||
868 | break; | ||
869 | nrates++; | ||
870 | } | ||
871 | |||
872 | /* limit tries to 8/nrates per rate */ | ||
873 | for (i = 0; i < nrates; i++) { | ||
874 | /* | ||
875 | * The magic expression here is equivalent to 8/nrates for | ||
876 | * all values that matter, but avoids division and jumps. | ||
877 | * Note that nrates can only take the values 1 through 4. | ||
878 | */ | ||
879 | calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1, | ||
880 | info->control.rates[i].count); | ||
881 | nremaining -= calculated_tries[i]; | ||
838 | } | 882 | } |
839 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 883 | |
840 | rate |= 0x40; | 884 | /* if there are tries left, distribute from back to front */ |
841 | cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; | 885 | for (i = nrates - 1; nremaining > 0 && i >= 0; i--) { |
842 | } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 886 | int tmp = info->control.rates[i].count - calculated_tries[i]; |
843 | rate |= 0x20; | 887 | |
844 | cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; | 888 | if (tmp <= 0) |
889 | continue; | ||
890 | /* RC requested more tries at this rate */ | ||
891 | |||
892 | tmp = min_t(int, tmp, nremaining); | ||
893 | calculated_tries[i] += tmp; | ||
894 | nremaining -= tmp; | ||
845 | } | 895 | } |
846 | memset(txhdr->rateset, rate, 8); | 896 | |
897 | ridx = 0; | ||
898 | for (i = 0; i < nrates && ridx < 8; i++) { | ||
899 | /* we register the rates in perfect order */ | ||
900 | rate = info->control.rates[i].idx; | ||
901 | if (info->band == IEEE80211_BAND_5GHZ) | ||
902 | rate += 4; | ||
903 | |||
904 | /* store the count we actually calculated for TX status */ | ||
905 | info->control.rates[i].count = calculated_tries[i]; | ||
906 | |||
907 | rc_flags = info->control.rates[i].flags; | ||
908 | if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { | ||
909 | rate |= 0x10; | ||
910 | cts_rate |= 0x10; | ||
911 | } | ||
912 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
913 | rate |= 0x40; | ||
914 | else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) | ||
915 | rate |= 0x20; | ||
916 | for (j = 0; j < calculated_tries[i] && ridx < 8; j++) { | ||
917 | txhdr->rateset[ridx] = rate; | ||
918 | ridx++; | ||
919 | } | ||
920 | } | ||
921 | hdr->retry2 = ridx; | ||
922 | |||
847 | txhdr->key_type = 0; | 923 | txhdr->key_type = 0; |
848 | txhdr->key_len = 0; | 924 | txhdr->key_len = 0; |
849 | txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; | 925 | txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; |
@@ -1393,6 +1469,16 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
1393 | priv->tx_stats[4].limit = 5; | 1469 | priv->tx_stats[4].limit = 5; |
1394 | dev->queues = 1; | 1470 | dev->queues = 1; |
1395 | priv->noise = -94; | 1471 | priv->noise = -94; |
1472 | /* | ||
1473 | * We support at most 8 tries no matter which rate they're at, | ||
1474 | * we cannot support max_rates * max_rate_tries as we set it | ||
1475 | * here, but setting it correctly to 4/2 or so would limit us | ||
1476 | * artificially if the RC algorithm wants just two rates, so | ||
1477 | * let's say 4/7, we'll redistribute it at TX time, see the | ||
1478 | * comments there. | ||
1479 | */ | ||
1480 | dev->max_rates = 4; | ||
1481 | dev->max_rate_tries = 7; | ||
1396 | dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + | 1482 | dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + |
1397 | sizeof(struct p54_tx_control_allocdata); | 1483 | sizeof(struct p54_tx_control_allocdata); |
1398 | 1484 | ||