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