aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-05-08 18:11:27 -0400
committerStephen Hemminger <shemminger@osdl.org>2006-05-08 19:00:24 -0400
commit1e5f1283a2aed429f4457e2eb875b1928a6643df (patch)
tree7468304afc4e981f54686d719d7dfa6877dc7726 /drivers
parentd324031245abbb54e4e0321004430826052b6c37 (diff)
sky2: status irq hang fix
The status interrupt flag should be cleared before processing, not afterwards to avoid race. Need to process in poll routine even if no new interrupt status. This is a normal occurrence when more than 64 frames (NAPI weight) are processed in one poll routine. Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sky2.c53
1 files changed, 25 insertions, 28 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 76da74fbe859..552aca76b283 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2105,45 +2105,42 @@ static int sky2_poll(struct net_device *dev0, int *budget)
2105 int work_done = 0; 2105 int work_done = 0;
2106 u32 status = sky2_read32(hw, B0_Y2_SP_EISR); 2106 u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
2107 2107
2108 if (unlikely(status & ~Y2_IS_STAT_BMU)) { 2108 if (status & Y2_IS_HW_ERR)
2109 if (status & Y2_IS_HW_ERR) 2109 sky2_hw_intr(hw);
2110 sky2_hw_intr(hw);
2111 2110
2112 if (status & Y2_IS_IRQ_PHY1) 2111 if (status & Y2_IS_IRQ_PHY1)
2113 sky2_phy_intr(hw, 0); 2112 sky2_phy_intr(hw, 0);
2114 2113
2115 if (status & Y2_IS_IRQ_PHY2) 2114 if (status & Y2_IS_IRQ_PHY2)
2116 sky2_phy_intr(hw, 1); 2115 sky2_phy_intr(hw, 1);
2117 2116
2118 if (status & Y2_IS_IRQ_MAC1) 2117 if (status & Y2_IS_IRQ_MAC1)
2119 sky2_mac_intr(hw, 0); 2118 sky2_mac_intr(hw, 0);
2120 2119
2121 if (status & Y2_IS_IRQ_MAC2) 2120 if (status & Y2_IS_IRQ_MAC2)
2122 sky2_mac_intr(hw, 1); 2121 sky2_mac_intr(hw, 1);
2123 2122
2124 if (status & Y2_IS_CHK_RX1) 2123 if (status & Y2_IS_CHK_RX1)
2125 sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1); 2124 sky2_descriptor_error(hw, 0, "receive", Y2_IS_CHK_RX1);
2126 2125
2127 if (status & Y2_IS_CHK_RX2) 2126 if (status & Y2_IS_CHK_RX2)
2128 sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2); 2127 sky2_descriptor_error(hw, 1, "receive", Y2_IS_CHK_RX2);
2129 2128
2130 if (status & Y2_IS_CHK_TXA1) 2129 if (status & Y2_IS_CHK_TXA1)
2131 sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1); 2130 sky2_descriptor_error(hw, 0, "transmit", Y2_IS_CHK_TXA1);
2132 2131
2133 if (status & Y2_IS_CHK_TXA2) 2132 if (status & Y2_IS_CHK_TXA2)
2134 sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); 2133 sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
2135 }
2136 2134
2137 if (status & Y2_IS_STAT_BMU) { 2135 if (status & Y2_IS_STAT_BMU)
2138 work_done = sky2_status_intr(hw, work_limit); 2136 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
2139 *budget -= work_done;
2140 dev0->quota -= work_done;
2141 2137
2142 if (work_done >= work_limit) 2138 work_done = sky2_status_intr(hw, work_limit);
2143 return 1; 2139 *budget -= work_done;
2140 dev0->quota -= work_done;
2144 2141
2145 sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); 2142 if (work_done >= work_limit)
2146 } 2143 return 1;
2147 2144
2148 mod_timer(&hw->idle_timer, jiffies + HZ); 2145 mod_timer(&hw->idle_timer, jiffies + HZ);
2149 2146