aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);