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, ®);
> 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® 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