diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-08-01 11:55:23 -0700 |
---|---|---|
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) | |
download | kernel_samsung_smdk4412-fe2a24dfc577a05349a39c6c8a6312818d28bb59.zip kernel_samsung_smdk4412-fe2a24dfc577a05349a39c6c8a6312818d28bb59.tar.gz kernel_samsung_smdk4412-fe2a24dfc577a05349a39c6c8a6312818d28bb59.tar.bz2 |
[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 de1177b..13431f6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -50,7 +50,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.5" +#define DRV_VERSION "1.6" #define PFX DRV_NAME " " /* @@ -1932,12 +1932,6 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } -/* Is status ring empty or is there more to do? */ -static inline int sky2_more_work(const struct sky2_hw *hw) -{ - return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); -} - /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do) { @@ -2028,6 +2022,9 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) } } + /* Fully processed status ring so clear irq */ + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + exit_loop: if (buf_write[0]) { sky2 = netdev_priv(hw->dev[0]); @@ -2237,19 +2234,16 @@ static int sky2_poll(struct net_device *dev0, int *budget) sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); work_done = sky2_status_intr(hw, work_limit); - *budget -= work_done; - dev0->quota -= work_done; - - if (status & Y2_IS_STAT_BMU) - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + if (work_done < work_limit) { + netif_rx_complete(dev0); - if (sky2_more_work(hw)) + sky2_read32(hw, B0_Y2_SP_LISR); + return 0; + } else { + *budget -= work_done; + dev0->quota -= work_done; return 1; - - netif_rx_complete(dev0); - - sky2_read32(hw, B0_Y2_SP_LISR); - return 0; + } } static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) |