diff options
Diffstat (limited to 'drivers/char/agp/intel-gtt.c')
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 75 |
1 files changed, 30 insertions, 45 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 826ab0939a12..0d09b537bb9a 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/agp_backend.h> | 23 | #include <linux/agp_backend.h> |
24 | #include <linux/delay.h> | ||
24 | #include <asm/smp.h> | 25 | #include <asm/smp.h> |
25 | #include "agp.h" | 26 | #include "agp.h" |
26 | #include "intel-agp.h" | 27 | #include "intel-agp.h" |
@@ -68,13 +69,10 @@ static struct _intel_private { | |||
68 | phys_addr_t gma_bus_addr; | 69 | phys_addr_t gma_bus_addr; |
69 | u32 PGETBL_save; | 70 | u32 PGETBL_save; |
70 | u32 __iomem *gtt; /* I915G */ | 71 | u32 __iomem *gtt; /* I915G */ |
72 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ | ||
71 | int num_dcache_entries; | 73 | int num_dcache_entries; |
72 | union { | 74 | void __iomem *i9xx_flush_page; |
73 | void __iomem *i9xx_flush_page; | ||
74 | void *i8xx_flush_page; | ||
75 | }; | ||
76 | char *i81x_gtt_table; | 75 | char *i81x_gtt_table; |
77 | struct page *i8xx_page; | ||
78 | struct resource ifp_resource; | 76 | struct resource ifp_resource; |
79 | int resource_valid; | 77 | int resource_valid; |
80 | struct page *scratch_page; | 78 | struct page *scratch_page; |
@@ -721,28 +719,6 @@ static int intel_fake_agp_fetch_size(void) | |||
721 | 719 | ||
722 | static void i830_cleanup(void) | 720 | static void i830_cleanup(void) |
723 | { | 721 | { |
724 | if (intel_private.i8xx_flush_page) { | ||
725 | kunmap(intel_private.i8xx_flush_page); | ||
726 | intel_private.i8xx_flush_page = NULL; | ||
727 | } | ||
728 | |||
729 | __free_page(intel_private.i8xx_page); | ||
730 | intel_private.i8xx_page = NULL; | ||
731 | } | ||
732 | |||
733 | static void intel_i830_setup_flush(void) | ||
734 | { | ||
735 | /* return if we've already set the flush mechanism up */ | ||
736 | if (intel_private.i8xx_page) | ||
737 | return; | ||
738 | |||
739 | intel_private.i8xx_page = alloc_page(GFP_KERNEL); | ||
740 | if (!intel_private.i8xx_page) | ||
741 | return; | ||
742 | |||
743 | intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); | ||
744 | if (!intel_private.i8xx_flush_page) | ||
745 | i830_cleanup(); | ||
746 | } | 722 | } |
747 | 723 | ||
748 | /* The chipset_flush interface needs to get data that has already been | 724 | /* The chipset_flush interface needs to get data that has already been |
@@ -757,14 +733,27 @@ static void intel_i830_setup_flush(void) | |||
757 | */ | 733 | */ |
758 | static void i830_chipset_flush(void) | 734 | static void i830_chipset_flush(void) |
759 | { | 735 | { |
760 | unsigned int *pg = intel_private.i8xx_flush_page; | 736 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
737 | |||
738 | /* Forcibly evict everything from the CPU write buffers. | ||
739 | * clflush appears to be insufficient. | ||
740 | */ | ||
741 | wbinvd_on_all_cpus(); | ||
761 | 742 | ||
762 | memset(pg, 0, 1024); | 743 | /* Now we've only seen documents for this magic bit on 855GM, |
744 | * we hope it exists for the other gen2 chipsets... | ||
745 | * | ||
746 | * Also works as advertised on my 845G. | ||
747 | */ | ||
748 | writel(readl(intel_private.registers+I830_HIC) | (1<<31), | ||
749 | intel_private.registers+I830_HIC); | ||
763 | 750 | ||
764 | if (cpu_has_clflush) | 751 | while (readl(intel_private.registers+I830_HIC) & (1<<31)) { |
765 | clflush_cache_range(pg, 1024); | 752 | if (time_after(jiffies, timeout)) |
766 | else if (wbinvd_on_all_cpus() != 0) | 753 | break; |
767 | printk(KERN_ERR "Timed out waiting for cache flush.\n"); | 754 | |
755 | udelay(50); | ||
756 | } | ||
768 | } | 757 | } |
769 | 758 | ||
770 | static void i830_write_entry(dma_addr_t addr, unsigned int entry, | 759 | static void i830_write_entry(dma_addr_t addr, unsigned int entry, |
@@ -848,8 +837,6 @@ static int i830_setup(void) | |||
848 | 837 | ||
849 | intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; | 838 | intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; |
850 | 839 | ||
851 | intel_i830_setup_flush(); | ||
852 | |||
853 | return 0; | 840 | return 0; |
854 | } | 841 | } |
855 | 842 | ||
@@ -869,21 +856,12 @@ static int intel_fake_agp_free_gatt_table(struct agp_bridge_data *bridge) | |||
869 | 856 | ||
870 | static int intel_fake_agp_configure(void) | 857 | static int intel_fake_agp_configure(void) |
871 | { | 858 | { |
872 | int i; | ||
873 | |||
874 | if (!intel_enable_gtt()) | 859 | if (!intel_enable_gtt()) |
875 | return -EIO; | 860 | return -EIO; |
876 | 861 | ||
862 | intel_private.clear_fake_agp = true; | ||
877 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; | 863 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; |
878 | 864 | ||
879 | for (i = 0; i < intel_private.base.gtt_total_entries; i++) { | ||
880 | intel_private.driver->write_entry(intel_private.scratch_page_dma, | ||
881 | i, 0); | ||
882 | } | ||
883 | readl(intel_private.gtt+i-1); /* PCI Posting. */ | ||
884 | |||
885 | global_cache_flush(); | ||
886 | |||
887 | return 0; | 865 | return 0; |
888 | } | 866 | } |
889 | 867 | ||
@@ -945,6 +923,13 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, | |||
945 | { | 923 | { |
946 | int ret = -EINVAL; | 924 | int ret = -EINVAL; |
947 | 925 | ||
926 | if (intel_private.clear_fake_agp) { | ||
927 | int start = intel_private.base.stolen_size / PAGE_SIZE; | ||
928 | int end = intel_private.base.gtt_mappable_entries; | ||
929 | intel_gtt_clear_range(start, end - start); | ||
930 | intel_private.clear_fake_agp = false; | ||
931 | } | ||
932 | |||
948 | if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY) | 933 | if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY) |
949 | return i810_insert_dcache_entries(mem, pg_start, type); | 934 | return i810_insert_dcache_entries(mem, pg_start, type); |
950 | 935 | ||