Skip to content

Commit

Permalink
Merge branch 'ieee802154'
Browse files Browse the repository at this point in the history
Phoebe Buckheister says:

====================
ieee802154: support rf212 and extended mac features

this patch set adds support for the RF212 radio chip to the existing
at86rf230 driver and adds support for numerous features of the RF212
chips to the ieee802154 stack. These features include CSMA parameter
configuration, transmit power control, CCA parameter configuration, and
automatic retransmission of frames. Netlink APIs are provided for all
new options introduced in this set.

Many features might also work for RF230, but since I have no such chips
at my disposal, most new features are implemented only for RF212.

Changes since v2:
 * Indentation
Changes since v1:
 * CodingStyle compliance. Thanks Sergei Shtylyov
 * Add CSMA parameters to netlink phy list that were forgotten in v1
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 17, 2014
2 parents 92e8c83 + f2fdd67 commit e035b8a
Show file tree
Hide file tree
Showing 10 changed files with 668 additions and 118 deletions.
433 changes: 321 additions & 112 deletions drivers/net/ieee802154/at86rf230.c

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions include/linux/nl802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ enum {
IEEE802154_ATTR_PHY_NAME,
IEEE802154_ATTR_DEV_TYPE,

IEEE802154_ATTR_TXPOWER,
IEEE802154_ATTR_LBT_ENABLED,
IEEE802154_ATTR_CCA_MODE,
IEEE802154_ATTR_CCA_ED_LEVEL,
IEEE802154_ATTR_CSMA_RETRIES,
IEEE802154_ATTR_CSMA_MIN_BE,
IEEE802154_ATTR_CSMA_MAX_BE,

IEEE802154_ATTR_FRAME_RETRIES,

__IEEE802154_ATTR_MAX,
};

Expand Down Expand Up @@ -122,6 +132,8 @@ enum {
IEEE802154_ADD_IFACE,
IEEE802154_DEL_IFACE,

IEEE802154_SET_PHYPARAMS,

__IEEE802154_CMD_MAX,
};

Expand Down
35 changes: 35 additions & 0 deletions include/net/mac802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ struct ieee802154_dev {
* Set radio for listening on specific address.
* Set the device for listening on specified address.
* Returns either zero, or negative errno.
*
* set_txpower:
* Set radio transmit power in dB. Called with pib_lock held.
* Returns either zero, or negative errno.
*
* set_lbt
* Enables or disables listen before talk on the device. Called with
* pib_lock held.
* Returns either zero, or negative errno.
*
* set_cca_mode
* Sets the CCA mode used by the device. Called with pib_lock held.
* Returns either zero, or negative errno.
*
* set_cca_ed_level
* Sets the CCA energy detection threshold in dBm. Called with pib_lock
* held.
* Returns either zero, or negative errno.
*
* set_csma_params
* Sets the CSMA parameter set for the PHY. Called with pib_lock held.
* Returns either zero, or negative errno.
*
* set_frame_retries
* Sets the retransmission attempt limit. Called with pib_lock held.
* Returns either zero, or negative errno.
*/
struct ieee802154_ops {
struct module *owner;
Expand All @@ -129,6 +155,15 @@ struct ieee802154_ops {
unsigned long changed);
int (*ieee_addr)(struct ieee802154_dev *dev,
u8 addr[IEEE802154_ADDR_LEN]);
int (*set_txpower)(struct ieee802154_dev *dev, int db);
int (*set_lbt)(struct ieee802154_dev *dev, bool on);
int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
int (*set_cca_ed_level)(struct ieee802154_dev *dev,
s32 level);
int (*set_csma_params)(struct ieee802154_dev *dev,
u8 min_be, u8 max_be, u8 retries);
int (*set_frame_retries)(struct ieee802154_dev *dev,
s8 retries);
};

/* Basic interface to register ieee802154 device */
Expand Down
19 changes: 17 additions & 2 deletions include/net/wpan-phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,22 @@ struct wpan_phy {
struct mutex pib_lock;

/*
* This is a PIB according to 802.15.4-2006.
* This is a PIB according to 802.15.4-2011.
* We do not provide timing-related variables, as they
* aren't used outside of driver
*/
u8 current_channel;
u8 current_page;
u32 channels_supported[32];
u8 transmit_power;
s8 transmit_power;
u8 cca_mode;
u8 min_be;
u8 max_be;
u8 csma_retries;
s8 frame_retries;

bool lbt;
s32 cca_ed_level;

struct device dev;
int idx;
Expand All @@ -54,6 +61,14 @@ struct wpan_phy {
const char *name, int type);
void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);

int (*set_txpower)(struct wpan_phy *phy, int db);
int (*set_lbt)(struct wpan_phy *phy, bool on);
int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
u8 retries);
int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);

char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
};

Expand Down
1 change: 1 addition & 0 deletions net/ieee802154/ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ 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,
Expand Down
1 change: 1 addition & 0 deletions net/ieee802154/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ 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),
Expand Down
198 changes: 197 additions & 1 deletion net/ieee802154/nl-phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ 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_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))
goto nla_put_failure;
for (i = 0; i < 32; i++) {
if (phy->channels_supported[i])
Expand Down Expand Up @@ -354,3 +362,191 @@ int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info)

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 > 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;
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;
}
10 changes: 10 additions & 0 deletions net/ieee802154/nl_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,15 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = {
[IEEE802154_ATTR_DURATION] = { .type = NLA_U8, },
[IEEE802154_ATTR_ED_LIST] = { .len = 27 },
[IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, },

[IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, },
[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, },
};

10 changes: 7 additions & 3 deletions net/ieee802154/wpan-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ static DEVICE_ATTR_RO(name);

MASTER_SHOW(current_channel, "%d");
MASTER_SHOW(current_page, "%d");
MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB",
((signed char) (phy->transmit_power << 2)) >> 2,
(phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1);
MASTER_SHOW(transmit_power, "%d +- 1 dB");
MASTER_SHOW(cca_mode, "%d");

static ssize_t channels_supported_show(struct device *dev,
Expand Down Expand Up @@ -171,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:
Expand Down
Loading

0 comments on commit e035b8a

Please sign in to comment.