Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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