diff options
author | Ishizaki Kou <kou.ishizaki@toshiba.co.jp> | 2007-08-20 09:13:27 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-09-13 00:16:31 -0400 |
commit | a041fe2e8d0bd749b2416ef79adc416e24af7c63 (patch) | |
tree | da75b65fd154d284fae277d855bbeb9e225e24ba /drivers/net/spider_net.c | |
parent | 64251621796d5d4c0c4b6a6b6d845e4a43c63aee (diff) |
spidernet: fix interrupt reason recognition
This patch solves a problem that the spidernet driver sometimes fails
to handle IRQ.
The problem happens because,
- In Cell architecture, interrupts may arrive at an interrupt
controller, even if they are masked by the setting on registers of
devices. It happens when interrupt packets are sent just before
the interrupts are masked.
- spidernet interrupt handler compares interrupt reasons with
interrupt masks, so when such interrupts occurs, spidernet interrupt
handler returns IRQ_NONE.
- When all of interrupt handler return IRQ_NONE, linux kernel disables
the IRQ and it no longer delivers interrupts to the interrupt handlers.
spidernet doesn't work after above sequence, because it can't receive
interrupts.
This patch changes spidernet interrupt handler that it compares
interrupt reason with SPIDER_NET_INTX_MASK_VALUE.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/spider_net.c')
-rw-r--r-- | drivers/net/spider_net.c | 12 |
1 files changed, 4 insertions, 8 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 590b12c7246c..82d837ab4db9 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -1441,17 +1441,14 @@ static void | |||
1441 | spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) | 1441 | spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) |
1442 | { | 1442 | { |
1443 | u32 error_reg1, error_reg2; | 1443 | u32 error_reg1, error_reg2; |
1444 | u32 mask_reg1, mask_reg2; | ||
1445 | u32 i; | 1444 | u32 i; |
1446 | int show_error = 1; | 1445 | int show_error = 1; |
1447 | 1446 | ||
1448 | error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); | 1447 | error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); |
1449 | error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); | 1448 | error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); |
1450 | mask_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1MSK); | ||
1451 | mask_reg2 = spider_net_read_reg(card,SPIDER_NET_GHIINT2MSK); | ||
1452 | 1449 | ||
1453 | error_reg1 &= mask_reg1; | 1450 | error_reg1 &= SPIDER_NET_INT1_MASK_VALUE; |
1454 | error_reg2 &= mask_reg2; | 1451 | error_reg2 &= SPIDER_NET_INT2_MASK_VALUE; |
1455 | 1452 | ||
1456 | /* check GHIINT0STS ************************************/ | 1453 | /* check GHIINT0STS ************************************/ |
1457 | if (status_reg) | 1454 | if (status_reg) |
@@ -1679,11 +1676,10 @@ spider_net_interrupt(int irq, void *ptr) | |||
1679 | { | 1676 | { |
1680 | struct net_device *netdev = ptr; | 1677 | struct net_device *netdev = ptr; |
1681 | struct spider_net_card *card = netdev_priv(netdev); | 1678 | struct spider_net_card *card = netdev_priv(netdev); |
1682 | u32 status_reg, mask_reg; | 1679 | u32 status_reg; |
1683 | 1680 | ||
1684 | status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); | 1681 | status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); |
1685 | mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); | 1682 | status_reg &= SPIDER_NET_INT0_MASK_VALUE; |
1686 | status_reg &= mask_reg; | ||
1687 | 1683 | ||
1688 | if (!status_reg) | 1684 | if (!status_reg) |
1689 | return IRQ_NONE; | 1685 | return IRQ_NONE; |