core.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * This is the linux wireless configuration interface.
  3. *
  4. * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
  5. */
  6. #include <linux/if.h>
  7. #include <linux/module.h>
  8. #include <linux/err.h>
  9. #include <linux/mutex.h>
  10. #include <linux/list.h>
  11. #include <linux/nl80211.h>
  12. #include <linux/debugfs.h>
  13. #include <linux/notifier.h>
  14. #include <linux/device.h>
  15. #include <net/genetlink.h>
  16. #include <net/cfg80211.h>
  17. #include <net/wireless.h>
  18. #include "core.h"
  19. #include "sysfs.h"
  20. /* name for sysfs, %d is appended */
  21. #define PHY_NAME "phy"
  22. MODULE_AUTHOR("Johannes Berg");
  23. MODULE_LICENSE("GPL");
  24. MODULE_DESCRIPTION("wireless configuration support");
  25. /* RCU might be appropriate here since we usually
  26. * only read the list, and that can happen quite
  27. * often because we need to do it for each command */
  28. LIST_HEAD(cfg80211_drv_list);
  29. DEFINE_MUTEX(cfg80211_drv_mutex);
  30. static int wiphy_counter;
  31. /* for debugfs */
  32. static struct dentry *ieee80211_debugfs_dir;
  33. /* exported functions */
  34. struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
  35. {
  36. struct cfg80211_registered_device *drv;
  37. int alloc_size;
  38. alloc_size = sizeof(*drv) + sizeof_priv;
  39. drv = kzalloc(alloc_size, GFP_KERNEL);
  40. if (!drv)
  41. return NULL;
  42. drv->ops = ops;
  43. mutex_lock(&cfg80211_drv_mutex);
  44. if (unlikely(wiphy_counter<0)) {
  45. /* ugh, wrapped! */
  46. kfree(drv);
  47. return NULL;
  48. }
  49. drv->idx = wiphy_counter;
  50. /* give it a proper name */
  51. snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
  52. PHY_NAME "%d", drv->idx);
  53. /* now increase counter for the next time */
  54. wiphy_counter++;
  55. mutex_unlock(&cfg80211_drv_mutex);
  56. mutex_init(&drv->mtx);
  57. mutex_init(&drv->devlist_mtx);
  58. INIT_LIST_HEAD(&drv->netdev_list);
  59. device_initialize(&drv->wiphy.dev);
  60. drv->wiphy.dev.class = &ieee80211_class;
  61. drv->wiphy.dev.platform_data = drv;
  62. return &drv->wiphy;
  63. }
  64. EXPORT_SYMBOL(wiphy_new);
  65. int wiphy_register(struct wiphy *wiphy)
  66. {
  67. struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
  68. int res;
  69. mutex_lock(&cfg80211_drv_mutex);
  70. res = device_add(&drv->wiphy.dev);
  71. if (res)
  72. goto out_unlock;
  73. list_add(&drv->list, &cfg80211_drv_list);
  74. /* add to debugfs */
  75. drv->wiphy.debugfsdir =
  76. debugfs_create_dir(wiphy_name(&drv->wiphy),
  77. ieee80211_debugfs_dir);
  78. res = 0;
  79. out_unlock:
  80. mutex_unlock(&cfg80211_drv_mutex);
  81. return res;
  82. }
  83. EXPORT_SYMBOL(wiphy_register);
  84. void wiphy_unregister(struct wiphy *wiphy)
  85. {
  86. struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
  87. mutex_lock(&cfg80211_drv_mutex);
  88. /* hold registered driver mutex during list removal as well
  89. * to make sure no commands are in progress at the moment */
  90. mutex_lock(&drv->mtx);
  91. list_del(&drv->list);
  92. mutex_unlock(&drv->mtx);
  93. device_del(&drv->wiphy.dev);
  94. debugfs_remove(drv->wiphy.debugfsdir);
  95. mutex_unlock(&cfg80211_drv_mutex);
  96. }
  97. EXPORT_SYMBOL(wiphy_unregister);
  98. void cfg80211_dev_free(struct cfg80211_registered_device *drv)
  99. {
  100. mutex_destroy(&drv->mtx);
  101. mutex_destroy(&drv->devlist_mtx);
  102. kfree(drv);
  103. }
  104. void wiphy_free(struct wiphy *wiphy)
  105. {
  106. put_device(&wiphy->dev);
  107. }
  108. EXPORT_SYMBOL(wiphy_free);
  109. static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
  110. unsigned long state,
  111. void *ndev)
  112. {
  113. struct net_device *dev = ndev;
  114. struct cfg80211_registered_device *rdev;
  115. if (!dev->ieee80211_ptr)
  116. return 0;
  117. rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
  118. switch (state) {
  119. case NETDEV_REGISTER:
  120. mutex_lock(&rdev->devlist_mtx);
  121. list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
  122. if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
  123. "phy80211")) {
  124. printk(KERN_ERR "wireless: failed to add phy80211 "
  125. "symlink to netdev!\n");
  126. }
  127. dev->ieee80211_ptr->netdev = dev;
  128. mutex_unlock(&rdev->devlist_mtx);
  129. break;
  130. case NETDEV_UNREGISTER:
  131. mutex_lock(&rdev->devlist_mtx);
  132. if (!list_empty(&dev->ieee80211_ptr->list)) {
  133. sysfs_remove_link(&dev->dev.kobj, "phy80211");
  134. list_del_init(&dev->ieee80211_ptr->list);
  135. }
  136. mutex_unlock(&rdev->devlist_mtx);
  137. break;
  138. }
  139. return 0;
  140. }
  141. static struct notifier_block cfg80211_netdev_notifier = {
  142. .notifier_call = cfg80211_netdev_notifier_call,
  143. };
  144. static int cfg80211_init(void)
  145. {
  146. int err = wiphy_sysfs_init();
  147. if (err)
  148. goto out_fail_sysfs;
  149. err = register_netdevice_notifier(&cfg80211_netdev_notifier);
  150. if (err)
  151. goto out_fail_notifier;
  152. ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
  153. return 0;
  154. out_fail_notifier:
  155. wiphy_sysfs_exit();
  156. out_fail_sysfs:
  157. return err;
  158. }
  159. module_init(cfg80211_init);
  160. static void cfg80211_exit(void)
  161. {
  162. debugfs_remove(ieee80211_debugfs_dir);
  163. unregister_netdevice_notifier(&cfg80211_netdev_notifier);
  164. wiphy_sysfs_exit();
  165. }
  166. module_exit(cfg80211_exit);