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/cfg802154.h>
30 #include "ieee802154_i.h"
32 int mac802154_slave_open(struct net_device
*dev
)
34 struct ieee802154_sub_if_data
*sdata
= IEEE802154_DEV_TO_SUB_IF(dev
);
35 struct ieee802154_sub_if_data
*subif
;
36 struct ieee802154_local
*local
= sdata
->local
;
41 if (sdata
->type
== IEEE802154_DEV_WPAN
) {
42 mutex_lock(&sdata
->local
->iflist_mtx
);
43 list_for_each_entry(subif
, &sdata
->local
->interfaces
, list
) {
44 if (subif
!= sdata
&& subif
->type
== sdata
->type
&&
46 mutex_unlock(&sdata
->local
->iflist_mtx
);
50 mutex_unlock(&sdata
->local
->iflist_mtx
);
53 mutex_lock(&sdata
->local
->iflist_mtx
);
54 sdata
->running
= true;
55 mutex_unlock(&sdata
->local
->iflist_mtx
);
57 if (local
->open_count
++ == 0) {
58 res
= local
->ops
->start(&local
->hw
);
64 netif_start_queue(dev
);
67 sdata
->local
->open_count
--;
72 int mac802154_slave_close(struct net_device
*dev
)
74 struct ieee802154_sub_if_data
*sdata
= IEEE802154_DEV_TO_SUB_IF(dev
);
75 struct ieee802154_local
*local
= sdata
->local
;
79 netif_stop_queue(dev
);
81 mutex_lock(&sdata
->local
->iflist_mtx
);
82 sdata
->running
= false;
83 mutex_unlock(&sdata
->local
->iflist_mtx
);
85 if (!--local
->open_count
)
86 local
->ops
->stop(&local
->hw
);
92 mac802154_netdev_register(struct wpan_phy
*phy
, struct net_device
*dev
)
94 struct ieee802154_sub_if_data
*sdata
= IEEE802154_DEV_TO_SUB_IF(dev
);
95 struct ieee802154_local
*local
;
98 local
= wpan_phy_priv(phy
);
101 sdata
->local
= local
;
103 dev
->needed_headroom
= local
->hw
.extra_tx_headroom
;
105 SET_NETDEV_DEV(dev
, &local
->phy
->dev
);
107 mutex_lock(&local
->iflist_mtx
);
108 if (!local
->running
) {
109 mutex_unlock(&local
->iflist_mtx
);
112 mutex_unlock(&local
->iflist_mtx
);
114 err
= register_netdev(dev
);
119 mutex_lock(&local
->iflist_mtx
);
120 list_add_tail_rcu(&sdata
->list
, &local
->interfaces
);
121 mutex_unlock(&local
->iflist_mtx
);
128 mac802154_del_iface(struct wpan_phy
*phy
, struct net_device
*dev
)
130 struct ieee802154_sub_if_data
*sdata
= IEEE802154_DEV_TO_SUB_IF(dev
);
134 BUG_ON(sdata
->local
->phy
!= phy
);
136 mutex_lock(&sdata
->local
->iflist_mtx
);
137 list_del_rcu(&sdata
->list
);
138 mutex_unlock(&sdata
->local
->iflist_mtx
);
141 unregister_netdevice(sdata
->dev
);
144 static struct net_device
*
145 mac802154_add_iface(struct wpan_phy
*phy
, const char *name
, int type
)
147 struct net_device
*dev
;
151 case IEEE802154_DEV_MONITOR
:
152 dev
= alloc_netdev(sizeof(struct ieee802154_sub_if_data
),
153 name
, NET_NAME_UNKNOWN
,
154 mac802154_monitor_setup
);
156 case IEEE802154_DEV_WPAN
:
157 dev
= alloc_netdev(sizeof(struct ieee802154_sub_if_data
),
158 name
, NET_NAME_UNKNOWN
,
159 mac802154_wpan_setup
);
169 err
= mac802154_netdev_register(phy
, dev
);
173 dev_hold(dev
); /* we return an incremented device refcount */
182 static int mac802154_set_txpower(struct wpan_phy
*phy
, int db
)
184 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
186 return local
->ops
->set_txpower(&local
->hw
, db
);
189 static int mac802154_set_lbt(struct wpan_phy
*phy
, bool on
)
191 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
193 return local
->ops
->set_lbt(&local
->hw
, on
);
196 static int mac802154_set_cca_mode(struct wpan_phy
*phy
, u8 mode
)
198 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
200 return local
->ops
->set_cca_mode(&local
->hw
, mode
);
203 static int mac802154_set_cca_ed_level(struct wpan_phy
*phy
, s32 level
)
205 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
207 return local
->ops
->set_cca_ed_level(&local
->hw
, level
);
210 static int mac802154_set_csma_params(struct wpan_phy
*phy
, u8 min_be
,
211 u8 max_be
, u8 retries
)
213 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
215 return local
->ops
->set_csma_params(&local
->hw
, min_be
, max_be
, retries
);
218 static int mac802154_set_frame_retries(struct wpan_phy
*phy
, s8 retries
)
220 struct ieee802154_local
*local
= wpan_phy_priv(phy
);
222 return local
->ops
->set_frame_retries(&local
->hw
, retries
);
225 struct ieee802154_hw
*
226 ieee802154_alloc_hw(size_t priv_data_len
, struct ieee802154_ops
*ops
)
228 struct wpan_phy
*phy
;
229 struct ieee802154_local
*local
;
232 if (!ops
|| !(ops
->xmit_async
|| ops
->xmit_sync
) || !ops
->ed
||
233 !ops
->start
|| !ops
->stop
|| !ops
->set_channel
) {
234 pr_err("undefined IEEE802.15.4 device operations\n");
238 /* Ensure 32-byte alignment of our private data and hw private data.
239 * We use the wpan_phy priv data for both our ieee802154_local and for
240 * the driver's private data
242 * in memory it'll be like this:
244 * +-------------------------+
245 * | struct wpan_phy |
246 * +-------------------------+
247 * | struct ieee802154_local |
248 * +-------------------------+
249 * | driver's private data |
250 * +-------------------------+
252 * Due to ieee802154 layer isn't aware of driver and MAC structures,
253 * so lets align them here.
256 priv_size
= ALIGN(sizeof(*local
), NETDEV_ALIGN
) + priv_data_len
;
258 phy
= wpan_phy_alloc(priv_size
);
260 pr_err("failure to allocate master IEEE802.15.4 device\n");
264 local
= wpan_phy_priv(phy
);
266 local
->hw
.phy
= local
->phy
;
267 local
->hw
.priv
= (char *)local
+ ALIGN(sizeof(*local
), NETDEV_ALIGN
);
270 INIT_LIST_HEAD(&local
->interfaces
);
271 mutex_init(&local
->iflist_mtx
);
275 EXPORT_SYMBOL(ieee802154_alloc_hw
);
277 void ieee802154_free_hw(struct ieee802154_hw
*hw
)
279 struct ieee802154_local
*local
= hw_to_local(hw
);
281 BUG_ON(!list_empty(&local
->interfaces
));
283 mutex_destroy(&local
->iflist_mtx
);
285 wpan_phy_free(local
->phy
);
287 EXPORT_SYMBOL(ieee802154_free_hw
);
289 int ieee802154_register_hw(struct ieee802154_hw
*hw
)
291 struct ieee802154_local
*local
= hw_to_local(hw
);
294 if (hw
->flags
& IEEE802154_HW_TXPOWER
) {
295 if (!local
->ops
->set_txpower
)
298 local
->phy
->set_txpower
= mac802154_set_txpower
;
301 if (hw
->flags
& IEEE802154_HW_LBT
) {
302 if (!local
->ops
->set_lbt
)
305 local
->phy
->set_lbt
= mac802154_set_lbt
;
308 if (hw
->flags
& IEEE802154_HW_CCA_MODE
) {
309 if (!local
->ops
->set_cca_mode
)
312 local
->phy
->set_cca_mode
= mac802154_set_cca_mode
;
315 if (hw
->flags
& IEEE802154_HW_CCA_ED_LEVEL
) {
316 if (!local
->ops
->set_cca_ed_level
)
319 local
->phy
->set_cca_ed_level
= mac802154_set_cca_ed_level
;
322 if (hw
->flags
& IEEE802154_HW_CSMA_PARAMS
) {
323 if (!local
->ops
->set_csma_params
)
326 local
->phy
->set_csma_params
= mac802154_set_csma_params
;
329 if (hw
->flags
& IEEE802154_HW_FRAME_RETRIES
) {
330 if (!local
->ops
->set_frame_retries
)
333 local
->phy
->set_frame_retries
= mac802154_set_frame_retries
;
337 create_singlethread_workqueue(wpan_phy_name(local
->phy
));
338 if (!local
->workqueue
) {
343 wpan_phy_set_dev(local
->phy
, local
->hw
.parent
);
345 local
->phy
->add_iface
= mac802154_add_iface
;
346 local
->phy
->del_iface
= mac802154_del_iface
;
348 rc
= wpan_phy_register(local
->phy
);
354 mutex_lock(&local
->iflist_mtx
);
355 local
->running
= MAC802154_DEVICE_RUN
;
356 mutex_unlock(&local
->iflist_mtx
);
363 destroy_workqueue(local
->workqueue
);
367 EXPORT_SYMBOL(ieee802154_register_hw
);
369 void ieee802154_unregister_hw(struct ieee802154_hw
*hw
)
371 struct ieee802154_local
*local
= hw_to_local(hw
);
372 struct ieee802154_sub_if_data
*sdata
, *next
;
374 flush_workqueue(local
->workqueue
);
375 destroy_workqueue(local
->workqueue
);
379 mutex_lock(&local
->iflist_mtx
);
380 local
->running
= MAC802154_DEVICE_STOPPED
;
381 mutex_unlock(&local
->iflist_mtx
);
383 list_for_each_entry_safe(sdata
, next
, &local
->interfaces
, list
) {
384 mutex_lock(&sdata
->local
->iflist_mtx
);
385 list_del(&sdata
->list
);
386 mutex_unlock(&sdata
->local
->iflist_mtx
);
388 unregister_netdevice(sdata
->dev
);
393 wpan_phy_unregister(local
->phy
);
395 EXPORT_SYMBOL(ieee802154_unregister_hw
);
397 MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
398 MODULE_LICENSE("GPL v2");