aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ieee802154
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2014-07-02 18:20:51 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 00:29:25 -0400
commit2e0571c0d6835e224b5863df630efbcf00696483 (patch)
tree25f8254ce3e7408c8bba0a8f7ae8fd0188828b48 /drivers/net/ieee802154
parent1db0558e87ddf0e4892963602b35ac079b507dd9 (diff)
at86rf230: rework state change and start/stop
This patch removes the current synchron state change function and add a new function for a state assert. Change the start and stop callbacks to use this new synchron state change behaviour. It's a wrapper around the async state change function. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ieee802154')
-rw-r--r--drivers/net/ieee802154/at86rf230.c126
1 files changed, 67 insertions, 59 deletions
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 46db6f8fb58f..265fea8a6030 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -42,6 +42,8 @@ struct at86rf230_local;
42 * All timings are in us. 42 * All timings are in us.
43 */ 43 */
44struct at86rf2xx_chip_data { 44struct at86rf2xx_chip_data {
45 u16 t_off_to_aack;
46 u16 t_off_to_tx_on;
45 u16 t_frame; 47 u16 t_frame;
46 u16 t_p_ack; 48 u16 t_p_ack;
47 /* short interframe spacing time */ 49 /* short interframe spacing time */
@@ -77,6 +79,9 @@ struct at86rf230_local {
77 struct at86rf2xx_chip_data *data; 79 struct at86rf2xx_chip_data *data;
78 struct regmap *regmap; 80 struct regmap *regmap;
79 81
82 struct completion state_complete;
83 struct at86rf230_state_change state;
84
80 struct at86rf230_state_change irq; 85 struct at86rf230_state_change irq;
81 86
82 bool tx_aret; 87 bool tx_aret;
@@ -547,6 +552,19 @@ at86rf230_async_state_delay(void *context)
547 } 552 }
548 553
549 switch (ctx->from_state) { 554 switch (ctx->from_state) {
555 case STATE_TRX_OFF:
556 switch (ctx->to_state) {
557 case STATE_RX_AACK_ON:
558 usleep_range(c->t_off_to_aack, c->t_off_to_aack + 10);
559 goto change;
560 case STATE_TX_ON:
561 usleep_range(c->t_off_to_tx_on,
562 c->t_off_to_tx_on + 10);
563 goto change;
564 default:
565 break;
566 }
567 break;
550 case STATE_BUSY_RX_AACK: 568 case STATE_BUSY_RX_AACK:
551 switch (ctx->to_state) { 569 switch (ctx->to_state) {
552 case STATE_TX_ON: 570 case STATE_TX_ON:
@@ -632,6 +650,39 @@ at86rf230_async_state_change(struct at86rf230_local *lp,
632} 650}
633 651
634static void 652static void
653at86rf230_sync_state_change_complete(void *context)
654{
655 struct at86rf230_state_change *ctx = context;
656 struct at86rf230_local *lp = ctx->lp;
657
658 complete(&lp->state_complete);
659}
660
661/* This function do a sync framework above the async state change.
662 * Some callbacks of the IEEE 802.15.4 driver interface need to be
663 * handled synchronously.
664 */
665static int
666at86rf230_sync_state_change(struct at86rf230_local *lp, unsigned int state)
667{
668 int rc;
669
670 rc = at86rf230_async_state_change(lp, &lp->state, state,
671 at86rf230_sync_state_change_complete);
672 if (rc) {
673 at86rf230_async_error(lp, &lp->state, rc);
674 return rc;
675 }
676
677 rc = wait_for_completion_timeout(&lp->state_complete,
678 msecs_to_jiffies(100));
679 if (!rc)
680 return -ETIMEDOUT;
681
682 return 0;
683}
684
685static void
635at86rf230_tx_complete(void *context) 686at86rf230_tx_complete(void *context)
636{ 687{
637 struct at86rf230_state_change *ctx = context; 688 struct at86rf230_state_change *ctx = context;
@@ -957,72 +1008,15 @@ at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
957} 1008}
958 1009
959static int 1010static int
960at86rf230_state(struct ieee802154_dev *dev, int state)
961{
962 struct at86rf230_local *lp = dev->priv;
963 int rc;
964 unsigned int val;
965 u8 desired_status;
966
967 might_sleep();
968
969 if (state == STATE_FORCE_TX_ON)
970 desired_status = STATE_TX_ON;
971 else if (state == STATE_FORCE_TRX_OFF)
972 desired_status = STATE_TRX_OFF;
973 else
974 desired_status = state;
975
976 do {
977 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
978 if (rc)
979 goto err;
980 } while (val == STATE_TRANSITION_IN_PROGRESS);
981
982 if (val == desired_status)
983 return 0;
984
985 /* state is equal to phy states */
986 rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
987 if (rc)
988 goto err;
989
990 do {
991 rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
992 if (rc)
993 goto err;
994 } while (val == STATE_TRANSITION_IN_PROGRESS);
995
996
997 if (val == desired_status ||
998 (desired_status == STATE_RX_ON && val == STATE_BUSY_RX) ||
999 (desired_status == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK))
1000 return 0;
1001
1002 pr_err("unexpected state change: %d, asked for %d\n", val, state);
1003 return -EBUSY;
1004
1005err:
1006 pr_err("error: %d\n", rc);
1007 return rc;
1008}
1009
1010static int
1011at86rf230_start(struct ieee802154_dev *dev) 1011at86rf230_start(struct ieee802154_dev *dev)
1012{ 1012{
1013 u8 rc; 1013 return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON);
1014
1015 rc = at86rf230_state(dev, STATE_TX_ON);
1016 if (rc)
1017 return rc;
1018
1019 return at86rf230_state(dev, STATE_RX_AACK_ON);
1020} 1014}
1021 1015
1022static void 1016static void
1023at86rf230_stop(struct ieee802154_dev *dev) 1017at86rf230_stop(struct ieee802154_dev *dev)
1024{ 1018{
1025 at86rf230_state(dev, STATE_FORCE_TRX_OFF); 1019 at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF);
1026} 1020}
1027 1021
1028static int 1022static int
@@ -1242,6 +1236,8 @@ static struct ieee802154_ops at86rf230_ops = {
1242}; 1236};
1243 1237
1244static struct at86rf2xx_chip_data at86rf233_data = { 1238static struct at86rf2xx_chip_data at86rf233_data = {
1239 .t_off_to_aack = 80,
1240 .t_off_to_tx_on = 80,
1245 .t_frame = 4096, 1241 .t_frame = 4096,
1246 .t_p_ack = 545, 1242 .t_p_ack = 545,
1247 .t_sifs = 192, 1243 .t_sifs = 192,
@@ -1253,6 +1249,8 @@ static struct at86rf2xx_chip_data at86rf233_data = {
1253}; 1249};
1254 1250
1255static struct at86rf2xx_chip_data at86rf231_data = { 1251static struct at86rf2xx_chip_data at86rf231_data = {
1252 .t_off_to_aack = 110,
1253 .t_off_to_tx_on = 110,
1256 .t_frame = 4096, 1254 .t_frame = 4096,
1257 .t_p_ack = 545, 1255 .t_p_ack = 545,
1258 .t_sifs = 192, 1256 .t_sifs = 192,
@@ -1264,6 +1262,8 @@ static struct at86rf2xx_chip_data at86rf231_data = {
1264}; 1262};
1265 1263
1266static struct at86rf2xx_chip_data at86rf212_data = { 1264static struct at86rf2xx_chip_data at86rf212_data = {
1265 .t_off_to_aack = 200,
1266 .t_off_to_tx_on = 200,
1267 .t_frame = 4096, 1267 .t_frame = 4096,
1268 .t_p_ack = 545, 1268 .t_p_ack = 545,
1269 .t_sifs = 192, 1269 .t_sifs = 192,
@@ -1427,6 +1427,13 @@ at86rf230_detect_device(struct at86rf230_local *lp)
1427static void 1427static void
1428at86rf230_setup_spi_messages(struct at86rf230_local *lp) 1428at86rf230_setup_spi_messages(struct at86rf230_local *lp)
1429{ 1429{
1430 lp->state.lp = lp;
1431 spi_message_init(&lp->state.msg);
1432 lp->state.msg.context = &lp->state;
1433 lp->state.trx.tx_buf = lp->state.buf;
1434 lp->state.trx.rx_buf = lp->state.buf;
1435 spi_message_add_tail(&lp->state.trx, &lp->state.msg);
1436
1430 lp->irq.lp = lp; 1437 lp->irq.lp = lp;
1431 spi_message_init(&lp->irq.msg); 1438 spi_message_init(&lp->irq.msg);
1432 lp->irq.msg.context = &lp->irq; 1439 lp->irq.msg.context = &lp->irq;
@@ -1509,6 +1516,7 @@ static int at86rf230_probe(struct spi_device *spi)
1509 1516
1510 spin_lock_init(&lp->lock); 1517 spin_lock_init(&lp->lock);
1511 init_completion(&lp->tx_complete); 1518 init_completion(&lp->tx_complete);
1519 init_completion(&lp->state_complete);
1512 1520
1513 spi_set_drvdata(spi, lp); 1521 spi_set_drvdata(spi, lp);
1514 1522