diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/intel-gtt.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 58e32f7c3229..e01f5eaaec82 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
@@ -84,40 +84,33 @@ static struct _intel_private { | |||
84 | #define IS_IRONLAKE intel_private.driver->is_ironlake | 84 | #define IS_IRONLAKE intel_private.driver->is_ironlake |
85 | #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable | 85 | #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable |
86 | 86 | ||
87 | int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, | 87 | static int intel_gtt_map_memory(struct page **pages, |
88 | struct scatterlist **sg_list, int *num_sg) | 88 | unsigned int num_entries, |
89 | struct sg_table *st) | ||
89 | { | 90 | { |
90 | struct sg_table st; | ||
91 | struct scatterlist *sg; | 91 | struct scatterlist *sg; |
92 | int i; | 92 | int i; |
93 | 93 | ||
94 | if (*sg_list) | ||
95 | return 0; /* already mapped (for e.g. resume */ | ||
96 | |||
97 | DBG("try mapping %lu pages\n", (unsigned long)num_entries); | 94 | DBG("try mapping %lu pages\n", (unsigned long)num_entries); |
98 | 95 | ||
99 | if (sg_alloc_table(&st, num_entries, GFP_KERNEL)) | 96 | if (sg_alloc_table(st, num_entries, GFP_KERNEL)) |
100 | goto err; | 97 | goto err; |
101 | 98 | ||
102 | *sg_list = sg = st.sgl; | 99 | for_each_sg(st->sgl, sg, num_entries, i) |
103 | |||
104 | for (i = 0 ; i < num_entries; i++, sg = sg_next(sg)) | ||
105 | sg_set_page(sg, pages[i], PAGE_SIZE, 0); | 100 | sg_set_page(sg, pages[i], PAGE_SIZE, 0); |
106 | 101 | ||
107 | *num_sg = pci_map_sg(intel_private.pcidev, *sg_list, | 102 | if (!pci_map_sg(intel_private.pcidev, |
108 | num_entries, PCI_DMA_BIDIRECTIONAL); | 103 | st->sgl, st->nents, PCI_DMA_BIDIRECTIONAL)) |
109 | if (unlikely(!*num_sg)) | ||
110 | goto err; | 104 | goto err; |
111 | 105 | ||
112 | return 0; | 106 | return 0; |
113 | 107 | ||
114 | err: | 108 | err: |
115 | sg_free_table(&st); | 109 | sg_free_table(st); |
116 | return -ENOMEM; | 110 | return -ENOMEM; |
117 | } | 111 | } |
118 | EXPORT_SYMBOL(intel_gtt_map_memory); | ||
119 | 112 | ||
120 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) | 113 | static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) |
121 | { | 114 | { |
122 | struct sg_table st; | 115 | struct sg_table st; |
123 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); | 116 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); |
@@ -130,7 +123,6 @@ void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) | |||
130 | 123 | ||
131 | sg_free_table(&st); | 124 | sg_free_table(&st); |
132 | } | 125 | } |
133 | EXPORT_SYMBOL(intel_gtt_unmap_memory); | ||
134 | 126 | ||
135 | static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) | 127 | static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) |
136 | { | 128 | { |
@@ -674,9 +666,14 @@ static int intel_gtt_init(void) | |||
674 | 666 | ||
675 | gtt_map_size = intel_private.base.gtt_total_entries * 4; | 667 | gtt_map_size = intel_private.base.gtt_total_entries * 4; |
676 | 668 | ||
677 | intel_private.gtt = ioremap(intel_private.gtt_bus_addr, | 669 | intel_private.gtt = NULL; |
678 | gtt_map_size); | 670 | if (INTEL_GTT_GEN < 6) |
679 | if (!intel_private.gtt) { | 671 | intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, |
672 | gtt_map_size); | ||
673 | if (intel_private.gtt == NULL) | ||
674 | intel_private.gtt = ioremap(intel_private.gtt_bus_addr, | ||
675 | gtt_map_size); | ||
676 | if (intel_private.gtt == NULL) { | ||
680 | intel_private.driver->cleanup(); | 677 | intel_private.driver->cleanup(); |
681 | iounmap(intel_private.registers); | 678 | iounmap(intel_private.registers); |
682 | return -ENOMEM; | 679 | return -ENOMEM; |
@@ -879,8 +876,7 @@ static bool i830_check_flags(unsigned int flags) | |||
879 | return false; | 876 | return false; |
880 | } | 877 | } |
881 | 878 | ||
882 | void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, | 879 | void intel_gtt_insert_sg_entries(struct sg_table *st, |
883 | unsigned int sg_len, | ||
884 | unsigned int pg_start, | 880 | unsigned int pg_start, |
885 | unsigned int flags) | 881 | unsigned int flags) |
886 | { | 882 | { |
@@ -892,12 +888,11 @@ void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, | |||
892 | 888 | ||
893 | /* sg may merge pages, but we have to separate | 889 | /* sg may merge pages, but we have to separate |
894 | * per-page addr for GTT */ | 890 | * per-page addr for GTT */ |
895 | for_each_sg(sg_list, sg, sg_len, i) { | 891 | for_each_sg(st->sgl, sg, st->nents, i) { |
896 | len = sg_dma_len(sg) >> PAGE_SHIFT; | 892 | len = sg_dma_len(sg) >> PAGE_SHIFT; |
897 | for (m = 0; m < len; m++) { | 893 | for (m = 0; m < len; m++) { |
898 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | 894 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
899 | intel_private.driver->write_entry(addr, | 895 | intel_private.driver->write_entry(addr, j, flags); |
900 | j, flags); | ||
901 | j++; | 896 | j++; |
902 | } | 897 | } |
903 | } | 898 | } |
@@ -905,8 +900,10 @@ void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, | |||
905 | } | 900 | } |
906 | EXPORT_SYMBOL(intel_gtt_insert_sg_entries); | 901 | EXPORT_SYMBOL(intel_gtt_insert_sg_entries); |
907 | 902 | ||
908 | void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, | 903 | static void intel_gtt_insert_pages(unsigned int first_entry, |
909 | struct page **pages, unsigned int flags) | 904 | unsigned int num_entries, |
905 | struct page **pages, | ||
906 | unsigned int flags) | ||
910 | { | 907 | { |
911 | int i, j; | 908 | int i, j; |
912 | 909 | ||
@@ -917,7 +914,6 @@ void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, | |||
917 | } | 914 | } |
918 | readl(intel_private.gtt+j-1); | 915 | readl(intel_private.gtt+j-1); |
919 | } | 916 | } |
920 | EXPORT_SYMBOL(intel_gtt_insert_pages); | ||
921 | 917 | ||
922 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, | 918 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, |
923 | off_t pg_start, int type) | 919 | off_t pg_start, int type) |
@@ -953,13 +949,15 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, | |||
953 | global_cache_flush(); | 949 | global_cache_flush(); |
954 | 950 | ||
955 | if (intel_private.base.needs_dmar) { | 951 | if (intel_private.base.needs_dmar) { |
956 | ret = intel_gtt_map_memory(mem->pages, mem->page_count, | 952 | struct sg_table st; |
957 | &mem->sg_list, &mem->num_sg); | 953 | |
954 | ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st); | ||
958 | if (ret != 0) | 955 | if (ret != 0) |
959 | return ret; | 956 | return ret; |
960 | 957 | ||
961 | intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, | 958 | intel_gtt_insert_sg_entries(&st, pg_start, type); |
962 | pg_start, type); | 959 | mem->sg_list = st.sgl; |
960 | mem->num_sg = st.nents; | ||
963 | } else | 961 | } else |
964 | intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, | 962 | intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, |
965 | type); | 963 | type); |