core.c 18.0 KB
Newer Older
1 2 3
/*
 * This is the linux wireless configuration interface.
 *
4
 * Copyright 2006-2009		Johannes Berg <johannes@sipsolutions.net>
5 6 7 8 9 10 11 12 13 14
 */

#include <linux/if.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/nl80211.h>
#include <linux/debugfs.h>
#include <linux/notifier.h>
#include <linux/device.h>
J
Johannes Berg 已提交
15
#include <linux/rtnetlink.h>
16 17
#include <net/genetlink.h>
#include <net/cfg80211.h>
18
#include "nl80211.h"
19 20
#include "core.h"
#include "sysfs.h"
21
#include "debugfs.h"
22 23 24 25 26 27 28 29 30 31 32

/* name for sysfs, %d is appended */
#define PHY_NAME "phy"

MODULE_AUTHOR("Johannes Berg");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");

/* RCU might be appropriate here since we usually
 * only read the list, and that can happen quite
 * often because we need to do it for each command */
33
LIST_HEAD(cfg80211_rdev_list);
34 35

/*
36
 * This is used to protect the cfg80211_rdev_list, cfg80211_regdomain,
37 38
 * country_ie_regdomain, the reg_beacon_list and the the last regulatory
 * request receipt (last_request).
39 40
 */
DEFINE_MUTEX(cfg80211_mutex);
41 42 43 44

/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;

45
/* requires cfg80211_mutex to be held! */
46
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
47
{
48
	struct cfg80211_registered_device *result = NULL, *rdev;
49

50 51 52
	if (!wiphy_idx_valid(wiphy_idx))
		return NULL;

53 54
	assert_cfg80211_lock();

55 56 57
	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
		if (rdev->wiphy_idx == wiphy_idx) {
			result = rdev;
58 59 60 61 62 63 64
			break;
		}
	}

	return result;
}

65 66
int get_wiphy_idx(struct wiphy *wiphy)
{
67
	struct cfg80211_registered_device *rdev;
68 69
	if (!wiphy)
		return WIPHY_IDX_STALE;
70 71
	rdev = wiphy_to_dev(wiphy);
	return rdev->wiphy_idx;
72 73
}

74
/* requires cfg80211_rdev_mutex to be held! */
75 76
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{
77
	struct cfg80211_registered_device *rdev;
78 79 80 81 82 83

	if (!wiphy_idx_valid(wiphy_idx))
		return NULL;

	assert_cfg80211_lock();

84 85
	rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
	if (!rdev)
86
		return NULL;
87
	return &rdev->wiphy;
88 89
}

90
/* requires cfg80211_mutex to be held! */
91
struct cfg80211_registered_device *
92
__cfg80211_rdev_from_info(struct genl_info *info)
93 94
{
	int ifindex;
95
	struct cfg80211_registered_device *bywiphyidx = NULL, *byifidx = NULL;
96 97 98
	struct net_device *dev;
	int err = -EINVAL;

99 100
	assert_cfg80211_lock();

101
	if (info->attrs[NL80211_ATTR_WIPHY]) {
102
		bywiphyidx = cfg80211_rdev_by_wiphy_idx(
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
				nla_get_u32(info->attrs[NL80211_ATTR_WIPHY]));
		err = -ENODEV;
	}

	if (info->attrs[NL80211_ATTR_IFINDEX]) {
		ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
		dev = dev_get_by_index(&init_net, ifindex);
		if (dev) {
			if (dev->ieee80211_ptr)
				byifidx =
					wiphy_to_dev(dev->ieee80211_ptr->wiphy);
			dev_put(dev);
		}
		err = -ENODEV;
	}

119 120
	if (bywiphyidx && byifidx) {
		if (bywiphyidx != byifidx)
121 122
			return ERR_PTR(-EINVAL);
		else
123
			return bywiphyidx; /* == byifidx */
124
	}
125 126
	if (bywiphyidx)
		return bywiphyidx;
127 128 129 130 131 132 133 134 135 136

	if (byifidx)
		return byifidx;

	return ERR_PTR(err);
}

struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct genl_info *info)
{
137
	struct cfg80211_registered_device *rdev;
138

139
	mutex_lock(&cfg80211_mutex);
140
	rdev = __cfg80211_rdev_from_info(info);
141 142 143 144

	/* if it is not an error we grab the lock on
	 * it to assure it won't be going away while
	 * we operate on it */
145 146
	if (!IS_ERR(rdev))
		mutex_lock(&rdev->mtx);
147

148
	mutex_unlock(&cfg80211_mutex);
149

150
	return rdev;
151 152 153 154 155
}

struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(int ifindex)
{
156
	struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
157 158
	struct net_device *dev;

159
	mutex_lock(&cfg80211_mutex);
160 161 162 163
	dev = dev_get_by_index(&init_net, ifindex);
	if (!dev)
		goto out;
	if (dev->ieee80211_ptr) {
164 165
		rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
		mutex_lock(&rdev->mtx);
166
	} else
167
		rdev = ERR_PTR(-ENODEV);
168 169
	dev_put(dev);
 out:
170
	mutex_unlock(&cfg80211_mutex);
171
	return rdev;
172 173
}

174
/* requires cfg80211_mutex to be held */
175 176 177
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
			char *newname)
{
178
	struct cfg80211_registered_device *rdev2;
179
	int wiphy_idx, taken = -1, result, digits;
180

181
	assert_cfg80211_lock();
182

183
	/* prohibit calling the thing phy%d when %d is not its number */
184 185 186
	sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
	if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
		/* count number of places needed to print wiphy_idx */
187
		digits = 1;
188
		while (wiphy_idx /= 10)
189 190 191 192 193 194
			digits++;
		/*
		 * deny the name if it is phy<idx> where <idx> is printed
		 * without leading zeroes. taken == strlen(newname) here
		 */
		if (taken == strlen(PHY_NAME) + digits)
195
			return -EINVAL;
196 197 198 199 200
	}


	/* Ignore nop renames */
	if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
201
		return 0;
202 203

	/* Ensure another device does not already have this name. */
204 205
	list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
		if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
206
			return -EINVAL;
207 208 209

	result = device_rename(&rdev->wiphy.dev, newname);
	if (result)
210
		return result;
211

212 213
	if (rdev->wiphy.debugfsdir &&
	    !debugfs_rename(rdev->wiphy.debugfsdir->d_parent,
214 215 216 217 218 219
			    rdev->wiphy.debugfsdir,
			    rdev->wiphy.debugfsdir->d_parent,
			    newname))
		printk(KERN_ERR "cfg80211: failed to rename debugfs dir to %s!\n",
		       newname);

220
	nl80211_notify_dev_rename(rdev);
221

222
	return 0;
223 224
}

J
Johannes Berg 已提交
225 226
static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
{
227
	struct cfg80211_registered_device *rdev = data;
J
Johannes Berg 已提交
228

229
	rdev->ops->rfkill_poll(&rdev->wiphy);
J
Johannes Berg 已提交
230 231 232 233
}

static int cfg80211_rfkill_set_block(void *data, bool blocked)
{
234
	struct cfg80211_registered_device *rdev = data;
J
Johannes Berg 已提交
235 236 237 238 239 240
	struct wireless_dev *wdev;

	if (!blocked)
		return 0;

	rtnl_lock();
241
	mutex_lock(&rdev->devlist_mtx);
J
Johannes Berg 已提交
242

243
	list_for_each_entry(wdev, &rdev->netdev_list, list)
J
Johannes Berg 已提交
244 245
		dev_close(wdev->netdev);

246
	mutex_unlock(&rdev->devlist_mtx);
J
Johannes Berg 已提交
247 248 249 250 251 252 253
	rtnl_unlock();

	return 0;
}

static void cfg80211_rfkill_sync_work(struct work_struct *work)
{
254
	struct cfg80211_registered_device *rdev;
J
Johannes Berg 已提交
255

256 257
	rdev = container_of(work, struct cfg80211_registered_device, rfkill_sync);
	cfg80211_rfkill_set_block(rdev, rfkill_blocked(rdev->rfkill));
J
Johannes Berg 已提交
258 259
}

J
Johannes Berg 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
static void cfg80211_process_events(struct wireless_dev *wdev)
{
	struct cfg80211_event *ev;
	unsigned long flags;

	spin_lock_irqsave(&wdev->event_lock, flags);
	while (!list_empty(&wdev->event_list)) {
		ev = list_first_entry(&wdev->event_list,
				      struct cfg80211_event, list);
		list_del(&ev->list);
		spin_unlock_irqrestore(&wdev->event_lock, flags);

		wdev_lock(wdev);
		switch (ev->type) {
		case EVENT_CONNECT_RESULT:
			__cfg80211_connect_result(
				wdev->netdev, ev->cr.bssid,
				ev->cr.req_ie, ev->cr.req_ie_len,
				ev->cr.resp_ie, ev->cr.resp_ie_len,
				ev->cr.status,
				ev->cr.status == WLAN_STATUS_SUCCESS);
			break;
		case EVENT_ROAMED:
			__cfg80211_roamed(wdev, ev->rm.bssid,
					  ev->rm.req_ie, ev->rm.req_ie_len,
					  ev->rm.resp_ie, ev->rm.resp_ie_len);
			break;
		case EVENT_DISCONNECTED:
			__cfg80211_disconnected(wdev->netdev,
						ev->dc.ie, ev->dc.ie_len,
						ev->dc.reason, true);
			break;
		case EVENT_IBSS_JOINED:
			__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
			break;
		}
		wdev_unlock(wdev);

		kfree(ev);

		spin_lock_irqsave(&wdev->event_lock, flags);
	}
	spin_unlock_irqrestore(&wdev->event_lock, flags);
}

static void cfg80211_event_work(struct work_struct *work)
{
	struct cfg80211_registered_device *rdev;
	struct wireless_dev *wdev;

	rdev = container_of(work, struct cfg80211_registered_device,
			    event_work);

	rtnl_lock();
	cfg80211_lock_rdev(rdev);
	mutex_lock(&rdev->devlist_mtx);

	list_for_each_entry(wdev, &rdev->netdev_list, list)
		cfg80211_process_events(wdev);

	mutex_unlock(&rdev->devlist_mtx);
	cfg80211_unlock_rdev(rdev);
	rtnl_unlock();
}

325 326
/* exported functions */

327
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
328
{
329 330
	static int wiphy_counter;

331
	struct cfg80211_registered_device *rdev;
332 333
	int alloc_size;

334 335 336 337 338 339 340
	WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
	WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
	WARN_ON(ops->connect && !ops->disconnect);
	WARN_ON(ops->join_ibss && !ops->leave_ibss);
	WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
	WARN_ON(ops->add_station && !ops->del_station);
	WARN_ON(ops->add_mpath && !ops->del_mpath);
341

342
	alloc_size = sizeof(*rdev) + sizeof_priv;
343

344 345
	rdev = kzalloc(alloc_size, GFP_KERNEL);
	if (!rdev)
346 347
		return NULL;

348
	rdev->ops = ops;
349

350
	mutex_lock(&cfg80211_mutex);
351

352
	rdev->wiphy_idx = wiphy_counter++;
353

354
	if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) {
355
		wiphy_counter--;
356
		mutex_unlock(&cfg80211_mutex);
357
		/* ugh, wrapped! */
358
		kfree(rdev);
359 360 361
		return NULL;
	}

362
	mutex_unlock(&cfg80211_mutex);
363

364
	/* give it a proper name */
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
	dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);

	mutex_init(&rdev->mtx);
	mutex_init(&rdev->devlist_mtx);
	INIT_LIST_HEAD(&rdev->netdev_list);
	spin_lock_init(&rdev->bss_lock);
	INIT_LIST_HEAD(&rdev->bss_list);
	INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);

	device_initialize(&rdev->wiphy.dev);
	rdev->wiphy.dev.class = &ieee80211_class;
	rdev->wiphy.dev.platform_data = rdev;

	rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
	rdev->rfkill = rfkill_alloc(dev_name(&rdev->wiphy.dev),
				   &rdev->wiphy.dev, RFKILL_TYPE_WLAN,
				   &rdev->rfkill_ops, rdev);

	if (!rdev->rfkill) {
		kfree(rdev);
J
Johannes Berg 已提交
385 386 387
		return NULL;
	}

388 389 390
	INIT_WORK(&rdev->rfkill_sync, cfg80211_rfkill_sync_work);
	INIT_WORK(&rdev->conn_work, cfg80211_conn_work);
	INIT_WORK(&rdev->event_work, cfg80211_event_work);
J
Johannes Berg 已提交
391

392 393 394 395 396
	/*
	 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
	 * Fragmentation and RTS threshold are disabled by default with the
	 * special -1 value.
	 */
397 398 399 400
	rdev->wiphy.retry_short = 7;
	rdev->wiphy.retry_long = 4;
	rdev->wiphy.frag_threshold = (u32) -1;
	rdev->wiphy.rts_threshold = (u32) -1;
401

402
	return &rdev->wiphy;
403 404 405 406 407
}
EXPORT_SYMBOL(wiphy_new);

int wiphy_register(struct wiphy *wiphy)
{
408
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
409
	int res;
410 411 412 413
	enum ieee80211_band band;
	struct ieee80211_supported_band *sband;
	bool have_band = false;
	int i;
414 415 416 417 418 419 420
	u16 ifmodes = wiphy->interface_modes;

	/* sanity check ifmodes */
	WARN_ON(!ifmodes);
	ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
	if (WARN_ON(ifmodes != wiphy->interface_modes))
		wiphy->interface_modes = ifmodes;
421 422 423 424 425 426 427 428 429

	/* sanity check supported bands/channels */
	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		sband = wiphy->bands[band];
		if (!sband)
			continue;

		sband->band = band;

430 431 432 433 434 435 436 437 438
		if (WARN_ON(!sband->n_channels || !sband->n_bitrates))
			return -EINVAL;

		/*
		 * Since we use a u32 for rate bitmaps in
		 * ieee80211_get_response_rate, we cannot
		 * have more than 32 legacy rates.
		 */
		if (WARN_ON(sband->n_bitrates > 32))
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
			return -EINVAL;

		for (i = 0; i < sband->n_channels; i++) {
			sband->channels[i].orig_flags =
				sband->channels[i].flags;
			sband->channels[i].orig_mag =
				sband->channels[i].max_antenna_gain;
			sband->channels[i].orig_mpwr =
				sband->channels[i].max_power;
			sband->channels[i].band = band;
		}

		have_band = true;
	}

	if (!have_band) {
		WARN_ON(1);
		return -EINVAL;
	}

	/* check and set up bitrates */
	ieee80211_set_bitrate_flags(wiphy);

462
	res = device_add(&rdev->wiphy.dev);
463
	if (res)
464
		return res;
465

466
	res = rfkill_register(rdev->rfkill);
J
Johannes Berg 已提交
467 468 469
	if (res)
		goto out_rm_dev;

470 471 472 473 474
	mutex_lock(&cfg80211_mutex);

	/* set up regulatory info */
	wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);

475
	list_add(&rdev->list, &cfg80211_rdev_list);
476

477 478
	mutex_unlock(&cfg80211_mutex);

479
	/* add to debugfs */
480 481
	rdev->wiphy.debugfsdir =
		debugfs_create_dir(wiphy_name(&rdev->wiphy),
482
				   ieee80211_debugfs_dir);
483 484
	if (IS_ERR(rdev->wiphy.debugfsdir))
		rdev->wiphy.debugfsdir = NULL;
485

486 487 488 489 490 491 492 493 494 495 496
	if (wiphy->custom_regulatory) {
		struct regulatory_request request;

		request.wiphy_idx = get_wiphy_idx(wiphy);
		request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
		request.alpha2[0] = '9';
		request.alpha2[1] = '9';

		nl80211_send_reg_change_event(&request);
	}

497
	cfg80211_debugfs_rdev_add(rdev);
498

499
	return 0;
J
Johannes Berg 已提交
500 501

 out_rm_dev:
502
	device_del(&rdev->wiphy.dev);
503 504 505 506
	return res;
}
EXPORT_SYMBOL(wiphy_register);

J
Johannes Berg 已提交
507 508
void wiphy_rfkill_start_polling(struct wiphy *wiphy)
{
509
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
J
Johannes Berg 已提交
510

511
	if (!rdev->ops->rfkill_poll)
J
Johannes Berg 已提交
512
		return;
513 514
	rdev->rfkill_ops.poll = cfg80211_rfkill_poll;
	rfkill_resume_polling(rdev->rfkill);
J
Johannes Berg 已提交
515 516 517 518 519
}
EXPORT_SYMBOL(wiphy_rfkill_start_polling);

void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
{
520
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
J
Johannes Berg 已提交
521

522
	rfkill_pause_polling(rdev->rfkill);
J
Johannes Berg 已提交
523 524 525
}
EXPORT_SYMBOL(wiphy_rfkill_stop_polling);

526 527
void wiphy_unregister(struct wiphy *wiphy)
{
528
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
529

530
	rfkill_unregister(rdev->rfkill);
J
Johannes Berg 已提交
531

532
	/* protect the device list */
533
	mutex_lock(&cfg80211_mutex);
534

535
	BUG_ON(!list_empty(&rdev->netdev_list));
536 537

	/*
538
	 * Try to grab rdev->mtx. If a command is still in progress,
539 540 541 542 543 544 545 546
	 * hopefully the driver will refuse it since it's tearing
	 * down the device already. We wait for this command to complete
	 * before unlinking the item from the list.
	 * Note: as codified by the BUG_ON above we cannot get here if
	 * a virtual interface is still associated. Hence, we can only
	 * get to lock contention here if userspace issues a command
	 * that identified the hardware by wiphy index.
	 */
547
	mutex_lock(&rdev->mtx);
548
	/* unlock again before freeing */
549
	mutex_unlock(&rdev->mtx);
550

551 552 553 554
	cancel_work_sync(&rdev->conn_work);
	cancel_work_sync(&rdev->scan_done_wk);
	kfree(rdev->scan_req);
	flush_work(&rdev->event_work);
555

556
	cfg80211_debugfs_rdev_del(rdev);
557

558 559 560 561
	/* If this device got a regulatory hint tell core its
	 * free to listen now to a new shiny device regulatory hint */
	reg_device_remove(wiphy);

562 563 564
	list_del(&rdev->list);
	device_del(&rdev->wiphy.dev);
	debugfs_remove(rdev->wiphy.debugfsdir);
565

566
	mutex_unlock(&cfg80211_mutex);
567 568 569
}
EXPORT_SYMBOL(wiphy_unregister);

570
void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
571
{
572
	struct cfg80211_internal_bss *scan, *tmp;
573 574 575 576
	rfkill_destroy(rdev->rfkill);
	mutex_destroy(&rdev->mtx);
	mutex_destroy(&rdev->devlist_mtx);
	list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list)
J
Johannes Berg 已提交
577
		cfg80211_put_bss(&scan->pub);
578
	kfree(rdev);
579 580 581 582 583 584 585 586
}

void wiphy_free(struct wiphy *wiphy)
{
	put_device(&wiphy->dev);
}
EXPORT_SYMBOL(wiphy_free);

J
Johannes Berg 已提交
587 588
void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
{
589
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
J
Johannes Berg 已提交
590

591 592
	if (rfkill_set_hw_state(rdev->rfkill, blocked))
		schedule_work(&rdev->rfkill_sync);
J
Johannes Berg 已提交
593 594 595
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);

596 597 598 599 600
static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
					 unsigned long state,
					 void *ndev)
{
	struct net_device *dev = ndev;
601
	struct wireless_dev *wdev = dev->ieee80211_ptr;
602 603
	struct cfg80211_registered_device *rdev;

604
	if (!wdev)
J
Johannes Berg 已提交
605
		return NOTIFY_DONE;
606

607
	rdev = wiphy_to_dev(wdev->wiphy);
608

609
	WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
J
Johannes Berg 已提交
610

611 612
	switch (state) {
	case NETDEV_REGISTER:
J
Johannes Berg 已提交
613 614 615
		mutex_init(&wdev->mtx);
		INIT_LIST_HEAD(&wdev->event_list);
		spin_lock_init(&wdev->event_lock);
616
		mutex_lock(&rdev->devlist_mtx);
617
		list_add(&wdev->list, &rdev->netdev_list);
618 619 620 621 622
		if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
				      "phy80211")) {
			printk(KERN_ERR "wireless: failed to add phy80211 "
				"symlink to netdev!\n");
		}
623
		wdev->netdev = dev;
S
Samuel Ortiz 已提交
624
		wdev->sme_state = CFG80211_SME_IDLE;
J
Johannes Berg 已提交
625
		mutex_unlock(&rdev->devlist_mtx);
626
#ifdef CONFIG_WIRELESS_EXT
627 628
		wdev->wext.default_key = -1;
		wdev->wext.default_mgmt_key = -1;
629
		wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
J
Johannes Berg 已提交
630 631 632 633 634 635 636 637 638
		wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE;
		wdev->wext.ps_timeout = 500;
		if (rdev->ops->set_power_mgmt)
			if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
						      wdev->wext.ps,
						      wdev->wext.ps_timeout)) {
				/* assume this means it's off */
				wdev->wext.ps = false;
			}
639
#endif
640
		break;
J
Johannes Berg 已提交
641
	case NETDEV_GOING_DOWN:
S
Samuel Ortiz 已提交
642 643 644 645 646
		switch (wdev->iftype) {
		case NL80211_IFTYPE_ADHOC:
			cfg80211_leave_ibss(rdev, dev, true);
			break;
		case NL80211_IFTYPE_STATION:
J
Johannes Berg 已提交
647
			wdev_lock(wdev);
648 649 650 651
#ifdef CONFIG_WIRELESS_EXT
			kfree(wdev->wext.ie);
			wdev->wext.ie = NULL;
			wdev->wext.ie_len = 0;
J
Johannes Berg 已提交
652
			wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
653
#endif
J
Johannes Berg 已提交
654 655
			__cfg80211_disconnect(rdev, dev,
					      WLAN_REASON_DEAUTH_LEAVING, true);
J
Johannes Berg 已提交
656
			cfg80211_mlme_down(rdev, dev);
J
Johannes Berg 已提交
657
			wdev_unlock(wdev);
S
Samuel Ortiz 已提交
658 659 660 661
			break;
		default:
			break;
		}
J
Johannes Berg 已提交
662 663 664
		break;
	case NETDEV_UP:
#ifdef CONFIG_WIRELESS_EXT
J
Johannes Berg 已提交
665 666
		cfg80211_lock_rdev(rdev);
		wdev_lock(wdev);
667 668
		switch (wdev->iftype) {
		case NL80211_IFTYPE_ADHOC:
J
Johannes Berg 已提交
669
			cfg80211_ibss_wext_join(rdev, wdev);
J
Johannes Berg 已提交
670
			break;
671
		case NL80211_IFTYPE_STATION:
J
Johannes Berg 已提交
672
			cfg80211_mgd_wext_connect(rdev, wdev);
673 674
			break;
		default:
J
Johannes Berg 已提交
675
			break;
676
		}
J
Johannes Berg 已提交
677 678
		wdev_unlock(wdev);
		cfg80211_unlock_rdev(rdev);
J
Johannes Berg 已提交
679
#endif
680
		break;
681 682
	case NETDEV_UNREGISTER:
		mutex_lock(&rdev->devlist_mtx);
683
		if (!list_empty(&wdev->list)) {
684
			sysfs_remove_link(&dev->dev.kobj, "phy80211");
685
			list_del_init(&wdev->list);
686 687
		}
		mutex_unlock(&rdev->devlist_mtx);
J
Johannes Berg 已提交
688
		mutex_destroy(&wdev->mtx);
J
Johannes Berg 已提交
689 690 691
#ifdef CONFIG_WIRELESS_EXT
		kfree(wdev->wext.keys);
#endif
692
		break;
J
Johannes Berg 已提交
693
	case NETDEV_PRE_UP:
694 695
		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
			return notifier_from_errno(-EOPNOTSUPP);
J
Johannes Berg 已提交
696 697 698
		if (rfkill_blocked(rdev->rfkill))
			return notifier_from_errno(-ERFKILL);
		break;
699 700
	}

J
Johannes Berg 已提交
701
	return NOTIFY_DONE;
702 703 704 705 706 707 708 709
}

static struct notifier_block cfg80211_netdev_notifier = {
	.notifier_call = cfg80211_netdev_notifier_call,
};

static int cfg80211_init(void)
{
710 711 712
	int err;

	err = wiphy_sysfs_init();
713 714 715 716 717 718 719
	if (err)
		goto out_fail_sysfs;

	err = register_netdevice_notifier(&cfg80211_netdev_notifier);
	if (err)
		goto out_fail_notifier;

720 721 722 723
	err = nl80211_init();
	if (err)
		goto out_fail_nl80211;

724 725
	ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);

726 727 728 729
	err = regulatory_init();
	if (err)
		goto out_fail_reg;

730 731
	return 0;

732 733
out_fail_reg:
	debugfs_remove(ieee80211_debugfs_dir);
734 735
out_fail_nl80211:
	unregister_netdevice_notifier(&cfg80211_netdev_notifier);
736 737 738 739 740
out_fail_notifier:
	wiphy_sysfs_exit();
out_fail_sysfs:
	return err;
}
741

742
subsys_initcall(cfg80211_init);
743 744 745 746

static void cfg80211_exit(void)
{
	debugfs_remove(ieee80211_debugfs_dir);
747
	nl80211_exit();
748 749
	unregister_netdevice_notifier(&cfg80211_netdev_notifier);
	wiphy_sysfs_exit();
750
	regulatory_exit();
751 752
}
module_exit(cfg80211_exit);