From 039fada5cd1963c32ed13d18d0dd467fdf966b66 Mon Sep 17 00:00:00 2001 From: Chan-yeol Park Date: Fri, 31 Oct 2014 14:23:06 +0900 Subject: [PATCH 01/61] Bluetooth: Fix hci_sync missing wakeup interrupt __hci_cmd_sync_ev(), __hci_req_sync() could miss wake_up_interrupt from hci_req_sync_complete() because hci_cmd_work() workqueue and its response could be completed before they are ready to get the signal through add_wait_queue(), set_current_state(TASK_INTERRUPTIBLE). Signed-off-by: Chan-yeol Park Signed-off-by: Kyungmin Park Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 91995f8ab0a0..41b147c36d11 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1147,13 +1147,15 @@ struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, hdev->req_status = HCI_REQ_PEND; - err = hci_req_run(&req, hci_req_sync_complete); - if (err < 0) - return ERR_PTR(err); - add_wait_queue(&hdev->req_wait_q, &wait); set_current_state(TASK_INTERRUPTIBLE); + err = hci_req_run(&req, hci_req_sync_complete); + if (err < 0) { + remove_wait_queue(&hdev->req_wait_q, &wait); + return ERR_PTR(err); + } + schedule_timeout(timeout); remove_wait_queue(&hdev->req_wait_q, &wait); @@ -1211,10 +1213,15 @@ static int __hci_req_sync(struct hci_dev *hdev, func(&req, opt); + add_wait_queue(&hdev->req_wait_q, &wait); + set_current_state(TASK_INTERRUPTIBLE); + err = hci_req_run(&req, hci_req_sync_complete); if (err < 0) { hdev->req_status = 0; + remove_wait_queue(&hdev->req_wait_q, &wait); + /* ENODATA means the HCI request command queue is empty. * This can happen when a request with conditionals doesn't * trigger any commands to be sent. This is normal behavior @@ -1226,9 +1233,6 @@ static int __hci_req_sync(struct hci_dev *hdev, return err; } - add_wait_queue(&hdev->req_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(timeout); remove_wait_queue(&hdev->req_wait_q, &wait); From fe23bcd920015bfb655f4b3d129a9368ce8e660c Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:32 +0100 Subject: [PATCH 02/61] at86rf230: fix page parameter constraints Since commit e37d2ec82a222f1819e7793a27bc052999a379fb ("mac802154: ops: declare channel and page as u8") the page parameter can't be below zero. This patch fix a kbuild test robot warning. Furthermore this check should be removed and handled by netlink 802.15.4 interface. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 9ad2d432ef43..624080d97209 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1047,7 +1047,7 @@ at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel) struct at86rf230_local *lp = hw->priv; int rc; - if (page < 0 || page > 31 || + if (page > 31 || !(lp->hw->phy->channels_supported[page] & BIT(channel))) { WARN_ON(1); return -EINVAL; From ff4e65581eb5349b7cefeda4083abe6eba44378a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:33 +0100 Subject: [PATCH 03/61] ieee802154: remove default channel settings This patch removes the default channel setting. A channel is always set and there is no default channel setting according 802.15.4. Drivers should set the default channel and page in probing routine. This behaviour is currently a lack of all 802.15.4 drivers. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index 620abc2ba5fc..dc294a415d05 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c @@ -100,9 +100,6 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size) phy->dev.class = &wpan_phy_class; - phy->current_channel = -1; /* not initialised */ - phy->current_page = 0; /* for compatibility */ - return phy; out: From fe58d016e396fc685364b5a1743faf83c1fb8103 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:34 +0100 Subject: [PATCH 04/61] at86rf230: add default channel settings This patch sets the reset state channels accoridng at86rf2xx datasheets. We don't need to set the default page here which is zero on all chips. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 624080d97209..f68ebba91b10 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1427,6 +1427,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) chip = "at86rf231"; lp->data = &at86rf231_data; lp->hw->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->current_channel = 11; break; case 7: chip = "at86rf212"; @@ -1435,6 +1436,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->hw->flags |= IEEE802154_HW_LBT; lp->hw->phy->channels_supported[0] = 0x00007FF; lp->hw->phy->channels_supported[2] = 0x00007FF; + lp->hw->phy->current_channel = 5; } else { rc = -ENOTSUPP; } @@ -1443,6 +1445,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) chip = "at86rf233"; lp->data = &at86rf233_data; lp->hw->phy->channels_supported[0] = 0x7FFF800; + lp->hw->phy->current_channel = 13; break; default: chip = "unkown"; From a5dd1d72d868ec9c8f44d60ca29900b6a38321b4 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:35 +0100 Subject: [PATCH 05/61] cfg802154: introduce cfg802154_registered_device This patch introduce the cfg802154_registered_device struct. Like cfg80211_registered_device in wireless this should contain similar functionality for cfg802154. This patch should not change any behaviour. We just adds cfg802154_registered_device as container for wpan_phy struct. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 8 +++++++- net/ieee802154/core.c | 39 ++++++++++++++++++++++++++------------- net/ieee802154/core.h | 18 ++++++++++++++++++ net/ieee802154/sysfs.c | 15 ++++++++++++--- net/mac802154/main.c | 2 +- 5 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 net/ieee802154/core.h diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 440b9bece9c6..12de66bda9a5 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -29,6 +29,11 @@ #define WPAN_NUM_CHANNELS 27 #define WPAN_NUM_PAGES 32 +struct wpan_phy; + +struct cfg802154_ops { +}; + struct wpan_phy { struct mutex pib_lock; @@ -62,7 +67,8 @@ struct wpan_phy { #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) -struct wpan_phy *wpan_phy_alloc(size_t priv_size); +struct wpan_phy * +wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size); static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev) { phy->dev.parent = dev; diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index dc294a415d05..ed5b014dbec7 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c @@ -21,6 +21,7 @@ #include "ieee802154.h" #include "sysfs.h" +#include "core.h" static DEFINE_MUTEX(wpan_phy_mutex); static int wpan_phy_idx; @@ -76,31 +77,38 @@ static int wpan_phy_idx_valid(int idx) return idx >= 0; } -struct wpan_phy *wpan_phy_alloc(size_t priv_size) +struct wpan_phy * +wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size) { - struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size, - GFP_KERNEL); + struct cfg802154_registered_device *rdev; + size_t alloc_size; + + alloc_size = sizeof(*rdev) + priv_size; + rdev = kzalloc(alloc_size, GFP_KERNEL); + if (!rdev) + return NULL; + + rdev->ops = ops; - if (!phy) - goto out; mutex_lock(&wpan_phy_mutex); - phy->idx = wpan_phy_idx++; - if (unlikely(!wpan_phy_idx_valid(phy->idx))) { + rdev->wpan_phy.idx = wpan_phy_idx++; + if (unlikely(!wpan_phy_idx_valid(rdev->wpan_phy.idx))) { wpan_phy_idx--; mutex_unlock(&wpan_phy_mutex); - kfree(phy); + kfree(rdev); goto out; } mutex_unlock(&wpan_phy_mutex); - mutex_init(&phy->pib_lock); + mutex_init(&rdev->wpan_phy.pib_lock); - device_initialize(&phy->dev); - dev_set_name(&phy->dev, "wpan-phy%d", phy->idx); + device_initialize(&rdev->wpan_phy.dev); + dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy.idx); - phy->dev.class = &wpan_phy_class; + rdev->wpan_phy.dev.class = &wpan_phy_class; + rdev->wpan_phy.dev.platform_data = rdev; - return phy; + return &rdev->wpan_phy; out: return NULL; @@ -125,6 +133,11 @@ void wpan_phy_free(struct wpan_phy *phy) } EXPORT_SYMBOL(wpan_phy_free); +void cfg802154_dev_free(struct cfg802154_registered_device *rdev) +{ + kfree(rdev); +} + static int __init wpan_phy_class_init(void) { int rc; diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h new file mode 100644 index 000000000000..26752ca54b4f --- /dev/null +++ b/net/ieee802154/core.h @@ -0,0 +1,18 @@ +#ifndef __IEEE802154_CORE_H +#define __IEEE802154_CORE_H + +#include + +struct cfg802154_registered_device { + const struct cfg802154_ops *ops; + + /* must be last because of the way we do wpan_phy_priv(), + * and it should at least be aligned to NETDEV_ALIGN + */ + struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN); +}; + +/* free object */ +void cfg802154_dev_free(struct cfg802154_registered_device *rdev); + +#endif /* __IEEE802154_CORE_H */ diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c index eb9ca6f99122..c6e038099e07 100644 --- a/net/ieee802154/sysfs.c +++ b/net/ieee802154/sysfs.c @@ -17,6 +17,15 @@ #include +#include "core.h" + +static inline struct cfg802154_registered_device * +dev_to_rdev(struct device *dev) +{ + return container_of(dev, struct cfg802154_registered_device, + wpan_phy.dev); +} + #define MASTER_SHOW_COMPLEX(name, format_string, args...) \ static ssize_t name ## _show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -60,11 +69,11 @@ static ssize_t channels_supported_show(struct device *dev, } static DEVICE_ATTR_RO(channels_supported); -static void wpan_phy_release(struct device *d) +static void wpan_phy_release(struct device *dev) { - struct wpan_phy *phy = container_of(d, struct wpan_phy, dev); + struct cfg802154_registered_device *rdev = dev_to_rdev(dev); - kfree(phy); + cfg802154_dev_free(rdev); } static struct attribute *pmib_attrs[] = { diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 86e533ed3775..ebc2bb123cfe 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -169,7 +169,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; - phy = wpan_phy_alloc(priv_size); + phy = wpan_phy_alloc(NULL, priv_size); if (!phy) { pr_err("failure to allocate master IEEE802.15.4 device\n"); return NULL; From 1201cd22fd1f4579a888c0f7abc65627d5962f29 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:36 +0100 Subject: [PATCH 06/61] mac802154: introduce mac802154_config_ops This patch introduces mac802154_config_ops struct. Like wireless this struct should be the only one interface between ieee802154 to mac802154 or possible HardMAC drivers. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/Makefile | 2 +- net/mac802154/cfg.c | 19 +++++++++++++++++++ net/mac802154/cfg.h | 9 +++++++++ net/mac802154/main.c | 3 ++- 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 net/mac802154/cfg.c create mode 100644 net/mac802154/cfg.h diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile index 2e497d0c829a..702d8b466317 100644 --- a/net/mac802154/Makefile +++ b/net/mac802154/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_MAC802154) += mac802154.o mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \ - iface.o llsec.o util.o + iface.o llsec.o util.o cfg.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c new file mode 100644 index 000000000000..105468ec8f26 --- /dev/null +++ b/net/mac802154/cfg.c @@ -0,0 +1,19 @@ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Authors: + * Alexander Aring + * + * Based on: net/mac80211/cfg.c + */ + +#include + +const struct cfg802154_ops mac802154_config_ops = { +}; diff --git a/net/mac802154/cfg.h b/net/mac802154/cfg.h new file mode 100644 index 000000000000..e2718f981e82 --- /dev/null +++ b/net/mac802154/cfg.h @@ -0,0 +1,9 @@ +/* mac802154 configuration hooks for cfg802154 + */ + +#ifndef __CFG_H +#define __CFG_H + +extern const struct cfg802154_ops mac802154_config_ops; + +#endif /* __CFG_H */ diff --git a/net/mac802154/main.c b/net/mac802154/main.c index ebc2bb123cfe..785abb1aafb4 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -28,6 +28,7 @@ #include #include "ieee802154_i.h" +#include "cfg.h" static int mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) @@ -169,7 +170,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len; - phy = wpan_phy_alloc(NULL, priv_size); + phy = wpan_phy_alloc(&mac802154_config_ops, priv_size); if (!phy) { pr_err("failure to allocate master IEEE802.15.4 device\n"); return NULL; From ea4dcd32a445908c12e04b3b879c57ec5b3e659a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:37 +0100 Subject: [PATCH 07/61] ieee802154: add helper wpan_phy_to_rdev function This patch introduce a function to get the cfg802154_registered_device from a wpan_phy. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/core.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h index 26752ca54b4f..1bc172587157 100644 --- a/net/ieee802154/core.h +++ b/net/ieee802154/core.h @@ -12,6 +12,14 @@ struct cfg802154_registered_device { struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN); }; +static inline struct cfg802154_registered_device * +wpan_phy_to_rdev(struct wpan_phy *wpan_phy) +{ + BUG_ON(!wpan_phy); + return container_of(wpan_phy, struct cfg802154_registered_device, + wpan_phy); +} + /* free object */ void cfg802154_dev_free(struct cfg802154_registered_device *rdev); From 4a9a816a4f8c79260446811bdf80615b36539949 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:38 +0100 Subject: [PATCH 08/61] cfg802154: convert deprecated iface add and del This patch removes the wpan_phy callbacks for add and del an interface on a phy. Instead we introduce deprecated cfg802154 callbacks for this. Furthermore we introduce a new netlink interface nl802154 which use different callbacks. The deprecated function is to have a backwards compatibility with the current netlink interface. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 9 +++++---- net/ieee802154/nl-phy.c | 19 ++++++------------- net/ieee802154/rdev-ops.h | 23 +++++++++++++++++++++++ net/mac802154/cfg.c | 17 +++++++++++++++++ net/mac802154/ieee802154_i.h | 4 ++++ net/mac802154/main.c | 8 ++------ 6 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 net/ieee802154/rdev-ops.h diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 12de66bda9a5..864bce2b0728 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -32,6 +32,11 @@ struct wpan_phy; struct cfg802154_ops { + struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, + const char *name, + int type); + void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy, + struct net_device *dev); }; struct wpan_phy { @@ -58,10 +63,6 @@ struct wpan_phy { struct device dev; int idx; - struct net_device *(*add_iface)(struct wpan_phy *phy, - const char *name, int type); - void (*del_iface)(struct wpan_phy *phy, struct net_device *dev); - char priv[0] __aligned(NETDEV_ALIGN); }; diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 0afe760ff512..5d914d30e0b1 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -30,6 +30,8 @@ #include #include "ieee802154.h" +#include "rdev-ops.h" +#include "core.h" static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, u32 seq, int flags, struct wpan_phy *phy) @@ -203,11 +205,6 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) if (!msg) goto out_dev; - if (!phy->add_iface) { - rc = -EINVAL; - goto nla_put_failure; - } - if (info->attrs[IEEE802154_ATTR_HW_ADDR] && nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) != IEEE802154_ADDR_LEN) { @@ -223,7 +220,8 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) } } - dev = phy->add_iface(phy, devname, type); + dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname, + type); if (IS_ERR(dev)) { rc = PTR_ERR(dev); goto nla_put_failure; @@ -257,7 +255,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) dev_unregister: rtnl_lock(); /* del_iface must be called with RTNL lock */ - phy->del_iface(phy, dev); + rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev); dev_put(dev); rtnl_unlock(); nla_put_failure: @@ -319,13 +317,8 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) if (!msg) goto out_dev; - if (!phy->del_iface) { - rc = -EINVAL; - goto nla_put_failure; - } - rtnl_lock(); - phy->del_iface(phy, dev); + rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev); /* We don't have device anymore */ dev_put(dev); diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h new file mode 100644 index 000000000000..ac8824ec168c --- /dev/null +++ b/net/ieee802154/rdev-ops.h @@ -0,0 +1,23 @@ +#ifndef __CFG802154_RDEV_OPS +#define __CFG802154_RDEV_OPS + +#include + +#include "core.h" + +static inline struct net_device * +rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, + const char *name, int type) +{ + return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name, + type); +} + +static inline void +rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev, + struct net_device *dev) +{ + rdev->ops->del_virtual_intf_deprecated(&rdev->wpan_phy, dev); +} + +#endif /* __CFG802154_RDEV_OPS */ diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 105468ec8f26..75a5d258ac24 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -15,5 +15,22 @@ #include +#include "ieee802154_i.h" + +static struct net_device * +ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, + const char *name, int type) +{ + return mac802154_add_iface(wpan_phy, name, type); +} + +static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, + struct net_device *dev) +{ + mac802154_del_iface(wpan_phy, dev); +} + const struct cfg802154_ops mac802154_config_ops = { + .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, + .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, }; diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 1086a9d96f8f..39af6eaec410 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -174,4 +174,8 @@ void mac802154_get_table(struct net_device *dev, struct ieee802154_llsec_table **t); void mac802154_unlock_table(struct net_device *dev); +struct net_device * +mac802154_add_iface(struct wpan_phy *phy, const char *name, int type); +void mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev); + #endif /* __IEEE802154_I_H */ diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 785abb1aafb4..b34ddbf43c3d 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -59,8 +59,7 @@ mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) return 0; } -static void -mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) +void mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); @@ -76,7 +75,7 @@ mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) unregister_netdevice(sdata->dev); } -static struct net_device * +struct net_device * mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) { struct net_device *dev; @@ -221,9 +220,6 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) wpan_phy_set_dev(local->phy, local->hw.parent); - local->phy->add_iface = mac802154_add_iface; - local->phy->del_iface = mac802154_del_iface; - rc = wpan_phy_register(local->phy); if (rc < 0) goto out_wq; From 8f499f991c275d5251a427c424360a9c60f549e4 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:39 +0100 Subject: [PATCH 09/61] ieee802154: don't allow to change addr while netif_running This patch changes the actual behaviour for setting address attributes. We should not change addresses while netif_running is true. Furthermore when netif_running is running the address attributes becomes read only and we can remove locking mechanism in receive and transmit hothpaths of 802.15.4 subsystem. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/nl-mac.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index abd0f31bdc66..cc2919dbe5e0 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -477,7 +477,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) u8 channel, bcn_ord, sf_ord; u8 page; int pan_coord, blx, coord_realign; - int ret = -EOPNOTSUPP; + int ret = -EBUSY; if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || @@ -493,9 +493,15 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) dev = ieee802154_nl_get_dev(info); if (!dev) return -ENODEV; - if (!ieee802154_mlme_ops(dev)->start_req) + + if (netif_running(dev)) goto out; + if (!ieee802154_mlme_ops(dev)->start_req) { + ret = -EOPNOTSUPP; + goto out; + } + addr.mode = IEEE802154_ADDR_SHORT; addr.short_addr = nla_get_shortaddr( info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); From ab24f50f2a3e3f6a38b4852530534aa99d86b4d1 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:40 +0100 Subject: [PATCH 10/61] mac802154: add helper for converting dev_addr This patch adds a helper for converting the dev_addr attribute in netdevice to __le64 type. The dev_addr attribute is a char pointer and contains the extended address in big endian byte order. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/mac802154.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 8f1de6844cb0..c17acbd0dadc 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -214,6 +214,15 @@ struct ieee802154_ops { const bool on); }; +/** + * ieee802154_netdev_to_extended_addr - convert __be64 u8 pointer to __le64 + * @dev_addr: big endian address pointer like netdevice dev_addr attribute + */ +static inline __le64 ieee802154_netdev_to_extended_addr(const u8 *dev_addr) +{ + return (__le64)swab64(*((__be64 *)dev_addr)); +} + /* Basic interface to register ieee802154 hwice */ struct ieee802154_hw * ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops); From 776e59de46b5db368e1bd0a4ec5c4feaa740a3d1 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:41 +0100 Subject: [PATCH 11/61] mac802154: set extended address filter on ifup This patch moves the setting of hardware extended address filtering inside of interface up instead doing it directly inside of netlink interface. Also we don't need to set the sdata extended attribute in netlink. This is already done by ndo_set_mac_address of net_device_ops. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/ieee802154_i.h | 1 - net/mac802154/iface.c | 10 +++++++++- net/mac802154/mac_cmd.c | 1 - net/mac802154/mib.c | 14 -------------- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 39af6eaec410..27e17e6bcf18 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -135,7 +135,6 @@ ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); /* MIB callbacks */ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); __le16 mac802154_dev_get_short_addr(const struct net_device *dev); -void mac802154_dev_set_ieee_addr(struct net_device *dev); __le16 mac802154_dev_get_pan_id(const struct net_device *dev); void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index f7a6f83301e2..a509a7151be9 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -110,6 +110,7 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) { + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct sockaddr *addr = p; if (netif_running(dev)) @@ -117,7 +118,8 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) /* FIXME: validate addr */ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - mac802154_dev_set_ieee_addr(dev); + sdata->extended_addr = ieee802154_netdev_to_extended_addr(dev->dev_addr); + return mac802154_wpan_update_llsec(dev); } @@ -202,6 +204,12 @@ static int mac802154_wpan_open(struct net_device *dev) goto out; } + if (local->hw.flags & IEEE802154_HW_AFILT) { + rc = drv_set_extended_addr(local, sdata->extended_addr); + if (rc < 0) + goto out; + } + if (local->hw.flags & IEEE802154_HW_TXPOWER) { rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); if (rc < 0) diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index fc261ab33347..90c1ad80a67d 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c @@ -43,7 +43,6 @@ static int mac802154_mlme_start_req(struct net_device *dev, mac802154_dev_set_pan_id(dev, addr->pan_id); mac802154_dev_set_short_addr(dev, addr->short_addr); - mac802154_dev_set_ieee_addr(dev); mac802154_dev_set_page_channel(dev, page, channel); if (ops->llsec) { diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 0184fced2f62..cfd4f657a24e 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c @@ -102,20 +102,6 @@ __le16 mac802154_dev_get_short_addr(const struct net_device *dev) return ret; } -void mac802154_dev_set_ieee_addr(struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - struct ieee802154_local *local = sdata->local; - - sdata->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr); - - if (local->ops->set_hw_addr_filt && - local->hw.hw_filt.ieee_addr != sdata->extended_addr) { - local->hw.hw_filt.ieee_addr = sdata->extended_addr; - set_hw_addr_filt(dev, IEEE802154_AFILT_IEEEADDR_CHANGED); - } -} - __le16 mac802154_dev_get_pan_id(const struct net_device *dev) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); From 78b4bad16ec41e1d3d5575ff9aca29aab2f831bc Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:42 +0100 Subject: [PATCH 12/61] mac802154: set short address filter on ifup This patch moves the setting of hardware short address filtering inside of interface up instead doing it it directly inside of netlink interface. The netlink call which can only be called when netif isn't running sets only the necessary short_addr value in sdata. After an interface up the address filter will be set with this value. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 4 ++++ net/mac802154/mib.c | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index a509a7151be9..1bae29dff082 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -208,6 +208,10 @@ static int mac802154_wpan_open(struct net_device *dev) rc = drv_set_extended_addr(local, sdata->extended_addr); if (rc < 0) goto out; + + rc = drv_set_short_addr(local, sdata->short_addr); + if (rc < 0) + goto out; } if (local->hw.flags & IEEE802154_HW_TXPOWER) { diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index cfd4f657a24e..755befde6a17 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c @@ -80,12 +80,6 @@ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) spin_lock_bh(&sdata->mib_lock); sdata->short_addr = val; spin_unlock_bh(&sdata->mib_lock); - - if ((sdata->local->ops->set_hw_addr_filt) && - (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) { - sdata->local->hw.hw_filt.short_addr = sdata->short_addr; - set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED); - } } __le16 mac802154_dev_get_short_addr(const struct net_device *dev) From 50c79075019e7b952327cfebf0681548573fd8e5 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:43 +0100 Subject: [PATCH 13/61] mac802154: set panid address filter on ifup This patch moves the setting of hardware panid address filtering inside of interface up instead doing it it directly inside of netlink interface. The netlink call which can only be called when netif isn't running sets only the necessary panid value in sdata. After an interface up the address filter will be set with this value. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 4 ++++ net/mac802154/mib.c | 51 ------------------------------------------- 2 files changed, 4 insertions(+), 51 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 1bae29dff082..5f94c70478f9 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -205,6 +205,10 @@ static int mac802154_wpan_open(struct net_device *dev) } if (local->hw.flags & IEEE802154_HW_AFILT) { + rc = drv_set_pan_id(local, sdata->pan_id); + if (rc < 0) + goto out; + rc = drv_set_extended_addr(local, sdata->extended_addr); if (rc < 0) goto out; diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 755befde6a17..6fa749154baf 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c @@ -26,51 +26,6 @@ #include "ieee802154_i.h" #include "driver-ops.h" -struct hw_addr_filt_notify_work { - struct work_struct work; - struct net_device *dev; - unsigned long changed; -}; - -static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - BUG_ON(dev->type != ARPHRD_IEEE802154); - - return sdata->local; -} - -static void hw_addr_notify(struct work_struct *work) -{ - struct hw_addr_filt_notify_work *nw = container_of(work, - struct hw_addr_filt_notify_work, work); - struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev); - int res; - - res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt, - nw->changed); - if (res) - pr_debug("failed changed mask %lx\n", nw->changed); - - kfree(nw); -} - -static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - struct hw_addr_filt_notify_work *work; - - work = kzalloc(sizeof(*work), GFP_ATOMIC); - if (!work) - return; - - INIT_WORK(&work->work, hw_addr_notify); - work->dev = dev; - work->changed = changed; - queue_work(sdata->local->workqueue, &work->work); -} - void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); @@ -119,12 +74,6 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) spin_lock_bh(&sdata->mib_lock); sdata->pan_id = val; spin_unlock_bh(&sdata->mib_lock); - - if ((sdata->local->ops->set_hw_addr_filt) && - (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) { - sdata->local->hw.hw_filt.pan_id = sdata->pan_id; - set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED); - } } u8 mac802154_dev_get_dsn(const struct net_device *dev) From f59f419d31ee27c131b44beda5b14b8ce0aaf519 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:44 +0100 Subject: [PATCH 14/61] mac802154: move phy settings into netlink receive All PHY attributes should be directly set to the transceiver after netlink. MAC attributes should be set by interface up. Currently the macparams netlink cmd contains mixed attributes of phy and mac settings. This patch moves all phy settings to the netlink receive function for setting macparams. This is the only way which doesn't change the userspace API and keep the deprecated netlink interface alive. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 19 ------------------- net/mac802154/mac_cmd.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 5f94c70478f9..eaad66590f10 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -218,31 +218,12 @@ static int mac802154_wpan_open(struct net_device *dev) goto out; } - if (local->hw.flags & IEEE802154_HW_TXPOWER) { - rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); - if (rc < 0) - goto out; - } - if (local->hw.flags & IEEE802154_HW_LBT) { rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); if (rc < 0) goto out; } - if (local->hw.flags & IEEE802154_HW_CCA_MODE) { - rc = drv_set_cca_mode(local, sdata->mac_params.cca_mode); - if (rc < 0) - goto out; - } - - if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { - rc = drv_set_cca_ed_level(local, - sdata->mac_params.cca_ed_level); - if (rc < 0) - goto out; - } - if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) { rc = drv_set_csma_params(local, sdata->mac_params.min_be, sdata->mac_params.max_be, diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index 90c1ad80a67d..9c2d6f61f194 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c @@ -28,6 +28,7 @@ #include #include "ieee802154_i.h" +#include "driver-ops.h" static int mac802154_mlme_start_req(struct net_device *dev, struct ieee802154_addr *addr, @@ -85,11 +86,31 @@ static int mac802154_set_mac_params(struct net_device *dev, const struct ieee802154_mac_params *params) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + struct ieee802154_local *local = sdata->local; + int ret; mutex_lock(&sdata->local->iflist_mtx); sdata->mac_params = *params; mutex_unlock(&sdata->local->iflist_mtx); + if (local->hw.flags & IEEE802154_HW_TXPOWER) { + ret = drv_set_tx_power(local, params->transmit_power); + if (ret < 0) + return ret; + } + + if (local->hw.flags & IEEE802154_HW_CCA_MODE) { + ret = drv_set_cca_mode(local, params->cca_mode); + if (ret < 0) + return ret; + } + + if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) { + ret = drv_set_cca_ed_level(local, params->cca_ed_level); + if (ret < 0) + return ret; + } + return 0; } From cb904b0a16305f9b2a98200cc6eb9dc3610278b0 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:45 +0100 Subject: [PATCH 15/61] ieee802154: add extended address validation helper This patch introduce an extended address validation helper to check if an extended address is valid or not. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 6e50a2a1d485..9bba5ca7f0ad 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -197,4 +197,18 @@ static inline bool ieee802154_is_valid_psdu_len(const u8 len) return (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU); } +/** + * ieee802154_is_valid_psdu_len - check if extended addr is valid + * @addr: extended addr to check + */ +static inline bool ieee802154_is_valid_extended_addr(const __le64 addr) +{ + /* These EUI-64 addresses are reserved by IEEE. 0xffffffffffffffff + * is used internally as extended to short address broadcast mapping. + * This is currently a workaround because neighbor discovery can't + * deal with short addresses types right now. + */ + return ((addr != 0x0000000000000000) || (addr != 0xffffffffffffffff)); +} + #endif /* LINUX_IEEE802154_H */ From ea7053c1df41689dea0db2c49dc9d25dbe8fcf33 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:46 +0100 Subject: [PATCH 16/61] mac802154: iface: add validation for extended address This patch use the validation function to check if an extended address is valid or not while set the extended address. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index eaad66590f10..ceedf3ef1ce2 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -112,13 +112,17 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct sockaddr *addr = p; + __le64 extended_addr; if (netif_running(dev)) return -EBUSY; - /* FIXME: validate addr */ + extended_addr = ieee802154_netdev_to_extended_addr(addr->sa_data); + if (!ieee802154_is_valid_extended_addr(extended_addr)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - sdata->extended_addr = ieee802154_netdev_to_extended_addr(dev->dev_addr); + sdata->extended_addr = extended_addr; return mac802154_wpan_update_llsec(dev); } From 62906710182a7d079a69932a93ebd003caaa7135 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 04:18:47 +0100 Subject: [PATCH 17/61] ieee802154: 6lowpan: remove set of mac address Currently the ieee802154 6lowpan interface operates on wpan interfaces only. Setting the wpan mac address over 6lowpan interface is complex and maybe we can't never do this. This patch removes the set of mac address handling in ieee802154 6lowpan interface for now. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/6lowpan_rtnl.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 519a65452d90..659f7b25ea1a 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -206,19 +206,6 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) return -EINVAL; } -static int lowpan_set_address(struct net_device *dev, void *p) -{ - struct sockaddr *sa = p; - - if (netif_running(dev)) - return -EBUSY; - - /* TODO: validate addr */ - memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); - - return 0; -} - static struct sk_buff* lowpan_alloc_frag(struct sk_buff *skb, int size, const struct ieee802154_hdr *master_hdr) @@ -474,7 +461,6 @@ static int lowpan_dev_init(struct net_device *dev) static const struct net_device_ops lowpan_netdev_ops = { .ndo_init = lowpan_dev_init, .ndo_start_xmit = lowpan_xmit, - .ndo_set_mac_address = lowpan_set_address, }; static struct ieee802154_mlme_ops lowpan_mlme = { From 8761f9d6620b0be6b08f21807568fbbfcbb128d2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 02:45:58 +0100 Subject: [PATCH 18/61] Bluetooth: Check status of command complete for HCI_Reset When the HCI_Reset command returns, the status needs to be checked. It is unlikely that HCI_Reset actually fails, but when it fails, it is a bad idea to reset all values since the controller will have not reset its values in that case. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index aa152140c3e2..3dd2550b4c07 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -189,6 +189,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) clear_bit(HCI_RESET, &hdev->flags); + if (status) + return; + /* Reset all non-persistent flags */ hdev->dev_flags &= ~HCI_PERSISTENT_MASK; From 24dfa343716a493472db0555342bb88678efa444 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 02:56:41 +0100 Subject: [PATCH 19/61] Bluetooth: Print error message for HCI_Hardware_Error event When the HCI_Hardware_Error event is send by the controller or injected by the driver, then at least print an error message. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 5 +++++ net/bluetooth/hci_event.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 6e8f24967308..ecfa306e1375 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1463,6 +1463,11 @@ struct hci_ev_cmd_status { __le16 opcode; } __packed; +#define HCI_EV_HARDWARE_ERROR 0x10 +struct hci_ev_hardware_error { + __u8 code; +} __packed; + #define HCI_EV_ROLE_CHANGE 0x12 struct hci_ev_role_change { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3dd2550b4c07..2f02ff0ed781 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2925,6 +2925,13 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) } } +static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_hardware_error *ev = (void *) skb->data; + + BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code); +} + static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_role_change *ev = (void *) skb->data; @@ -4746,6 +4753,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_cmd_status_evt(hdev, skb); break; + case HCI_EV_HARDWARE_ERROR: + hci_hardware_error_evt(hdev, skb); + break; + case HCI_EV_ROLE_CHANGE: hci_role_change_evt(hdev, skb); break; From b34490011d0d1a08124ffd6c4d5814ec94cd8f8f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 03:02:01 +0100 Subject: [PATCH 20/61] Bluetooth: Use HCI_EV_HARDWARE_ERROR define for event payload When constructing the event payload for the HCI_Hardware_Error event message, use the HCI_EV_HARDWARE_ERROR define. In addition rename the variables from hard_err to hw_err to clearly indicate that this is about the hardware error and not a hard error. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci_h5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 20bdd71559b1..bd1fe37a7993 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -172,7 +172,7 @@ static void h5_peer_reset(struct hci_uart *hu) { struct h5 *h5 = hu->priv; struct sk_buff *skb; - const unsigned char hard_err[] = { 0x10, 0x01, 0x00 }; + const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 }; BT_ERR("Peer device has reset"); @@ -192,7 +192,7 @@ static void h5_peer_reset(struct hci_uart *hu) return; bt_cb(skb)->pkt_type = HCI_EVENT_PKT; - memcpy(skb_put(skb, 3), hard_err, 3); + memcpy(skb_put(skb, 3), hw_err, 3); /* Send Hardware Error to upper stack */ hci_recv_frame(hu->hdev, skb); From 65efd2bf4885312b42de9829159789199221cc60 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 03:32:25 +0100 Subject: [PATCH 21/61] Bluetooth: Introduce BT_BREDR and BT_LE config options The current kernel options do not make it clear which modules are for Bluetooth Classic (BR/EDR) and which are for Bluetooth Low Energy (LE). To make it really clear, introduce BT_BREDR and BT_LE options with proper dependencies into the different modules. Both new options default to y to not create a regression with previous kernel config files. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/Kconfig | 20 +++++++++++++++----- net/bluetooth/bnep/Kconfig | 2 +- net/bluetooth/cmtp/Kconfig | 2 +- net/bluetooth/hidp/Kconfig | 2 +- net/bluetooth/rfcomm/Kconfig | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 600fb29288f4..5e97a8ff850b 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -39,11 +39,10 @@ menuconfig BT to Bluetooth kernel modules are provided in the BlueZ packages. For more information, see . -config BT_6LOWPAN - tristate "Bluetooth 6LoWPAN support" - depends on BT && 6LOWPAN - help - IPv6 compression over Bluetooth Low Energy. +config BT_BREDR + bool "Bluetooth Classic (BR/EDR) features" + depends on BT + default y source "net/bluetooth/rfcomm/Kconfig" @@ -53,4 +52,15 @@ source "net/bluetooth/cmtp/Kconfig" source "net/bluetooth/hidp/Kconfig" +config BT_LE + bool "Bluetooth Low Energy (LE) features" + depends on BT + default y + +config BT_6LOWPAN + tristate "Bluetooth 6LoWPAN support" + depends on BT_LE && 6LOWPAN + help + IPv6 compression over Bluetooth Low Energy. + source "drivers/bluetooth/Kconfig" diff --git a/net/bluetooth/bnep/Kconfig b/net/bluetooth/bnep/Kconfig index 71791fc9f6b1..9b70317c49dc 100644 --- a/net/bluetooth/bnep/Kconfig +++ b/net/bluetooth/bnep/Kconfig @@ -1,6 +1,6 @@ config BT_BNEP tristate "BNEP protocol support" - depends on BT + depends on BT_BREDR select CRC32 help BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet diff --git a/net/bluetooth/cmtp/Kconfig b/net/bluetooth/cmtp/Kconfig index 94cbf42ce155..939da0fbdd88 100644 --- a/net/bluetooth/cmtp/Kconfig +++ b/net/bluetooth/cmtp/Kconfig @@ -1,6 +1,6 @@ config BT_CMTP tristate "CMTP protocol support" - depends on BT && ISDN_CAPI + depends on BT_BREDR && ISDN_CAPI help CMTP (CAPI Message Transport Protocol) is a transport layer for CAPI messages. CMTP is required for the Bluetooth Common diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig index 9332bc7aa851..bc8610b24077 100644 --- a/net/bluetooth/hidp/Kconfig +++ b/net/bluetooth/hidp/Kconfig @@ -1,6 +1,6 @@ config BT_HIDP tristate "HIDP protocol support" - depends on BT && INPUT + depends on BT_BREDR && INPUT select HID help HIDP (Human Interface Device Protocol) is a transport layer diff --git a/net/bluetooth/rfcomm/Kconfig b/net/bluetooth/rfcomm/Kconfig index 18d352ea2bc7..335df7515220 100644 --- a/net/bluetooth/rfcomm/Kconfig +++ b/net/bluetooth/rfcomm/Kconfig @@ -1,6 +1,6 @@ config BT_RFCOMM tristate "RFCOMM protocol support" - depends on BT + depends on BT_BREDR help RFCOMM provides connection oriented stream transport. RFCOMM support is required for Dialup Networking, OBEX and other Bluetooth From 75e0569f7fc22272ec5e3b99bf94c6f0ad43b35f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 08:15:38 +0100 Subject: [PATCH 22/61] Bluetooth: Add hci_reset_dev() for driver triggerd stack reset Some Bluetooth drivers require to reset the upper stack. To avoid having all drivers send HCI Hardware Error events, provide a generic function to wrap the reset functionality. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b8685a77a15e..27ddb905b351 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -856,6 +856,7 @@ int hci_register_dev(struct hci_dev *hdev); void hci_unregister_dev(struct hci_dev *hdev); int hci_suspend_dev(struct hci_dev *hdev); int hci_resume_dev(struct hci_dev *hdev); +int hci_reset_dev(struct hci_dev *hdev); int hci_dev_open(__u16 dev); int hci_dev_close(__u16 dev); int hci_dev_reset(__u16 dev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 41b147c36d11..a12e018ee21c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -4248,6 +4248,24 @@ int hci_resume_dev(struct hci_dev *hdev) } EXPORT_SYMBOL(hci_resume_dev); +/* Reset HCI device */ +int hci_reset_dev(struct hci_dev *hdev) +{ + const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 }; + struct sk_buff *skb; + + skb = bt_skb_alloc(3, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + bt_cb(skb)->pkt_type = HCI_EVENT_PKT; + memcpy(skb_put(skb, 3), hw_err, 3); + + /* Send Hardware Error to upper stack */ + return hci_recv_frame(hdev, skb); +} +EXPORT_SYMBOL(hci_reset_dev); + /* Receive frame from HCI drivers */ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) { From 882809fb724c46b8ebc4de0944e94914ceb94e1c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 08:15:39 +0100 Subject: [PATCH 23/61] Bluetooth: Switch HCI H5 driver to use hci_reset_dev() function Instead of having the driver generate the HCI Hardware Error event manually, just call hci_reset_dev() to trigger the upper stack reset. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/hci_h5.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index bd1fe37a7993..ec0fa7732c0d 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -171,8 +171,6 @@ static void h5_timed_event(unsigned long arg) static void h5_peer_reset(struct hci_uart *hu) { struct h5 *h5 = hu->priv; - struct sk_buff *skb; - const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 }; BT_ERR("Peer device has reset"); @@ -187,15 +185,8 @@ static void h5_peer_reset(struct hci_uart *hu) h5->tx_seq = 0; h5->tx_ack = 0; - skb = bt_skb_alloc(3, GFP_ATOMIC); - if (!skb) - return; - - bt_cb(skb)->pkt_type = HCI_EVENT_PKT; - memcpy(skb_put(skb, 3), hw_err, 3); - - /* Send Hardware Error to upper stack */ - hci_recv_frame(hu->hdev, skb); + /* Send reset request to upper stack */ + hci_reset_dev(hu->hdev); } static int h5_open(struct hci_uart *hu) From a4164eb4dd3f4f2a22f8bf7b26394e8384f3d9a2 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:01 +0100 Subject: [PATCH 24/61] ieee802154: add missing ULL definition Running make C=2 occurs warning: constant 0xffffffffffffffff is so big it is unsigned long This patch fix this warning by adding a ULL to the constant definitions. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 9bba5ca7f0ad..9da7c011fbba 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -208,7 +208,8 @@ static inline bool ieee802154_is_valid_extended_addr(const __le64 addr) * This is currently a workaround because neighbor discovery can't * deal with short addresses types right now. */ - return ((addr != 0x0000000000000000) || (addr != 0xffffffffffffffff)); + return ((addr != 0x0000000000000000ULL) || + (addr != 0xffffffffffffffffULL)); } #endif /* LINUX_IEEE802154_H */ From c28bee84c5c49312befe1b442e1044ac2392d80d Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:02 +0100 Subject: [PATCH 25/61] ieee802154: fix byteorder issues This patch fix byteorder issues which occurs because we compare __le64 with an host byteorder value. Simple add a cpu_to_le64 to convert the host byteorder values to __le64. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 9da7c011fbba..5d9e7459d94b 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -24,6 +24,7 @@ #define LINUX_IEEE802154_H #include +#include #define IEEE802154_MTU 127 #define IEEE802154_MIN_PSDU_LEN 5 @@ -208,8 +209,8 @@ static inline bool ieee802154_is_valid_extended_addr(const __le64 addr) * This is currently a workaround because neighbor discovery can't * deal with short addresses types right now. */ - return ((addr != 0x0000000000000000ULL) || - (addr != 0xffffffffffffffffULL)); + return ((addr != cpu_to_le64(0x0000000000000000ULL)) || + (addr != cpu_to_le64(0xffffffffffffffffULL))); } #endif /* LINUX_IEEE802154_H */ From f753f7eeb4178ab8eeaf513a4fdf1c20ddf40474 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:03 +0100 Subject: [PATCH 26/61] mac802154: fix byteorder issues Running make C=2 occurs these warnings: cast from restricted __be64 incorrect type in argument 1 (different base types) expected unsigned long long[unsigned] [usertype] val got restricted __be64 [usertype] cast from restricted __be64 cast to restricted __le64 This patch fix these warnings by forcing to __le64 type and using swabp64 instead swab64. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- include/net/mac802154.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/net/mac802154.h b/include/net/mac802154.h index c17acbd0dadc..8b0c26bc0762 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -215,12 +215,12 @@ struct ieee802154_ops { }; /** - * ieee802154_netdev_to_extended_addr - convert __be64 u8 pointer to __le64 + * ieee802154_netdev_to_extended_addr - convert big endian 64 byte void pointer to __le64 * @dev_addr: big endian address pointer like netdevice dev_addr attribute */ -static inline __le64 ieee802154_netdev_to_extended_addr(const u8 *dev_addr) +static inline __le64 ieee802154_netdev_to_extended_addr(const void *dev_addr) { - return (__le64)swab64(*((__be64 *)dev_addr)); + return (__force __le64)swab64p(dev_addr); } /* Basic interface to register ieee802154 hwice */ From c5fbbc4683276598ca1bfca95c90c35d1a3d962f Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:04 +0100 Subject: [PATCH 27/61] ieee802154: sysfs: add missing include Running make C=2 occurs in warnings: symbol 'wpan_phy_class' was not declared. Should it be static? symbol 'wpan_phy_sysfs_init' was not declared. Should it be static? symbol 'wpan_phy_sysfs_exit' wasnot declared. Should it be static? This patch adds a missing include "sysfs.h" to solve these warnings. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- net/ieee802154/sysfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c index c6e038099e07..88199980dae9 100644 --- a/net/ieee802154/sysfs.c +++ b/net/ieee802154/sysfs.c @@ -18,6 +18,7 @@ #include #include "core.h" +#include "sysfs.h" static inline struct cfg802154_registered_device * dev_to_rdev(struct device *dev) From fdd2068ab7574d9d9b966a97cc7af296a4232694 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:05 +0100 Subject: [PATCH 28/61] mac802154: cfg: add missing include Running make C=2 occurs warning: symbol 'mac802154_config_ops' was not declared. Should it be static? This patch adds a missing include in cfg.c to solve this warning. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- net/mac802154/cfg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 75a5d258ac24..0c69b44ba312 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -16,6 +16,7 @@ #include #include "ieee802154_i.h" +#include "cfg.h" static struct net_device * ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, From 868ed8e06a35ea2e73dfe4cb81d96dc85f545a8e Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 21:43:06 +0100 Subject: [PATCH 29/61] ieee802154: remove unnecessary functions This patch fixes commit c7420c367d63a7e1414e010afb52c3837fd9134e ("mac802154: move mac_params functions into mac_cmd"). The mac_params functions wasn't deleted by this commit. Signed-off-by: Alexander Aring Reported-by: Marcel Holtmann Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index ceedf3ef1ce2..0c9d00c83654 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -127,28 +127,6 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) return mac802154_wpan_update_llsec(dev); } -int mac802154_set_mac_params(struct net_device *dev, - const struct ieee802154_mac_params *params) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - mutex_lock(&sdata->local->iflist_mtx); - sdata->mac_params = *params; - mutex_unlock(&sdata->local->iflist_mtx); - - return 0; -} - -void mac802154_get_mac_params(struct net_device *dev, - struct ieee802154_mac_params *params) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - mutex_lock(&sdata->local->iflist_mtx); - *params = sdata->mac_params; - mutex_unlock(&sdata->local->iflist_mtx); -} - static int mac802154_slave_open(struct net_device *dev) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); From 43d6bc46e2d342204693d24ce1c607305d93d8fb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 20:52:23 +0100 Subject: [PATCH 30/61] Bluetooth: Introduce HCI_QUIRK_STRICT_DUPLICATE_FILTER Some vendors decide to use a strict duplicate filter policy that only filters on Bluetooth device addresses. This means that when the RSSI changes, these devices are not reported again. During discovery it is useful to actually get the RSSI updates. Since this is specific to each controller, add a new quirk setting that allows drivers to tell the core what kind of filtering policy the controller uses. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ecfa306e1375..2e08f5a89463 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -129,6 +129,15 @@ enum { * during the hdev->setup vendor callback. */ HCI_QUIRK_INVALID_BDADDR, + + /* When this quirk is set, the duplicate filtering during + * scanning is based on Bluetooth devices addresses. To allow + * RSSI based updates, restart scanning if needed. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_STRICT_DUPLICATE_FILTER, }; /* HCI device flags */ From 27c3fbe00b4beb373f1460b745164d699de94247 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 20:52:24 +0100 Subject: [PATCH 31/61] Bluetooth: Set HCI_QUIRK_STRICT_DUPLICATE_FILTER for Broadcom devices The Bluetooth controllers from Broadcom use a strict scanning filter policy that filters based on Bluetooth device addresses and not on RSSI. So tell the core about this. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 03ce301fca92..c85426d6e33d 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2035,6 +2035,7 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_BCM_PATCHRAM) { hdev->setup = btusb_setup_bcm_patchram; hdev->set_bdaddr = btusb_set_bdaddr_bcm; + set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); } if (id->driver_info & BTUSB_INTEL) { From 40f4938aa6bfe2d792c0665c16d9dd15a5c1b119 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 2 Nov 2014 21:46:52 +0100 Subject: [PATCH 32/61] Bluetooth: Consolidate whitelist debugfs entry into device_list The debufs entry for the BR/EDR whitelist is confusing since there is a controller debugfs entry with the name white_list and both are two different things. With the BR/EDR whitelist, the actual interface in use is the device list and thus just include all values from the internal BR/EDR whitelist in the device_list debugfs entry. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index a12e018ee21c..6c162c8809cf 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -200,31 +200,6 @@ static const struct file_operations blacklist_fops = { .release = single_release, }; -static int whitelist_show(struct seq_file *f, void *p) -{ - struct hci_dev *hdev = f->private; - struct bdaddr_list *b; - - hci_dev_lock(hdev); - list_for_each_entry(b, &hdev->whitelist, list) - seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); - hci_dev_unlock(hdev); - - return 0; -} - -static int whitelist_open(struct inode *inode, struct file *file) -{ - return single_open(file, whitelist_show, inode->i_private); -} - -static const struct file_operations whitelist_fops = { - .open = whitelist_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static int uuids_show(struct seq_file *f, void *p) { struct hci_dev *hdev = f->private; @@ -1030,10 +1005,13 @@ static int device_list_show(struct seq_file *f, void *ptr) { struct hci_dev *hdev = f->private; struct hci_conn_params *p; + struct bdaddr_list *b; hci_dev_lock(hdev); + list_for_each_entry(b, &hdev->whitelist, list) + seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); list_for_each_entry(p, &hdev->le_conn_params, list) { - seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type, + seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type, p->auto_connect); } hci_dev_unlock(hdev); @@ -1815,10 +1793,10 @@ static int __hci_init(struct hci_dev *hdev) &hdev->manufacturer); debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver); debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); + debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, + &device_list_fops); debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, &blacklist_fops); - debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev, - &whitelist_fops); debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, @@ -1897,8 +1875,6 @@ static int __hci_init(struct hci_dev *hdev) hdev, &adv_min_interval_fops); debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, hdev, &adv_max_interval_fops); - debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, - &device_list_fops); debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs, &hdev->discov_interleaved_timeout); From 2cbd3f5ccd43ba823e183f98a798d4b23cfb12b8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 3 Nov 2014 05:16:07 +0100 Subject: [PATCH 33/61] Bluetooth: btusb: Add internal callback for USB bulk rx data Some vendors require special handling of the rx data from the USB bulk endpoints. For that case provide an internal callback that can overwrite it with a custom receive function. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/btusb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index c85426d6e33d..cd634f3b76d3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -299,6 +299,8 @@ struct btusb_data { unsigned int sco_num; int isoc_altsetting; int suspend_count; + + int (*recv_bulk)(struct btusb_data *data, void *buffer, int count); }; static inline void btusb_free_frags(struct btusb_data *data) @@ -590,7 +592,7 @@ static void btusb_bulk_complete(struct urb *urb) if (urb->status == 0) { hdev->stat.byte_rx += urb->actual_length; - if (btusb_recv_bulk(data, urb->transfer_buffer, + if (data->recv_bulk(data, urb->transfer_buffer, urb->actual_length) < 0) { BT_ERR("%s corrupted ACL packet", hdev->name); hdev->stat.err_rx++; @@ -2012,6 +2014,8 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->isoc_anchor); spin_lock_init(&data->rxlock); + data->recv_bulk = btusb_recv_bulk; + hdev = hci_alloc_dev(); if (!hdev) return -ENOMEM; From 845472e8d50c898c73b4f69f4edad5249b13d6a9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 3 Nov 2014 05:16:08 +0100 Subject: [PATCH 34/61] Bluetooth: Add hci_conn_lookup_type() helper function Some drivers require knowledge of what connection handle is assigned to what connection link type (ACL or SCO/eSCO). Instead of having each driver implement connection tracking, provide a simple helper function for lookup of the link type. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 1 + include/net/bluetooth/hci_core.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 2e08f5a89463..d5f85d7746bc 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -274,6 +274,7 @@ enum { /* Low Energy links do not have defined link type. Use invented one */ #define LE_LINK 0x80 #define AMP_LINK 0x81 +#define INVALID_LINK 0xff /* LMP features */ #define LMP_3SLOT 0x01 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 27ddb905b351..4e39a5adfcab 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -646,6 +646,26 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev) return c->acl_num + c->amp_num + c->sco_num + c->le_num; } +static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle) +{ + struct hci_conn_hash *h = &hdev->conn_hash; + struct hci_conn *c; + __u8 type = INVALID_LINK; + + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { + if (c->handle == handle) { + type = c->type; + break; + } + } + + rcu_read_unlock(); + + return type; +} + static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { From a736abc1ac09b824387fb75b2aa7887c6e3ed68a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 3 Nov 2014 14:20:56 +0100 Subject: [PATCH 35/61] Bluetooth: Fix invalid response for 'Start Discovery' command According to Management Interface API 'Start Discovery' command should generate a Command Complete event on failure. Currently kernel is sending Command Status on early errors. This results in userspace ignoring such event due to invalid size. bluetoothd[28499]: src/adapter.c:trigger_start_discovery() bluetoothd[28499]: src/adapter.c:cancel_passive_scanning() bluetoothd[28499]: src/adapter.c:start_discovery_timeout() bluetoothd[28499]: src/adapter.c:start_discovery_complete() status 0x0a bluetoothd[28499]: Wrong size of start discovery return parameters Reported-by: Jukka Taimisto Signed-off-by: Szymon Janc Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 56 +++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9c4daf715cf8..ce0272c6f71f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, hci_dev_lock(hdev); if (!hdev_is_powered(hdev)) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_NOT_POWERED); + err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_NOT_POWERED, + &cp->type, sizeof(cp->type)); goto failed; } if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_BUSY); + err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_BUSY, &cp->type, + sizeof(cp->type)); goto failed; } if (hdev->discovery.state != DISCOVERY_STOPPED) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_BUSY); + err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_BUSY, &cp->type, + sizeof(cp->type)); goto failed; } @@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, case DISCOV_TYPE_BREDR: status = mgmt_bredr_support(hdev); if (status) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - status); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, status, + &cp->type, sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } if (test_bit(HCI_INQUIRY, &hdev->flags)) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_BUSY); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, + MGMT_STATUS_BUSY, &cp->type, + sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } @@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, case DISCOV_TYPE_INTERLEAVED: status = mgmt_le_support(hdev); if (status) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - status); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, status, + &cp->type, sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_NOT_SUPPORTED); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, + MGMT_STATUS_NOT_SUPPORTED, + &cp->type, sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } @@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, */ if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) { - err = cmd_status(sk, hdev->id, - MGMT_OP_START_DISCOVERY, - MGMT_STATUS_REJECTED); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, + MGMT_STATUS_REJECTED, + &cp->type, + sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } @@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, */ err = hci_update_random_address(&req, true, &own_addr_type); if (err < 0) { - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_FAILED); + err = cmd_complete(sk, hdev->id, + MGMT_OP_START_DISCOVERY, + MGMT_STATUS_FAILED, + &cp->type, sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } @@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, break; default: - err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_INVALID_PARAMS); + err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY, + MGMT_STATUS_INVALID_PARAMS, + &cp->type, sizeof(cp->type)); mgmt_pending_remove(cmd); goto failed; } From 98a18b6ffc79baa69f4a0d1bae58faf2a8aef4c8 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 2 Nov 2014 06:44:54 +0100 Subject: [PATCH 36/61] netdevice: add ieee802154_ptr to net_device This patch adds an ieee802154_ptr to the net_device structure. Furthermore the 802.15.4 subsystem will introduce a nl802154 framework which is similar like the nl80211 framework and a wpan_dev structure. The wpan_dev structure will hold additional net_device attributes like address options which are 802.15.4 specific. In the upcoming nl802154 implementation we will introduce a NL802154_FLAG_NEED_WPAN_DEV like NL80211_FLAG_NEED_WDEV. For this flag an ieee802154_ptr in net_device is needed. Additional we can access the wpan_dev attributes in upper layers like IEEE 802.15.4 6LoWPAN easily. Current solution is a complicated callback interface and getting these values over subif data structure in mac802154. Signed-off-by: Alexander Aring Acked-by: David S. Miller Signed-off-by: Marcel Holtmann --- include/linux/netdevice.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 74fd5d37f15a..c9bcf33efb47 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -57,6 +57,8 @@ struct device; struct phy_device; /* 802.11 specific */ struct wireless_dev; +/* 802.15.4 specific */ +struct wpan_dev; void netdev_set_default_ethtool_ops(struct net_device *dev, const struct ethtool_ops *ops); @@ -1572,6 +1574,7 @@ struct net_device { struct inet6_dev __rcu *ip6_ptr; void *ax25_ptr; struct wireless_dev *ieee80211_ptr; + struct wpan_dev *ieee802154_ptr; /* * Cache lines mostly used on receive path (including eth_type_trans()) From 2a68c897246b70a0c6b51a4a7d48d19b56b3e76b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 4 Nov 2014 08:45:45 +0200 Subject: [PATCH 37/61] Bluetooth: Fix sparse warnings in RFCOMM This patch fixes the following sparse warnings in rfcomm/core.c: net/bluetooth/rfcomm/core.c:391:16: warning: dubious: x | !y net/bluetooth/rfcomm/core.c:546:24: warning: dubious: x | !y Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/rfcomm/core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index bce9c3d39324..64e20dde4837 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -81,6 +81,8 @@ static struct rfcomm_session *rfcomm_session_del(struct rfcomm_session *s); #define __test_cr(b) (!!(b & 0x02)) #define __test_pf(b) (!!(b & 0x10)) +#define __session_dir(s) ((s)->initiator ? 0x00 : 0x01) + #define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01) #define __ctrl(type, pf) (((type & 0xef) | (pf << 4))) #define __dlci(dir, chn) (((chn & 0x1f) << 1) | dir) @@ -388,7 +390,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, return err; } - dlci = __dlci(!s->initiator, channel); + dlci = __dlci(__session_dir(s), channel); /* Check if DLCI already exists */ if (rfcomm_dlc_get(s, dlci)) @@ -543,7 +545,7 @@ struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel) rfcomm_lock(); s = rfcomm_session_get(src, dst); if (s) { - dlci = __dlci(!s->initiator, channel); + dlci = __dlci(__session_dir(s), channel); dlc = rfcomm_dlc_get(s, dlci); } rfcomm_unlock(); From 980edbd503dc0823c75e138edc53a48f99e1e3f6 Mon Sep 17 00:00:00 2001 From: Simon Vincent Date: Tue, 4 Nov 2014 15:29:51 +0000 Subject: [PATCH 38/61] 6lowpan: fix udp header compression when using raw sockets If you use RAW sockets the transport header offset is not set by the ipv6 stack so when we get to the udp header compression it does not compress the right part of the packet. This patch adds a check for this scenario and sets the transport header offset. Signed-off-by: Simon Vincent Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/6lowpan/iphc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index 73a7065f0c6b..cd5f8b8e34cd 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -512,9 +512,17 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) { - struct udphdr *uh = udp_hdr(skb); + struct udphdr *uh; u8 tmp; + /* In the case of RAW sockets the transport header is not set by + * the ip6 stack so we must set it ourselves + */ + if (skb->transport_header == skb->network_header) + skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + + uh = udp_hdr(skb); + if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) == LOWPAN_NHC_UDP_4BIT_PORT) && ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) == From 0d8a52f933f817d0b62955a5a362fb7f2508f06c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Nov 2014 11:55:09 +0300 Subject: [PATCH 39/61] ieee802154: || vs && in ieee802154_is_valid_extended_addr() The ieee802154_is_valid_extended_addr() always returns true because there is a typo. The || should be &&. Neither 0x0000000000000000ULL nor 0xffffffffffffffffULL are valid addresses. Signed-off-by: Dan Carpenter Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 5d9e7459d94b..4c032863cd71 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -209,7 +209,7 @@ static inline bool ieee802154_is_valid_extended_addr(const __le64 addr) * This is currently a workaround because neighbor discovery can't * deal with short addresses types right now. */ - return ((addr != cpu_to_le64(0x0000000000000000ULL)) || + return ((addr != cpu_to_le64(0x0000000000000000ULL)) && (addr != cpu_to_le64(0xffffffffffffffffULL))); } From 53f9ee61b46d81a43d8c6694d136896e8f49a7b8 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:12 +0100 Subject: [PATCH 40/61] ieee802154: rework wpan_phy index assignment This patch reworks the wpan_phy index incrementation. It's now similar like wireless wiphy index incrementation. We move the wpan_phy index attribute inside of cfg802154_registered_device and use atomic operations instead locking mechanism via wpan_phy_mutex. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 1 - net/ieee802154/core.c | 30 +++++++++++------------------- net/ieee802154/core.h | 3 +++ 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 864bce2b0728..29c6de5a426c 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -61,7 +61,6 @@ struct wpan_phy { s32 cca_ed_level; struct device dev; - int idx; char priv[0] __aligned(NETDEV_ALIGN); }; diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index ed5b014dbec7..d1cd0edfb149 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c @@ -23,9 +23,6 @@ #include "sysfs.h" #include "core.h" -static DEFINE_MUTEX(wpan_phy_mutex); -static int wpan_phy_idx; - static int wpan_phy_match(struct device *dev, const void *data) { return !strcmp(dev_name(dev), (const char *)data); @@ -72,14 +69,10 @@ int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), } EXPORT_SYMBOL(wpan_phy_for_each); -static int wpan_phy_idx_valid(int idx) -{ - return idx >= 0; -} - struct wpan_phy * wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size) { + static atomic_t wpan_phy_counter = ATOMIC_INIT(0); struct cfg802154_registered_device *rdev; size_t alloc_size; @@ -90,28 +83,27 @@ wpan_phy_alloc(const struct cfg802154_ops *ops, size_t priv_size) rdev->ops = ops; - mutex_lock(&wpan_phy_mutex); - rdev->wpan_phy.idx = wpan_phy_idx++; - if (unlikely(!wpan_phy_idx_valid(rdev->wpan_phy.idx))) { - wpan_phy_idx--; - mutex_unlock(&wpan_phy_mutex); + rdev->wpan_phy_idx = atomic_inc_return(&wpan_phy_counter); + + if (unlikely(rdev->wpan_phy_idx < 0)) { + /* ugh, wrapped! */ + atomic_dec(&wpan_phy_counter); kfree(rdev); - goto out; + return NULL; } - mutex_unlock(&wpan_phy_mutex); + + /* atomic_inc_return makes it start at 1, make it start at 0 */ + rdev->wpan_phy_idx--; mutex_init(&rdev->wpan_phy.pib_lock); device_initialize(&rdev->wpan_phy.dev); - dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy.idx); + dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx); rdev->wpan_phy.dev.class = &wpan_phy_class; rdev->wpan_phy.dev.platform_data = rdev; return &rdev->wpan_phy; - -out: - return NULL; } EXPORT_SYMBOL(wpan_phy_alloc); diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h index 1bc172587157..fea60b3a8846 100644 --- a/net/ieee802154/core.h +++ b/net/ieee802154/core.h @@ -6,6 +6,9 @@ struct cfg802154_registered_device { const struct cfg802154_ops *ops; + /* wpan_phy index, internal only */ + int wpan_phy_idx; + /* must be last because of the way we do wpan_phy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ From 9f3295b9ea8e54a6c65231d267f069edf420b64f Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:13 +0100 Subject: [PATCH 41/61] ieee802154: remove nl802154 unused functions The include/net/nl802154.h file contains a lot of prototypes which are not used inside of ieee802154 subsystem. This patch removes this file and make the only one used prototype "ieee802154_nl_start_confirm" as static declaration in ieee802154/nl-mac.c Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- MAINTAINERS | 1 - include/net/nl802154.h | 122 -------------------------- net/ieee802154/nl-mac.c | 187 ++-------------------------------------- net/mac802154/mac_cmd.c | 6 -- 4 files changed, 6 insertions(+), 310 deletions(-) delete mode 100644 include/net/nl802154.h diff --git a/MAINTAINERS b/MAINTAINERS index 7ec37a396ffe..b42eb50b7426 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4699,7 +4699,6 @@ F: net/mac802154/ F: drivers/net/ieee802154/ F: include/linux/nl802154.h F: include/linux/ieee802154.h -F: include/net/nl802154.h F: include/net/mac802154.h F: include/net/af_ieee802154.h F: include/net/cfg802154.h diff --git a/include/net/nl802154.h b/include/net/nl802154.h deleted file mode 100644 index b5cdea29d9d9..000000000000 --- a/include/net/nl802154.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * nl802154.h - * - * Copyright (C) 2007, 2008, 2009 Siemens AG - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef IEEE802154_NL_H -#define IEEE802154_NL_H - -struct net_device; -struct ieee802154_addr; - -/** - * ieee802154_nl_assoc_indic - Notify userland of an association request. - * @dev: The network device on which this association request was - * received. - * @addr: The address of the device requesting association. - * @cap: The capability information field from the device. - * - * This informs a userland coordinator of a device requesting to - * associate with the PAN controlled by the coordinator. - * - * Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document. - */ -int ieee802154_nl_assoc_indic(struct net_device *dev, - struct ieee802154_addr *addr, u8 cap); - -/** - * ieee802154_nl_assoc_confirm - Notify userland of association. - * @dev: The device which has completed association. - * @short_addr: The short address assigned to the device. - * @status: The status of the association. - * - * Inform userland of the result of an association request. If the - * association request included asking the coordinator to allocate - * a short address then it is returned in @short_addr. - * - * Note: This is in section 7.3.2 of the IEEE 802.15.4 document. - */ -int ieee802154_nl_assoc_confirm(struct net_device *dev, - __le16 short_addr, u8 status); - -/** - * ieee802154_nl_disassoc_indic - Notify userland of disassociation. - * @dev: The device on which disassociation was indicated. - * @addr: The device which is disassociating. - * @reason: The reason for the disassociation. - * - * Inform userland that a device has disassociated from the network. - * - * Note: This is in section 7.3.3 of the IEEE 802.15.4 document. - */ -int ieee802154_nl_disassoc_indic(struct net_device *dev, - struct ieee802154_addr *addr, u8 reason); - -/** - * ieee802154_nl_disassoc_confirm - Notify userland of disassociation - * completion. - * @dev: The device on which disassociation was ordered. - * @status: The result of the disassociation. - * - * Inform userland of the result of requesting that a device - * disassociate, or the result of requesting that we disassociate from - * a PAN managed by another coordinator. - * - * Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document. - */ -int ieee802154_nl_disassoc_confirm(struct net_device *dev, - u8 status); - -/** - * ieee802154_nl_scan_confirm - Notify userland of completion of scan. - * @dev: The device which was instructed to scan. - * @status: The status of the scan operation. - * @scan_type: What type of scan was performed. - * @unscanned: Any channels that the device was unable to scan. - * @edl: The energy levels (if a passive scan). - * - * - * Note: This is in section 7.1.11 of the IEEE 802.15.4 document. - * Note: This API does not permit the return of an active scan result. - */ -int ieee802154_nl_scan_confirm(struct net_device *dev, - u8 status, u8 scan_type, u32 unscanned, u8 page, - u8 *edl/*, struct list_head *pan_desc_list */); - -/** - * ieee802154_nl_beacon_indic - Notify userland of a received beacon. - * @dev: The device on which a beacon was received. - * @panid: The PAN of the coordinator. - * @coord_addr: The short address of the coordinator on that PAN. - * - * Note: This is in section 7.1.5 of the IEEE 802.15.4 document. - * Note: This API does not provide extended information such as what - * channel the PAN is on or what the LQI of the beacon frame was on - * receipt. - * Note: This API cannot indicate a beacon frame for a coordinator - * operating in long addressing mode. - */ -int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, - __le16 coord_addr); - -/** - * ieee802154_nl_start_confirm - Notify userland of completion of start. - * @dev: The device which was instructed to scan. - * @status: The status of the scan operation. - * - * Note: This is in section 7.1.14 of the IEEE 802.15.4 document. - */ -int ieee802154_nl_start_confirm(struct net_device *dev, u8 status); - -#endif diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index cc2919dbe5e0..91a1855e521c 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -55,186 +54,7 @@ static __le16 nla_get_shortaddr(const struct nlattr *nla) return cpu_to_le16(nla_get_u16(nla)); } -int ieee802154_nl_assoc_indic(struct net_device *dev, - struct ieee802154_addr *addr, - u8 cap) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - if (addr->mode != IEEE802154_ADDR_LONG) { - pr_err("%s: received non-long source address!\n", __func__); - return -EINVAL; - } - - msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr) || - nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, - addr->extended_addr) || - nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) - goto nla_put_failure; - - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_assoc_indic); - -int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, - u8 status) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr) || - nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || - nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) - goto nla_put_failure; - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); - -int ieee802154_nl_disassoc_indic(struct net_device *dev, - struct ieee802154_addr *addr, - u8 reason) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr)) - goto nla_put_failure; - if (addr->mode == IEEE802154_ADDR_LONG) { - if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, - addr->extended_addr)) - goto nla_put_failure; - } else { - if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, - addr->short_addr)) - goto nla_put_failure; - } - if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) - goto nla_put_failure; - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_disassoc_indic); - -int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr) || - nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) - goto nla_put_failure; - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); - -int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, - __le16 coord_addr) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr) || - nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, - coord_addr) || - nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) - goto nla_put_failure; - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_beacon_indic); - -int ieee802154_nl_scan_confirm(struct net_device *dev, - u8 status, u8 scan_type, - u32 unscanned, u8 page, - u8 *edl/* , struct list_head *pan_desc_list */) -{ - struct sk_buff *msg; - - pr_debug("%s\n", __func__); - - msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF); - if (!msg) - return -ENOBUFS; - - if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || - nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || - nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, - dev->dev_addr) || - nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) || - nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) || - nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) || - nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) || - (edl && - nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl))) - goto nla_put_failure; - return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); - -nla_put_failure: - nlmsg_free(msg); - return -ENOBUFS; -} -EXPORT_SYMBOL(ieee802154_nl_scan_confirm); - -int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) +static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) { struct sk_buff *msg; @@ -530,6 +350,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, bcn_ord, sf_ord, pan_coord, blx, coord_realign); + /* FIXME: add validation for unused parameters to be sane + * for SoftMAC + */ + ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS); + out: dev_put(dev); return ret; diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index 9c2d6f61f194..e1ad83e35899 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "ieee802154_i.h" #include "driver-ops.h" @@ -65,11 +64,6 @@ static int mac802154_mlme_start_req(struct net_device *dev, rc = ops->llsec->set_params(dev, ¶ms, changed); } - /* FIXME: add validation for unused parameters to be sane - * for SoftMAC - */ - ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS); - return rc; } From b210b18747cb511bb71f6a49c97e8d38f639b435 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:14 +0100 Subject: [PATCH 42/61] mac802154: move interface del handling in iface This patch moves and rename the mac802154_del_iface function into iface.c and rename the function to ieee802154_if_remove which is a similar naming convention like mac80211. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/cfg.c | 4 +++- net/mac802154/ieee802154_i.h | 2 +- net/mac802154/iface.c | 12 ++++++++++++ net/mac802154/main.c | 16 ---------------- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 0c69b44ba312..3f9afad1f612 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -28,7 +28,9 @@ ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, struct net_device *dev) { - mac802154_del_iface(wpan_phy, dev); + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + + ieee802154_if_remove(sdata); } const struct cfg802154_ops mac802154_config_ops = { diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 27e17e6bcf18..61a6a0fd39ad 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -175,6 +175,6 @@ void mac802154_unlock_table(struct net_device *dev); struct net_device * mac802154_add_iface(struct wpan_phy *phy, const char *name, int type); -void mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev); +void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); #endif /* __IEEE802154_I_H */ diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 0c9d00c83654..9d6012e430de 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -443,3 +443,15 @@ void mac802154_monitor_setup(struct net_device *dev) sdata->promisuous_mode = true; } + +void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) +{ + ASSERT_RTNL(); + + mutex_lock(&sdata->local->iflist_mtx); + list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); + + synchronize_rcu(); + unregister_netdevice(sdata->dev); +} diff --git a/net/mac802154/main.c b/net/mac802154/main.c index b34ddbf43c3d..333d33daec6e 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -59,22 +59,6 @@ mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) return 0; } -void mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - ASSERT_RTNL(); - - BUG_ON(sdata->local->phy != phy); - - mutex_lock(&sdata->local->iflist_mtx); - list_del_rcu(&sdata->list); - mutex_unlock(&sdata->local->iflist_mtx); - - synchronize_rcu(); - unregister_netdevice(sdata->dev); -} - struct net_device * mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) { From 986a8abfc51e66c96f9d39529a6ff0443fcd2591 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:15 +0100 Subject: [PATCH 43/61] mac802154: move interface add handling in iface This patch moves and renames the mac802154_add_iface and mac802154_netdev_register functions into iface.c. The function mac802154_add_iface is renamed to ieee802154_if_add which is a similar naming convention like mac80211. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/cfg.c | 4 ++- net/mac802154/ieee802154_i.h | 3 ++ net/mac802154/iface.c | 66 +++++++++++++++++++++++++++++++++++ net/mac802154/main.c | 67 ------------------------------------ 4 files changed, 72 insertions(+), 68 deletions(-) diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 3f9afad1f612..0a08f66512b3 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -22,7 +22,9 @@ static struct net_device * ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, const char *name, int type) { - return mac802154_add_iface(wpan_phy, name, type); + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + + return ieee802154_if_add(local, name, NULL, type); } static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 61a6a0fd39ad..3ad85404fc94 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -176,5 +176,8 @@ void mac802154_unlock_table(struct net_device *dev); struct net_device * mac802154_add_iface(struct wpan_phy *phy, const char *name, int type); void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); +struct net_device * +ieee802154_if_add(struct ieee802154_local *local, const char *name, + struct wpan_dev **new_wpan_dev, int type); #endif /* __IEEE802154_I_H */ diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 9d6012e430de..fced04b05275 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -444,6 +444,72 @@ void mac802154_monitor_setup(struct net_device *dev) sdata->promisuous_mode = true; } +static int +mac802154_netdev_register(struct ieee802154_local *local, + struct net_device *dev) +{ + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + int err; + + sdata->dev = dev; + sdata->local = local; + + dev->needed_headroom = local->hw.extra_tx_headroom; + + SET_NETDEV_DEV(dev, &local->phy->dev); + + err = register_netdev(dev); + if (err < 0) + return err; + + rtnl_lock(); + mutex_lock(&local->iflist_mtx); + list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); + rtnl_unlock(); + + return 0; +} + +struct net_device * +ieee802154_if_add(struct ieee802154_local *local, const char *name, + struct wpan_dev **new_wpan_dev, int type) +{ + struct net_device *dev; + int err = -ENOMEM; + + switch (type) { + case IEEE802154_DEV_MONITOR: + dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), + name, NET_NAME_UNKNOWN, + mac802154_monitor_setup); + break; + case IEEE802154_DEV_WPAN: + dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), + name, NET_NAME_UNKNOWN, + mac802154_wpan_setup); + break; + default: + dev = NULL; + err = -EINVAL; + break; + } + if (!dev) + goto err; + + err = mac802154_netdev_register(local, dev); + if (err) + goto err_free; + + dev_hold(dev); /* we return an incremented device refcount */ + return dev; + +err_free: + free_netdev(dev); +err: + return ERR_PTR(err); +} + void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) { ASSERT_RTNL(); diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 333d33daec6e..a371eb5fa053 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -30,73 +30,6 @@ #include "ieee802154_i.h" #include "cfg.h" -static int -mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - struct ieee802154_local *local; - int err; - - local = wpan_phy_priv(phy); - - sdata->dev = dev; - sdata->local = local; - - dev->needed_headroom = local->hw.extra_tx_headroom; - - SET_NETDEV_DEV(dev, &local->phy->dev); - - err = register_netdev(dev); - if (err < 0) - return err; - - rtnl_lock(); - mutex_lock(&local->iflist_mtx); - list_add_tail_rcu(&sdata->list, &local->interfaces); - mutex_unlock(&local->iflist_mtx); - rtnl_unlock(); - - return 0; -} - -struct net_device * -mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) -{ - struct net_device *dev; - int err = -ENOMEM; - - switch (type) { - case IEEE802154_DEV_MONITOR: - dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), - name, NET_NAME_UNKNOWN, - mac802154_monitor_setup); - break; - case IEEE802154_DEV_WPAN: - dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), - name, NET_NAME_UNKNOWN, - mac802154_wpan_setup); - break; - default: - dev = NULL; - err = -EINVAL; - break; - } - if (!dev) - goto err; - - err = mac802154_netdev_register(phy, dev); - if (err) - goto err_free; - - dev_hold(dev); /* we return an incremented device refcount */ - return dev; - -err_free: - free_netdev(dev); -err: - return ERR_PTR(err); -} - static void ieee802154_tasklet_handler(unsigned long data) { struct ieee802154_local *local = (struct ieee802154_local *)data; From 12cb56c2370b2911295026630a71af044c12d2aa Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:16 +0100 Subject: [PATCH 44/61] mac802154: move dev_hold out of ieee802154_if_add This patch moves the dev_hold call inside of nl-phy ieee802154_add_iface function. The ieee802154_add_iface is the only one function which use the ieee802154_if_add function and contains the corresponding dev_put call. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/ieee802154/nl-phy.c | 1 + net/mac802154/iface.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 5d914d30e0b1..397ca126d9a2 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -226,6 +226,7 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) rc = PTR_ERR(dev); goto nla_put_failure; } + dev_hold(dev); if (info->attrs[IEEE802154_ATTR_HW_ADDR]) { struct sockaddr addr; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index fced04b05275..78cb38124a2a 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -501,7 +501,6 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, if (err) goto err_free; - dev_hold(dev); /* we return an incremented device refcount */ return dev; err_free: From d5ae67bacd9654b0e26b9f248249e9ee1b6e338b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:17 +0100 Subject: [PATCH 45/61] ieee802154: rework interface registration This patch meld mac802154_netdev_register into ieee802154_if_add function. Also we have now only one alloc_netdev call with one interface setup routine "ieee802154_if_setup" instead two different one for each interface type. This patch checks via runtime the interface type and do different handling now. Additional we add the wpan_dev struct in ieee802154_sub_if_data and set the new ieee802154_ptr while netdev registration. This behaviour is very similar the mac80211 netdev registration functionality. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 4 + net/mac802154/cfg.c | 8 +- net/mac802154/ieee802154_i.h | 4 + net/mac802154/iface.c | 168 +++++++++++++++++------------------ 4 files changed, 97 insertions(+), 87 deletions(-) diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 29c6de5a426c..57333f1ee75c 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -65,6 +65,10 @@ struct wpan_phy { char priv[0] __aligned(NETDEV_ALIGN); }; +struct wpan_dev { + struct wpan_phy *wpan_phy; +}; + #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) struct wpan_phy * diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index 0a08f66512b3..d2c4e8f89720 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -13,6 +13,7 @@ * Based on: net/mac80211/cfg.c */ +#include #include #include "ieee802154_i.h" @@ -23,8 +24,13 @@ ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy, const char *name, int type) { struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + struct net_device *dev; - return ieee802154_if_add(local, name, NULL, type); + rtnl_lock(); + dev = ieee802154_if_add(local, name, NULL, type); + rtnl_unlock(); + + return dev; } static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 3ad85404fc94..748dc5afe367 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -20,6 +20,7 @@ #define __IEEE802154_I_H #include +#include #include #include @@ -73,11 +74,14 @@ enum ieee802154_sdata_state_bits { struct ieee802154_sub_if_data { struct list_head list; /* the ieee802154_priv->slaves list */ + struct wpan_dev wpan_dev; + struct ieee802154_local *local; struct net_device *dev; int type; unsigned long state; + char name[IFNAMSIZ]; spinlock_t mib_lock; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 78cb38124a2a..f9ed608aa260 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -381,30 +381,23 @@ static void mac802154_wpan_free(struct net_device *dev) free_netdev(dev); } -void mac802154_wpan_setup(struct net_device *dev) +static void ieee802154_if_setup(struct net_device *dev) { - struct ieee802154_sub_if_data *sdata; - dev->addr_len = IEEE802154_ADDR_LEN; memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; - dev->header_ops = &mac802154_header_ops; dev->needed_tailroom = 2 + 16; /* FCS + MIC */ dev->mtu = IEEE802154_MTU; dev->tx_queue_len = 300; - dev->type = ARPHRD_IEEE802154; dev->flags = IFF_NOARP | IFF_BROADCAST; +} - dev->destructor = mac802154_wpan_free; - dev->netdev_ops = &mac802154_wpan_ops; - dev->ml_priv = &mac802154_mlme_wpan; - - sdata = IEEE802154_DEV_TO_SUB_IF(dev); - sdata->type = IEEE802154_DEV_WPAN; - - spin_lock_init(&sdata->mib_lock); - mutex_init(&sdata->sec_mtx); +static int +ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) +{ + /* set some type-dependent values */ + sdata->type = type; get_random_bytes(&sdata->bsn, 1); get_random_bytes(&sdata->dsn, 1); @@ -419,54 +412,28 @@ void mac802154_wpan_setup(struct net_device *dev) sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); - sdata->promisuous_mode = false; + switch (type) { + case IEEE802154_DEV_WPAN: + sdata->dev->header_ops = &mac802154_header_ops; + sdata->dev->destructor = mac802154_wpan_free; + sdata->dev->netdev_ops = &mac802154_wpan_ops; + sdata->dev->ml_priv = &mac802154_mlme_wpan; + sdata->promisuous_mode = false; - mac802154_llsec_init(&sdata->sec); -} + spin_lock_init(&sdata->mib_lock); + mutex_init(&sdata->sec_mtx); -void mac802154_monitor_setup(struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata; - - dev->needed_tailroom = 2; /* room for FCS */ - dev->mtu = IEEE802154_MTU; - dev->tx_queue_len = 10; - dev->type = ARPHRD_IEEE802154_MONITOR; - dev->flags = IFF_NOARP | IFF_BROADCAST; - - dev->destructor = free_netdev; - dev->netdev_ops = &mac802154_monitor_ops; - dev->ml_priv = &mac802154_mlme_reduced; - - sdata = IEEE802154_DEV_TO_SUB_IF(dev); - sdata->type = IEEE802154_DEV_MONITOR; - - sdata->promisuous_mode = true; -} - -static int -mac802154_netdev_register(struct ieee802154_local *local, - struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - int err; - - sdata->dev = dev; - sdata->local = local; - - dev->needed_headroom = local->hw.extra_tx_headroom; - - SET_NETDEV_DEV(dev, &local->phy->dev); - - err = register_netdev(dev); - if (err < 0) - return err; - - rtnl_lock(); - mutex_lock(&local->iflist_mtx); - list_add_tail_rcu(&sdata->list, &local->interfaces); - mutex_unlock(&local->iflist_mtx); - rtnl_unlock(); + mac802154_llsec_init(&sdata->sec); + break; + case IEEE802154_DEV_MONITOR: + sdata->dev->destructor = free_netdev; + sdata->dev->netdev_ops = &mac802154_monitor_ops; + sdata->dev->ml_priv = &mac802154_mlme_reduced; + sdata->promisuous_mode = true; + break; + default: + BUG(); + } return 0; } @@ -475,38 +442,67 @@ struct net_device * ieee802154_if_add(struct ieee802154_local *local, const char *name, struct wpan_dev **new_wpan_dev, int type) { - struct net_device *dev; - int err = -ENOMEM; + struct net_device *ndev = NULL; + struct ieee802154_sub_if_data *sdata = NULL; + int ret = -ENOMEM; - switch (type) { - case IEEE802154_DEV_MONITOR: - dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), - name, NET_NAME_UNKNOWN, - mac802154_monitor_setup); - break; - case IEEE802154_DEV_WPAN: - dev = alloc_netdev(sizeof(struct ieee802154_sub_if_data), - name, NET_NAME_UNKNOWN, - mac802154_wpan_setup); - break; - default: - dev = NULL; - err = -EINVAL; - break; - } - if (!dev) + ASSERT_RTNL(); + + ndev = alloc_netdev(sizeof(*sdata), name, NET_NAME_UNKNOWN, + ieee802154_if_setup); + if (!ndev) + return ERR_PTR(-ENOMEM); + + ndev->needed_headroom = local->hw.extra_tx_headroom; + + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) goto err; - err = mac802154_netdev_register(local, dev); - if (err) - goto err_free; + switch (type) { + case IEEE802154_DEV_WPAN: + ndev->type = ARPHRD_IEEE802154; + break; + case IEEE802154_DEV_MONITOR: + ndev->type = ARPHRD_IEEE802154_MONITOR; + break; + default: + ret = -EINVAL; + goto err; + } - return dev; + /* TODO check this */ + SET_NETDEV_DEV(ndev, &local->phy->dev); + sdata = netdev_priv(ndev); + ndev->ieee802154_ptr = &sdata->wpan_dev; + memcpy(sdata->name, ndev->name, IFNAMSIZ); + sdata->dev = ndev; + sdata->wpan_dev.wpan_phy = local->hw.phy; + sdata->local = local; + + /* setup type-dependent data */ + ret = ieee802154_setup_sdata(sdata, type); + if (ret) + goto err; + + if (ndev) { + ret = register_netdevice(ndev); + if (ret < 0) + goto err; + } + + mutex_lock(&local->iflist_mtx); + list_add_tail_rcu(&sdata->list, &local->interfaces); + mutex_unlock(&local->iflist_mtx); + + if (new_wpan_dev) + *new_wpan_dev = &sdata->wpan_dev; + + return ndev; -err_free: - free_netdev(dev); err: - return ERR_PTR(err); + free_netdev(ndev); + return ERR_PTR(ret); } void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) From bd28a11f25f2c2a563620e7be588dc4dd8a91396 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:18 +0100 Subject: [PATCH 46/61] ieee802154: remove mlme get_phy callback This patch removes the get_phy callback from mlme ops structure. Instead we doing a dereference via ieee802154_ptr dev pointer. For backwards compatibility we need to run get_device after dereference wpan_phy via ieee802154_ptr. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/ieee802154_netdev.h | 12 ------------ net/ieee802154/6lowpan_rtnl.c | 8 -------- net/ieee802154/nl-mac.c | 6 ++++-- net/ieee802154/nl-phy.c | 3 ++- net/mac802154/iface.c | 1 - net/mac802154/mac_cmd.c | 14 -------------- 6 files changed, 6 insertions(+), 38 deletions(-) diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index 5e62d758eea5..83bb8a73d23c 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -423,8 +423,6 @@ struct ieee802154_mlme_ops { /* The fields below are required. */ - struct wpan_phy *(*get_phy)(const struct net_device *dev); - /* * FIXME: these should become the part of PIB/MIB interface. * However we still don't have IB interface of any kind @@ -434,16 +432,6 @@ struct ieee802154_mlme_ops { u8 (*get_dsn)(const struct net_device *dev); }; -/* The IEEE 802.15.4 standard defines 2 type of the devices: - * - FFD - full functionality device - * - RFD - reduce functionality device - * - * So 2 sets of mlme operations are needed - */ -struct ieee802154_reduced_mlme_ops { - struct wpan_phy *(*get_phy)(const struct net_device *dev); -}; - static inline struct ieee802154_mlme_ops * ieee802154_mlme_ops(const struct net_device *dev) { diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index 659f7b25ea1a..a96b64c9a73d 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -407,13 +407,6 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) } } -static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) -{ - struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; - - return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); -} - static __le16 lowpan_get_pan_id(const struct net_device *dev) { struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; @@ -465,7 +458,6 @@ static const struct net_device_ops lowpan_netdev_ops = { static struct ieee802154_mlme_ops lowpan_mlme = { .get_pan_id = lowpan_get_pan_id, - .get_phy = lowpan_get_phy, .get_short_addr = lowpan_get_short_addr, .get_dsn = lowpan_get_dsn, }; diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 91a1855e521c..7127b9d1a684 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -94,8 +94,9 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, goto out; ops = ieee802154_mlme_ops(dev); - phy = ops->get_phy(dev); + phy = dev->ieee802154_ptr->wpan_phy; BUG_ON(!phy); + get_device(&phy->dev); short_addr = ops->get_short_addr(dev); pan_id = ops->get_pan_id(dev); @@ -493,7 +494,8 @@ int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) goto out; - phy = ops->get_phy(dev); + phy = dev->ieee802154_ptr->wpan_phy; + get_device(&phy->dev); ops->get_mac_params(dev, ¶ms); diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 397ca126d9a2..80a946dddd90 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -287,8 +287,9 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info) if (!dev) return -ENODEV; - phy = ieee802154_mlme_ops(dev)->get_phy(dev); + phy = dev->ieee802154_ptr->wpan_phy; BUG_ON(!phy); + get_device(&phy->dev); rc = -EINVAL; /* phy name is optional, but should be checked if it's given */ diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index f9ed608aa260..2e2638e72ae8 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -428,7 +428,6 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) case IEEE802154_DEV_MONITOR: sdata->dev->destructor = free_netdev; sdata->dev->netdev_ops = &mac802154_monitor_ops; - sdata->dev->ml_priv = &mac802154_mlme_reduced; sdata->promisuous_mode = true; break; default: diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index e1ad83e35899..00b2b214770e 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c @@ -67,15 +67,6 @@ static int mac802154_mlme_start_req(struct net_device *dev, return rc; } -static struct wpan_phy *mac802154_get_phy(const struct net_device *dev) -{ - struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); - - BUG_ON(dev->type != ARPHRD_IEEE802154); - - return to_phy(get_device(&sdata->local->phy->dev)); -} - static int mac802154_set_mac_params(struct net_device *dev, const struct ieee802154_mac_params *params) { @@ -134,12 +125,7 @@ static struct ieee802154_llsec_ops mac802154_llsec_ops = { .unlock_table = mac802154_unlock_table, }; -struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = { - .get_phy = mac802154_get_phy, -}; - struct ieee802154_mlme_ops mac802154_mlme_wpan = { - .get_phy = mac802154_get_phy, .start_req = mac802154_mlme_start_req, .get_pan_id = mac802154_dev_get_pan_id, .get_short_addr = mac802154_dev_get_short_addr, From e4962a14435e15c0c070e8aa1b010454c9292c02 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:19 +0100 Subject: [PATCH 47/61] mac802154: add default interface registration This patch adds a default interface registration for a wpan interface type. Currently the 802.15.4 subsystem need to call userspace tools to add an interface. This patch is like mac80211 handling for registration a station interface type by default. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mac802154/main.c b/net/mac802154/main.c index a371eb5fa053..7d0ff7fd2cd4 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -126,6 +126,7 @@ EXPORT_SYMBOL(ieee802154_free_hw); int ieee802154_register_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); + struct net_device *dev; int rc = -ENOSYS; local->workqueue = @@ -141,6 +142,17 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) if (rc < 0) goto out_wq; + rtnl_lock(); + + dev = ieee802154_if_add(local, "wpan%d", NULL, IEEE802154_DEV_WPAN); + if (IS_ERR(dev)) { + rtnl_unlock(); + rc = PTR_ERR(dev); + goto out_wq; + } + + rtnl_unlock(); + return 0; out_wq: From 7c118c1a866454cf2091fd84404d0915a27b0eef Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:20 +0100 Subject: [PATCH 48/61] mac802154: add ieee802154_vif struct This patch adds an ieee802154_vif similar like the ieee80211_vif which holds the interface type and maybe further more attributes like the ieee80211_vif structure. Signed-off-by: Alexander Aring Cc: Varka Bhadram Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 1 + drivers/net/ieee802154/cc2520.c | 1 + include/net/mac802154.h | 8 ++++++++ net/mac802154/ieee802154_i.h | 3 ++- net/mac802154/iface.c | 11 ++++++----- net/mac802154/rx.c | 4 ++-- 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index f68ebba91b10..bf477851415b 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1533,6 +1533,7 @@ static int at86rf230_probe(struct spi_device *spi) lp->hw = hw; lp->spi = spi; hw->parent = &spi->dev; + hw->vif_data_size = sizeof(*lp); lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); if (IS_ERR(lp->regmap)) { diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index 340671b747b1..ccbb082f3391 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -651,6 +651,7 @@ static int cc2520_register(struct cc2520_private *priv) priv->hw->priv = priv; priv->hw->parent = &priv->spi->dev; priv->hw->extra_tx_headroom = 0; + priv->hw->vif_data_size = sizeof(*priv); /* We do support only 2.4 Ghz */ priv->hw->phy->channels_supported[0] = 0x7FFF800; diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 8b0c26bc0762..10711a6409f4 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -52,6 +52,13 @@ struct ieee802154_hw_addr_filt { u8 pan_coord; }; +struct ieee802154_vif { + int type; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); +}; + struct ieee802154_hw { /* filled by the driver */ int extra_tx_headroom; @@ -62,6 +69,7 @@ struct ieee802154_hw { struct ieee802154_hw_addr_filt hw_filt; void *priv; struct wpan_phy *phy; + size_t vif_data_size; }; /* Checksum is in hardware and is omitted from a packet diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 748dc5afe367..931f8516cee6 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -79,7 +79,6 @@ struct ieee802154_sub_if_data { struct ieee802154_local *local; struct net_device *dev; - int type; unsigned long state; char name[IFNAMSIZ]; @@ -103,6 +102,8 @@ struct ieee802154_sub_if_data { struct mutex sec_mtx; struct mac802154_llsec sec; + /* must be last, dynamically sized area in this! */ + struct ieee802154_vif vif; }; #define MAC802154_CHAN_NONE 0xff /* No channel is assigned */ diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 2e2638e72ae8..764ce496fdc3 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -136,10 +136,11 @@ static int mac802154_slave_open(struct net_device *dev) ASSERT_RTNL(); - if (sdata->type == IEEE802154_DEV_WPAN) { + if (sdata->vif.type == IEEE802154_DEV_WPAN) { mutex_lock(&sdata->local->iflist_mtx); list_for_each_entry(subif, &sdata->local->interfaces, list) { - if (subif != sdata && subif->type == sdata->type && + if (subif != sdata && + subif->vif.type == sdata->vif.type && ieee802154_sdata_running(subif)) { mutex_unlock(&sdata->local->iflist_mtx); return -EBUSY; @@ -397,7 +398,7 @@ static int ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) { /* set some type-dependent values */ - sdata->type = type; + sdata->vif.type = type; get_random_bytes(&sdata->bsn, 1); get_random_bytes(&sdata->dsn, 1); @@ -447,8 +448,8 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, ASSERT_RTNL(); - ndev = alloc_netdev(sizeof(*sdata), name, NET_NAME_UNKNOWN, - ieee802154_if_setup); + ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name, + NET_NAME_UNKNOWN, ieee802154_if_setup); if (!ndev) return ERR_PTR(-ENOMEM); diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index 95961cccc253..4b54cf33e562 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c @@ -208,7 +208,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local, } list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->type != IEEE802154_DEV_WPAN || + if (sdata->vif.type != IEEE802154_DEV_WPAN || !netif_running(sdata->dev)) continue; @@ -233,7 +233,7 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb) skb->protocol = htons(ETH_P_IEEE802154); list_for_each_entry_rcu(sdata, &local->interfaces, list) { - if (sdata->type != IEEE802154_DEV_MONITOR) + if (sdata->vif.type != IEEE802154_DEV_MONITOR) continue; if (!ieee802154_sdata_running(sdata)) From 1906bbbddbe085b19be2c21cd132335260f551c3 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:21 +0100 Subject: [PATCH 49/61] ieee802154: add IEEE802154_EXTENDED_ADDR_LEN This patch adds a new define for getting the length of an extended address. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index 4c032863cd71..a907fe59b1d1 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -29,6 +29,8 @@ #define IEEE802154_MTU 127 #define IEEE802154_MIN_PSDU_LEN 5 +#define IEEE802154_EXTENDED_ADDR_LEN 8 + #define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */ #define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */ #define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */ From 35d5a374a559a1ba9c6810739cf3ad1d672c2de2 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:22 +0100 Subject: [PATCH 50/61] ieee802154: add ieee802154_random_extended_addr This patch adds a new function to generate a random IEEE 802.15.4 extended address. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/linux/ieee802154.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h index a907fe59b1d1..d043449a079d 100644 --- a/include/linux/ieee802154.h +++ b/include/linux/ieee802154.h @@ -24,6 +24,7 @@ #define LINUX_IEEE802154_H #include +#include #include #define IEEE802154_MTU 127 @@ -215,4 +216,17 @@ static inline bool ieee802154_is_valid_extended_addr(const __le64 addr) (addr != cpu_to_le64(0xffffffffffffffffULL))); } +/** + * ieee802154_random_extended_addr - generates a random extended address + * @addr: extended addr pointer to place the random address + */ +static inline void ieee802154_random_extended_addr(__le64 *addr) +{ + get_random_bytes(addr, IEEE802154_EXTENDED_ADDR_LEN); + + /* toggle some bit if we hit an invalid extended addr */ + if (!ieee802154_is_valid_extended_addr(*addr)) + ((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] ^= 0x01; +} + #endif /* LINUX_IEEE802154_H */ From 239a84a9a0bcbc7214eb93fb3ba76962de846239 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:23 +0100 Subject: [PATCH 51/61] mac802154: add ieee802154_le64_to_be64 This patch adds a new function to convert a le64 to a be64. This is useful to translate an extended address to a netdev dev_addr. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/mac802154.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 10711a6409f4..cc188cb4f94d 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -17,6 +17,7 @@ #define NET_MAC802154_H #include +#include #include /* General MAC frame format: @@ -231,6 +232,18 @@ static inline __le64 ieee802154_netdev_to_extended_addr(const void *dev_addr) return (__force __le64)swab64p(dev_addr); } +/** + * ieee802154_le64_to_be64 - copies and convert le64 to be64 + * @be64_dst: be64 destination pointer + * @le64_src: le64 source pointer + */ +static inline void ieee802154_le64_to_be64(void *be64_dst, const void *le64_src) +{ + __be64 tmp = (__force __be64)swab64p(le64_src); + + memcpy(be64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN); +} + /* Basic interface to register ieee802154 hwice */ struct ieee802154_hw * ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops); From 705cbbbe9ccca260658f971a4369c22f5704db75 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:24 +0100 Subject: [PATCH 52/61] mac802154: cleanup ieee802154_netdev_to_extended_addr This patch cleanups the ieee802154_be64_to_le64 to have a similar function like ieee802154_le64_to_be64 only with switched source and destionation types. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/mac802154.h | 11 +++++++---- net/mac802154/iface.c | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/net/mac802154.h b/include/net/mac802154.h index cc188cb4f94d..632f6566adb5 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -224,12 +224,15 @@ struct ieee802154_ops { }; /** - * ieee802154_netdev_to_extended_addr - convert big endian 64 byte void pointer to __le64 - * @dev_addr: big endian address pointer like netdevice dev_addr attribute + * ieee802154_be64_to_le64 - copies and convert be64 to le64 + * @le64_dst: le64 destination pointer + * @be64_src: be64 source pointer */ -static inline __le64 ieee802154_netdev_to_extended_addr(const void *dev_addr) +static inline void ieee802154_be64_to_le64(void *le64_dst, const void *be64_src) { - return (__force __le64)swab64p(dev_addr); + __le64 tmp = (__force __le64)swab64p(be64_src); + + memcpy(le64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN); } /** diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 764ce496fdc3..a1aa09b03d12 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -117,7 +117,7 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) if (netif_running(dev)) return -EBUSY; - extended_addr = ieee802154_netdev_to_extended_addr(addr->sa_data); + ieee802154_be64_to_le64(&extended_addr, addr->sa_data); if (!ieee802154_is_valid_extended_addr(extended_addr)) return -EINVAL; From dee56d14779b1e01706adafb9e020303318e22e3 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:25 +0100 Subject: [PATCH 53/61] mac802154: add support for perm_extended_addr This patch adding support for a perm extended address. This is useful when a device supports an eeprom with a programmed static extended address. If a device doesn't support such eeprom or serial registers then the driver should generate a random extended address. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- include/net/cfg802154.h | 2 ++ net/mac802154/iface.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 57333f1ee75c..9d99b9655760 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -57,6 +57,8 @@ struct wpan_phy { u8 csma_retries; s8 frame_retries; + __le64 perm_extended_addr; + bool lbt; s32 cca_ed_level; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index a1aa09b03d12..97e5bed9f917 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -410,6 +410,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) /* for compatibility, actual default is 3 */ sdata->mac_params.frame_retries = -1; + ieee802154_be64_to_le64(&sdata->extended_addr, sdata->dev->dev_addr); sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); @@ -471,6 +472,9 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name, goto err; } + ieee802154_le64_to_be64(ndev->perm_addr, + &local->hw.phy->perm_extended_addr); + memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN); /* TODO check this */ SET_NETDEV_DEV(ndev, &local->phy->dev); sdata = netdev_priv(ndev); From f6f4e86a1a3be1c4ecbafe7828764736daf4cf63 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:26 +0100 Subject: [PATCH 54/61] at86rf230: generate random perm extended address This patch adds support for a random generated perm extended address for the at86rf230 driver. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index bf477851415b..a6db76806715 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1534,6 +1534,7 @@ static int at86rf230_probe(struct spi_device *spi) lp->spi = spi; hw->parent = &spi->dev; hw->vif_data_size = sizeof(*lp); + ieee802154_random_extended_addr(&hw->phy->perm_extended_addr); lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); if (IS_ERR(lp->regmap)) { From 05e3f2f351d3c6f19a81ff7eb0a661ffcd4b19b7 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:27 +0100 Subject: [PATCH 55/61] at86rf230: add force slotted operation bit This patch adds a force setting of slotted operation bit. The atben chips sometimes set these bit. The reason is unknown. Nevertheless we don't support slotted operation so we set this bit now force while probing. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index a6db76806715..a3cc7d9f28ab 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1358,6 +1358,14 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) return -EINVAL; } + /* Force setting slotted operation bit to 0. Sometimes the atben + * sets this bit and I don't know why. We set this always force + * to zero while probing. + */ + rc = at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0); + if (rc) + return rc; + return 0; } From e57a8946847148560114a8deb8e9fad0112530b2 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:28 +0100 Subject: [PATCH 56/61] mac802154: use IEEE802154_EXTENDED_ADDR_LEN This patch removes the af_ieee802154 defines and use the IEEE802154_EXTENDED_ADDR_LEN. We should do this everywhere in the 802.15.4 subsystem because af_ieee802154 should be normally an uapi header. Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/iface.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 97e5bed9f917..51abe05a6aab 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -384,8 +383,8 @@ static void mac802154_wpan_free(struct net_device *dev) static void ieee802154_if_setup(struct net_device *dev) { - dev->addr_len = IEEE802154_ADDR_LEN; - memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN); + dev->addr_len = IEEE802154_EXTENDED_ADDR_LEN; + memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN); dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; dev->needed_tailroom = 2 + 16; /* FCS + MIC */ From 0916c02205ed76c03863b401e60fa105c4008cfa Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Wed, 5 Nov 2014 20:51:29 +0100 Subject: [PATCH 57/61] mac802154: fix typo promisuous to promiscuous Signed-off-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/mac802154/ieee802154_i.h | 2 +- net/mac802154/iface.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 931f8516cee6..4acacea0d371 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -87,7 +87,7 @@ struct ieee802154_sub_if_data { __le16 pan_id; __le16 short_addr; __le64 extended_addr; - bool promisuous_mode; + bool promiscuous_mode; struct ieee802154_mac_params mac_params; diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index 51abe05a6aab..384f4bb3c99b 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -181,7 +181,7 @@ static int mac802154_wpan_open(struct net_device *dev) mutex_lock(&phy->pib_lock); if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) { - rc = drv_set_promiscuous_mode(local, sdata->promisuous_mode); + rc = drv_set_promiscuous_mode(local, sdata->promiscuous_mode); if (rc < 0) goto out; } @@ -419,7 +419,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) sdata->dev->destructor = mac802154_wpan_free; sdata->dev->netdev_ops = &mac802154_wpan_ops; sdata->dev->ml_priv = &mac802154_mlme_wpan; - sdata->promisuous_mode = false; + sdata->promiscuous_mode = false; spin_lock_init(&sdata->mib_lock); mutex_init(&sdata->sec_mtx); @@ -429,7 +429,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type) case IEEE802154_DEV_MONITOR: sdata->dev->destructor = free_netdev; sdata->dev->netdev_ops = &mac802154_monitor_ops; - sdata->promisuous_mode = true; + sdata->promiscuous_mode = true; break; default: BUG(); From 6cc6399c719d3a6ad6d6aa54a7f26f90b4bb171d Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Thu, 6 Nov 2014 15:31:57 +0800 Subject: [PATCH 58/61] at86rf230: fix simple_return.cocci warnings drivers/net/ieee802154/at86rf230.c:1365:1-3: WARNING: end returns can be simpified Simplify a trivial if-return sequence. Possibly combine with a preceding function call. Generated by: scripts/coccinelle/misc/simple_return.cocci Signed-off-by: Fengguang Wu Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- drivers/net/ieee802154/at86rf230.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index a3cc7d9f28ab..ebcbeb3a06e8 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1362,11 +1362,7 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) * sets this bit and I don't know why. We set this always force * to zero while probing. */ - rc = at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0); - if (rc) - return rc; - - return 0; + return at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0); } static struct at86rf230_platform_data * From 50fc85f1b04908301c463e5b963f16d18a90d5cc Mon Sep 17 00:00:00 2001 From: Kuba Pawlak Date: Thu, 6 Nov 2014 19:36:52 +0100 Subject: [PATCH 59/61] Bluetooth: Clear role switch pending flag If role switch was rejected by the controller and HCI Event: Command Status returned with status "Command Disallowed" (0x0C) the flag HCI_CONN_RSWITCH_PEND remains set. No further role switches are possible as this flag prevents us from sending any new HCI Switch Role requests and the only way to clear it is to receive a valid HCI Event Switch Role. This patch clears the flag if command was rejected. 2013-01-01 00:03:44.209913 < HCI Command: Switch Role (0x02|0x000b) plen 7 bdaddr BC:C6:DB:C4:6F:79 role 0x00 Role: Master 2013-01-01 00:03:44.210867 > HCI Event: Command Status (0x0f) plen 4 Switch Role (0x02|0x000b) status 0x0c ncmd 1 Error: Command Disallowed Signed-off-by: Kuba Pawlak Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2f02ff0ed781..73d9bb4a2c1e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1947,6 +1947,29 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) hci_dev_unlock(hdev); } +static void hci_cs_switch_role(struct hci_dev *hdev, u8 status) +{ + struct hci_cp_switch_role *cp; + struct hci_conn *conn; + + BT_DBG("%s status 0x%2.2x", hdev->name, status); + + if (!status) + return; + + cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE); + if (!cp) + return; + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); + if (conn) + clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); + + hci_dev_unlock(hdev); +} + static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); @@ -2886,6 +2909,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_exit_sniff_mode(hdev, ev->status); break; + case HCI_OP_SWITCH_ROLE: + hci_cs_switch_role(hdev, ev->status); + break; + case HCI_OP_DISCONNECT: hci_cs_disconnect(hdev, ev->status); break; From 9645c76c7c233da82ff7aced0177c8a131a51e70 Mon Sep 17 00:00:00 2001 From: Kuba Pawlak Date: Thu, 6 Nov 2014 19:36:53 +0100 Subject: [PATCH 60/61] Bluetooth: Sort switch cases by opcode's numeric value Opcodes in switch/case in hci_cmd_status_evt are not sorted by value. This patch restores proper ordering. Signed-off-by: Kuba Pawlak Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 73d9bb4a2c1e..5e7be804c709 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2873,6 +2873,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_create_conn(hdev, ev->status); break; + case HCI_OP_DISCONNECT: + hci_cs_disconnect(hdev, ev->status); + break; + case HCI_OP_ADD_SCO: hci_cs_add_sco(hdev, ev->status); break; @@ -2901,6 +2905,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_setup_sync_conn(hdev, ev->status); break; + case HCI_OP_CREATE_PHY_LINK: + hci_cs_create_phylink(hdev, ev->status); + break; + + case HCI_OP_ACCEPT_PHY_LINK: + hci_cs_accept_phylink(hdev, ev->status); + break; + case HCI_OP_SNIFF_MODE: hci_cs_sniff_mode(hdev, ev->status); break; @@ -2913,18 +2925,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_switch_role(hdev, ev->status); break; - case HCI_OP_DISCONNECT: - hci_cs_disconnect(hdev, ev->status); - break; - - case HCI_OP_CREATE_PHY_LINK: - hci_cs_create_phylink(hdev, ev->status); - break; - - case HCI_OP_ACCEPT_PHY_LINK: - hci_cs_accept_phylink(hdev, ev->status); - break; - case HCI_OP_LE_CREATE_CONN: hci_cs_le_create_conn(hdev, ev->status); break; From 56b2c3eea398c772dd895dc62c18cbdd1ba127b1 Mon Sep 17 00:00:00 2001 From: Martin Townsend Date: Thu, 6 Nov 2014 19:15:13 +0000 Subject: [PATCH 61/61] 6lowpan: move skb_free from error paths in decompression Currently we ensure that the skb is freed on every error path in IPHC decompression which makes it easy to introduce skb leaks. By centralising the skb_free into the receive function it makes future decompression routines easier to maintain. It does come at the expense of ensuring that the skb passed into the decompression routine must not be copied. Signed-off-by: Martin Townsend Acked-by: Jukka Rissanen Acked-by: Alexander Aring Signed-off-by: Marcel Holtmann --- net/6lowpan/iphc.c | 31 ++++++++++++------------------- net/bluetooth/6lowpan.c | 15 +++++++-------- net/ieee802154/6lowpan_rtnl.c | 16 ++++++---------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c index cd5f8b8e34cd..aced97db62f0 100644 --- a/net/6lowpan/iphc.c +++ b/net/6lowpan/iphc.c @@ -319,7 +319,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, if (iphc1 & LOWPAN_IPHC_CID) { pr_debug("CID flag is set, increase header with one\n"); if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) - goto drop; + return -EINVAL; } hdr.version = 6; @@ -331,7 +331,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, */ case 0: /* 00b */ if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) - goto drop; + return -EINVAL; memcpy(&hdr.flow_lbl, &skb->data[0], 3); skb_pull(skb, 3); @@ -344,7 +344,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, */ case 2: /* 10b */ if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) - goto drop; + return -EINVAL; hdr.priority = ((tmp >> 2) & 0x0f); hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); @@ -354,7 +354,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, */ case 1: /* 01b */ if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) - goto drop; + return -EINVAL; hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); memcpy(&hdr.flow_lbl[1], &skb->data[0], 2); @@ -371,7 +371,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { /* Next header is carried inline */ if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) - goto drop; + return -EINVAL; pr_debug("NH flag is set, next header carried inline: %02x\n", hdr.nexthdr); @@ -383,7 +383,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, } else { if (lowpan_fetch_skb(skb, &hdr.hop_limit, sizeof(hdr.hop_limit))) - goto drop; + return -EINVAL; } /* Extract SAM to the tmp variable */ @@ -402,7 +402,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, /* Check on error of previous branch */ if (err) - goto drop; + return -EINVAL; /* Extract DAM to the tmp variable */ tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03; @@ -417,7 +417,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, tmp); if (err) - goto drop; + return -EINVAL; } } else { err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, @@ -425,7 +425,7 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, pr_debug("dest: stateless compression mode %d dest %pI6c\n", tmp, &hdr.daddr); if (err) - goto drop; + return -EINVAL; } /* UDP data uncompression */ @@ -434,16 +434,14 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, const int needed = sizeof(struct udphdr) + sizeof(hdr); if (uncompress_udp_header(skb, &uh)) - goto drop; + return -EINVAL; /* replace the compressed UDP head by the uncompressed UDP * header */ err = skb_cow(skb, needed); - if (unlikely(err)) { - kfree_skb(skb); + if (unlikely(err)) return err; - } skb_push(skb, sizeof(struct udphdr)); skb_reset_transport_header(skb); @@ -455,10 +453,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, hdr.nexthdr = UIP_PROTO_UDP; } else { err = skb_cow(skb, sizeof(hdr)); - if (unlikely(err)) { - kfree_skb(skb); + if (unlikely(err)) return err; - } } hdr.payload_len = htons(skb->len); @@ -478,9 +474,6 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev, raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); return 0; -drop: - kfree_skb(skb); - return -EINVAL; } EXPORT_SYMBOL_GPL(lowpan_header_decompress); diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index eef298d17452..dc23c55f1ab6 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -294,20 +294,20 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, peer = __peer_lookup_chan(dev, chan); rcu_read_unlock(); if (!peer) - goto drop; + return -EINVAL; saddr = peer->eui64_addr; daddr = dev->netdev->dev_addr; /* at least two bytes will be used for the encoding */ if (skb->len < 2) - goto drop; + return -EINVAL; if (lowpan_fetch_skb_u8(skb, &iphc0)) - goto drop; + return -EINVAL; if (lowpan_fetch_skb_u8(skb, &iphc1)) - goto drop; + return -EINVAL; return lowpan_header_decompress(skb, netdev, saddr, IEEE802154_ADDR_LONG, @@ -315,9 +315,6 @@ static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN, iphc0, iphc1); -drop: - kfree_skb(skb); - return -EINVAL; } static int recv_pkt(struct sk_buff *skb, struct net_device *dev, @@ -370,8 +367,10 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, goto drop; ret = iphc_decompress(local_skb, dev, chan); - if (ret < 0) + if (ret < 0) { + kfree_skb(local_skb); goto drop; + } local_skb->protocol = htons(ETH_P_IPV6); local_skb->pkt_type = PACKET_HOST; diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index a96b64c9a73d..290e14f2e92e 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c @@ -176,13 +176,13 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); /* at least two bytes will be used for the encoding */ if (skb->len < 2) - goto drop; + return -EINVAL; if (lowpan_fetch_skb_u8(skb, &iphc0)) - goto drop; + return -EINVAL; if (lowpan_fetch_skb_u8(skb, &iphc1)) - goto drop; + return -EINVAL; ieee802154_addr_to_sa(&sa, &hdr->source); ieee802154_addr_to_sa(&da, &hdr->dest); @@ -200,10 +200,6 @@ iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr) return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type, IEEE802154_ADDR_LEN, dap, da.addr_type, IEEE802154_ADDR_LEN, iphc0, iphc1); - -drop: - kfree_skb(skb); - return -EINVAL; } static struct sk_buff* @@ -522,7 +518,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ ret = iphc_decompress(skb, &hdr); if (ret < 0) - goto drop; + goto drop_skb; return lowpan_give_skb_to_devices(skb, NULL); case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ @@ -530,7 +526,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, if (ret == 1) { ret = iphc_decompress(skb, &hdr); if (ret < 0) - goto drop; + goto drop_skb; return lowpan_give_skb_to_devices(skb, NULL); } else if (ret == -1) { @@ -543,7 +539,7 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, if (ret == 1) { ret = iphc_decompress(skb, &hdr); if (ret < 0) - goto drop; + goto drop_skb; return lowpan_give_skb_to_devices(skb, NULL); } else if (ret == -1) {