rate.c revision 2c8dccc77420fb7433da5674818959d3499d35be
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 "rate.h" 14#include "ieee80211_i.h" 15 16struct rate_control_alg { 17 struct list_head list; 18 struct rate_control_ops *ops; 19}; 20 21static LIST_HEAD(rate_ctrl_algs); 22static DEFINE_MUTEX(rate_ctrl_mutex); 23 24static char *ieee80211_default_rc_algo = CONFIG_MAC80211_RC_DEFAULT; 25module_param(ieee80211_default_rc_algo, charp, 0644); 26MODULE_PARM_DESC(ieee80211_default_rc_algo, 27 "Default rate control algorithm for mac80211 to use"); 28 29int ieee80211_rate_control_register(struct rate_control_ops *ops) 30{ 31 struct rate_control_alg *alg; 32 33 if (!ops->name) 34 return -EINVAL; 35 36 mutex_lock(&rate_ctrl_mutex); 37 list_for_each_entry(alg, &rate_ctrl_algs, list) { 38 if (!strcmp(alg->ops->name, ops->name)) { 39 /* don't register an algorithm twice */ 40 WARN_ON(1); 41 mutex_unlock(&rate_ctrl_mutex); 42 return -EALREADY; 43 } 44 } 45 46 alg = kzalloc(sizeof(*alg), GFP_KERNEL); 47 if (alg == NULL) { 48 mutex_unlock(&rate_ctrl_mutex); 49 return -ENOMEM; 50 } 51 alg->ops = ops; 52 53 list_add_tail(&alg->list, &rate_ctrl_algs); 54 mutex_unlock(&rate_ctrl_mutex); 55 56 return 0; 57} 58EXPORT_SYMBOL(ieee80211_rate_control_register); 59 60void ieee80211_rate_control_unregister(struct rate_control_ops *ops) 61{ 62 struct rate_control_alg *alg; 63 64 mutex_lock(&rate_ctrl_mutex); 65 list_for_each_entry(alg, &rate_ctrl_algs, list) { 66 if (alg->ops == ops) { 67 list_del(&alg->list); 68 kfree(alg); 69 break; 70 } 71 } 72 mutex_unlock(&rate_ctrl_mutex); 73} 74EXPORT_SYMBOL(ieee80211_rate_control_unregister); 75 76static struct rate_control_ops * 77ieee80211_try_rate_control_ops_get(const char *name) 78{ 79 struct rate_control_alg *alg; 80 struct rate_control_ops *ops = NULL; 81 82 if (!name) 83 return NULL; 84 85 mutex_lock(&rate_ctrl_mutex); 86 list_for_each_entry(alg, &rate_ctrl_algs, list) { 87 if (!strcmp(alg->ops->name, name)) 88 if (try_module_get(alg->ops->module)) { 89 ops = alg->ops; 90 break; 91 } 92 } 93 mutex_unlock(&rate_ctrl_mutex); 94 return ops; 95} 96 97/* Get the rate control algorithm. */ 98static struct rate_control_ops * 99ieee80211_rate_control_ops_get(const char *name) 100{ 101 struct rate_control_ops *ops; 102 const char *alg_name; 103 104 if (!name) 105 alg_name = ieee80211_default_rc_algo; 106 else 107 alg_name = name; 108 109 ops = ieee80211_try_rate_control_ops_get(alg_name); 110 if (!ops) { 111 request_module("rc80211_%s", alg_name); 112 ops = ieee80211_try_rate_control_ops_get(alg_name); 113 } 114 if (!ops && name) 115 /* try default if specific alg requested but not found */ 116 ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); 117 118 /* try built-in one if specific alg requested but not found */ 119 if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) 120 ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); 121 122 return ops; 123} 124 125static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) 126{ 127 module_put(ops->module); 128} 129 130struct rate_control_ref *rate_control_alloc(const char *name, 131 struct ieee80211_local *local) 132{ 133 struct rate_control_ref *ref; 134 135 ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); 136 if (!ref) 137 goto fail_ref; 138 kref_init(&ref->kref); 139 ref->ops = ieee80211_rate_control_ops_get(name); 140 if (!ref->ops) 141 goto fail_ops; 142 ref->priv = ref->ops->alloc(local); 143 if (!ref->priv) 144 goto fail_priv; 145 return ref; 146 147fail_priv: 148 ieee80211_rate_control_ops_put(ref->ops); 149fail_ops: 150 kfree(ref); 151fail_ref: 152 return NULL; 153} 154 155static void rate_control_release(struct kref *kref) 156{ 157 struct rate_control_ref *ctrl_ref; 158 159 ctrl_ref = container_of(kref, struct rate_control_ref, kref); 160 ctrl_ref->ops->free(ctrl_ref->priv); 161 ieee80211_rate_control_ops_put(ctrl_ref->ops); 162 kfree(ctrl_ref); 163} 164 165void rate_control_get_rate(struct net_device *dev, 166 struct ieee80211_supported_band *sband, 167 struct sk_buff *skb, 168 struct rate_selection *sel) 169{ 170 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 171 struct rate_control_ref *ref = local->rate_ctrl; 172 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 173 struct sta_info *sta; 174 int i; 175 176 rcu_read_lock(); 177 sta = sta_info_get(local, hdr->addr1); 178 179 memset(sel, 0, sizeof(struct rate_selection)); 180 181 ref->ops->get_rate(ref->priv, dev, sband, skb, sel); 182 183 /* Select a non-ERP backup rate. */ 184 if (!sel->nonerp) { 185 for (i = 0; i < sband->n_bitrates; i++) { 186 struct ieee80211_rate *rate = &sband->bitrates[i]; 187 if (sel->rate->bitrate < rate->bitrate) 188 break; 189 190 if (rate_supported(sta, sband->band, i) && 191 !(rate->flags & IEEE80211_RATE_ERP_G)) 192 sel->nonerp = rate; 193 } 194 } 195 196 rcu_read_unlock(); 197} 198 199struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) 200{ 201 kref_get(&ref->kref); 202 return ref; 203} 204 205void rate_control_put(struct rate_control_ref *ref) 206{ 207 kref_put(&ref->kref, rate_control_release); 208} 209 210int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, 211 const char *name) 212{ 213 struct rate_control_ref *ref, *old; 214 215 ASSERT_RTNL(); 216 if (local->open_count || netif_running(local->mdev)) 217 return -EBUSY; 218 219 ref = rate_control_alloc(name, local); 220 if (!ref) { 221 printk(KERN_WARNING "%s: Failed to select rate control " 222 "algorithm\n", wiphy_name(local->hw.wiphy)); 223 return -ENOENT; 224 } 225 226 old = local->rate_ctrl; 227 local->rate_ctrl = ref; 228 if (old) { 229 rate_control_put(old); 230 sta_info_flush(local, NULL); 231 } 232 233 printk(KERN_DEBUG "%s: Selected rate control " 234 "algorithm '%s'\n", wiphy_name(local->hw.wiphy), 235 ref->ops->name); 236 237 238 return 0; 239} 240 241void rate_control_deinitialize(struct ieee80211_local *local) 242{ 243 struct rate_control_ref *ref; 244 245 ref = local->rate_ctrl; 246 local->rate_ctrl = NULL; 247 rate_control_put(ref); 248} 249 250