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>

+78 -30
+78 -30
drivers/char/agp/intel-agp.c
··· 117 117 * popup and for the GTT. 118 118 */ 119 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 125 struct resource ifp_resource; 122 126 } intel_private; 123 127 ··· 583 579 intel_private.gtt_entries = gtt_entries; 584 580 } 585 581 582 + static void intel_i830_fini_flush(void) 583 + { 584 + kunmap(intel_private.i8xx_page); 585 + intel_private.i8xx_flush_page = NULL; 586 + unmap_page_from_agp(intel_private.i8xx_page); 587 + flush_agp_mappings(); 588 + 589 + __free_page(intel_private.i8xx_page); 590 + } 591 + 592 + static void intel_i830_setup_flush(void) 593 + { 594 + 595 + intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); 596 + if (!intel_private.i8xx_page) { 597 + return; 598 + } 599 + 600 + /* make page uncached */ 601 + map_page_into_agp(intel_private.i8xx_page); 602 + flush_agp_mappings(); 603 + 604 + intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page); 605 + if (!intel_private.i8xx_flush_page) 606 + intel_i830_fini_flush(); 607 + } 608 + 609 + static void intel_i830_chipset_flush(struct agp_bridge_data *bridge) 610 + { 611 + unsigned int *pg = intel_private.i8xx_flush_page; 612 + int i; 613 + 614 + for (i = 0; i < 256; i+=2) 615 + *(pg + i) = i; 616 + 617 + wmb(); 618 + } 619 + 586 620 /* The intel i830 automatically initializes the agp aperture during POST. 587 621 * Use the memory already set aside for in the GTT. 588 622 */ ··· 721 679 } 722 680 723 681 global_cache_flush(); 682 + 683 + intel_i830_setup_flush(); 724 684 return 0; 725 685 } 726 686 ··· 822 778 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 823 779 PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 824 780 pcibios_align_resource, agp_bridge->dev); 825 - if (ret != 0) 826 - return ret; 827 781 828 - printk("intel priv bus start %08lx\n", intel_private.ifp_resource.start); 829 - return 0; 782 + return ret; 830 783 } 831 784 832 785 static void intel_i915_setup_chipset_flush(void) ··· 863 822 864 823 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32)); 865 824 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 866 - intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 867 825 } else { 868 826 u64 l64; 869 827 ··· 873 833 intel_private.ifp_resource.end = l64 + PAGE_SIZE; 874 834 ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 875 835 if (!ret) { 876 - intel_private.ifp_resource.start = 0; 877 - printk("Failed inserting resource into tree\n"); 836 + printk("Failed inserting resource into tree - continuing\n"); 878 837 } 838 + } 839 + } 840 + 841 + static void intel_i9xx_setup_flush(void) 842 + { 843 + /* setup a resource for this object */ 844 + memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource)); 845 + 846 + intel_private.ifp_resource.name = "Intel Flush Page"; 847 + intel_private.ifp_resource.flags = IORESOURCE_MEM; 848 + 849 + /* Setup chipset flush for 915 */ 850 + if (IS_I965 || IS_G33) { 851 + intel_i965_g33_setup_chipset_flush(); 852 + } else { 853 + intel_i915_setup_chipset_flush(); 854 + } 855 + 856 + if (intel_private.ifp_resource.start) { 857 + intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 858 + if (!intel_private.i9xx_flush_page) 859 + printk("unable to ioremap flush page - no chipset flushing"); 879 860 } 880 861 } 881 862 ··· 929 868 930 869 global_cache_flush(); 931 870 932 - /* setup a resource for this object */ 933 - memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource)); 934 - 935 - intel_private.ifp_resource.name = "Intel Flush Page"; 936 - intel_private.ifp_resource.flags = IORESOURCE_MEM; 937 - 938 - /* Setup chipset flush for 915 */ 939 - if (IS_I965 || IS_G33) { 940 - intel_i965_g33_setup_chipset_flush(); 941 - } else { 942 - intel_i915_setup_chipset_flush(); 943 - } 944 - 945 - if (intel_private.ifp_resource.start) { 946 - intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 947 - if (!intel_private.flush_page) 948 - printk("unable to ioremap flush page - no chipset flushing"); 949 - } 871 + intel_i9xx_setup_flush(); 950 872 951 873 return 0; 952 874 } 953 875 954 876 static void intel_i915_cleanup(void) 955 877 { 956 - if (intel_private.flush_page) 957 - iounmap(intel_private.flush_page); 878 + if (intel_private.i9xx_flush_page) 879 + iounmap(intel_private.i9xx_flush_page); 958 880 iounmap(intel_private.gtt); 959 881 iounmap(intel_private.registers); 960 882 } 961 883 962 884 static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 963 885 { 964 - if (intel_private.flush_page) 965 - writel(1, intel_private.flush_page); 886 + if (intel_private.i9xx_flush_page) 887 + writel(1, intel_private.i9xx_flush_page); 966 888 } 967 889 968 890 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, ··· 1439 1395 pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1)); 1440 1396 /* clear any possible error conditions */ 1441 1397 pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 1398 + 1399 + intel_i830_setup_flush(); 1442 1400 return 0; 1443 1401 } 1444 1402 ··· 1697 1651 .agp_alloc_page = agp_generic_alloc_page, 1698 1652 .agp_destroy_page = agp_generic_destroy_page, 1699 1653 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1654 + .chipset_flush = intel_i830_chipset_flush, 1700 1655 }; 1701 1656 1702 1657 static const struct agp_bridge_driver intel_820_driver = { ··· 1794 1747 .agp_alloc_page = agp_generic_alloc_page, 1795 1748 .agp_destroy_page = agp_generic_destroy_page, 1796 1749 .agp_type_to_mask_type = agp_generic_type_to_mask_type, 1750 + .chipset_flush = intel_i830_chipset_flush, 1797 1751 }; 1798 1752 1799 1753 static const struct agp_bridge_driver intel_850_driver = {