Skip to content

Commit

Permalink
[AGPGART] Remove unnecessary flushes when inserting and removing pages.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Thomas Hellstrom authored and Dave Jones committed Dec 23, 2006
1 parent d5cb8d3 commit 5aa80c7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
11 changes: 8 additions & 3 deletions drivers/char/agp/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
if (!bridge)
return -EINVAL;

if (mem->page_count == 0)
return 0;

temp = bridge->current_size;

switch (bridge->driver->size_type) {
Expand Down Expand Up @@ -1016,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)

for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
readl(bridge->gatt_table+j); /* PCI Posting. */
}
readl(bridge->gatt_table+j-1); /* PCI Posting. */

bridge->driver->tlb_flush(mem);
return 0;
Expand All @@ -1034,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
if (!bridge)
return -EINVAL;

if (mem->page_count == 0)
return 0;

if (type != 0 || mem->type != 0) {
/* The generic routines know nothing of memory types */
return -EINVAL;
Expand All @@ -1042,10 +1048,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
/* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(bridge->scratch_page, bridge->gatt_table+i);
readl(bridge->gatt_table+i); /* PCI Posting. */
}
readl(bridge->gatt_table+i-1); /* PCI Posting. */

global_cache_flush();
bridge->driver->tlb_flush(mem);
return 0;
}
Expand Down
62 changes: 42 additions & 20 deletions drivers/char/agp/intel-agp.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
int i, j, num_entries;
void *temp;

if (mem->page_count == 0)
return 0;

temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;

Expand All @@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
if (type != 0 || mem->type != 0) {
if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) {
/* special insert */
global_cache_flush();
if (!mem->is_flushed) {
global_cache_flush();
mem->is_flushed = TRUE;
}

for (i = pg_start; i < (pg_start + mem->page_count); i++) {
writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4));
readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
global_cache_flush();
readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */

agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand All @@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
}

insert:
global_cache_flush();
if (!mem->is_flushed) {
global_cache_flush();
mem->is_flushed = TRUE;
}

for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i810_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
global_cache_flush();
readl(intel_i810_private.registers+I810_PTE_BASE+(j-1*4)); /* PCI Posting. */

agp_bridge->driver->tlb_flush(mem);
return 0;
Expand All @@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
{
int i;

if (mem->page_count == 0)
return 0;

for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4));
readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4));

global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand Down Expand Up @@ -576,6 +588,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
int i,j,num_entries;
void *temp;

if (mem->page_count == 0)
return 0;

temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;

Expand All @@ -598,16 +613,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;

global_cache_flush(); /* FIXME: Necessary ?*/
if (!mem->is_flushed) {
global_cache_flush();
mem->is_flushed = TRUE;
}

for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type),
intel_i830_private.registers+I810_PTE_BASE+(j*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */
}
readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4));

global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand All @@ -617,7 +634,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
{
int i;

global_cache_flush();
if (mem->page_count == 0)
return 0;

if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
Expand All @@ -626,10 +644,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,

for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */
}
readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4));

global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand Down Expand Up @@ -686,6 +703,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
int i,j,num_entries;
void *temp;

if (mem->page_count == 0)
return 0;

temp = agp_bridge->current_size;
num_entries = A_SIZE_FIX(temp)->num_entries;

Expand All @@ -708,15 +728,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
return -EINVAL;

global_cache_flush();
if (!mem->is_flushed) {
global_cache_flush();
mem->is_flushed = TRUE;
}

for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
mem->memory[i], mem->type), intel_i830_private.gtt+j);
readl(intel_i830_private.gtt+j); /* PCI Posting. */
}
readl(intel_i830_private.gtt+j-1);

global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand All @@ -726,7 +748,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
{
int i;

global_cache_flush();
if (mem->page_count == 0)
return 0;

if (pg_start < intel_i830_private.gtt_entries) {
printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
Expand All @@ -735,10 +758,9 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,

for (i = pg_start; i < (mem->page_count + pg_start); i++) {
writel(agp_bridge->scratch_page, intel_i830_private.gtt+i);
readl(intel_i830_private.gtt+i);
}
readl(intel_i830_private.gtt+i-1);

global_cache_flush();
agp_bridge->driver->tlb_flush(mem);
return 0;
}
Expand Down

0 comments on commit 5aa80c7

Please sign in to comment.