aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-17 12:18:36 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-18 17:09:24 -0500
commitaf65cd96dd4ea8ea5adc6ee850e61a407cd1067a (patch)
treefcdd50d2b9121bc26110329cb0fbefdeace99858
parentc95cf3d09adc9afe7816a13a920b6df36062a3fe (diff)
mac80211: make software rate control optional
Some devices implement the entire rate control in firmware in some way, like wl1271 or like iwlwifi which does some things in software but not a lot. Therefore generic software rate control is rather useless for them and just adds avoidable overhead to the transmit path. It's fairly simple to let drivers indicate that they do not need rate control, but they need to fulfil a number of conditions that we encode in WARN_ONs. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h14
-rw-r--r--net/mac80211/debugfs.c2
-rw-r--r--net/mac80211/rate.c12
-rw-r--r--net/mac80211/rate.h9
-rw-r--r--net/mac80211/sta_info.c29
-rw-r--r--net/mac80211/tx.c3
6 files changed, 56 insertions, 13 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4af0ffb98aaf..f34f4ca7016c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -855,6 +855,19 @@ enum ieee80211_tkip_key_type {
855 * any particular flags. There are some exceptions to this rule, 855 * any particular flags. There are some exceptions to this rule,
856 * however, so you are advised to review these flags carefully. 856 * however, so you are advised to review these flags carefully.
857 * 857 *
858 * @IEEE80211_HW_HAS_RATE_CONTROL:
859 * The hardware or firmware includes rate control, and cannot be
860 * controlled by the stack. As such, no rate control algorithm
861 * should be instantiated, and the TX rate reported to userspace
862 * will be taken from the TX status instead of the rate control
863 * algorithm.
864 * Note that this requires that the driver implement a number of
865 * callbacks so it has the correct information, it needs to have
866 * the @set_rts_threshold callback and must look at the BSS config
867 * @use_cts_prot for G/N protection, @use_short_slot for slot
868 * timing in 2.4 GHz and @use_short_preamble for preambles for
869 * CCK frames.
870 *
858 * @IEEE80211_HW_RX_INCLUDES_FCS: 871 * @IEEE80211_HW_RX_INCLUDES_FCS:
859 * Indicates that received frames passed to the stack include 872 * Indicates that received frames passed to the stack include
860 * the FCS at the end. 873 * the FCS at the end.
@@ -913,6 +926,7 @@ enum ieee80211_tkip_key_type {
913 * avoid waking up cpu. 926 * avoid waking up cpu.
914 */ 927 */
915enum ieee80211_hw_flags { 928enum ieee80211_hw_flags {
929 IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
916 IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, 930 IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
917 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, 931 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2,
918 IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, 932 IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3,
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 82c807723b6f..e4b54093d41b 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -52,7 +52,7 @@ DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
52DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", 52DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
53 local->wep_iv & 0xffffff); 53 local->wep_iv & 0xffffff);
54DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", 54DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
55 local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>"); 55 local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
56 56
57static ssize_t tsf_read(struct file *file, char __user *user_buf, 57static ssize_t tsf_read(struct file *file, char __user *user_buf,
58 size_t count, loff_t *ppos) 58 size_t count, loff_t *ppos)
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index ccda7454fb17..b9007f80cb92 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -284,9 +284,16 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
284 struct rate_control_ref *ref, *old; 284 struct rate_control_ref *ref, *old;
285 285
286 ASSERT_RTNL(); 286 ASSERT_RTNL();
287
287 if (local->open_count) 288 if (local->open_count)
288 return -EBUSY; 289 return -EBUSY;
289 290
291 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) {
292 if (WARN_ON(!local->ops->set_rts_threshold))
293 return -EINVAL;
294 return 0;
295 }
296
290 ref = rate_control_alloc(name, local); 297 ref = rate_control_alloc(name, local);
291 if (!ref) { 298 if (!ref) {
292 printk(KERN_WARNING "%s: Failed to select rate control " 299 printk(KERN_WARNING "%s: Failed to select rate control "
@@ -305,7 +312,6 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
305 "algorithm '%s'\n", wiphy_name(local->hw.wiphy), 312 "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
306 ref->ops->name); 313 ref->ops->name);
307 314
308
309 return 0; 315 return 0;
310} 316}
311 317
@@ -314,6 +320,10 @@ void rate_control_deinitialize(struct ieee80211_local *local)
314 struct rate_control_ref *ref; 320 struct rate_control_ref *ref;
315 321
316 ref = local->rate_ctrl; 322 ref = local->rate_ctrl;
323
324 if (!ref)
325 return;
326
317 local->rate_ctrl = NULL; 327 local->rate_ctrl = NULL;
318 rate_control_put(ref); 328 rate_control_put(ref);
319} 329}
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 2ab5ad9e71ce..cb9bd1f65e27 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -59,6 +59,9 @@ static inline void rate_control_rate_init(struct sta_info *sta)
59 void *priv_sta = sta->rate_ctrl_priv; 59 void *priv_sta = sta->rate_ctrl_priv;
60 struct ieee80211_supported_band *sband; 60 struct ieee80211_supported_band *sband;
61 61
62 if (!ref)
63 return;
64
62 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 65 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
63 66
64 ref->ops->rate_init(ref->priv, sband, ista, priv_sta); 67 ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
@@ -72,7 +75,7 @@ static inline void rate_control_rate_update(struct ieee80211_local *local,
72 struct ieee80211_sta *ista = &sta->sta; 75 struct ieee80211_sta *ista = &sta->sta;
73 void *priv_sta = sta->rate_ctrl_priv; 76 void *priv_sta = sta->rate_ctrl_priv;
74 77
75 if (ref->ops->rate_update) 78 if (ref && ref->ops->rate_update)
76 ref->ops->rate_update(ref->priv, sband, ista, 79 ref->ops->rate_update(ref->priv, sband, ista,
77 priv_sta, changed); 80 priv_sta, changed);
78} 81}
@@ -97,7 +100,7 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
97{ 100{
98#ifdef CONFIG_MAC80211_DEBUGFS 101#ifdef CONFIG_MAC80211_DEBUGFS
99 struct rate_control_ref *ref = sta->rate_ctrl; 102 struct rate_control_ref *ref = sta->rate_ctrl;
100 if (sta->debugfs.dir && ref->ops->add_sta_debugfs) 103 if (ref && sta->debugfs.dir && ref->ops->add_sta_debugfs)
101 ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, 104 ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
102 sta->debugfs.dir); 105 sta->debugfs.dir);
103#endif 106#endif
@@ -107,7 +110,7 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
107{ 110{
108#ifdef CONFIG_MAC80211_DEBUGFS 111#ifdef CONFIG_MAC80211_DEBUGFS
109 struct rate_control_ref *ref = sta->rate_ctrl; 112 struct rate_control_ref *ref = sta->rate_ctrl;
110 if (ref->ops->remove_sta_debugfs) 113 if (ref && ref->ops->remove_sta_debugfs)
111 ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); 114 ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
112#endif 115#endif
113} 116}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aa017a56afc8..71f370dd24bc 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -148,8 +148,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
148static void __sta_info_free(struct ieee80211_local *local, 148static void __sta_info_free(struct ieee80211_local *local,
149 struct sta_info *sta) 149 struct sta_info *sta)
150{ 150{
151 rate_control_free_sta(sta); 151 if (sta->rate_ctrl) {
152 rate_control_put(sta->rate_ctrl); 152 rate_control_free_sta(sta);
153 rate_control_put(sta->rate_ctrl);
154 }
153 155
154#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 156#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
155 printk(KERN_DEBUG "%s: Destroyed STA %pM\n", 157 printk(KERN_DEBUG "%s: Destroyed STA %pM\n",
@@ -277,6 +279,23 @@ static void sta_unblock(struct work_struct *wk)
277 ieee80211_sta_ps_deliver_poll_response(sta); 279 ieee80211_sta_ps_deliver_poll_response(sta);
278} 280}
279 281
282static int sta_prepare_rate_control(struct ieee80211_local *local,
283 struct sta_info *sta, gfp_t gfp)
284{
285 if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
286 return 0;
287
288 sta->rate_ctrl = rate_control_get(local->rate_ctrl);
289 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
290 &sta->sta, gfp);
291 if (!sta->rate_ctrl_priv) {
292 rate_control_put(sta->rate_ctrl);
293 return -ENOMEM;
294 }
295
296 return 0;
297}
298
280struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, 299struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
281 u8 *addr, gfp_t gfp) 300 u8 *addr, gfp_t gfp)
282{ 301{
@@ -296,11 +315,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
296 sta->local = local; 315 sta->local = local;
297 sta->sdata = sdata; 316 sta->sdata = sdata;
298 317
299 sta->rate_ctrl = rate_control_get(local->rate_ctrl); 318 if (sta_prepare_rate_control(local, sta, gfp)) {
300 sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl,
301 &sta->sta, gfp);
302 if (!sta->rate_ctrl_priv) {
303 rate_control_put(sta->rate_ctrl);
304 kfree(sta); 319 kfree(sta);
305 return NULL; 320 return NULL;
306 } 321 }
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3466e1f7fd12..bd916437e2fb 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1219,7 +1219,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1219 CALL_TXH(ieee80211_tx_h_ps_buf); 1219 CALL_TXH(ieee80211_tx_h_ps_buf);
1220 CALL_TXH(ieee80211_tx_h_select_key); 1220 CALL_TXH(ieee80211_tx_h_select_key);
1221 CALL_TXH(ieee80211_tx_h_michael_mic_add); 1221 CALL_TXH(ieee80211_tx_h_michael_mic_add);
1222 CALL_TXH(ieee80211_tx_h_rate_ctrl); 1222 if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
1223 CALL_TXH(ieee80211_tx_h_rate_ctrl);
1223 CALL_TXH(ieee80211_tx_h_misc); 1224 CALL_TXH(ieee80211_tx_h_misc);
1224 CALL_TXH(ieee80211_tx_h_sequence); 1225 CALL_TXH(ieee80211_tx_h_sequence);
1225 CALL_TXH(ieee80211_tx_h_fragment); 1226 CALL_TXH(ieee80211_tx_h_fragment);