aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-08-21 17:34:03 -0400
committerJeff Garzik <jeff@garzik.org>2007-08-25 02:31:08 -0400
commit32c2c30085324aef9699934295281cca0161ef7e (patch)
treed335d8b73e84a830008d3fb37678b516af0c5a22 /drivers/net
parentb23457737f073eaf5a7b797c2a195f83633e003d (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>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/sky2.c55
-rw-r--r--drivers/net/sky2.h3
2 files changed, 27 insertions, 31 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 33ba3486389..00c5f056ef7 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -99,10 +99,6 @@ static int disable_msi = 0;
99module_param(disable_msi, int, 0); 99module_param(disable_msi, int, 0);
100MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); 100MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
101 101
102static int idle_timeout = 100;
103module_param(idle_timeout, int, 0);
104MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)");
105
106static const struct pci_device_id sky2_id_table[] = { 102static 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. 2438static void sky2_watchdog(unsigned long arg)
2431 */
2432static 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
2439static 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;
4184out: 4180out:
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 dce4d276d44..72e12b7cfa4 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;