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 = { |
