diff options
-rw-r--r-- | drivers/char/agp/intel-agp.c | 108 |
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 | ||
586 | static 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 | |||
596 | static 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 | |||
613 | static 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 | ||
788 | static void intel_i915_setup_chipset_flush(void) | 829 | static 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 | ||
881 | static 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 | |||
842 | static int intel_i915_configure(void) | 903 | static 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 | ||
893 | static void intel_i915_cleanup(void) | 937 | static 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 | ||
901 | static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) | 945 | static 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 | ||
907 | static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | 951 | static 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 | ||
1656 | static const struct agp_bridge_driver intel_820_driver = { | 1703 | static 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 | ||
1752 | static const struct agp_bridge_driver intel_850_driver = { | 1800 | static const struct agp_bridge_driver intel_850_driver = { |