aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/intel-agp.c
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 /drivers/char/agp/intel-agp.c
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>
Diffstat (limited to 'drivers/char/agp/intel-agp.c')
-rw-r--r--drivers/char/agp/intel-agp.c62
1 files changed, 42 insertions, 20 deletions
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}