aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/pci-gart_64.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2008-06-09 18:10:48 -0400
committerIngo Molnar <mingo@elte.hu>2008-06-12 08:11:25 -0400
commit6703f6d10dcd3316e03641a5ecaa6c8a04374d98 (patch)
treef8c1d9bbc5695979d2ad822a7bccb42f375dc904 /arch/x86/kernel/pci-gart_64.c
parentbb6dfb32f90094fea647e1f27d994a8b6ddd2766 (diff)
x86, gart: add resume handling
If GART IOMMU is used on an AMD64 system, the northbridge registers related to it should be restored during resume so that memory is not corrupted. Make gart_resume() handle that as appropriate. Ref. http://lkml.org/lkml/2008/5/25/96 and the following thread. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/pci-gart_64.c')
-rw-r--r--arch/x86/kernel/pci-gart_64.c57
1 files changed, 52 insertions, 5 deletions
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index 3710097f02eb..f505c3890358 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -549,14 +549,63 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size)
549 return aper_base; 549 return aper_base;
550} 550}
551 551
552static void enable_gart_translations(void)
553{
554 int i;
555
556 for (i = 0; i < num_k8_northbridges; i++) {
557 struct pci_dev *dev = k8_northbridges[i];
558
559 enable_gart_translation(dev, __pa(agp_gatt_table));
560 }
561}
562
563/*
564 * If fix_up_north_bridges is set, the north bridges have to be fixed up on
565 * resume in the same way as they are handled in gart_iommu_hole_init().
566 */
567static bool fix_up_north_bridges;
568static u32 aperture_order;
569static u32 aperture_alloc;
570
571void set_up_gart_resume(u32 aper_order, u32 aper_alloc)
572{
573 fix_up_north_bridges = true;
574 aperture_order = aper_order;
575 aperture_alloc = aper_alloc;
576}
577
552static int gart_resume(struct sys_device *dev) 578static int gart_resume(struct sys_device *dev)
553{ 579{
580 printk(KERN_INFO "PCI-DMA: Resuming GART IOMMU\n");
581
582 if (fix_up_north_bridges) {
583 int i;
584
585 printk(KERN_INFO "PCI-DMA: Restoring GART aperture settings\n");
586
587 for (i = 0; i < num_k8_northbridges; i++) {
588 struct pci_dev *dev = k8_northbridges[i];
589
590 /*
591 * Don't enable translations just yet. That is the next
592 * step. Restore the pre-suspend aperture settings.
593 */
594 pci_write_config_dword(dev, AMD64_GARTAPERTURECTL,
595 aperture_order << 1);
596 pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE,
597 aperture_alloc >> 25);
598 }
599 }
600
601 enable_gart_translations();
602
554 return 0; 603 return 0;
555} 604}
556 605
557static int gart_suspend(struct sys_device *dev, pm_message_t state) 606static int gart_suspend(struct sys_device *dev, pm_message_t state)
558{ 607{
559 return -EINVAL; 608 return 0;
560} 609}
561 610
562static struct sysdev_class gart_sysdev_class = { 611static struct sysdev_class gart_sysdev_class = {
@@ -614,16 +663,14 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
614 memset(gatt, 0, gatt_size); 663 memset(gatt, 0, gatt_size);
615 agp_gatt_table = gatt; 664 agp_gatt_table = gatt;
616 665
617 for (i = 0; i < num_k8_northbridges; i++) { 666 enable_gart_translations();
618 dev = k8_northbridges[i];
619 enable_gart_translation(dev, __pa(gatt));
620 }
621 667
622 error = sysdev_class_register(&gart_sysdev_class); 668 error = sysdev_class_register(&gart_sysdev_class);
623 if (!error) 669 if (!error)
624 error = sysdev_register(&device_gart); 670 error = sysdev_register(&device_gart);
625 if (error) 671 if (error)
626 panic("Could not register gart_sysdev -- would corrupt data on next suspend"); 672 panic("Could not register gart_sysdev -- would corrupt data on next suspend");
673
627 flush_gart(); 674 flush_gart();
628 675
629 printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n", 676 printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n",