aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas@tungstengraphics.com>2006-12-20 10:33:41 -0500
committerDave Jones <davej@redhat.com>2006-12-22 22:44:09 -0500
commit5aa80c72263904f1e52eee8ed8cb75887b1d1dc3 (patch)
tree1ab5970066b59a07067765135645224c630424de
parentd5cb8d38cd0029b3573e1c8d5d99d99c86dbdbd6 (diff)
[AGPGART] Remove unnecessary flushes when inserting and removing pages.
This patch is to speed up flipping of pages in and out of the AGP aperture as needed by the new drm memory manager. A number of global cache flushes are removed as well as some PCI posting flushes. The following guidelines have been used: 1) Memory that is only mapped uncached and that has been subject to a global cache flush after the mapping was changed to uncached does not need any more cache flushes. Neither before binding to the aperture nor after unbinding. 2) Only do one PCI posting flush after a sequence of writes modifying page entries in the GATT. Signed-off-by: Thomas Hellstrom <thomas@tungstengraphics.com> Signed-off-by: Dave Jones <davej@redhat.com>
-rw-r--r--drivers/char/agp/generic.c11
-rw-r--r--drivers/char/agp/intel-agp.c62
2 files changed, 50 insertions, 23 deletions
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 883a36a27833..3491d6f84bc6 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -965,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
965 if (!bridge) 965 if (!bridge)
966 return -EINVAL; 966 return -EINVAL;
967 967
968 if (mem->page_count == 0)
969 return 0;
970
968 temp = bridge->current_size; 971 temp = bridge->current_size;
969 972
970 switch (bridge->driver->size_type) { 973 switch (bridge->driver->size_type) {
@@ -1016,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
1016 1019
1017 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1020 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1018 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); 1021 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
1019 readl(bridge->gatt_table+j); /* PCI Posting. */
1020 } 1022 }
1023 readl(bridge->gatt_table+j-1); /* PCI Posting. */
1021 1024
1022 bridge->driver->tlb_flush(mem); 1025 bridge->driver->tlb_flush(mem);
1023 return 0; 1026 return 0;
@@ -1034,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1034 if (!bridge) 1037 if (!bridge)
1035 return -EINVAL; 1038 return -EINVAL;
1036 1039
1040 if (mem->page_count == 0)
1041 return 0;
1042
1037 if (type != 0 || mem->type != 0) { 1043 if (type != 0 || mem->type != 0) {
1038 /* The generic routines know nothing of memory types */ 1044 /* The generic routines know nothing of memory types */
1039 return -EINVAL; 1045 return -EINVAL;
@@ -1042,10 +1048,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
1042 /* AK: bogus, should encode addresses > 4GB */ 1048 /* AK: bogus, should encode addresses > 4GB */
1043 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 1049 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
1044 writel(bridge->scratch_page, bridge->gatt_table+i); 1050 writel(bridge->scratch_page, bridge->gatt_table+i);
1045 readl(bridge->gatt_table+i); /* PCI Posting. */
1046 } 1051 }
1052 readl(bridge->gatt_table+i-1); /* PCI Posting. */
1047 1053
1048 global_cache_flush();
1049 bridge->driver->tlb_flush(mem); 1054 bridge->driver->tlb_flush(mem);
1050 return 0; 1055 return 0;
1051} 1056}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 555b3a8ab49c..029d7f697567 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
207 int i, j, num_entries; 207 int i, j, num_entries;
208 void *temp; 208 void *temp;
209 209
210 if (mem->page_count == 0)
211 return 0;
212
210 temp = agp_bridge->current_size; 213 temp = agp_bridge->current_size;
211 num_entries = A_SIZE_FIX(temp)->num_entries; 214 num_entries = A_SIZE_FIX(temp)->num_entries;
212 215
@@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
221 if (type != 0 || mem->type != 0) { 224 if (type != 0 || mem->type != 0) {
222 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { 225 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
223 /* special insert */ 226 /* special insert */
224 global_cache_flush(); 227 if (!mem->is_flushed) {
228 global_cache_flush();
229 mem->is_flushed = TRUE;
230 }
231
225 for (i = pg_start; i < (pg_start + mem->page_count); i++) { 232 for (i = pg_start; i < (pg_start + mem->page_count); i++) {
226 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); 233 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
227 readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
228 } 234 }
229 global_cache_flush(); 235 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */
236
230 agp_bridge->driver->tlb_flush(mem); 237 agp_bridge->driver->tlb_flush(mem);
231 return 0; 238 return 0;
232 } 239 }
@@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
236 } 243 }
237 244
238insert: 245insert:
239 global_cache_flush(); 246 if (!mem->is_flushed) {
247 global_cache_flush();
248 mem->is_flushed = TRUE;
249 }
250
240 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 251 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
241 writel(agp_bridge->driver->mask_memory(agp_bridge, 252 writel(agp_bridge->driver->mask_memory(agp_bridge,
242 mem->memory[i], mem->type), 253 mem->memory[i], mem->type),
243 intel_i810_private.registers+I810_PTE_BASE+(j*4)); 254 intel_i810_private.registers+I810_PTE_BASE+(j*4));
244 readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
245 } 255 }
246 global_cache_flush(); 256 readl(intel_i810_private.registers+I810_PTE_BASE+(j-1*4)); /* PCI Posting. */
247 257
248 agp_bridge->driver->tlb_flush(mem); 258 agp_bridge->driver->tlb_flush(mem);
249 return 0; 259 return 0;
@@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
254{ 264{
255 int i; 265 int i;
256 266
267 if (mem->page_count == 0)
268 return 0;
269
257 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 270 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
258 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); 271 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
259 readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
260 } 272 }
273 readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));
261 274
262 global_cache_flush();
263 agp_bridge->driver->tlb_flush(mem); 275 agp_bridge->driver->tlb_flush(mem);
264 return 0; 276 return 0;
265} 277}
@@ -576,6 +588,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
576 int i,j,num_entries; 588 int i,j,num_entries;
577 void *temp; 589 void *temp;
578 590
591 if (mem->page_count == 0)
592 return 0;
593
579 temp = agp_bridge->current_size; 594 temp = agp_bridge->current_size;
580 num_entries = A_SIZE_FIX(temp)->num_entries; 595 num_entries = A_SIZE_FIX(temp)->num_entries;
581 596
@@ -598,16 +613,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
598 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 613 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
599 return -EINVAL; 614 return -EINVAL;
600 615
601 global_cache_flush(); /* FIXME: Necessary ?*/ 616 if (!mem->is_flushed) {
617 global_cache_flush();
618 mem->is_flushed = TRUE;
619 }
602 620
603 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 621 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
604 writel(agp_bridge->driver->mask_memory(agp_bridge, 622 writel(agp_bridge->driver->mask_memory(agp_bridge,
605 mem->memory[i], mem->type), 623 mem->memory[i], mem->type),
606 intel_i830_private.registers+I810_PTE_BASE+(j*4)); 624 intel_i830_private.registers+I810_PTE_BASE+(j*4));
607 readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
608 } 625 }
626 readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));
609 627
610 global_cache_flush();
611 agp_bridge->driver->tlb_flush(mem); 628 agp_bridge->driver->tlb_flush(mem);
612 return 0; 629 return 0;
613} 630}
@@ -617,7 +634,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
617{ 634{
618 int i; 635 int i;
619 636
620 global_cache_flush(); 637 if (mem->page_count == 0)
638 return 0;
621 639
622 if (pg_start < intel_i830_private.gtt_entries) { 640 if (pg_start < intel_i830_private.gtt_entries) {
623 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); 641 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -626,10 +644,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
626 644
627 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 645 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
628 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); 646 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
629 readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
630 } 647 }
648 readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));
631 649
632 global_cache_flush();
633 agp_bridge->driver->tlb_flush(mem); 650 agp_bridge->driver->tlb_flush(mem);
634 return 0; 651 return 0;
635} 652}
@@ -686,6 +703,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
686 int i,j,num_entries; 703 int i,j,num_entries;
687 void *temp; 704 void *temp;
688 705
706 if (mem->page_count == 0)
707 return 0;
708
689 temp = agp_bridge->current_size; 709 temp = agp_bridge->current_size;
690 num_entries = A_SIZE_FIX(temp)->num_entries; 710 num_entries = A_SIZE_FIX(temp)->num_entries;
691 711
@@ -708,15 +728,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
708 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 728 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
709 return -EINVAL; 729 return -EINVAL;
710 730
711 global_cache_flush(); 731 if (!mem->is_flushed) {
732 global_cache_flush();
733 mem->is_flushed = TRUE;
734 }
712 735
713 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 736 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
714 writel(agp_bridge->driver->mask_memory(agp_bridge, 737 writel(agp_bridge->driver->mask_memory(agp_bridge,
715 mem->memory[i], mem->type), intel_i830_private.gtt+j); 738 mem->memory[i], mem->type), intel_i830_private.gtt+j);
716 readl(intel_i830_private.gtt+j); /* PCI Posting. */
717 } 739 }
740 readl(intel_i830_private.gtt+j-1);
718 741
719 global_cache_flush();
720 agp_bridge->driver->tlb_flush(mem); 742 agp_bridge->driver->tlb_flush(mem);
721 return 0; 743 return 0;
722} 744}
@@ -726,7 +748,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
726{ 748{
727 int i; 749 int i;
728 750
729 global_cache_flush(); 751 if (mem->page_count == 0)
752 return 0;
730 753
731 if (pg_start < intel_i830_private.gtt_entries) { 754 if (pg_start < intel_i830_private.gtt_entries) {
732 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); 755 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
@@ -735,10 +758,9 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
735 758
736 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 759 for (i = pg_start; i < (mem->page_count + pg_start); i++) {
737 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); 760 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
738 readl(intel_i830_private.gtt+i);
739 } 761 }
762 readl(intel_i830_private.gtt+i-1);
740 763
741 global_cache_flush();
742 agp_bridge->driver->tlb_flush(mem); 764 agp_bridge->driver->tlb_flush(mem);
743 return 0; 765 return 0;
744} 766}