On 03/13/2013 03:45 AM, Wolf-Bastian Pöttner wrote: > Implement the filter function to update short address, pan id and ieee > address on change. Allowing for hardware address filtering needed for > auto ACK. Switch state machine to use auto ACK states for rx. > > This will handle CSMA/CA for us as well as re-sending frames when no ack comes > in timely. > > The register names have been wrong since the beginning but it only showed up > now > as they are actualy used for the upcoming auto ACK support. > > Signed-off-by: Stefan Schmidt <ste...@datenfreihafen.org> > --- > drivers/ieee802154/at86rf230.c | 108 ++++++++++++++++++++++++++++++++++++++- > 1 files changed, 105 insertions(+), 3 deletions(-) > > diff --git a/drivers/ieee802154/at86rf230.c b/drivers/ieee802154/at86rf230.c > index 4d32ac4..761343b 100644 > --- a/drivers/ieee802154/at86rf230.c > +++ b/drivers/ieee802154/at86rf230.c > @@ -38,6 +38,9 @@ > long unsigned int bytes_tx; > long unsigned int bytes_rx; > > +#define ENABLE_AACK > +#define ENABLE_ARET > +
#ifdef stuff isn't going to fly in the mainline kernel. Just a heads-up. Ack support is something that's been on my radar to add, but haven't had time. Maybe you have time to do this properly, by making a new netlink item to turn acking on and off and pushing it through iz. > struct at86rf230_local { > struct spi_device *spi; > int rstn, slp_tr, dig2; > @@ -236,8 +239,8 @@ struct at86rf230_local { > #define STATE_SLEEP 0x0F > #define STATE_BUSY_RX_AACK 0x11 > #define STATE_BUSY_TX_ARET 0x12 > -#define STATE_BUSY_RX_AACK_ON 0x16 > -#define STATE_BUSY_TX_ARET_ON 0x19 > +#define STATE_RX_AACK_ON 0x16 > +#define STATE_TX_ARET_ON 0x19 > #define STATE_RX_ON_NOCLK 0x1C > #define STATE_RX_AACK_ON_NOCLK 0x1D > #define STATE_BUSY_RX_AACK_NOCLK 0x1E > @@ -462,7 +465,11 @@ at86rf230_state(struct ieee802154_dev *dev, int state) > might_sleep(); > > if (state == STATE_FORCE_TX_ON) > +#ifdef ENABLE_ARET > + desired_status = STATE_TX_ARET_ON; > +#else > desired_status = STATE_TX_ON; > +#endif > else if (state == STATE_FORCE_TRX_OFF) > desired_status = STATE_TRX_OFF; > else > @@ -488,10 +495,43 @@ at86rf230_state(struct ieee802154_dev *dev, int state) > goto err; > } while (val == STATE_TRANSITION_IN_PROGRESS); > > +#ifdef ENABLE_ARET > + /* Make sure we go to TX_ON before we go to STATE_TX_ARET_ON */ > + if (desired_status == STATE_TX_ARET_ON) { > + rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON); > + if (rc) > + goto err; > + > + do { > + rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val); > + if (rc) > + goto err; > + pr_debug("%s val3 = %x\n", __func__, val); > + } while (val == STATE_TRANSITION_IN_PROGRESS); > + > + rc = at86rf230_write_subreg(lp, SR_TRX_CMD, desired_status); > + if (rc) > + goto err; > + > + do { > + rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val); > + if (rc) > + goto err; > + pr_debug("%s val4 = %x\n", __func__, val); > + } while (val == STATE_TRANSITION_IN_PROGRESS); > + } > +#endif > > if (val == desired_status) > return 0; > > +#ifdef ENABLE_AACK > + if (state == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK) > +#else > + if (state == STATE_RX_ON && val == STATE_BUSY_RX) > +#endif > + return 0; > + > pr_err("unexpected state change: %d, asked for %d\n", val, state); > return -EBUSY; > > @@ -510,7 +550,11 @@ at86rf230_start(struct ieee802154_dev *dev) > if (rc) > return rc; > > +#ifdef ENABLE_AACK > + return at86rf230_state(dev, STATE_RX_AACK_ON); > +#else > return at86rf230_state(dev, STATE_RX_ON); > +#endif > } > > static void > @@ -625,6 +669,54 @@ err: > return -EINVAL; > } > > +#ifdef ENABLE_AACK > +static int > +at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev, > + struct ieee802154_hw_addr_filt > *filt, > + unsigned long changed) > +{ > + struct at86rf230_local *lp = dev->priv; > + > + might_sleep(); > + > + at86rf230_stop(dev); > + > + msleep(10); Why this msleep()? is this from the datasheet, or is it a hack? Also, you might get pushback on using a magic number (10) there, and not a #define. > + > + if (changed & IEEE802515_AFILT_SADDR_CHANGED) { > + __at86rf230_write(lp, RG_SHORT_ADDR_0, filt->short_addr & > 0xff); /* LSB */ > + __at86rf230_write(lp, RG_SHORT_ADDR_1, (filt->short_addr >> 8) > & 0xff); /* MSB */ > + } > + > + if (changed & IEEE802515_AFILT_PANID_CHANGED) { > + __at86rf230_write(lp, RG_PAN_ID_0, filt->pan_id & 0xff); /* LSB > */ > + __at86rf230_write(lp, RG_PAN_ID_1, (filt->pan_id >> 8) & 0xff); > /* MSB */ > + } > + > + if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) { > + // Make sure order MSB to LSB is correct > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_0, filt->ieee_addr[7]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_1, filt->ieee_addr[6]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_2, filt->ieee_addr[5]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_3, filt->ieee_addr[4]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_4, filt->ieee_addr[3]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_5, filt->ieee_addr[2]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_6, filt->ieee_addr[1]); > + at86rf230_write_subreg(lp, SR_IEEE_ADDR_7, filt->ieee_addr[0]); > + } > + > + if (changed & IEEE802515_AFILT_PANC_CHANGED) { > + if (filt->pan_coord) > + at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1); > + else > + at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 0); > + } > + > + at86rf230_start(dev); > + > + return 0; > +} > +#endif We need filter stuff regardless of acking, so split this off into a separate patch. I do question the need to _start() and _stop() though. What makes you think this is necessary? > static struct ieee802154_ops at86rf230_ops = { > .owner = THIS_MODULE, > .xmit = at86rf230_xmit, > @@ -632,6 +724,9 @@ static struct ieee802154_ops at86rf230_ops = { > .set_channel = at86rf230_channel, > .start = at86rf230_start, > .stop = at86rf230_stop, > +#ifdef ENABLE_AACK > + .set_hw_addr_filt = at86rf230_set_hw_addr_filt, > +#endif > }; > > static void at86rf230_irqwork(struct work_struct *work) > @@ -680,7 +775,6 @@ static irqreturn_t at86rf230_isr(int irq, void *data) > return IRQ_HANDLED; > } > > - ^^^ Stray whitespace change > static int at86rf230_hw_init(struct at86rf230_local *lp) > { > u8 status; > @@ -718,7 +812,11 @@ static int at86rf230_hw_init(struct at86rf230_local *lp) > /* Wait the next SLEEP cycle */ > msleep(100); > > +#ifdef ENABLE_ARET > + rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON); > +#else > rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON); > +#endif > if (rc) > return rc; > msleep(1); > @@ -802,7 +900,11 @@ static int __devinit at86rf230_probe(struct spi_device > *spi) > dev->extra_tx_headroom = 0; > /* We do support only 2.4 Ghz */ > dev->phy->channels_supported[0] = 0x7FFF800; > +#ifdef ENABLE_AACK > + dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK; > +#else > dev->flags = IEEE802154_HW_OMIT_CKSUM; > +#endif > > mutex_init(&lp->bmux); > INIT_WORK(&lp->irqwork, at86rf230_irqwork); It looks like you've put some work into this. Good job. I think a little bit more and it'll be first class. :) Alan. ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_mar _______________________________________________ Linux-zigbee-devel mailing list Linux-zigbee-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel