Skip to content

Commit c91a301

Browse files
alexaringholtmann
authored andcommitted
mrf24j40: rework rx handling to async rx handling
This patch prepares that we can do the receive handling inside interrupt context by using spi_async. This is necessary for introduce a non-threaded irq handling. Also we drop the bit setting for "RXDECINV" at register "BBREG1", we do a driectly full write of register "BBREG1", because it contains the bit RXDECINV only. Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com> Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent 6844a0e commit c91a301

File tree

1 file changed

+118
-164
lines changed

1 file changed

+118
-164
lines changed

drivers/net/ieee802154/mrf24j40.c

Lines changed: 118 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,20 @@ struct mrf24j40 {
167167
u8 tx_post_buf[2];
168168
struct spi_transfer tx_post_trx;
169169

170+
/* for protect/unprotect/read length rxfifo */
171+
struct spi_message rx_msg;
172+
u8 rx_buf[3];
173+
struct spi_transfer rx_trx;
174+
175+
/* receive handling */
176+
struct spi_message rx_buf_msg;
177+
u8 rx_addr_buf[2];
178+
struct spi_transfer rx_addr_trx;
179+
u8 rx_lqi_buf[2];
180+
struct spi_transfer rx_lqi_trx;
181+
u8 rx_fifo_buf[RX_FIFO_SIZE];
182+
struct spi_transfer rx_fifo_buf_trx;
183+
170184
struct mutex buffer_mutex; /* only used to protect buf */
171185
u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
172186
};
@@ -472,32 +486,6 @@ static const struct regmap_bus mrf24j40_long_regmap_bus = {
472486
.val_format_endian_default = REGMAP_ENDIAN_BIG,
473487
};
474488

475-
static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value)
476-
{
477-
int ret;
478-
struct spi_message msg;
479-
struct spi_transfer xfer = {
480-
.len = 2,
481-
.tx_buf = devrec->buf,
482-
.rx_buf = devrec->buf,
483-
};
484-
485-
spi_message_init(&msg);
486-
spi_message_add_tail(&xfer, &msg);
487-
488-
mutex_lock(&devrec->buffer_mutex);
489-
devrec->buf[0] = MRF24J40_WRITESHORT(reg);
490-
devrec->buf[1] = value;
491-
492-
ret = spi_sync(devrec->spi, &msg);
493-
if (ret)
494-
dev_err(printdev(devrec),
495-
"SPI write Failed for short register 0x%hhx\n", reg);
496-
497-
mutex_unlock(&devrec->buffer_mutex);
498-
return ret;
499-
}
500-
501489
static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
502490
{
503491
int ret = -1;
@@ -526,37 +514,6 @@ static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
526514
return ret;
527515
}
528516

529-
static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
530-
{
531-
int ret;
532-
u16 cmd;
533-
struct spi_message msg;
534-
struct spi_transfer xfer = {
535-
.len = 3,
536-
.tx_buf = devrec->buf,
537-
.rx_buf = devrec->buf,
538-
};
539-
540-
spi_message_init(&msg);
541-
spi_message_add_tail(&xfer, &msg);
542-
543-
cmd = MRF24J40_READLONG(reg);
544-
mutex_lock(&devrec->buffer_mutex);
545-
devrec->buf[0] = cmd >> 8 & 0xff;
546-
devrec->buf[1] = cmd & 0xff;
547-
devrec->buf[2] = 0;
548-
549-
ret = spi_sync(devrec->spi, &msg);
550-
if (ret)
551-
dev_err(printdev(devrec),
552-
"SPI read Failed for long register 0x%hx\n", reg);
553-
else
554-
*value = devrec->buf[2];
555-
556-
mutex_unlock(&devrec->buffer_mutex);
557-
return ret;
558-
}
559-
560517
static void write_tx_buf_complete(void *context)
561518
{
562519
struct mrf24j40 *devrec = context;
@@ -616,78 +573,6 @@ static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
616573
return write_tx_buf(devrec, 0x000, skb->data, skb->len);
617574
}
618575

619-
static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
620-
u8 *data, u8 *len, u8 *lqi)
621-
{
622-
u8 rx_len;
623-
u8 addr[2];
624-
u8 lqi_rssi[2];
625-
u16 cmd;
626-
int ret;
627-
struct spi_message msg;
628-
struct spi_transfer addr_xfer = {
629-
.len = 2,
630-
.tx_buf = &addr,
631-
};
632-
struct spi_transfer data_xfer = {
633-
.len = 0x0, /* set below */
634-
.rx_buf = data,
635-
};
636-
struct spi_transfer status_xfer = {
637-
.len = 2,
638-
.rx_buf = &lqi_rssi,
639-
};
640-
641-
/* Get the length of the data in the RX FIFO. The length in this
642-
* register exclues the 1-byte length field at the beginning. */
643-
ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len);
644-
if (ret)
645-
goto out;
646-
647-
/* Range check the RX FIFO length, accounting for the one-byte
648-
* length field at the beginning. */
649-
if (rx_len > RX_FIFO_SIZE-1) {
650-
dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n");
651-
rx_len = RX_FIFO_SIZE-1;
652-
}
653-
654-
if (rx_len > *len) {
655-
/* Passed in buffer wasn't big enough. Should never happen. */
656-
dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n");
657-
rx_len = *len;
658-
}
659-
660-
/* Set up the commands to read the data. */
661-
cmd = MRF24J40_READLONG(REG_RX_FIFO+1);
662-
addr[0] = cmd >> 8 & 0xff;
663-
addr[1] = cmd & 0xff;
664-
data_xfer.len = rx_len;
665-
666-
spi_message_init(&msg);
667-
spi_message_add_tail(&addr_xfer, &msg);
668-
spi_message_add_tail(&data_xfer, &msg);
669-
spi_message_add_tail(&status_xfer, &msg);
670-
671-
ret = spi_sync(devrec->spi, &msg);
672-
if (ret) {
673-
dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n");
674-
goto out;
675-
}
676-
677-
*lqi = lqi_rssi[0];
678-
*len = rx_len;
679-
680-
#ifdef DEBUG
681-
print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
682-
DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
683-
pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
684-
lqi_rssi[0], lqi_rssi[1]);
685-
#endif
686-
687-
out:
688-
return ret;
689-
}
690-
691576
static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
692577
{
693578
/* TODO: */
@@ -823,53 +708,98 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
823708
return 0;
824709
}
825710

826-
static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
711+
static void mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec)
827712
{
828-
u8 len = RX_FIFO_SIZE;
829-
u8 lqi = 0;
830-
u8 val;
831-
int ret = 0;
832-
int ret2;
833-
struct sk_buff *skb;
713+
int ret;
834714

835-
/* Turn off reception of packets off the air. This prevents the
836-
* device from overwriting the buffer while we're reading it. */
837-
ret = read_short_reg(devrec, REG_BBREG1, &val);
715+
/* Turn back on reception of packets off the air. */
716+
devrec->rx_msg.complete = NULL;
717+
devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
718+
devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */
719+
ret = spi_async(devrec->spi, &devrec->rx_msg);
838720
if (ret)
839-
goto out;
840-
val |= 4; /* SET RXDECINV */
841-
write_short_reg(devrec, REG_BBREG1, val);
721+
dev_err(printdev(devrec), "failed to unlock rx buffer\n");
722+
}
842723

843-
skb = dev_alloc_skb(len);
724+
static void mrf24j40_handle_rx_read_buf_complete(void *context)
725+
{
726+
struct mrf24j40 *devrec = context;
727+
u8 len = devrec->rx_buf[2];
728+
u8 rx_local_buf[RX_FIFO_SIZE];
729+
struct sk_buff *skb;
730+
731+
memcpy(rx_local_buf, devrec->rx_fifo_buf, len);
732+
mrf24j40_handle_rx_read_buf_unlock(devrec);
733+
734+
skb = dev_alloc_skb(IEEE802154_MTU);
844735
if (!skb) {
845-
ret = -ENOMEM;
846-
goto out;
736+
dev_err(printdev(devrec), "failed to allocate skb\n");
737+
return;
847738
}
848739

849-
ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi);
850-
if (ret < 0) {
851-
dev_err(printdev(devrec), "Failure reading RX FIFO\n");
852-
kfree_skb(skb);
853-
ret = -EINVAL;
854-
goto out;
740+
memcpy(skb_put(skb, len), rx_local_buf, len);
741+
ieee802154_rx_irqsafe(devrec->hw, skb, 0);
742+
743+
#ifdef DEBUG
744+
print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1,
745+
rx_local_buf, len, 0);
746+
pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
747+
devrec->rx_lqi_buf[0], devrec->rx_lqi_buf[1]);
748+
#endif
749+
}
750+
751+
static void mrf24j40_handle_rx_read_buf(void *context)
752+
{
753+
struct mrf24j40 *devrec = context;
754+
u16 cmd;
755+
int ret;
756+
757+
/* if length is invalid read the full MTU */
758+
if (!ieee802154_is_valid_psdu_len(devrec->rx_buf[2]))
759+
devrec->rx_buf[2] = IEEE802154_MTU;
760+
761+
cmd = MRF24J40_READLONG(REG_RX_FIFO + 1);
762+
devrec->rx_addr_buf[0] = cmd >> 8 & 0xff;
763+
devrec->rx_addr_buf[1] = cmd & 0xff;
764+
devrec->rx_fifo_buf_trx.len = devrec->rx_buf[2];
765+
ret = spi_async(devrec->spi, &devrec->rx_buf_msg);
766+
if (ret) {
767+
dev_err(printdev(devrec), "failed to read rx buffer\n");
768+
mrf24j40_handle_rx_read_buf_unlock(devrec);
855769
}
770+
}
856771

857-
/* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
858-
* also from a workqueue). I think irqsafe is not necessary here.
859-
* Can someone confirm? */
860-
ieee802154_rx_irqsafe(devrec->hw, skb, lqi);
772+
static void mrf24j40_handle_rx_read_len(void *context)
773+
{
774+
struct mrf24j40 *devrec = context;
775+
u16 cmd;
776+
int ret;
861777

862-
dev_dbg(printdev(devrec), "RX Handled\n");
778+
/* read the length of received frame */
779+
devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf;
780+
devrec->rx_trx.len = 3;
781+
cmd = MRF24J40_READLONG(REG_RX_FIFO);
782+
devrec->rx_buf[0] = cmd >> 8 & 0xff;
783+
devrec->rx_buf[1] = cmd & 0xff;
863784

864-
out:
865-
/* Turn back on reception of packets off the air. */
866-
ret2 = read_short_reg(devrec, REG_BBREG1, &val);
867-
if (ret2)
868-
return ret2;
869-
val &= ~0x4; /* Clear RXDECINV */
870-
write_short_reg(devrec, REG_BBREG1, val);
785+
ret = spi_async(devrec->spi, &devrec->rx_msg);
786+
if (ret) {
787+
dev_err(printdev(devrec), "failed to read rx buffer length\n");
788+
mrf24j40_handle_rx_read_buf_unlock(devrec);
789+
}
790+
}
871791

872-
return ret;
792+
static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
793+
{
794+
/* Turn off reception of packets off the air. This prevents the
795+
* device from overwriting the buffer while we're reading it.
796+
*/
797+
devrec->rx_msg.complete = mrf24j40_handle_rx_read_len;
798+
devrec->rx_trx.len = 2;
799+
devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
800+
devrec->rx_buf[1] = 0x04; /* SET RXDECINV */
801+
802+
return spi_async(devrec->spi, &devrec->rx_msg);
873803
}
874804

875805
static const struct ieee802154_ops mrf24j40_ops = {
@@ -1025,6 +955,29 @@ mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec)
1025955
spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg);
1026956
}
1027957

958+
static void
959+
mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec)
960+
{
961+
spi_message_init(&devrec->rx_msg);
962+
devrec->rx_msg.context = devrec;
963+
devrec->rx_trx.len = 2;
964+
devrec->rx_trx.tx_buf = devrec->rx_buf;
965+
devrec->rx_trx.rx_buf = devrec->rx_buf;
966+
spi_message_add_tail(&devrec->rx_trx, &devrec->rx_msg);
967+
968+
spi_message_init(&devrec->rx_buf_msg);
969+
devrec->rx_buf_msg.context = devrec;
970+
devrec->rx_buf_msg.complete = mrf24j40_handle_rx_read_buf_complete;
971+
devrec->rx_addr_trx.len = 2;
972+
devrec->rx_addr_trx.tx_buf = devrec->rx_addr_buf;
973+
spi_message_add_tail(&devrec->rx_addr_trx, &devrec->rx_buf_msg);
974+
devrec->rx_fifo_buf_trx.rx_buf = devrec->rx_fifo_buf;
975+
spi_message_add_tail(&devrec->rx_fifo_buf_trx, &devrec->rx_buf_msg);
976+
devrec->rx_lqi_trx.len = 2;
977+
devrec->rx_lqi_trx.rx_buf = devrec->rx_lqi_buf;
978+
spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg);
979+
}
980+
1028981
static void mrf24j40_phy_setup(struct mrf24j40 *devrec)
1029982
{
1030983
ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
@@ -1054,6 +1007,7 @@ static int mrf24j40_probe(struct spi_device *spi)
10541007
devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT;
10551008

10561009
mrf24j40_setup_tx_spi_messages(devrec);
1010+
mrf24j40_setup_rx_spi_messages(devrec);
10571011

10581012
devrec->regmap_short = devm_regmap_init_spi(spi,
10591013
&mrf24j40_short_regmap);

0 commit comments

Comments
 (0)