2 * Copyright (C) 2007-2012 Siemens AG
5 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
7 * Based on the code from 'linux-zigbee.sourceforge.net' project.
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.
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.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/netdevice.h>
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/wpan-phy.h>
30 #include "mac802154.h"
32 int mac802154_slave_open(struct net_device *dev)
34 struct mac802154_sub_if_data *priv = netdev_priv(dev);
35 struct mac802154_sub_if_data *subif;
36 struct mac802154_priv *ipriv = priv->hw;
41 if (priv->type == IEEE802154_DEV_WPAN) {
42 mutex_lock(&priv->hw->slaves_mtx);
43 list_for_each_entry(subif, &priv->hw->slaves, list) {
44 if (subif != priv && subif->type == priv->type &&
46 mutex_unlock(&priv->hw->slaves_mtx);
50 mutex_unlock(&priv->hw->slaves_mtx);
53 mutex_lock(&priv->hw->slaves_mtx);
55 mutex_unlock(&priv->hw->slaves_mtx);
57 if (ipriv->open_count++ == 0) {
58 res = ipriv->ops->start(&ipriv->hw);
64 if (ipriv->ops->ieee_addr) {
65 __le64 addr = ieee802154_devaddr_from_raw(dev->dev_addr);
67 res = ipriv->ops->ieee_addr(&ipriv->hw, addr);
71 mac802154_dev_set_ieee_addr(dev);
74 netif_start_queue(dev);
77 priv->hw->open_count--;
82 int mac802154_slave_close(struct net_device *dev)
84 struct mac802154_sub_if_data *priv = netdev_priv(dev);
85 struct mac802154_priv *ipriv = priv->hw;
89 netif_stop_queue(dev);
91 mutex_lock(&priv->hw->slaves_mtx);
92 priv->running = false;
93 mutex_unlock(&priv->hw->slaves_mtx);
95 if (!--ipriv->open_count)
96 ipriv->ops->stop(&ipriv->hw);
102 mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev)
104 struct mac802154_sub_if_data *priv;
105 struct mac802154_priv *ipriv;
108 ipriv = wpan_phy_priv(phy);
110 priv = netdev_priv(dev);
114 dev->needed_headroom = ipriv->hw.extra_tx_headroom;
116 SET_NETDEV_DEV(dev, &ipriv->phy->dev);
118 mutex_lock(&ipriv->slaves_mtx);
119 if (!ipriv->running) {
120 mutex_unlock(&ipriv->slaves_mtx);
123 mutex_unlock(&ipriv->slaves_mtx);
125 err = register_netdev(dev);
130 mutex_lock(&ipriv->slaves_mtx);
131 list_add_tail_rcu(&priv->list, &ipriv->slaves);
132 mutex_unlock(&ipriv->slaves_mtx);
139 mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev)
141 struct mac802154_sub_if_data *sdata;
145 sdata = netdev_priv(dev);
147 BUG_ON(sdata->hw->phy != phy);
149 mutex_lock(&sdata->hw->slaves_mtx);
150 list_del_rcu(&sdata->list);
151 mutex_unlock(&sdata->hw->slaves_mtx);
154 unregister_netdevice(sdata->dev);
157 static struct net_device *
158 mac802154_add_iface(struct wpan_phy *phy, const char *name, int type)
160 struct net_device *dev;
164 case IEEE802154_DEV_MONITOR:
165 dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
166 name, NET_NAME_UNKNOWN,
167 mac802154_monitor_setup);
169 case IEEE802154_DEV_WPAN:
170 dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
171 name, NET_NAME_UNKNOWN,
172 mac802154_wpan_setup);
182 err = mac802154_netdev_register(phy, dev);
186 dev_hold(dev); /* we return an incremented device refcount */
195 static int mac802154_set_txpower(struct wpan_phy *phy, int db)
197 struct mac802154_priv *priv = wpan_phy_priv(phy);
199 return priv->ops->set_txpower(&priv->hw, db);
202 static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
204 struct mac802154_priv *priv = wpan_phy_priv(phy);
206 return priv->ops->set_lbt(&priv->hw, on);
209 static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
211 struct mac802154_priv *priv = wpan_phy_priv(phy);
213 return priv->ops->set_cca_mode(&priv->hw, mode);
216 static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
218 struct mac802154_priv *priv = wpan_phy_priv(phy);
220 return priv->ops->set_cca_ed_level(&priv->hw, level);
223 static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
224 u8 max_be, u8 retries)
226 struct mac802154_priv *priv = wpan_phy_priv(phy);
228 return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
231 static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
233 struct mac802154_priv *priv = wpan_phy_priv(phy);
235 return priv->ops->set_frame_retries(&priv->hw, retries);
238 struct ieee802154_dev *
239 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
241 struct wpan_phy *phy;
242 struct mac802154_priv *priv;
245 if (!ops || !ops->xmit || !ops->ed || !ops->start ||
246 !ops->stop || !ops->set_channel) {
247 pr_err("undefined IEEE802.15.4 device operations\n");
251 /* Ensure 32-byte alignment of our private data and hw private data.
252 * We use the wpan_phy priv data for both our mac802154_priv and for
253 * the driver's private data
255 * in memory it'll be like this:
257 * +-----------------------+
258 * | struct wpan_phy |
259 * +-----------------------+
260 * | struct mac802154_priv |
261 * +-----------------------+
262 * | driver's private data |
263 * +-----------------------+
265 * Due to ieee802154 layer isn't aware of driver and MAC structures,
266 * so lets align them here.
269 priv_size = ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_data_len;
271 phy = wpan_phy_alloc(priv_size);
273 pr_err("failure to allocate master IEEE802.15.4 device\n");
277 priv = wpan_phy_priv(phy);
279 priv->hw.phy = priv->phy;
280 priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
283 INIT_LIST_HEAD(&priv->slaves);
284 mutex_init(&priv->slaves_mtx);
288 EXPORT_SYMBOL(ieee802154_alloc_device);
290 void ieee802154_free_device(struct ieee802154_dev *hw)
292 struct mac802154_priv *priv = mac802154_to_priv(hw);
294 BUG_ON(!list_empty(&priv->slaves));
296 mutex_destroy(&priv->slaves_mtx);
298 wpan_phy_free(priv->phy);
300 EXPORT_SYMBOL(ieee802154_free_device);
302 int ieee802154_register_device(struct ieee802154_dev *dev)
304 struct mac802154_priv *priv = mac802154_to_priv(dev);
307 if (dev->flags & IEEE802154_HW_TXPOWER) {
308 if (!priv->ops->set_txpower)
311 priv->phy->set_txpower = mac802154_set_txpower;
314 if (dev->flags & IEEE802154_HW_LBT) {
315 if (!priv->ops->set_lbt)
318 priv->phy->set_lbt = mac802154_set_lbt;
321 if (dev->flags & IEEE802154_HW_CCA_MODE) {
322 if (!priv->ops->set_cca_mode)
325 priv->phy->set_cca_mode = mac802154_set_cca_mode;
328 if (dev->flags & IEEE802154_HW_CCA_ED_LEVEL) {
329 if (!priv->ops->set_cca_ed_level)
332 priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
335 if (dev->flags & IEEE802154_HW_CSMA_PARAMS) {
336 if (!priv->ops->set_csma_params)
339 priv->phy->set_csma_params = mac802154_set_csma_params;
342 if (dev->flags & IEEE802154_HW_FRAME_RETRIES) {
343 if (!priv->ops->set_frame_retries)
346 priv->phy->set_frame_retries = mac802154_set_frame_retries;
349 priv->dev_workqueue =
350 create_singlethread_workqueue(wpan_phy_name(priv->phy));
351 if (!priv->dev_workqueue) {
356 wpan_phy_set_dev(priv->phy, priv->hw.parent);
358 priv->phy->add_iface = mac802154_add_iface;
359 priv->phy->del_iface = mac802154_del_iface;
361 rc = wpan_phy_register(priv->phy);
367 mutex_lock(&priv->slaves_mtx);
368 priv->running = MAC802154_DEVICE_RUN;
369 mutex_unlock(&priv->slaves_mtx);
376 destroy_workqueue(priv->dev_workqueue);
380 EXPORT_SYMBOL(ieee802154_register_device);
382 void ieee802154_unregister_device(struct ieee802154_dev *dev)
384 struct mac802154_priv *priv = mac802154_to_priv(dev);
385 struct mac802154_sub_if_data *sdata, *next;
387 flush_workqueue(priv->dev_workqueue);
388 destroy_workqueue(priv->dev_workqueue);
392 mutex_lock(&priv->slaves_mtx);
393 priv->running = MAC802154_DEVICE_STOPPED;
394 mutex_unlock(&priv->slaves_mtx);
396 list_for_each_entry_safe(sdata, next, &priv->slaves, list) {
397 mutex_lock(&sdata->hw->slaves_mtx);
398 list_del(&sdata->list);
399 mutex_unlock(&sdata->hw->slaves_mtx);
401 unregister_netdevice(sdata->dev);
406 wpan_phy_unregister(priv->phy);
408 EXPORT_SYMBOL(ieee802154_unregister_device);
410 MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
411 MODULE_LICENSE("GPL v2");