aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c148
1 files changed, 136 insertions, 12 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index d1f556535f6d..d5850292b3df 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
@@ -12,12 +12,13 @@
12#include <linux/debugfs.h> 12#include <linux/debugfs.h>
13#include <linux/notifier.h> 13#include <linux/notifier.h>
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/rtnetlink.h>
15#include <net/genetlink.h> 16#include <net/genetlink.h>
16#include <net/cfg80211.h> 17#include <net/cfg80211.h>
17#include <net/wireless.h>
18#include "nl80211.h" 18#include "nl80211.h"
19#include "core.h" 19#include "core.h"
20#include "sysfs.h" 20#include "sysfs.h"
21#include "debugfs.h"
21 22
22/* name for sysfs, %d is appended */ 23/* name for sysfs, %d is appended */
23#define PHY_NAME "phy" 24#define PHY_NAME "phy"
@@ -227,9 +228,44 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
227 return 0; 228 return 0;
228} 229}
229 230
231static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
232{
233 struct cfg80211_registered_device *drv = data;
234
235 drv->ops->rfkill_poll(&drv->wiphy);
236}
237
238static int cfg80211_rfkill_set_block(void *data, bool blocked)
239{
240 struct cfg80211_registered_device *drv = data;
241 struct wireless_dev *wdev;
242
243 if (!blocked)
244 return 0;
245
246 rtnl_lock();
247 mutex_lock(&drv->devlist_mtx);
248
249 list_for_each_entry(wdev, &drv->netdev_list, list)
250 dev_close(wdev->netdev);
251
252 mutex_unlock(&drv->devlist_mtx);
253 rtnl_unlock();
254
255 return 0;
256}
257
258static void cfg80211_rfkill_sync_work(struct work_struct *work)
259{
260 struct cfg80211_registered_device *drv;
261
262 drv = container_of(work, struct cfg80211_registered_device, rfkill_sync);
263 cfg80211_rfkill_set_block(drv, rfkill_blocked(drv->rfkill));
264}
265
230/* exported functions */ 266/* exported functions */
231 267
232struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) 268struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
233{ 269{
234 static int wiphy_counter; 270 static int wiphy_counter;
235 271
@@ -274,6 +310,28 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
274 drv->wiphy.dev.class = &ieee80211_class; 310 drv->wiphy.dev.class = &ieee80211_class;
275 drv->wiphy.dev.platform_data = drv; 311 drv->wiphy.dev.platform_data = drv;
276 312
313 drv->rfkill_ops.set_block = cfg80211_rfkill_set_block;
314 drv->rfkill = rfkill_alloc(dev_name(&drv->wiphy.dev),
315 &drv->wiphy.dev, RFKILL_TYPE_WLAN,
316 &drv->rfkill_ops, drv);
317
318 if (!drv->rfkill) {
319 kfree(drv);
320 return NULL;
321 }
322
323 INIT_WORK(&drv->rfkill_sync, cfg80211_rfkill_sync_work);
324
325 /*
326 * Initialize wiphy parameters to IEEE 802.11 MIB default values.
327 * Fragmentation and RTS threshold are disabled by default with the
328 * special -1 value.
329 */
330 drv->wiphy.retry_short = 7;
331 drv->wiphy.retry_long = 4;
332 drv->wiphy.frag_threshold = (u32) -1;
333 drv->wiphy.rts_threshold = (u32) -1;
334
277 return &drv->wiphy; 335 return &drv->wiphy;
278} 336}
279EXPORT_SYMBOL(wiphy_new); 337EXPORT_SYMBOL(wiphy_new);
@@ -337,17 +395,23 @@ int wiphy_register(struct wiphy *wiphy)
337 /* check and set up bitrates */ 395 /* check and set up bitrates */
338 ieee80211_set_bitrate_flags(wiphy); 396 ieee80211_set_bitrate_flags(wiphy);
339 397
398 res = device_add(&drv->wiphy.dev);
399 if (res)
400 return res;
401
402 res = rfkill_register(drv->rfkill);
403 if (res)
404 goto out_rm_dev;
405
340 mutex_lock(&cfg80211_mutex); 406 mutex_lock(&cfg80211_mutex);
341 407
342 /* set up regulatory info */ 408 /* set up regulatory info */
343 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 409 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
344 410
345 res = device_add(&drv->wiphy.dev);
346 if (res)
347 goto out_unlock;
348
349 list_add(&drv->list, &cfg80211_drv_list); 411 list_add(&drv->list, &cfg80211_drv_list);
350 412
413 mutex_unlock(&cfg80211_mutex);
414
351 /* add to debugfs */ 415 /* add to debugfs */
352 drv->wiphy.debugfsdir = 416 drv->wiphy.debugfsdir =
353 debugfs_create_dir(wiphy_name(&drv->wiphy), 417 debugfs_create_dir(wiphy_name(&drv->wiphy),
@@ -366,17 +430,41 @@ int wiphy_register(struct wiphy *wiphy)
366 nl80211_send_reg_change_event(&request); 430 nl80211_send_reg_change_event(&request);
367 } 431 }
368 432
369 res = 0; 433 cfg80211_debugfs_drv_add(drv);
370out_unlock: 434
371 mutex_unlock(&cfg80211_mutex); 435 return 0;
436
437 out_rm_dev:
438 device_del(&drv->wiphy.dev);
372 return res; 439 return res;
373} 440}
374EXPORT_SYMBOL(wiphy_register); 441EXPORT_SYMBOL(wiphy_register);
375 442
443void wiphy_rfkill_start_polling(struct wiphy *wiphy)
444{
445 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
446
447 if (!drv->ops->rfkill_poll)
448 return;
449 drv->rfkill_ops.poll = cfg80211_rfkill_poll;
450 rfkill_resume_polling(drv->rfkill);
451}
452EXPORT_SYMBOL(wiphy_rfkill_start_polling);
453
454void wiphy_rfkill_stop_polling(struct wiphy *wiphy)
455{
456 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
457
458 rfkill_pause_polling(drv->rfkill);
459}
460EXPORT_SYMBOL(wiphy_rfkill_stop_polling);
461
376void wiphy_unregister(struct wiphy *wiphy) 462void wiphy_unregister(struct wiphy *wiphy)
377{ 463{
378 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy); 464 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
379 465
466 rfkill_unregister(drv->rfkill);
467
380 /* protect the device list */ 468 /* protect the device list */
381 mutex_lock(&cfg80211_mutex); 469 mutex_lock(&cfg80211_mutex);
382 470
@@ -396,6 +484,8 @@ void wiphy_unregister(struct wiphy *wiphy)
396 /* unlock again before freeing */ 484 /* unlock again before freeing */
397 mutex_unlock(&drv->mtx); 485 mutex_unlock(&drv->mtx);
398 486
487 cfg80211_debugfs_drv_del(drv);
488
399 /* If this device got a regulatory hint tell core its 489 /* If this device got a regulatory hint tell core its
400 * free to listen now to a new shiny device regulatory hint */ 490 * free to listen now to a new shiny device regulatory hint */
401 reg_device_remove(wiphy); 491 reg_device_remove(wiphy);
@@ -411,6 +501,7 @@ EXPORT_SYMBOL(wiphy_unregister);
411void cfg80211_dev_free(struct cfg80211_registered_device *drv) 501void cfg80211_dev_free(struct cfg80211_registered_device *drv)
412{ 502{
413 struct cfg80211_internal_bss *scan, *tmp; 503 struct cfg80211_internal_bss *scan, *tmp;
504 rfkill_destroy(drv->rfkill);
414 mutex_destroy(&drv->mtx); 505 mutex_destroy(&drv->mtx);
415 mutex_destroy(&drv->devlist_mtx); 506 mutex_destroy(&drv->devlist_mtx);
416 list_for_each_entry_safe(scan, tmp, &drv->bss_list, list) 507 list_for_each_entry_safe(scan, tmp, &drv->bss_list, list)
@@ -424,6 +515,15 @@ void wiphy_free(struct wiphy *wiphy)
424} 515}
425EXPORT_SYMBOL(wiphy_free); 516EXPORT_SYMBOL(wiphy_free);
426 517
518void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
519{
520 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
521
522 if (rfkill_set_hw_state(drv->rfkill, blocked))
523 schedule_work(&drv->rfkill_sync);
524}
525EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
526
427static int cfg80211_netdev_notifier_call(struct notifier_block * nb, 527static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
428 unsigned long state, 528 unsigned long state,
429 void *ndev) 529 void *ndev)
@@ -432,7 +532,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
432 struct cfg80211_registered_device *rdev; 532 struct cfg80211_registered_device *rdev;
433 533
434 if (!dev->ieee80211_ptr) 534 if (!dev->ieee80211_ptr)
435 return 0; 535 return NOTIFY_DONE;
436 536
437 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); 537 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
438 538
@@ -448,8 +548,28 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
448 "symlink to netdev!\n"); 548 "symlink to netdev!\n");
449 } 549 }
450 dev->ieee80211_ptr->netdev = dev; 550 dev->ieee80211_ptr->netdev = dev;
551#ifdef CONFIG_WIRELESS_EXT
552 dev->ieee80211_ptr->wext.default_key = -1;
553 dev->ieee80211_ptr->wext.default_mgmt_key = -1;
554#endif
451 mutex_unlock(&rdev->devlist_mtx); 555 mutex_unlock(&rdev->devlist_mtx);
452 break; 556 break;
557 case NETDEV_GOING_DOWN:
558 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
559 break;
560 if (!dev->ieee80211_ptr->ssid_len)
561 break;
562 cfg80211_leave_ibss(rdev, dev, true);
563 break;
564 case NETDEV_UP:
565#ifdef CONFIG_WIRELESS_EXT
566 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC)
567 break;
568 if (!dev->ieee80211_ptr->wext.ibss.ssid_len)
569 break;
570 cfg80211_join_ibss(rdev, dev, &dev->ieee80211_ptr->wext.ibss);
571 break;
572#endif
453 case NETDEV_UNREGISTER: 573 case NETDEV_UNREGISTER:
454 mutex_lock(&rdev->devlist_mtx); 574 mutex_lock(&rdev->devlist_mtx);
455 if (!list_empty(&dev->ieee80211_ptr->list)) { 575 if (!list_empty(&dev->ieee80211_ptr->list)) {
@@ -458,9 +578,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
458 } 578 }
459 mutex_unlock(&rdev->devlist_mtx); 579 mutex_unlock(&rdev->devlist_mtx);
460 break; 580 break;
581 case NETDEV_PRE_UP:
582 if (rfkill_blocked(rdev->rfkill))
583 return notifier_from_errno(-ERFKILL);
584 break;
461 } 585 }
462 586
463 return 0; 587 return NOTIFY_DONE;
464} 588}
465 589
466static struct notifier_block cfg80211_netdev_notifier = { 590static struct notifier_block cfg80211_netdev_notifier = {