diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-02-17 05:34:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-17 16:42:38 -0500 |
commit | ba08fea53a43e02b590d89224afdad976dece841 (patch) | |
tree | b7cfcfcfc9b923360c477e55df12a501eda169b0 | |
parent | 84dda3c648fd55898064d76366b14f964cdc9d16 (diff) |
ieee802154: add support for CCA mode in wpan phys
The standard describes four modes of clear channel assesment: "energy
above threshold", "carrier found", and the logical and/or of these two.
Support for CCA mode setting is included in the at86rf230 driver,
predicated for RF212 chips.
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 9 | ||||
-rw-r--r-- | include/linux/nl802154.h | 1 | ||||
-rw-r--r-- | include/net/mac802154.h | 5 | ||||
-rw-r--r-- | include/net/wpan-phy.h | 1 | ||||
-rw-r--r-- | net/ieee802154/nl-phy.c | 32 | ||||
-rw-r--r-- | net/ieee802154/nl_policy.c | 1 | ||||
-rw-r--r-- | net/mac802154/ieee802154_dev.c | 11 |
7 files changed, 57 insertions, 3 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 3d40c2350261..c60871aff333 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -794,6 +794,14 @@ at86rf212_set_lbt(struct ieee802154_dev *dev, bool on) | |||
794 | return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on); | 794 | return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on); |
795 | } | 795 | } |
796 | 796 | ||
797 | static int | ||
798 | at86rf212_set_cca_mode(struct ieee802154_dev *dev, u8 mode) | ||
799 | { | ||
800 | struct at86rf230_local *lp = dev->priv; | ||
801 | |||
802 | return at86rf230_write_subreg(lp, SR_CCA_MODE, mode); | ||
803 | } | ||
804 | |||
797 | static struct ieee802154_ops at86rf230_ops = { | 805 | static struct ieee802154_ops at86rf230_ops = { |
798 | .owner = THIS_MODULE, | 806 | .owner = THIS_MODULE, |
799 | .xmit = at86rf230_xmit, | 807 | .xmit = at86rf230_xmit, |
@@ -814,6 +822,7 @@ static struct ieee802154_ops at86rf212_ops = { | |||
814 | .set_hw_addr_filt = at86rf230_set_hw_addr_filt, | 822 | .set_hw_addr_filt = at86rf230_set_hw_addr_filt, |
815 | .set_txpower = at86rf212_set_txpower, | 823 | .set_txpower = at86rf212_set_txpower, |
816 | .set_lbt = at86rf212_set_lbt, | 824 | .set_lbt = at86rf212_set_lbt, |
825 | .set_cca_mode = at86rf212_set_cca_mode, | ||
817 | }; | 826 | }; |
818 | 827 | ||
819 | static void at86rf230_irqwork(struct work_struct *work) | 828 | static void at86rf230_irqwork(struct work_struct *work) |
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h index 326baee227f7..5edefc14bd83 100644 --- a/include/linux/nl802154.h +++ b/include/linux/nl802154.h | |||
@@ -72,6 +72,7 @@ enum { | |||
72 | 72 | ||
73 | IEEE802154_ATTR_TXPOWER, | 73 | IEEE802154_ATTR_TXPOWER, |
74 | IEEE802154_ATTR_LBT_ENABLED, | 74 | IEEE802154_ATTR_LBT_ENABLED, |
75 | IEEE802154_ATTR_CCA_MODE, | ||
75 | 76 | ||
76 | __IEEE802154_ATTR_MAX, | 77 | __IEEE802154_ATTR_MAX, |
77 | }; | 78 | }; |
diff --git a/include/net/mac802154.h b/include/net/mac802154.h index 521edcb0e586..1a98e5014e66 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h | |||
@@ -122,6 +122,10 @@ struct ieee802154_dev { | |||
122 | * Enables or disables listen before talk on the device. Called with | 122 | * Enables or disables listen before talk on the device. Called with |
123 | * pib_lock held. | 123 | * pib_lock held. |
124 | * Returns either zero, or negative errno. | 124 | * Returns either zero, or negative errno. |
125 | * | ||
126 | * set_cca_mode | ||
127 | * Sets the CCA mode used by the device. Called with pib_lock held. | ||
128 | * Returns either zero, or negative errno. | ||
125 | */ | 129 | */ |
126 | struct ieee802154_ops { | 130 | struct ieee802154_ops { |
127 | struct module *owner; | 131 | struct module *owner; |
@@ -140,6 +144,7 @@ struct ieee802154_ops { | |||
140 | u8 addr[IEEE802154_ADDR_LEN]); | 144 | u8 addr[IEEE802154_ADDR_LEN]); |
141 | int (*set_txpower)(struct ieee802154_dev *dev, int db); | 145 | int (*set_txpower)(struct ieee802154_dev *dev, int db); |
142 | int (*set_lbt)(struct ieee802154_dev *dev, bool on); | 146 | int (*set_lbt)(struct ieee802154_dev *dev, bool on); |
147 | int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode); | ||
143 | }; | 148 | }; |
144 | 149 | ||
145 | /* Basic interface to register ieee802154 device */ | 150 | /* Basic interface to register ieee802154 device */ |
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h index 804e6c4f5f8a..03b59051972d 100644 --- a/include/net/wpan-phy.h +++ b/include/net/wpan-phy.h | |||
@@ -58,6 +58,7 @@ struct wpan_phy { | |||
58 | 58 | ||
59 | int (*set_txpower)(struct wpan_phy *phy, int db); | 59 | int (*set_txpower)(struct wpan_phy *phy, int db); |
60 | int (*set_lbt)(struct wpan_phy *phy, bool on); | 60 | int (*set_lbt)(struct wpan_phy *phy, bool on); |
61 | int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode); | ||
61 | 62 | ||
62 | char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 63 | char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); |
63 | }; | 64 | }; |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index f029310b0662..36f58d633868 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -57,7 +57,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, | |||
57 | nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || | 57 | nla_put_u8(msg, IEEE802154_ATTR_PAGE, phy->current_page) || |
58 | nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) || | 58 | nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel) || |
59 | nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) || | 59 | nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, phy->transmit_power) || |
60 | nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt)) | 60 | nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, phy->lbt) || |
61 | nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, phy->cca_mode)) | ||
61 | goto nla_put_failure; | 62 | goto nla_put_failure; |
62 | for (i = 0; i < 32; i++) { | 63 | for (i = 0; i < 32; i++) { |
63 | if (phy->channels_supported[i]) | 64 | if (phy->channels_supported[i]) |
@@ -385,6 +386,23 @@ static int phy_set_lbt(struct wpan_phy *phy, struct genl_info *info) | |||
385 | return 0; | 386 | return 0; |
386 | } | 387 | } |
387 | 388 | ||
389 | static int phy_set_cca_mode(struct wpan_phy *phy, struct genl_info *info) | ||
390 | { | ||
391 | u8 mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]); | ||
392 | int rc; | ||
393 | |||
394 | if (mode > 3) | ||
395 | return -EINVAL; | ||
396 | |||
397 | rc = phy->set_cca_mode(phy, mode); | ||
398 | if (rc < 0) | ||
399 | return rc; | ||
400 | |||
401 | phy->cca_mode = mode; | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | |||
388 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | 406 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) |
389 | { | 407 | { |
390 | struct wpan_phy *phy; | 408 | struct wpan_phy *phy; |
@@ -394,7 +412,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | |||
394 | pr_debug("%s\n", __func__); | 412 | pr_debug("%s\n", __func__); |
395 | 413 | ||
396 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME] && | 414 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME] && |
397 | !info->attrs[IEEE802154_ATTR_LBT_ENABLED]) | 415 | !info->attrs[IEEE802154_ATTR_LBT_ENABLED] && |
416 | !info->attrs[IEEE802154_ATTR_CCA_MODE]) | ||
398 | return -EINVAL; | 417 | return -EINVAL; |
399 | 418 | ||
400 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | 419 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); |
@@ -406,7 +425,8 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | |||
406 | return -ENODEV; | 425 | return -ENODEV; |
407 | 426 | ||
408 | if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) || | 427 | if ((!phy->set_txpower && info->attrs[IEEE802154_ATTR_TXPOWER]) || |
409 | (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED])) | 428 | (!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) || |
429 | (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE])) | ||
410 | goto out; | 430 | goto out; |
411 | 431 | ||
412 | mutex_lock(&phy->pib_lock); | 432 | mutex_lock(&phy->pib_lock); |
@@ -423,6 +443,12 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | |||
423 | goto error; | 443 | goto error; |
424 | } | 444 | } |
425 | 445 | ||
446 | if (info->attrs[IEEE802154_ATTR_CCA_MODE]) { | ||
447 | rc = phy_set_cca_mode(phy, info); | ||
448 | if (rc < 0) | ||
449 | goto error; | ||
450 | } | ||
451 | |||
426 | mutex_unlock(&phy->pib_lock); | 452 | mutex_unlock(&phy->pib_lock); |
427 | 453 | ||
428 | wpan_phy_put(phy); | 454 | wpan_phy_put(phy); |
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index a09f6423a6e9..d87c2c904110 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c | |||
@@ -55,5 +55,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { | |||
55 | 55 | ||
56 | [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, }, | 56 | [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, }, |
57 | [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, }, | 57 | [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, }, |
58 | [IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, }, | ||
58 | }; | 59 | }; |
59 | 60 | ||
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 56338c8cfc33..4965e4ce6b5b 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c | |||
@@ -185,6 +185,16 @@ static int mac802154_set_lbt(struct wpan_phy *phy, bool on) | |||
185 | return priv->ops->set_lbt(&priv->hw, on); | 185 | return priv->ops->set_lbt(&priv->hw, on); |
186 | } | 186 | } |
187 | 187 | ||
188 | static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode) | ||
189 | { | ||
190 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
191 | |||
192 | if (!priv->ops->set_cca_mode) | ||
193 | return -ENOTSUPP; | ||
194 | |||
195 | return priv->ops->set_cca_mode(&priv->hw, mode); | ||
196 | } | ||
197 | |||
188 | struct ieee802154_dev * | 198 | struct ieee802154_dev * |
189 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) | 199 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) |
190 | { | 200 | { |
@@ -264,6 +274,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev) | |||
264 | priv->phy->del_iface = mac802154_del_iface; | 274 | priv->phy->del_iface = mac802154_del_iface; |
265 | priv->phy->set_txpower = mac802154_set_txpower; | 275 | priv->phy->set_txpower = mac802154_set_txpower; |
266 | priv->phy->set_lbt = mac802154_set_lbt; | 276 | priv->phy->set_lbt = mac802154_set_lbt; |
277 | priv->phy->set_cca_mode = mac802154_set_cca_mode; | ||
267 | 278 | ||
268 | rc = wpan_phy_register(priv->phy); | 279 | rc = wpan_phy_register(priv->phy); |
269 | if (rc < 0) | 280 | if (rc < 0) |