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,
};
* 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;
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 */
u32 channels_supported[32];
s8 transmit_power;
u8 cca_mode;
+ u8 min_be;
+ u8 max_be;
+ u8 csma_retries;
+ s8 frame_retries;
bool lbt;
s32 cca_ed_level;
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)));
};
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_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])
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;
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_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]);
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);
[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, },
};
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:
return priv->ops->set_cca_ed_level(&priv->hw, level);
}
+static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
+ u8 max_be, u8 retries)
+{
+ 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);
+}
+
+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);
+}
+
struct ieee802154_dev *
ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
{
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;
rc = wpan_phy_register(priv->phy);
if (rc < 0)