diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-09-18 12:14:18 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-09-24 16:18:03 -0400 |
commit | 4b7679a561e552eeda1e3567119bef2bca99b66e (patch) | |
tree | b5f2b45c9186eb954f9329322d07e277e669b422 /net/mac80211/rc80211_pid_algo.c | |
parent | 2ff6a6d4e92270283432690adf53a7e5ab186d19 (diff) |
mac80211: clean up rate control API
Long awaited, hard work. This patch totally cleans up the rate control
API to remove the requirement to include internal headers outside of
net/mac80211/.
There's one internal use in the PID algorithm left for mesh networking,
we'll have to figure out a way to clean that one up and decide how to
do the peer link evaluation, possibly independent of the rate control
algorithm or via new API.
Additionally, ath9k is left using the cross-inclusion hack for now, we
will add new API where necessary to make this work properly, but right
now I'm not expert enough to do it. It's still off better than before.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rc80211_pid_algo.c')
-rw-r--r-- | net/mac80211/rc80211_pid_algo.c | 158 |
1 files changed, 59 insertions, 99 deletions
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa1..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -68,18 +68,14 @@ | |||
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct sta_info *sta, int adj, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | ||
73 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
74 | { | 75 | { |
75 | struct ieee80211_sub_if_data *sdata; | ||
76 | struct ieee80211_supported_band *sband; | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
79 | int cur = spinfo->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
80 | 78 | ||
81 | sdata = sta->sdata; | ||
82 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
83 | band = sband->band; | 79 | band = sband->band; |
84 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
85 | 81 | ||
@@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | |||
146 | } | 142 | } |
147 | 143 | ||
148 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
149 | struct ieee80211_local *local, | 145 | struct ieee80211_supported_band *sband, |
150 | struct sta_info *sta) | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | ||
151 | { | 148 | { |
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
153 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
154 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
155 | struct ieee80211_supported_band *sband; | ||
156 | u32 pf; | 150 | u32 pf; |
157 | s32 err_avg; | 151 | s32 err_avg; |
158 | u32 err_prop; | 152 | u32 err_prop; |
@@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
161 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
162 | unsigned long period; | 156 | unsigned long period; |
163 | 157 | ||
164 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
165 | spinfo = sta->rate_ctrl_priv; | ||
166 | |||
167 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
168 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
169 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
179 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
180 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
181 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
182 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
183 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) | 177 | |
184 | mesh_plink_broken(sta); | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
179 | mesh_plink_broken(si); | ||
185 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
186 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
187 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
188 | } | 183 | } |
189 | 184 | ||
@@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
229 | 224 | ||
230 | /* Change rate. */ | 225 | /* Change rate. */ |
231 | if (adj) | 226 | if (adj) |
232 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
233 | } | 228 | } |
234 | 229 | ||
235 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | ||
236 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
237 | { | 233 | { |
238 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
239 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
240 | struct ieee80211_sub_if_data *sdata; | ||
241 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
242 | struct sta_info *sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
243 | struct rc_pid_sta_info *spinfo; | ||
244 | unsigned long period; | 236 | unsigned long period; |
245 | struct ieee80211_supported_band *sband; | ||
246 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
247 | 238 | ||
248 | rcu_read_lock(); | 239 | if (!spinfo) |
249 | 240 | return; | |
250 | sta = sta_info_get(local, hdr->addr1); | ||
251 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
252 | |||
253 | if (!sta) | ||
254 | goto unlock; | ||
255 | |||
256 | spinfo = sta->rate_ctrl_priv; | ||
257 | |||
258 | /* Don't update the state if we're not controlling the rate. */ | ||
259 | sdata = sta->sdata; | ||
260 | if (sdata->force_unicast_rateidx > -1) { | ||
261 | spinfo->txrate_idx = sdata->max_ratectrl_rateidx; | ||
262 | goto unlock; | ||
263 | } | ||
264 | 241 | ||
265 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
266 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
267 | if (info->tx_rate_idx != spinfo->txrate_idx) | 244 | if (info->tx_rate_idx != spinfo->txrate_idx) |
268 | goto unlock; | 245 | return; |
269 | 246 | ||
270 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
271 | 248 | ||
@@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
289 | if (!period) | 266 | if (!period) |
290 | period = 1; | 267 | period = 1; |
291 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
292 | rate_control_pid_sample(pinfo, local, sta); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
293 | |||
294 | unlock: | ||
295 | rcu_read_unlock(); | ||
296 | } | 270 | } |
297 | 271 | ||
298 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | 272 | static void |
299 | struct ieee80211_supported_band *sband, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, |
300 | struct sk_buff *skb, | 274 | struct ieee80211_sta *sta, void *priv_sta, |
301 | struct rate_selection *sel) | 275 | struct sk_buff *skb, |
276 | struct rate_selection *sel) | ||
302 | { | 277 | { |
303 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
305 | struct ieee80211_sub_if_data *sdata; | 279 | struct rc_pid_sta_info *spinfo = priv_sta; |
306 | struct rc_pid_sta_info *spinfo; | ||
307 | struct sta_info *sta; | ||
308 | int rateidx; | 280 | int rateidx; |
309 | u16 fc; | 281 | u16 fc; |
310 | 282 | ||
311 | rcu_read_lock(); | ||
312 | |||
313 | sta = sta_info_get(local, hdr->addr1); | ||
314 | |||
315 | /* Send management frames and broadcast/multicast data using lowest | 283 | /* Send management frames and broadcast/multicast data using lowest |
316 | * rate. */ | 284 | * rate. */ |
317 | fc = le16_to_cpu(hdr->frame_control); | 285 | fc = le16_to_cpu(hdr->frame_control); |
318 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 286 | if (!sta || !spinfo || |
319 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 287 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
320 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 288 | is_multicast_ether_addr(hdr->addr1)) { |
321 | rcu_read_unlock(); | 289 | sel->rate_idx = rate_lowest_index(sband, sta); |
322 | return; | 290 | return; |
323 | } | 291 | } |
324 | 292 | ||
325 | /* If a forced rate is in effect, select it. */ | ||
326 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
327 | spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; | ||
328 | if (sdata->force_unicast_rateidx > -1) | ||
329 | spinfo->txrate_idx = sdata->force_unicast_rateidx; | ||
330 | |||
331 | rateidx = spinfo->txrate_idx; | 293 | rateidx = spinfo->txrate_idx; |
332 | 294 | ||
333 | if (rateidx >= sband->n_bitrates) | 295 | if (rateidx >= sband->n_bitrates) |
334 | rateidx = sband->n_bitrates - 1; | 296 | rateidx = sband->n_bitrates - 1; |
335 | 297 | ||
336 | rcu_read_unlock(); | ||
337 | |||
338 | sel->rate_idx = rateidx; | 298 | sel->rate_idx = rateidx; |
339 | 299 | ||
340 | #ifdef CONFIG_MAC80211_DEBUGFS | 300 | #ifdef CONFIG_MAC80211_DEBUGFS |
341 | rate_control_pid_event_tx_rate( | 301 | rate_control_pid_event_tx_rate(&spinfo->events, |
342 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
343 | rateidx, sband->bitrates[rateidx].bitrate); | 302 | rateidx, sband->bitrates[rateidx].bitrate); |
344 | #endif | 303 | #endif |
345 | } | 304 | } |
346 | 305 | ||
347 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | 306 | static void |
348 | struct ieee80211_local *local, | 307 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
349 | struct sta_info *sta) | 308 | struct ieee80211_sta *sta, void *priv_sta) |
350 | { | 309 | { |
310 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
311 | struct sta_info *si; | ||
312 | |||
351 | /* TODO: This routine should consider using RSSI from previous packets | 313 | /* TODO: This routine should consider using RSSI from previous packets |
352 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 314 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
353 | * Until that method is implemented, we will use the lowest supported | 315 | * Until that method is implemented, we will use the lowest supported |
354 | * rate as a workaround. */ | 316 | * rate as a workaround. */ |
355 | struct ieee80211_supported_band *sband; | ||
356 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
357 | 317 | ||
358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 318 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
359 | spinfo->txrate_idx = rate_lowest_index(local, sband, sta); | 319 | /* HACK */ |
360 | sta->fail_avg = 0; | 320 | si = container_of(sta, struct sta_info, sta); |
321 | si->fail_avg = 0; | ||
361 | } | 322 | } |
362 | 323 | ||
363 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | 324 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
325 | struct dentry *debugfsdir) | ||
364 | { | 326 | { |
365 | struct rc_pid_info *pinfo; | 327 | struct rc_pid_info *pinfo; |
366 | struct rc_pid_rateinfo *rinfo; | 328 | struct rc_pid_rateinfo *rinfo; |
@@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
371 | struct rc_pid_debugfs_entries *de; | 333 | struct rc_pid_debugfs_entries *de; |
372 | #endif | 334 | #endif |
373 | 335 | ||
374 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 336 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
375 | 337 | ||
376 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 338 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
377 | if (!pinfo) | 339 | if (!pinfo) |
@@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
426 | 388 | ||
427 | #ifdef CONFIG_MAC80211_DEBUGFS | 389 | #ifdef CONFIG_MAC80211_DEBUGFS |
428 | de = &pinfo->dentries; | 390 | de = &pinfo->dentries; |
429 | de->dir = debugfs_create_dir("rc80211_pid", | ||
430 | local->hw.wiphy->debugfsdir); | ||
431 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 391 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
432 | de->dir, &pinfo->target); | 392 | debugfsdir, &pinfo->target); |
433 | de->sampling_period = debugfs_create_u32("sampling_period", | 393 | de->sampling_period = debugfs_create_u32("sampling_period", |
434 | S_IRUSR | S_IWUSR, de->dir, | 394 | S_IRUSR | S_IWUSR, debugfsdir, |
435 | &pinfo->sampling_period); | 395 | &pinfo->sampling_period); |
436 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 396 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
437 | de->dir, &pinfo->coeff_p); | 397 | debugfsdir, &pinfo->coeff_p); |
438 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 398 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
439 | de->dir, &pinfo->coeff_i); | 399 | debugfsdir, &pinfo->coeff_i); |
440 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 400 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
441 | de->dir, &pinfo->coeff_d); | 401 | debugfsdir, &pinfo->coeff_d); |
442 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 402 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
443 | S_IRUSR | S_IWUSR, de->dir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
444 | &pinfo->smoothing_shift); | 404 | &pinfo->smoothing_shift); |
445 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 405 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
446 | S_IRUSR | S_IWUSR, de->dir, | 406 | S_IRUSR | S_IWUSR, debugfsdir, |
447 | &pinfo->sharpen_factor); | 407 | &pinfo->sharpen_factor); |
448 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 408 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
449 | S_IRUSR | S_IWUSR, de->dir, | 409 | S_IRUSR | S_IWUSR, debugfsdir, |
450 | &pinfo->sharpen_duration); | 410 | &pinfo->sharpen_duration); |
451 | de->norm_offset = debugfs_create_u32("norm_offset", | 411 | de->norm_offset = debugfs_create_u32("norm_offset", |
452 | S_IRUSR | S_IWUSR, de->dir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
453 | &pinfo->norm_offset); | 413 | &pinfo->norm_offset); |
454 | #endif | 414 | #endif |
455 | 415 | ||
@@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) | |||
471 | debugfs_remove(de->coeff_p); | 431 | debugfs_remove(de->coeff_p); |
472 | debugfs_remove(de->sampling_period); | 432 | debugfs_remove(de->sampling_period); |
473 | debugfs_remove(de->target); | 433 | debugfs_remove(de->target); |
474 | debugfs_remove(de->dir); | ||
475 | #endif | 434 | #endif |
476 | 435 | ||
477 | kfree(pinfo->rinfo); | 436 | kfree(pinfo->rinfo); |
@@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) | |||
482 | { | 441 | { |
483 | } | 442 | } |
484 | 443 | ||
485 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | 444 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
445 | gfp_t gfp) | ||
486 | { | 446 | { |
487 | struct rc_pid_sta_info *spinfo; | 447 | struct rc_pid_sta_info *spinfo; |
488 | 448 | ||
@@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | |||
500 | return spinfo; | 460 | return spinfo; |
501 | } | 461 | } |
502 | 462 | ||
503 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | 463 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
464 | void *priv_sta) | ||
504 | { | 465 | { |
505 | struct rc_pid_sta_info *spinfo = priv_sta; | 466 | kfree(priv_sta); |
506 | kfree(spinfo); | ||
507 | } | 467 | } |
508 | 468 | ||
509 | static struct rate_control_ops mac80211_rcpid = { | 469 | static struct rate_control_ops mac80211_rcpid = { |