Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

radeonfb: Fix resume from D3Cold on some platforms

For historical reason, this driver used its own saving/restoring
of the PCI config space, and used the state of it on resume as
an indication as to whether it needed to re-POST the chip or not.

This methods breaks with the later core changes since the core will
have restored things for us.

This patch fixes it by removing that custom code, using standard
core methods to save/restore state, and testing for the need to
re-POST by comparing the content of a few key PLL registers.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Benjamin Herrenschmidt and committed by
Linus Torvalds
1fb25cb8 b746bb77

+20 -67
+20 -65
drivers/video/aty/radeon_pm.c
··· 2509 2509 2510 2510 static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) 2511 2511 { 2512 - u16 pwr_cmd; 2513 2512 u32 tmp; 2514 - int i; 2515 2513 2516 2514 if (!rinfo->pm_reg) 2517 2515 return; ··· 2555 2557 } 2556 2558 } 2557 2559 2558 - for (i = 0; i < 64; ++i) 2559 - pci_read_config_dword(rinfo->pdev, i * 4, 2560 - &rinfo->cfg_save[i]); 2561 - 2562 2560 /* Switch PCI power management to D2. */ 2563 2561 pci_disable_device(rinfo->pdev); 2564 - for (;;) { 2565 - pci_read_config_word( 2566 - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 2567 - &pwr_cmd); 2568 - if (pwr_cmd & 2) 2569 - break; 2570 - pci_write_config_word( 2571 - rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 2572 - (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); 2573 - mdelay(500); 2574 - } 2562 + pci_save_state(rinfo->pdev); 2563 + pci_set_power_state(rinfo->pdev, PCI_D2); 2575 2564 } else { 2576 2565 printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", 2577 2566 pci_name(rinfo->pdev)); 2578 - 2579 - /* Switch back PCI powermanagment to D0 */ 2580 - mdelay(200); 2581 - pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); 2582 - mdelay(500); 2583 2567 2584 2568 if (rinfo->family <= CHIP_FAMILY_RV250) { 2585 2569 /* Reset the SDRAM controller */ ··· 2578 2598 } 2579 2599 } 2580 2600 2581 - static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo) 2582 - { 2583 - int i; 2584 - static u32 radeon_cfg_after_resume[64]; 2585 - 2586 - for (i = 0; i < 64; ++i) 2587 - pci_read_config_dword(rinfo->pdev, i * 4, 2588 - &radeon_cfg_after_resume[i]); 2589 - 2590 - if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4] 2591 - == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4]) 2592 - return 0; /* assume everything is ok */ 2593 - 2594 - for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) { 2595 - if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i]) 2596 - pci_write_config_dword(rinfo->pdev, i * 4, 2597 - rinfo->cfg_save[i]); 2598 - } 2599 - pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE, 2600 - rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]); 2601 - pci_write_config_word(rinfo->pdev, PCI_COMMAND, 2602 - rinfo->cfg_save[PCI_COMMAND/4]); 2603 - return 1; 2604 - } 2605 - 2606 - 2607 2601 int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) 2608 2602 { 2609 2603 struct fb_info *info = pci_get_drvdata(pdev); 2610 2604 struct radeonfb_info *rinfo = info->par; 2611 - int i; 2612 2605 2613 2606 if (mesg.event == pdev->dev.power.power_state.event) 2614 2607 return 0; ··· 2627 2674 pmac_suspend_agp_for_card(pdev); 2628 2675 #endif /* CONFIG_PPC_PMAC */ 2629 2676 2677 + /* It's unclear whether or when the generic code will do that, so let's 2678 + * do it ourselves. We save state before we do any power management 2679 + */ 2680 + pci_save_state(pdev); 2681 + 2630 2682 /* If we support wakeup from poweroff, we save all regs we can including cfg 2631 2683 * space 2632 2684 */ ··· 2656 2698 mdelay(20); 2657 2699 OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); 2658 2700 } 2659 - // FIXME: Use PCI layer 2660 - for (i = 0; i < 64; ++i) 2661 - pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]); 2662 2701 pci_disable_device(pdev); 2663 2702 } 2664 2703 /* If we support D2, we go to it (should be fixed later with a flag forcing ··· 2670 2715 pdev->dev.power.power_state = mesg; 2671 2716 2672 2717 return 0; 2718 + } 2719 + 2720 + static int radeon_check_power_loss(struct radeonfb_info *rinfo) 2721 + { 2722 + return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || 2723 + rinfo->save_regs[2] != INPLL(MCLK_CNTL) || 2724 + rinfo->save_regs[3] != INPLL(SCLK_CNTL); 2673 2725 } 2674 2726 2675 2727 int radeonfb_pci_resume(struct pci_dev *pdev) ··· 2697 2735 printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", 2698 2736 pci_name(pdev), pdev->dev.power.power_state.event); 2699 2737 2700 - 2701 - if (pci_enable_device(pdev)) { 2702 - rc = -ENODEV; 2703 - printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", 2704 - pci_name(pdev)); 2705 - goto bail; 2706 - } 2707 - pci_set_master(pdev); 2708 - 2738 + /* PCI state will have been restored by the core, so 2739 + * we should be in D0 now with our config space fully 2740 + * restored 2741 + */ 2709 2742 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { 2710 - /* Wakeup chip. Check from config space if we were powered off 2711 - * (todo: additionally, check CLK_PIN_CNTL too) 2712 - */ 2713 - if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) { 2743 + /* Wakeup chip */ 2744 + if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { 2714 2745 if (rinfo->reinit_func != NULL) 2715 2746 rinfo->reinit_func(rinfo); 2716 2747 else {
-2
drivers/video/aty/radeonfb.h
··· 361 361 #ifdef CONFIG_FB_RADEON_I2C 362 362 struct radeon_i2c_chan i2c[4]; 363 363 #endif 364 - 365 - u32 cfg_save[64]; 366 364 }; 367 365 368 366