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 "cfg.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 err = register_netdev(dev); 50 if (err < 0) 51 return err; 52 53 rtnl_lock(); 54 mutex_lock(&local->iflist_mtx); 55 list_add_tail_rcu(&sdata->list, &local->interfaces); 56 mutex_unlock(&local->iflist_mtx); 57 rtnl_unlock(); 58 59 return 0; 60 } 61 62 static void 63 mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) 64 { 65 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); 66 67 ASSERT_RTNL(); 68 69 BUG_ON(sdata->local->phy != phy); 70 71 mutex_lock(&sdata->local->iflist_mtx); 72 list_del_rcu(&sdata->list); 73 mutex_unlock(&sdata->local->iflist_mtx); 74 75 synchronize_rcu(); 76 unregister_netdevice(sdata->dev); 77 } 78 79 static struct net_device * 80 mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) 81 { 82 struct net_device *dev; 83 int err = -ENOMEM; 84 85 switch (type) { 86 case IEEE802154_DEV_MONITOR: 87 dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), 88 name, NET_NAME_UNKNOWN, 89 mac802154_monitor_setup); 90 break; 91 case IEEE802154_DEV_WPAN: 92 dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), 93 name, NET_NAME_UNKNOWN, 94 mac802154_wpan_setup); 95 break; 96 default: 97 dev = NULL; 98 err = -EINVAL; 99 break; 100 } 101 if (!dev) 102 goto err; 103 104 err = mac802154_netdev_register(phy, dev); 105 if (err) 106 goto err_free; 107 108 dev_hold(dev); /* we return an incremented device refcount */ 109 return dev; 110 111 err_free: 112 free_netdev(dev); 113 err: 114 return ERR_PTR(err); 115 } 116 117 static void ieee802154_tasklet_handler(unsigned long data) 118 { 119 struct ieee802154_local *local = (struct ieee802154_local *)data; 120 struct sk_buff *skb; 121 122 while ((skb = skb_dequeue(&local->skb_queue))) { 123 switch (skb->pkt_type) { 124 case IEEE802154_RX_MSG: 125 /* Clear skb->pkt_type in order to not confuse kernel 126 * netstack. 127 */ 128 skb->pkt_type = 0; 129 ieee802154_rx(&local->hw, skb); 130 break; 131 default: 132 WARN(1, "mac802154: Packet is of unknown type %d\n", 133 skb->pkt_type); 134 kfree_skb(skb); 135 break; 136 } 137 } 138 } 139 140 struct ieee802154_hw * 141 ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) 142 { 143 struct wpan_phy *phy; 144 struct ieee802154_local *local; 145 size_t priv_size; 146 147 if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed || 148 !ops->start || !ops->stop || !ops->set_channel) { 149 pr_err("undefined IEEE802.15.4 device operations\n"); 150 return NULL; 151 } 152 153 /* Ensure 32-byte alignment of our private data and hw private data. 154 * We use the wpan_phy priv data for both our ieee802154_local and for 155 * the driver's private data 156 * 157 * in memory it'll be like this: 158 * 159 * +-------------------------+ 160 * | struct wpan_phy | 161 * +-------------------------+ 162 * | struct ieee802154_local | 163 * +-------------------------+ 164 * | driver's private data | 165 * +-------------------------+ 166 * 167 * Due to ieee802154 layer isn't aware of driver and MAC structures, 168 * so lets align them here. 169 */ 170 171 priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; 172 173 phy = wpan_phy_alloc(&mac802154_config_ops, priv_size); 174 if (!phy) { 175 pr_err("failure to allocate master IEEE802.15.4 device\n"); 176 return NULL; 177 } 178 179 local = wpan_phy_priv(phy); 180 local->phy = phy; 181 local->hw.phy = local->phy; 182 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 183 local->ops = ops; 184 185 INIT_LIST_HEAD(&local->interfaces); 186 mutex_init(&local->iflist_mtx); 187 188 tasklet_init(&local->tasklet, 189 ieee802154_tasklet_handler, 190 (unsigned long)local); 191 192 skb_queue_head_init(&local->skb_queue); 193 194 return &local->hw; 195 } 196 EXPORT_SYMBOL(ieee802154_alloc_hw); 197 198 void ieee802154_free_hw(struct ieee802154_hw *hw) 199 { 200 struct ieee802154_local *local = hw_to_local(hw); 201 202 BUG_ON(!list_empty(&local->interfaces)); 203 204 mutex_destroy(&local->iflist_mtx); 205 206 wpan_phy_free(local->phy); 207 } 208 EXPORT_SYMBOL(ieee802154_free_hw); 209 210 int ieee802154_register_hw(struct ieee802154_hw *hw) 211 { 212 struct ieee802154_local *local = hw_to_local(hw); 213 int rc = -ENOSYS; 214 215 local->workqueue = 216 create_singlethread_workqueue(wpan_phy_name(local->phy)); 217 if (!local->workqueue) { 218 rc = -ENOMEM; 219 goto out; 220 } 221 222 wpan_phy_set_dev(local->phy, local->hw.parent); 223 224 local->phy->add_iface = mac802154_add_iface; 225 local->phy->del_iface = mac802154_del_iface; 226 227 rc = wpan_phy_register(local->phy); 228 if (rc < 0) 229 goto out_wq; 230 231 return 0; 232 233 out_wq: 234 destroy_workqueue(local->workqueue); 235 out: 236 return rc; 237 } 238 EXPORT_SYMBOL(ieee802154_register_hw); 239 240 void ieee802154_unregister_hw(struct ieee802154_hw *hw) 241 { 242 struct ieee802154_local *local = hw_to_local(hw); 243 struct ieee802154_sub_if_data *sdata, *next; 244 245 tasklet_kill(&local->tasklet); 246 flush_workqueue(local->workqueue); 247 destroy_workqueue(local->workqueue); 248 249 rtnl_lock(); 250 251 list_for_each_entry_safe(sdata, next, &local->interfaces, list) { 252 mutex_lock(&sdata->local->iflist_mtx); 253 list_del(&sdata->list); 254 mutex_unlock(&sdata->local->iflist_mtx); 255 256 unregister_netdevice(sdata->dev); 257 } 258 259 rtnl_unlock(); 260 261 wpan_phy_unregister(local->phy); 262 } 263 EXPORT_SYMBOL(ieee802154_unregister_hw); 264 265 MODULE_DESCRIPTION("IEEE 802.15.4 implementation"); 266 MODULE_LICENSE("GPL v2"); 267