diff options
author | Ishizaki Kou <kou.ishizaki@toshiba.co.jp> | 2007-07-09 19:17:42 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 12:22:30 -0400 |
commit | 7a627558214664f0e071b2652fc37e4d7d3dce32 (patch) | |
tree | ccaa169e29df4f8ea82716a2489ac7451edf6efc | |
parent | b8a1fcee26126b566d9e28ba80c643a7a10543eb (diff) |
spidernet: improve interrupt handling
We intend this patch to improve spidernet interrupt handling to be
more strict. We had following problem and this patch solves it.
-when CONFIG_DEBUG_SHIRQ=y, request_irq() calls handler().
-when spider_net_open() is called, it calls request_irq() which calls
spider_net_interrupt().
-if some specific interrupt bit is set at this timing, it calls
netif_rx_schedule() and spider_net_poll() is scheduled.
-spider_net_open() calls netif_poll_enable() which clears the bit
__LINK_STATE_RX_SCHED.
-when spider_net_poll() is called, it calls netif_rx_complete() which
causes BUG_ON() because __LINK_STATE_RX_SCHED is not set.
Signed-off-by: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/spider_net.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index f5abb5279d4d..590b12c7246c 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -1441,11 +1441,17 @@ 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; | ||
1444 | u32 i; | 1445 | u32 i; |
1445 | int show_error = 1; | 1446 | int show_error = 1; |
1446 | 1447 | ||
1447 | error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); | 1448 | error_reg1 = spider_net_read_reg(card, SPIDER_NET_GHIINT1STS); |
1448 | error_reg2 = spider_net_read_reg(card, SPIDER_NET_GHIINT2STS); | 1449 | 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 | |||
1453 | error_reg1 &= mask_reg1; | ||
1454 | error_reg2 &= mask_reg2; | ||
1449 | 1455 | ||
1450 | /* check GHIINT0STS ************************************/ | 1456 | /* check GHIINT0STS ************************************/ |
1451 | if (status_reg) | 1457 | if (status_reg) |
@@ -1673,9 +1679,11 @@ spider_net_interrupt(int irq, void *ptr) | |||
1673 | { | 1679 | { |
1674 | struct net_device *netdev = ptr; | 1680 | struct net_device *netdev = ptr; |
1675 | struct spider_net_card *card = netdev_priv(netdev); | 1681 | struct spider_net_card *card = netdev_priv(netdev); |
1676 | u32 status_reg; | 1682 | u32 status_reg, mask_reg; |
1677 | 1683 | ||
1678 | status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); | 1684 | status_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0STS); |
1685 | mask_reg = spider_net_read_reg(card, SPIDER_NET_GHIINT0MSK); | ||
1686 | status_reg &= mask_reg; | ||
1679 | 1687 | ||
1680 | if (!status_reg) | 1688 | if (!status_reg) |
1681 | return IRQ_NONE; | 1689 | return IRQ_NONE; |
@@ -1717,6 +1725,38 @@ spider_net_poll_controller(struct net_device *netdev) | |||
1717 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | 1725 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
1718 | 1726 | ||
1719 | /** | 1727 | /** |
1728 | * spider_net_enable_interrupts - enable interrupts | ||
1729 | * @card: card structure | ||
1730 | * | ||
1731 | * spider_net_enable_interrupt enables several interrupts | ||
1732 | */ | ||
1733 | static void | ||
1734 | spider_net_enable_interrupts(struct spider_net_card *card) | ||
1735 | { | ||
1736 | spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, | ||
1737 | SPIDER_NET_INT0_MASK_VALUE); | ||
1738 | spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, | ||
1739 | SPIDER_NET_INT1_MASK_VALUE); | ||
1740 | spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, | ||
1741 | SPIDER_NET_INT2_MASK_VALUE); | ||
1742 | } | ||
1743 | |||
1744 | /** | ||
1745 | * spider_net_disable_interrupts - disable interrupts | ||
1746 | * @card: card structure | ||
1747 | * | ||
1748 | * spider_net_disable_interrupts disables all the interrupts | ||
1749 | */ | ||
1750 | static void | ||
1751 | spider_net_disable_interrupts(struct spider_net_card *card) | ||
1752 | { | ||
1753 | spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); | ||
1754 | spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); | ||
1755 | spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); | ||
1756 | spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); | ||
1757 | } | ||
1758 | |||
1759 | /** | ||
1720 | * spider_net_init_card - initializes the card | 1760 | * spider_net_init_card - initializes the card |
1721 | * @card: card structure | 1761 | * @card: card structure |
1722 | * | 1762 | * |
@@ -1736,6 +1776,7 @@ spider_net_init_card(struct spider_net_card *card) | |||
1736 | spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, | 1776 | spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, |
1737 | spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); | 1777 | spider_net_read_reg(card, SPIDER_NET_GMACOPEMD) | 0x4); |
1738 | 1778 | ||
1779 | spider_net_disable_interrupts(card); | ||
1739 | } | 1780 | } |
1740 | 1781 | ||
1741 | /** | 1782 | /** |
@@ -1823,14 +1864,6 @@ spider_net_enable_card(struct spider_net_card *card) | |||
1823 | spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, | 1864 | spider_net_write_reg(card, SPIDER_NET_GMACOPEMD, |
1824 | SPIDER_NET_OPMODE_VALUE); | 1865 | SPIDER_NET_OPMODE_VALUE); |
1825 | 1866 | ||
1826 | /* set interrupt mask registers */ | ||
1827 | spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, | ||
1828 | SPIDER_NET_INT0_MASK_VALUE); | ||
1829 | spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, | ||
1830 | SPIDER_NET_INT1_MASK_VALUE); | ||
1831 | spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, | ||
1832 | SPIDER_NET_INT2_MASK_VALUE); | ||
1833 | |||
1834 | spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, | 1867 | spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, |
1835 | SPIDER_NET_GDTBSTA); | 1868 | SPIDER_NET_GDTBSTA); |
1836 | } | 1869 | } |
@@ -2007,6 +2040,8 @@ spider_net_open(struct net_device *netdev) | |||
2007 | netif_carrier_on(netdev); | 2040 | netif_carrier_on(netdev); |
2008 | netif_poll_enable(netdev); | 2041 | netif_poll_enable(netdev); |
2009 | 2042 | ||
2043 | spider_net_enable_interrupts(card); | ||
2044 | |||
2010 | return 0; | 2045 | return 0; |
2011 | 2046 | ||
2012 | register_int_failed: | 2047 | register_int_failed: |
@@ -2179,11 +2214,7 @@ spider_net_stop(struct net_device *netdev) | |||
2179 | del_timer_sync(&card->tx_timer); | 2214 | del_timer_sync(&card->tx_timer); |
2180 | del_timer_sync(&card->aneg_timer); | 2215 | del_timer_sync(&card->aneg_timer); |
2181 | 2216 | ||
2182 | /* disable/mask all interrupts */ | 2217 | spider_net_disable_interrupts(card); |
2183 | spider_net_write_reg(card, SPIDER_NET_GHIINT0MSK, 0); | ||
2184 | spider_net_write_reg(card, SPIDER_NET_GHIINT1MSK, 0); | ||
2185 | spider_net_write_reg(card, SPIDER_NET_GHIINT2MSK, 0); | ||
2186 | spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0); | ||
2187 | 2218 | ||
2188 | free_irq(netdev->irq, netdev); | 2219 | free_irq(netdev->irq, netdev); |
2189 | 2220 | ||