[PATCH] sched: add new SCHED_BATCH policy
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ieee80211 / ieee80211_module.c
CommitLineData
b453872c
JG
1/*******************************************************************************
2
ebeaddcc 3 Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
b453872c
JG
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
34#include <linux/config.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
b453872c
JG
43#include <linux/proc_fs.h>
44#include <linux/skbuff.h>
45#include <linux/slab.h>
46#include <linux/tcp.h>
47#include <linux/types.h>
b453872c
JG
48#include <linux/wireless.h>
49#include <linux/etherdevice.h>
50#include <asm/uaccess.h>
51#include <net/arp.h>
52
53#include <net/ieee80211.h>
54
31696160
JK
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME "ieee80211"
57#define DRV_VERSION IEEE80211_VERSION
58#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
59
60MODULE_VERSION(DRV_VERSION);
61MODULE_DESCRIPTION(DRV_DESCRIPTION);
62MODULE_AUTHOR(DRV_COPYRIGHT);
b453872c
JG
63MODULE_LICENSE("GPL");
64
b453872c
JG
65static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66{
67 if (ieee->networks)
68 return 0;
69
0edd5b44
JG
70 ieee->networks =
71 kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
72 GFP_KERNEL);
b453872c
JG
73 if (!ieee->networks) {
74 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
75 ieee->dev->name);
76 return -ENOMEM;
77 }
78
79 memset(ieee->networks, 0,
80 MAX_NETWORK_COUNT * sizeof(struct ieee80211_network));
81
82 return 0;
83}
84
85static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
86{
87 if (!ieee->networks)
88 return;
89 kfree(ieee->networks);
90 ieee->networks = NULL;
91}
92
93static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
94{
95 int i;
96
97 INIT_LIST_HEAD(&ieee->network_free_list);
98 INIT_LIST_HEAD(&ieee->network_list);
99 for (i = 0; i < MAX_NETWORK_COUNT; i++)
0edd5b44
JG
100 list_add_tail(&ieee->networks[i].list,
101 &ieee->network_free_list);
b453872c
JG
102}
103
b453872c
JG
104struct net_device *alloc_ieee80211(int sizeof_priv)
105{
106 struct ieee80211_device *ieee;
107 struct net_device *dev;
108 int err;
109
110 IEEE80211_DEBUG_INFO("Initializing...\n");
111
112 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
113 if (!dev) {
114 IEEE80211_ERROR("Unable to network device.\n");
115 goto failed;
116 }
117 ieee = netdev_priv(dev);
118 dev->hard_start_xmit = ieee80211_xmit;
119
120 ieee->dev = dev;
121
122 err = ieee80211_networks_allocate(ieee);
123 if (err) {
0edd5b44 124 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
b453872c
JG
125 goto failed;
126 }
127 ieee80211_networks_initialize(ieee);
128
129 /* Default fragmentation threshold is maximum payload size */
130 ieee->fts = DEFAULT_FTS;
3cdd00c5 131 ieee->rts = DEFAULT_FTS;
b453872c
JG
132 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
133 ieee->open_wep = 1;
134
135 /* Default to enabling full open WEP with host based encrypt/decrypt */
136 ieee->host_encrypt = 1;
137 ieee->host_decrypt = 1;
ccd0fda3
JK
138 ieee->host_mc_decrypt = 1;
139
1264fc04
JK
140 /* Host fragementation in Open mode. Default is enabled.
141 * Note: host fragmentation is always enabled if host encryption
142 * is enabled. For cards can do hardware encryption, they must do
143 * hardware fragmentation as well. So we don't need a variable
144 * like host_enc_frag. */
145 ieee->host_open_frag = 1;
0edd5b44 146 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c
JG
147
148 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
149 init_timer(&ieee->crypt_deinit_timer);
150 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
151 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
0ad0c3c6 152 ieee->crypt_quiesced = 0;
b453872c
JG
153
154 spin_lock_init(&ieee->lock);
155
0edd5b44 156 ieee->wpa_enabled = 0;
0edd5b44
JG
157 ieee->drop_unencrypted = 0;
158 ieee->privacy_invoked = 0;
b453872c
JG
159
160 return dev;
161
0edd5b44 162 failed:
b453872c
JG
163 if (dev)
164 free_netdev(dev);
165 return NULL;
166}
167
b453872c
JG
168void free_ieee80211(struct net_device *dev)
169{
170 struct ieee80211_device *ieee = netdev_priv(dev);
171
172 int i;
173
0ad0c3c6 174 ieee80211_crypt_quiescing(ieee);
b453872c
JG
175 del_timer_sync(&ieee->crypt_deinit_timer);
176 ieee80211_crypt_deinit_entries(ieee, 1);
177
178 for (i = 0; i < WEP_KEYS; i++) {
179 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
180 if (crypt) {
181 if (crypt->ops) {
182 crypt->ops->deinit(crypt->priv);
183 module_put(crypt->ops->owner);
184 }
185 kfree(crypt);
186 ieee->crypt[i] = NULL;
187 }
188 }
189
190 ieee80211_networks_free(ieee);
191 free_netdev(dev);
192}
193
194#ifdef CONFIG_IEEE80211_DEBUG
195
196static int debug = 0;
197u32 ieee80211_debug_level = 0;
198struct proc_dir_entry *ieee80211_proc = NULL;
199
200static int show_debug_level(char *page, char **start, off_t offset,
201 int count, int *eof, void *data)
202{
203 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
204}
205
0edd5b44 206static int store_debug_level(struct file *file, const char __user * buffer,
b453872c
JG
207 unsigned long count, void *data)
208{
262d8e46
JK
209 char buf[] = "0x00000000\n";
210 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
b453872c
JG
211 unsigned long val;
212
262d8e46 213 if (copy_from_user(buf, buffer, len))
b453872c 214 return count;
262d8e46
JK
215 buf[len] = 0;
216 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
217 printk(KERN_INFO DRV_NAME
218 ": %s is not in hex or decimal form.\n", buf);
219 else
220 ieee80211_debug_level = val;
221
262d8e46 222 return strnlen(buf, len);
b453872c 223}
31696160 224#endif /* CONFIG_IEEE80211_DEBUG */
b453872c
JG
225
226static int __init ieee80211_init(void)
227{
31696160 228#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
229 struct proc_dir_entry *e;
230
231 ieee80211_debug_level = debug;
66600221 232 ieee80211_proc = proc_mkdir(DRV_NAME, proc_net);
b453872c
JG
233 if (ieee80211_proc == NULL) {
234 IEEE80211_ERROR("Unable to create " DRV_NAME
235 " proc directory\n");
236 return -EIO;
237 }
238 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
239 ieee80211_proc);
240 if (!e) {
241 remove_proc_entry(DRV_NAME, proc_net);
242 ieee80211_proc = NULL;
243 return -EIO;
244 }
245 e->read_proc = show_debug_level;
246 e->write_proc = store_debug_level;
247 e->data = NULL;
31696160
JK
248#endif /* CONFIG_IEEE80211_DEBUG */
249
250 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
251 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
252
253 return 0;
254}
255
256static void __exit ieee80211_exit(void)
257{
31696160 258#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
259 if (ieee80211_proc) {
260 remove_proc_entry("debug_level", ieee80211_proc);
261 remove_proc_entry(DRV_NAME, proc_net);
262 ieee80211_proc = NULL;
263 }
31696160 264#endif /* CONFIG_IEEE80211_DEBUG */
b453872c
JG
265}
266
31696160 267#ifdef CONFIG_IEEE80211_DEBUG
b453872c
JG
268#include <linux/moduleparam.h>
269module_param(debug, int, 0444);
270MODULE_PARM_DESC(debug, "debug output mask");
31696160 271#endif /* CONFIG_IEEE80211_DEBUG */
b453872c 272
b453872c
JG
273module_exit(ieee80211_exit);
274module_init(ieee80211_init);
b453872c 275
0edd5b44
JG
276const char *escape_essid(const char *essid, u8 essid_len)
277{
e88187ee
JB
278 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
279 const char *s = essid;
280 char *d = escaped;
281
282 if (ieee80211_is_empty_essid(essid, essid_len)) {
283 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
284 return escaped;
285 }
286
0edd5b44 287 essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
e88187ee
JB
288 while (essid_len--) {
289 if (*s == '\0') {
290 *d++ = '\\';
291 *d++ = '0';
292 s++;
293 } else {
294 *d++ = *s++;
295 }
296 }
297 *d = '\0';
298 return escaped;
299}
300
b453872c
JG
301EXPORT_SYMBOL(alloc_ieee80211);
302EXPORT_SYMBOL(free_ieee80211);
e88187ee 303EXPORT_SYMBOL(escape_essid);