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; |