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); 225