diff options
Diffstat (limited to 'net/mac802154')
-rw-r--r-- | net/mac802154/Makefile | 2 | ||||
-rw-r--r-- | net/mac802154/cfg.c | 210 | ||||
-rw-r--r-- | net/mac802154/cfg.h | 9 | ||||
-rw-r--r-- | net/mac802154/driver-ops.h | 46 | ||||
-rw-r--r-- | net/mac802154/ieee802154_i.h | 47 | ||||
-rw-r--r-- | net/mac802154/iface.c | 310 | ||||
-rw-r--r-- | net/mac802154/mac_cmd.c | 78 | ||||
-rw-r--r-- | net/mac802154/main.c | 150 | ||||
-rw-r--r-- | net/mac802154/mib.c | 81 | ||||
-rw-r--r-- | net/mac802154/rx.c | 14 | ||||
-rw-r--r-- | net/mac802154/tx.c | 2 | ||||
-rw-r--r-- | net/mac802154/util.c | 35 |
12 files changed, 633 insertions, 351 deletions
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..c035708ada16 --- /dev/null +++ b/net/mac802154/cfg.c @@ -0,0 +1,210 @@ +/* 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 <aar@pengutronix.de> + * + * Based on: net/mac80211/cfg.c + */ + +#include <net/rtnetlink.h> +#include <net/cfg802154.h> + +#include "ieee802154_i.h" +#include "driver-ops.h" +#include "cfg.h" + +static struct net_device * +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; + + rtnl_lock(); + dev = ieee802154_if_add(local, name, type, + cpu_to_le64(0x0000000000000000ULL)); + rtnl_unlock(); + + return dev; +} + +static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy, + struct net_device *dev) +{ + struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + + ieee802154_if_remove(sdata); +} + +static int +ieee802154_add_iface(struct wpan_phy *phy, const char *name, + enum nl802154_iftype type, __le64 extended_addr) +{ + struct ieee802154_local *local = wpan_phy_priv(phy); + struct net_device *err; + + err = ieee802154_if_add(local, name, type, extended_addr); + if (IS_ERR(err)) + return PTR_ERR(err); + + return 0; +} + +static int +ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev) +{ + ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev)); + + return 0; +} + +static int +ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel) +{ + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + int ret; + + ASSERT_RTNL(); + + /* check if phy support this setting */ + if (!(wpan_phy->channels_supported[page] & BIT(channel))) + return -EINVAL; + + ret = drv_set_channel(local, page, channel); + if (!ret) { + wpan_phy->current_page = page; + wpan_phy->current_channel = channel; + } + + return ret; +} + +static int +ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, + __le16 pan_id) +{ + ASSERT_RTNL(); + + /* TODO + * I am not sure about to check here on broadcast pan_id. + * Broadcast is a valid setting, comment from 802.15.4: + * If this value is 0xffff, the device is not associated. + * + * This could useful to simple deassociate an device. + */ + if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST)) + return -EINVAL; + + wpan_dev->pan_id = pan_id; + return 0; +} + +static int +ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy, + struct wpan_dev *wpan_dev, + u8 min_be, u8 max_be) +{ + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + + ASSERT_RTNL(); + + if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS)) + return -EOPNOTSUPP; + + wpan_dev->min_be = min_be; + wpan_dev->max_be = max_be; + return 0; +} + +static int +ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, + __le16 short_addr) +{ + ASSERT_RTNL(); + + /* TODO + * I am not sure about to check here on broadcast short_addr. + * Broadcast is a valid setting, comment from 802.15.4: + * A value of 0xfffe indicates that the device has + * associated but has not been allocated an address. A + * value of 0xffff indicates that the device does not + * have a short address. + * + * I think we should allow to set these settings but + * don't allow to allow socket communication with it. + */ + if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) || + short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST)) + return -EINVAL; + + wpan_dev->short_addr = short_addr; + return 0; +} + +static int +ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy, + struct wpan_dev *wpan_dev, + u8 max_csma_backoffs) +{ + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + + ASSERT_RTNL(); + + if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS)) + return -EOPNOTSUPP; + + wpan_dev->csma_retries = max_csma_backoffs; + return 0; +} + +static int +ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy, + struct wpan_dev *wpan_dev, + s8 max_frame_retries) +{ + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + + ASSERT_RTNL(); + + if (!(local->hw.flags & IEEE802154_HW_FRAME_RETRIES)) + return -EOPNOTSUPP; + + wpan_dev->frame_retries = max_frame_retries; + return 0; +} + +static int +ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev, + bool mode) +{ + struct ieee802154_local *local = wpan_phy_priv(wpan_phy); + + ASSERT_RTNL(); + + if (!(local->hw.flags & IEEE802154_HW_LBT)) + return -EOPNOTSUPP; + + wpan_dev->lbt = mode; + return 0; +} + +const struct cfg802154_ops mac802154_config_ops = { + .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated, + .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated, + .add_virtual_intf = ieee802154_add_iface, + .del_virtual_intf = ieee802154_del_iface, + .set_channel = ieee802154_set_channel, + .set_pan_id = ieee802154_set_pan_id, + .set_short_addr = ieee802154_set_short_addr, + .set_backoff_exponent = ieee802154_set_backoff_exponent, + .set_max_csma_backoffs = ieee802154_set_max_csma_backoffs, + .set_max_frame_retries = ieee802154_set_max_frame_retries, + .set_lbt_mode = ieee802154_set_lbt_mode, +}; 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/driver-ops.h b/net/mac802154/driver-ops.h index dfd29ffb8fee..f21e864613d0 100644 --- a/net/mac802154/driver-ops.h +++ b/net/mac802154/driver-ops.h @@ -50,16 +50,15 @@ static inline void drv_stop(struct ieee802154_local *local) local->started = false; } -static inline int drv_set_channel(struct ieee802154_local *local, - const u8 page, const u8 channel) +static inline int +drv_set_channel(struct ieee802154_local *local, u8 page, u8 channel) { might_sleep(); return local->ops->set_channel(&local->hw, page, channel); } -static inline int drv_set_tx_power(struct ieee802154_local *local, - const s8 dbm) +static inline int drv_set_tx_power(struct ieee802154_local *local, s8 dbm) { might_sleep(); @@ -71,8 +70,7 @@ static inline int drv_set_tx_power(struct ieee802154_local *local, return local->ops->set_txpower(&local->hw, dbm); } -static inline int drv_set_cca_mode(struct ieee802154_local *local, - const u8 cca_mode) +static inline int drv_set_cca_mode(struct ieee802154_local *local, u8 cca_mode) { might_sleep(); @@ -84,8 +82,7 @@ static inline int drv_set_cca_mode(struct ieee802154_local *local, return local->ops->set_cca_mode(&local->hw, cca_mode); } -static inline int drv_set_lbt_mode(struct ieee802154_local *local, - const bool mode) +static inline int drv_set_lbt_mode(struct ieee802154_local *local, bool mode) { might_sleep(); @@ -97,8 +94,8 @@ static inline int drv_set_lbt_mode(struct ieee802154_local *local, return local->ops->set_lbt(&local->hw, mode); } -static inline int drv_set_cca_ed_level(struct ieee802154_local *local, - const s32 ed_level) +static inline int +drv_set_cca_ed_level(struct ieee802154_local *local, s32 ed_level) { might_sleep(); @@ -110,8 +107,7 @@ static inline int drv_set_cca_ed_level(struct ieee802154_local *local, return local->ops->set_cca_ed_level(&local->hw, ed_level); } -static inline int drv_set_pan_id(struct ieee802154_local *local, - const __le16 pan_id) +static inline int drv_set_pan_id(struct ieee802154_local *local, __le16 pan_id) { struct ieee802154_hw_addr_filt filt; @@ -128,8 +124,8 @@ static inline int drv_set_pan_id(struct ieee802154_local *local, IEEE802154_AFILT_PANID_CHANGED); } -static inline int drv_set_extended_addr(struct ieee802154_local *local, - const __le64 extended_addr) +static inline int +drv_set_extended_addr(struct ieee802154_local *local, __le64 extended_addr) { struct ieee802154_hw_addr_filt filt; @@ -146,8 +142,8 @@ static inline int drv_set_extended_addr(struct ieee802154_local *local, IEEE802154_AFILT_IEEEADDR_CHANGED); } -static inline int drv_set_short_addr(struct ieee802154_local *local, - const __le16 short_addr) +static inline int +drv_set_short_addr(struct ieee802154_local *local, __le16 short_addr) { struct ieee802154_hw_addr_filt filt; @@ -164,8 +160,8 @@ static inline int drv_set_short_addr(struct ieee802154_local *local, IEEE802154_AFILT_SADDR_CHANGED); } -static inline int drv_set_pan_coord(struct ieee802154_local *local, - const bool is_coord) +static inline int +drv_set_pan_coord(struct ieee802154_local *local, bool is_coord) { struct ieee802154_hw_addr_filt filt; @@ -182,9 +178,9 @@ static inline int drv_set_pan_coord(struct ieee802154_local *local, IEEE802154_AFILT_PANC_CHANGED); } -static inline int drv_set_csma_params(struct ieee802154_local *local, - u8 min_be, u8 max_be, - u8 max_csma_backoffs) +static inline int +drv_set_csma_params(struct ieee802154_local *local, u8 min_be, u8 max_be, + u8 max_csma_backoffs) { might_sleep(); @@ -197,8 +193,8 @@ static inline int drv_set_csma_params(struct ieee802154_local *local, max_csma_backoffs); } -static inline int drv_set_max_frame_retries(struct ieee802154_local *local, - s8 max_frame_retries) +static inline int +drv_set_max_frame_retries(struct ieee802154_local *local, s8 max_frame_retries) { might_sleep(); @@ -210,8 +206,8 @@ static inline int drv_set_max_frame_retries(struct ieee802154_local *local, return local->ops->set_frame_retries(&local->hw, max_frame_retries); } -static inline int drv_set_promiscuous_mode(struct ieee802154_local *local, - const bool on) +static inline int +drv_set_promiscuous_mode(struct ieee802154_local *local, bool on) { might_sleep(); diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h index 1086a9d96f8f..bebd70ffc7a3 100644 --- a/net/mac802154/ieee802154_i.h +++ b/net/mac802154/ieee802154_i.h @@ -20,7 +20,10 @@ #define __IEEE802154_I_H #include <linux/mutex.h> +#include <linux/hrtimer.h> +#include <net/cfg802154.h> #include <net/mac802154.h> +#include <net/nl802154.h> #include <net/ieee802154_netdev.h> #include "llsec.h" @@ -50,6 +53,8 @@ struct ieee802154_local { */ struct workqueue_struct *workqueue; + struct hrtimer ifs_timer; + bool started; struct tasklet_struct tasklet; @@ -73,36 +78,31 @@ 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; - __le16 pan_id; - __le16 short_addr; - __le64 extended_addr; - bool promisuous_mode; - - struct ieee802154_mac_params mac_params; - - /* MAC BSN field */ - u8 bsn; - /* MAC DSN field */ - u8 dsn; - /* protects sec from concurrent access by netlink. access by * encrypt/decrypt/header_create safe without additional protection. */ 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 */ +/* utility functions/constants */ +extern const void *const mac802154_wpan_phy_privid; /* for wpan_phy privid */ + static inline struct ieee802154_local * hw_to_local(struct ieee802154_hw *hw) { @@ -115,27 +115,29 @@ IEEE802154_DEV_TO_SUB_IF(const struct net_device *dev) return netdev_priv(dev); } +static inline struct ieee802154_sub_if_data * +IEEE802154_WPAN_DEV_TO_SUB_IF(struct wpan_dev *wpan_dev) +{ + return container_of(wpan_dev, struct ieee802154_sub_if_data, wpan_dev); +} + static inline bool ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata) { return test_bit(SDATA_STATE_RUNNING, &sdata->state); } -extern struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced; extern struct ieee802154_mlme_ops mac802154_mlme_wpan; -void mac802154_monitor_setup(struct net_device *dev); netdev_tx_t ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); - -void mac802154_wpan_setup(struct net_device *dev); netdev_tx_t ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer); /* 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); @@ -174,4 +176,13 @@ void mac802154_get_table(struct net_device *dev, struct ieee802154_llsec_table **t); void mac802154_unlock_table(struct net_device *dev); +/* interface handling */ +int ieee802154_iface_init(void); +void ieee802154_iface_exit(void); +void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata); +struct net_device * +ieee802154_if_add(struct ieee802154_local *local, const char *name, + enum nl802154_iftype type, __le64 extended_addr); +void ieee802154_remove_interfaces(struct ieee802154_local *local); + #endif /* __IEEE802154_I_H */ diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c index f7a6f83301e2..38dfc72d24b6 100644 --- a/net/mac802154/iface.c +++ b/net/mac802154/iface.c @@ -22,9 +22,7 @@ #include <linux/if_arp.h> #include <linux/ieee802154.h> -#include <net/rtnetlink.h> -#include <linux/nl802154.h> -#include <net/af_ieee802154.h> +#include <net/nl802154.h> #include <net/mac802154.h> #include <net/ieee802154_netdev.h> #include <net/cfg802154.h> @@ -36,16 +34,17 @@ static int mac802154_wpan_update_llsec(struct net_device *dev) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); + struct wpan_dev *wpan_dev = &sdata->wpan_dev; int rc = 0; if (ops->llsec) { struct ieee802154_llsec_params params; int changed = 0; - params.pan_id = sdata->pan_id; + params.pan_id = wpan_dev->pan_id; changed |= IEEE802154_LLSEC_PARAM_PAN_ID; - params.hwaddr = sdata->extended_addr; + params.hwaddr = wpan_dev->extended_addr; changed |= IEEE802154_LLSEC_PARAM_HWADDR; rc = ops->llsec->set_params(dev, ¶ms, changed); @@ -58,10 +57,13 @@ static int mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + struct wpan_dev *wpan_dev = &sdata->wpan_dev; struct sockaddr_ieee802154 *sa = (struct sockaddr_ieee802154 *)&ifr->ifr_addr; int err = -ENOIOCTLCMD; + ASSERT_RTNL(); + spin_lock_bh(&sdata->mib_lock); switch (cmd) { @@ -69,8 +71,8 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { u16 pan_id, short_addr; - pan_id = le16_to_cpu(sdata->pan_id); - short_addr = le16_to_cpu(sdata->short_addr); + pan_id = le16_to_cpu(wpan_dev->pan_id); + short_addr = le16_to_cpu(wpan_dev->short_addr); if (pan_id == IEEE802154_PANID_BROADCAST || short_addr == IEEE802154_ADDR_BROADCAST) { err = -EADDRNOTAVAIL; @@ -86,6 +88,11 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } case SIOCSIFADDR: + if (netif_running(dev)) { + spin_unlock_bh(&sdata->mib_lock); + return -EBUSY; + } + dev_warn(&dev->dev, "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n"); if (sa->family != AF_IEEE802154 || @@ -97,8 +104,8 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } - sdata->pan_id = cpu_to_le16(sa->addr.pan_id); - sdata->short_addr = cpu_to_le16(sa->addr.short_addr); + wpan_dev->pan_id = cpu_to_le16(sa->addr.pan_id); + wpan_dev->short_addr = cpu_to_le16(sa->addr.short_addr); err = mac802154_wpan_update_llsec(dev); break; @@ -110,37 +117,21 @@ 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; + __le64 extended_addr; if (netif_running(dev)) return -EBUSY; - /* FIXME: validate addr */ - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - mac802154_dev_set_ieee_addr(dev); - 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; -} + ieee802154_be64_to_le64(&extended_addr, addr->sa_data); + if (!ieee802154_is_valid_extended_addr(extended_addr)) + return -EINVAL; -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); + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + sdata->wpan_dev.extended_addr = extended_addr; - mutex_lock(&sdata->local->iflist_mtx); - *params = sdata->mac_params; - mutex_unlock(&sdata->local->iflist_mtx); + return mac802154_wpan_update_llsec(dev); } static int mac802154_slave_open(struct net_device *dev) @@ -152,10 +143,11 @@ static int mac802154_slave_open(struct net_device *dev) ASSERT_RTNL(); - if (sdata->type == IEEE802154_DEV_WPAN) { + if (sdata->vif.type == NL802154_IFTYPE_NODE) { 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; @@ -188,6 +180,7 @@ static int mac802154_wpan_open(struct net_device *dev) int rc; struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); struct ieee802154_local *local = sdata->local; + struct wpan_dev *wpan_dev = &sdata->wpan_dev; struct wpan_phy *phy = sdata->local->phy; rc = mac802154_slave_open(dev); @@ -197,47 +190,42 @@ 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, + wpan_dev->promiscuous_mode); if (rc < 0) goto out; } - if (local->hw.flags & IEEE802154_HW_TXPOWER) { - rc = drv_set_tx_power(local, sdata->mac_params.transmit_power); + if (local->hw.flags & IEEE802154_HW_AFILT) { + rc = drv_set_pan_id(local, wpan_dev->pan_id); if (rc < 0) goto out; - } - if (local->hw.flags & IEEE802154_HW_LBT) { - rc = drv_set_lbt_mode(local, sdata->mac_params.lbt); + rc = drv_set_extended_addr(local, wpan_dev->extended_addr); if (rc < 0) goto out; - } - if (local->hw.flags & IEEE802154_HW_CCA_MODE) { - rc = drv_set_cca_mode(local, sdata->mac_params.cca_mode); + rc = drv_set_short_addr(local, wpan_dev->short_addr); 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 (local->hw.flags & IEEE802154_HW_LBT) { + rc = drv_set_lbt_mode(local, wpan_dev->lbt); 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, - sdata->mac_params.csma_retries); + rc = drv_set_csma_params(local, wpan_dev->min_be, + wpan_dev->max_be, + wpan_dev->csma_retries); if (rc < 0) goto out; } if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) { - rc = drv_set_max_frame_retries(local, - sdata->mac_params.frame_retries); + rc = drv_set_max_frame_retries(local, wpan_dev->frame_retries); if (rc < 0) goto out; } @@ -257,6 +245,8 @@ static int mac802154_slave_close(struct net_device *dev) ASSERT_RTNL(); + hrtimer_cancel(&local->ifs_timer); + netif_stop_queue(dev); local->open_count--; @@ -309,6 +299,7 @@ static int mac802154_header_create(struct sk_buff *skb, { struct ieee802154_hdr hdr; struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + struct wpan_dev *wpan_dev = &sdata->wpan_dev; struct ieee802154_mac_cb *cb = mac_cb(skb); int hlen; @@ -327,17 +318,17 @@ static int mac802154_header_create(struct sk_buff *skb, if (!saddr) { spin_lock_bh(&sdata->mib_lock); - if (sdata->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) || - sdata->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || - sdata->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) { + if (wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) || + wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || + wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) { hdr.source.mode = IEEE802154_ADDR_LONG; - hdr.source.extended_addr = sdata->extended_addr; + hdr.source.extended_addr = wpan_dev->extended_addr; } else { hdr.source.mode = IEEE802154_ADDR_SHORT; - hdr.source.short_addr = sdata->short_addr; + hdr.source.short_addr = wpan_dev->short_addr; } - hdr.source.pan_id = sdata->pan_id; + hdr.source.pan_id = wpan_dev->pan_id; spin_unlock_bh(&sdata->mib_lock); } else { @@ -402,65 +393,196 @@ 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->addr_len = IEEE802154_EXTENDED_ADDR_LEN; + memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_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; +static int +ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, + enum nl802154_iftype type) +{ + struct wpan_dev *wpan_dev = &sdata->wpan_dev; - spin_lock_init(&sdata->mib_lock); - mutex_init(&sdata->sec_mtx); + /* set some type-dependent values */ + sdata->vif.type = type; + sdata->wpan_dev.iftype = type; - get_random_bytes(&sdata->bsn, 1); - get_random_bytes(&sdata->dsn, 1); + get_random_bytes(&wpan_dev->bsn, 1); + get_random_bytes(&wpan_dev->dsn, 1); /* defaults per 802.15.4-2011 */ - sdata->mac_params.min_be = 3; - sdata->mac_params.max_be = 5; - sdata->mac_params.csma_retries = 4; + wpan_dev->min_be = 3; + wpan_dev->max_be = 5; + wpan_dev->csma_retries = 4; /* for compatibility, actual default is 3 */ - sdata->mac_params.frame_retries = -1; + wpan_dev->frame_retries = -1; + + wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); + wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); + + switch (type) { + case NL802154_IFTYPE_NODE: + ieee802154_be64_to_le64(&wpan_dev->extended_addr, + sdata->dev->dev_addr); + + 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; + wpan_dev->promiscuous_mode = false; + + spin_lock_init(&sdata->mib_lock); + mutex_init(&sdata->sec_mtx); + + mac802154_llsec_init(&sdata->sec); + break; + case NL802154_IFTYPE_MONITOR: + sdata->dev->destructor = free_netdev; + sdata->dev->netdev_ops = &mac802154_monitor_ops; + wpan_dev->promiscuous_mode = true; + break; + default: + BUG(); + } + + return 0; +} + +struct net_device * +ieee802154_if_add(struct ieee802154_local *local, const char *name, + enum nl802154_iftype type, __le64 extended_addr) +{ + struct net_device *ndev = NULL; + struct ieee802154_sub_if_data *sdata = NULL; + int ret = -ENOMEM; + + ASSERT_RTNL(); + + ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, 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; + + ieee802154_le64_to_be64(ndev->perm_addr, + &local->hw.phy->perm_extended_addr); + switch (type) { + case NL802154_IFTYPE_NODE: + ndev->type = ARPHRD_IEEE802154; + if (ieee802154_is_valid_extended_addr(extended_addr)) + ieee802154_le64_to_be64(ndev->dev_addr, &extended_addr); + else + memcpy(ndev->dev_addr, ndev->perm_addr, + IEEE802154_EXTENDED_ADDR_LEN); + break; + case NL802154_IFTYPE_MONITOR: + ndev->type = ARPHRD_IEEE802154_MONITOR; + break; + default: + ret = -EINVAL; + goto err; + } + + /* 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); + + return ndev; + +err: + free_netdev(ndev); + return ERR_PTR(ret); +} - sdata->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); - sdata->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); +void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata) +{ + ASSERT_RTNL(); - sdata->promisuous_mode = false; + mutex_lock(&sdata->local->iflist_mtx); + list_del_rcu(&sdata->list); + mutex_unlock(&sdata->local->iflist_mtx); - mac802154_llsec_init(&sdata->sec); + synchronize_rcu(); + unregister_netdevice(sdata->dev); } -void mac802154_monitor_setup(struct net_device *dev) +void ieee802154_remove_interfaces(struct ieee802154_local *local) { + struct ieee802154_sub_if_data *sdata, *tmp; + + mutex_lock(&local->iflist_mtx); + list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { + list_del(&sdata->list); + + unregister_netdevice(sdata->dev); + } + mutex_unlock(&local->iflist_mtx); +} + +static int netdev_notify(struct notifier_block *nb, + unsigned long state, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); 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; + if (state != NETDEV_CHANGENAME) + return NOTIFY_DONE; + + if (!dev->ieee802154_ptr || !dev->ieee802154_ptr->wpan_phy) + return NOTIFY_DONE; - dev->destructor = free_netdev; - dev->netdev_ops = &mac802154_monitor_ops; - dev->ml_priv = &mac802154_mlme_reduced; + if (dev->ieee802154_ptr->wpan_phy->privid != mac802154_wpan_phy_privid) + return NOTIFY_DONE; sdata = IEEE802154_DEV_TO_SUB_IF(dev); - sdata->type = IEEE802154_DEV_MONITOR; + memcpy(sdata->name, dev->name, IFNAMSIZ); + + return NOTIFY_OK; +} + +static struct notifier_block mac802154_netdev_notifier = { + .notifier_call = netdev_notify, +}; - sdata->promisuous_mode = true; +int ieee802154_iface_init(void) +{ + return register_netdevice_notifier(&mac802154_netdev_notifier); +} + +void ieee802154_iface_exit(void) +{ + unregister_netdevice_notifier(&mac802154_netdev_notifier); } diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index fc261ab33347..6aacb1816889 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c @@ -25,9 +25,9 @@ #include <net/ieee802154_netdev.h> #include <net/cfg802154.h> #include <net/mac802154.h> -#include <net/nl802154.h> #include "ieee802154_i.h" +#include "driver-ops.h" static int mac802154_mlme_start_req(struct net_device *dev, struct ieee802154_addr *addr, @@ -39,11 +39,12 @@ static int mac802154_mlme_start_req(struct net_device *dev, struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev); int rc = 0; + ASSERT_RTNL(); + BUG_ON(addr->mode != IEEE802154_ADDR_SHORT); 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) { @@ -65,31 +66,48 @@ 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; } -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) { struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev); + struct ieee802154_local *local = sdata->local; + struct wpan_dev *wpan_dev = &sdata->wpan_dev; + int ret; + + ASSERT_RTNL(); + + /* PHY */ + wpan_dev->wpan_phy->transmit_power = params->transmit_power; + wpan_dev->wpan_phy->cca_mode = params->cca_mode; + wpan_dev->wpan_phy->cca_ed_level = params->cca_ed_level; + + /* MAC */ + wpan_dev->min_be = params->min_be; + wpan_dev->max_be = params->max_be; + wpan_dev->csma_retries = params->csma_retries; + wpan_dev->frame_retries = params->frame_retries; + wpan_dev->lbt = params->lbt; + + 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; + } - mutex_lock(&sdata->local->iflist_mtx); - sdata->mac_params = *params; - mutex_unlock(&sdata->local->iflist_mtx); + 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; } @@ -98,10 +116,21 @@ static 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); + struct wpan_dev *wpan_dev = &sdata->wpan_dev; - mutex_lock(&sdata->local->iflist_mtx); - *params = sdata->mac_params; - mutex_unlock(&sdata->local->iflist_mtx); + ASSERT_RTNL(); + + /* PHY */ + params->transmit_power = wpan_dev->wpan_phy->transmit_power; + params->cca_mode = wpan_dev->wpan_phy->cca_mode; + params->cca_ed_level = wpan_dev->wpan_phy->cca_ed_level; + + /* MAC */ + params->min_be = wpan_dev->min_be; + params->max_be = wpan_dev->max_be; + params->csma_retries = wpan_dev->csma_retries; + params->frame_retries = wpan_dev->frame_retries; + params->lbt = wpan_dev->lbt; } static struct ieee802154_llsec_ops mac802154_llsec_ops = { @@ -120,12 +149,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, diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 86e533ed3775..8500378c8318 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -4,8 +4,6 @@ * Written by: * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> * - * Based on the code from 'linux-zigbee.sourceforge.net' project. - * * 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. @@ -21,97 +19,14 @@ #include <linux/netdevice.h> #include <net/netlink.h> -#include <linux/nl802154.h> +#include <net/nl802154.h> #include <net/mac802154.h> #include <net/ieee802154_netdev.h> #include <net/route.h> #include <net/cfg802154.h> #include "ieee802154_i.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; -} - -static 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); -} - -static 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); -} +#include "cfg.h" static void ieee802154_tasklet_handler(unsigned long data) { @@ -169,12 +84,14 @@ 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_new(&mac802154_config_ops, priv_size); if (!phy) { pr_err("failure to allocate master IEEE802.15.4 device\n"); return NULL; } + phy->privid = mac802154_wpan_phy_privid; + local = wpan_phy_priv(phy); local->phy = phy; local->hw.phy = local->phy; @@ -206,9 +123,22 @@ void ieee802154_free_hw(struct ieee802154_hw *hw) } EXPORT_SYMBOL(ieee802154_free_hw); +static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy) +{ + /* TODO warn on empty symbol_duration + * Should be done when all drivers sets this value. + */ + + wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD * + wpan_phy->symbol_duration; + wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD * + wpan_phy->symbol_duration; +} + 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 = @@ -218,15 +148,29 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) goto out; } + hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + local->ifs_timer.function = ieee802154_xmit_ifs_timer; + wpan_phy_set_dev(local->phy, local->hw.parent); - local->phy->add_iface = mac802154_add_iface; - local->phy->del_iface = mac802154_del_iface; + ieee802154_setup_wpan_phy_pib(local->phy); rc = wpan_phy_register(local->phy); if (rc < 0) goto out_wq; + rtnl_lock(); + + dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE, + cpu_to_le64(0x0000000000000000ULL)); + if (IS_ERR(dev)) { + rtnl_unlock(); + rc = PTR_ERR(dev); + goto out_wq; + } + + rtnl_unlock(); + return 0; out_wq: @@ -239,7 +183,6 @@ EXPORT_SYMBOL(ieee802154_register_hw); void ieee802154_unregister_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); - struct ieee802154_sub_if_data *sdata, *next; tasklet_kill(&local->tasklet); flush_workqueue(local->workqueue); @@ -247,13 +190,7 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw) rtnl_lock(); - list_for_each_entry_safe(sdata, next, &local->interfaces, list) { - mutex_lock(&sdata->local->iflist_mtx); - list_del(&sdata->list); - mutex_unlock(&sdata->local->iflist_mtx); - - unregister_netdevice(sdata->dev); - } + ieee802154_remove_interfaces(local); rtnl_unlock(); @@ -261,5 +198,20 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw) } EXPORT_SYMBOL(ieee802154_unregister_hw); -MODULE_DESCRIPTION("IEEE 802.15.4 implementation"); +static int __init ieee802154_init(void) +{ + return ieee802154_iface_init(); +} + +static void __exit ieee802154_exit(void) +{ + ieee802154_iface_exit(); + + rcu_barrier(); +} + +subsys_initcall(ieee802154_init); +module_exit(ieee802154_exit); + +MODULE_DESCRIPTION("IEEE 802.15.4 subsystem"); MODULE_LICENSE("GPL v2"); diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 0184fced2f62..3596b29ead6b 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); @@ -78,14 +33,8 @@ void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) BUG_ON(dev->type != ARPHRD_IEEE802154); spin_lock_bh(&sdata->mib_lock); - sdata->short_addr = val; + sdata->wpan_dev.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) @@ -96,26 +45,12 @@ __le16 mac802154_dev_get_short_addr(const struct net_device *dev) BUG_ON(dev->type != ARPHRD_IEEE802154); spin_lock_bh(&sdata->mib_lock); - ret = sdata->short_addr; + ret = sdata->wpan_dev.short_addr; spin_unlock_bh(&sdata->mib_lock); 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); @@ -124,7 +59,7 @@ __le16 mac802154_dev_get_pan_id(const struct net_device *dev) BUG_ON(dev->type != ARPHRD_IEEE802154); spin_lock_bh(&sdata->mib_lock); - ret = sdata->pan_id; + ret = sdata->wpan_dev.pan_id; spin_unlock_bh(&sdata->mib_lock); return ret; @@ -137,14 +72,8 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) BUG_ON(dev->type != ARPHRD_IEEE802154); spin_lock_bh(&sdata->mib_lock); - sdata->pan_id = val; + sdata->wpan_dev.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) @@ -153,7 +82,7 @@ u8 mac802154_dev_get_dsn(const struct net_device *dev) BUG_ON(dev->type != ARPHRD_IEEE802154); - return sdata->dsn++; + return sdata->wpan_dev.dsn++; } void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan) diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index 95961cccc253..041dbd5958d4 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c @@ -25,8 +25,7 @@ #include <net/mac802154.h> #include <net/ieee802154_netdev.h> -#include <net/rtnetlink.h> -#include <linux/nl802154.h> +#include <net/nl802154.h> #include "ieee802154_i.h" @@ -42,6 +41,7 @@ static int ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata, struct sk_buff *skb, const struct ieee802154_hdr *hdr) { + struct wpan_dev *wpan_dev = &sdata->wpan_dev; __le16 span, sshort; int rc; @@ -49,8 +49,8 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata, spin_lock_bh(&sdata->mib_lock); - span = sdata->pan_id; - sshort = sdata->short_addr; + span = wpan_dev->pan_id; + sshort = wpan_dev->short_addr; switch (mac_cb(skb)->dest.mode) { case IEEE802154_ADDR_NONE: @@ -65,7 +65,7 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata, if (mac_cb(skb)->dest.pan_id != span && mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST)) skb->pkt_type = PACKET_OTHERHOST; - else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr) + else if (mac_cb(skb)->dest.extended_addr == wpan_dev->extended_addr) skb->pkt_type = PACKET_HOST; else skb->pkt_type = PACKET_OTHERHOST; @@ -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 != NL802154_IFTYPE_NODE || !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 != NL802154_IFTYPE_MONITOR) continue; if (!ieee802154_sdata_running(sdata)) diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index cc37b77f2632..c62e95695c78 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c @@ -60,7 +60,7 @@ static void ieee802154_xmit_worker(struct work_struct *work) if (res) goto err_tx; - ieee802154_xmit_complete(&local->hw, skb); + ieee802154_xmit_complete(&local->hw, skb, false); dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; diff --git a/net/mac802154/util.c b/net/mac802154/util.c index 117e4eff4ca8..5fc979027919 100644 --- a/net/mac802154/util.c +++ b/net/mac802154/util.c @@ -15,6 +15,9 @@ #include "ieee802154_i.h" +/* privid for wpan_phys to determine whether they belong to us or not */ +const void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid; + void ieee802154_wake_queue(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); @@ -47,9 +50,35 @@ void ieee802154_stop_queue(struct ieee802154_hw *hw) } EXPORT_SYMBOL(ieee802154_stop_queue); -void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb) +enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer) { - ieee802154_wake_queue(hw); - consume_skb(skb); + struct ieee802154_local *local = + container_of(timer, struct ieee802154_local, ifs_timer); + + ieee802154_wake_queue(&local->hw); + + return HRTIMER_NORESTART; +} + +void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb, + bool ifs_handling) +{ + if (ifs_handling) { + struct ieee802154_local *local = hw_to_local(hw); + + if (skb->len > 18) + hrtimer_start(&local->ifs_timer, + ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC), + HRTIMER_MODE_REL); + else + hrtimer_start(&local->ifs_timer, + ktime_set(0, hw->phy->sifs_period * NSEC_PER_USEC), + HRTIMER_MODE_REL); + + consume_skb(skb); + } else { + ieee802154_wake_queue(hw); + consume_skb(skb); + } } EXPORT_SYMBOL(ieee802154_xmit_complete); |