diff options
author | Jouni Malinen <j@w1.fi> | 2009-04-20 12:39:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-04-22 16:57:17 -0400 |
commit | b9a5f8cab751d362f7c2d94899ca788c22fcd1ef (patch) | |
tree | e769e2f59ef845cf7c7cc93b64d33eeed49bb9f7 /net/wireless | |
parent | 9e52b0623c6eb49c3f23a326c1fb97bdecc49ba1 (diff) |
nl80211: Add set/get for frag/rts threshold and retry limits
Add new nl80211 attributes that can be used with NL80211_CMD_SET_WIPHY
and NL80211_CMD_GET_WIPHY to manage fragmentation/RTS threshold and
retry limits.
Since these values are stored in struct wiphy, remove the local copy
from mac80211 where feasible (frag & rts threshold). The retry limits
are currently needed in struct ieee80211_conf, but these could be
eventually removed since the driver should have access to the values
in struct wiphy.
Signed-off-by: Jouni Malinen <j@w1.fi>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.c | 10 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 95 | ||||
-rw-r--r-- | net/wireless/wext-compat.c | 151 |
3 files changed, 256 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 827a56263551..f256b4f7e833 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -273,6 +273,16 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
273 | drv->wiphy.dev.class = &ieee80211_class; | 273 | drv->wiphy.dev.class = &ieee80211_class; |
274 | drv->wiphy.dev.platform_data = drv; | 274 | drv->wiphy.dev.platform_data = drv; |
275 | 275 | ||
276 | /* | ||
277 | * Initialize wiphy parameters to IEEE 802.11 MIB default values. | ||
278 | * Fragmentation and RTS threshold are disabled by default with the | ||
279 | * special -1 value. | ||
280 | */ | ||
281 | drv->wiphy.retry_short = 7; | ||
282 | drv->wiphy.retry_long = 4; | ||
283 | drv->wiphy.frag_threshold = (u32) -1; | ||
284 | drv->wiphy.rts_threshold = (u32) -1; | ||
285 | |||
276 | return &drv->wiphy; | 286 | return &drv->wiphy; |
277 | } | 287 | } |
278 | EXPORT_SYMBOL(wiphy_new); | 288 | EXPORT_SYMBOL(wiphy_new); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 16f86356ac97..5a9a5c6c71db 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -61,6 +61,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
64 | [NL80211_ATTR_WIPHY_RETRY_SHORT] = { .type = NLA_U8 }, | ||
65 | [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, | ||
66 | [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, | ||
67 | [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, | ||
64 | 68 | ||
65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 69 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 70 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -204,6 +208,16 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
204 | 208 | ||
205 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); | 209 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); |
206 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); | 210 | NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); |
211 | |||
212 | NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, | ||
213 | dev->wiphy.retry_short); | ||
214 | NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, | ||
215 | dev->wiphy.retry_long); | ||
216 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, | ||
217 | dev->wiphy.frag_threshold); | ||
218 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, | ||
219 | dev->wiphy.rts_threshold); | ||
220 | |||
207 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, | 221 | NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, |
208 | dev->wiphy.max_scan_ssids); | 222 | dev->wiphy.max_scan_ssids); |
209 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, | 223 | NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, |
@@ -416,6 +430,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
416 | struct cfg80211_registered_device *rdev; | 430 | struct cfg80211_registered_device *rdev; |
417 | int result = 0, rem_txq_params = 0; | 431 | int result = 0, rem_txq_params = 0; |
418 | struct nlattr *nl_txq_params; | 432 | struct nlattr *nl_txq_params; |
433 | u32 changed; | ||
434 | u8 retry_short = 0, retry_long = 0; | ||
435 | u32 frag_threshold = 0, rts_threshold = 0; | ||
419 | 436 | ||
420 | rtnl_lock(); | 437 | rtnl_lock(); |
421 | 438 | ||
@@ -530,6 +547,84 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
530 | goto bad_res; | 547 | goto bad_res; |
531 | } | 548 | } |
532 | 549 | ||
550 | changed = 0; | ||
551 | |||
552 | if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) { | ||
553 | retry_short = nla_get_u8( | ||
554 | info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]); | ||
555 | if (retry_short == 0) { | ||
556 | result = -EINVAL; | ||
557 | goto bad_res; | ||
558 | } | ||
559 | changed |= WIPHY_PARAM_RETRY_SHORT; | ||
560 | } | ||
561 | |||
562 | if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) { | ||
563 | retry_long = nla_get_u8( | ||
564 | info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]); | ||
565 | if (retry_long == 0) { | ||
566 | result = -EINVAL; | ||
567 | goto bad_res; | ||
568 | } | ||
569 | changed |= WIPHY_PARAM_RETRY_LONG; | ||
570 | } | ||
571 | |||
572 | if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { | ||
573 | frag_threshold = nla_get_u32( | ||
574 | info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); | ||
575 | if (frag_threshold < 256) { | ||
576 | result = -EINVAL; | ||
577 | goto bad_res; | ||
578 | } | ||
579 | if (frag_threshold != (u32) -1) { | ||
580 | /* | ||
581 | * Fragments (apart from the last one) are required to | ||
582 | * have even length. Make the fragmentation code | ||
583 | * simpler by stripping LSB should someone try to use | ||
584 | * odd threshold value. | ||
585 | */ | ||
586 | frag_threshold &= ~0x1; | ||
587 | } | ||
588 | changed |= WIPHY_PARAM_FRAG_THRESHOLD; | ||
589 | } | ||
590 | |||
591 | if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) { | ||
592 | rts_threshold = nla_get_u32( | ||
593 | info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]); | ||
594 | changed |= WIPHY_PARAM_RTS_THRESHOLD; | ||
595 | } | ||
596 | |||
597 | if (changed) { | ||
598 | u8 old_retry_short, old_retry_long; | ||
599 | u32 old_frag_threshold, old_rts_threshold; | ||
600 | |||
601 | if (!rdev->ops->set_wiphy_params) { | ||
602 | result = -EOPNOTSUPP; | ||
603 | goto bad_res; | ||
604 | } | ||
605 | |||
606 | old_retry_short = rdev->wiphy.retry_short; | ||
607 | old_retry_long = rdev->wiphy.retry_long; | ||
608 | old_frag_threshold = rdev->wiphy.frag_threshold; | ||
609 | old_rts_threshold = rdev->wiphy.rts_threshold; | ||
610 | |||
611 | if (changed & WIPHY_PARAM_RETRY_SHORT) | ||
612 | rdev->wiphy.retry_short = retry_short; | ||
613 | if (changed & WIPHY_PARAM_RETRY_LONG) | ||
614 | rdev->wiphy.retry_long = retry_long; | ||
615 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | ||
616 | rdev->wiphy.frag_threshold = frag_threshold; | ||
617 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) | ||
618 | rdev->wiphy.rts_threshold = rts_threshold; | ||
619 | |||
620 | result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); | ||
621 | if (result) { | ||
622 | rdev->wiphy.retry_short = old_retry_short; | ||
623 | rdev->wiphy.retry_long = old_retry_long; | ||
624 | rdev->wiphy.frag_threshold = old_frag_threshold; | ||
625 | rdev->wiphy.rts_threshold = old_rts_threshold; | ||
626 | } | ||
627 | } | ||
533 | 628 | ||
534 | bad_res: | 629 | bad_res: |
535 | mutex_unlock(&rdev->mtx); | 630 | mutex_unlock(&rdev->mtx); |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 4e054ea9c0a0..3279e7f038dc 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -314,3 +314,154 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, | |||
314 | 314 | ||
315 | } | 315 | } |
316 | EXPORT_SYMBOL(cfg80211_wext_freq); | 316 | EXPORT_SYMBOL(cfg80211_wext_freq); |
317 | |||
318 | int cfg80211_wext_siwrts(struct net_device *dev, | ||
319 | struct iw_request_info *info, | ||
320 | struct iw_param *rts, char *extra) | ||
321 | { | ||
322 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
323 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
324 | u32 orts = wdev->wiphy->rts_threshold; | ||
325 | int err; | ||
326 | |||
327 | if (rts->disabled || !rts->fixed) | ||
328 | wdev->wiphy->rts_threshold = (u32) -1; | ||
329 | else if (rts->value < 0) | ||
330 | return -EINVAL; | ||
331 | else | ||
332 | wdev->wiphy->rts_threshold = rts->value; | ||
333 | |||
334 | err = rdev->ops->set_wiphy_params(wdev->wiphy, | ||
335 | WIPHY_PARAM_RTS_THRESHOLD); | ||
336 | if (err) | ||
337 | wdev->wiphy->rts_threshold = orts; | ||
338 | |||
339 | return err; | ||
340 | } | ||
341 | EXPORT_SYMBOL(cfg80211_wext_siwrts); | ||
342 | |||
343 | int cfg80211_wext_giwrts(struct net_device *dev, | ||
344 | struct iw_request_info *info, | ||
345 | struct iw_param *rts, char *extra) | ||
346 | { | ||
347 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
348 | |||
349 | rts->value = wdev->wiphy->rts_threshold; | ||
350 | rts->disabled = rts->value == (u32) -1; | ||
351 | rts->fixed = 1; | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | EXPORT_SYMBOL(cfg80211_wext_giwrts); | ||
356 | |||
357 | int cfg80211_wext_siwfrag(struct net_device *dev, | ||
358 | struct iw_request_info *info, | ||
359 | struct iw_param *frag, char *extra) | ||
360 | { | ||
361 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
362 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
363 | u32 ofrag = wdev->wiphy->frag_threshold; | ||
364 | int err; | ||
365 | |||
366 | if (frag->disabled || !frag->fixed) | ||
367 | wdev->wiphy->frag_threshold = (u32) -1; | ||
368 | else if (frag->value < 256) | ||
369 | return -EINVAL; | ||
370 | else { | ||
371 | /* Fragment length must be even, so strip LSB. */ | ||
372 | wdev->wiphy->frag_threshold = frag->value & ~0x1; | ||
373 | } | ||
374 | |||
375 | err = rdev->ops->set_wiphy_params(wdev->wiphy, | ||
376 | WIPHY_PARAM_FRAG_THRESHOLD); | ||
377 | if (err) | ||
378 | wdev->wiphy->frag_threshold = ofrag; | ||
379 | |||
380 | return err; | ||
381 | } | ||
382 | EXPORT_SYMBOL(cfg80211_wext_siwfrag); | ||
383 | |||
384 | int cfg80211_wext_giwfrag(struct net_device *dev, | ||
385 | struct iw_request_info *info, | ||
386 | struct iw_param *frag, char *extra) | ||
387 | { | ||
388 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
389 | |||
390 | frag->value = wdev->wiphy->frag_threshold; | ||
391 | frag->disabled = frag->value == (u32) -1; | ||
392 | frag->fixed = 1; | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | EXPORT_SYMBOL(cfg80211_wext_giwfrag); | ||
397 | |||
398 | int cfg80211_wext_siwretry(struct net_device *dev, | ||
399 | struct iw_request_info *info, | ||
400 | struct iw_param *retry, char *extra) | ||
401 | { | ||
402 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
403 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
404 | u32 changed = 0; | ||
405 | u8 olong = wdev->wiphy->retry_long; | ||
406 | u8 oshort = wdev->wiphy->retry_short; | ||
407 | int err; | ||
408 | |||
409 | if (retry->disabled || | ||
410 | (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) | ||
411 | return -EINVAL; | ||
412 | |||
413 | if (retry->flags & IW_RETRY_LONG) { | ||
414 | wdev->wiphy->retry_long = retry->value; | ||
415 | changed |= WIPHY_PARAM_RETRY_LONG; | ||
416 | } else if (retry->flags & IW_RETRY_SHORT) { | ||
417 | wdev->wiphy->retry_short = retry->value; | ||
418 | changed |= WIPHY_PARAM_RETRY_SHORT; | ||
419 | } else { | ||
420 | wdev->wiphy->retry_short = retry->value; | ||
421 | wdev->wiphy->retry_long = retry->value; | ||
422 | changed |= WIPHY_PARAM_RETRY_LONG; | ||
423 | changed |= WIPHY_PARAM_RETRY_SHORT; | ||
424 | } | ||
425 | |||
426 | if (!changed) | ||
427 | return 0; | ||
428 | |||
429 | err = rdev->ops->set_wiphy_params(wdev->wiphy, changed); | ||
430 | if (err) { | ||
431 | wdev->wiphy->retry_short = oshort; | ||
432 | wdev->wiphy->retry_long = olong; | ||
433 | } | ||
434 | |||
435 | return err; | ||
436 | } | ||
437 | EXPORT_SYMBOL(cfg80211_wext_siwretry); | ||
438 | |||
439 | int cfg80211_wext_giwretry(struct net_device *dev, | ||
440 | struct iw_request_info *info, | ||
441 | struct iw_param *retry, char *extra) | ||
442 | { | ||
443 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
444 | |||
445 | retry->disabled = 0; | ||
446 | |||
447 | if (retry->flags == 0 || (retry->flags & IW_RETRY_SHORT)) { | ||
448 | /* | ||
449 | * First return short value, iwconfig will ask long value | ||
450 | * later if needed | ||
451 | */ | ||
452 | retry->flags |= IW_RETRY_LIMIT; | ||
453 | retry->value = wdev->wiphy->retry_short; | ||
454 | if (wdev->wiphy->retry_long != wdev->wiphy->retry_short) | ||
455 | retry->flags |= IW_RETRY_LONG; | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | if (retry->flags & IW_RETRY_LONG) { | ||
461 | retry->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; | ||
462 | retry->value = wdev->wiphy->retry_long; | ||
463 | } | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | EXPORT_SYMBOL(cfg80211_wext_giwretry); | ||