diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-11-17 12:18:36 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-18 17:09:24 -0500 |
commit | af65cd96dd4ea8ea5adc6ee850e61a407cd1067a (patch) | |
tree | fcdd50d2b9121bc26110329cb0fbefdeace99858 /net | |
parent | c95cf3d09adc9afe7816a13a920b6df36062a3fe (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>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/debugfs.c | 2 | ||||
-rw-r--r-- | net/mac80211/rate.c | 12 | ||||
-rw-r--r-- | net/mac80211/rate.h | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 29 | ||||
-rw-r--r-- | net/mac80211/tx.c | 3 |
5 files changed, 42 insertions, 13 deletions
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", | |||
52 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", | 52 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", |
53 | local->wep_iv & 0xffffff); | 53 | local->wep_iv & 0xffffff); |
54 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | 54 | DEBUGFS_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 | ||
57 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | 57 | static 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, | |||
148 | static void __sta_info_free(struct ieee80211_local *local, | 148 | static 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 | ||
282 | static 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 | |||
280 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 299 | struct 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); |