diff options
Diffstat (limited to 'drivers/net/wireless/ipw2x00/libipw_module.c')
-rw-r--r-- | drivers/net/wireless/ipw2x00/libipw_module.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index eb2b60834c17..2fa55867bd8b 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -62,18 +62,22 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
62 | MODULE_AUTHOR(DRV_COPYRIGHT); | 62 | MODULE_AUTHOR(DRV_COPYRIGHT); |
63 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
64 | 64 | ||
65 | struct cfg80211_ops libipw_config_ops = { }; | ||
66 | void *libipw_wiphy_privid = &libipw_wiphy_privid; | ||
67 | |||
65 | static int libipw_networks_allocate(struct libipw_device *ieee) | 68 | static int libipw_networks_allocate(struct libipw_device *ieee) |
66 | { | 69 | { |
67 | if (ieee->networks) | 70 | int i, j; |
68 | return 0; | 71 | |
69 | 72 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | |
70 | ieee->networks = | 73 | ieee->networks[i] = kzalloc(sizeof(struct libipw_network), |
71 | kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network), | 74 | GFP_KERNEL); |
72 | GFP_KERNEL); | 75 | if (!ieee->networks[i]) { |
73 | if (!ieee->networks) { | 76 | LIBIPW_ERROR("Out of memory allocating beacons\n"); |
74 | printk(KERN_WARNING "%s: Out of memory allocating beacons\n", | 77 | for (j = 0; j < i; j++) |
75 | ieee->dev->name); | 78 | kfree(ieee->networks[j]); |
76 | return -ENOMEM; | 79 | return -ENOMEM; |
80 | } | ||
77 | } | 81 | } |
78 | 82 | ||
79 | return 0; | 83 | return 0; |
@@ -94,15 +98,11 @@ static inline void libipw_networks_free(struct libipw_device *ieee) | |||
94 | { | 98 | { |
95 | int i; | 99 | int i; |
96 | 100 | ||
97 | if (!ieee->networks) | 101 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { |
98 | return; | 102 | if (ieee->networks[i]->ibss_dfs) |
99 | 103 | kfree(ieee->networks[i]->ibss_dfs); | |
100 | for (i = 0; i < MAX_NETWORK_COUNT; i++) | 104 | kfree(ieee->networks[i]); |
101 | if (ieee->networks[i].ibss_dfs) | 105 | } |
102 | kfree(ieee->networks[i].ibss_dfs); | ||
103 | |||
104 | kfree(ieee->networks); | ||
105 | ieee->networks = NULL; | ||
106 | } | 106 | } |
107 | 107 | ||
108 | void libipw_networks_age(struct libipw_device *ieee, | 108 | void libipw_networks_age(struct libipw_device *ieee, |
@@ -127,7 +127,7 @@ static void libipw_networks_initialize(struct libipw_device *ieee) | |||
127 | INIT_LIST_HEAD(&ieee->network_free_list); | 127 | INIT_LIST_HEAD(&ieee->network_free_list); |
128 | INIT_LIST_HEAD(&ieee->network_list); | 128 | INIT_LIST_HEAD(&ieee->network_list); |
129 | for (i = 0; i < MAX_NETWORK_COUNT; i++) | 129 | for (i = 0; i < MAX_NETWORK_COUNT; i++) |
130 | list_add_tail(&ieee->networks[i].list, | 130 | list_add_tail(&ieee->networks[i]->list, |
131 | &ieee->network_free_list); | 131 | &ieee->network_free_list); |
132 | } | 132 | } |
133 | 133 | ||
@@ -140,7 +140,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu) | |||
140 | } | 140 | } |
141 | EXPORT_SYMBOL(libipw_change_mtu); | 141 | EXPORT_SYMBOL(libipw_change_mtu); |
142 | 142 | ||
143 | struct net_device *alloc_ieee80211(int sizeof_priv) | 143 | struct net_device *alloc_ieee80211(int sizeof_priv, int monitor) |
144 | { | 144 | { |
145 | struct libipw_device *ieee; | 145 | struct libipw_device *ieee; |
146 | struct net_device *dev; | 146 | struct net_device *dev; |
@@ -157,10 +157,31 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
157 | 157 | ||
158 | ieee->dev = dev; | 158 | ieee->dev = dev; |
159 | 159 | ||
160 | if (!monitor) { | ||
161 | ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0); | ||
162 | if (!ieee->wdev.wiphy) { | ||
163 | LIBIPW_ERROR("Unable to allocate wiphy.\n"); | ||
164 | goto failed_free_netdev; | ||
165 | } | ||
166 | |||
167 | ieee->dev->ieee80211_ptr = &ieee->wdev; | ||
168 | ieee->wdev.iftype = NL80211_IFTYPE_STATION; | ||
169 | |||
170 | /* Fill-out wiphy structure bits we know... Not enough info | ||
171 | here to call set_wiphy_dev or set MAC address or channel info | ||
172 | -- have to do that in ->ndo_init... */ | ||
173 | ieee->wdev.wiphy->privid = libipw_wiphy_privid; | ||
174 | |||
175 | ieee->wdev.wiphy->max_scan_ssids = 1; | ||
176 | ieee->wdev.wiphy->max_scan_ie_len = 0; | ||
177 | ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | ||
178 | | BIT(NL80211_IFTYPE_ADHOC); | ||
179 | } | ||
180 | |||
160 | err = libipw_networks_allocate(ieee); | 181 | err = libipw_networks_allocate(ieee); |
161 | if (err) { | 182 | if (err) { |
162 | LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); | 183 | LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); |
163 | goto failed_free_netdev; | 184 | goto failed_free_wiphy; |
164 | } | 185 | } |
165 | libipw_networks_initialize(ieee); | 186 | libipw_networks_initialize(ieee); |
166 | 187 | ||
@@ -175,7 +196,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
175 | ieee->host_decrypt = 1; | 196 | ieee->host_decrypt = 1; |
176 | ieee->host_mc_decrypt = 1; | 197 | ieee->host_mc_decrypt = 1; |
177 | 198 | ||
178 | /* Host fragementation in Open mode. Default is enabled. | 199 | /* Host fragmentation in Open mode. Default is enabled. |
179 | * Note: host fragmentation is always enabled if host encryption | 200 | * Note: host fragmentation is always enabled if host encryption |
180 | * is enabled. For cards can do hardware encryption, they must do | 201 | * is enabled. For cards can do hardware encryption, they must do |
181 | * hardware fragmentation as well. So we don't need a variable | 202 | * hardware fragmentation as well. So we don't need a variable |
@@ -193,19 +214,27 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
193 | 214 | ||
194 | return dev; | 215 | return dev; |
195 | 216 | ||
217 | failed_free_wiphy: | ||
218 | if (!monitor) | ||
219 | wiphy_free(ieee->wdev.wiphy); | ||
196 | failed_free_netdev: | 220 | failed_free_netdev: |
197 | free_netdev(dev); | 221 | free_netdev(dev); |
198 | failed: | 222 | failed: |
199 | return NULL; | 223 | return NULL; |
200 | } | 224 | } |
201 | 225 | ||
202 | void free_ieee80211(struct net_device *dev) | 226 | void free_ieee80211(struct net_device *dev, int monitor) |
203 | { | 227 | { |
204 | struct libipw_device *ieee = netdev_priv(dev); | 228 | struct libipw_device *ieee = netdev_priv(dev); |
205 | 229 | ||
206 | lib80211_crypt_info_free(&ieee->crypt_info); | 230 | lib80211_crypt_info_free(&ieee->crypt_info); |
207 | 231 | ||
208 | libipw_networks_free(ieee); | 232 | libipw_networks_free(ieee); |
233 | |||
234 | /* free cfg80211 resources */ | ||
235 | if (!monitor) | ||
236 | wiphy_free(ieee->wdev.wiphy); | ||
237 | |||
209 | free_netdev(dev); | 238 | free_netdev(dev); |
210 | } | 239 | } |
211 | 240 | ||
@@ -216,17 +245,22 @@ u32 libipw_debug_level = 0; | |||
216 | EXPORT_SYMBOL_GPL(libipw_debug_level); | 245 | EXPORT_SYMBOL_GPL(libipw_debug_level); |
217 | static struct proc_dir_entry *libipw_proc = NULL; | 246 | static struct proc_dir_entry *libipw_proc = NULL; |
218 | 247 | ||
219 | static int show_debug_level(char *page, char **start, off_t offset, | 248 | static int debug_level_proc_show(struct seq_file *m, void *v) |
220 | int count, int *eof, void *data) | ||
221 | { | 249 | { |
222 | return snprintf(page, count, "0x%08X\n", libipw_debug_level); | 250 | seq_printf(m, "0x%08X\n", libipw_debug_level); |
251 | return 0; | ||
223 | } | 252 | } |
224 | 253 | ||
225 | static int store_debug_level(struct file *file, const char __user * buffer, | 254 | static int debug_level_proc_open(struct inode *inode, struct file *file) |
226 | unsigned long count, void *data) | 255 | { |
256 | return single_open(file, debug_level_proc_show, NULL); | ||
257 | } | ||
258 | |||
259 | static ssize_t debug_level_proc_write(struct file *file, | ||
260 | const char __user *buffer, size_t count, loff_t *pos) | ||
227 | { | 261 | { |
228 | char buf[] = "0x00000000\n"; | 262 | char buf[] = "0x00000000\n"; |
229 | unsigned long len = min((unsigned long)sizeof(buf) - 1, count); | 263 | size_t len = min(sizeof(buf) - 1, count); |
230 | unsigned long val; | 264 | unsigned long val; |
231 | 265 | ||
232 | if (copy_from_user(buf, buffer, len)) | 266 | if (copy_from_user(buf, buffer, len)) |
@@ -240,6 +274,15 @@ static int store_debug_level(struct file *file, const char __user * buffer, | |||
240 | 274 | ||
241 | return strnlen(buf, len); | 275 | return strnlen(buf, len); |
242 | } | 276 | } |
277 | |||
278 | static const struct file_operations debug_level_proc_fops = { | ||
279 | .owner = THIS_MODULE, | ||
280 | .open = debug_level_proc_open, | ||
281 | .read = seq_read, | ||
282 | .llseek = seq_lseek, | ||
283 | .release = single_release, | ||
284 | .write = debug_level_proc_write, | ||
285 | }; | ||
243 | #endif /* CONFIG_LIBIPW_DEBUG */ | 286 | #endif /* CONFIG_LIBIPW_DEBUG */ |
244 | 287 | ||
245 | static int __init libipw_init(void) | 288 | static int __init libipw_init(void) |
@@ -254,16 +297,13 @@ static int __init libipw_init(void) | |||
254 | " proc directory\n"); | 297 | " proc directory\n"); |
255 | return -EIO; | 298 | return -EIO; |
256 | } | 299 | } |
257 | e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, | 300 | e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc, |
258 | libipw_proc); | 301 | &debug_level_proc_fops); |
259 | if (!e) { | 302 | if (!e) { |
260 | remove_proc_entry(DRV_NAME, init_net.proc_net); | 303 | remove_proc_entry(DRV_NAME, init_net.proc_net); |
261 | libipw_proc = NULL; | 304 | libipw_proc = NULL; |
262 | return -EIO; | 305 | return -EIO; |
263 | } | 306 | } |
264 | e->read_proc = show_debug_level; | ||
265 | e->write_proc = store_debug_level; | ||
266 | e->data = NULL; | ||
267 | #endif /* CONFIG_LIBIPW_DEBUG */ | 307 | #endif /* CONFIG_LIBIPW_DEBUG */ |
268 | 308 | ||
269 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 309 | printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); |