diff options
| author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-08-21 17:34:03 -0400 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-08-25 02:31:08 -0400 |
| commit | 32c2c30085324aef9699934295281cca0161ef7e (patch) | |
| tree | d335d8b73e84a830008d3fb37678b516af0c5a22 | |
| parent | b23457737f073eaf5a7b797c2a195f83633e003d (diff) | |
sky2: only bring up watchdog if link is active
This fixes the extra timer overhead that people were whining about
as a 2.6.23 regression.
Running the watchdog timer all the time is unneeded. Change it
to run only if link is up, and reduce frequency to save power.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
| -rw-r--r-- | drivers/net/sky2.c | 55 | ||||
| -rw-r--r-- | drivers/net/sky2.h | 3 |
2 files changed, 27 insertions, 31 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 33ba3486389e..00c5f056ef7e 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
| @@ -99,10 +99,6 @@ static int disable_msi = 0; | |||
| 99 | module_param(disable_msi, int, 0); | 99 | module_param(disable_msi, int, 0); |
| 100 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | 100 | MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); |
| 101 | 101 | ||
| 102 | static int idle_timeout = 100; | ||
| 103 | module_param(idle_timeout, int, 0); | ||
| 104 | MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); | ||
| 105 | |||
| 106 | static const struct pci_device_id sky2_id_table[] = { | 102 | static const struct pci_device_id sky2_id_table[] = { |
| 107 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ | 103 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ |
| 108 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ | 104 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ |
| @@ -1624,6 +1620,9 @@ static int sky2_down(struct net_device *dev) | |||
| 1624 | if (netif_msg_ifdown(sky2)) | 1620 | if (netif_msg_ifdown(sky2)) |
| 1625 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 1621 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
| 1626 | 1622 | ||
| 1623 | if (netif_carrier_ok(dev) && --hw->active == 0) | ||
| 1624 | del_timer(&hw->watchdog_timer); | ||
| 1625 | |||
| 1627 | /* Stop more packets from being queued */ | 1626 | /* Stop more packets from being queued */ |
| 1628 | netif_stop_queue(dev); | 1627 | netif_stop_queue(dev); |
| 1629 | 1628 | ||
| @@ -1744,6 +1743,10 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
| 1744 | 1743 | ||
| 1745 | netif_carrier_on(sky2->netdev); | 1744 | netif_carrier_on(sky2->netdev); |
| 1746 | 1745 | ||
| 1746 | if (hw->active++ == 0) | ||
| 1747 | mod_timer(&hw->watchdog_timer, jiffies + 1); | ||
| 1748 | |||
| 1749 | |||
| 1747 | /* Turn on link LED */ | 1750 | /* Turn on link LED */ |
| 1748 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), | 1751 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), |
| 1749 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); | 1752 | LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF); |
| @@ -1795,6 +1798,11 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
| 1795 | 1798 | ||
| 1796 | netif_carrier_off(sky2->netdev); | 1799 | netif_carrier_off(sky2->netdev); |
| 1797 | 1800 | ||
| 1801 | /* Stop watchdog if both ports are not active */ | ||
| 1802 | if (--hw->active == 0) | ||
| 1803 | del_timer(&hw->watchdog_timer); | ||
| 1804 | |||
| 1805 | |||
| 1798 | /* Turn on link LED */ | 1806 | /* Turn on link LED */ |
| 1799 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); | 1807 | sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); |
| 1800 | 1808 | ||
| @@ -2426,25 +2434,20 @@ static void sky2_le_error(struct sky2_hw *hw, unsigned port, | |||
| 2426 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); | 2434 | sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK); |
| 2427 | } | 2435 | } |
| 2428 | 2436 | ||
| 2429 | /* If idle then force a fake soft NAPI poll once a second | 2437 | /* Check for lost IRQ once a second */ |
| 2430 | * to work around cases where sharing an edge triggered interrupt. | 2438 | static void sky2_watchdog(unsigned long arg) |
| 2431 | */ | ||
| 2432 | static inline void sky2_idle_start(struct sky2_hw *hw) | ||
| 2433 | { | ||
| 2434 | if (idle_timeout > 0) | ||
| 2435 | mod_timer(&hw->idle_timer, | ||
| 2436 | jiffies + msecs_to_jiffies(idle_timeout)); | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | static void sky2_idle(unsigned long arg) | ||
| 2440 | { | 2439 | { |
| 2441 | struct sky2_hw *hw = (struct sky2_hw *) arg; | 2440 | struct sky2_hw *hw = (struct sky2_hw *) arg; |
| 2442 | struct net_device *dev = hw->dev[0]; | ||
| 2443 | 2441 | ||
| 2444 | if (__netif_rx_schedule_prep(dev)) | 2442 | if (sky2_read32(hw, B0_ISRC)) { |
| 2445 | __netif_rx_schedule(dev); | 2443 | struct net_device *dev = hw->dev[0]; |
| 2444 | |||
| 2445 | if (__netif_rx_schedule_prep(dev)) | ||
| 2446 | __netif_rx_schedule(dev); | ||
| 2447 | } | ||
| 2446 | 2448 | ||
| 2447 | mod_timer(&hw->idle_timer, jiffies + msecs_to_jiffies(idle_timeout)); | 2449 | if (hw->active > 0) |
| 2450 | mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ)); | ||
| 2448 | } | 2451 | } |
| 2449 | 2452 | ||
| 2450 | /* Hardware/software error handling */ | 2453 | /* Hardware/software error handling */ |
| @@ -2732,8 +2735,6 @@ static void sky2_restart(struct work_struct *work) | |||
| 2732 | struct net_device *dev; | 2735 | struct net_device *dev; |
| 2733 | int i, err; | 2736 | int i, err; |
| 2734 | 2737 | ||
| 2735 | del_timer_sync(&hw->idle_timer); | ||
| 2736 | |||
| 2737 | rtnl_lock(); | 2738 | rtnl_lock(); |
| 2738 | sky2_write32(hw, B0_IMSK, 0); | 2739 | sky2_write32(hw, B0_IMSK, 0); |
| 2739 | sky2_read32(hw, B0_IMSK); | 2740 | sky2_read32(hw, B0_IMSK); |
| @@ -2762,8 +2763,6 @@ static void sky2_restart(struct work_struct *work) | |||
| 2762 | } | 2763 | } |
| 2763 | } | 2764 | } |
| 2764 | 2765 | ||
| 2765 | sky2_idle_start(hw); | ||
| 2766 | |||
| 2767 | rtnl_unlock(); | 2766 | rtnl_unlock(); |
| 2768 | } | 2767 | } |
| 2769 | 2768 | ||
| @@ -4030,11 +4029,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
| 4030 | sky2_show_addr(dev1); | 4029 | sky2_show_addr(dev1); |
| 4031 | } | 4030 | } |
| 4032 | 4031 | ||
| 4033 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw); | 4032 | setup_timer(&hw->watchdog_timer, sky2_watchdog, (unsigned long) hw); |
| 4034 | INIT_WORK(&hw->restart_work, sky2_restart); | 4033 | INIT_WORK(&hw->restart_work, sky2_restart); |
| 4035 | 4034 | ||
| 4036 | sky2_idle_start(hw); | ||
| 4037 | |||
| 4038 | pci_set_drvdata(pdev, hw); | 4035 | pci_set_drvdata(pdev, hw); |
| 4039 | 4036 | ||
| 4040 | return 0; | 4037 | return 0; |
| @@ -4069,7 +4066,7 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
| 4069 | if (!hw) | 4066 | if (!hw) |
| 4070 | return; | 4067 | return; |
| 4071 | 4068 | ||
| 4072 | del_timer_sync(&hw->idle_timer); | 4069 | del_timer_sync(&hw->watchdog_timer); |
| 4073 | 4070 | ||
| 4074 | flush_scheduled_work(); | 4071 | flush_scheduled_work(); |
| 4075 | 4072 | ||
| @@ -4113,7 +4110,6 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 4113 | if (!hw) | 4110 | if (!hw) |
| 4114 | return 0; | 4111 | return 0; |
| 4115 | 4112 | ||
| 4116 | del_timer_sync(&hw->idle_timer); | ||
| 4117 | netif_poll_disable(hw->dev[0]); | 4113 | netif_poll_disable(hw->dev[0]); |
| 4118 | 4114 | ||
| 4119 | for (i = 0; i < hw->ports; i++) { | 4115 | for (i = 0; i < hw->ports; i++) { |
| @@ -4179,7 +4175,7 @@ static int sky2_resume(struct pci_dev *pdev) | |||
| 4179 | } | 4175 | } |
| 4180 | 4176 | ||
| 4181 | netif_poll_enable(hw->dev[0]); | 4177 | netif_poll_enable(hw->dev[0]); |
| 4182 | sky2_idle_start(hw); | 4178 | |
| 4183 | return 0; | 4179 | return 0; |
| 4184 | out: | 4180 | out: |
| 4185 | dev_err(&pdev->dev, "resume failed (%d)\n", err); | 4181 | dev_err(&pdev->dev, "resume failed (%d)\n", err); |
| @@ -4196,7 +4192,6 @@ static void sky2_shutdown(struct pci_dev *pdev) | |||
| 4196 | if (!hw) | 4192 | if (!hw) |
| 4197 | return; | 4193 | return; |
| 4198 | 4194 | ||
| 4199 | del_timer_sync(&hw->idle_timer); | ||
| 4200 | netif_poll_disable(hw->dev[0]); | 4195 | netif_poll_disable(hw->dev[0]); |
| 4201 | 4196 | ||
| 4202 | for (i = 0; i < hw->ports; i++) { | 4197 | for (i = 0; i < hw->ports; i++) { |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index dce4d276d443..72e12b7cfa40 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
| @@ -2045,12 +2045,13 @@ struct sky2_hw { | |||
| 2045 | u8 chip_rev; | 2045 | u8 chip_rev; |
| 2046 | u8 pmd_type; | 2046 | u8 pmd_type; |
| 2047 | u8 ports; | 2047 | u8 ports; |
| 2048 | u8 active; | ||
| 2048 | 2049 | ||
| 2049 | struct sky2_status_le *st_le; | 2050 | struct sky2_status_le *st_le; |
| 2050 | u32 st_idx; | 2051 | u32 st_idx; |
| 2051 | dma_addr_t st_dma; | 2052 | dma_addr_t st_dma; |
| 2052 | 2053 | ||
| 2053 | struct timer_list idle_timer; | 2054 | struct timer_list watchdog_timer; |
| 2054 | struct work_struct restart_work; | 2055 | struct work_struct restart_work; |
| 2055 | int msi; | 2056 | int msi; |
| 2056 | wait_queue_head_t msi_wait; | 2057 | wait_queue_head_t msi_wait; |
