Some RF chips allow automatic retransmissions of frames that are not
ACKed by the receiver within a specific timeframe, and automatically
sending such ACKs to senders that request them. Add two new fields to
struct wpan_phy that describe these two options, and driver support for
at86rf230.

Signed-off-by: Phoebe Buckheister <phoebe.buckheis...@itwm.fraunhofer.de>
---
 drivers/net/ieee802154/at86rf230.c |   23 ++++++++++++++--
 include/linux/nl802154.h           |    2 ++
 include/net/mac802154.h            |   10 +++++++
 include/net/wpan-phy.h             |    4 +++
 net/ieee802154/nl-phy.c            |   51 +++++++++++++++++++++++++++++++++---
 net/ieee802154/nl_policy.c         |    2 ++
 net/mac802154/ieee802154_dev.c     |   16 +++++++++++
 7 files changed, 103 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ieee802154/at86rf230.c 
b/drivers/net/ieee802154/at86rf230.c
index a92c3e8..967453d 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -520,7 +520,8 @@ at86rf230_start(struct ieee802154_dev *dev)
        if (rc)
                return rc;
 
-       return at86rf230_state(dev, STATE_RX_ON);
+       return at86rf230_state(dev, lp->dev->phy->autoack
+                       ? STATE_RX_AACK_ON : STATE_RX_ON);
 }
 
 static void
@@ -601,7 +602,9 @@ at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff 
*skb)
        if (rc)
                goto err_rx;
 
-       rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
+       rc = at86rf230_write_subreg(lp, SR_TRX_CMD,
+               lp->dev->phy->retransmit
+                       ? STATE_TX_ARET_ON : STATE_BUSY_TX);
        if (rc)
                goto err_rx;
 
@@ -772,6 +775,20 @@ at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 
level)
        return rc;
 }
 
+static int
+at86rf230_set_autoack(struct ieee802154_dev *dev, u8 on)
+{
+       // AACK_ON takes effect after next receive
+       return 0;
+}
+
+static int
+at86rf230_set_retransmit(struct ieee802154_dev *dev, u8 on)
+{
+       // TX_ARET takes effect on next transmission
+       return 0;
+}
+
 static struct ieee802154_ops at86rf230_ops = {
        .owner = THIS_MODULE,
        .xmit = at86rf230_xmit,
@@ -784,6 +801,8 @@ static struct ieee802154_ops at86rf230_ops = {
        .set_lbt = at86rf230_set_lbt,
        .set_cca_mode = at86rf230_set_cca_mode,
        .set_cca_ed_level = at86rf230_set_cca_ed_level,
+       .set_autoack = at86rf230_set_autoack,
+       .set_retransmit = at86rf230_set_retransmit,
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 0594a0a..d122656 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -74,6 +74,8 @@ enum {
        IEEE802154_ATTR_LBT_ENABLED,
        IEEE802154_ATTR_CCA_MODE,
        IEEE802154_ATTR_CCA_ED_LEVEL,
+       IEEE802154_ATTR_AUTOACK_ENABLED,
+       IEEE802154_ATTR_RETRANSMIT_ENABLED,
 
        __IEEE802154_ATTR_MAX,
 };
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 1feabc5..4f41ea2 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -129,6 +129,14 @@ struct ieee802154_dev {
  * set_cca_ed_level
  *       Sets the CCA energy detection threshold in dBm.
  *       Returns either zero, or negative errno.
+ *
+ * set_autoack
+ *       Enabled or disables the frame autoack feature of the device
+ *       Returns either zero, or negative errno.
+ *
+ * set_retransmit
+ *       Enable or disable the frame retransmit feature of the device.
+ *       Returns either zero, or negative errno.
  */
 struct ieee802154_ops {
        struct module   *owner;
@@ -150,6 +158,8 @@ struct ieee802154_ops {
        int             (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
        int             (*set_cca_ed_level)(struct ieee802154_dev *dev,
                                            s32 level);
+       int             (*set_autoack)(struct ieee802154_dev *dev, u8 on);
+       int             (*set_retransmit)(struct ieee802154_dev *dev, u8 on);
 };
 
 /* Basic interface to register ieee802154 device */
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 79923c6..347cf5d 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -48,6 +48,8 @@ struct wpan_phy {
        u8 cca_mode;
 
        u8 lbt:1;
+       u8 autoack:1;
+       u8 retransmit:1;
        s32 cca_ed_level;
 
        struct device dev;
@@ -61,6 +63,8 @@ struct wpan_phy {
        int (*set_lbt)(struct wpan_phy *phy, u8 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_autoack)(struct wpan_phy *phy, u8 on);
+       int (*set_retransmit)(struct wpan_phy *phy, u8 on);
 
        char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
 };
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 24922fe..3189d88 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -60,7 +60,10 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 
portid,
                    ((signed char) (phy->transmit_power << 2)) >> 2) ||
            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_AUTOACK_ENABLED, phy->autoack) ||
+           nla_put_u8(msg, IEEE802154_ATTR_RETRANSMIT_ENABLED,
+                   phy->retransmit))
                goto nla_put_failure;
        for (i = 0; i < 32; i++) {
                if (phy->channels_supported[i])
@@ -425,6 +428,34 @@ static int phy_set_cca_ed_level(struct wpan_phy *phy, 
struct genl_info *info)
        return 0;
 }
 
+static int phy_set_autoack(struct wpan_phy *phy, struct genl_info *info)
+{
+       u8 on = nla_get_u8(info->attrs[IEEE802154_ATTR_AUTOACK_ENABLED]);
+       int rc;
+
+       rc = phy->set_autoack(phy, !!on);
+       if (rc < 0)
+               return rc;
+
+       phy->autoack = !!on;
+
+       return 0;
+}
+
+static int phy_set_retransmit(struct wpan_phy *phy, struct genl_info *info)
+{
+       u8 on = nla_get_u8(info->attrs[IEEE802154_ATTR_RETRANSMIT_ENABLED]);
+       int rc;
+
+       rc = phy->set_retransmit(phy, !!on);
+       if (rc < 0)
+               return rc;
+
+       phy->retransmit = !!on;
+
+       return 0;
+}
+
 int ieee802154_set_phyparams(struct sk_buff *skb, struct genl_info *info)
 {
        struct wpan_phy *phy;
@@ -436,7 +467,9 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct 
genl_info *info)
        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_AUTOACK_ENABLED] &&
+               !info->attrs[IEEE802154_ATTR_RETRANSMIT_ENABLED])
                return -EINVAL;
 
        name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]);
@@ -451,7 +484,11 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct 
genl_info *info)
                (!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]))
+                       info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) ||
+               (!phy->set_autoack &&
+                       info->attrs[IEEE802154_ATTR_AUTOACK_ENABLED]) ||
+               (!phy->set_retransmit &&
+                       info->attrs[IEEE802154_ATTR_RETRANSMIT_ENABLED]))
                goto out;
 
        if (info->attrs[IEEE802154_ATTR_TXPOWER] &&
@@ -470,6 +507,14 @@ int ieee802154_set_phyparams(struct sk_buff *skb, struct 
genl_info *info)
                (rc = phy_set_cca_ed_level(phy, info)) < 0)
                goto out;
 
+       if (info->attrs[IEEE802154_ATTR_AUTOACK_ENABLED] &&
+               (rc = phy_set_autoack(phy, info)) < 0)
+               goto out;
+
+       if (info->attrs[IEEE802154_ATTR_RETRANSMIT_ENABLED] &&
+               (rc = phy_set_retransmit(phy, info)) < 0)
+               goto out;
+
        wpan_phy_put(phy);
 
        return 0;
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index c8a8687..d210cec 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -57,5 +57,7 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX 
+ 1] = {
        [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, },
        [IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
        [IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
+       [IEEE802154_ATTR_AUTOACK_ENABLED] = { .type = NLA_U8, },
+       [IEEE802154_ATTR_RETRANSMIT_ENABLED] = { .type = NLA_U8, },
 };
 
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
index 5f877b7..64fd663 100644
--- a/net/mac802154/ieee802154_dev.c
+++ b/net/mac802154/ieee802154_dev.c
@@ -193,6 +193,20 @@ static int mac802154_set_cca_ed_level(struct wpan_phy 
*phy, s32 level)
        return priv->ops->set_cca_ed_level(&priv->hw, level);
 }
 
+static int mac802154_set_autoack(struct wpan_phy *phy, u8 on)
+{
+       struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+       return priv->ops->set_autoack(&priv->hw, on);
+}
+
+static int mac802154_set_retransmit(struct wpan_phy *phy, u8 on)
+{
+       struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+       return priv->ops->set_retransmit(&priv->hw, on);
+}
+
 struct ieee802154_dev *
 ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
 {
@@ -274,6 +288,8 @@ int ieee802154_register_device(struct ieee802154_dev *dev)
        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_autoack = mac802154_set_autoack;
+       priv->phy->set_retransmit = mac802154_set_retransmit;
 
        rc = wpan_phy_register(priv->phy);
        if (rc < 0)
-- 
1.7.9.5


------------------------------------------------------------------------------
CenturyLink Cloud: The Leader in Enterprise Cloud Services.
Learn Why More Businesses Are Choosing CenturyLink Cloud For
Critical Workloads, Development Environments & Everything In Between.
Get a Quote or Start a Free Trial Today. 
http://pubads.g.doubleclick.net/gampad/clk?id=119420431&iu=/4140/ostg.clktrk
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to