diff options
| author | Stephen Hemminger <shemminger@osdl.org> | 2006-04-25 13:58:51 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2006-04-26 06:19:45 -0400 |
| commit | d27ed38765d6e01eaab443a7909f53a37f090e99 (patch) | |
| tree | d4abd4a0364d0ba971dbde615cde8165d10bb905 | |
| parent | 734cbc363b159caee158d5a83408c72d98bcacf0 (diff) | |
[PATCH] sky2: add fake idle irq timer
Add an fake NAPI schedule once a second. This is an attempt to work around
for broken configurations with edge-triggered interrupts.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/net/sky2.c | 22 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 2 |
2 files changed, 23 insertions, 1 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 618fde8622ca..6673ddf763a4 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -2086,6 +2086,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
| 2086 | } | 2086 | } |
| 2087 | } | 2087 | } |
| 2088 | 2088 | ||
| 2089 | /* If idle then force a fake soft NAPI poll once a second | ||
| 2090 | * to work around cases where sharing an edge triggered interrupt. | ||
| 2091 | */ | ||
| 2092 | static void sky2_idle(unsigned long arg) | ||
| 2093 | { | ||
| 2094 | struct net_device *dev = (struct net_device *) arg; | ||
| 2095 | |||
| 2096 | local_irq_disable(); | ||
| 2097 | if (__netif_rx_schedule_prep(dev)) | ||
| 2098 | __netif_rx_schedule(dev); | ||
| 2099 | local_irq_enable(); | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | |||
| 2089 | static int sky2_poll(struct net_device *dev0, int *budget) | 2103 | static int sky2_poll(struct net_device *dev0, int *budget) |
| 2090 | { | 2104 | { |
| 2091 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2105 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
| @@ -2134,6 +2148,8 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
| 2134 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2148 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
| 2135 | } | 2149 | } |
| 2136 | 2150 | ||
| 2151 | mod_timer(&hw->idle_timer, jiffies + HZ); | ||
| 2152 | |||
| 2137 | local_irq_disable(); | 2153 | local_irq_disable(); |
| 2138 | __netif_rx_complete(dev0); | 2154 | __netif_rx_complete(dev0); |
| 2139 | 2155 | ||
| @@ -3288,6 +3304,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 3288 | 3304 | ||
| 3289 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3305 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
| 3290 | 3306 | ||
| 3307 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
| 3308 | |||
| 3291 | pci_set_drvdata(pdev, hw); | 3309 | pci_set_drvdata(pdev, hw); |
| 3292 | 3310 | ||
| 3293 | return 0; | 3311 | return 0; |
| @@ -3323,13 +3341,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 3323 | if (!hw) | 3341 | if (!hw) |
| 3324 | return; | 3342 | return; |
| 3325 | 3343 | ||
| 3344 | del_timer_sync(&hw->idle_timer); | ||
| 3345 | |||
| 3346 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3326 | dev0 = hw->dev[0]; | 3347 | dev0 = hw->dev[0]; |
| 3327 | dev1 = hw->dev[1]; | 3348 | dev1 = hw->dev[1]; |
| 3328 | if (dev1) | 3349 | if (dev1) |
| 3329 | unregister_netdev(dev1); | 3350 | unregister_netdev(dev1); |
| 3330 | unregister_netdev(dev0); | 3351 | unregister_netdev(dev0); |
| 3331 | 3352 | ||
| 3332 | sky2_write32(hw, B0_IMSK, 0); | ||
| 3333 | sky2_set_power_state(hw, PCI_D3hot); | 3353 | sky2_set_power_state(hw, PCI_D3hot); |
| 3334 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3354 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
| 3335 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3355 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 89dd18cd12f0..b026f5653f04 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
| @@ -1880,6 +1880,8 @@ struct sky2_hw { | |||
| 1880 | struct sky2_status_le *st_le; | 1880 | struct sky2_status_le *st_le; |
| 1881 | u32 st_idx; | 1881 | u32 st_idx; |
| 1882 | dma_addr_t st_dma; | 1882 | dma_addr_t st_dma; |
| 1883 | |||
| 1884 | struct timer_list idle_timer; | ||
| 1883 | int msi_detected; | 1885 | int msi_detected; |
| 1884 | wait_queue_head_t msi_wait; | 1886 | wait_queue_head_t msi_wait; |
| 1885 | }; | 1887 | }; |
