diff options
Diffstat (limited to 'arch/x86/kernel/pci-gart_64.c')
-rw-r--r-- | arch/x86/kernel/pci-gart_64.c | 114 |
1 files changed, 76 insertions, 38 deletions
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index aa8ec928caa8..49285f8fd4d5 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/mtrr.h> | 32 | #include <asm/mtrr.h> |
33 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
34 | #include <asm/proto.h> | 34 | #include <asm/proto.h> |
35 | #include <asm/iommu.h> | ||
35 | #include <asm/gart.h> | 36 | #include <asm/gart.h> |
36 | #include <asm/cacheflush.h> | 37 | #include <asm/cacheflush.h> |
37 | #include <asm/swiotlb.h> | 38 | #include <asm/swiotlb.h> |
@@ -66,9 +67,6 @@ static u32 gart_unmapped_entry; | |||
66 | (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) | 67 | (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) |
67 | #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) | 68 | #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) |
68 | 69 | ||
69 | #define to_pages(addr, size) \ | ||
70 | (round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT) | ||
71 | |||
72 | #define EMERGENCY_PAGES 32 /* = 128KB */ | 70 | #define EMERGENCY_PAGES 32 /* = 128KB */ |
73 | 71 | ||
74 | #ifdef CONFIG_AGP | 72 | #ifdef CONFIG_AGP |
@@ -104,7 +102,6 @@ static unsigned long alloc_iommu(struct device *dev, int size) | |||
104 | size, base_index, boundary_size, 0); | 102 | size, base_index, boundary_size, 0); |
105 | } | 103 | } |
106 | if (offset != -1) { | 104 | if (offset != -1) { |
107 | set_bit_string(iommu_gart_bitmap, offset, size); | ||
108 | next_bit = offset+size; | 105 | next_bit = offset+size; |
109 | if (next_bit >= iommu_pages) { | 106 | if (next_bit >= iommu_pages) { |
110 | next_bit = 0; | 107 | next_bit = 0; |
@@ -198,9 +195,7 @@ static void iommu_full(struct device *dev, size_t size, int dir) | |||
198 | * out. Hopefully no network devices use single mappings that big. | 195 | * out. Hopefully no network devices use single mappings that big. |
199 | */ | 196 | */ |
200 | 197 | ||
201 | printk(KERN_ERR | 198 | dev_err(dev, "PCI-DMA: Out of IOMMU space for %lu bytes\n", size); |
202 | "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", | ||
203 | size, dev->bus_id); | ||
204 | 199 | ||
205 | if (size > PAGE_SIZE*EMERGENCY_PAGES) { | 200 | if (size > PAGE_SIZE*EMERGENCY_PAGES) { |
206 | if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) | 201 | if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) |
@@ -243,7 +238,7 @@ nonforced_iommu(struct device *dev, unsigned long addr, size_t size) | |||
243 | static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, | 238 | static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem, |
244 | size_t size, int dir) | 239 | size_t size, int dir) |
245 | { | 240 | { |
246 | unsigned long npages = to_pages(phys_mem, size); | 241 | unsigned long npages = iommu_num_pages(phys_mem, size); |
247 | unsigned long iommu_page = alloc_iommu(dev, npages); | 242 | unsigned long iommu_page = alloc_iommu(dev, npages); |
248 | int i; | 243 | int i; |
249 | 244 | ||
@@ -306,7 +301,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr, | |||
306 | return; | 301 | return; |
307 | 302 | ||
308 | iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; | 303 | iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; |
309 | npages = to_pages(dma_addr, size); | 304 | npages = iommu_num_pages(dma_addr, size); |
310 | for (i = 0; i < npages; i++) { | 305 | for (i = 0; i < npages; i++) { |
311 | iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; | 306 | iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; |
312 | CLEAR_LEAK(iommu_page + i); | 307 | CLEAR_LEAK(iommu_page + i); |
@@ -389,7 +384,7 @@ static int __dma_map_cont(struct device *dev, struct scatterlist *start, | |||
389 | } | 384 | } |
390 | 385 | ||
391 | addr = phys_addr; | 386 | addr = phys_addr; |
392 | pages = to_pages(s->offset, s->length); | 387 | pages = iommu_num_pages(s->offset, s->length); |
393 | while (pages--) { | 388 | while (pages--) { |
394 | iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); | 389 | iommu_gatt_base[iommu_page] = GPTE_ENCODE(addr); |
395 | SET_LEAK(iommu_page); | 390 | SET_LEAK(iommu_page); |
@@ -472,7 +467,7 @@ gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) | |||
472 | 467 | ||
473 | seg_size += s->length; | 468 | seg_size += s->length; |
474 | need = nextneed; | 469 | need = nextneed; |
475 | pages += to_pages(s->offset, s->length); | 470 | pages += iommu_num_pages(s->offset, s->length); |
476 | ps = s; | 471 | ps = s; |
477 | } | 472 | } |
478 | if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0) | 473 | if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0) |
@@ -534,8 +529,8 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) | |||
534 | unsigned aper_size = 0, aper_base_32, aper_order; | 529 | unsigned aper_size = 0, aper_base_32, aper_order; |
535 | u64 aper_base; | 530 | u64 aper_base; |
536 | 531 | ||
537 | pci_read_config_dword(dev, 0x94, &aper_base_32); | 532 | pci_read_config_dword(dev, AMD64_GARTAPERTUREBASE, &aper_base_32); |
538 | pci_read_config_dword(dev, 0x90, &aper_order); | 533 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &aper_order); |
539 | aper_order = (aper_order >> 1) & 7; | 534 | aper_order = (aper_order >> 1) & 7; |
540 | 535 | ||
541 | aper_base = aper_base_32 & 0x7fff; | 536 | aper_base = aper_base_32 & 0x7fff; |
@@ -549,14 +544,63 @@ static __init unsigned read_aperture(struct pci_dev *dev, u32 *size) | |||
549 | return aper_base; | 544 | return aper_base; |
550 | } | 545 | } |
551 | 546 | ||
547 | static void enable_gart_translations(void) | ||
548 | { | ||
549 | int i; | ||
550 | |||
551 | for (i = 0; i < num_k8_northbridges; i++) { | ||
552 | struct pci_dev *dev = k8_northbridges[i]; | ||
553 | |||
554 | enable_gart_translation(dev, __pa(agp_gatt_table)); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * If fix_up_north_bridges is set, the north bridges have to be fixed up on | ||
560 | * resume in the same way as they are handled in gart_iommu_hole_init(). | ||
561 | */ | ||
562 | static bool fix_up_north_bridges; | ||
563 | static u32 aperture_order; | ||
564 | static u32 aperture_alloc; | ||
565 | |||
566 | void set_up_gart_resume(u32 aper_order, u32 aper_alloc) | ||
567 | { | ||
568 | fix_up_north_bridges = true; | ||
569 | aperture_order = aper_order; | ||
570 | aperture_alloc = aper_alloc; | ||
571 | } | ||
572 | |||
552 | static int gart_resume(struct sys_device *dev) | 573 | static int gart_resume(struct sys_device *dev) |
553 | { | 574 | { |
575 | printk(KERN_INFO "PCI-DMA: Resuming GART IOMMU\n"); | ||
576 | |||
577 | if (fix_up_north_bridges) { | ||
578 | int i; | ||
579 | |||
580 | printk(KERN_INFO "PCI-DMA: Restoring GART aperture settings\n"); | ||
581 | |||
582 | for (i = 0; i < num_k8_northbridges; i++) { | ||
583 | struct pci_dev *dev = k8_northbridges[i]; | ||
584 | |||
585 | /* | ||
586 | * Don't enable translations just yet. That is the next | ||
587 | * step. Restore the pre-suspend aperture settings. | ||
588 | */ | ||
589 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, | ||
590 | aperture_order << 1); | ||
591 | pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, | ||
592 | aperture_alloc >> 25); | ||
593 | } | ||
594 | } | ||
595 | |||
596 | enable_gart_translations(); | ||
597 | |||
554 | return 0; | 598 | return 0; |
555 | } | 599 | } |
556 | 600 | ||
557 | static int gart_suspend(struct sys_device *dev, pm_message_t state) | 601 | static int gart_suspend(struct sys_device *dev, pm_message_t state) |
558 | { | 602 | { |
559 | return -EINVAL; | 603 | return 0; |
560 | } | 604 | } |
561 | 605 | ||
562 | static struct sysdev_class gart_sysdev_class = { | 606 | static struct sysdev_class gart_sysdev_class = { |
@@ -582,6 +626,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
582 | struct pci_dev *dev; | 626 | struct pci_dev *dev; |
583 | void *gatt; | 627 | void *gatt; |
584 | int i, error; | 628 | int i, error; |
629 | unsigned long start_pfn, end_pfn; | ||
585 | 630 | ||
586 | printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); | 631 | printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); |
587 | aper_size = aper_base = info->aper_size = 0; | 632 | aper_size = aper_base = info->aper_size = 0; |
@@ -614,31 +659,25 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
614 | memset(gatt, 0, gatt_size); | 659 | memset(gatt, 0, gatt_size); |
615 | agp_gatt_table = gatt; | 660 | agp_gatt_table = gatt; |
616 | 661 | ||
617 | for (i = 0; i < num_k8_northbridges; i++) { | 662 | enable_gart_translations(); |
618 | u32 gatt_reg; | ||
619 | u32 ctl; | ||
620 | |||
621 | dev = k8_northbridges[i]; | ||
622 | gatt_reg = __pa(gatt) >> 12; | ||
623 | gatt_reg <<= 4; | ||
624 | pci_write_config_dword(dev, 0x98, gatt_reg); | ||
625 | pci_read_config_dword(dev, 0x90, &ctl); | ||
626 | |||
627 | ctl |= 1; | ||
628 | ctl &= ~((1<<4) | (1<<5)); | ||
629 | |||
630 | pci_write_config_dword(dev, 0x90, ctl); | ||
631 | } | ||
632 | 663 | ||
633 | error = sysdev_class_register(&gart_sysdev_class); | 664 | error = sysdev_class_register(&gart_sysdev_class); |
634 | if (!error) | 665 | if (!error) |
635 | error = sysdev_register(&device_gart); | 666 | error = sysdev_register(&device_gart); |
636 | if (error) | 667 | if (error) |
637 | panic("Could not register gart_sysdev -- would corrupt data on next suspend"); | 668 | panic("Could not register gart_sysdev -- would corrupt data on next suspend"); |
669 | |||
638 | flush_gart(); | 670 | flush_gart(); |
639 | 671 | ||
640 | printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n", | 672 | printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n", |
641 | aper_base, aper_size>>10); | 673 | aper_base, aper_size>>10); |
674 | |||
675 | /* need to map that range */ | ||
676 | end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); | ||
677 | if (end_pfn > max_low_pfn_mapped) { | ||
678 | start_pfn = (aper_base>>PAGE_SHIFT); | ||
679 | init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT); | ||
680 | } | ||
642 | return 0; | 681 | return 0; |
643 | 682 | ||
644 | nommu: | 683 | nommu: |
@@ -650,8 +689,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
650 | 689 | ||
651 | extern int agp_amd64_init(void); | 690 | extern int agp_amd64_init(void); |
652 | 691 | ||
653 | static const struct dma_mapping_ops gart_dma_ops = { | 692 | static struct dma_mapping_ops gart_dma_ops = { |
654 | .mapping_error = NULL, | ||
655 | .map_single = gart_map_single, | 693 | .map_single = gart_map_single, |
656 | .map_simple = gart_map_simple, | 694 | .map_simple = gart_map_simple, |
657 | .unmap_single = gart_unmap_single, | 695 | .unmap_single = gart_unmap_single, |
@@ -677,11 +715,11 @@ void gart_iommu_shutdown(void) | |||
677 | u32 ctl; | 715 | u32 ctl; |
678 | 716 | ||
679 | dev = k8_northbridges[i]; | 717 | dev = k8_northbridges[i]; |
680 | pci_read_config_dword(dev, 0x90, &ctl); | 718 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); |
681 | 719 | ||
682 | ctl &= ~1; | 720 | ctl &= ~GARTEN; |
683 | 721 | ||
684 | pci_write_config_dword(dev, 0x90, ctl); | 722 | pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl); |
685 | } | 723 | } |
686 | } | 724 | } |
687 | 725 | ||
@@ -716,10 +754,10 @@ void __init gart_iommu_init(void) | |||
716 | return; | 754 | return; |
717 | 755 | ||
718 | if (no_iommu || | 756 | if (no_iommu || |
719 | (!force_iommu && end_pfn <= MAX_DMA32_PFN) || | 757 | (!force_iommu && max_pfn <= MAX_DMA32_PFN) || |
720 | !gart_iommu_aperture || | 758 | !gart_iommu_aperture || |
721 | (no_agp && init_k8_gatt(&info) < 0)) { | 759 | (no_agp && init_k8_gatt(&info) < 0)) { |
722 | if (end_pfn > MAX_DMA32_PFN) { | 760 | if (max_pfn > MAX_DMA32_PFN) { |
723 | printk(KERN_WARNING "More than 4GB of memory " | 761 | printk(KERN_WARNING "More than 4GB of memory " |
724 | "but GART IOMMU not available.\n" | 762 | "but GART IOMMU not available.\n" |
725 | KERN_WARNING "falling back to iommu=soft.\n"); | 763 | KERN_WARNING "falling back to iommu=soft.\n"); |
@@ -788,10 +826,10 @@ void __init gart_iommu_init(void) | |||
788 | wbinvd(); | 826 | wbinvd(); |
789 | 827 | ||
790 | /* | 828 | /* |
791 | * Try to workaround a bug (thanks to BenH) | 829 | * Try to workaround a bug (thanks to BenH): |
792 | * Set unmapped entries to a scratch page instead of 0. | 830 | * Set unmapped entries to a scratch page instead of 0. |
793 | * Any prefetches that hit unmapped entries won't get an bus abort | 831 | * Any prefetches that hit unmapped entries won't get an bus abort |
794 | * then. | 832 | * then. (P2P bridge may be prefetching on DMA reads). |
795 | */ | 833 | */ |
796 | scratch = get_zeroed_page(GFP_KERNEL); | 834 | scratch = get_zeroed_page(GFP_KERNEL); |
797 | if (!scratch) | 835 | if (!scratch) |