nl802154: introduce support for cca settings
authorAlexander Aring <alex.aring@gmail.com>
Wed, 10 Dec 2014 14:33:13 +0000 (15:33 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Thu, 18 Dec 2014 23:19:23 +0000 (00:19 +0100)
This patch adds support for setting cca parameters via nl802154.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/cfg802154.h
include/net/nl802154.h
net/ieee802154/nl802154.c
net/ieee802154/rdev-ops.h
net/mac802154/cfg.c

index 6ee2618ac78a66913367771603a422146fa798b7..eeda67652766a9979478de97105322b5ee6a7977 100644 (file)
@@ -25,6 +25,7 @@
 #include <net/nl802154.h>
 
 struct wpan_phy;
+struct wpan_phy_cca;
 
 struct cfg802154_ops {
        struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
@@ -39,6 +40,8 @@ struct cfg802154_ops {
        int     (*del_virtual_intf)(struct wpan_phy *wpan_phy,
                                    struct wpan_dev *wpan_dev);
        int     (*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
+       int     (*set_cca_mode)(struct wpan_phy *wpan_phy,
+                               const struct wpan_phy_cca *cca);
        int     (*set_pan_id)(struct wpan_phy *wpan_phy,
                              struct wpan_dev *wpan_dev, __le16 pan_id);
        int     (*set_short_addr)(struct wpan_phy *wpan_phy,
index 86c1b2f15b57b09ac6fa45d91487856b152f5b44..f8b5bc997959f7ba171258bd31852c696873bc21 100644 (file)
@@ -82,7 +82,7 @@ enum nl802154_attrs {
        NL802154_ATTR_TX_POWER,
 
        NL802154_ATTR_CCA_MODE,
-       NL802154_ATTR_CCA_MODE3_AND,
+       NL802154_ATTR_CCA_OPT,
        NL802154_ATTR_CCA_ED_LEVEL,
 
        NL802154_ATTR_MAX_FRAME_RETRIES,
index 1efbe42500248c885607cbd420be85760220d834..a25b9bbd077be000d2e1de99bf795ac8e1fc0897 100644 (file)
@@ -209,7 +209,8 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 
        [NL802154_ATTR_TX_POWER] = { .type = NLA_S8, },
 
-       [NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
+       [NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, },
+       [NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, },
 
        [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
 
@@ -290,10 +291,16 @@ static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
                goto nla_put_failure;
 
        /* cca mode */
-       if (nla_put_u8(msg, NL802154_ATTR_CCA_MODE,
-                      rdev->wpan_phy.cca.mode))
+       if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE,
+                       rdev->wpan_phy.cca.mode))
                goto nla_put_failure;
 
+       if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) {
+               if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT,
+                               rdev->wpan_phy.cca.opt))
+                       goto nla_put_failure;
+       }
+
        if (nla_put_s8(msg, NL802154_ATTR_TX_POWER,
                       rdev->wpan_phy.transmit_power))
                goto nla_put_failure;
@@ -622,6 +629,31 @@ static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
        return rdev_set_channel(rdev, page, channel);
 }
 
+static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg802154_registered_device *rdev = info->user_ptr[0];
+       struct wpan_phy_cca cca;
+
+       if (!info->attrs[NL802154_ATTR_CCA_MODE])
+               return -EINVAL;
+
+       cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
+       /* checking 802.15.4 constraints */
+       if (cca.mode < NL802154_CCA_ENERGY || cca.mode > NL802154_CCA_ATTR_MAX)
+               return -EINVAL;
+
+       if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
+               if (!info->attrs[NL802154_ATTR_CCA_OPT])
+                       return -EINVAL;
+
+               cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
+               if (cca.opt > NL802154_CCA_OPT_ATTR_MAX)
+                       return -EINVAL;
+       }
+
+       return rdev_set_cca_mode(rdev, &cca);
+}
+
 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg802154_registered_device *rdev = info->user_ptr[0];
@@ -894,6 +926,14 @@ static const struct genl_ops nl802154_ops[] = {
                .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
                                  NL802154_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL802154_CMD_SET_CCA_MODE,
+               .doit = nl802154_set_cca_mode,
+               .policy = nl802154_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
+                                 NL802154_FLAG_NEED_RTNL,
+       },
        {
                .cmd = NL802154_CMD_SET_PAN_ID,
                .doit = nl802154_set_pan_id,
index aff54fbd9264e92fd03578d6ecb5298d53226a42..7c46732fad2bdd3f6778fce066cb89330b5aeaa3 100644 (file)
@@ -41,6 +41,13 @@ rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel)
        return rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
 }
 
+static inline int
+rdev_set_cca_mode(struct cfg802154_registered_device *rdev,
+                 const struct wpan_phy_cca *cca)
+{
+       return rdev->ops->set_cca_mode(&rdev->wpan_phy, cca);
+}
+
 static inline int
 rdev_set_pan_id(struct cfg802154_registered_device *rdev,
                struct wpan_dev *wpan_dev, __le16 pan_id)
index c035708ada160d5364417db8a4c3179819016d49..7d31da503dcfcd24d00826d24b121228075ced35 100644 (file)
@@ -86,6 +86,26 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
        return ret;
 }
 
+static int
+ieee802154_set_cca_mode(struct wpan_phy *wpan_phy,
+                       const struct wpan_phy_cca *cca)
+{
+       struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+       int ret;
+
+       ASSERT_RTNL();
+
+       /* check if phy support this setting */
+       if (!(local->hw.flags & IEEE802154_HW_CCA_MODE))
+               return -EOPNOTSUPP;
+
+       ret = drv_set_cca_mode(local, cca);
+       if (!ret)
+               wpan_phy->cca = *cca;
+
+       return ret;
+}
+
 static int
 ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
                      __le16 pan_id)
@@ -201,6 +221,7 @@ const struct cfg802154_ops mac802154_config_ops = {
        .add_virtual_intf = ieee802154_add_iface,
        .del_virtual_intf = ieee802154_del_iface,
        .set_channel = ieee802154_set_channel,
+       .set_cca_mode = ieee802154_set_cca_mode,
        .set_pan_id = ieee802154_set_pan_id,
        .set_short_addr = ieee802154_set_short_addr,
        .set_backoff_exponent = ieee802154_set_backoff_exponent,