diff options
author | Stephen Hemminger <shemminger@vyatta.com> | 2008-08-04 16:33:37 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-08-07 01:55:50 -0400 |
commit | f71eb1a24a8cdde8d388c8f93e935aa7ac491047 (patch) | |
tree | b5520365b42d4c26ae1f1a8c5e0a9eee81e84e7b /drivers/net/sky2.c | |
parent | a6ef5e9d7dd6f3de4f88b68c390f0f0d7072944c (diff) |
sky2: fix PM related regressions
Fix the problems reported for 2.6.27-rc1 caused by over aggressive
power management. Turning clock off on PCI Express is problematic for WOL,
and when doing multi-booting.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 103 |
1 files changed, 10 insertions, 93 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 5257cf464f1a..7d29edcd40b4 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -275,86 +275,6 @@ static void sky2_power_aux(struct sky2_hw *hw) | |||
275 | PC_VAUX_ON | PC_VCC_OFF)); | 275 | PC_VAUX_ON | PC_VCC_OFF)); |
276 | } | 276 | } |
277 | 277 | ||
278 | static void sky2_power_state(struct sky2_hw *hw, pci_power_t state) | ||
279 | { | ||
280 | u16 power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL); | ||
281 | int pex = pci_find_capability(hw->pdev, PCI_CAP_ID_EXP); | ||
282 | u32 reg; | ||
283 | |||
284 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
285 | |||
286 | switch (state) { | ||
287 | case PCI_D0: | ||
288 | break; | ||
289 | |||
290 | case PCI_D1: | ||
291 | power_control |= 1; | ||
292 | break; | ||
293 | |||
294 | case PCI_D2: | ||
295 | power_control |= 2; | ||
296 | break; | ||
297 | |||
298 | case PCI_D3hot: | ||
299 | case PCI_D3cold: | ||
300 | power_control |= 3; | ||
301 | if (hw->flags & SKY2_HW_ADV_POWER_CTL) { | ||
302 | /* additional power saving measurements */ | ||
303 | reg = sky2_pci_read32(hw, PCI_DEV_REG4); | ||
304 | |||
305 | /* set gating core clock for LTSSM in L1 state */ | ||
306 | reg |= P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | | ||
307 | /* auto clock gated scheme controlled by CLKREQ */ | ||
308 | P_ASPM_A1_MODE_SELECT | | ||
309 | /* enable Gate Root Core Clock */ | ||
310 | P_CLK_GATE_ROOT_COR_ENA; | ||
311 | |||
312 | if (pex && (hw->flags & SKY2_HW_CLK_POWER)) { | ||
313 | /* enable Clock Power Management (CLKREQ) */ | ||
314 | u16 ctrl = sky2_pci_read16(hw, pex + PCI_EXP_DEVCTL); | ||
315 | |||
316 | ctrl |= PCI_EXP_DEVCTL_AUX_PME; | ||
317 | sky2_pci_write16(hw, pex + PCI_EXP_DEVCTL, ctrl); | ||
318 | } else | ||
319 | /* force CLKREQ Enable in Our4 (A1b only) */ | ||
320 | reg |= P_ASPM_FORCE_CLKREQ_ENA; | ||
321 | |||
322 | /* set Mask Register for Release/Gate Clock */ | ||
323 | sky2_pci_write32(hw, PCI_DEV_REG5, | ||
324 | P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | | ||
325 | P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | | ||
326 | P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN); | ||
327 | } else | ||
328 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_CLK_HALT); | ||
329 | |||
330 | /* put CPU into reset state */ | ||
331 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_RESET); | ||
332 | if (hw->chip_id == CHIP_ID_YUKON_SUPR && hw->chip_rev == CHIP_REV_YU_SU_A0) | ||
333 | /* put CPU into halt state */ | ||
334 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_HALTED); | ||
335 | |||
336 | if (pex && !(hw->flags & SKY2_HW_RAM_BUFFER)) { | ||
337 | reg = sky2_pci_read32(hw, PCI_DEV_REG1); | ||
338 | /* force to PCIe L1 */ | ||
339 | reg |= PCI_FORCE_PEX_L1; | ||
340 | sky2_pci_write32(hw, PCI_DEV_REG1, reg); | ||
341 | } | ||
342 | break; | ||
343 | |||
344 | default: | ||
345 | dev_warn(&hw->pdev->dev, PFX "Invalid power state (%d) ", | ||
346 | state); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | power_control |= PCI_PM_CTRL_PME_ENABLE; | ||
351 | /* Finally, set the new power state. */ | ||
352 | sky2_pci_write32(hw, hw->pm_cap + PCI_PM_CTRL, power_control); | ||
353 | |||
354 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
355 | sky2_pci_read32(hw, B0_CTST); | ||
356 | } | ||
357 | |||
358 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) | 278 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) |
359 | { | 279 | { |
360 | u16 reg; | 280 | u16 reg; |
@@ -709,6 +629,11 @@ static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port) | |||
709 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); | 629 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); |
710 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 630 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
711 | sky2_pci_read32(hw, PCI_DEV_REG1); | 631 | sky2_pci_read32(hw, PCI_DEV_REG1); |
632 | |||
633 | if (hw->chip_id == CHIP_ID_YUKON_FE) | ||
634 | gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_ANE); | ||
635 | else if (hw->flags & SKY2_HW_ADV_POWER_CTL) | ||
636 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); | ||
712 | } | 637 | } |
713 | 638 | ||
714 | static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) | 639 | static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) |
@@ -2855,10 +2780,6 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2855 | hw->flags = SKY2_HW_GIGABIT | 2780 | hw->flags = SKY2_HW_GIGABIT |
2856 | | SKY2_HW_NEWER_PHY | 2781 | | SKY2_HW_NEWER_PHY |
2857 | | SKY2_HW_ADV_POWER_CTL; | 2782 | | SKY2_HW_ADV_POWER_CTL; |
2858 | |||
2859 | /* check for Rev. A1 dev 4200 */ | ||
2860 | if (sky2_read16(hw, Q_ADDR(Q_XA1, Q_WM)) == 0) | ||
2861 | hw->flags |= SKY2_HW_CLK_POWER; | ||
2862 | break; | 2783 | break; |
2863 | 2784 | ||
2864 | case CHIP_ID_YUKON_EX: | 2785 | case CHIP_ID_YUKON_EX: |
@@ -2914,12 +2835,6 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2914 | if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') | 2835 | if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') |
2915 | hw->flags |= SKY2_HW_FIBRE_PHY; | 2836 | hw->flags |= SKY2_HW_FIBRE_PHY; |
2916 | 2837 | ||
2917 | hw->pm_cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PM); | ||
2918 | if (hw->pm_cap == 0) { | ||
2919 | dev_err(&hw->pdev->dev, "cannot find PowerManagement capability\n"); | ||
2920 | return -EIO; | ||
2921 | } | ||
2922 | |||
2923 | hw->ports = 1; | 2838 | hw->ports = 1; |
2924 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | 2839 | t8 = sky2_read8(hw, B2_Y2_HW_RES); |
2925 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | 2840 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { |
@@ -4512,7 +4427,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4512 | 4427 | ||
4513 | pci_save_state(pdev); | 4428 | pci_save_state(pdev); |
4514 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); | 4429 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); |
4515 | sky2_power_state(hw, pci_choose_state(pdev, state)); | 4430 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
4516 | 4431 | ||
4517 | return 0; | 4432 | return 0; |
4518 | } | 4433 | } |
@@ -4525,7 +4440,9 @@ static int sky2_resume(struct pci_dev *pdev) | |||
4525 | if (!hw) | 4440 | if (!hw) |
4526 | return 0; | 4441 | return 0; |
4527 | 4442 | ||
4528 | sky2_power_state(hw, PCI_D0); | 4443 | err = pci_set_power_state(pdev, PCI_D0); |
4444 | if (err) | ||
4445 | goto out; | ||
4529 | 4446 | ||
4530 | err = pci_restore_state(pdev); | 4447 | err = pci_restore_state(pdev); |
4531 | if (err) | 4448 | if (err) |
@@ -4595,7 +4512,7 @@ static void sky2_shutdown(struct pci_dev *pdev) | |||
4595 | pci_enable_wake(pdev, PCI_D3cold, wol); | 4512 | pci_enable_wake(pdev, PCI_D3cold, wol); |
4596 | 4513 | ||
4597 | pci_disable_device(pdev); | 4514 | pci_disable_device(pdev); |
4598 | sky2_power_state(hw, PCI_D3hot); | 4515 | pci_set_power_state(pdev, PCI_D3hot); |
4599 | } | 4516 | } |
4600 | 4517 | ||
4601 | static struct pci_driver sky2_driver = { | 4518 | static struct pci_driver sky2_driver = { |