~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/wireless/core.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
 * This is the linux wireless configuration interface.
 
3
 *
 
4
 * Copyright 2006, 2007         Johannes Berg <johannes@sipsolutions.net>
 
5
 */
 
6
 
 
7
#include <linux/if.h>
 
8
#include <linux/module.h>
 
9
#include <linux/err.h>
 
10
#include <linux/mutex.h>
 
11
#include <linux/list.h>
 
12
#include <linux/nl80211.h>
 
13
#include <linux/debugfs.h>
 
14
#include <linux/notifier.h>
 
15
#include <linux/device.h>
 
16
#include <net/genetlink.h>
 
17
#include <net/cfg80211.h>
 
18
#include <net/wireless.h>
 
19
#include "core.h"
 
20
#include "sysfs.h"
 
21
 
 
22
/* name for sysfs, %d is appended */
 
23
#define PHY_NAME "phy"
 
24
 
 
25
MODULE_AUTHOR("Johannes Berg");
 
26
MODULE_LICENSE("GPL");
 
27
MODULE_DESCRIPTION("wireless configuration support");
 
28
 
 
29
/* RCU might be appropriate here since we usually
 
30
 * only read the list, and that can happen quite
 
31
 * often because we need to do it for each command */
 
32
LIST_HEAD(cfg80211_drv_list);
 
33
DEFINE_MUTEX(cfg80211_drv_mutex);
 
34
static int wiphy_counter;
 
35
 
 
36
/* for debugfs */
 
37
static struct dentry *ieee80211_debugfs_dir;
 
38
 
 
39
/* exported functions */
 
40
 
 
41
struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
 
42
{
 
43
        struct cfg80211_registered_device *drv;
 
44
        int alloc_size;
 
45
 
 
46
        alloc_size = sizeof(*drv) + sizeof_priv;
 
47
 
 
48
        drv = kzalloc(alloc_size, GFP_KERNEL);
 
49
        if (!drv)
 
50
                return NULL;
 
51
 
 
52
        drv->ops = ops;
 
53
 
 
54
        mutex_lock(&cfg80211_drv_mutex);
 
55
 
 
56
        drv->idx = wiphy_counter;
 
57
 
 
58
        /* now increase counter for the next device unless
 
59
         * it has wrapped previously */
 
60
        if (wiphy_counter >= 0)
 
61
                wiphy_counter++;
 
62
 
 
63
        mutex_unlock(&cfg80211_drv_mutex);
 
64
 
 
65
        if (unlikely(drv->idx < 0)) {
 
66
                /* ugh, wrapped! */
 
67
                kfree(drv);
 
68
                return NULL;
 
69
        }
 
70
 
 
71
        /* give it a proper name */
 
72
        snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
 
73
                 PHY_NAME "%d", drv->idx);
 
74
 
 
75
        mutex_init(&drv->mtx);
 
76
        mutex_init(&drv->devlist_mtx);
 
77
        INIT_LIST_HEAD(&drv->netdev_list);
 
78
 
 
79
        device_initialize(&drv->wiphy.dev);
 
80
        drv->wiphy.dev.class = &ieee80211_class;
 
81
        drv->wiphy.dev.platform_data = drv;
 
82
 
 
83
        return &drv->wiphy;
 
84
}
 
85
EXPORT_SYMBOL(wiphy_new);
 
86
 
 
87
int wiphy_register(struct wiphy *wiphy)
 
88
{
 
89
        struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
 
90
        int res;
 
91
 
 
92
        mutex_lock(&cfg80211_drv_mutex);
 
93
 
 
94
        res = device_add(&drv->wiphy.dev);
 
95
        if (res)
 
96
                goto out_unlock;
 
97
 
 
98
        list_add(&drv->list, &cfg80211_drv_list);
 
99
 
 
100
        /* add to debugfs */
 
101
        drv->wiphy.debugfsdir =
 
102
                debugfs_create_dir(wiphy_name(&drv->wiphy),
 
103
                                   ieee80211_debugfs_dir);
 
104
 
 
105
        res = 0;
 
106
out_unlock:
 
107
        mutex_unlock(&cfg80211_drv_mutex);
 
108
        return res;
 
109
}
 
110
EXPORT_SYMBOL(wiphy_register);
 
111
 
 
112
void wiphy_unregister(struct wiphy *wiphy)
 
113
{
 
114
        struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
 
115
 
 
116
        /* protect the device list */
 
117
        mutex_lock(&cfg80211_drv_mutex);
 
118
 
 
119
        BUG_ON(!list_empty(&drv->netdev_list));
 
120
 
 
121
        /*
 
122
         * Try to grab drv->mtx. If a command is still in progress,
 
123
         * hopefully the driver will refuse it since it's tearing
 
124
         * down the device already. We wait for this command to complete
 
125
         * before unlinking the item from the list.
 
126
         * Note: as codified by the BUG_ON above we cannot get here if
 
127
         * a virtual interface is still associated. Hence, we can only
 
128
         * get to lock contention here if userspace issues a command
 
129
         * that identified the hardware by wiphy index.
 
130
         */
 
131
        mutex_lock(&drv->mtx);
 
132
        /* unlock again before freeing */
 
133
        mutex_unlock(&drv->mtx);
 
134
 
 
135
        list_del(&drv->list);
 
136
        device_del(&drv->wiphy.dev);
 
137
        debugfs_remove(drv->wiphy.debugfsdir);
 
138
 
 
139
        mutex_unlock(&cfg80211_drv_mutex);
 
140
}
 
141
EXPORT_SYMBOL(wiphy_unregister);
 
142
 
 
143
void cfg80211_dev_free(struct cfg80211_registered_device *drv)
 
144
{
 
145
        mutex_destroy(&drv->mtx);
 
146
        mutex_destroy(&drv->devlist_mtx);
 
147
        kfree(drv);
 
148
}
 
149
 
 
150
void wiphy_free(struct wiphy *wiphy)
 
151
{
 
152
        put_device(&wiphy->dev);
 
153
}
 
154
EXPORT_SYMBOL(wiphy_free);
 
155
 
 
156
static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 
157
                                         unsigned long state,
 
158
                                         void *ndev)
 
159
{
 
160
        struct net_device *dev = ndev;
 
161
        struct cfg80211_registered_device *rdev;
 
162
 
 
163
        if (!dev->ieee80211_ptr)
 
164
                return 0;
 
165
 
 
166
        rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
 
167
 
 
168
        switch (state) {
 
169
        case NETDEV_REGISTER:
 
170
                mutex_lock(&rdev->devlist_mtx);
 
171
                list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
 
172
                if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
 
173
                                      "phy80211")) {
 
174
                        printk(KERN_ERR "wireless: failed to add phy80211 "
 
175
                                "symlink to netdev!\n");
 
176
                }
 
177
                dev->ieee80211_ptr->netdev = dev;
 
178
                mutex_unlock(&rdev->devlist_mtx);
 
179
                break;
 
180
        case NETDEV_UNREGISTER:
 
181
                mutex_lock(&rdev->devlist_mtx);
 
182
                if (!list_empty(&dev->ieee80211_ptr->list)) {
 
183
                        sysfs_remove_link(&dev->dev.kobj, "phy80211");
 
184
                        list_del_init(&dev->ieee80211_ptr->list);
 
185
                }
 
186
                mutex_unlock(&rdev->devlist_mtx);
 
187
                break;
 
188
        }
 
189
 
 
190
        return 0;
 
191
}
 
192
 
 
193
static struct notifier_block cfg80211_netdev_notifier = {
 
194
        .notifier_call = cfg80211_netdev_notifier_call,
 
195
};
 
196
 
 
197
static int cfg80211_init(void)
 
198
{
 
199
        int err = wiphy_sysfs_init();
 
200
        if (err)
 
201
                goto out_fail_sysfs;
 
202
 
 
203
        err = register_netdevice_notifier(&cfg80211_netdev_notifier);
 
204
        if (err)
 
205
                goto out_fail_notifier;
 
206
 
 
207
        ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
 
208
 
 
209
        return 0;
 
210
 
 
211
out_fail_notifier:
 
212
        wiphy_sysfs_exit();
 
213
out_fail_sysfs:
 
214
        return err;
 
215
}
 
216
module_init(cfg80211_init);
 
217
 
 
218
static void cfg80211_exit(void)
 
219
{
 
220
        debugfs_remove(ieee80211_debugfs_dir);
 
221
        unregister_netdevice_notifier(&cfg80211_netdev_notifier);
 
222
        wiphy_sysfs_exit();
 
223
}
 
224
module_exit(cfg80211_exit);