aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2017-11-28 07:53:15 -0500
committerStefan Schmidt <stefan@osg.samsung.com>2017-11-29 10:49:41 -0500
commit8f1878a182dcc5a15a57c7fc7d8182bea0733dfa (patch)
treebb933e39458a1f36bff86e8d3dd973689cbd2910
parentc78c1b01394406182fab5caff25ac58f754c702d (diff)
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>
-rw-r--r--drivers/net/ieee802154/adf7242.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c
index 548bec16906e..64f1b1e77bc0 100644
--- a/drivers/net/ieee802154/adf7242.c
+++ b/drivers/net/ieee802154/adf7242.c
@@ -563,6 +563,22 @@ static int adf7242_verify_firmware(struct adf7242_local *lp,
563 return 0; 563 return 0;
564} 564}
565 565
566static 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
573static 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
566static int adf7242_set_txpower(struct ieee802154_hw *hw, int mbm) 582static int adf7242_set_txpower(struct ieee802154_hw *hw, int mbm)
567{ 583{
568 struct adf7242_local *lp = hw->priv; 584 struct adf7242_local *lp = hw->priv;
@@ -666,7 +682,7 @@ static int adf7242_start(struct ieee802154_hw *hw)
666 struct adf7242_local *lp = hw->priv; 682 struct adf7242_local *lp = hw->priv;
667 683
668 adf7242_cmd(lp, CMD_RC_PHY_RDY); 684 adf7242_cmd(lp, CMD_RC_PHY_RDY);
669 adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF); 685 adf7242_clear_irqstat(lp);
670 enable_irq(lp->spi->irq); 686 enable_irq(lp->spi->irq);
671 set_bit(FLAG_START, &lp->flags); 687 set_bit(FLAG_START, &lp->flags);
672 688
@@ -677,10 +693,10 @@ static void adf7242_stop(struct ieee802154_hw *hw)
677{ 693{
678 struct adf7242_local *lp = hw->priv; 694 struct adf7242_local *lp = hw->priv;
679 695
696 disable_irq(lp->spi->irq);
680 adf7242_cmd(lp, CMD_RC_IDLE); 697 adf7242_cmd(lp, CMD_RC_IDLE);
681 clear_bit(FLAG_START, &lp->flags); 698 clear_bit(FLAG_START, &lp->flags);
682 disable_irq(lp->spi->irq); 699 adf7242_clear_irqstat(lp);
683 adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF);
684} 700}
685 701
686static int adf7242_channel(struct ieee802154_hw *hw, u8 page, u8 channel) 702static 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)
795 struct adf7242_local *lp = hw->priv; 811 struct adf7242_local *lp = hw->priv;
796 int ret; 812 int ret;
797 813
814 /* ensure existing instances of the IRQ handler have completed */
815 disable_irq(lp->spi->irq);
798 set_bit(FLAG_XMIT, &lp->flags); 816 set_bit(FLAG_XMIT, &lp->flags);
799 reinit_completion(&lp->tx_complete); 817 reinit_completion(&lp->tx_complete);
800 adf7242_cmd(lp, CMD_RC_PHY_RDY); 818 adf7242_cmd(lp, CMD_RC_PHY_RDY);
819 adf7242_clear_irqstat(lp);
801 820
802 ret = adf7242_write_fbuf(lp, skb->data, skb->len); 821 ret = adf7242_write_fbuf(lp, skb->data, skb->len);
803 if (ret) 822 if (ret)
@@ -806,6 +825,7 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
806 ret = adf7242_cmd(lp, CMD_RC_CSMACA); 825 ret = adf7242_cmd(lp, CMD_RC_CSMACA);
807 if (ret) 826 if (ret)
808 goto err; 827 goto err;
828 enable_irq(lp->spi->irq);
809 829
810 ret = wait_for_completion_interruptible_timeout(&lp->tx_complete, 830 ret = wait_for_completion_interruptible_timeout(&lp->tx_complete,
811 HZ / 10); 831 HZ / 10);
@@ -828,7 +848,7 @@ static int adf7242_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
828 848
829err: 849err:
830 clear_bit(FLAG_XMIT, &lp->flags); 850 clear_bit(FLAG_XMIT, &lp->flags);
831 adf7242_cmd(lp, CMD_RC_RX); 851 adf7242_cmd_rx(lp);
832 852
833 return ret; 853 return ret;
834} 854}
@@ -852,7 +872,7 @@ static int adf7242_rx(struct adf7242_local *lp)
852 872
853 skb = dev_alloc_skb(len); 873 skb = dev_alloc_skb(len);
854 if (!skb) { 874 if (!skb) {
855 adf7242_cmd(lp, CMD_RC_RX); 875 adf7242_cmd_rx(lp);
856 return -ENOMEM; 876 return -ENOMEM;
857 } 877 }
858 878
@@ -860,14 +880,14 @@ static int adf7242_rx(struct adf7242_local *lp)
860 ret = adf7242_read_fbuf(lp, data, len, true); 880 ret = adf7242_read_fbuf(lp, data, len, true);
861 if (ret < 0) { 881 if (ret < 0) {
862 kfree_skb(skb); 882 kfree_skb(skb);
863 adf7242_cmd(lp, CMD_RC_RX); 883 adf7242_cmd_rx(lp);
864 return ret; 884 return ret;
865 } 885 }
866 886
867 lqi = data[len - 2]; 887 lqi = data[len - 2];
868 lp->rssi = data[len - 1]; 888 lp->rssi = data[len - 1];
869 889
870 adf7242_cmd(lp, CMD_RC_RX); 890 ret = adf7242_cmd_rx(lp);
871 891
872 skb_trim(skb, len - 2); /* Don't put RSSI/LQI or CRC into the frame */ 892 skb_trim(skb, len - 2); /* Don't put RSSI/LQI or CRC into the frame */
873 893
@@ -876,7 +896,7 @@ static int adf7242_rx(struct adf7242_local *lp)
876 dev_dbg(&lp->spi->dev, "%s: ret=%d len=%d lqi=%d rssi=%d\n", 896 dev_dbg(&lp->spi->dev, "%s: ret=%d len=%d lqi=%d rssi=%d\n",
877 __func__, ret, (int)len, (int)lqi, lp->rssi); 897 __func__, ret, (int)len, (int)lqi, lp->rssi);
878 898
879 return 0; 899 return ret;
880} 900}
881 901
882static const struct ieee802154_ops adf7242_ops = { 902static const struct ieee802154_ops adf7242_ops = {
@@ -932,10 +952,7 @@ static irqreturn_t adf7242_isr(int irq, void *data)
932 unsigned int xmit; 952 unsigned int xmit;
933 u8 irq1; 953 u8 irq1;
934 954
935 adf7242_wait_status(lp, RC_STATUS_PHY_RDY, RC_STATUS_MASK, __LINE__);
936
937 adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1); 955 adf7242_read_reg(lp, REG_IRQ1_SRC1, &irq1);
938 adf7242_write_reg(lp, REG_IRQ1_SRC1, irq1);
939 956
940 if (!(irq1 & (IRQ_RX_PKT_RCVD | IRQ_CSMA_CA))) 957 if (!(irq1 & (IRQ_RX_PKT_RCVD | IRQ_CSMA_CA)))
941 dev_err(&lp->spi->dev, "%s :ERROR IRQ1 = 0x%X\n", 958 dev_err(&lp->spi->dev, "%s :ERROR IRQ1 = 0x%X\n",
@@ -946,6 +963,9 @@ static irqreturn_t adf7242_isr(int irq, void *data)
946 xmit = test_bit(FLAG_XMIT, &lp->flags); 963 xmit = test_bit(FLAG_XMIT, &lp->flags);
947 964
948 if (xmit && (irq1 & IRQ_CSMA_CA)) { 965 if (xmit && (irq1 & IRQ_CSMA_CA)) {
966 adf7242_wait_status(lp, RC_STATUS_PHY_RDY,
967 RC_STATUS_MASK, __LINE__);
968
949 if (ADF7242_REPORT_CSMA_CA_STAT) { 969 if (ADF7242_REPORT_CSMA_CA_STAT) {
950 u8 astat; 970 u8 astat;
951 971
@@ -966,6 +986,7 @@ static irqreturn_t adf7242_isr(int irq, void *data)
966 lp->tx_stat = SUCCESS; 986 lp->tx_stat = SUCCESS;
967 } 987 }
968 complete(&lp->tx_complete); 988 complete(&lp->tx_complete);
989 adf7242_clear_irqstat(lp);
969 } else if (!xmit && (irq1 & IRQ_RX_PKT_RCVD) && 990 } else if (!xmit && (irq1 & IRQ_RX_PKT_RCVD) &&
970 (irq1 & IRQ_FRAME_VALID)) { 991 (irq1 & IRQ_FRAME_VALID)) {
971 adf7242_rx(lp); 992 adf7242_rx(lp);
@@ -974,16 +995,19 @@ static irqreturn_t adf7242_isr(int irq, void *data)
974 dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X\n", 995 dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X\n",
975 __func__, __LINE__, irq1); 996 __func__, __LINE__, irq1);
976 adf7242_cmd(lp, CMD_RC_PHY_RDY); 997 adf7242_cmd(lp, CMD_RC_PHY_RDY);
977 adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF); 998 adf7242_cmd_rx(lp);
978 adf7242_cmd(lp, CMD_RC_RX);
979 } else { 999 } else {
980 /* This can only be xmit without IRQ, likely a RX packet. 1000 /* This can only be xmit without IRQ, likely a RX packet.
981 * we get an TX IRQ shortly - do nothing or let the xmit 1001 * we get an TX IRQ shortly - do nothing or let the xmit
982 * timeout handle this 1002 * timeout handle this
983 */ 1003 */
1004
984 dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X, xmit %d\n", 1005 dev_dbg(&lp->spi->dev, "%s:%d : ERROR IRQ1 = 0x%X, xmit %d\n",
985 __func__, __LINE__, irq1, xmit); 1006 __func__, __LINE__, irq1, xmit);
1007 adf7242_wait_status(lp, RC_STATUS_PHY_RDY,
1008 RC_STATUS_MASK, __LINE__);
986 complete(&lp->tx_complete); 1009 complete(&lp->tx_complete);
1010 adf7242_clear_irqstat(lp);
987 } 1011 }
988 1012
989 return IRQ_HANDLED; 1013 return IRQ_HANDLED;
@@ -1003,7 +1027,7 @@ static int adf7242_soft_reset(struct adf7242_local *lp, int line)
1003 adf7242_set_promiscuous_mode(lp->hw, lp->promiscuous); 1027 adf7242_set_promiscuous_mode(lp->hw, lp->promiscuous);
1004 adf7242_set_csma_params(lp->hw, lp->min_be, lp->max_be, 1028 adf7242_set_csma_params(lp->hw, lp->min_be, lp->max_be,
1005 lp->max_cca_retries); 1029 lp->max_cca_retries);
1006 adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF); 1030 adf7242_clear_irqstat(lp);
1007 1031
1008 if (test_bit(FLAG_START, &lp->flags)) { 1032 if (test_bit(FLAG_START, &lp->flags)) {
1009 enable_irq(lp->spi->irq); 1033 enable_irq(lp->spi->irq);
@@ -1069,7 +1093,7 @@ static int adf7242_hw_init(struct adf7242_local *lp)
1069 adf7242_write_reg(lp, REG_IRQ1_EN0, 0); 1093 adf7242_write_reg(lp, REG_IRQ1_EN0, 0);
1070 adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | IRQ_CSMA_CA); 1094 adf7242_write_reg(lp, REG_IRQ1_EN1, IRQ_RX_PKT_RCVD | IRQ_CSMA_CA);
1071 1095
1072 adf7242_write_reg(lp, REG_IRQ1_SRC1, 0xFF); 1096 adf7242_clear_irqstat(lp);
1073 adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF); 1097 adf7242_write_reg(lp, REG_IRQ1_SRC0, 0xFF);
1074 1098
1075 adf7242_cmd(lp, CMD_RC_IDLE); 1099 adf7242_cmd(lp, CMD_RC_IDLE);