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) { |
