diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ieee802154/nl-phy.c | 69 | ||||
-rw-r--r-- | net/ieee802154/nl_policy.c | 5 | ||||
-rw-r--r-- | net/ieee802154/wpan-class.c | 6 | ||||
-rw-r--r-- | net/mac802154/ieee802154_dev.c | 23 |
4 files changed, 101 insertions, 2 deletions
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 0af0d424dee0..c9dfd6f59e34 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -59,7 +59,11 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, 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_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)) goto nla_put_failure; for (i = 0; i < 32; i++) { if (phy->channels_supported[i]) @@ -418,6 +422,49 @@ static int phy_set_cca_ed_level(struct wpan_phy *phy, struct genl_info *info) 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 > 8 || min_be > max_be || + retries < -1 || retries > 7) + 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; + + 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; @@ -429,7 +476,11 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) 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_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]); @@ -473,6 +524,20 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) 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); diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 55b5616295ff..fd7be5e45cef 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c @@ -57,5 +57,10 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, }, [IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, }, [IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, }, + [IEEE802154_ATTR_CSMA_RETRIES] = { .type = NLA_U8, }, + [IEEE802154_ATTR_CSMA_MIN_BE] = { .type = NLA_U8, }, + [IEEE802154_ATTR_CSMA_MAX_BE] = { .type = NLA_U8, }, + + [IEEE802154_ATTR_FRAME_RETRIES] = { .type = NLA_S8, }, }; diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 8d6f6704da84..edd0962d55f9 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c @@ -169,6 +169,12 @@ 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: diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 4707f36546d3..b75bb01e5c6b 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c @@ -205,6 +205,27 @@ static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level) return priv->ops->set_cca_ed_level(&priv->hw, level); } +static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be, + u8 max_be, u8 retries) +{ + 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); +} + +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); +} + struct ieee802154_dev * ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) { @@ -286,6 +307,8 @@ int ieee802154_register_device(struct ieee802154_dev *dev) 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; rc = wpan_phy_register(priv->phy); if (rc < 0) |