Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Thomas Hellstrom and committed by
Dave Jones
5aa80c72 d5cb8d38

+50 -23
+8 -3
drivers/char/agp/generic.c
··· 965 965 if (!bridge) 966 966 return -EINVAL; 967 967 968 + if (mem->page_count == 0) 969 + return 0; 970 + 968 971 temp = bridge->current_size; 969 972 970 973 switch (bridge->driver->size_type) { ··· 1019 1016 1020 1017 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1021 1018 writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); 1022 - readl(bridge->gatt_table+j); /* PCI Posting. */ 1023 1019 } 1020 + readl(bridge->gatt_table+j-1); /* PCI Posting. */ 1024 1021 1025 1022 bridge->driver->tlb_flush(mem); 1026 1023 return 0; ··· 1037 1034 if (!bridge) 1038 1035 return -EINVAL; 1039 1036 1037 + if (mem->page_count == 0) 1038 + return 0; 1039 + 1040 1040 if (type != 0 || mem->type != 0) { 1041 1041 /* The generic routines know nothing of memory types */ 1042 1042 return -EINVAL; ··· 1048 1042 /* AK: bogus, should encode addresses > 4GB */ 1049 1043 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 1050 1044 writel(bridge->scratch_page, bridge->gatt_table+i); 1051 - readl(bridge->gatt_table+i); /* PCI Posting. */ 1052 1045 } 1046 + readl(bridge->gatt_table+i-1); /* PCI Posting. */ 1053 1047 1054 - global_cache_flush(); 1055 1048 bridge->driver->tlb_flush(mem); 1056 1049 return 0; 1057 1050 }
+42 -20
drivers/char/agp/intel-agp.c
··· 207 207 int i, j, num_entries; 208 208 void *temp; 209 209 210 + if (mem->page_count == 0) 211 + return 0; 212 + 210 213 temp = agp_bridge->current_size; 211 214 num_entries = A_SIZE_FIX(temp)->num_entries; 212 215 ··· 224 221 if (type != 0 || mem->type != 0) { 225 222 if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { 226 223 /* special insert */ 227 - global_cache_flush(); 224 + if (!mem->is_flushed) { 225 + global_cache_flush(); 226 + mem->is_flushed = TRUE; 227 + } 228 + 228 229 for (i = pg_start; i < (pg_start + mem->page_count); i++) { 229 230 writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); 230 - readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ 231 231 } 232 - global_cache_flush(); 232 + readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ 233 + 233 234 agp_bridge->driver->tlb_flush(mem); 234 235 return 0; 235 236 } ··· 243 236 } 244 237 245 238 insert: 246 - global_cache_flush(); 239 + if (!mem->is_flushed) { 240 + global_cache_flush(); 241 + mem->is_flushed = TRUE; 242 + } 243 + 247 244 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 248 245 writel(agp_bridge->driver->mask_memory(agp_bridge, 249 246 mem->memory[i], mem->type), 250 247 intel_i810_private.registers+I810_PTE_BASE+(j*4)); 251 - readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ 252 248 } 253 - global_cache_flush(); 249 + readl(intel_i810_private.registers+I810_PTE_BASE+(j-1*4)); /* PCI Posting. */ 254 250 255 251 agp_bridge->driver->tlb_flush(mem); 256 252 return 0; ··· 264 254 { 265 255 int i; 266 256 257 + if (mem->page_count == 0) 258 + return 0; 259 + 267 260 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 268 261 writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); 269 - readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ 270 262 } 263 + readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); 271 264 272 - global_cache_flush(); 273 265 agp_bridge->driver->tlb_flush(mem); 274 266 return 0; 275 267 } ··· 588 576 int i,j,num_entries; 589 577 void *temp; 590 578 579 + if (mem->page_count == 0) 580 + return 0; 581 + 591 582 temp = agp_bridge->current_size; 592 583 num_entries = A_SIZE_FIX(temp)->num_entries; 593 584 ··· 613 598 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 614 599 return -EINVAL; 615 600 616 - global_cache_flush(); /* FIXME: Necessary ?*/ 601 + if (!mem->is_flushed) { 602 + global_cache_flush(); 603 + mem->is_flushed = TRUE; 604 + } 617 605 618 606 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 619 607 writel(agp_bridge->driver->mask_memory(agp_bridge, 620 608 mem->memory[i], mem->type), 621 609 intel_i830_private.registers+I810_PTE_BASE+(j*4)); 622 - readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ 623 610 } 611 + readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); 624 612 625 - global_cache_flush(); 626 613 agp_bridge->driver->tlb_flush(mem); 627 614 return 0; 628 615 } ··· 634 617 { 635 618 int i; 636 619 637 - global_cache_flush(); 620 + if (mem->page_count == 0) 621 + return 0; 638 622 639 623 if (pg_start < intel_i830_private.gtt_entries) { 640 624 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); ··· 644 626 645 627 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 646 628 writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); 647 - readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ 648 629 } 630 + readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4)); 649 631 650 - global_cache_flush(); 651 632 agp_bridge->driver->tlb_flush(mem); 652 633 return 0; 653 634 } ··· 703 686 int i,j,num_entries; 704 687 void *temp; 705 688 689 + if (mem->page_count == 0) 690 + return 0; 691 + 706 692 temp = agp_bridge->current_size; 707 693 num_entries = A_SIZE_FIX(temp)->num_entries; 708 694 ··· 728 708 (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) 729 709 return -EINVAL; 730 710 731 - global_cache_flush(); 711 + if (!mem->is_flushed) { 712 + global_cache_flush(); 713 + mem->is_flushed = TRUE; 714 + } 732 715 733 716 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 734 717 writel(agp_bridge->driver->mask_memory(agp_bridge, 735 718 mem->memory[i], mem->type), intel_i830_private.gtt+j); 736 - readl(intel_i830_private.gtt+j); /* PCI Posting. */ 737 719 } 720 + readl(intel_i830_private.gtt+j-1); 738 721 739 - global_cache_flush(); 740 722 agp_bridge->driver->tlb_flush(mem); 741 723 return 0; 742 724 } ··· 748 726 { 749 727 int i; 750 728 751 - global_cache_flush(); 729 + if (mem->page_count == 0) 730 + return 0; 752 731 753 732 if (pg_start < intel_i830_private.gtt_entries) { 754 733 printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); ··· 758 735 759 736 for (i = pg_start; i < (mem->page_count + pg_start); i++) { 760 737 writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); 761 - readl(intel_i830_private.gtt+i); 762 738 } 739 + readl(intel_i830_private.gtt+i-1); 763 740 764 - global_cache_flush(); 765 741 agp_bridge->driver->tlb_flush(mem); 766 742 return 0; 767 743 }