diff options
author | Mattias Nissler <mattias.nissler@gmx.de> | 2007-12-20 07:50:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:17 -0500 |
commit | 1abbe498e4b5e4f2000dfc30a0fa25be9553530e (patch) | |
tree | 8f899d2f623b2316f874fd8ae4b84838ad4e8b40 | |
parent | 98f0b0a3a412eade153c7cf00c6b863600980d89 (diff) |
mac80211: clean up rate selection
Move some code out of rc80211_simple since it's probably needed for all rate
selection algorithms, and fix iwlwifi accordingly. While at it, clean up the
rate_control_get_rate() interface.
Signed-off-by: Stefano Brivio <stefano.brivio@polimi.it>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 46 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_rate.c | 47 | ||||
-rw-r--r-- | net/mac80211/ieee80211_rate.h | 73 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 13 | ||||
-rw-r--r-- | net/mac80211/rc80211_simple.c | 64 | ||||
-rw-r--r-- | net/mac80211/tx.c | 42 |
8 files changed, 146 insertions, 189 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index c48b1b537d2b..ea7f459e961b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -562,22 +562,6 @@ static void rs_tx_status(void *priv_rate, | |||
562 | return; | 562 | return; |
563 | } | 563 | } |
564 | 564 | ||
565 | static struct ieee80211_rate *iwl_get_lowest_rate(struct ieee80211_local | ||
566 | *local) | ||
567 | { | ||
568 | struct ieee80211_hw_mode *mode = local->oper_hw_mode; | ||
569 | int i; | ||
570 | |||
571 | for (i = 0; i < mode->num_rates; i++) { | ||
572 | struct ieee80211_rate *rate = &mode->rates[i]; | ||
573 | |||
574 | if (rate->flags & IEEE80211_RATE_SUPPORTED) | ||
575 | return rate; | ||
576 | } | ||
577 | |||
578 | return &mode->rates[0]; | ||
579 | } | ||
580 | |||
581 | static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv, | 565 | static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv, |
582 | u8 index, u16 rate_mask, int phymode) | 566 | u8 index, u16 rate_mask, int phymode) |
583 | { | 567 | { |
@@ -656,10 +640,9 @@ static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv, | |||
656 | * rate table and must reference the driver allocated rate table | 640 | * rate table and must reference the driver allocated rate table |
657 | * | 641 | * |
658 | */ | 642 | */ |
659 | static struct ieee80211_rate *rs_get_rate(void *priv_rate, | 643 | static void rs_get_rate(void *priv_rate, struct net_device *dev, |
660 | struct net_device *dev, | 644 | struct ieee80211_hw_mode *mode, struct sk_buff *skb, |
661 | struct sk_buff *skb, | 645 | struct rate_selection *sel) |
662 | struct rate_control_extra *extra) | ||
663 | { | 646 | { |
664 | u8 low = IWL_RATE_INVALID; | 647 | u8 low = IWL_RATE_INVALID; |
665 | u8 high = IWL_RATE_INVALID; | 648 | u8 high = IWL_RATE_INVALID; |
@@ -676,32 +659,19 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, | |||
676 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 659 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
677 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 660 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
678 | struct sta_info *sta; | 661 | struct sta_info *sta; |
679 | u16 fc, rate_mask; | 662 | u16 rate_mask; |
680 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | 663 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; |
681 | DECLARE_MAC_BUF(mac); | 664 | DECLARE_MAC_BUF(mac); |
682 | 665 | ||
683 | IWL_DEBUG_RATE("enter\n"); | 666 | IWL_DEBUG_RATE("enter\n"); |
684 | 667 | ||
685 | memset(extra, 0, sizeof(*extra)); | ||
686 | |||
687 | fc = le16_to_cpu(hdr->frame_control); | ||
688 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || | ||
689 | (is_multicast_ether_addr(hdr->addr1))) { | ||
690 | /* Send management frames and broadcast/multicast data using | ||
691 | * lowest rate. */ | ||
692 | /* TODO: this could probably be improved.. */ | ||
693 | IWL_DEBUG_RATE("leave: lowest rate (not data or is " | ||
694 | "multicast)\n"); | ||
695 | |||
696 | return iwl_get_lowest_rate(local); | ||
697 | } | ||
698 | |||
699 | sta = sta_info_get(local, hdr->addr1); | 668 | sta = sta_info_get(local, hdr->addr1); |
700 | if (!sta || !sta->rate_ctrl_priv) { | 669 | if (!sta || !sta->rate_ctrl_priv) { |
701 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); | 670 | IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); |
671 | sel->rate = rate_lowest(local, local->oper_hw_mode, sta); | ||
702 | if (sta) | 672 | if (sta) |
703 | sta_info_put(sta); | 673 | sta_info_put(sta); |
704 | return NULL; | 674 | return; |
705 | } | 675 | } |
706 | 676 | ||
707 | rate_mask = sta->supp_rates; | 677 | rate_mask = sta->supp_rates; |
@@ -846,7 +816,7 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, | |||
846 | 816 | ||
847 | IWL_DEBUG_RATE("leave: %d\n", index); | 817 | IWL_DEBUG_RATE("leave: %d\n", index); |
848 | 818 | ||
849 | return &priv->ieee_rates[index]; | 819 | sel->rate = &priv->ieee_rates[index]; |
850 | } | 820 | } |
851 | 821 | ||
852 | static struct rate_control_ops rs_ops = { | 822 | static struct rate_control_ops rs_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 8dc78c0bf1ff..62a3b52b3270 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c | |||
@@ -1693,55 +1693,27 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
1693 | return; | 1693 | return; |
1694 | } | 1694 | } |
1695 | 1695 | ||
1696 | static struct ieee80211_rate *rs_get_lowest_rate(struct ieee80211_local | 1696 | static void rs_get_rate(void *priv_rate, struct net_device *dev, |
1697 | *local) | 1697 | struct ieee80211_hw_mode *mode, struct sk_buff *skb, |
1698 | { | 1698 | struct rate_selection *sel) |
1699 | struct ieee80211_hw_mode *mode = local->oper_hw_mode; | ||
1700 | int i; | ||
1701 | |||
1702 | for (i = 0; i < mode->num_rates; i++) { | ||
1703 | struct ieee80211_rate *rate = &mode->rates[i]; | ||
1704 | |||
1705 | if (rate->flags & IEEE80211_RATE_SUPPORTED) | ||
1706 | return rate; | ||
1707 | } | ||
1708 | |||
1709 | return &mode->rates[0]; | ||
1710 | } | ||
1711 | |||
1712 | static struct ieee80211_rate *rs_get_rate(void *priv_rate, | ||
1713 | struct net_device *dev, | ||
1714 | struct sk_buff *skb, | ||
1715 | struct rate_control_extra | ||
1716 | *extra) | ||
1717 | { | 1699 | { |
1718 | 1700 | ||
1719 | int i; | 1701 | int i; |
1720 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1702 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1721 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1703 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1722 | struct sta_info *sta; | 1704 | struct sta_info *sta; |
1723 | u16 fc; | ||
1724 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | 1705 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; |
1725 | struct iwl_rate_scale_priv *lq; | 1706 | struct iwl_rate_scale_priv *lq; |
1726 | 1707 | ||
1727 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); | 1708 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); |
1728 | 1709 | ||
1729 | memset(extra, 0, sizeof(*extra)); | ||
1730 | |||
1731 | fc = le16_to_cpu(hdr->frame_control); | ||
1732 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { | ||
1733 | /* Send management frames and broadcast/multicast data using | ||
1734 | * lowest rate. */ | ||
1735 | /* TODO: this could probably be improved.. */ | ||
1736 | return rs_get_lowest_rate(local); | ||
1737 | } | ||
1738 | |||
1739 | sta = sta_info_get(local, hdr->addr1); | 1710 | sta = sta_info_get(local, hdr->addr1); |
1740 | 1711 | ||
1741 | if (!sta || !sta->rate_ctrl_priv) { | 1712 | if (!sta || !sta->rate_ctrl_priv) { |
1713 | sel->rate = rate_lowest(local, local->oper_hw_mode, sta); | ||
1742 | if (sta) | 1714 | if (sta) |
1743 | sta_info_put(sta); | 1715 | sta_info_put(sta); |
1744 | return rs_get_lowest_rate(local); | 1716 | return; |
1745 | } | 1717 | } |
1746 | 1718 | ||
1747 | lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv; | 1719 | lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv; |
@@ -1768,11 +1740,13 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate, | |||
1768 | } | 1740 | } |
1769 | 1741 | ||
1770 | done: | 1742 | done: |
1743 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | ||
1744 | sel->rate = rate_lowest(local, local->oper_hw_mode, sta); | ||
1745 | return; | ||
1746 | } | ||
1771 | sta_info_put(sta); | 1747 | sta_info_put(sta); |
1772 | if ((i < 0) || (i > IWL_RATE_COUNT)) | ||
1773 | return rs_get_lowest_rate(local); | ||
1774 | 1748 | ||
1775 | return &priv->ieee_rates[i]; | 1749 | sel->rate = &priv->ieee_rates[i]; |
1776 | } | 1750 | } |
1777 | 1751 | ||
1778 | static void *rs_alloc_sta(void *priv, gfp_t gfp) | 1752 | static void *rs_alloc_sta(void *priv, gfp_t gfp) |
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index d6a97a68a62e..5bf7a5bebfc9 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -859,10 +859,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
859 | sta_info_put(sta); | 859 | sta_info_put(sta); |
860 | return; | 860 | return; |
861 | } | 861 | } |
862 | } else { | 862 | } else |
863 | /* FIXME: STUPID to call this with both local and local->mdev */ | 863 | rate_control_tx_status(local->mdev, skb, status); |
864 | rate_control_tx_status(local, local->mdev, skb, status); | ||
865 | } | ||
866 | 864 | ||
867 | ieee80211_led_tx(local, 0); | 865 | ieee80211_led_tx(local, 0); |
868 | 866 | ||
diff --git a/net/mac80211/ieee80211_rate.c b/net/mac80211/ieee80211_rate.c index c3f278393741..e495b0998b4d 100644 --- a/net/mac80211/ieee80211_rate.c +++ b/net/mac80211/ieee80211_rate.c | |||
@@ -147,6 +147,53 @@ static void rate_control_release(struct kref *kref) | |||
147 | kfree(ctrl_ref); | 147 | kfree(ctrl_ref); |
148 | } | 148 | } |
149 | 149 | ||
150 | void rate_control_get_rate(struct net_device *dev, | ||
151 | struct ieee80211_hw_mode *mode, struct sk_buff *skb, | ||
152 | struct rate_selection *sel) | ||
153 | { | ||
154 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
155 | struct rate_control_ref *ref = local->rate_ctrl; | ||
156 | struct ieee80211_sub_if_data *sdata; | ||
157 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
158 | struct sta_info *sta = sta_info_get(local, hdr->addr1); | ||
159 | int i; | ||
160 | u16 fc; | ||
161 | |||
162 | memset(sel, 0, sizeof(struct rate_selection)); | ||
163 | |||
164 | /* Send management frames and broadcast/multicast data using lowest | ||
165 | * rate. */ | ||
166 | fc = le16_to_cpu(hdr->frame_control); | ||
167 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
168 | is_multicast_ether_addr(hdr->addr1)) | ||
169 | sel->rate = rate_lowest(local, mode, sta); | ||
170 | |||
171 | /* If a forced rate is in effect, select it. */ | ||
172 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
173 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) | ||
174 | sel->rate = &mode->rates[sdata->bss->force_unicast_rateidx]; | ||
175 | |||
176 | /* If we haven't found the rate yet, ask the rate control algo. */ | ||
177 | if (!sel->rate) | ||
178 | ref->ops->get_rate(ref->priv, dev, mode, skb, sel); | ||
179 | |||
180 | /* Select a non-ERP backup rate. */ | ||
181 | if (!sel->nonerp) { | ||
182 | for (i = 0; i < mode->num_rates - 1; i++) { | ||
183 | struct ieee80211_rate *rate = &mode->rates[i]; | ||
184 | if (sel->rate->rate < rate->rate) | ||
185 | break; | ||
186 | |||
187 | if (rate_supported(sta, mode, i) && | ||
188 | !(rate->flags & IEEE80211_RATE_ERP)) | ||
189 | sel->nonerp = rate; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | if (sta) | ||
194 | sta_info_put(sta); | ||
195 | } | ||
196 | |||
150 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | 197 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) |
151 | { | 198 | { |
152 | kref_get(&ref->kref); | 199 | kref_get(&ref->kref); |
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h index 23688139ffb3..787134bd6abf 100644 --- a/net/mac80211/ieee80211_rate.h +++ b/net/mac80211/ieee80211_rate.h | |||
@@ -18,31 +18,24 @@ | |||
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "sta_info.h" | 19 | #include "sta_info.h" |
20 | 20 | ||
21 | #define RATE_CONTROL_NUM_DOWN 20 | 21 | struct rate_selection { |
22 | #define RATE_CONTROL_NUM_UP 15 | 22 | /* Selected transmission rate */ |
23 | 23 | struct ieee80211_rate *rate; | |
24 | 24 | /* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */ | |
25 | struct rate_control_extra { | ||
26 | /* values from rate_control_get_rate() to the caller: */ | ||
27 | struct ieee80211_rate *probe; /* probe with this rate, or NULL for no | ||
28 | * probing */ | ||
29 | struct ieee80211_rate *nonerp; | 25 | struct ieee80211_rate *nonerp; |
30 | 26 | /* probe with this rate, or NULL for no probing */ | |
31 | /* parameters from the caller to rate_control_get_rate(): */ | 27 | struct ieee80211_rate *probe; |
32 | struct ieee80211_hw_mode *mode; | ||
33 | u16 ethertype; | ||
34 | }; | 28 | }; |
35 | 29 | ||
36 | |||
37 | struct rate_control_ops { | 30 | struct rate_control_ops { |
38 | struct module *module; | 31 | struct module *module; |
39 | const char *name; | 32 | const char *name; |
40 | void (*tx_status)(void *priv, struct net_device *dev, | 33 | void (*tx_status)(void *priv, struct net_device *dev, |
41 | struct sk_buff *skb, | 34 | struct sk_buff *skb, |
42 | struct ieee80211_tx_status *status); | 35 | struct ieee80211_tx_status *status); |
43 | struct ieee80211_rate *(*get_rate)(void *priv, struct net_device *dev, | 36 | void (*get_rate)(void *priv, struct net_device *dev, |
44 | struct sk_buff *skb, | 37 | struct ieee80211_hw_mode *mode, struct sk_buff *skb, |
45 | struct rate_control_extra *extra); | 38 | struct rate_selection *sel); |
46 | void (*rate_init)(void *priv, void *priv_sta, | 39 | void (*rate_init)(void *priv, void *priv_sta, |
47 | struct ieee80211_local *local, struct sta_info *sta); | 40 | struct ieee80211_local *local, struct sta_info *sta); |
48 | void (*clear)(void *priv); | 41 | void (*clear)(void *priv); |
@@ -75,25 +68,20 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | |||
75 | * first available algorithm. */ | 68 | * first available algorithm. */ |
76 | struct rate_control_ref *rate_control_alloc(const char *name, | 69 | struct rate_control_ref *rate_control_alloc(const char *name, |
77 | struct ieee80211_local *local); | 70 | struct ieee80211_local *local); |
71 | void rate_control_get_rate(struct net_device *dev, | ||
72 | struct ieee80211_hw_mode *mode, struct sk_buff *skb, | ||
73 | struct rate_selection *sel); | ||
78 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 74 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
79 | void rate_control_put(struct rate_control_ref *ref); | 75 | void rate_control_put(struct rate_control_ref *ref); |
80 | 76 | ||
81 | static inline void rate_control_tx_status(struct ieee80211_local *local, | 77 | static inline void rate_control_tx_status(struct net_device *dev, |
82 | struct net_device *dev, | ||
83 | struct sk_buff *skb, | 78 | struct sk_buff *skb, |
84 | struct ieee80211_tx_status *status) | 79 | struct ieee80211_tx_status *status) |
85 | { | 80 | { |
81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
86 | struct rate_control_ref *ref = local->rate_ctrl; | 82 | struct rate_control_ref *ref = local->rate_ctrl; |
87 | ref->ops->tx_status(ref->priv, dev, skb, status); | ||
88 | } | ||
89 | 83 | ||
90 | 84 | ref->ops->tx_status(ref->priv, dev, skb, status); | |
91 | static inline struct ieee80211_rate * | ||
92 | rate_control_get_rate(struct ieee80211_local *local, struct net_device *dev, | ||
93 | struct sk_buff *skb, struct rate_control_extra *extra) | ||
94 | { | ||
95 | struct rate_control_ref *ref = local->rate_ctrl; | ||
96 | return ref->ops->get_rate(ref->priv, dev, skb, extra); | ||
97 | } | 85 | } |
98 | 86 | ||
99 | 87 | ||
@@ -142,6 +130,37 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
142 | #endif | 130 | #endif |
143 | } | 131 | } |
144 | 132 | ||
133 | static inline int | ||
134 | rate_supported(struct sta_info *sta, struct ieee80211_hw_mode *mode, int index) | ||
135 | { | ||
136 | return (sta == NULL || sta->supp_rates & BIT(index)) && | ||
137 | (mode->rates[index].flags & IEEE80211_RATE_SUPPORTED); | ||
138 | } | ||
139 | |||
140 | static inline int | ||
141 | rate_lowest_index(struct ieee80211_local *local, struct ieee80211_hw_mode *mode, | ||
142 | struct sta_info *sta) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | for (i = 0; i < mode->num_rates; i++) { | ||
147 | if (rate_supported(sta, mode, i)) | ||
148 | return i; | ||
149 | } | ||
150 | |||
151 | /* warn when we cannot find a rate. */ | ||
152 | WARN_ON(1); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static inline struct ieee80211_rate * | ||
158 | rate_lowest(struct ieee80211_local *local, struct ieee80211_hw_mode *mode, | ||
159 | struct sta_info *sta) | ||
160 | { | ||
161 | return &mode->rates[rate_lowest_index(local, mode, sta)]; | ||
162 | } | ||
163 | |||
145 | 164 | ||
146 | /* functions for rate control related to a device */ | 165 | /* functions for rate control related to a device */ |
147 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 166 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 3c552fed2af5..3978ad606b5c 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -2463,9 +2463,8 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2463 | struct sk_buff *skb; | 2463 | struct sk_buff *skb; |
2464 | struct ieee80211_mgmt *mgmt; | 2464 | struct ieee80211_mgmt *mgmt; |
2465 | struct ieee80211_tx_control control; | 2465 | struct ieee80211_tx_control control; |
2466 | struct ieee80211_rate *rate; | ||
2467 | struct ieee80211_hw_mode *mode; | 2466 | struct ieee80211_hw_mode *mode; |
2468 | struct rate_control_extra extra; | 2467 | struct rate_selection ratesel; |
2469 | u8 *pos; | 2468 | u8 *pos; |
2470 | struct ieee80211_sub_if_data *sdata; | 2469 | struct ieee80211_sub_if_data *sdata; |
2471 | 2470 | ||
@@ -2550,18 +2549,16 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2550 | } | 2549 | } |
2551 | 2550 | ||
2552 | memset(&control, 0, sizeof(control)); | 2551 | memset(&control, 0, sizeof(control)); |
2553 | memset(&extra, 0, sizeof(extra)); | 2552 | rate_control_get_rate(dev, local->oper_hw_mode, skb, &ratesel); |
2554 | extra.mode = local->oper_hw_mode; | 2553 | if (!ratesel.rate) { |
2555 | rate = rate_control_get_rate(local, dev, skb, &extra); | ||
2556 | if (!rate) { | ||
2557 | printk(KERN_DEBUG "%s: Failed to determine TX rate " | 2554 | printk(KERN_DEBUG "%s: Failed to determine TX rate " |
2558 | "for IBSS beacon\n", dev->name); | 2555 | "for IBSS beacon\n", dev->name); |
2559 | break; | 2556 | break; |
2560 | } | 2557 | } |
2561 | control.tx_rate = | 2558 | control.tx_rate = |
2562 | ((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) && | 2559 | ((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) && |
2563 | (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? | 2560 | (ratesel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ? |
2564 | rate->val2 : rate->val; | 2561 | ratesel.rate->val2 : ratesel.rate->val; |
2565 | control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 2562 | control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
2566 | control.power_level = local->hw.conf.power_level; | 2563 | control.power_level = local->hw.conf.power_level; |
2567 | control.flags |= IEEE80211_TXCTL_NO_ACK; | 2564 | control.flags |= IEEE80211_TXCTL_NO_ACK; |
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c index da72737364e4..c1c8b76a56af 100644 --- a/net/mac80211/rc80211_simple.c +++ b/net/mac80211/rc80211_simple.c | |||
@@ -23,6 +23,8 @@ | |||
23 | /* This is a minimal implementation of TX rate controlling that can be used | 23 | /* This is a minimal implementation of TX rate controlling that can be used |
24 | * as the default when no improved mechanisms are available. */ | 24 | * as the default when no improved mechanisms are available. */ |
25 | 25 | ||
26 | #define RATE_CONTROL_NUM_DOWN 20 | ||
27 | #define RATE_CONTROL_NUM_UP 15 | ||
26 | 28 | ||
27 | #define RATE_CONTROL_EMERG_DEC 2 | 29 | #define RATE_CONTROL_EMERG_DEC 2 |
28 | #define RATE_CONTROL_INTERVAL (HZ / 20) | 30 | #define RATE_CONTROL_INTERVAL (HZ / 20) |
@@ -87,26 +89,6 @@ static void rate_control_rate_dec(struct ieee80211_local *local, | |||
87 | } | 89 | } |
88 | } | 90 | } |
89 | 91 | ||
90 | |||
91 | static struct ieee80211_rate * | ||
92 | rate_control_lowest_rate(struct ieee80211_local *local, | ||
93 | struct ieee80211_hw_mode *mode) | ||
94 | { | ||
95 | int i; | ||
96 | |||
97 | for (i = 0; i < mode->num_rates; i++) { | ||
98 | struct ieee80211_rate *rate = &mode->rates[i]; | ||
99 | |||
100 | if (rate->flags & IEEE80211_RATE_SUPPORTED) | ||
101 | return rate; | ||
102 | } | ||
103 | |||
104 | printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates " | ||
105 | "found\n"); | ||
106 | return &mode->rates[0]; | ||
107 | } | ||
108 | |||
109 | |||
110 | struct global_rate_control { | 92 | struct global_rate_control { |
111 | int dummy; | 93 | int dummy; |
112 | }; | 94 | }; |
@@ -216,56 +198,32 @@ static void rate_control_simple_tx_status(void *priv, struct net_device *dev, | |||
216 | } | 198 | } |
217 | 199 | ||
218 | 200 | ||
219 | static struct ieee80211_rate * | 201 | static void |
220 | rate_control_simple_get_rate(void *priv, struct net_device *dev, | 202 | rate_control_simple_get_rate(void *priv, struct net_device *dev, |
203 | struct ieee80211_hw_mode *mode, | ||
221 | struct sk_buff *skb, | 204 | struct sk_buff *skb, |
222 | struct rate_control_extra *extra) | 205 | struct rate_selection *sel) |
223 | { | 206 | { |
224 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 207 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
225 | struct ieee80211_sub_if_data *sdata; | ||
226 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
227 | struct ieee80211_hw_mode *mode = extra->mode; | ||
228 | struct sta_info *sta; | 209 | struct sta_info *sta; |
229 | int rateidx, nonerp_idx; | 210 | int rateidx; |
230 | u16 fc; | ||
231 | |||
232 | memset(extra, 0, sizeof(*extra)); | ||
233 | |||
234 | fc = le16_to_cpu(hdr->frame_control); | ||
235 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
236 | (hdr->addr1[0] & 0x01)) { | ||
237 | /* Send management frames and broadcast/multicast data using | ||
238 | * lowest rate. */ | ||
239 | /* TODO: this could probably be improved.. */ | ||
240 | return rate_control_lowest_rate(local, mode); | ||
241 | } | ||
242 | 211 | ||
243 | sta = sta_info_get(local, hdr->addr1); | 212 | sta = sta_info_get(local, hdr->addr1); |
244 | 213 | ||
245 | if (!sta) | 214 | if (!sta) { |
246 | return rate_control_lowest_rate(local, mode); | 215 | sel->rate = rate_lowest(local, mode, NULL); |
247 | 216 | return; | |
248 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 217 | } |
249 | if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) | ||
250 | sta->txrate = sdata->bss->force_unicast_rateidx; | ||
251 | 218 | ||
252 | rateidx = sta->txrate; | 219 | rateidx = sta->txrate; |
253 | 220 | ||
254 | if (rateidx >= mode->num_rates) | 221 | if (rateidx >= mode->num_rates) |
255 | rateidx = mode->num_rates - 1; | 222 | rateidx = mode->num_rates - 1; |
256 | 223 | ||
257 | sta->last_txrate = rateidx; | ||
258 | nonerp_idx = rateidx; | ||
259 | while (nonerp_idx > 0 && | ||
260 | ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) || | ||
261 | !(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) || | ||
262 | !(sta->supp_rates & BIT(nonerp_idx)))) | ||
263 | nonerp_idx--; | ||
264 | extra->nonerp = &mode->rates[nonerp_idx]; | ||
265 | |||
266 | sta_info_put(sta); | 224 | sta_info_put(sta); |
267 | 225 | ||
268 | return &mode->rates[rateidx]; | 226 | sel->rate = &mode->rates[rateidx]; |
269 | } | 227 | } |
270 | 228 | ||
271 | 229 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 12c15588af68..4655e3038658 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -569,21 +569,17 @@ ieee80211_tx_h_encrypt(struct ieee80211_txrx_data *tx) | |||
569 | static ieee80211_txrx_result | 569 | static ieee80211_txrx_result |
570 | ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) | 570 | ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) |
571 | { | 571 | { |
572 | struct rate_control_extra extra; | 572 | struct rate_selection rsel; |
573 | 573 | ||
574 | if (likely(!tx->u.tx.rate)) { | 574 | if (likely(!tx->u.tx.rate)) { |
575 | memset(&extra, 0, sizeof(extra)); | 575 | rate_control_get_rate(tx->dev, tx->u.tx.mode, tx->skb, &rsel); |
576 | extra.mode = tx->u.tx.mode; | 576 | tx->u.tx.rate = rsel.rate; |
577 | extra.ethertype = tx->ethertype; | 577 | if (unlikely(rsel.probe != NULL)) { |
578 | |||
579 | tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, | ||
580 | tx->skb, &extra); | ||
581 | if (unlikely(extra.probe != NULL)) { | ||
582 | tx->u.tx.control->flags |= | 578 | tx->u.tx.control->flags |= |
583 | IEEE80211_TXCTL_RATE_CTRL_PROBE; | 579 | IEEE80211_TXCTL_RATE_CTRL_PROBE; |
584 | tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; | 580 | tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; |
585 | tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val; | 581 | tx->u.tx.control->alt_retry_rate = tx->u.tx.rate->val; |
586 | tx->u.tx.rate = extra.probe; | 582 | tx->u.tx.rate = rsel.probe; |
587 | } else | 583 | } else |
588 | tx->u.tx.control->alt_retry_rate = -1; | 584 | tx->u.tx.control->alt_retry_rate = -1; |
589 | 585 | ||
@@ -594,14 +590,14 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx) | |||
594 | 590 | ||
595 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && | 591 | if (tx->u.tx.mode->mode == MODE_IEEE80211G && |
596 | (tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) && | 592 | (tx->sdata->flags & IEEE80211_SDATA_USE_PROTECTION) && |
597 | (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && extra.nonerp) { | 593 | (tx->flags & IEEE80211_TXRXD_FRAGMENTED) && rsel.nonerp) { |
598 | tx->u.tx.last_frag_rate = tx->u.tx.rate; | 594 | tx->u.tx.last_frag_rate = tx->u.tx.rate; |
599 | if (extra.probe) | 595 | if (rsel.probe) |
600 | tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG; | 596 | tx->flags &= ~IEEE80211_TXRXD_TXPROBE_LAST_FRAG; |
601 | else | 597 | else |
602 | tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; | 598 | tx->flags |= IEEE80211_TXRXD_TXPROBE_LAST_FRAG; |
603 | tx->u.tx.rate = extra.nonerp; | 599 | tx->u.tx.rate = rsel.nonerp; |
604 | tx->u.tx.control->rate = extra.nonerp; | 600 | tx->u.tx.control->rate = rsel.nonerp; |
605 | tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE; | 601 | tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE; |
606 | } else { | 602 | } else { |
607 | tx->u.tx.last_frag_rate = tx->u.tx.rate; | 603 | tx->u.tx.last_frag_rate = tx->u.tx.rate; |
@@ -1667,8 +1663,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, | |||
1667 | struct net_device *bdev; | 1663 | struct net_device *bdev; |
1668 | struct ieee80211_sub_if_data *sdata = NULL; | 1664 | struct ieee80211_sub_if_data *sdata = NULL; |
1669 | struct ieee80211_if_ap *ap = NULL; | 1665 | struct ieee80211_if_ap *ap = NULL; |
1670 | struct ieee80211_rate *rate; | 1666 | struct rate_selection rsel; |
1671 | struct rate_control_extra extra; | ||
1672 | u8 *b_head, *b_tail; | 1667 | u8 *b_head, *b_tail; |
1673 | int bh_len, bt_len; | 1668 | int bh_len, bt_len; |
1674 | 1669 | ||
@@ -1712,14 +1707,13 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, | |||
1712 | } | 1707 | } |
1713 | 1708 | ||
1714 | if (control) { | 1709 | if (control) { |
1715 | memset(&extra, 0, sizeof(extra)); | 1710 | rate_control_get_rate(local->mdev, local->oper_hw_mode, skb, |
1716 | extra.mode = local->oper_hw_mode; | 1711 | &rsel); |
1717 | 1712 | if (!rsel.rate) { | |
1718 | rate = rate_control_get_rate(local, local->mdev, skb, &extra); | ||
1719 | if (!rate) { | ||
1720 | if (net_ratelimit()) { | 1713 | if (net_ratelimit()) { |
1721 | printk(KERN_DEBUG "%s: ieee80211_beacon_get: no rate " | 1714 | printk(KERN_DEBUG "%s: ieee80211_beacon_get: " |
1722 | "found\n", wiphy_name(local->hw.wiphy)); | 1715 | "no rate found\n", |
1716 | wiphy_name(local->hw.wiphy)); | ||
1723 | } | 1717 | } |
1724 | dev_kfree_skb(skb); | 1718 | dev_kfree_skb(skb); |
1725 | return NULL; | 1719 | return NULL; |
@@ -1727,8 +1721,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id, | |||
1727 | 1721 | ||
1728 | control->tx_rate = | 1722 | control->tx_rate = |
1729 | ((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) && | 1723 | ((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) && |
1730 | (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? | 1724 | (rsel.rate->flags & IEEE80211_RATE_PREAMBLE2)) ? |
1731 | rate->val2 : rate->val; | 1725 | rsel.rate->val2 : rsel.rate->val; |
1732 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1726 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
1733 | control->power_level = local->hw.conf.power_level; | 1727 | control->power_level = local->hw.conf.power_level; |
1734 | control->flags |= IEEE80211_TXCTL_NO_ACK; | 1728 | control->flags |= IEEE80211_TXCTL_NO_ACK; |