On Tue, Mar 2, 2010 at 11:06 PM, Hennerich, Michael
<[email protected]> wrote:
> 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.

Looks fine. Thank you. Could you please however resend this patch
either as an attachment, or (preferred) via git-send-email.
Otherwise all TAB characters are busted.

> 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 set_hw_addr_filt.
> All this is optional, and shouldn't influence drivers without such hardware 
> support.
>
> Example ieee802154_ops:set_hw_addr_filt callback:
>
> static int trx_set_hw_addr_filt(struct ieee802154_dev *dev,
>        struct ieee802154_hw_addr_filt *filt, unsigned long changed)
> {
>        struct trx_local *lp = dev->priv;
>        u8 reg;
>
>        might_sleep();
>
>        if (changed & IEEE802515_IEEEADDR_CHANGED) {
>                trx_write_reg(lp, REG_IEEE_ADDR_0, filt->ieee_addr[7]);
>                trx_write_reg(lp, REG_IEEE_ADDR_1, filt->ieee_addr[6]);
>                trx_write_reg(lp, REG_IEEE_ADDR_2, filt->ieee_addr[5]);
>                trx_write_reg(lp, REG_IEEE_ADDR_3, filt->ieee_addr[4]);
>                trx_write_reg(lp, REG_IEEE_ADDR_4, filt->ieee_addr[3]);
>                trx_write_reg(lp, REG_IEEE_ADDR_5, filt->ieee_addr[2]);
>                trx_write_reg(lp, REG_IEEE_ADDR_6, filt->ieee_addr[1]);
>                trx_write_reg(lp, REG_IEEE_ADDR_7, filt->ieee_addr[0]);
>        }
>
>        if (changed & IEEE802515_SADDR_CHANGED) {
>                trx_write_reg(lp, REG_SHORT_ADDR_0, filt->short_addr);
>                trx_write_reg(lp, REG_SHORT_ADDR_1, filt->short_addr >> 8);
>        }
>
>        if (changed & IEEE802515_PANID_CHANGED) {
>                trx_write_reg(lp, REG_PAN_ID0, filt->pan_id);
>                trx_write_reg(lp, REG_PAN_ID1, filt->pan_id >> 8);
>        }
>
>        if (changed & IEEE802515_PANC_CHANGED) {
>                trx_read_reg(lp, REG_AUTO_CFG, &reg);
>                if (filt->pan_coord)
>                        reg |= IS_PANCOORD;
>                else
>                        reg &= ~IS_PANCOORD;
>                trx_write_reg(lp, REG_AUTO_CFG, reg);
>        }
>
>        return 0;
> }
>
> Version 2 changes:
> -Keep wpan-phy a phy-only instance.
> -Refractor callback function so it takes as argument a pointer to a structure 
> containing all addressing fields and a changed mask.
>
>
> From: Michael Hennerich <[email protected]>
>
>  include/net/mac802154.h |   46 ++++++++++++++++++++++++++-
>  net/mac802154/dev.c     |    1 +
>  net/mac802154/mac_cmd.c |    3 ++
>  net/mac802154/mib.c     |   78 
> +++++++++++++++++++++++++++++++++++++++++++++++
>  net/mac802154/mib.h     |    2 +
>  5 files changed, 128 insertions(+), 2 deletions(-)
>
> diff --git a/include/net/mac802154.h b/include/net/mac802154.h
> index 3463996..e3bb579 100644
> --- a/include/net/mac802154.h
> +++ b/include/net/mac802154.h
> @@ -21,6 +21,40 @@
>  #ifndef NET_MAC802154_H
>  #define NET_MAC802154_H
>
> +#include <net/af_ieee802154.h>
> +
> +/**
> + * enum ieee802154_hw_addr_filt_flags - hardware flags
> + *
> + * These flags are used to indicate changed address settings from
> + * the stack to the hardware.
> + *
> + * @IEEE802515_SADDR_CHANGED:
> + *     Indicates that the Short Address changed
> + *
> + * @IEEE802515_IEEEADDR_CHANGED:
> + *     Indicates that the IEEE Address changed
> + *
> + * @IEEE802515_PANID_CHANGED:
> + *     Indicates that the PAN ID changed
> + *
> + * @IEEE802515_PANC_CHANGED:
> + *     Indicates that PAN Coordinator status changed
> + */
> +enum ieee802154_hw_addr_filt_flags {
> +       IEEE802515_SADDR_CHANGED        = 1 << 0,
> +       IEEE802515_IEEEADDR_CHANGED     = 1 << 1,
> +       IEEE802515_PANID_CHANGED        = 1 << 2,
> +       IEEE802515_PANC_CHANGED         = 1 << 3,
> +};
> +
> +struct ieee802154_hw_addr_filt {
> +       u16 pan_id;
> +       u16 short_addr;
> +       u8 ieee_addr[IEEE802154_ADDR_LEN];
> +       u8 pan_coord;
> +};
> +
>  struct ieee802154_dev {
>        /* filled by the driver */
>        int     extra_tx_headroom; /* headroom to reserve for tx skb */
> @@ -28,6 +62,7 @@ struct ieee802154_dev {
>        struct device *parent;
>
>        /* filled by mac802154 core */
> +       struct ieee802154_hw_addr_filt hw_filt;
>        void    *priv;          /* driver-specific data */
>        struct wpan_phy *phy;
>  };
> @@ -86,16 +121,23 @@ struct sk_buff;
>  *      Set the device for listening on specified channel.
>  *      Returns either zero, or negative errno.
>  *      Called with pib_lock held.
> + *
> + * @set_hw_addr_filt: Set radio for listening on specific address.
> + *      Set the device for listening on specified address.
> + *      Returns either zero, or negative errno.
>  */
>  struct ieee802154_ops {
>        struct module   *owner;
>        int             (*start)(struct ieee802154_dev *dev);
>        void            (*stop)(struct ieee802154_dev *dev);
>        int             (*xmit)(struct ieee802154_dev *dev,
> -                                               struct sk_buff *skb);
> +                                       struct sk_buff *skb);
>        int             (*ed)(struct ieee802154_dev *dev, u8 *level);
>        int             (*set_channel)(struct ieee802154_dev *dev,
> -                                               int channel);
> +                                       int channel);
> +       int             (*set_hw_addr_filt)(struct ieee802154_dev *dev,
> +                                       struct ieee802154_hw_addr_filt *filt,
> +                                       unsigned long changed);
>  };
>
>  struct ieee802154_dev *ieee802154_alloc_device(size_t priv_size,
> diff --git a/net/mac802154/dev.c b/net/mac802154/dev.c
> index 7c21252..cdd0f78 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..b3dfb08 100644
> --- a/net/mac802154/mib.c
> +++ b/net/mac802154/mib.c
> @@ -33,6 +33,47 @@ struct phy_chan_notify_work {
>        struct net_device *dev;
>  };
>
> +struct hw_addr_filt_notify_work {
> +       struct work_struct work;
> +       struct net_device *dev;
> +       unsigned long changed;
> +};
> +
> +static void hw_addr_notify(struct work_struct *work)
> +{
> +       struct hw_addr_filt_notify_work *nw = container_of(work,
> +                       struct hw_addr_filt_notify_work, work);
> +       struct ieee802154_priv *hw = ieee802154_slave_get_priv(nw->dev);
> +       int res;
> +
> +       res = hw->ops->set_hw_addr_filt(&hw->hw,
> +               &hw->hw.hw_filt, nw->changed);
> +       if (res)
> +               pr_debug("%s: failed changed mask %lx\n",
> +                       __func__, nw->changed);
> +
> +       kfree(nw);
> +
> +       return;
> +}
> +
> +static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
> +{
> +       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
> +       struct hw_addr_filt_notify_work *work;
> +
> +       work = kzalloc(sizeof(*work), GFP_ATOMIC);
> +       if (!work)
> +               return;
> +
> +       INIT_WORK(&work->work, hw_addr_notify);
> +       work->dev = dev;
> +       work->changed = changed;
> +       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 +128,24 @@ 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->set_hw_addr_filt &&
> +               (priv->hw->hw.hw_filt.pan_id != priv->pan_id)) {
> +               priv->hw->hw.hw_filt.pan_id = priv->pan_id;
> +               set_hw_addr_filt(dev, IEEE802515_PANID_CHANGED);
> +       }
> +}
> +
> +void ieee802154_dev_set_pan_coord(struct net_device *dev)
> +{
> +       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
> +       int pan_coord = !!(dev->priv_flags & IFF_IEEE802154_COORD);
> +
> +       if (priv->hw->ops->set_hw_addr_filt &&
> +               (priv->hw->hw.hw_filt.pan_coord != pan_coord)) {
> +               priv->hw->hw.hw_filt.pan_coord = pan_coord;
> +               set_hw_addr_filt(dev, IEEE802515_PANC_CHANGED);
> +       }
>  }
>
>  void ieee802154_dev_set_short_addr(struct net_device *dev, u16 val)
> @@ -98,6 +157,25 @@ 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->set_hw_addr_filt &&
> +               (priv->hw->hw.hw_filt.short_addr != priv->short_addr)) {
> +               priv->hw->hw.hw_filt.short_addr = priv->short_addr;
> +               set_hw_addr_filt(dev, IEEE802515_SADDR_CHANGED);
> +       }
> +}
> +
> +void ieee802154_dev_set_ieee_addr(struct net_device *dev)
> +{
> +       struct ieee802154_sub_if_data *priv = netdev_priv(dev);
> +
> +       if (priv->hw->ops->set_hw_addr_filt &&
> +               memcmp(priv->hw->hw.hw_filt.ieee_addr,
> +                       dev->dev_addr, IEEE802154_ADDR_LEN)) {
> +               memcpy(priv->hw->hw.hw_filt.ieee_addr,
> +                       dev->dev_addr, IEEE802154_ADDR_LEN);
> +               set_hw_addr_filt(dev, IEEE802515_IEEEADDR_CHANGED);
> +       }
>  }
>
>  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
>
>



-- 
With best wishes
Dmitry

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Linux-zigbee-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to