diff options
Diffstat (limited to 'arch/x86/kernel/pci-gart_64.c')
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 120 |
1 files changed, 96 insertions, 24 deletions
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index c07455d1695f..c3fe78406d18 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kdebug.h> | 26 | #include <linux/kdebug.h> |
27 | #include <linux/scatterlist.h> | 27 | #include <linux/scatterlist.h> |
28 | #include <linux/iommu-helper.h> | 28 | #include <linux/iommu-helper.h> |
29 | #include <linux/sysdev.h> | ||
29 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
31 | #include <asm/mtrr.h> | 32 | #include <asm/mtrr.h> |
@@ -103,7 +104,6 @@ static unsigned long alloc_iommu(struct device *dev, int size) | |||
103 | size, base_index, boundary_size, 0); | 104 | size, base_index, boundary_size, 0); |
104 | } | 105 | } |
105 | if (offset != -1) { | 106 | if (offset != -1) { |
106 | set_bit_string(iommu_gart_bitmap, offset, size); | ||
107 | next_bit = offset+size; | 107 | next_bit = offset+size; |
108 | if (next_bit >= iommu_pages) { | 108 | if (next_bit >= iommu_pages) { |
109 | next_bit = 0; | 109 | next_bit = 0; |
@@ -533,8 +533,8 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) | |||
533 | unsigned aper_size = 0, aper_base_32, aper_order; | 533 | unsigned aper_size = 0, aper_base_32, aper_order; |
534 | u64 aper_base; | 534 | u64 aper_base; |
535 | 535 | ||
536 | pci_read_config_dword(dev, 0x94, &aper_base_32); | 536 | pci_read_config_dword(dev, AMD64_GARTAPERTUREBASE, &aper_base_32); |
537 | pci_read_config_dword(dev, 0x90, &aper_order); | 537 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &aper_order); |
538 | aper_order = (aper_order >> 1) & 7; | 538 | aper_order = (aper_order >> 1) & 7; |
539 | 539 | ||
540 | aper_base = aper_base_32 & 0x7fff; | 540 | aper_base = aper_base_32 & 0x7fff; |
@@ -548,6 +548,77 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) | |||
548 | return aper_base; | 548 | return aper_base; |
549 | } | 549 | } |
550 | 550 | ||
551 | static void enable_gart_translations(void) | ||
552 | { | ||
553 | int i; | ||
554 | |||
555 | for (i = 0; i < num_k8_northbridges; i++) { | ||
556 | struct pci_dev *dev = k8_northbridges[i]; | ||
557 | |||
558 | enable_gart_translation(dev, __pa(agp_gatt_table)); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* | ||
563 | * If fix_up_north_bridges is set, the north bridges have to be fixed up on | ||
564 | * resume in the same way as they are handled in gart_iommu_hole_init(). | ||
565 | */ | ||
566 | static bool fix_up_north_bridges; | ||
567 | static u32 aperture_order; | ||
568 | static u32 aperture_alloc; | ||
569 | |||
570 | void set_up_gart_resume(u32 aper_order, u32 aper_alloc) | ||
571 | { | ||
572 | fix_up_north_bridges = true; | ||
573 | aperture_order = aper_order; | ||
574 | aperture_alloc = aper_alloc; | ||
575 | } | ||
576 | |||
577 | static int gart_resume(struct sys_device *dev) | ||
578 | { | ||
579 | printk(KERN_INFO "PCI-DMA: Resuming GART IOMMU\n"); | ||
580 | |||
581 | if (fix_up_north_bridges) { | ||
582 | int i; | ||
583 | |||
584 | printk(KERN_INFO "PCI-DMA: Restoring GART aperture settings\n"); | ||
585 | |||
586 | for (i = 0; i < num_k8_northbridges; i++) { | ||
587 | struct pci_dev *dev = k8_northbridges[i]; | ||
588 | |||
589 | /* | ||
590 | * Don't enable translations just yet. That is the next | ||
591 | * step. Restore the pre-suspend aperture settings. | ||
592 | */ | ||
593 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, | ||
594 | aperture_order << 1); | ||
595 | pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, | ||
596 | aperture_alloc >> 25); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | enable_gart_translations(); | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static int gart_suspend(struct sys_device *dev, pm_message_t state) | ||
606 | { | ||
607 | return 0; | ||
608 | } | ||
609 | |||
610 | static struct sysdev_class gart_sysdev_class = { | ||
611 | .name = "gart", | ||
612 | .suspend = gart_suspend, | ||
613 | .resume = gart_resume, | ||
614 | |||
615 | }; | ||
616 | |||
617 | static struct sys_device device_gart = { | ||
618 | .id = 0, | ||
619 | .cls = &gart_sysdev_class, | ||
620 | }; | ||
621 | |||
551 | /* | 622 | /* |
552 | * Private Northbridge GATT initialization in case we cannot use the | 623 | * Private Northbridge GATT initialization in case we cannot use the |
553 | * AGP driver for some reason. | 624 | * AGP driver for some reason. |
@@ -558,7 +629,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
558 | unsigned aper_base, new_aper_base; | 629 | unsigned aper_base, new_aper_base; |
559 | struct pci_dev *dev; | 630 | struct pci_dev *dev; |
560 | void *gatt; | 631 | void *gatt; |
561 | int i; | 632 | int i, error; |
633 | unsigned long start_pfn, end_pfn; | ||
562 | 634 | ||
563 | printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); | 635 | printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); |
564 | aper_size = aper_base = info->aper_size = 0; | 636 | aper_size = aper_base = info->aper_size = 0; |
@@ -591,25 +663,25 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
591 | memset(gatt, 0, gatt_size); | 663 | memset(gatt, 0, gatt_size); |
592 | agp_gatt_table = gatt; | 664 | agp_gatt_table = gatt; |
593 | 665 | ||
594 | for (i = 0; i < num_k8_northbridges; i++) { | 666 | enable_gart_translations(); |
595 | u32 gatt_reg; | ||
596 | u32 ctl; | ||
597 | 667 | ||
598 | dev = k8_northbridges[i]; | 668 | error = sysdev_class_register(&gart_sysdev_class); |
599 | gatt_reg = __pa(gatt) >> 12; | 669 | if (!error) |
600 | gatt_reg <<= 4; | 670 | error = sysdev_register(&device_gart); |
601 | pci_write_config_dword(dev, 0x98, gatt_reg); | 671 | if (error) |
602 | pci_read_config_dword(dev, 0x90, &ctl); | 672 | panic("Could not register gart_sysdev -- would corrupt data on next suspend"); |
603 | |||
604 | ctl |= 1; | ||
605 | ctl &= ~((1<<4) | (1<<5)); | ||
606 | 673 | ||
607 | pci_write_config_dword(dev, 0x90, ctl); | ||
608 | } | ||
609 | flush_gart(); | 674 | flush_gart(); |
610 | 675 | ||
611 | 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", |
612 | aper_base, aper_size>>10); | 677 | aper_base, aper_size>>10); |
678 | |||
679 | /* need to map that range */ | ||
680 | end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); | ||
681 | if (end_pfn > max_low_pfn_mapped) { | ||
682 | start_pfn = (aper_base>>PAGE_SHIFT); | ||
683 | init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
684 | } | ||
613 | return 0; | 685 | return 0; |
614 | 686 | ||
615 | nommu: | 687 | nommu: |
@@ -648,11 +720,11 @@ void gart_iommu_shutdown(void) | |||
648 | u32 ctl; | 720 | u32 ctl; |
649 | 721 | ||
650 | dev = k8_northbridges[i]; | 722 | dev = k8_northbridges[i]; |
651 | pci_read_config_dword(dev, 0x90, &ctl); | 723 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); |
652 | 724 | ||
653 | ctl &= ~1; | 725 | ctl &= ~GARTEN; |
654 | 726 | ||
655 | pci_write_config_dword(dev, 0x90, ctl); | 727 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl); |
656 | } | 728 | } |
657 | } | 729 | } |
658 | 730 | ||
@@ -687,10 +759,10 @@ void __init gart_iommu_init(void) | |||
687 | return; | 759 | return; |
688 | 760 | ||
689 | if (no_iommu || | 761 | if (no_iommu || |
690 | (!force_iommu && end_pfn <= MAX_DMA32_PFN) || | 762 | (!force_iommu && max_pfn <= MAX_DMA32_PFN) || |
691 | !gart_iommu_aperture || | 763 | !gart_iommu_aperture || |
692 | (no_agp && init_k8_gatt(&info) < 0)) { | 764 | (no_agp && init_k8_gatt(&info) < 0)) { |
693 | if (end_pfn > MAX_DMA32_PFN) { | 765 | if (max_pfn > MAX_DMA32_PFN) { |
694 | printk(KERN_WARNING "More than 4GB of memory " | 766 | printk(KERN_WARNING "More than 4GB of memory " |
695 | "but GART IOMMU not available.\n" | 767 | "but GART IOMMU not available.\n" |
696 | KERN_WARNING "falling back to iommu=soft.\n"); | 768 | KERN_WARNING "falling back to iommu=soft.\n"); |
@@ -759,10 +831,10 @@ void __init gart_iommu_init(void) | |||
759 | wbinvd(); | 831 | wbinvd(); |
760 | 832 | ||
761 | /* | 833 | /* |
762 | * Try to workaround a bug (thanks to BenH) | 834 | * Try to workaround a bug (thanks to BenH): |
763 | * Set unmapped entries to a scratch page instead of 0. | 835 | * Set unmapped entries to a scratch page instead of 0. |
764 | * Any prefetches that hit unmapped entries won't get an bus abort | 836 | * Any prefetches that hit unmapped entries won't get an bus abort |
765 | * then. | 837 | * then. (P2P bridge may be prefetching on DMA reads). |
766 | */ | 838 | */ |
767 | scratch = get_zeroed_page(GFP_KERNEL); | 839 | scratch = get_zeroed_page(GFP_KERNEL); |
768 | if (!scratch) | 840 | if (!scratch) |