diff options
author | Thomas Hellstrom <thomas@tungstengraphics.com> | 2006-12-20 10:33:41 -0500 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2006-12-22 22:44:09 -0500 |
commit | 5aa80c72263904f1e52eee8ed8cb75887b1d1dc3 (patch) | |
tree | 1ab5970066b59a07067765135645224c630424de | |
parent | d5cb8d38cd0029b3573e1c8d5d99d99c86dbdbd6 (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.c | 11 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.c | 62 |
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 | ||
238 | insert: | 245 | insert: |
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 | } |