aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-14 10:56:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:24 -0400
commitc12abae333ac550acacf9d324ed54b7d17ead0c0 (patch)
treec138e2fdfab8a25c583bb4371d528e6fa5beec4e /drivers/net/wireless/p54
parente6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (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.c130
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