aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-04-09 18:32:45 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-11 11:54:43 -0400
commit692412b31ffb5df00197ea591dd635fc07506c02 (patch)
treee0dfc9a42d8b2763a62ad63e0b16a32f23c34566 /drivers/net
parent9467a8fc89844ff2ea9c6d13460dddb3b674cc37 (diff)
skge: fix wake on lan
Need to rework wake on lan code to setup properly and get activated on shutdown (and suspend), not when ethtool is run. This does not need to go to stable queue because wake on lan was not even included in 2.6.20 (or earlier versions). 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/skge.c94
1 files changed, 58 insertions, 36 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index cc907a1a5ecc..d476a3cc2e94 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -163,27 +163,46 @@ static void skge_wol_init(struct skge_port *skge)
163{ 163{
164 struct skge_hw *hw = skge->hw; 164 struct skge_hw *hw = skge->hw;
165 int port = skge->port; 165 int port = skge->port;
166 enum pause_control save_mode; 166 u16 ctrl;
167 u32 ctrl;
168 167
169 /* Bring hardware out of reset */
170 skge_write16(hw, B0_CTST, CS_RST_CLR); 168 skge_write16(hw, B0_CTST, CS_RST_CLR);
171 skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); 169 skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR);
172 170
173 skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); 171 /* Turn on Vaux */
174 skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); 172 skge_write8(hw, B0_POWER_CTRL,
173 PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF);
175 174
176 /* Force to 10/100 skge_reset will re-enable on resume */ 175 /* WA code for COMA mode -- clear PHY reset */
177 save_mode = skge->flow_control; 176 if (hw->chip_id == CHIP_ID_YUKON_LITE &&
178 skge->flow_control = FLOW_MODE_SYMMETRIC; 177 hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
178 u32 reg = skge_read32(hw, B2_GP_IO);
179 reg |= GP_DIR_9;
180 reg &= ~GP_IO_9;
181 skge_write32(hw, B2_GP_IO, reg);
182 }
179 183
180 ctrl = skge->advertising; 184 skge_write32(hw, SK_REG(port, GPHY_CTRL),
181 skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); 185 GPC_DIS_SLEEP |
186 GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
187 GPC_ANEG_1 | GPC_RST_SET);
182 188
183 skge_phy_reset(skge); 189 skge_write32(hw, SK_REG(port, GPHY_CTRL),
190 GPC_DIS_SLEEP |
191 GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 |
192 GPC_ANEG_1 | GPC_RST_CLR);
193
194 skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR);
195
196 /* Force to 10/100 skge_reset will re-enable on resume */
197 gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
198 PHY_AN_100FULL | PHY_AN_100HALF |
199 PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA);
200 /* no 1000 HD/FD */
201 gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0);
202 gm_phy_write(hw, port, PHY_MARV_CTRL,
203 PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE |
204 PHY_CT_RE_CFG | PHY_CT_DUP_MD);
184 205
185 skge->flow_control = save_mode;
186 skge->advertising = ctrl;
187 206
188 /* Set GMAC to no flow control and auto update for speed/duplex */ 207 /* Set GMAC to no flow control and auto update for speed/duplex */
189 gma_write16(hw, port, GM_GP_CTRL, 208 gma_write16(hw, port, GM_GP_CTRL,
@@ -227,12 +246,10 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
227 struct skge_port *skge = netdev_priv(dev); 246 struct skge_port *skge = netdev_priv(dev);
228 struct skge_hw *hw = skge->hw; 247 struct skge_hw *hw = skge->hw;
229 248
230 if (wol->wolopts & wol_supported(hw)) 249 if (wol->wolopts & ~wol_supported(hw))
231 return -EOPNOTSUPP; 250 return -EOPNOTSUPP;
232 251
233 skge->wol = wol->wolopts; 252 skge->wol = wol->wolopts;
234 if (!netif_running(dev))
235 skge_wol_init(skge);
236 return 0; 253 return 0;
237} 254}
238 255
@@ -2535,11 +2552,12 @@ static int skge_down(struct net_device *dev)
2535 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); 2552 printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
2536 2553
2537 netif_stop_queue(dev); 2554 netif_stop_queue(dev);
2538 netif_carrier_off(dev); 2555
2539 if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) 2556 if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
2540 del_timer_sync(&skge->link_timer); 2557 del_timer_sync(&skge->link_timer);
2541 2558
2542 netif_poll_disable(dev); 2559 netif_poll_disable(dev);
2560 netif_carrier_off(dev);
2543 2561
2544 spin_lock_irq(&hw->hw_lock); 2562 spin_lock_irq(&hw->hw_lock);
2545 hw->intr_mask &= ~portmask[port]; 2563 hw->intr_mask &= ~portmask[port];
@@ -3766,21 +3784,6 @@ static void __devexit skge_remove(struct pci_dev *pdev)
3766} 3784}
3767 3785
3768#ifdef CONFIG_PM 3786#ifdef CONFIG_PM
3769static int vaux_avail(struct pci_dev *pdev)
3770{
3771 int pm_cap;
3772
3773 pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
3774 if (pm_cap) {
3775 u16 ctl;
3776 pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl);
3777 if (ctl & PCI_PM_CAP_AUX_POWER)
3778 return 1;
3779 }
3780 return 0;
3781}
3782
3783
3784static int skge_suspend(struct pci_dev *pdev, pm_message_t state) 3787static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
3785{ 3788{
3786 struct skge_hw *hw = pci_get_drvdata(pdev); 3789 struct skge_hw *hw = pci_get_drvdata(pdev);
@@ -3802,10 +3805,6 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
3802 wol |= skge->wol; 3805 wol |= skge->wol;
3803 } 3806 }
3804 3807
3805 if (wol && vaux_avail(pdev))
3806 skge_write8(hw, B0_POWER_CTRL,
3807 PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF);
3808
3809 skge_write32(hw, B0_IMSK, 0); 3808 skge_write32(hw, B0_IMSK, 0);
3810 pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); 3809 pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
3811 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 3810 pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -3851,6 +3850,28 @@ out:
3851} 3850}
3852#endif 3851#endif
3853 3852
3853static void skge_shutdown(struct pci_dev *pdev)
3854{
3855 struct skge_hw *hw = pci_get_drvdata(pdev);
3856 int i, wol = 0;
3857
3858 for (i = 0; i < hw->ports; i++) {
3859 struct net_device *dev = hw->dev[i];
3860 struct skge_port *skge = netdev_priv(dev);
3861
3862 if (skge->wol)
3863 skge_wol_init(skge);
3864 wol |= skge->wol;
3865 }
3866
3867 pci_enable_wake(pdev, PCI_D3hot, wol);
3868 pci_enable_wake(pdev, PCI_D3cold, wol);
3869
3870 pci_disable_device(pdev);
3871 pci_set_power_state(pdev, PCI_D3hot);
3872
3873}
3874
3854static struct pci_driver skge_driver = { 3875static struct pci_driver skge_driver = {
3855 .name = DRV_NAME, 3876 .name = DRV_NAME,
3856 .id_table = skge_id_table, 3877 .id_table = skge_id_table,
@@ -3860,6 +3881,7 @@ static struct pci_driver skge_driver = {
3860 .suspend = skge_suspend, 3881 .suspend = skge_suspend,
3861 .resume = skge_resume, 3882 .resume = skge_resume,
3862#endif 3883#endif
3884 .shutdown = skge_shutdown,
3863}; 3885};
3864 3886
3865static int __init skge_init_module(void) 3887static int __init skge_init_module(void)