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.23-rc4 139 lines 3.2 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 "ieee80211_rate.h" 13#include "ieee80211_i.h" 14 15struct rate_control_alg { 16 struct list_head list; 17 struct rate_control_ops *ops; 18}; 19 20static LIST_HEAD(rate_ctrl_algs); 21static DEFINE_MUTEX(rate_ctrl_mutex); 22 23int ieee80211_rate_control_register(struct rate_control_ops *ops) 24{ 25 struct rate_control_alg *alg; 26 27 alg = kzalloc(sizeof(*alg), GFP_KERNEL); 28 if (alg == NULL) { 29 return -ENOMEM; 30 } 31 alg->ops = ops; 32 33 mutex_lock(&rate_ctrl_mutex); 34 list_add_tail(&alg->list, &rate_ctrl_algs); 35 mutex_unlock(&rate_ctrl_mutex); 36 37 return 0; 38} 39EXPORT_SYMBOL(ieee80211_rate_control_register); 40 41void ieee80211_rate_control_unregister(struct rate_control_ops *ops) 42{ 43 struct rate_control_alg *alg; 44 45 mutex_lock(&rate_ctrl_mutex); 46 list_for_each_entry(alg, &rate_ctrl_algs, list) { 47 if (alg->ops == ops) { 48 list_del(&alg->list); 49 break; 50 } 51 } 52 mutex_unlock(&rate_ctrl_mutex); 53 kfree(alg); 54} 55EXPORT_SYMBOL(ieee80211_rate_control_unregister); 56 57static struct rate_control_ops * 58ieee80211_try_rate_control_ops_get(const char *name) 59{ 60 struct rate_control_alg *alg; 61 struct rate_control_ops *ops = NULL; 62 63 mutex_lock(&rate_ctrl_mutex); 64 list_for_each_entry(alg, &rate_ctrl_algs, list) { 65 if (!name || !strcmp(alg->ops->name, name)) 66 if (try_module_get(alg->ops->module)) { 67 ops = alg->ops; 68 break; 69 } 70 } 71 mutex_unlock(&rate_ctrl_mutex); 72 return ops; 73} 74 75/* Get the rate control algorithm. If `name' is NULL, get the first 76 * available algorithm. */ 77static struct rate_control_ops * 78ieee80211_rate_control_ops_get(const char *name) 79{ 80 struct rate_control_ops *ops; 81 82 ops = ieee80211_try_rate_control_ops_get(name); 83 if (!ops) { 84 request_module("rc80211_%s", name ? name : "default"); 85 ops = ieee80211_try_rate_control_ops_get(name); 86 } 87 return ops; 88} 89 90static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) 91{ 92 module_put(ops->module); 93} 94 95struct rate_control_ref *rate_control_alloc(const char *name, 96 struct ieee80211_local *local) 97{ 98 struct rate_control_ref *ref; 99 100 ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); 101 if (!ref) 102 goto fail_ref; 103 kref_init(&ref->kref); 104 ref->ops = ieee80211_rate_control_ops_get(name); 105 if (!ref->ops) 106 goto fail_ops; 107 ref->priv = ref->ops->alloc(local); 108 if (!ref->priv) 109 goto fail_priv; 110 return ref; 111 112fail_priv: 113 ieee80211_rate_control_ops_put(ref->ops); 114fail_ops: 115 kfree(ref); 116fail_ref: 117 return NULL; 118} 119 120static void rate_control_release(struct kref *kref) 121{ 122 struct rate_control_ref *ctrl_ref; 123 124 ctrl_ref = container_of(kref, struct rate_control_ref, kref); 125 ctrl_ref->ops->free(ctrl_ref->priv); 126 ieee80211_rate_control_ops_put(ctrl_ref->ops); 127 kfree(ctrl_ref); 128} 129 130struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) 131{ 132 kref_get(&ref->kref); 133 return ref; 134} 135 136void rate_control_put(struct rate_control_ref *ref) 137{ 138 kref_put(&ref->kref, rate_control_release); 139}