From 84dda3c648fd55898064d76366b14f964cdc9d16 Mon Sep 17 00:00:00 2001 From: Phoebe Buckheister Date: Mon, 17 Feb 2014 11:34:10 +0100 Subject: ieee802154: add support for listen-before-talk in wpan_phy Listen-before-talk is an alternative to CSMA in uncoordinated networks and prescribed by european regulations if one wants to have a device with radio duty cycles above 10% (or less in some bands). Add a phy property to enable/disable LBT in the phy, including support in the at86rf230 driver for RF212 chips. Signed-off-by: Phoebe Buckheister Signed-off-by: David S. Miller --- net/ieee802154/nl-phy.c | 58 ++++++++++++++++++++++++++++++++++++---------- net/ieee802154/nl_policy.c | 1 + 2 files changed, 47 insertions(+), 12 deletions(-) (limited to 'net/ieee802154') diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index d3ee62fbae99..f029310b0662 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c @@ -56,7 +56,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, 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_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) || + nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt)) goto nla_put_failure; for (i = 0; i < 32; i++) { if (phy->channels_supported[i]) @@ -356,40 +357,71 @@ 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; +} + int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) { struct wpan_phy *phy; const char *name; - int txpower; - int rc = -EINVAL; + int rc = -ENOTSUPP; pr_debug("%s\n", __func__); - if (!info->attrs[IEEE802154_ATTR_PHY_NAME]) + if (!info->attrs[IEEE802154_ATTR_PHY_NAME] && + !info->attrs[IEEE802154_ATTR_LBT_ENABLED]) 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 */ - txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); - phy = wpan_phy_find(name); if (!phy) return -ENODEV; - if (!phy->set_txpower) + if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) || + (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED])) goto out; mutex_lock(&phy->pib_lock); - rc = phy->set_txpower(phy, txpower); - if (rc < 0) { - mutex_unlock(&phy->pib_lock); - goto out; + if (info->attrs[IEEE802154_ATTR_TXPOWER]) { + rc = phy_set_txpower(phy, info); + if (rc < 0) + goto error; } - phy->transmit_power = txpower; + if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) { + rc = phy_set_lbt(phy, info); + if (rc < 0) + goto error; + } mutex_unlock(&phy->pib_lock); @@ -397,6 +429,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) return 0; +error: + mutex_unlock(&phy->pib_lock); out: wpan_phy_put(phy); return rc; diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 90b1d0d2c14e..a09f6423a6e9 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c @@ -54,5 +54,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, }, + [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, }, }; -- cgit v1.2.3-59-g8ed1b