diff options
author | Alexander Aring <alex.aring@gmail.com> | 2014-11-17 02:20:53 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-11-17 03:49:17 -0500 |
commit | b821ecd4c8a0b3b1fc1bdd191bb7d555d818cafe (patch) | |
tree | c8f3ac6ef58c923437e200b7d96b6c7987576dd7 /net/ieee802154 | |
parent | 0e57547eb7f0aa99aba32b50c49dbd722a80d6fb (diff) |
ieee802154: add del interface command
This patch adds support for deleting a wpan interface via nl802154.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/nl802154.c | 28 | ||||
-rw-r--r-- | net/ieee802154/rdev-ops.h | 7 |
2 files changed, 35 insertions, 0 deletions
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 49c4d8a5004a..6b9bc93944a6 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c | |||
@@ -583,6 +583,26 @@ static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
583 | type, extended_addr); | 583 | type, extended_addr); |
584 | } | 584 | } |
585 | 585 | ||
586 | static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) | ||
587 | { | ||
588 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | ||
589 | struct wpan_dev *wpan_dev = info->user_ptr[1]; | ||
590 | |||
591 | if (!rdev->ops->del_virtual_intf) | ||
592 | return -EOPNOTSUPP; | ||
593 | |||
594 | /* If we remove a wpan device without a netdev then clear | ||
595 | * user_ptr[1] so that nl802154_post_doit won't dereference it | ||
596 | * to check if it needs to do dev_put(). Otherwise it crashes | ||
597 | * since the wpan_dev has been freed, unlike with a netdev where | ||
598 | * we need the dev_put() for the netdev to really be freed. | ||
599 | */ | ||
600 | if (!wpan_dev->netdev) | ||
601 | info->user_ptr[1] = NULL; | ||
602 | |||
603 | return rdev_del_virtual_intf(rdev, wpan_dev); | ||
604 | } | ||
605 | |||
586 | static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info) | 606 | static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info) |
587 | { | 607 | { |
588 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; | 608 | struct cfg802154_registered_device *rdev = info->user_ptr[0]; |
@@ -859,6 +879,14 @@ static const struct genl_ops nl802154_ops[] = { | |||
859 | NL802154_FLAG_NEED_RTNL, | 879 | NL802154_FLAG_NEED_RTNL, |
860 | }, | 880 | }, |
861 | { | 881 | { |
882 | .cmd = NL802154_CMD_DEL_INTERFACE, | ||
883 | .doit = nl802154_del_interface, | ||
884 | .policy = nl802154_policy, | ||
885 | .flags = GENL_ADMIN_PERM, | ||
886 | .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | | ||
887 | NL802154_FLAG_NEED_RTNL, | ||
888 | }, | ||
889 | { | ||
862 | .cmd = NL802154_CMD_SET_CHANNEL, | 890 | .cmd = NL802154_CMD_SET_CHANNEL, |
863 | .doit = nl802154_set_channel, | 891 | .doit = nl802154_set_channel, |
864 | .policy = nl802154_policy, | 892 | .policy = nl802154_policy, |
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h index 06e97542dafb..40ffbc0d8b85 100644 --- a/net/ieee802154/rdev-ops.h +++ b/net/ieee802154/rdev-ops.h | |||
@@ -29,6 +29,13 @@ rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name, | |||
29 | } | 29 | } |
30 | 30 | ||
31 | static inline int | 31 | static inline int |
32 | rdev_del_virtual_intf(struct cfg802154_registered_device *rdev, | ||
33 | struct wpan_dev *wpan_dev) | ||
34 | { | ||
35 | return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev); | ||
36 | } | ||
37 | |||
38 | static inline int | ||
32 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) | 39 | rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel) |
33 | { | 40 | { |
34 | return rdev->ops->set_channel(&rdev->wpan_phy, page, channel); | 41 | return rdev->ops->set_channel(&rdev->wpan_phy, page, channel); |