1 /* 2 * Copyright (C) 2007-2012 Siemens AG 3 * 4 * Written by: 5 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 6 * 7 * Based on the code from 'linux-zigbee.sourceforge.net' project. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 11 * as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include <linux/kernel.h> 20 #include <linux/module.h> 21 #include <linux/netdevice.h> 22 23 #include <net/netlink.h> 24 #include <linux/nl802154.h> 25 #include <net/mac802154.h> 26 #include <net/ieee802154_netdev.h> 27 #include <net/route.h> 28 #include <net/cfg802154.h> 29 30 #include "ieee802154_i.h" 31 #include "driver-ops.h" 32 33 static int 34 mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) 35 { 36 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 37 struct ieee802154_local *local; 38 int err; 39 40 local = wpan_phy_priv(phy); 41 42 sdata->dev = dev; 43 sdata->local = local; 44 45 dev->needed_headroom = local->hw.extra_tx_headroom; 46 47 SET_NETDEV_DEV(dev, &local->phy->dev); 48 49 mutex_lock(&local->iflist_mtx); 50 if (!local->started) { 51 mutex_unlock(&local->iflist_mtx); 52 return -ENODEV; 53 } 54 mutex_unlock(&local->iflist_mtx); 55 56 err = register_netdev(dev); 57 if (err < 0) 58 return err; 59 60 rtnl_lock(); 61 mutex_lock(&local->iflist_mtx); 62 list_add_tail_rcu(&sdata->list, &local->interfaces); 63 mutex_unlock(&local->iflist_mtx); 64 rtnl_unlock(); 65 66 return 0; 67 } 68 69 static void 70 mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) 71 { 72 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 73 74 ASSERT_RTNL(); 75 76 BUG_ON(sdata->local->phy != phy); 77 78 mutex_lock(&sdata->local->iflist_mtx); 79 list_del_rcu(&sdata->list); 80 mutex_unlock(&sdata->local->iflist_mtx); 81 82 synchronize_rcu(); 83 unregister_netdevice(sdata->dev); 84 } 85 86 static struct net_device * 87 mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) 88 { 89 struct net_device *dev; 90 int err = -ENOMEM; 91 92 switch (type) { 93 case IEEE802154_DEV_MONITOR: 94 dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), 95 name, NET_NAME_UNKNOWN, 96 mac802154_monitor_setup); 97 break; 98 case IEEE802154_DEV_WPAN: 99 dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), 100 name, NET_NAME_UNKNOWN, 101 mac802154_wpan_setup); 102 break; 103 default: 104 dev = NULL; 105 err = -EINVAL; 106 break; 107 } 108 if (!dev) 109 goto err; 110 111 err = mac802154_netdev_register(phy, dev); 112 if (err) 113 goto err_free; 114 115 dev_hold(dev); /* we return an incremented device refcount */ 116 return dev; 117 118 err_free: 119 free_netdev(dev); 120 err: 121 return ERR_PTR(err); 122 } 123 124 static void ieee802154_tasklet_handler(unsigned long data) 125 { 126 struct ieee802154_local *local = (struct ieee802154_local *)data; 127 struct sk_buff *skb; 128 129 while ((skb = skb_dequeue(&local->skb_queue))) { 130 switch (skb->pkt_type) { 131 case IEEE802154_RX_MSG: 132 /* Clear skb->pkt_type in order to not confuse kernel 133 * netstack. 134 */ 135 skb->pkt_type = 0; 136 ieee802154_rx(&local->hw, skb); 137 break; 138 default: 139 WARN(1, "mac802154: Packet is of unknown type %d\n", 140 skb->pkt_type); 141 kfree_skb(skb); 142 break; 143 } 144 } 145 } 146 147 struct ieee802154_hw * 148 ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) 149 { 150 struct wpan_phy *phy; 151 struct ieee802154_local *local; 152 size_t priv_size; 153 154 if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed || 155 !ops->start || !ops->stop || !ops->set_channel) { 156 pr_err("undefined IEEE802.15.4 device operations\n"); 157 return NULL; 158 } 159 160 /* Ensure 32-byte alignment of our private data and hw private data. 161 * We use the wpan_phy priv data for both our ieee802154_local and for 162 * the driver's private data 163 * 164 * in memory it'll be like this: 165 * 166 * +-------------------------+ 167 * | struct wpan_phy | 168 * +-------------------------+ 169 * | struct ieee802154_local | 170 * +-------------------------+ 171 * | driver's private data | 172 * +-------------------------+ 173 * 174 * Due to ieee802154 layer isn't aware of driver and MAC structures, 175 * so lets align them here. 176 */ 177 178 priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; 179 180 phy = wpan_phy_alloc(priv_size); 181 if (!phy) { 182 pr_err("failure to allocate master IEEE802.15.4 device\n"); 183 return NULL; 184 } 185 186 local = wpan_phy_priv(phy); 187 local->phy = phy; 188 local->hw.phy = local->phy; 189 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 190 local->ops = ops; 191 192 INIT_LIST_HEAD(&local->interfaces); 193 mutex_init(&local->iflist_mtx); 194 195 tasklet_init(&local->tasklet, 196 ieee802154_tasklet_handler, 197 (unsigned long)local); 198 199 skb_queue_head_init(&local->skb_queue); 200 201 return &local->hw; 202 } 203 EXPORT_SYMBOL(ieee802154_alloc_hw); 204 205 void ieee802154_free_hw(struct ieee802154_hw *hw) 206 { 207 struct ieee802154_local *local = hw_to_local(hw); 208 209 BUG_ON(!list_empty(&local->interfaces)); 210 211 mutex_destroy(&local->iflist_mtx); 212 213 wpan_phy_free(local->phy); 214 } 215 EXPORT_SYMBOL(ieee802154_free_hw); 216 217 int ieee802154_register_hw(struct ieee802154_hw *hw) 218 { 219 struct ieee802154_local *local = hw_to_local(hw); 220 int rc = -ENOSYS; 221 222 local->workqueue = 223 create_singlethread_workqueue(wpan_phy_name(local->phy)); 224 if (!local->workqueue) { 225 rc = -ENOMEM; 226 goto out; 227 } 228 229 wpan_phy_set_dev(local->phy, local->hw.parent); 230 231 local->phy->add_iface = mac802154_add_iface; 232 local->phy->del_iface = mac802154_del_iface; 233 234 rc = wpan_phy_register(local->phy); 235 if (rc < 0) 236 goto out_wq; 237 238 rtnl_lock(); 239 240 mutex_lock(&local->iflist_mtx); 241 local->started = MAC802154_DEVICE_RUN; 242 mutex_unlock(&local->iflist_mtx); 243 244 rtnl_unlock(); 245 246 return 0; 247 248 out_wq: 249 destroy_workqueue(local->workqueue); 250 out: 251 return rc; 252 } 253 EXPORT_SYMBOL(ieee802154_register_hw); 254 255 void ieee802154_unregister_hw(struct ieee802154_hw *hw) 256 { 257 struct ieee802154_local *local = hw_to_local(hw); 258 struct ieee802154_sub_if_data *sdata, *next; 259 260 tasklet_kill(&local->tasklet); 261 flush_workqueue(local->workqueue); 262 destroy_workqueue(local->workqueue); 263 264 rtnl_lock(); 265 266 mutex_lock(&local->iflist_mtx); 267 local->started = MAC802154_DEVICE_STOPPED; 268 mutex_unlock(&local->iflist_mtx); 269 270 list_for_each_entry_safe(sdata, next, &local->interfaces, list) { 271 mutex_lock(&sdata->local->iflist_mtx); 272 list_del(&sdata->list); 273 mutex_unlock(&sdata->local->iflist_mtx); 274 275 unregister_netdevice(sdata->dev); 276 } 277 278 rtnl_unlock(); 279 280 wpan_phy_unregister(local->phy); 281 } 282 EXPORT_SYMBOL(ieee802154_unregister_hw); 283 284 MODULE_DESCRIPTION("IEEE 802.15.4 implementation"); 285 MODULE_LICENSE("GPL v2"); 286