iwlwifi: fix unloading driver while scanning
[deliverable/linux.git] / drivers / net / wireless / ipw2x00 / libipw_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
85d32e7b
JM
8 <j@w1.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
b453872c
JG
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>
b453872c
JG
34#include <linux/errno.h>
35#include <linux/if_arp.h>
36#include <linux/in6.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/netdevice.h>
b453872c
JG
42#include <linux/proc_fs.h>
43#include <linux/skbuff.h>
44#include <linux/slab.h>
45#include <linux/tcp.h>
46#include <linux/types.h>
b453872c
JG
47#include <linux/wireless.h>
48#include <linux/etherdevice.h>
49#include <asm/uaccess.h>
457c4cbc 50#include <net/net_namespace.h>
b453872c
JG
51#include <net/arp.h>
52
b0a4e7d8 53#include "libipw.h"
b453872c 54
31696160
JK
55#define DRV_DESCRIPTION "802.11 data/management/control stack"
56#define DRV_NAME "ieee80211"
b0a4e7d8 57#define DRV_VERSION LIBIPW_VERSION
31696160
JK
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
b0a4e7d8 65static int libipw_networks_allocate(struct libipw_device *ieee)
b453872c
JG
66{
67 if (ieee->networks)
68 return 0;
69
0edd5b44 70 ieee->networks =
b0a4e7d8 71 kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
0edd5b44 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
b453872c
JG
79 return 0;
80}
81
b0a4e7d8 82void libipw_network_reset(struct libipw_network *network)
15f38598
ZY
83{
84 if (!network)
85 return;
86
87 if (network->ibss_dfs) {
88 kfree(network->ibss_dfs);
89 network->ibss_dfs = NULL;
90 }
91}
92
b0a4e7d8 93static inline void libipw_networks_free(struct libipw_device *ieee)
b453872c 94{
15f38598
ZY
95 int i;
96
b453872c
JG
97 if (!ieee->networks)
98 return;
15f38598
ZY
99
100 for (i = 0; i < MAX_NETWORK_COUNT; i++)
101 if (ieee->networks[i].ibss_dfs)
102 kfree(ieee->networks[i].ibss_dfs);
103
b453872c
JG
104 kfree(ieee->networks);
105 ieee->networks = NULL;
106}
107
b0a4e7d8 108void libipw_networks_age(struct libipw_device *ieee,
c3d72b96
DW
109 unsigned long age_secs)
110{
b0a4e7d8 111 struct libipw_network *network = NULL;
c3d72b96
DW
112 unsigned long flags;
113 unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC);
114
115 spin_lock_irqsave(&ieee->lock, flags);
116 list_for_each_entry(network, &ieee->network_list, list) {
117 network->last_scanned -= age_jiffies;
118 }
119 spin_unlock_irqrestore(&ieee->lock, flags);
120}
b0a4e7d8 121EXPORT_SYMBOL(libipw_networks_age);
c3d72b96 122
b0a4e7d8 123static void libipw_networks_initialize(struct libipw_device *ieee)
b453872c
JG
124{
125 int i;
126
127 INIT_LIST_HEAD(&ieee->network_free_list);
128 INIT_LIST_HEAD(&ieee->network_list);
129 for (i = 0; i < MAX_NETWORK_COUNT; i++)
0edd5b44
JG
130 list_add_tail(&ieee->networks[i].list,
131 &ieee->network_free_list);
b453872c
JG
132}
133
b0a4e7d8 134int libipw_change_mtu(struct net_device *dev, int new_mtu)
42a4cf95 135{
b0a4e7d8 136 if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN))
42a4cf95 137 return -EINVAL;
138 dev->mtu = new_mtu;
139 return 0;
140}
b0a4e7d8 141EXPORT_SYMBOL(libipw_change_mtu);
42a4cf95 142
b453872c
JG
143struct net_device *alloc_ieee80211(int sizeof_priv)
144{
b0a4e7d8 145 struct libipw_device *ieee;
b453872c
JG
146 struct net_device *dev;
147 int err;
148
b0a4e7d8 149 LIBIPW_DEBUG_INFO("Initializing...\n");
b453872c 150
b0a4e7d8 151 dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv);
b453872c 152 if (!dev) {
b0a4e7d8 153 LIBIPW_ERROR("Unable to allocate network device.\n");
b453872c
JG
154 goto failed;
155 }
156 ieee = netdev_priv(dev);
b453872c
JG
157
158 ieee->dev = dev;
159
b0a4e7d8 160 err = libipw_networks_allocate(ieee);
b453872c 161 if (err) {
b0a4e7d8 162 LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err);
d92a8e81 163 goto failed_free_netdev;
b453872c 164 }
b0a4e7d8 165 libipw_networks_initialize(ieee);
b453872c
JG
166
167 /* Default fragmentation threshold is maximum payload size */
168 ieee->fts = DEFAULT_FTS;
3cdd00c5 169 ieee->rts = DEFAULT_FTS;
b453872c
JG
170 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
171 ieee->open_wep = 1;
172
173 /* Default to enabling full open WEP with host based encrypt/decrypt */
174 ieee->host_encrypt = 1;
175 ieee->host_decrypt = 1;
ccd0fda3
JK
176 ieee->host_mc_decrypt = 1;
177
1264fc04
JK
178 /* Host fragementation in Open mode. Default is enabled.
179 * Note: host fragmentation is always enabled if host encryption
180 * is enabled. For cards can do hardware encryption, they must do
181 * hardware fragmentation as well. So we don't need a variable
182 * like host_enc_frag. */
183 ieee->host_open_frag = 1;
0edd5b44 184 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
b453872c 185
b453872c
JG
186 spin_lock_init(&ieee->lock);
187
2ba4b32e 188 lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
274bfb8d 189
0edd5b44 190 ieee->wpa_enabled = 0;
0edd5b44
JG
191 ieee->drop_unencrypted = 0;
192 ieee->privacy_invoked = 0;
b453872c
JG
193
194 return dev;
195
d92a8e81
JL
196failed_free_netdev:
197 free_netdev(dev);
198failed:
b453872c
JG
199 return NULL;
200}
201
b453872c
JG
202void free_ieee80211(struct net_device *dev)
203{
b0a4e7d8 204 struct libipw_device *ieee = netdev_priv(dev);
b453872c 205
2ba4b32e 206 lib80211_crypt_info_free(&ieee->crypt_info);
b453872c 207
b0a4e7d8 208 libipw_networks_free(ieee);
b453872c
JG
209 free_netdev(dev);
210}
211
3756162b 212#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
213
214static int debug = 0;
b0a4e7d8
JL
215u32 libipw_debug_level = 0;
216EXPORT_SYMBOL_GPL(libipw_debug_level);
217static struct proc_dir_entry *libipw_proc = NULL;
b453872c
JG
218
219static int show_debug_level(char *page, char **start, off_t offset,
220 int count, int *eof, void *data)
221{
b0a4e7d8 222 return snprintf(page, count, "0x%08X\n", libipw_debug_level);
b453872c
JG
223}
224
0edd5b44 225static int store_debug_level(struct file *file, const char __user * buffer,
b453872c
JG
226 unsigned long count, void *data)
227{
262d8e46
JK
228 char buf[] = "0x00000000\n";
229 unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
b453872c
JG
230 unsigned long val;
231
262d8e46 232 if (copy_from_user(buf, buffer, len))
b453872c 233 return count;
262d8e46
JK
234 buf[len] = 0;
235 if (sscanf(buf, "%li", &val) != 1)
b453872c
JG
236 printk(KERN_INFO DRV_NAME
237 ": %s is not in hex or decimal form.\n", buf);
238 else
b0a4e7d8 239 libipw_debug_level = val;
b453872c 240
262d8e46 241 return strnlen(buf, len);
b453872c 242}
3756162b 243#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 244
b0a4e7d8 245static int __init libipw_init(void)
b453872c 246{
3756162b 247#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
248 struct proc_dir_entry *e;
249
b0a4e7d8
JL
250 libipw_debug_level = debug;
251 libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
252 if (libipw_proc == NULL) {
253 LIBIPW_ERROR("Unable to create " DRV_NAME
b453872c
JG
254 " proc directory\n");
255 return -EIO;
256 }
257 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
b0a4e7d8 258 libipw_proc);
b453872c 259 if (!e) {
457c4cbc 260 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 261 libipw_proc = NULL;
b453872c
JG
262 return -EIO;
263 }
264 e->read_proc = show_debug_level;
265 e->write_proc = store_debug_level;
266 e->data = NULL;
3756162b 267#endif /* CONFIG_LIBIPW_DEBUG */
31696160
JK
268
269 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
270 printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
b453872c
JG
271
272 return 0;
273}
274
b0a4e7d8 275static void __exit libipw_exit(void)
b453872c 276{
3756162b 277#ifdef CONFIG_LIBIPW_DEBUG
b0a4e7d8
JL
278 if (libipw_proc) {
279 remove_proc_entry("debug_level", libipw_proc);
457c4cbc 280 remove_proc_entry(DRV_NAME, init_net.proc_net);
b0a4e7d8 281 libipw_proc = NULL;
b453872c 282 }
3756162b 283#endif /* CONFIG_LIBIPW_DEBUG */
b453872c
JG
284}
285
3756162b 286#ifdef CONFIG_LIBIPW_DEBUG
b453872c
JG
287#include <linux/moduleparam.h>
288module_param(debug, int, 0444);
289MODULE_PARM_DESC(debug, "debug output mask");
3756162b 290#endif /* CONFIG_LIBIPW_DEBUG */
b453872c 291
b0a4e7d8
JL
292module_exit(libipw_exit);
293module_init(libipw_init);
b453872c
JG
294
295EXPORT_SYMBOL(alloc_ieee80211);
296EXPORT_SYMBOL(free_ieee80211);
This page took 0.534729 seconds and 5 git commands to generate.