ath9k: fix 802.11g conformance test limit typo
[linux-2.6] / drivers / net / wireless / ipw2x00 / libipw_module.c
1 /*******************************************************************************
2
3   Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
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   <j@w1.fi>
9   Copyright (c) 2002-2003, Jouni Malinen <j@w1.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/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>
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>
47 #include <linux/wireless.h>
48 #include <linux/etherdevice.h>
49 #include <asm/uaccess.h>
50 #include <net/net_namespace.h>
51 #include <net/arp.h>
52
53 #include "ieee80211.h"
54
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
60 MODULE_VERSION(DRV_VERSION);
61 MODULE_DESCRIPTION(DRV_DESCRIPTION);
62 MODULE_AUTHOR(DRV_COPYRIGHT);
63 MODULE_LICENSE("GPL");
64
65 static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
66 {
67         if (ieee->networks)
68                 return 0;
69
70         ieee->networks =
71             kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
72                     GFP_KERNEL);
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         return 0;
80 }
81
82 void ieee80211_network_reset(struct ieee80211_network *network)
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
93 static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
94 {
95         int i;
96
97         if (!ieee->networks)
98                 return;
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
104         kfree(ieee->networks);
105         ieee->networks = NULL;
106 }
107
108 void ieee80211_networks_age(struct ieee80211_device *ieee,
109                             unsigned long age_secs)
110 {
111         struct ieee80211_network *network = NULL;
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 }
121 EXPORT_SYMBOL(ieee80211_networks_age);
122
123 static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
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++)
130                 list_add_tail(&ieee->networks[i].list,
131                               &ieee->network_free_list);
132 }
133
134 static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
135 {
136         if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
137                 return -EINVAL;
138         dev->mtu = new_mtu;
139         return 0;
140 }
141
142 static struct net_device_stats *ieee80211_generic_get_stats(
143         struct net_device *dev)
144 {
145         struct ieee80211_device *ieee = netdev_priv(dev);
146         return &ieee->stats;
147 }
148
149 struct net_device *alloc_ieee80211(int sizeof_priv)
150 {
151         struct ieee80211_device *ieee;
152         struct net_device *dev;
153         int err;
154
155         IEEE80211_DEBUG_INFO("Initializing...\n");
156
157         dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
158         if (!dev) {
159                 IEEE80211_ERROR("Unable to allocate network device.\n");
160                 goto failed;
161         }
162         ieee = netdev_priv(dev);
163         dev->hard_start_xmit = ieee80211_xmit;
164         dev->change_mtu = ieee80211_change_mtu;
165
166         /* Drivers are free to override this if the generic implementation
167          * does not meet their needs. */
168         dev->get_stats = ieee80211_generic_get_stats;
169
170         ieee->dev = dev;
171
172         err = ieee80211_networks_allocate(ieee);
173         if (err) {
174                 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
175                 goto failed_free_netdev;
176         }
177         ieee80211_networks_initialize(ieee);
178
179         /* Default fragmentation threshold is maximum payload size */
180         ieee->fts = DEFAULT_FTS;
181         ieee->rts = DEFAULT_FTS;
182         ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
183         ieee->open_wep = 1;
184
185         /* Default to enabling full open WEP with host based encrypt/decrypt */
186         ieee->host_encrypt = 1;
187         ieee->host_decrypt = 1;
188         ieee->host_mc_decrypt = 1;
189
190         /* Host fragementation in Open mode. Default is enabled.
191          * Note: host fragmentation is always enabled if host encryption
192          * is enabled. For cards can do hardware encryption, they must do
193          * hardware fragmentation as well. So we don't need a variable
194          * like host_enc_frag. */
195         ieee->host_open_frag = 1;
196         ieee->ieee802_1x = 1;   /* Default to supporting 802.1x */
197
198         spin_lock_init(&ieee->lock);
199
200         lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
201
202         ieee->wpa_enabled = 0;
203         ieee->drop_unencrypted = 0;
204         ieee->privacy_invoked = 0;
205
206         return dev;
207
208 failed_free_netdev:
209         free_netdev(dev);
210 failed:
211         return NULL;
212 }
213
214 void free_ieee80211(struct net_device *dev)
215 {
216         struct ieee80211_device *ieee = netdev_priv(dev);
217
218         lib80211_crypt_info_free(&ieee->crypt_info);
219
220         ieee80211_networks_free(ieee);
221         free_netdev(dev);
222 }
223
224 #ifdef CONFIG_IEEE80211_DEBUG
225
226 static int debug = 0;
227 u32 ieee80211_debug_level = 0;
228 EXPORT_SYMBOL_GPL(ieee80211_debug_level);
229 static struct proc_dir_entry *ieee80211_proc = NULL;
230
231 static int show_debug_level(char *page, char **start, off_t offset,
232                             int count, int *eof, void *data)
233 {
234         return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
235 }
236
237 static int store_debug_level(struct file *file, const char __user * buffer,
238                              unsigned long count, void *data)
239 {
240         char buf[] = "0x00000000\n";
241         unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
242         unsigned long val;
243
244         if (copy_from_user(buf, buffer, len))
245                 return count;
246         buf[len] = 0;
247         if (sscanf(buf, "%li", &val) != 1)
248                 printk(KERN_INFO DRV_NAME
249                        ": %s is not in hex or decimal form.\n", buf);
250         else
251                 ieee80211_debug_level = val;
252
253         return strnlen(buf, len);
254 }
255 #endif                          /* CONFIG_IEEE80211_DEBUG */
256
257 static int __init ieee80211_init(void)
258 {
259 #ifdef CONFIG_IEEE80211_DEBUG
260         struct proc_dir_entry *e;
261
262         ieee80211_debug_level = debug;
263         ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
264         if (ieee80211_proc == NULL) {
265                 IEEE80211_ERROR("Unable to create " DRV_NAME
266                                 " proc directory\n");
267                 return -EIO;
268         }
269         e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
270                               ieee80211_proc);
271         if (!e) {
272                 remove_proc_entry(DRV_NAME, init_net.proc_net);
273                 ieee80211_proc = NULL;
274                 return -EIO;
275         }
276         e->read_proc = show_debug_level;
277         e->write_proc = store_debug_level;
278         e->data = NULL;
279 #endif                          /* CONFIG_IEEE80211_DEBUG */
280
281         printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
282         printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
283
284         return 0;
285 }
286
287 static void __exit ieee80211_exit(void)
288 {
289 #ifdef CONFIG_IEEE80211_DEBUG
290         if (ieee80211_proc) {
291                 remove_proc_entry("debug_level", ieee80211_proc);
292                 remove_proc_entry(DRV_NAME, init_net.proc_net);
293                 ieee80211_proc = NULL;
294         }
295 #endif                          /* CONFIG_IEEE80211_DEBUG */
296 }
297
298 #ifdef CONFIG_IEEE80211_DEBUG
299 #include <linux/moduleparam.h>
300 module_param(debug, int, 0444);
301 MODULE_PARM_DESC(debug, "debug output mask");
302 #endif                          /* CONFIG_IEEE80211_DEBUG */
303
304 module_exit(ieee80211_exit);
305 module_init(ieee80211_init);
306
307 EXPORT_SYMBOL(alloc_ieee80211);
308 EXPORT_SYMBOL(free_ieee80211);