summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl802154.h2
-rw-r--r--include/net/ieee802154_netdev.h17
-rw-r--r--net/ieee802154/ieee802154.h2
-rw-r--r--net/ieee802154/netlink.c2
-rw-r--r--net/ieee802154/nl-mac.c122
-rw-r--r--net/ieee802154/nl-phy.c200
-rw-r--r--net/ieee802154/wpan-class.c6
-rw-r--r--net/mac802154/ieee802154_dev.c36
-rw-r--r--net/mac802154/mac802154.h9
-rw-r--r--net/mac802154/mac_cmd.c3
-rw-r--r--net/mac802154/wpan.c89
11 files changed, 252 insertions, 236 deletions
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index e110b8c266f5..c8d7f3965fff 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -132,7 +132,7 @@ enum {
IEEE802154_ADD_IFACE,
IEEE802154_DEL_IFACE,
- IEEE802154_SET_PHYPARAMS,
+ IEEE802154_SET_MACPARAMS,
__IEEE802154_CMD_MAX,
};
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index e1717cbf609b..5a719ca892f4 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -229,6 +229,18 @@ static inline int mac_cb_type(struct sk_buff *skb)
#define IEEE802154_MAC_SCAN_PASSIVE 2
#define IEEE802154_MAC_SCAN_ORPHAN 3
+struct ieee802154_mac_params {
+ s8 transmit_power;
+ u8 min_be;
+ u8 max_be;
+ u8 csma_retries;
+ s8 frame_retries;
+
+ bool lbt;
+ u8 cca_mode;
+ s32 cca_ed_level;
+};
+
struct wpan_phy;
/*
* This should be located at net_device->ml_priv
@@ -255,6 +267,11 @@ struct ieee802154_mlme_ops {
int (*scan_req)(struct net_device *dev,
u8 type, u32 channels, u8 page, u8 duration);
+ int (*set_mac_params)(struct net_device *dev,
+ const struct ieee802154_mac_params *params);
+ void (*get_mac_params)(struct net_device *dev,
+ struct ieee802154_mac_params *params);
+
/* The fields below are required. */
struct wpan_phy *(*get_phy)(const struct net_device *dev);
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index 6cbc8965be91..6693a5cf01ce 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -53,7 +53,6 @@ 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,
@@ -67,5 +66,6 @@ int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info);
int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info);
int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info);
int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb);
+int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info);
#endif
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 67c151bf4b91..04b20589d97a 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -115,7 +115,6 @@ 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),
@@ -124,6 +123,7 @@ static const struct genl_ops ieee8021154_ops[] = {
IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req),
IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
ieee802154_dump_iface),
+ IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
};
static const struct genl_multicast_group ieee802154_mcgrps[] = {
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index bda8dba4f993..5d285498c0f6 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -264,6 +264,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
{
void *hdr;
struct wpan_phy *phy;
+ struct ieee802154_mlme_ops *ops;
__le16 short_addr, pan_id;
pr_debug("%s\n", __func__);
@@ -273,11 +274,12 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
if (!hdr)
goto out;
- phy = ieee802154_mlme_ops(dev)->get_phy(dev);
+ ops = ieee802154_mlme_ops(dev);
+ phy = ops->get_phy(dev);
BUG_ON(!phy);
- short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
- pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
+ short_addr = ops->get_short_addr(dev);
+ pan_id = ops->get_pan_id(dev);
if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
@@ -287,6 +289,30 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
goto nla_put_failure;
+
+ if (ops->get_mac_params) {
+ struct ieee802154_mac_params params;
+
+ ops->get_mac_params(dev, &params);
+
+ if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
+ params.transmit_power) ||
+ nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
+ nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
+ params.cca_mode) ||
+ nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
+ params.cca_ed_level) ||
+ nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
+ params.csma_retries) ||
+ nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
+ params.min_be) ||
+ nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
+ params.max_be) ||
+ nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
+ params.frame_retries))
+ goto nla_put_failure;
+ }
+
wpan_phy_put(phy);
return genlmsg_end(msg, hdr);
@@ -599,3 +625,93 @@ cont:
return skb->len;
}
+
+int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net_device *dev = NULL;
+ struct ieee802154_mlme_ops *ops;
+ struct ieee802154_mac_params params;
+ struct wpan_phy *phy;
+ int rc = -EINVAL;
+
+ pr_debug("%s\n", __func__);
+
+ dev = ieee802154_nl_get_dev(info);
+ if (!dev)
+ return -ENODEV;
+
+ ops = ieee802154_mlme_ops(dev);
+
+ if (!ops->get_mac_params || !ops->set_mac_params) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (netif_running(dev)) {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ if (!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])
+ goto out;
+
+ phy = ops->get_phy(dev);
+
+ if ((!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]) ||
+ (!phy->set_csma_params &&
+ (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
+ info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
+ info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) ||
+ (!phy->set_frame_retries &&
+ info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) {
+ rc = -EOPNOTSUPP;
+ goto out_phy;
+ }
+
+ ops->get_mac_params(dev, &params);
+
+ if (info->attrs[IEEE802154_ATTR_TXPOWER])
+ params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]);
+
+ if (info->attrs[IEEE802154_ATTR_LBT_ENABLED])
+ params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
+
+ if (info->attrs[IEEE802154_ATTR_CCA_MODE])
+ params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
+
+ if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
+ params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]);
+
+ if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
+ params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
+
+ if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
+ params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
+
+ if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
+ params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
+
+ if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
+ params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
+
+ rc = ops->set_mac_params(dev, &params);
+
+ wpan_phy_put(phy);
+ dev_put(dev);
+ return rc;
+
+out_phy:
+ wpan_phy_put(phy);
+out:
+ dev_put(dev);
+ return rc;
+}
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 222310a07762..89b265aea151 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -55,15 +55,7 @@ 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_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))
+ nla_put_u8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel))
goto nla_put_failure;
for (i = 0; i < 32; i++) {
if (phy->channels_supported[i])
@@ -362,193 +354,3 @@ 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;
-}
-
-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 < 3 || max_be > 8 || min_be > max_be)
- 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;
-
- if (retries < -1 || retries > 7)
- return -EINVAL;
-
- 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;
-}
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
index edd0962d55f9..8d6f6704da84 100644
--- a/net/ieee802154/wpan-class.c
+++ b/net/ieee802154/wpan-class.c
@@ -169,12 +169,6 @@ 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 e7aa76445fe1..2cf66d885e68 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -197,9 +197,6 @@ static int mac802154_set_txpower(struct wpan_phy *phy, int db)
{
struct mac802154_priv *priv = wpan_phy_priv(phy);
- if (!priv->ops->set_txpower)
- return -ENOTSUPP;
-
return priv->ops->set_txpower(&priv->hw, db);
}
@@ -207,9 +204,6 @@ static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
{
struct mac802154_priv *priv = wpan_phy_priv(phy);
- if (!priv->ops->set_lbt)
- return -ENOTSUPP;
-
return priv->ops->set_lbt(&priv->hw, on);
}
@@ -217,9 +211,6 @@ static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
{
struct mac802154_priv *priv = wpan_phy_priv(phy);
- if (!priv->ops->set_cca_mode)
- return -ENOTSUPP;
-
return priv->ops->set_cca_mode(&priv->hw, mode);
}
@@ -227,9 +218,6 @@ static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
{
struct mac802154_priv *priv = wpan_phy_priv(phy);
- if (!priv->ops->set_cca_ed_level)
- return -ENOTSUPP;
-
return priv->ops->set_cca_ed_level(&priv->hw, level);
}
@@ -238,9 +226,6 @@ static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
{
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);
}
@@ -248,9 +233,6 @@ 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);
}
@@ -331,12 +313,18 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
priv->phy->add_iface = mac802154_add_iface;
priv->phy->del_iface = mac802154_del_iface;
- priv->phy->set_txpower = mac802154_set_txpower;
- 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;
+ if (priv->ops->set_txpower)
+ priv->phy->set_txpower = mac802154_set_txpower;
+ if (priv->ops->set_lbt)
+ priv->phy->set_lbt = mac802154_set_lbt;
+ if (priv->ops->set_cca_mode)
+ priv->phy->set_cca_mode = mac802154_set_cca_mode;
+ if (priv->ops->set_cca_ed_level)
+ priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
+ if (priv->ops->set_csma_params)
+ priv->phy->set_csma_params = mac802154_set_csma_params;
+ if (priv->ops->set_frame_retries)
+ priv->phy->set_frame_retries = mac802154_set_frame_retries;
rc = wpan_phy_register(priv->phy);
if (rc < 0)
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h
index f40522ef288c..28ef59c566e6 100644
--- a/net/mac802154/mac802154.h
+++ b/net/mac802154/mac802154.h
@@ -23,6 +23,8 @@
#ifndef MAC802154_H
#define MAC802154_H
+#include <net/ieee802154_netdev.h>
+
/* mac802154 device private data */
struct mac802154_priv {
struct ieee802154_dev hw;
@@ -82,6 +84,8 @@ struct mac802154_sub_if_data {
u8 chan;
u8 page;
+ struct ieee802154_mac_params mac_params;
+
/* MAC BSN field */
u8 bsn;
/* MAC DSN field */
@@ -116,4 +120,9 @@ void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val);
void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
u8 mac802154_dev_get_dsn(const struct net_device *dev);
+int mac802154_set_mac_params(struct net_device *dev,
+ const struct ieee802154_mac_params *params);
+void mac802154_get_mac_params(struct net_device *dev,
+ struct ieee802154_mac_params *params);
+
#endif /* MAC802154_H */
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index 15bac3358889..d40c0928bc62 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -74,4 +74,7 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = {
.get_pan_id = mac802154_dev_get_pan_id,
.get_short_addr = mac802154_dev_get_short_addr,
.get_dsn = mac802154_dev_get_dsn,
+
+ .set_mac_params = mac802154_set_mac_params,
+ .get_mac_params = mac802154_get_mac_params,
};
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
index 80cbee1a2f56..1df7a6a57386 100644
--- a/net/mac802154/wpan.c
+++ b/net/mac802154/wpan.c
@@ -102,6 +102,87 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
return 0;
}
+int mac802154_set_mac_params(struct net_device *dev,
+ const struct ieee802154_mac_params *params)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ priv->mac_params = *params;
+ mutex_unlock(&priv->hw->slaves_mtx);
+
+ return 0;
+}
+
+void mac802154_get_mac_params(struct net_device *dev,
+ struct ieee802154_mac_params *params)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ *params = priv->mac_params;
+ mutex_unlock(&priv->hw->slaves_mtx);
+}
+
+int mac802154_wpan_open(struct net_device *dev)
+{
+ int rc;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct wpan_phy *phy = priv->hw->phy;
+
+ rc = mac802154_slave_open(dev);
+ if (rc < 0)
+ return rc;
+
+ mutex_lock(&phy->pib_lock);
+
+ if (phy->set_txpower) {
+ rc = phy->set_txpower(phy, priv->mac_params.transmit_power);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_lbt) {
+ rc = phy->set_lbt(phy, priv->mac_params.lbt);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_cca_mode) {
+ rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_cca_ed_level) {
+ rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_csma_params) {
+ rc = phy->set_csma_params(phy, priv->mac_params.min_be,
+ priv->mac_params.max_be,
+ priv->mac_params.csma_retries);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_frame_retries) {
+ rc = phy->set_frame_retries(phy,
+ priv->mac_params.frame_retries);
+ if (rc < 0)
+ goto out;
+ }
+
+ mutex_unlock(&phy->pib_lock);
+ return 0;
+
+out:
+ mutex_unlock(&phy->pib_lock);
+ return rc;
+}
+
static int mac802154_header_create(struct sk_buff *skb,
struct net_device *dev,
unsigned short type,
@@ -204,7 +285,7 @@ static struct header_ops mac802154_header_ops = {
};
static const struct net_device_ops mac802154_wpan_ops = {
- .ndo_open = mac802154_slave_open,
+ .ndo_open = mac802154_wpan_open,
.ndo_stop = mac802154_slave_close,
.ndo_start_xmit = mac802154_wpan_xmit,
.ndo_do_ioctl = mac802154_wpan_ioctl,
@@ -242,6 +323,12 @@ void mac802154_wpan_setup(struct net_device *dev)
get_random_bytes(&priv->bsn, 1);
get_random_bytes(&priv->dsn, 1);
+ /* defaults per 802.15.4-2011 */
+ priv->mac_params.min_be = 3;
+ priv->mac_params.max_be = 5;
+ priv->mac_params.csma_retries = 4;
+ priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */
+
priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
}