~ubuntu-branches/ubuntu/hardy/linux-backports-modules-2.6.24/hardy-security

« back to all changes in this revision

Viewing changes to updates/wireless/iwlwifi/mac80211/compatible/net/mac80211/ieee80211_iface.c

  • Committer: Bazaar Package Importer
  • Author(s): , Ben Collins
  • Date: 2008-04-02 06:59:04 UTC
  • Revision ID: james.westby@ubuntu.com-20080402065904-e5knh2gn2hms3xbb
Tags: 2.6.24-14.11
[Ben Collins]

* iwlwifi: Update to iwlwifi-1.2.25 and mac80211-10.0.4
  - LP: #200950
* ubuntu: Slight cleanups to module hiearchy and Makefiles
* mac80211: Enable LED triggers
* iwlwifi: Add LED trigger support (rx and tx only)
  - LP: #176090

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include <linux/kernel.h>
 
11
#include <linux/if_arp.h>
 
12
#include <linux/netdevice.h>
 
13
#include <linux/rtnetlink.h>
 
14
#include <net/mac80211.h>
 
15
#include "ieee80211_i.h"
 
16
#include "sta_info.h"
 
17
#include "debugfs_netdev.h"
 
18
 
 
19
void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
 
20
{
 
21
        int i;
 
22
 
 
23
        /* Default values for sub-interface parameters */
 
24
        sdata->drop_unencrypted = 0;
 
25
        sdata->eapol = 1;
 
26
        for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
 
27
                skb_queue_head_init(&sdata->fragments[i].skb_list);
 
28
}
 
29
 
 
30
static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
 
31
{
 
32
        int i;
 
33
 
 
34
        for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
 
35
                __skb_queue_purge(&sdata->fragments[i].skb_list);
 
36
        }
 
37
}
 
38
 
 
39
/* Must be called with rtnl lock held. */
 
40
int ieee80211_if_add(struct net_device *dev, const char *name,
 
41
                     struct net_device **new_dev, int type)
 
42
{
 
43
        struct net_device *ndev;
 
44
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
45
        struct ieee80211_sub_if_data *sdata = NULL;
 
46
        int ret;
 
47
 
 
48
        ASSERT_RTNL();
 
49
        ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data),
 
50
                            name, ieee80211_if_setup);
 
51
        if (!ndev)
 
52
                return -ENOMEM;
 
53
 
 
54
        ret = dev_alloc_name(ndev, ndev->name);
 
55
        if (ret < 0)
 
56
                goto fail;
 
57
 
 
58
        memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
 
59
        ndev->base_addr = dev->base_addr;
 
60
        ndev->irq = dev->irq;
 
61
        ndev->mem_start = dev->mem_start;
 
62
        ndev->mem_end = dev->mem_end;
 
63
        SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
 
64
 
 
65
        sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
 
66
        ndev->ieee80211_ptr = &sdata->wdev;
 
67
        sdata->wdev.wiphy = local->hw.wiphy;
 
68
        sdata->type = IEEE80211_IF_TYPE_AP;
 
69
        sdata->dev = ndev;
 
70
        sdata->local = local;
 
71
        ieee80211_if_sdata_init(sdata);
 
72
 
 
73
        ret = register_netdevice(ndev);
 
74
        if (ret)
 
75
                goto fail;
 
76
 
 
77
        ieee80211_debugfs_add_netdev(sdata);
 
78
        ieee80211_if_set_type(ndev, type);
 
79
 
 
80
        write_lock_bh(&local->sub_if_lock);
 
81
        if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
 
82
                write_unlock_bh(&local->sub_if_lock);
 
83
                __ieee80211_if_del(local, sdata);
 
84
                return -ENODEV;
 
85
        }
 
86
        list_add(&sdata->list, &local->sub_if_list);
 
87
        if (new_dev)
 
88
                *new_dev = ndev;
 
89
        write_unlock_bh(&local->sub_if_lock);
 
90
 
 
91
        ieee80211_update_default_wep_only(local);
 
92
 
 
93
        return 0;
 
94
 
 
95
fail:
 
96
        free_netdev(ndev);
 
97
        return ret;
 
98
}
 
99
 
 
100
int ieee80211_if_add_mgmt(struct ieee80211_local *local)
 
101
{
 
102
        struct net_device *ndev;
 
103
        struct ieee80211_sub_if_data *nsdata;
 
104
        int ret;
 
105
 
 
106
        ASSERT_RTNL();
 
107
 
 
108
        ndev = alloc_netdev(sizeof(struct ieee80211_sub_if_data), "wmgmt%d",
 
109
                            ieee80211_if_mgmt_setup);
 
110
        if (!ndev)
 
111
                return -ENOMEM;
 
112
        ret = dev_alloc_name(ndev, ndev->name);
 
113
        if (ret < 0)
 
114
                goto fail;
 
115
 
 
116
        memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
 
117
        SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
 
118
 
 
119
        nsdata = IEEE80211_DEV_TO_SUB_IF(ndev);
 
120
        ndev->ieee80211_ptr = &nsdata->wdev;
 
121
        nsdata->wdev.wiphy = local->hw.wiphy;
 
122
        nsdata->type = IEEE80211_IF_TYPE_MGMT;
 
123
        nsdata->dev = ndev;
 
124
        nsdata->local = local;
 
125
        ieee80211_if_sdata_init(nsdata);
 
126
 
 
127
        ret = register_netdevice(ndev);
 
128
        if (ret)
 
129
                goto fail;
 
130
 
 
131
        ieee80211_debugfs_add_netdev(nsdata);
 
132
 
 
133
        if (local->open_count > 0)
 
134
                dev_open(ndev);
 
135
        local->apdev = ndev;
 
136
        return 0;
 
137
 
 
138
fail:
 
139
        free_netdev(ndev);
 
140
        return ret;
 
141
}
 
142
 
 
143
void ieee80211_if_del_mgmt(struct ieee80211_local *local)
 
144
{
 
145
        struct net_device *apdev;
 
146
 
 
147
        ASSERT_RTNL();
 
148
        apdev = local->apdev;
 
149
        ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev));
 
150
        local->apdev = NULL;
 
151
        unregister_netdevice(apdev);
 
152
}
 
153
 
 
154
void ieee80211_if_set_type(struct net_device *dev, int type)
 
155
{
 
156
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
157
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
158
        int oldtype = sdata->type;
 
159
 
 
160
        dev->hard_start_xmit = ieee80211_subif_start_xmit;
 
161
 
 
162
        sdata->type = type;
 
163
        switch (type) {
 
164
        case IEEE80211_IF_TYPE_WDS:
 
165
                sdata->bss = NULL;
 
166
                break;
 
167
        case IEEE80211_IF_TYPE_VLAN:
 
168
                break;
 
169
        case IEEE80211_IF_TYPE_AP:
 
170
                sdata->u.ap.dtim_period = 2;
 
171
                sdata->u.ap.force_unicast_rateidx = -1;
 
172
                sdata->u.ap.max_ratectrl_rateidx = -1;
 
173
                skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
 
174
                sdata->bss = &sdata->u.ap;
 
175
                break;
 
176
        case IEEE80211_IF_TYPE_STA:
 
177
        case IEEE80211_IF_TYPE_IBSS: {
 
178
                struct ieee80211_sub_if_data *msdata;
 
179
                struct ieee80211_if_sta *ifsta;
 
180
 
 
181
                ifsta = &sdata->u.sta;
 
182
                INIT_WORK(&ifsta->work, ieee80211_sta_work);
 
183
                setup_timer(&ifsta->timer, ieee80211_sta_timer,
 
184
                            (unsigned long) sdata);
 
185
                skb_queue_head_init(&ifsta->skb_queue);
 
186
 
 
187
                init_timer(&ifsta->admit_timer);
 
188
                ifsta->admit_timer.data = (unsigned long) dev;
 
189
                ifsta->admit_timer.function = ieee80211_admit_refresh;
 
190
 
 
191
                ifsta->capab = WLAN_CAPABILITY_ESS;
 
192
                ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
 
193
                        IEEE80211_AUTH_ALG_SHARED_KEY;
 
194
                ifsta->create_ibss = 1;
 
195
                ifsta->wmm_enabled = 1;
 
196
                ifsta->ht_enabled = 1;
 
197
                ifsta->auto_channel_sel = 1;
 
198
                ifsta->auto_bssid_sel = 1;
 
199
 
 
200
                /* Initialize non-AP QSTA QoS Params */
 
201
                ifsta->dot11EDCAAveragingPeriod = 5;
 
202
                ifsta->MPDUExchangeTime = 0;
 
203
#ifdef CONFIG_MAC80211_DEBUGFS
 
204
                ifsta->tspec.nominal_msdu_size = cpu_to_le16(200),
 
205
                ifsta->tspec.inactivity_interval = cpu_to_le32(40),
 
206
                ifsta->tspec.mean_data_rate = cpu_to_le32(40000),
 
207
                ifsta->tspec.min_phy_rate = cpu_to_le32(6000000),
 
208
                ifsta->tspec.surplus_band_allow = cpu_to_le16(8192),
 
209
                ifsta->tspec.medium_time = cpu_to_le16(30),
 
210
#endif
 
211
 
 
212
                msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
 
213
                sdata->bss = &msdata->u.ap;
 
214
                break;
 
215
        }
 
216
        case IEEE80211_IF_TYPE_MNTR:
 
217
                dev->type = ARPHRD_IEEE80211_RADIOTAP;
 
218
                dev->hard_start_xmit = ieee80211_monitor_start_xmit;
 
219
                break;
 
220
        default:
 
221
                printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
 
222
                       dev->name, __FUNCTION__, type);
 
223
        }
 
224
        ieee80211_debugfs_change_if_type(sdata, oldtype);
 
225
        ieee80211_update_default_wep_only(local);
 
226
}
 
227
 
 
228
/* Must be called with rtnl lock held. */
 
229
void ieee80211_if_reinit(struct net_device *dev)
 
230
{
 
231
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
232
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
233
        struct sta_info *sta;
 
234
        int i;
 
235
 
 
236
        ASSERT_RTNL();
 
237
        ieee80211_if_sdata_deinit(sdata);
 
238
        for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
 
239
                if (!sdata->keys[i])
 
240
                        continue;
 
241
#if 0
 
242
                /* The interface is down at the moment, so there is not
 
243
                 * really much point in disabling the keys at this point. */
 
244
                memset(addr, 0xff, ETH_ALEN);
 
245
                if (local->ops->set_key)
 
246
                        local->ops->set_key(local_to_hw(local), DISABLE_KEY, addr,
 
247
                                            local->keys[i], 0);
 
248
#endif
 
249
                ieee80211_key_free(sdata->keys[i]);
 
250
                sdata->keys[i] = NULL;
 
251
        }
 
252
 
 
253
        switch (sdata->type) {
 
254
        case IEEE80211_IF_TYPE_AP: {
 
255
                /* Remove all virtual interfaces that use this BSS
 
256
                 * as their sdata->bss */
 
257
                struct ieee80211_sub_if_data *tsdata, *n;
 
258
                LIST_HEAD(tmp_list);
 
259
 
 
260
                write_lock_bh(&local->sub_if_lock);
 
261
                list_for_each_entry_safe(tsdata, n, &local->sub_if_list, list) {
 
262
                        if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
 
263
                                printk(KERN_DEBUG "%s: removing virtual "
 
264
                                       "interface %s because its BSS interface"
 
265
                                       " is being removed\n",
 
266
                                       sdata->dev->name, tsdata->dev->name);
 
267
                                list_move_tail(&tsdata->list, &tmp_list);
 
268
                        }
 
269
                }
 
270
                write_unlock_bh(&local->sub_if_lock);
 
271
 
 
272
                list_for_each_entry_safe(tsdata, n, &tmp_list, list)
 
273
                        __ieee80211_if_del(local, tsdata);
 
274
 
 
275
                kfree(sdata->u.ap.beacon_head);
 
276
                kfree(sdata->u.ap.beacon_tail);
 
277
                kfree(sdata->u.ap.generic_elem);
 
278
 
 
279
                if (dev != local->mdev) {
 
280
                        struct sk_buff *skb;
 
281
                        while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
 
282
                                local->total_ps_buffered--;
 
283
                                dev_kfree_skb(skb);
 
284
                        }
 
285
                }
 
286
 
 
287
                break;
 
288
        }
 
289
        case IEEE80211_IF_TYPE_WDS:
 
290
                sta = iwlwifi_sta_info_get(local, sdata->u.wds.remote_addr);
 
291
                if (sta) {
 
292
                        iwlwifi_sta_info_put(sta);
 
293
                        sta_info_free(sta, 0);
 
294
                } else {
 
295
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 
296
                        printk(KERN_DEBUG "%s: Someone had deleted my STA "
 
297
                               "entry for the WDS link\n", dev->name);
 
298
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
 
299
                }
 
300
                break;
 
301
        case IEEE80211_IF_TYPE_STA:
 
302
        case IEEE80211_IF_TYPE_IBSS:
 
303
                kfree(sdata->u.sta.extra_ie);
 
304
                sdata->u.sta.extra_ie = NULL;
 
305
                kfree(sdata->u.sta.assocreq_ies);
 
306
                sdata->u.sta.assocreq_ies = NULL;
 
307
                kfree(sdata->u.sta.assocresp_ies);
 
308
                sdata->u.sta.assocresp_ies = NULL;
 
309
                if (sdata->u.sta.probe_resp) {
 
310
                        dev_kfree_skb(sdata->u.sta.probe_resp);
 
311
                        sdata->u.sta.probe_resp = NULL;
 
312
                }
 
313
 
 
314
                break;
 
315
        case IEEE80211_IF_TYPE_MNTR:
 
316
                dev->type = ARPHRD_ETHER;
 
317
                break;
 
318
        }
 
319
 
 
320
        /* remove all STAs that are bound to this virtual interface */
 
321
        sta_info_flush(local, dev);
 
322
 
 
323
        memset(&sdata->u, 0, sizeof(sdata->u));
 
324
        ieee80211_if_sdata_init(sdata);
 
325
}
 
326
 
 
327
/* Must be called with rtnl lock held. */
 
328
void __ieee80211_if_del(struct ieee80211_local *local,
 
329
                        struct ieee80211_sub_if_data *sdata)
 
330
{
 
331
        struct net_device *dev = sdata->dev;
 
332
 
 
333
        ieee80211_debugfs_remove_netdev(sdata);
 
334
        unregister_netdevice(dev);
 
335
        /* Except master interface, the net_device will be freed by
 
336
         * net_device->destructor (i. e. ieee80211_if_free). */
 
337
}
 
338
 
 
339
/* Must be called with rtnl lock held. */
 
340
int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
 
341
{
 
342
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
343
        struct ieee80211_sub_if_data *sdata, *n;
 
344
 
 
345
        ASSERT_RTNL();
 
346
 
 
347
        write_lock_bh(&local->sub_if_lock);
 
348
        list_for_each_entry_safe(sdata, n, &local->sub_if_list, list) {
 
349
                if ((sdata->type == id || id == -1) &&
 
350
                    strcmp(name, sdata->dev->name) == 0 &&
 
351
                    sdata->dev != local->mdev) {
 
352
                        list_del(&sdata->list);
 
353
                        write_unlock_bh(&local->sub_if_lock);
 
354
                        __ieee80211_if_del(local, sdata);
 
355
                        ieee80211_update_default_wep_only(local);
 
356
                        return 0;
 
357
                }
 
358
        }
 
359
        write_unlock_bh(&local->sub_if_lock);
 
360
        return -ENODEV;
 
361
}
 
362
 
 
363
void ieee80211_if_free(struct net_device *dev)
 
364
{
 
365
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
366
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
367
 
 
368
        /* local->apdev must be NULL when freeing management interface */
 
369
        BUG_ON(dev == local->apdev);
 
370
        ieee80211_if_sdata_deinit(sdata);
 
371
        free_netdev(dev);
 
372
}