Skip to content

Commit 6844a0e

Browse files
alexaringholtmann
authored andcommitted
mrf24j40: rework tx handling to async tx handling
This patch reworks the current transmit API to spi_async handling. We removed the error handling check, because mac802154 has no chance to report it. Also the transmit timeout handling can't be handled by xmit async handling, for this usecase we need to implement the netdev watchdog. These are all unlikely cases which we drop now and should be provided by netdev watchdog. We also drop the bit setting for TXNACKREQ at register TXNCON, this is not necessary. The TXNCON register should set only once for each frame, previous settings doesn't matter. 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 79750ac commit 6844a0e

File tree

1 file changed

+78
-83
lines changed

1 file changed

+78
-83
lines changed

drivers/net/ieee802154/mrf24j40.c

Lines changed: 78 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,22 @@ struct mrf24j40 {
152152

153153
struct regmap *regmap_short;
154154
struct regmap *regmap_long;
155+
156+
/* for writing txfifo */
157+
struct spi_message tx_msg;
158+
u8 tx_hdr_buf[2];
159+
struct spi_transfer tx_hdr_trx;
160+
u8 tx_len_buf[2];
161+
struct spi_transfer tx_len_trx;
162+
struct spi_transfer tx_buf_trx;
163+
struct sk_buff *tx_skb;
164+
165+
/* post transmit message to send frame out */
166+
struct spi_message tx_post_msg;
167+
u8 tx_post_buf[2];
168+
struct spi_transfer tx_post_trx;
169+
155170
struct mutex buffer_mutex; /* only used to protect buf */
156-
struct completion tx_complete;
157171
u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
158172
};
159173

@@ -543,55 +557,65 @@ static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
543557
return ret;
544558
}
545559

560+
static void write_tx_buf_complete(void *context)
561+
{
562+
struct mrf24j40 *devrec = context;
563+
__le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb);
564+
u8 val = 0x01;
565+
int ret;
566+
567+
if (ieee802154_is_ackreq(fc))
568+
val |= 0x04;
569+
570+
devrec->tx_post_msg.complete = NULL;
571+
devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON);
572+
devrec->tx_post_buf[1] = val;
573+
574+
ret = spi_async(devrec->spi, &devrec->tx_post_msg);
575+
if (ret)
576+
dev_err(printdev(devrec), "SPI write Failed for transmit buf\n");
577+
}
578+
546579
/* This function relies on an undocumented write method. Once a write command
547580
and address is set, as many bytes of data as desired can be clocked into
548581
the device. The datasheet only shows setting one byte at a time. */
549582
static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
550583
const u8 *data, size_t length)
551584
{
552-
int ret;
553585
u16 cmd;
554-
u8 lengths[2];
555-
struct spi_message msg;
556-
struct spi_transfer addr_xfer = {
557-
.len = 2,
558-
.tx_buf = devrec->buf,
559-
};
560-
struct spi_transfer lengths_xfer = {
561-
.len = 2,
562-
.tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */
563-
};
564-
struct spi_transfer data_xfer = {
565-
.len = length,
566-
.tx_buf = data,
567-
};
586+
int ret;
568587

569588
/* Range check the length. 2 bytes are used for the length fields.*/
570589
if (length > TX_FIFO_SIZE-2) {
571590
dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n");
572591
length = TX_FIFO_SIZE-2;
573592
}
574593

575-
spi_message_init(&msg);
576-
spi_message_add_tail(&addr_xfer, &msg);
577-
spi_message_add_tail(&lengths_xfer, &msg);
578-
spi_message_add_tail(&data_xfer, &msg);
579-
580594
cmd = MRF24J40_WRITELONG(reg);
581-
mutex_lock(&devrec->buffer_mutex);
582-
devrec->buf[0] = cmd >> 8 & 0xff;
583-
devrec->buf[1] = cmd & 0xff;
584-
lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
585-
lengths[1] = length; /* Total length */
586-
587-
ret = spi_sync(devrec->spi, &msg);
595+
devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff;
596+
devrec->tx_hdr_buf[1] = cmd & 0xff;
597+
devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
598+
devrec->tx_len_buf[1] = length; /* Total length */
599+
devrec->tx_buf_trx.tx_buf = data;
600+
devrec->tx_buf_trx.len = length;
601+
602+
ret = spi_async(devrec->spi, &devrec->tx_msg);
588603
if (ret)
589604
dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
590605

591-
mutex_unlock(&devrec->buffer_mutex);
592606
return ret;
593607
}
594608

609+
static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
610+
{
611+
struct mrf24j40 *devrec = hw->priv;
612+
613+
dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
614+
devrec->tx_skb = skb;
615+
616+
return write_tx_buf(devrec, 0x000, skb->data, skb->len);
617+
}
618+
595619
static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
596620
u8 *data, u8 *len, u8 *lqi)
597621
{
@@ -664,57 +688,6 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
664688
return ret;
665689
}
666690

667-
static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
668-
{
669-
struct mrf24j40 *devrec = hw->priv;
670-
u8 val;
671-
int ret = 0;
672-
673-
dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
674-
675-
ret = write_tx_buf(devrec, 0x000, skb->data, skb->len);
676-
if (ret)
677-
goto err;
678-
679-
reinit_completion(&devrec->tx_complete);
680-
681-
/* Set TXNTRIG bit of TXNCON to send packet */
682-
ret = read_short_reg(devrec, REG_TXNCON, &val);
683-
if (ret)
684-
goto err;
685-
val |= 0x1;
686-
/* Set TXNACKREQ if the ACK bit is set in the packet. */
687-
if (skb->data[0] & IEEE802154_FC_ACK_REQ)
688-
val |= 0x4;
689-
write_short_reg(devrec, REG_TXNCON, val);
690-
691-
/* Wait for the device to send the TX complete interrupt. */
692-
ret = wait_for_completion_interruptible_timeout(
693-
&devrec->tx_complete,
694-
5 * HZ);
695-
if (ret == -ERESTARTSYS)
696-
goto err;
697-
if (ret == 0) {
698-
dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n");
699-
ret = -ETIMEDOUT;
700-
goto err;
701-
}
702-
703-
/* Check for send error from the device. */
704-
ret = read_short_reg(devrec, REG_TXSTAT, &val);
705-
if (ret)
706-
goto err;
707-
if (val & 0x1) {
708-
dev_dbg(printdev(devrec), "Error Sending. Retry count exceeded\n");
709-
ret = -ECOMM; /* TODO: Better error code ? */
710-
} else
711-
dev_dbg(printdev(devrec), "Packet Sent\n");
712-
713-
err:
714-
715-
return ret;
716-
}
717-
718691
static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
719692
{
720693
/* TODO: */
@@ -901,7 +874,7 @@ static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
901874

902875
static const struct ieee802154_ops mrf24j40_ops = {
903876
.owner = THIS_MODULE,
904-
.xmit_sync = mrf24j40_tx,
877+
.xmit_async = mrf24j40_tx,
905878
.ed = mrf24j40_ed,
906879
.start = mrf24j40_start,
907880
.stop = mrf24j40_stop,
@@ -922,7 +895,7 @@ static irqreturn_t mrf24j40_isr(int irq, void *data)
922895

923896
/* Check for TX complete */
924897
if (intstat & 0x1)
925-
complete(&devrec->tx_complete);
898+
ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false);
926899

927900
/* Check for Rx */
928901
if (intstat & 0x8)
@@ -1031,6 +1004,27 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec)
10311004
return ret;
10321005
}
10331006

1007+
static void
1008+
mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec)
1009+
{
1010+
spi_message_init(&devrec->tx_msg);
1011+
devrec->tx_msg.context = devrec;
1012+
devrec->tx_msg.complete = write_tx_buf_complete;
1013+
devrec->tx_hdr_trx.len = 2;
1014+
devrec->tx_hdr_trx.tx_buf = devrec->tx_hdr_buf;
1015+
spi_message_add_tail(&devrec->tx_hdr_trx, &devrec->tx_msg);
1016+
devrec->tx_len_trx.len = 2;
1017+
devrec->tx_len_trx.tx_buf = devrec->tx_len_buf;
1018+
spi_message_add_tail(&devrec->tx_len_trx, &devrec->tx_msg);
1019+
spi_message_add_tail(&devrec->tx_buf_trx, &devrec->tx_msg);
1020+
1021+
spi_message_init(&devrec->tx_post_msg);
1022+
devrec->tx_post_msg.context = devrec;
1023+
devrec->tx_post_trx.len = 2;
1024+
devrec->tx_post_trx.tx_buf = devrec->tx_post_buf;
1025+
spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg);
1026+
}
1027+
10341028
static void mrf24j40_phy_setup(struct mrf24j40 *devrec)
10351029
{
10361030
ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
@@ -1059,6 +1053,8 @@ static int mrf24j40_probe(struct spi_device *spi)
10591053
devrec->hw->phy->supported.channels[0] = CHANNEL_MASK;
10601054
devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT;
10611055

1056+
mrf24j40_setup_tx_spi_messages(devrec);
1057+
10621058
devrec->regmap_short = devm_regmap_init_spi(spi,
10631059
&mrf24j40_short_regmap);
10641060
if (IS_ERR(devrec->regmap_short)) {
@@ -1089,7 +1085,6 @@ static int mrf24j40_probe(struct spi_device *spi)
10891085
}
10901086

10911087
mutex_init(&devrec->buffer_mutex);
1092-
init_completion(&devrec->tx_complete);
10931088

10941089
ret = mrf24j40_hw_init(devrec);
10951090
if (ret)

0 commit comments

Comments
 (0)