This patch adds support for MAC Hardware Accelerator functions such as 
Automated Acknowledgement (AACK) and CSMA-CA with Retransmission found on a few 
802.15.4 Radio Transceivers.
In order to support such functionality the radio's address filtering needs to 
know it's Short, IEEE Address and PAN ID.
This patch makes sure that this information is pushed to the radio in case it 
provides a new ieee802154_ops callback function (ext_mac_ctrl).
All this is optional, and shouldn't influence the current implementation.

Current kernel-zigbee doesn't implement ACK transmissions, nor does it 
implement any kind of Retry.
(BTW it also doesn't do anything useful with the xmit return value)
I understand that this is going to be added in future, as part of the softmac 
implementation.
I also understand that this softmac allows for greater flexibility such 
indirect addressing or utilizing different sets of addresses on the same radio.

However for some reduced function devices or for platforms where soft ACK 
latencies may violate the 802.15.4 ACK window, this HW AACK function is going 
to be of great value.
It also temporarily fills the gap of missing kernel-zigbee functionality.

Once there is some xmit return value handling, we should add some standard 
return values for these auto modes:

XMIT_SUCCESS
XMIT_SUCCESS_DATPEND
XMIT_FAILURE_CSMACA
XMIT_FAILURE_NOACK

From: Michael Hennerich <[email protected]>

 include/net/mac802154.h |    6 +++
 include/net/wpan-phy.h  |    8 ++++
 net/mac802154/dev.c     |    1 +
 net/mac802154/mac_cmd.c |    3 ++
 net/mac802154/mib.c     |   89 +++++++++++++++++++++++++++++++++++++++++++++++
 net/mac802154/mib.h     |    2 +
 6 files changed, 109 insertions(+), 0 deletions(-)

diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 3463996..081aa45 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -21,6 +21,10 @@
 #ifndef NET_MAC802154_H
 #define NET_MAC802154_H

+#define IEEE802154_PHY_CMD_IEEE_ADDR   1
+#define IEEE802154_PHY_CMD_SHORT_ADDR  2
+#define IEEE802154_PHY_CMD_PAN_ID      3
+#define IEEE802154_PHY_CMD_PAN_COORD   4
 struct ieee802154_dev {
        /* filled by the driver */
        int     extra_tx_headroom; /* headroom to reserve for tx skb */
@@ -96,6 +100,8 @@ struct ieee802154_ops {
        int             (*ed)(struct ieee802154_dev *dev, u8 *level);
        int             (*set_channel)(struct ieee802154_dev *dev,
                                                int channel);
+       int             (*ext_mac_ctrl)(struct ieee802154_dev *dev,
+                                               int cmd, unsigned long val);
 };

 struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
index 8592623..802c555 100644
--- a/include/net/wpan-phy.h
+++ b/include/net/wpan-phy.h
@@ -23,6 +23,7 @@

 #include <linux/netdevice.h>
 #include <linux/mutex.h>
+#include <net/af_ieee802154.h>

 struct wpan_phy {
        struct mutex pib_lock;
@@ -38,6 +39,13 @@ struct wpan_phy {
        u8 transmit_power;
        u8 cca_mode;

+       /*
+        * Extended MAC Control
+        */
+       u8 current_pan_coord;
+       u16 current_pan_id;
+       u16 current_short_addr;
+       u8 current_ieee_addr[IEEE802154_ADDR_LEN];
        struct device dev;
        int idx;

diff --git a/net/mac802154/dev.c b/net/mac802154/dev.c
index a07cf72..3c9ee9b 100644
--- a/net/mac802154/dev.c
+++ b/net/mac802154/dev.c
@@ -219,6 +219,7 @@ static int ieee802154_slave_mac_addr(struct net_device 
*dev, void *p)
                return -EBUSY;
        /* FIXME: validate addr */
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+       ieee802154_dev_set_ieee_addr(dev);
        return 0;
 }

diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index bbad128..5d1c630 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -250,6 +250,7 @@ static int ieee802154_mlme_assoc_req(struct net_device *dev,
        ieee802154_dev_set_pan_id(dev, addr->pan_id);
        ieee802154_dev_set_page(dev, page);
        ieee802154_dev_set_channel(dev, channel);
+       ieee802154_dev_set_ieee_addr(dev);

        buf[pos++] = IEEE802154_CMD_ASSOCIATION_REQ;
        buf[pos++] = cap;
@@ -311,6 +312,7 @@ static int ieee802154_mlme_start_req(struct net_device *dev,

        ieee802154_dev_set_pan_id(dev, addr->pan_id);
        ieee802154_dev_set_short_addr(dev, addr->short_addr);
+       ieee802154_dev_set_ieee_addr(dev);
        ieee802154_dev_set_page(dev, page);
        ieee802154_dev_set_channel(dev, channel);

@@ -324,6 +326,7 @@ static int ieee802154_mlme_start_req(struct net_device *dev,
        else
                dev->priv_flags &= ~IFF_IEEE802154_COORD;

+       ieee802154_dev_set_pan_coord(dev);
        ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);

        return 0;
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index 94dc0e9..8b1c5ae 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -33,6 +33,70 @@ struct phy_chan_notify_work {
        struct net_device *dev;
 };

+struct phy_ext_mac_notify_work {
+       struct work_struct work;
+       struct net_device *dev;
+       int cmd;
+};
+
+static void ext_mac_notify(struct work_struct *work)
+{
+       struct phy_ext_mac_notify_work *nw = container_of(work,
+                       struct phy_ext_mac_notify_work, work);
+       struct ieee802154_priv *hw = ieee802154_slave_get_priv(nw->dev);
+       struct ieee802154_sub_if_data *priv = netdev_priv(nw->dev);
+       int res;
+
+       switch(nw->cmd) {
+       case IEEE802154_PHY_CMD_IEEE_ADDR:
+               /* FIXME: Let the PHY copy */
+               memcpy(priv->hw->phy->current_ieee_addr,
+                       nw->dev->dev_addr, IEEE802154_ADDR_LEN),
+
+               res = hw->ops->ext_mac_ctrl(&hw->hw, nw->cmd, 0);
+               break;
+       case IEEE802154_PHY_CMD_SHORT_ADDR:
+               res = hw->ops->ext_mac_ctrl(&hw->hw, nw->cmd,
+                        priv->short_addr);
+               break;
+       case IEEE802154_PHY_CMD_PAN_ID:
+               res = hw->ops->ext_mac_ctrl(&hw->hw, nw->cmd,
+                        priv->pan_id);
+               break;
+       case IEEE802154_PHY_CMD_PAN_COORD:
+               res = hw->ops->ext_mac_ctrl(&hw->hw, nw->cmd,
+                        !!(nw->dev->priv_flags & IFF_IEEE802154_COORD));
+
+               break;
+       default:
+               res = -EFAULT;
+       }
+
+       if (res)
+               pr_debug("ext_mac_notify failed CMD %d\n", nw->cmd);
+
+       kfree(nw);
+
+       return;
+}
+
+static void ext_mac_ctrl(struct net_device *dev, int cmd)
+{
+       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
+       struct phy_ext_mac_notify_work *work;
+
+       work = kzalloc(sizeof(*work), GFP_ATOMIC);
+       if (!work)
+               return;
+
+       INIT_WORK(&work->work, ext_mac_notify);
+       work->dev = dev;
+       work->cmd = cmd;
+       queue_work(priv->hw->dev_workqueue, &work->work);
+
+       return;
+}
+
 static void phy_chan_notify(struct work_struct *work)
 {
        struct phy_chan_notify_work *nw = container_of(work,
@@ -87,6 +151,18 @@ void ieee802154_dev_set_pan_id(struct net_device *dev, u16 
val)
        spin_lock_bh(&priv->mib_lock);
        priv->pan_id = val;
        spin_unlock_bh(&priv->mib_lock);
+       if (priv->hw->ops->ext_mac_ctrl &&
+               (priv->hw->phy->current_pan_id != priv->pan_id))
+               ext_mac_ctrl(dev, IEEE802154_PHY_CMD_PAN_ID);
+}
+
+void ieee802154_dev_set_pan_coord(struct net_device *dev)
+{
+       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
+
+       if (priv->hw->ops->ext_mac_ctrl &&
+               (priv->hw->phy->current_pan_coord != priv->pan_id))
+               ext_mac_ctrl(dev, IEEE802154_PHY_CMD_PAN_COORD);
 }

 void ieee802154_dev_set_short_addr(struct net_device *dev, u16 val)
@@ -98,6 +174,19 @@ void ieee802154_dev_set_short_addr(struct net_device *dev, 
u16 val)
        spin_lock_bh(&priv->mib_lock);
        priv->short_addr = val;
        spin_unlock_bh(&priv->mib_lock);
+       if (priv->hw->ops->ext_mac_ctrl &&
+               (priv->hw->phy->current_short_addr != priv->short_addr))
+               ext_mac_ctrl(dev, IEEE802154_PHY_CMD_SHORT_ADDR);
+}
+
+void ieee802154_dev_set_ieee_addr(struct net_device *dev)
+{
+       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
+
+       if (priv->hw->ops->ext_mac_ctrl &&
+               memcmp(priv->hw->phy->current_ieee_addr,
+                       dev->dev_addr, IEEE802154_ADDR_LEN))
+               ext_mac_ctrl(dev, IEEE802154_PHY_CMD_IEEE_ADDR);
 }

 void ieee802154_dev_set_channel(struct net_device *dev, u8 val)
diff --git a/net/mac802154/mib.h b/net/mac802154/mib.h
index 5096c6a..8b66d0d 100644
--- a/net/mac802154/mib.h
+++ b/net/mac802154/mib.h
@@ -25,7 +25,9 @@ u8 ieee802154_dev_get_bsn(const struct net_device *dev);
 u16 ieee802154_dev_get_pan_id(const struct net_device *dev);
 u16 ieee802154_dev_get_short_addr(const struct net_device *dev);
 void ieee802154_dev_set_pan_id(struct net_device *dev, u16 val);
+void ieee802154_dev_set_pan_coord(struct net_device *dev);
 void ieee802154_dev_set_short_addr(struct net_device *dev, u16 val);
+void ieee802154_dev_set_ieee_addr(struct net_device *dev);
 void ieee802154_dev_set_channel(struct net_device *dev, u8 chan);
 void ieee802154_dev_set_page(struct net_device *dev, u8 page);
 struct wpan_phy *ieee802154_get_phy(const struct net_device *dev);



------------------------------------------------------------------
********* Analog Devices GmbH              Open Platform Solutions
**  *****
**     ** Wilhelm-Wagenfeld-Strasse 6
**  ***** D-80807 Munich
********* Germany
Registergericht München HRB 40368,  Geschäftsführer: Thomas Wessel, William A. 
Martin, Margaret K. Seif


------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Linux-zigbee-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to