diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-02-17 05:34:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-17 16:42:38 -0500 |
commit | 9b2777d6089bcd7fb035847f907280560fe233c8 (patch) | |
tree | 868e579924e3c6cd154996acfef67fb9157e8b26 /net | |
parent | 5b520bbb538da7f7122b1e5dc85f2b4c592d4781 (diff) |
ieee802154: add TX power control to wpan_phy
Replace the current u8 transmit_power in wpan_phy with s8 transmit_power.
The u8 field contained the actual tx power and a tolerance field,
which no physical radio every used. Adjust sysfs entries to keep
compatibility with userspace, give tolerances of +-1dB statically there.
This patch only adds support for this in the at86rf230 driver and the
RF212 chip. Configuration calculation for RF212 is also somewhat basic,
but does the job - the RF212 datasheet gives a large table with
suggested values for combinations of TX power and page/channel, if this
does not work well, we might have to copy the whole table.
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ieee802154/ieee802154.h | 1 | ||||
-rw-r--r-- | net/ieee802154/netlink.c | 1 | ||||
-rw-r--r-- | net/ieee802154/nl-phy.c | 49 | ||||
-rw-r--r-- | net/ieee802154/nl_policy.c | 2 | ||||
-rw-r--r-- | net/ieee802154/wpan-class.c | 4 | ||||
-rw-r--r-- | net/mac802154/ieee802154_dev.c | 11 |
6 files changed, 64 insertions, 4 deletions
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h index cee4425b9956..6cbc8965be91 100644 --- a/net/ieee802154/ieee802154.h +++ b/net/ieee802154/ieee802154.h | |||
@@ -53,6 +53,7 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info); | |||
53 | int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb); | 53 | int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb); |
54 | int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info); | 54 | int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info); |
55 | int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info); | 55 | int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info); |
56 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info); | ||
56 | 57 | ||
57 | enum ieee802154_mcgrp_ids { | 58 | enum ieee802154_mcgrp_ids { |
58 | IEEE802154_COORD_MCGRP, | 59 | IEEE802154_COORD_MCGRP, |
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 43f1b2bf469f..67c151bf4b91 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c | |||
@@ -115,6 +115,7 @@ static const struct genl_ops ieee8021154_ops[] = { | |||
115 | ieee802154_dump_phy), | 115 | ieee802154_dump_phy), |
116 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), | 116 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), |
117 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), | 117 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), |
118 | IEEE802154_OP(IEEE802154_SET_PHYPARAMS, ieee802154_set_phyparams), | ||
118 | /* see nl-mac.c */ | 119 | /* see nl-mac.c */ |
119 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), | 120 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), |
120 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), | 121 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 89b265aea151..d3ee62fbae99 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -55,7 +55,8 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, | |||
55 | mutex_lock(&phy->pib_lock); | 55 | mutex_lock(&phy->pib_lock); |
56 | if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || | 56 | if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || |
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 | goto nla_put_failure; | 60 | goto nla_put_failure; |
60 | for (i = 0; i < 32; i++) { | 61 | for (i = 0; i < 32; i++) { |
61 | if (phy->channels_supported[i]) | 62 | if (phy->channels_supported[i]) |
@@ -354,3 +355,49 @@ out_dev: | |||
354 | 355 | ||
355 | return rc; | 356 | return rc; |
356 | } | 357 | } |
358 | |||
359 | int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info) | ||
360 | { | ||
361 | struct wpan_phy *phy; | ||
362 | const char *name; | ||
363 | int txpower; | ||
364 | int rc = -EINVAL; | ||
365 | |||
366 | pr_debug("%s\n", __func__); | ||
367 | |||
368 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME]) | ||
369 | return -EINVAL; | ||
370 | |||
371 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | ||
372 | if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0') | ||
373 | return -EINVAL; /* phy name should be null-terminated */ | ||
374 | |||
375 | txpower = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); | ||
376 | |||
377 | phy = wpan_phy_find(name); | ||
378 | if (!phy) | ||
379 | return -ENODEV; | ||
380 | |||
381 | if (!phy->set_txpower) | ||
382 | goto out; | ||
383 | |||
384 | mutex_lock(&phy->pib_lock); | ||
385 | |||
386 | rc = phy->set_txpower(phy, txpower); | ||
387 | if (rc < 0) { | ||
388 | mutex_unlock(&phy->pib_lock); | ||
389 | goto out; | ||
390 | } | ||
391 | |||
392 | phy->transmit_power = txpower; | ||
393 | |||
394 | mutex_unlock(&phy->pib_lock); | ||
395 | |||
396 | wpan_phy_put(phy); | ||
397 | |||
398 | return 0; | ||
399 | |||
400 | out: | ||
401 | wpan_phy_put(phy); | ||
402 | return rc; | ||
403 | } | ||
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 6adda4d46f95..90b1d0d2c14e 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c | |||
@@ -52,5 +52,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { | |||
52 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, | 52 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, |
53 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, | 53 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, |
54 | [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, | 54 | [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, |
55 | |||
56 | [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, }, | ||
55 | }; | 57 | }; |
56 | 58 | ||
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 4dd37615a749..8d6f6704da84 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c | |||
@@ -44,9 +44,7 @@ static DEVICE_ATTR_RO(name); | |||
44 | 44 | ||
45 | MASTER_SHOW(current_channel, "%d"); | 45 | MASTER_SHOW(current_channel, "%d"); |
46 | MASTER_SHOW(current_page, "%d"); | 46 | MASTER_SHOW(current_page, "%d"); |
47 | MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB", | 47 | MASTER_SHOW(transmit_power, "%d +- 1 dB"); |
48 | ((signed char) (phy->transmit_power << 2)) >> 2, | ||
49 | (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1); | ||
50 | MASTER_SHOW(cca_mode, "%d"); | 48 | MASTER_SHOW(cca_mode, "%d"); |
51 | 49 | ||
52 | static ssize_t channels_supported_show(struct device *dev, | 50 | static ssize_t channels_supported_show(struct device *dev, |
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 52ae6646a411..9eb49e0886a4 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c | |||
@@ -165,6 +165,16 @@ err: | |||
165 | return ERR_PTR(err); | 165 | return ERR_PTR(err); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int mac802154_set_txpower(struct wpan_phy *phy, int db) | ||
169 | { | ||
170 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
171 | |||
172 | if (!priv->ops->set_txpower) | ||
173 | return -ENOTSUPP; | ||
174 | |||
175 | return priv->ops->set_txpower(&priv->hw, db); | ||
176 | } | ||
177 | |||
168 | struct ieee802154_dev * | 178 | struct ieee802154_dev * |
169 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) | 179 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) |
170 | { | 180 | { |
@@ -242,6 +252,7 @@ int ieee802154_register_device(struct ieee802154_dev *dev) | |||
242 | 252 | ||
243 | priv->phy->add_iface = mac802154_add_iface; | 253 | priv->phy->add_iface = mac802154_add_iface; |
244 | priv->phy->del_iface = mac802154_del_iface; | 254 | priv->phy->del_iface = mac802154_del_iface; |
255 | priv->phy->set_txpower = mac802154_set_txpower; | ||
245 | 256 | ||
246 | rc = wpan_phy_register(priv->phy); | 257 | rc = wpan_phy_register(priv->phy); |
247 | if (rc < 0) | 258 | if (rc < 0) |