ieee80211_rate.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright 2002-2005, Instant802 Networks, Inc.
  3. * Copyright 2005-2006, Devicescape Software, Inc.
  4. * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/rtnetlink.h>
  12. #include "ieee80211_rate.h"
  13. #include "ieee80211_i.h"
  14. struct rate_control_alg {
  15. struct list_head list;
  16. struct rate_control_ops *ops;
  17. };
  18. static LIST_HEAD(rate_ctrl_algs);
  19. static DEFINE_MUTEX(rate_ctrl_mutex);
  20. int ieee80211_rate_control_register(struct rate_control_ops *ops)
  21. {
  22. struct rate_control_alg *alg;
  23. if (!ops->name)
  24. return -EINVAL;
  25. mutex_lock(&rate_ctrl_mutex);
  26. list_for_each_entry(alg, &rate_ctrl_algs, list) {
  27. if (!strcmp(alg->ops->name, ops->name)) {
  28. /* don't register an algorithm twice */
  29. WARN_ON(1);
  30. return -EALREADY;
  31. }
  32. }
  33. alg = kzalloc(sizeof(*alg), GFP_KERNEL);
  34. if (alg == NULL) {
  35. mutex_unlock(&rate_ctrl_mutex);
  36. return -ENOMEM;
  37. }
  38. alg->ops = ops;
  39. list_add_tail(&alg->list, &rate_ctrl_algs);
  40. mutex_unlock(&rate_ctrl_mutex);
  41. return 0;
  42. }
  43. EXPORT_SYMBOL(ieee80211_rate_control_register);
  44. void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
  45. {
  46. struct rate_control_alg *alg;
  47. mutex_lock(&rate_ctrl_mutex);
  48. list_for_each_entry(alg, &rate_ctrl_algs, list) {
  49. if (alg->ops == ops) {
  50. list_del(&alg->list);
  51. break;
  52. }
  53. }
  54. mutex_unlock(&rate_ctrl_mutex);
  55. kfree(alg);
  56. }
  57. EXPORT_SYMBOL(ieee80211_rate_control_unregister);
  58. static struct rate_control_ops *
  59. ieee80211_try_rate_control_ops_get(const char *name)
  60. {
  61. struct rate_control_alg *alg;
  62. struct rate_control_ops *ops = NULL;
  63. if (!name)
  64. return NULL;
  65. mutex_lock(&rate_ctrl_mutex);
  66. list_for_each_entry(alg, &rate_ctrl_algs, list) {
  67. if (!strcmp(alg->ops->name, name))
  68. if (try_module_get(alg->ops->module)) {
  69. ops = alg->ops;
  70. break;
  71. }
  72. }
  73. mutex_unlock(&rate_ctrl_mutex);
  74. return ops;
  75. }
  76. /* Get the rate control algorithm. If `name' is NULL, get the first
  77. * available algorithm. */
  78. static struct rate_control_ops *
  79. ieee80211_rate_control_ops_get(const char *name)
  80. {
  81. struct rate_control_ops *ops;
  82. if (!name)
  83. name = "simple";
  84. ops = ieee80211_try_rate_control_ops_get(name);
  85. if (!ops) {
  86. request_module("rc80211_%s", name);
  87. ops = ieee80211_try_rate_control_ops_get(name);
  88. }
  89. return ops;
  90. }
  91. static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
  92. {
  93. module_put(ops->module);
  94. }
  95. struct rate_control_ref *rate_control_alloc(const char *name,
  96. struct ieee80211_local *local)
  97. {
  98. struct rate_control_ref *ref;
  99. ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
  100. if (!ref)
  101. goto fail_ref;
  102. kref_init(&ref->kref);
  103. ref->ops = ieee80211_rate_control_ops_get(name);
  104. if (!ref->ops)
  105. goto fail_ops;
  106. ref->priv = ref->ops->alloc(local);
  107. if (!ref->priv)
  108. goto fail_priv;
  109. return ref;
  110. fail_priv:
  111. ieee80211_rate_control_ops_put(ref->ops);
  112. fail_ops:
  113. kfree(ref);
  114. fail_ref:
  115. return NULL;
  116. }
  117. static void rate_control_release(struct kref *kref)
  118. {
  119. struct rate_control_ref *ctrl_ref;
  120. ctrl_ref = container_of(kref, struct rate_control_ref, kref);
  121. ctrl_ref->ops->free(ctrl_ref->priv);
  122. ieee80211_rate_control_ops_put(ctrl_ref->ops);
  123. kfree(ctrl_ref);
  124. }
  125. struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
  126. {
  127. kref_get(&ref->kref);
  128. return ref;
  129. }
  130. void rate_control_put(struct rate_control_ref *ref)
  131. {
  132. kref_put(&ref->kref, rate_control_release);
  133. }
  134. int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
  135. const char *name)
  136. {
  137. struct rate_control_ref *ref, *old;
  138. ASSERT_RTNL();
  139. if (local->open_count || netif_running(local->mdev))
  140. return -EBUSY;
  141. ref = rate_control_alloc(name, local);
  142. if (!ref) {
  143. printk(KERN_WARNING "%s: Failed to select rate control "
  144. "algorithm\n", wiphy_name(local->hw.wiphy));
  145. return -ENOENT;
  146. }
  147. old = local->rate_ctrl;
  148. local->rate_ctrl = ref;
  149. if (old) {
  150. rate_control_put(old);
  151. sta_info_flush(local, NULL);
  152. }
  153. printk(KERN_DEBUG "%s: Selected rate control "
  154. "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
  155. ref->ops->name);
  156. return 0;
  157. }
  158. void rate_control_deinitialize(struct ieee80211_local *local)
  159. {
  160. struct rate_control_ref *ref;
  161. ref = local->rate_ctrl;
  162. local->rate_ctrl = NULL;
  163. rate_control_put(ref);
  164. }