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.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/netdevice.h>
27 #include <net/netlink.h>
28 #include <linux/nl802154.h>
29 #include <net/mac802154.h>
30 #include <net/ieee802154_netdev.h>
31 #include <net/route.h>
32 #include <net/wpan-phy.h>
34 #include "mac802154.h"
36 int mac802154_slave_open(struct net_device
*dev
)
38 struct mac802154_sub_if_data
*priv
= netdev_priv(dev
);
39 struct mac802154_sub_if_data
*subif
;
40 struct mac802154_priv
*ipriv
= priv
->hw
;
45 if (priv
->type
== IEEE802154_DEV_WPAN
) {
46 mutex_lock(&priv
->hw
->slaves_mtx
);
47 list_for_each_entry(subif
, &priv
->hw
->slaves
, list
) {
48 if (subif
!= priv
&& subif
->type
== priv
->type
&&
50 mutex_unlock(&priv
->hw
->slaves_mtx
);
54 mutex_unlock(&priv
->hw
->slaves_mtx
);
57 mutex_lock(&priv
->hw
->slaves_mtx
);
59 mutex_unlock(&priv
->hw
->slaves_mtx
);
61 if (ipriv
->open_count
++ == 0) {
62 res
= ipriv
->ops
->start(&ipriv
->hw
);
68 if (ipriv
->ops
->ieee_addr
) {
69 __le64 addr
= ieee802154_devaddr_from_raw(dev
->dev_addr
);
71 res
= ipriv
->ops
->ieee_addr(&ipriv
->hw
, addr
);
75 mac802154_dev_set_ieee_addr(dev
);
78 netif_start_queue(dev
);
81 priv
->hw
->open_count
--;
86 int mac802154_slave_close(struct net_device
*dev
)
88 struct mac802154_sub_if_data
*priv
= netdev_priv(dev
);
89 struct mac802154_priv
*ipriv
= priv
->hw
;
93 netif_stop_queue(dev
);
95 mutex_lock(&priv
->hw
->slaves_mtx
);
96 priv
->running
= false;
97 mutex_unlock(&priv
->hw
->slaves_mtx
);
99 if (!--ipriv
->open_count
)
100 ipriv
->ops
->stop(&ipriv
->hw
);
106 mac802154_netdev_register(struct wpan_phy
*phy
, struct net_device
*dev
)
108 struct mac802154_sub_if_data
*priv
;
109 struct mac802154_priv
*ipriv
;
112 ipriv
= wpan_phy_priv(phy
);
114 priv
= netdev_priv(dev
);
118 dev
->needed_headroom
= ipriv
->hw
.extra_tx_headroom
;
120 SET_NETDEV_DEV(dev
, &ipriv
->phy
->dev
);
122 mutex_lock(&ipriv
->slaves_mtx
);
123 if (!ipriv
->running
) {
124 mutex_unlock(&ipriv
->slaves_mtx
);
127 mutex_unlock(&ipriv
->slaves_mtx
);
129 err
= register_netdev(dev
);
134 mutex_lock(&ipriv
->slaves_mtx
);
135 list_add_tail_rcu(&priv
->list
, &ipriv
->slaves
);
136 mutex_unlock(&ipriv
->slaves_mtx
);
143 mac802154_del_iface(struct wpan_phy
*phy
, struct net_device
*dev
)
145 struct mac802154_sub_if_data
*sdata
;
149 sdata
= netdev_priv(dev
);
151 BUG_ON(sdata
->hw
->phy
!= phy
);
153 mutex_lock(&sdata
->hw
->slaves_mtx
);
154 list_del_rcu(&sdata
->list
);
155 mutex_unlock(&sdata
->hw
->slaves_mtx
);
158 unregister_netdevice(sdata
->dev
);
161 static struct net_device
*
162 mac802154_add_iface(struct wpan_phy
*phy
, const char *name
, int type
)
164 struct net_device
*dev
;
168 case IEEE802154_DEV_MONITOR
:
169 dev
= alloc_netdev(sizeof(struct mac802154_sub_if_data
),
170 name
, NET_NAME_UNKNOWN
,
171 mac802154_monitor_setup
);
173 case IEEE802154_DEV_WPAN
:
174 dev
= alloc_netdev(sizeof(struct mac802154_sub_if_data
),
175 name
, NET_NAME_UNKNOWN
,
176 mac802154_wpan_setup
);
186 err
= mac802154_netdev_register(phy
, dev
);
190 dev_hold(dev
); /* we return an incremented device refcount */
199 static int mac802154_set_txpower(struct wpan_phy
*phy
, int db
)
201 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
203 return priv
->ops
->set_txpower(&priv
->hw
, db
);
206 static int mac802154_set_lbt(struct wpan_phy
*phy
, bool on
)
208 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
210 return priv
->ops
->set_lbt(&priv
->hw
, on
);
213 static int mac802154_set_cca_mode(struct wpan_phy
*phy
, u8 mode
)
215 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
217 return priv
->ops
->set_cca_mode(&priv
->hw
, mode
);
220 static int mac802154_set_cca_ed_level(struct wpan_phy
*phy
, s32 level
)
222 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
224 return priv
->ops
->set_cca_ed_level(&priv
->hw
, level
);
227 static int mac802154_set_csma_params(struct wpan_phy
*phy
, u8 min_be
,
228 u8 max_be
, u8 retries
)
230 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
232 return priv
->ops
->set_csma_params(&priv
->hw
, min_be
, max_be
, retries
);
235 static int mac802154_set_frame_retries(struct wpan_phy
*phy
, s8 retries
)
237 struct mac802154_priv
*priv
= wpan_phy_priv(phy
);
239 return priv
->ops
->set_frame_retries(&priv
->hw
, retries
);
242 struct ieee802154_dev
*
243 ieee802154_alloc_device(size_t priv_data_len
, struct ieee802154_ops
*ops
)
245 struct wpan_phy
*phy
;
246 struct mac802154_priv
*priv
;
249 if (!ops
|| !ops
->xmit
|| !ops
->ed
|| !ops
->start
||
250 !ops
->stop
|| !ops
->set_channel
) {
251 pr_err("undefined IEEE802.15.4 device operations\n");
255 /* Ensure 32-byte alignment of our private data and hw private data.
256 * We use the wpan_phy priv data for both our mac802154_priv and for
257 * the driver's private data
259 * in memory it'll be like this:
261 * +-----------------------+
262 * | struct wpan_phy |
263 * +-----------------------+
264 * | struct mac802154_priv |
265 * +-----------------------+
266 * | driver's private data |
267 * +-----------------------+
269 * Due to ieee802154 layer isn't aware of driver and MAC structures,
270 * so lets allign them here.
273 priv_size
= ALIGN(sizeof(*priv
), NETDEV_ALIGN
) + priv_data_len
;
275 phy
= wpan_phy_alloc(priv_size
);
277 pr_err("failure to allocate master IEEE802.15.4 device\n");
281 priv
= wpan_phy_priv(phy
);
283 priv
->hw
.phy
= priv
->phy
;
284 priv
->hw
.priv
= (char *)priv
+ ALIGN(sizeof(*priv
), NETDEV_ALIGN
);
287 INIT_LIST_HEAD(&priv
->slaves
);
288 mutex_init(&priv
->slaves_mtx
);
292 EXPORT_SYMBOL(ieee802154_alloc_device
);
294 void ieee802154_free_device(struct ieee802154_dev
*hw
)
296 struct mac802154_priv
*priv
= mac802154_to_priv(hw
);
298 BUG_ON(!list_empty(&priv
->slaves
));
300 mutex_destroy(&priv
->slaves_mtx
);
302 wpan_phy_free(priv
->phy
);
304 EXPORT_SYMBOL(ieee802154_free_device
);
306 int ieee802154_register_device(struct ieee802154_dev
*dev
)
308 struct mac802154_priv
*priv
= mac802154_to_priv(dev
);
311 if (dev
->flags
& IEEE802154_HW_TXPOWER
) {
312 if (!priv
->ops
->set_txpower
)
315 priv
->phy
->set_txpower
= mac802154_set_txpower
;
318 if (dev
->flags
& IEEE802154_HW_LBT
) {
319 if (!priv
->ops
->set_lbt
)
322 priv
->phy
->set_lbt
= mac802154_set_lbt
;
325 if (dev
->flags
& IEEE802154_HW_CCA_MODE
) {
326 if (!priv
->ops
->set_cca_mode
)
329 priv
->phy
->set_cca_mode
= mac802154_set_cca_mode
;
332 if (dev
->flags
& IEEE802154_HW_CCA_ED_LEVEL
) {
333 if (!priv
->ops
->set_cca_ed_level
)
336 priv
->phy
->set_cca_ed_level
= mac802154_set_cca_ed_level
;
339 if (dev
->flags
& IEEE802154_HW_CSMA_PARAMS
) {
340 if (!priv
->ops
->set_csma_params
)
343 priv
->phy
->set_csma_params
= mac802154_set_csma_params
;
346 if (dev
->flags
& IEEE802154_HW_FRAME_RETRIES
) {
347 if (!priv
->ops
->set_frame_retries
)
350 priv
->phy
->set_frame_retries
= mac802154_set_frame_retries
;
353 priv
->dev_workqueue
=
354 create_singlethread_workqueue(wpan_phy_name(priv
->phy
));
355 if (!priv
->dev_workqueue
) {
360 wpan_phy_set_dev(priv
->phy
, priv
->hw
.parent
);
362 priv
->phy
->add_iface
= mac802154_add_iface
;
363 priv
->phy
->del_iface
= mac802154_del_iface
;
365 rc
= wpan_phy_register(priv
->phy
);
371 mutex_lock(&priv
->slaves_mtx
);
372 priv
->running
= MAC802154_DEVICE_RUN
;
373 mutex_unlock(&priv
->slaves_mtx
);
380 destroy_workqueue(priv
->dev_workqueue
);
384 EXPORT_SYMBOL(ieee802154_register_device
);
386 void ieee802154_unregister_device(struct ieee802154_dev
*dev
)
388 struct mac802154_priv
*priv
= mac802154_to_priv(dev
);
389 struct mac802154_sub_if_data
*sdata
, *next
;
391 flush_workqueue(priv
->dev_workqueue
);
392 destroy_workqueue(priv
->dev_workqueue
);
396 mutex_lock(&priv
->slaves_mtx
);
397 priv
->running
= MAC802154_DEVICE_STOPPED
;
398 mutex_unlock(&priv
->slaves_mtx
);
400 list_for_each_entry_safe(sdata
, next
, &priv
->slaves
, list
) {
401 mutex_lock(&sdata
->hw
->slaves_mtx
);
402 list_del(&sdata
->list
);
403 mutex_unlock(&sdata
->hw
->slaves_mtx
);
405 unregister_netdevice(sdata
->dev
);
410 wpan_phy_unregister(priv
->phy
);
412 EXPORT_SYMBOL(ieee802154_unregister_device
);
414 MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
415 MODULE_LICENSE("GPL v2");