mac802154: make csma/cca parameters per-wpan
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Mon, 31 Mar 2014 19:37:46 +0000 (21:37 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 1 Apr 2014 20:25:51 +0000 (16:25 -0400)
Commit 9b2777d6089bcd (ieee802154: add TX power control to wpan_phy)
and following erroneously added CSMA and CCA parameters for 802.15.4
devices as PHY parameters, while they are actually MAC parameters and
can differ for any two WPAN instances. Since it is now sensible to have
multiple WPAN devices with differing CSMA/CCA parameters, make these
parameters MAC parameters instead.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/nl802154.h
include/net/ieee802154_netdev.h
net/ieee802154/ieee802154.h
net/ieee802154/netlink.c
net/ieee802154/nl-mac.c
net/ieee802154/nl-phy.c
net/ieee802154/wpan-class.c
net/mac802154/ieee802154_dev.c
net/mac802154/mac802154.h
net/mac802154/mac_cmd.c
net/mac802154/wpan.c

index e110b8c266f547a884bca0040dd15e3be03f1485..c8d7f3965fff913a55f158a53b7bc0944c1d4b61 100644 (file)
@@ -132,7 +132,7 @@ enum {
        IEEE802154_ADD_IFACE,
        IEEE802154_DEL_IFACE,
 
-       IEEE802154_SET_PHYPARAMS,
+       IEEE802154_SET_MACPARAMS,
 
        __IEEE802154_CMD_MAX,
 };
index e1717cbf609b67d6761dc68ed9d8a40a202bbfb3..5a719ca892f41c24eb45e849a64327cd6221d407 100644 (file)
@@ -229,6 +229,18 @@ static inline int mac_cb_type(struct sk_buff *skb)
 #define IEEE802154_MAC_SCAN_PASSIVE    2
 #define IEEE802154_MAC_SCAN_ORPHAN     3
 
+struct ieee802154_mac_params {
+       s8 transmit_power;
+       u8 min_be;
+       u8 max_be;
+       u8 csma_retries;
+       s8 frame_retries;
+
+       bool lbt;
+       u8 cca_mode;
+       s32 cca_ed_level;
+};
+
 struct wpan_phy;
 /*
  * This should be located at net_device->ml_priv
@@ -255,6 +267,11 @@ struct ieee802154_mlme_ops {
        int (*scan_req)(struct net_device *dev,
                        u8 type, u32 channels, u8 page, u8 duration);
 
+       int (*set_mac_params)(struct net_device *dev,
+                             const struct ieee802154_mac_params *params);
+       void (*get_mac_params)(struct net_device *dev,
+                              struct ieee802154_mac_params *params);
+
        /* The fields below are required. */
 
        struct wpan_phy *(*get_phy)(const struct net_device *dev);
index 6cbc8965be9181ce27314973532968dd7caab181..6693a5cf01ce5e5fc39fcd33a64547dc4bdb5748 100644 (file)
@@ -53,7 +53,6 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb);
 int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info);
-int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info);
 
 enum ieee802154_mcgrp_ids {
        IEEE802154_COORD_MCGRP,
@@ -67,5 +66,6 @@ int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info);
 int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb);
+int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info);
 
 #endif
index 67c151bf4b91b610835ffc60185428a9a84be8d8..04b20589d97ab91eeb203ba0527122184936dc06 100644 (file)
@@ -115,7 +115,6 @@ static const struct genl_ops ieee8021154_ops[] = {
                        ieee802154_dump_phy),
        IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface),
        IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface),
-       IEEE802154_OP(IEEE802154_SET_PHYPARAMS, ieee802154_set_phyparams),
        /* see nl-mac.c */
        IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req),
        IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp),
@@ -124,6 +123,7 @@ static const struct genl_ops ieee8021154_ops[] = {
        IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
        IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
                        ieee802154_dump_iface),
+       IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
 };
 
 static const struct genl_multicast_group ieee802154_mcgrps[] = {
index bda8dba4f993b0ce981888627cd3099dc2f13642..5d285498c0f691a906de5d9c82c64f867a857418 100644 (file)
@@ -264,6 +264,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
 {
        void *hdr;
        struct wpan_phy *phy;
+       struct ieee802154_mlme_ops *ops;
        __le16 short_addr, pan_id;
 
        pr_debug("%s\n", __func__);
@@ -273,11 +274,12 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
        if (!hdr)
                goto out;
 
-       phy = ieee802154_mlme_ops(dev)->get_phy(dev);
+       ops = ieee802154_mlme_ops(dev);
+       phy = ops->get_phy(dev);
        BUG_ON(!phy);
 
-       short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
-       pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+       short_addr = ops->get_short_addr(dev);
+       pan_id = ops->get_pan_id(dev);
 
        if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
            nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
@@ -287,6 +289,30 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
            nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
            nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
                goto nla_put_failure;
+
+       if (ops->get_mac_params) {
+               struct ieee802154_mac_params params;
+
+               ops->get_mac_params(dev, &params);
+
+               if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
+                              params.transmit_power) ||
+                   nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
+                   nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
+                              params.cca_mode) ||
+                   nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
+                               params.cca_ed_level) ||
+                   nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
+                              params.csma_retries) ||
+                   nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
+                              params.min_be) ||
+                   nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
+                              params.max_be) ||
+                   nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
+                              params.frame_retries))
+                       goto nla_put_failure;
+       }
+
        wpan_phy_put(phy);
        return genlmsg_end(msg, hdr);
 
@@ -599,3 +625,93 @@ cont:
 
        return skb->len;
 }
+
+int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
+{
+       struct net_device *dev = NULL;
+       struct ieee802154_mlme_ops *ops;
+       struct ieee802154_mac_params params;
+       struct wpan_phy *phy;
+       int rc = -EINVAL;
+
+       pr_debug("%s\n", __func__);
+
+       dev = ieee802154_nl_get_dev(info);
+       if (!dev)
+               return -ENODEV;
+
+       ops = ieee802154_mlme_ops(dev);
+
+       if (!ops->get_mac_params || !ops->set_mac_params) {
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       if (netif_running(dev)) {
+               rc = -EBUSY;
+               goto out;
+       }
+
+       if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
+           !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
+           !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
+           !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
+           !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
+           !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
+           !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
+               goto out;
+
+       phy = ops->get_phy(dev);
+
+       if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
+           (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
+           (!phy->set_cca_ed_level &&
+            info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) ||
+           (!phy->set_csma_params &&
+            (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
+             info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
+             info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) ||
+           (!phy->set_frame_retries &&
+            info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) {
+               rc = -EOPNOTSUPP;
+               goto out_phy;
+       }
+
+       ops->get_mac_params(dev, &params);
+
+       if (info->attrs[IEEE802154_ATTR_TXPOWER])
+               params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
+
+       if (info->attrs[IEEE802154_ATTR_LBT_ENABLED])
+               params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
+
+       if (info->attrs[IEEE802154_ATTR_CCA_MODE])
+               params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
+
+       if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
+               params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
+
+       if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
+               params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
+
+       if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
+               params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
+
+       if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
+               params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
+
+       if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
+               params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
+
+       rc = ops->set_mac_params(dev, &params);
+
+       wpan_phy_put(phy);
+       dev_put(dev);
+       return rc;
+
+out_phy:
+       wpan_phy_put(phy);
+out:
+       dev_put(dev);
+       return rc;
+}
index 222310a07762237cee3f1d339348dc73ab8f6dda..89b265aea151eaf7f301c28f391d064b7d22edfc 100644 (file)
@@ -55,15 +55,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
        mutex_lock(&phy->pib_lock);
        if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
            nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) ||
-           nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) ||
-           nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) ||
-           nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) ||
-           nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode) ||
-           nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, phy->cca_ed_level) ||
-           nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, phy->csma_retries) ||
-           nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, phy->min_be) ||
-           nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, phy->max_be) ||
-           nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, phy->frame_retries))
+           nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
                goto nla_put_failure;
        for (i = 0; i < 32; i++) {
                if (phy->channels_supported[i])
@@ -362,193 +354,3 @@ out_dev:
 
        return rc;
 }
-
-static int phy_set_txpower(struct wpan_phy *phy, struct genl_info *info)
-{
-       int txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
-       int rc;
-
-       rc = phy->set_txpower(phy, txpower);
-       if (rc < 0)
-               return rc;
-
-       phy->transmit_power = txpower;
-
-       return 0;
-}
-
-static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info)
-{
-       u8 on = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
-       int rc;
-
-       rc = phy->set_lbt(phy, on);
-       if (rc < 0)
-               return rc;
-
-       phy->lbt = on;
-
-       return 0;
-}
-
-static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info)
-{
-       u8 mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
-       int rc;
-
-       if (mode > 3)
-               return -EINVAL;
-
-       rc = phy->set_cca_mode(phy, mode);
-       if (rc < 0)
-               return rc;
-
-       phy->cca_mode = mode;
-
-       return 0;
-}
-
-static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info)
-{
-       s32 level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
-       int rc;
-
-       rc = phy->set_cca_ed_level(phy, level);
-       if (rc < 0)
-               return rc;
-
-       phy->cca_ed_level = level;
-
-       return 0;
-}
-
-static int phy_set_csma_params(struct wpan_phy *phy, struct genl_info *info)
-{
-       int rc;
-       u8 min_be = phy->min_be;
-       u8 max_be = phy->max_be;
-       u8 retries = phy->csma_retries;
-
-       if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
-               retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
-       if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
-               min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
-       if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
-               max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
-
-       if (retries > 5 || max_be < 3 || max_be > 8 || min_be > max_be)
-               return -EINVAL;
-
-       rc = phy->set_csma_params(phy, min_be, max_be, retries);
-       if (rc < 0)
-               return rc;
-
-       phy->min_be = min_be;
-       phy->max_be = max_be;
-       phy->csma_retries = retries;
-
-       return 0;
-}
-
-static int phy_set_frame_retries(struct wpan_phy *phy, struct genl_info *info)
-{
-       s8 retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
-       int rc;
-
-       if (retries < -1 || retries > 7)
-               return -EINVAL;
-
-       rc = phy->set_frame_retries(phy, retries);
-       if (rc < 0)
-               return rc;
-
-       phy->frame_retries = retries;
-
-       return 0;
-}
-
-int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
-{
-       struct wpan_phy *phy;
-       const char *name;
-       int rc = -ENOTSUPP;
-
-       pr_debug("%s\n", __func__);
-
-       if (!info->attrs[IEEE802154_ATTR_PHY_NAME] &&
-           !info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
-           !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
-           !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
-           !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
-           !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
-           !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
-           !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
-               return -EINVAL;
-
-       name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
-       if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
-               return -EINVAL; /* phy name should be null-terminated */
-
-       phy = wpan_phy_find(name);
-       if (!phy)
-               return -ENODEV;
-
-       if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) ||
-           (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
-           (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
-           (!phy->set_cca_ed_level &&
-            info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]))
-               goto out;
-
-       mutex_lock(&phy->pib_lock);
-
-       if (info->attrs[IEEE802154_ATTR_TXPOWER]) {
-               rc = phy_set_txpower(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) {
-               rc = phy_set_lbt(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       if (info->attrs[IEEE802154_ATTR_CCA_MODE]) {
-               rc = phy_set_cca_mode(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) {
-               rc = phy_set_cca_ed_level(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
-           info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
-           info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) {
-               rc = phy_set_csma_params(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) {
-               rc = phy_set_frame_retries(phy, info);
-               if (rc < 0)
-                       goto error;
-       }
-
-       mutex_unlock(&phy->pib_lock);
-
-       wpan_phy_put(phy);
-
-       return 0;
-
-error:
-       mutex_unlock(&phy->pib_lock);
-out:
-       wpan_phy_put(phy);
-       return rc;
-}
index edd0962d55f9a14a18c8901ffa0fa32432c1fcf6..8d6f6704da84e8b95745cedb7040230cb5b96cb1 100644 (file)
@@ -169,12 +169,6 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size)
        phy->current_channel = -1; /* not initialised */
        phy->current_page = 0; /* for compatibility */
 
-       /* defaults per 802.15.4-2011 */
-       phy->min_be = 3;
-       phy->max_be = 5;
-       phy->csma_retries = 4;
-       phy->frame_retries = -1; /* for compatibility, actual default is 3 */
-
        return phy;
 
 out:
index e7aa76445fe1501698984e1666d048f4d900d17d..2cf66d885e68f38360cfb1ced1a08a924b342d22 100644 (file)
@@ -197,9 +197,6 @@ static int mac802154_set_txpower(struct wpan_phy *phy, int db)
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_txpower)
-               return -ENOTSUPP;
-
        return priv->ops->set_txpower(&priv->hw, db);
 }
 
@@ -207,9 +204,6 @@ static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_lbt)
-               return -ENOTSUPP;
-
        return priv->ops->set_lbt(&priv->hw, on);
 }
 
@@ -217,9 +211,6 @@ static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_cca_mode)
-               return -ENOTSUPP;
-
        return priv->ops->set_cca_mode(&priv->hw, mode);
 }
 
@@ -227,9 +218,6 @@ static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_cca_ed_level)
-               return -ENOTSUPP;
-
        return priv->ops->set_cca_ed_level(&priv->hw, level);
 }
 
@@ -238,9 +226,6 @@ static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_csma_params)
-               return -ENOTSUPP;
-
        return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
 }
 
@@ -248,9 +233,6 @@ static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
 {
        struct mac802154_priv *priv = wpan_phy_priv(phy);
 
-       if (!priv->ops->set_frame_retries)
-               return -ENOTSUPP;
-
        return priv->ops->set_frame_retries(&priv->hw, retries);
 }
 
@@ -331,12 +313,18 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
 
        priv->phy->add_iface = mac802154_add_iface;
        priv->phy->del_iface = mac802154_del_iface;
-       priv->phy->set_txpower = mac802154_set_txpower;
-       priv->phy->set_lbt = mac802154_set_lbt;
-       priv->phy->set_cca_mode = mac802154_set_cca_mode;
-       priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
-       priv->phy->set_csma_params = mac802154_set_csma_params;
-       priv->phy->set_frame_retries = mac802154_set_frame_retries;
+       if (priv->ops->set_txpower)
+               priv->phy->set_txpower = mac802154_set_txpower;
+       if (priv->ops->set_lbt)
+               priv->phy->set_lbt = mac802154_set_lbt;
+       if (priv->ops->set_cca_mode)
+               priv->phy->set_cca_mode = mac802154_set_cca_mode;
+       if (priv->ops->set_cca_ed_level)
+               priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
+       if (priv->ops->set_csma_params)
+               priv->phy->set_csma_params = mac802154_set_csma_params;
+       if (priv->ops->set_frame_retries)
+               priv->phy->set_frame_retries = mac802154_set_frame_retries;
 
        rc = wpan_phy_register(priv->phy);
        if (rc < 0)
index f40522ef288c76c8f5b22eb8c34b7ca501d264d2..28ef59c566e6ee78df73edd1246d84d4c2c4d912 100644 (file)
@@ -23,6 +23,8 @@
 #ifndef MAC802154_H
 #define MAC802154_H
 
+#include <net/ieee802154_netdev.h>
+
 /* mac802154 device private data */
 struct mac802154_priv {
        struct ieee802154_dev hw;
@@ -82,6 +84,8 @@ struct mac802154_sub_if_data {
        u8 chan;
        u8 page;
 
+       struct ieee802154_mac_params mac_params;
+
        /* MAC BSN field */
        u8 bsn;
        /* MAC DSN field */
@@ -116,4 +120,9 @@ 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);
 u8 mac802154_dev_get_dsn(const struct net_device *dev);
 
+int mac802154_set_mac_params(struct net_device *dev,
+                            const struct ieee802154_mac_params *params);
+void mac802154_get_mac_params(struct net_device *dev,
+                             struct ieee802154_mac_params *params);
+
 #endif /* MAC802154_H */
index 15bac3358889198e4b34800896bec9fc12163450..d40c0928bc622d5802c9dcd1bdb740150ee06744 100644 (file)
@@ -74,4 +74,7 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
        .get_pan_id = mac802154_dev_get_pan_id,
        .get_short_addr = mac802154_dev_get_short_addr,
        .get_dsn = mac802154_dev_get_dsn,
+
+       .set_mac_params = mac802154_set_mac_params,
+       .get_mac_params = mac802154_get_mac_params,
 };
index 80cbee1a2f567aaf3521419bc13e9beab168bb59..1df7a6a573865b4add87261300cc1d7ff01fa243 100644 (file)
@@ -102,6 +102,87 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
        return 0;
 }
 
+int mac802154_set_mac_params(struct net_device *dev,
+                            const struct ieee802154_mac_params *params)
+{
+       struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+       mutex_lock(&priv->hw->slaves_mtx);
+       priv->mac_params = *params;
+       mutex_unlock(&priv->hw->slaves_mtx);
+
+       return 0;
+}
+
+void mac802154_get_mac_params(struct net_device *dev,
+                             struct ieee802154_mac_params *params)
+{
+       struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+       mutex_lock(&priv->hw->slaves_mtx);
+       *params = priv->mac_params;
+       mutex_unlock(&priv->hw->slaves_mtx);
+}
+
+int mac802154_wpan_open(struct net_device *dev)
+{
+       int rc;
+       struct mac802154_sub_if_data *priv = netdev_priv(dev);
+       struct wpan_phy *phy = priv->hw->phy;
+
+       rc = mac802154_slave_open(dev);
+       if (rc < 0)
+               return rc;
+
+       mutex_lock(&phy->pib_lock);
+
+       if (phy->set_txpower) {
+               rc = phy->set_txpower(phy, priv->mac_params.transmit_power);
+               if (rc < 0)
+                       goto out;
+       }
+
+       if (phy->set_lbt) {
+               rc = phy->set_lbt(phy, priv->mac_params.lbt);
+               if (rc < 0)
+                       goto out;
+       }
+
+       if (phy->set_cca_mode) {
+               rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode);
+               if (rc < 0)
+                       goto out;
+       }
+
+       if (phy->set_cca_ed_level) {
+               rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level);
+               if (rc < 0)
+                       goto out;
+       }
+
+       if (phy->set_csma_params) {
+               rc = phy->set_csma_params(phy, priv->mac_params.min_be,
+                                         priv->mac_params.max_be,
+                                         priv->mac_params.csma_retries);
+               if (rc < 0)
+                       goto out;
+       }
+
+       if (phy->set_frame_retries) {
+               rc = phy->set_frame_retries(phy,
+                                           priv->mac_params.frame_retries);
+               if (rc < 0)
+                       goto out;
+       }
+
+       mutex_unlock(&phy->pib_lock);
+       return 0;
+
+out:
+       mutex_unlock(&phy->pib_lock);
+       return rc;
+}
+
 static int mac802154_header_create(struct sk_buff *skb,
                                   struct net_device *dev,
                                   unsigned short type,
@@ -204,7 +285,7 @@ static struct header_ops mac802154_header_ops = {
 };
 
 static const struct net_device_ops mac802154_wpan_ops = {
-       .ndo_open               = mac802154_slave_open,
+       .ndo_open               = mac802154_wpan_open,
        .ndo_stop               = mac802154_slave_close,
        .ndo_start_xmit         = mac802154_wpan_xmit,
        .ndo_do_ioctl           = mac802154_wpan_ioctl,
@@ -242,6 +323,12 @@ void mac802154_wpan_setup(struct net_device *dev)
        get_random_bytes(&priv->bsn, 1);
        get_random_bytes(&priv->dsn, 1);
 
+       /* defaults per 802.15.4-2011 */
+       priv->mac_params.min_be = 3;
+       priv->mac_params.max_be = 5;
+       priv->mac_params.csma_retries = 4;
+       priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */
+
        priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
        priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
 }