diff options
-rw-r--r-- | include/net/mac80211.h | 14 | ||||
-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 |
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 | */ |
915 | enum ieee80211_hw_flags { | 928 | enum 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", | |||
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); |