aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIshizaki Kou <kou.ishizaki@toshiba.co.jp>2007-07-09 19:17:42 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-10 12:22:30 -0400
commit7a627558214664f0e071b2652fc37e4d7d3dce32 (patch)
treeccaa169e29df4f8ea82716a2489ac7451edf6efc /drivers
parentb8a1fcee26126b566d9e28ba80c643a7a10543eb (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/spider_net.c59
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
1441spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg) 1441spider_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 */
1733static void
1734spider_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 */
1750static void
1751spider_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
2012register_int_failed: 2047register_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