mac80211: make simple rate control algorithm built-in
[linux-2.6] / net / mac80211 / ieee80211_rate.c
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
11 #include <linux/kernel.h>
12 #include <linux/rtnetlink.h>
13 #include "ieee80211_rate.h"
14 #include "ieee80211_i.h"
15
16 struct rate_control_alg {
17         struct list_head list;
18         struct rate_control_ops *ops;
19 };
20
21 static LIST_HEAD(rate_ctrl_algs);
22 static DEFINE_MUTEX(rate_ctrl_mutex);
23
24 int ieee80211_rate_control_register(struct rate_control_ops *ops)
25 {
26         struct rate_control_alg *alg;
27
28         if (!ops->name)
29                 return -EINVAL;
30
31         alg = kzalloc(sizeof(*alg), GFP_KERNEL);
32         if (alg == NULL) {
33                 return -ENOMEM;
34         }
35         alg->ops = ops;
36
37         mutex_lock(&rate_ctrl_mutex);
38         list_add_tail(&alg->list, &rate_ctrl_algs);
39         mutex_unlock(&rate_ctrl_mutex);
40
41         return 0;
42 }
43 EXPORT_SYMBOL(ieee80211_rate_control_register);
44
45 void ieee80211_rate_control_unregister(struct rate_control_ops *ops)
46 {
47         struct rate_control_alg *alg;
48
49         mutex_lock(&rate_ctrl_mutex);
50         list_for_each_entry(alg, &rate_ctrl_algs, list) {
51                 if (alg->ops == ops) {
52                         list_del(&alg->list);
53                         break;
54                 }
55         }
56         mutex_unlock(&rate_ctrl_mutex);
57         kfree(alg);
58 }
59 EXPORT_SYMBOL(ieee80211_rate_control_unregister);
60
61 static struct rate_control_ops *
62 ieee80211_try_rate_control_ops_get(const char *name)
63 {
64         struct rate_control_alg *alg;
65         struct rate_control_ops *ops = NULL;
66
67         if (!name)
68                 return NULL;
69
70         mutex_lock(&rate_ctrl_mutex);
71         list_for_each_entry(alg, &rate_ctrl_algs, list) {
72                 if (!strcmp(alg->ops->name, name))
73                         if (try_module_get(alg->ops->module)) {
74                                 ops = alg->ops;
75                                 break;
76                         }
77         }
78         mutex_unlock(&rate_ctrl_mutex);
79         return ops;
80 }
81
82 /* Get the rate control algorithm. If `name' is NULL, get the first
83  * available algorithm. */
84 static struct rate_control_ops *
85 ieee80211_rate_control_ops_get(const char *name)
86 {
87         struct rate_control_ops *ops;
88
89         if (!name)
90                 name = "simple";
91
92         ops = ieee80211_try_rate_control_ops_get(name);
93         if (!ops) {
94                 request_module("rc80211_%s", name);
95                 ops = ieee80211_try_rate_control_ops_get(name);
96         }
97         return ops;
98 }
99
100 static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops)
101 {
102         module_put(ops->module);
103 }
104
105 struct rate_control_ref *rate_control_alloc(const char *name,
106                                             struct ieee80211_local *local)
107 {
108         struct rate_control_ref *ref;
109
110         ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL);
111         if (!ref)
112                 goto fail_ref;
113         kref_init(&ref->kref);
114         ref->ops = ieee80211_rate_control_ops_get(name);
115         if (!ref->ops)
116                 goto fail_ops;
117         ref->priv = ref->ops->alloc(local);
118         if (!ref->priv)
119                 goto fail_priv;
120         return ref;
121
122 fail_priv:
123         ieee80211_rate_control_ops_put(ref->ops);
124 fail_ops:
125         kfree(ref);
126 fail_ref:
127         return NULL;
128 }
129
130 static void rate_control_release(struct kref *kref)
131 {
132         struct rate_control_ref *ctrl_ref;
133
134         ctrl_ref = container_of(kref, struct rate_control_ref, kref);
135         ctrl_ref->ops->free(ctrl_ref->priv);
136         ieee80211_rate_control_ops_put(ctrl_ref->ops);
137         kfree(ctrl_ref);
138 }
139
140 struct rate_control_ref *rate_control_get(struct rate_control_ref *ref)
141 {
142         kref_get(&ref->kref);
143         return ref;
144 }
145
146 void rate_control_put(struct rate_control_ref *ref)
147 {
148         kref_put(&ref->kref, rate_control_release);
149 }
150
151 int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
152                                  const char *name)
153 {
154         struct rate_control_ref *ref, *old;
155
156         ASSERT_RTNL();
157         if (local->open_count || netif_running(local->mdev))
158                 return -EBUSY;
159
160         ref = rate_control_alloc(name, local);
161         if (!ref) {
162                 printk(KERN_WARNING "%s: Failed to select rate control "
163                        "algorithm\n", wiphy_name(local->hw.wiphy));
164                 return -ENOENT;
165         }
166
167         old = local->rate_ctrl;
168         local->rate_ctrl = ref;
169         if (old) {
170                 rate_control_put(old);
171                 sta_info_flush(local, NULL);
172         }
173
174         printk(KERN_DEBUG "%s: Selected rate control "
175                "algorithm '%s'\n", wiphy_name(local->hw.wiphy),
176                ref->ops->name);
177
178
179         return 0;
180 }
181
182 void rate_control_deinitialize(struct ieee80211_local *local)
183 {
184         struct rate_control_ref *ref;
185
186         ref = local->rate_ctrl;
187         local->rate_ctrl = NULL;
188         rate_control_put(ref);
189 }