diff options
author | Alexander Aring <alex.aring@gmail.com> | 2014-07-02 18:20:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:29:25 -0400 |
commit | 2e0571c0d6835e224b5863df630efbcf00696483 (patch) | |
tree | 25f8254ce3e7408c8bba0a8f7ae8fd0188828b48 /drivers/net/ieee802154 | |
parent | 1db0558e87ddf0e4892963602b35ac079b507dd9 (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.c | 126 |
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 | */ |
44 | struct at86rf2xx_chip_data { | 44 | struct 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 | ||
634 | static void | 652 | static void |
653 | at86rf230_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 | */ | ||
665 | static int | ||
666 | at86rf230_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 | |||
685 | static void | ||
635 | at86rf230_tx_complete(void *context) | 686 | at86rf230_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 | ||
959 | static int | 1010 | static int |
960 | at86rf230_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 | |||
1005 | err: | ||
1006 | pr_err("error: %d\n", rc); | ||
1007 | return rc; | ||
1008 | } | ||
1009 | |||
1010 | static int | ||
1011 | at86rf230_start(struct ieee802154_dev *dev) | 1011 | at86rf230_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 | ||
1022 | static void | 1016 | static void |
1023 | at86rf230_stop(struct ieee802154_dev *dev) | 1017 | at86rf230_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 | ||
1028 | static int | 1022 | static int |
@@ -1242,6 +1236,8 @@ static struct ieee802154_ops at86rf230_ops = { | |||
1242 | }; | 1236 | }; |
1243 | 1237 | ||
1244 | static struct at86rf2xx_chip_data at86rf233_data = { | 1238 | static 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 | ||
1255 | static struct at86rf2xx_chip_data at86rf231_data = { | 1251 | static 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 | ||
1266 | static struct at86rf2xx_chip_data at86rf212_data = { | 1264 | static 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) | |||
1427 | static void | 1427 | static void |
1428 | at86rf230_setup_spi_messages(struct at86rf230_local *lp) | 1428 | at86rf230_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 | ||