diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-08-01 14:55:23 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-03 17:36:39 -0400 |
commit | fe2a24dfc577a05349a39c6c8a6312818d28bb59 (patch) | |
tree | 5e5b206787da449ef688762136b82c183208284f /drivers/net/sky2.c | |
parent | 834695ee415f064036dacdd1b2c414cff1e81cb4 (diff) |
[PATCH] sky2: status interrupt handling improvement
More changes to prevent losing status and causing hangs.
The hardware is smarter than I gave it credit for.
Clearing the status IRQ causes the status state machine to
toggle an IRQ if needed and post any more transmits.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index de1177b7b996..13431f6a3ad9 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -50,7 +50,7 @@ | |||
50 | #include "sky2.h" | 50 | #include "sky2.h" |
51 | 51 | ||
52 | #define DRV_NAME "sky2" | 52 | #define DRV_NAME "sky2" |
53 | #define DRV_VERSION "1.5" | 53 | #define DRV_VERSION "1.6" |
54 | #define PFX DRV_NAME " " | 54 | #define PFX DRV_NAME " " |
55 | 55 | ||
56 | /* | 56 | /* |
@@ -1932,12 +1932,6 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) | |||
1932 | } | 1932 | } |
1933 | } | 1933 | } |
1934 | 1934 | ||
1935 | /* Is status ring empty or is there more to do? */ | ||
1936 | static inline int sky2_more_work(const struct sky2_hw *hw) | ||
1937 | { | ||
1938 | return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); | ||
1939 | } | ||
1940 | |||
1941 | /* Process status response ring */ | 1935 | /* Process status response ring */ |
1942 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) | 1936 | static int sky2_status_intr(struct sky2_hw *hw, int to_do) |
1943 | { | 1937 | { |
@@ -2028,6 +2022,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) | |||
2028 | } | 2022 | } |
2029 | } | 2023 | } |
2030 | 2024 | ||
2025 | /* Fully processed status ring so clear irq */ | ||
2026 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2027 | |||
2031 | exit_loop: | 2028 | exit_loop: |
2032 | if (buf_write[0]) { | 2029 | if (buf_write[0]) { |
2033 | sky2 = netdev_priv(hw->dev[0]); | 2030 | sky2 = netdev_priv(hw->dev[0]); |
@@ -2237,19 +2234,16 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2237 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); | 2234 | sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); |
2238 | 2235 | ||
2239 | work_done = sky2_status_intr(hw, work_limit); | 2236 | work_done = sky2_status_intr(hw, work_limit); |
2240 | *budget -= work_done; | 2237 | if (work_done < work_limit) { |
2241 | dev0->quota -= work_done; | 2238 | netif_rx_complete(dev0); |
2242 | |||
2243 | if (status & Y2_IS_STAT_BMU) | ||
2244 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | ||
2245 | 2239 | ||
2246 | if (sky2_more_work(hw)) | 2240 | sky2_read32(hw, B0_Y2_SP_LISR); |
2241 | return 0; | ||
2242 | } else { | ||
2243 | *budget -= work_done; | ||
2244 | dev0->quota -= work_done; | ||
2247 | return 1; | 2245 | return 1; |
2248 | 2246 | } | |
2249 | netif_rx_complete(dev0); | ||
2250 | |||
2251 | sky2_read32(hw, B0_Y2_SP_LISR); | ||
2252 | return 0; | ||
2253 | } | 2247 | } |
2254 | 2248 | ||
2255 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | 2249 | static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) |