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 = kmalloc(sizeof(*alg), GFP_KERNEL); 28 if (alg == NULL) { 29 return -ENOMEM; 30 } 31 memset(alg, 0, sizeof(*alg)); 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