aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/intel-agp.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2007-11-21 01:36:31 -0500
committerDave Airlie <airlied@redhat.com>2008-02-04 23:33:32 -0500
commit2162e6a2b0cd5acbb9bd8a3c94e1c1269b078295 (patch)
treebce822874c1a0e4845992a27d47e45a6fca0595e /drivers/char/agp/intel-agp.c
parent6c00a61e1bc969c3ea931f62f8789d9818bf1918 (diff)
agp/intel: Add chipset flushing support for i8xx chipsets.
This is a bit of a large hammer but it makes sure the chipset is flushed by writing out 1k of data to an uncached page. We may be able to get better information in the future on how to this better. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/agp/intel-agp.c')
-rw-r--r--drivers/char/agp/intel-agp.c108
1 files changed, 78 insertions, 30 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 4d062fc3e825..ce75fa3a4723 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -117,7 +117,11 @@ static struct _intel_private {
117 * popup and for the GTT. 117 * popup and for the GTT.
118 */ 118 */
119 int gtt_entries; /* i830+ */ 119 int gtt_entries; /* i830+ */
120 void __iomem *flush_page; 120 union {
121 void __iomem *i9xx_flush_page;
122 void *i8xx_flush_page;
123 };
124 struct page *i8xx_page;
121 struct resource ifp_resource; 125 struct resource ifp_resource;
122} intel_private; 126} intel_private;
123 127
@@ -579,6 +583,44 @@ static void intel_i830_init_gtt_entries(void)
579 intel_private.gtt_entries = gtt_entries; 583 intel_private.gtt_entries = gtt_entries;
580} 584}
581 585
586static void intel_i830_fini_flush(void)
587{
588 kunmap(intel_private.i8xx_page);
589 intel_private.i8xx_flush_page = NULL;
590 unmap_page_from_agp(intel_private.i8xx_page);
591 flush_agp_mappings();
592
593 __free_page(intel_private.i8xx_page);
594}
595
596static void intel_i830_setup_flush(void)
597{
598
599 intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
600 if (!intel_private.i8xx_page) {
601 return;
602 }
603
604 /* make page uncached */
605 map_page_into_agp(intel_private.i8xx_page);
606 flush_agp_mappings();
607
608 intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
609 if (!intel_private.i8xx_flush_page)
610 intel_i830_fini_flush();
611}
612
613static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
614{
615 unsigned int *pg = intel_private.i8xx_flush_page;
616 int i;
617
618 for (i = 0; i < 256; i+=2)
619 *(pg + i) = i;
620
621 wmb();
622}
623
582/* The intel i830 automatically initializes the agp aperture during POST. 624/* The intel i830 automatically initializes the agp aperture during POST.
583 * Use the memory already set aside for in the GTT. 625 * Use the memory already set aside for in the GTT.
584 */ 626 */
@@ -679,6 +721,8 @@ static int intel_i830_configure(void)
679 } 721 }
680 722
681 global_cache_flush(); 723 global_cache_flush();
724
725 intel_i830_setup_flush();
682 return 0; 726 return 0;
683} 727}
684 728
@@ -778,11 +822,8 @@ static int intel_alloc_chipset_flush_resource(void)
778 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 822 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
779 PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 823 PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
780 pcibios_align_resource, agp_bridge->dev); 824 pcibios_align_resource, agp_bridge->dev);
781 if (ret != 0)
782 return ret;
783 825
784 printk("intel priv bus start %08lx\n", intel_private.ifp_resource.start); 826 return ret;
785 return 0;
786} 827}
787 828
788static void intel_i915_setup_chipset_flush(void) 829static void intel_i915_setup_chipset_flush(void)
@@ -822,7 +863,6 @@ static void intel_i965_g33_setup_chipset_flush(void)
822 863
823 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32)); 864 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32));
824 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 865 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
825 intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
826 } else { 866 } else {
827 u64 l64; 867 u64 l64;
828 868
@@ -833,12 +873,33 @@ static void intel_i965_g33_setup_chipset_flush(void)
833 intel_private.ifp_resource.end = l64 + PAGE_SIZE; 873 intel_private.ifp_resource.end = l64 + PAGE_SIZE;
834 ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 874 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
835 if (!ret) { 875 if (!ret) {
836 intel_private.ifp_resource.start = 0; 876 printk("Failed inserting resource into tree - continuing\n");
837 printk("Failed inserting resource into tree\n");
838 } 877 }
839 } 878 }
840} 879}
841 880
881static void intel_i9xx_setup_flush(void)
882{
883 /* setup a resource for this object */
884 memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource));
885
886 intel_private.ifp_resource.name = "Intel Flush Page";
887 intel_private.ifp_resource.flags = IORESOURCE_MEM;
888
889 /* Setup chipset flush for 915 */
890 if (IS_I965 || IS_G33) {
891 intel_i965_g33_setup_chipset_flush();
892 } else {
893 intel_i915_setup_chipset_flush();
894 }
895
896 if (intel_private.ifp_resource.start) {
897 intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
898 if (!intel_private.i9xx_flush_page)
899 printk("unable to ioremap flush page - no chipset flushing");
900 }
901}
902
842static int intel_i915_configure(void) 903static int intel_i915_configure(void)
843{ 904{
844 struct aper_size_info_fixed *current_size; 905 struct aper_size_info_fixed *current_size;
@@ -868,40 +929,23 @@ static int intel_i915_configure(void)
868 929
869 global_cache_flush(); 930 global_cache_flush();
870 931
871 /* setup a resource for this object */ 932 intel_i9xx_setup_flush();
872 memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource));
873
874 intel_private.ifp_resource.name = "Intel Flush Page";
875 intel_private.ifp_resource.flags = IORESOURCE_MEM;
876
877 /* Setup chipset flush for 915 */
878 if (IS_I965 || IS_G33) {
879 intel_i965_g33_setup_chipset_flush();
880 } else {
881 intel_i915_setup_chipset_flush();
882 }
883
884 if (intel_private.ifp_resource.start) {
885 intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
886 if (!intel_private.flush_page)
887 printk("unable to ioremap flush page - no chipset flushing");
888 }
889 933
890 return 0; 934 return 0;
891} 935}
892 936
893static void intel_i915_cleanup(void) 937static void intel_i915_cleanup(void)
894{ 938{
895 if (intel_private.flush_page) 939 if (intel_private.i9xx_flush_page)
896 iounmap(intel_private.flush_page); 940 iounmap(intel_private.i9xx_flush_page);
897 iounmap(intel_private.gtt); 941 iounmap(intel_private.gtt);
898 iounmap(intel_private.registers); 942 iounmap(intel_private.registers);
899} 943}
900 944
901static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 945static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
902{ 946{
903 if (intel_private.flush_page) 947 if (intel_private.i9xx_flush_page)
904 writel(1, intel_private.flush_page); 948 writel(1, intel_private.i9xx_flush_page);
905} 949}
906 950
907static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, 951static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -1395,6 +1439,8 @@ static int intel_845_configure(void)
1395 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1)); 1439 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
1396 /* clear any possible error conditions */ 1440 /* clear any possible error conditions */
1397 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 1441 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
1442
1443 intel_i830_setup_flush();
1398 return 0; 1444 return 0;
1399} 1445}
1400 1446
@@ -1651,6 +1697,7 @@ static const struct agp_bridge_driver intel_830_driver = {
1651 .agp_alloc_page = agp_generic_alloc_page, 1697 .agp_alloc_page = agp_generic_alloc_page,
1652 .agp_destroy_page = agp_generic_destroy_page, 1698 .agp_destroy_page = agp_generic_destroy_page,
1653 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1699 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1700 .chipset_flush = intel_i830_chipset_flush,
1654}; 1701};
1655 1702
1656static const struct agp_bridge_driver intel_820_driver = { 1703static const struct agp_bridge_driver intel_820_driver = {
@@ -1747,6 +1794,7 @@ static const struct agp_bridge_driver intel_845_driver = {
1747 .agp_alloc_page = agp_generic_alloc_page, 1794 .agp_alloc_page = agp_generic_alloc_page,
1748 .agp_destroy_page = agp_generic_destroy_page, 1795 .agp_destroy_page = agp_generic_destroy_page,
1749 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1796 .agp_type_to_mask_type = agp_generic_type_to_mask_type,
1797 .chipset_flush = intel_i830_chipset_flush,
1750}; 1798};
1751 1799
1752static const struct agp_bridge_driver intel_850_driver = { 1800static const struct agp_bridge_driver intel_850_driver = {