Skip to content

Commit 8f1878a

Browse files
mhennerichStefan Schmidt
authored andcommitted
net: ieee802154: adf7242: Rework IRQ and packet handling
* Stop unconditionally polling for RC_STATUS_PHY_RDY at the entry of the threaded IRQ handler. Once IRQ_RX_PKT_RCVD is received we can read immediately the packet from the buffer. However we still need to wait afterwards for RC_STATUS_PHY_RDY, to make sure that the ACK (in case requested) was processed and send out by the Radio Controller, before we issue the next CMD_RC_RX. This significantly reduces the overall time spend in the threaded IRQ handler. * Avoid raise condition between xmit and coincident packet reception, by disabling the IRQ and clearing the IRQ status upon xmit entry. * Introduce helper functions adf7242_clear_irqstat() and adf7242_cmd_rx() Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Stefan Schmidt <stefan@osg.samsung.com>
1 parent c78c1b0 commit 8f1878a

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

drivers/net/ieee802154/adf7242.c

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,22 @@ static int adf7242_verify_firmware(struct adf7242_local *lp,
563563
return 0;
564564
}
565565

566+
static void adf7242_clear_irqstat(struct adf7242_local *lp)
567+
{
568+
adf7242_write_reg(lp, REG_IRQ1_SRC1, IRQ_CCA_COMPLETE | IRQ_SFD_RX |
569+
IRQ_SFD_TX | IRQ_RX_PKT_RCVD | IRQ_TX_PKT_SENT |
570+
IRQ_FRAME_VALID | IRQ_ADDRESS_VALID | IRQ_CSMA_CA);
571+
}
572+
573+
static int adf7242_cmd_rx(struct adf7242_local *lp)
574+
{
575+
/* Wait until the ACK is sent */
576+
adf7242_wait_status(lp, RC_STATUS_PHY_RDY, RC_STATUS_MASK, __LINE__);
577+
adf7242_clear_irqstat(lp);
578+
579+
return adf7242_cmd(lp, CMD_RC_RX);
580+
}
581+
566582
static int adf7242_set_txpower(struct ieee802154_hw *hw, int mbm)
567583
{
568584
struct adf7242_local *lp = hw->priv;
@@ -666,7 +682,7 @@ static int adf7242_start(struct ieee802154_hw *hw)
666682
struct adf7242_local *lp = hw->priv;
667683

668684
adf7242_cmd(lp, CMD_RC_PHY_RDY);
669-
adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
685+
adf7242_clear_irqstat(lp);
670686
enable_irq(lp->spi->irq);
671687
set_bit(FLAG_START, &lp->flags);
672688

@@ -677,10 +693,10 @@ static void adf7242_stop(struct ieee802154_hw *hw)
677693
{
678694
struct adf7242_local *lp = hw->priv;
679695

696+
disable_irq(lp->spi->irq);
680697
adf7242_cmd(lp, CMD_RC_IDLE);
681698
clear_bit(FLAG_START, &lp->flags);
682-
disable_irq(lp->spi->irq);
683-
adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
699+
adf7242_clear_irqstat(lp);
684700
}
685701

686702
static int adf7242_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
@@ -795,9 +811,12 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
795811
struct adf7242_local *lp = hw->priv;
796812
int ret;
797813

814+
/* ensure existing instances of the IRQ handler have completed */
815+
disable_irq(lp->spi->irq);
798816
set_bit(FLAG_XMIT, &lp->flags);
799817
reinit_completion(&lp->tx_complete);
800818
adf7242_cmd(lp, CMD_RC_PHY_RDY);
819+
adf7242_clear_irqstat(lp);
801820

802821
ret = adf7242_write_fbuf(lp, skb->data, skb->len);
803822
if (ret)
@@ -806,6 +825,7 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
806825
ret = adf7242_cmd(lp, CMD_RC_CSMACA);
807826
if (ret)
808827
goto err;
828+
enable_irq(lp->spi->irq);
809829

810830
ret = wait_for_completion_interruptible_timeout(&lp->tx_complete,
811831
HZ / 10);
@@ -828,7 +848,7 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
828848

829849
err:
830850
clear_bit(FLAG_XMIT, &lp->flags);
831-
adf7242_cmd(lp, CMD_RC_RX);
851+
adf7242_cmd_rx(lp);
832852

833853
return ret;
834854
}
@@ -852,22 +872,22 @@ static int adf7242_rx(struct adf7242_local *lp)
852872

853873
skb = dev_alloc_skb(len);
854874
if (!skb) {
855-
adf7242_cmd(lp, CMD_RC_RX);
875+
adf7242_cmd_rx(lp);
856876
return -ENOMEM;
857877
}
858878

859879
data = skb_put(skb, len);
860880
ret = adf7242_read_fbuf(lp, data, len, true);
861881
if (ret < 0) {
862882
kfree_skb(skb);
863-
adf7242_cmd(lp, CMD_RC_RX);
883+
adf7242_cmd_rx(lp);
864884
return ret;
865885
}
866886

867887
lqi = data[len - 2];
868888
lp->rssi = data[len - 1];
869889

870-
adf7242_cmd(lp, CMD_RC_RX);
890+
ret = adf7242_cmd_rx(lp);
871891

872892
skb_trim(skb, len - 2); /* Don't put RSSI/LQI or CRC into the frame */
873893

@@ -876,7 +896,7 @@ static int adf7242_rx(struct adf7242_local *lp)
876896
dev_dbg(&lp->spi->dev, "%s: ret=%d len=%d lqi=%d rssi=%d\n",
877897
__func__, ret, (int)len, (int)lqi, lp->rssi);
878898

879-
return 0;
899+
return ret;
880900
}
881901

882902
static const struct ieee802154_ops adf7242_ops = {
@@ -932,10 +952,7 @@ static irqreturn_t adf7242_isr(int irq, void *data)
932952
unsigned int xmit;
933953
u8 irq1;
934954

935-
adf7242_wait_status(lp, RC_STATUS_PHY_RDY, RC_STATUS_MASK, __LINE__);
936-
937955
adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
938-
adf7242_write_reg(lp, REG_IRQ1_SRC1, irq1);
939956

940957
if (!(irq1 & (IRQ_RX_PKT_RCVD | IRQ_CSMA_CA)))
941958
dev_err(&lp->spi->dev, "%s :ERROR IRQ1 = 0x%X\n",
@@ -946,6 +963,9 @@ static irqreturn_t adf7242_isr(int irq, void *data)
946963
xmit = test_bit(FLAG_XMIT, &lp->flags);
947964

948965
if (xmit && (irq1 & IRQ_CSMA_CA)) {
966+
adf7242_wait_status(lp, RC_STATUS_PHY_RDY,
967+
RC_STATUS_MASK, __LINE__);
968+
949969
if (ADF7242_REPORT_CSMA_CA_STAT) {
950970
u8 astat;
951971

@@ -966,6 +986,7 @@ static irqreturn_t adf7242_isr(int irq, void *data)
966986
lp->tx_stat = SUCCESS;
967987
}
968988
complete(&lp->tx_complete);
989+
adf7242_clear_irqstat(lp);
969990
} else if (!xmit && (irq1 & IRQ_RX_PKT_RCVD) &&
970991
(irq1 & IRQ_FRAME_VALID)) {
971992
adf7242_rx(lp);
@@ -974,16 +995,19 @@ static irqreturn_t adf7242_isr(int irq, void *data)
974995
dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X\n",
975996
__func__, __LINE__, irq1);
976997
adf7242_cmd(lp, CMD_RC_PHY_RDY);
977-
adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
978-
adf7242_cmd(lp, CMD_RC_RX);
998+
adf7242_cmd_rx(lp);
979999
} else {
9801000
/* This can only be xmit without IRQ, likely a RX packet.
9811001
* we get an TX IRQ shortly - do nothing or let the xmit
9821002
* timeout handle this
9831003
*/
1004+
9841005
dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X, xmit %d\n",
9851006
__func__, __LINE__, irq1, xmit);
1007+
adf7242_wait_status(lp, RC_STATUS_PHY_RDY,
1008+
RC_STATUS_MASK, __LINE__);
9861009
complete(&lp->tx_complete);
1010+
adf7242_clear_irqstat(lp);
9871011
}
9881012

9891013
return IRQ_HANDLED;
@@ -1003,7 +1027,7 @@ static int adf7242_soft_reset(struct adf7242_local *lp, int line)
10031027
adf7242_set_promiscuous_mode(lp->hw, lp->promiscuous);
10041028
adf7242_set_csma_params(lp->hw, lp->min_be, lp->max_be,
10051029
lp->max_cca_retries);
1006-
adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
1030+
adf7242_clear_irqstat(lp);
10071031

10081032
if (test_bit(FLAG_START, &lp->flags)) {
10091033
enable_irq(lp->spi->irq);
@@ -1069,7 +1093,7 @@ static int adf7242_hw_init(struct adf7242_local *lp)
10691093
adf7242_write_reg(lp, REG_IRQ1_EN0, 0);
10701094
adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | IRQ_CSMA_CA);
10711095

1072-
adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
1096+
adf7242_clear_irqstat(lp);
10731097
adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF);
10741098

10751099
adf7242_cmd(lp, CMD_RC_IDLE);

0 commit comments

Comments
 (0)