diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2010-10-19 20:02:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-21 07:27:03 -0400 |
commit | 5601b2dfae86198667dd6e075a074fbef0c83423 (patch) | |
tree | f099538e1603c4c326228cd4cd21cf1c055b3938 | |
parent | 1e55659ce6ddb5247cee0b1f720d77a799902b85 (diff) |
can: mcp251x: fix endless loop in interrupt handler if CANINTF_MERRF is set
Commit d3cd15657516141adce387810be8cb377baf020e introduced a bug, the
interrupt handler would loop endlessly if the CANINTF_MERRF bit is set,
because it's not cleared.
This patch fixes the problem by masking out the CANINTF_MERRF and all other
non interesting bits.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/can/mcp251x.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index c664be261e98..59f40bce1ffc 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c | |||
@@ -125,8 +125,9 @@ | |||
125 | # define CANINTF_TX0IF 0x04 | 125 | # define CANINTF_TX0IF 0x04 |
126 | # define CANINTF_RX1IF 0x02 | 126 | # define CANINTF_RX1IF 0x02 |
127 | # define CANINTF_RX0IF 0x01 | 127 | # define CANINTF_RX0IF 0x01 |
128 | # define CANINTF_ERR_TX \ | 128 | # define CANINTF_RX (CANINTF_RX0IF | CANINTF_RX1IF) |
129 | (CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) | 129 | # define CANINTF_TX (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) |
130 | # define CANINTF_ERR (CANINTF_ERRIF) | ||
130 | #define EFLG 0x2d | 131 | #define EFLG 0x2d |
131 | # define EFLG_EWARN 0x01 | 132 | # define EFLG_EWARN 0x01 |
132 | # define EFLG_RXWAR 0x02 | 133 | # define EFLG_RXWAR 0x02 |
@@ -790,6 +791,9 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | |||
790 | 791 | ||
791 | mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); | 792 | mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); |
792 | 793 | ||
794 | /* mask out flags we don't care about */ | ||
795 | intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR; | ||
796 | |||
793 | /* receive buffer 0 */ | 797 | /* receive buffer 0 */ |
794 | if (intf & CANINTF_RX0IF) { | 798 | if (intf & CANINTF_RX0IF) { |
795 | mcp251x_hw_rx(spi, 0); | 799 | mcp251x_hw_rx(spi, 0); |
@@ -810,8 +814,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | |||
810 | } | 814 | } |
811 | 815 | ||
812 | /* any error or tx interrupt we need to clear? */ | 816 | /* any error or tx interrupt we need to clear? */ |
813 | if (intf & CANINTF_ERR_TX) | 817 | if (intf & (CANINTF_ERR | CANINTF_TX)) |
814 | clear_intf |= intf & CANINTF_ERR_TX; | 818 | clear_intf |= intf & (CANINTF_ERR | CANINTF_TX); |
815 | if (clear_intf) | 819 | if (clear_intf) |
816 | mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); | 820 | mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); |
817 | 821 | ||
@@ -887,7 +891,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | |||
887 | if (intf == 0) | 891 | if (intf == 0) |
888 | break; | 892 | break; |
889 | 893 | ||
890 | if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) { | 894 | if (intf & CANINTF_TX) { |
891 | net->stats.tx_packets++; | 895 | net->stats.tx_packets++; |
892 | net->stats.tx_bytes += priv->tx_len - 1; | 896 | net->stats.tx_bytes += priv->tx_len - 1; |
893 | if (priv->tx_len) { | 897 | if (priv->tx_len) { |