Skip to content

Commit

Permalink
agp: two-stage page destruction issue
Browse files Browse the repository at this point in the history
besides it apparently being useful only in 2.6.24 (the changes in 2.6.25
really mean that it could be converted back to a single-stage mechanism),
I'm seeing an issue in Xen Dom0 kernels, which is caused by the calling
of gart_to_virt() in the second stage invocations of the destroy function.
I think that besides this being a real issue with Xen (where
unmap_page_from_agp() is not just a page table attribute change), this
also is invalid from a theoretical perspective: One should not assume that
gart_to_virt() is still valid after unmapping a page. So minimally (keeping
the 2-stage mechanism) a patch like the one below would be needed.

Jan

Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Jan Beulich authored and Dave Airlie committed Jun 18, 2008
1 parent dcd981a commit da503fa
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 12 deletions.
16 changes: 8 additions & 8 deletions drivers/char/agp/backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)

err_out:
if (bridge->driver->needs_scratch_page) {
bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
AGP_PAGE_DESTROY_UNMAP);
bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
AGP_PAGE_DESTROY_FREE);
void *va = gart_to_virt(bridge->scratch_page_real);

bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
}
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
Expand All @@ -215,10 +215,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)

if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page) {
bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
AGP_PAGE_DESTROY_UNMAP);
bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
AGP_PAGE_DESTROY_FREE);
void *va = gart_to_virt(bridge->scratch_page_real);

bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
}
}

Expand Down
7 changes: 5 additions & 2 deletions drivers/char/agp/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,13 @@ void agp_free_memory(struct agp_memory *curr)
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP);
curr->memory[i] = (unsigned long)gart_to_virt(curr->memory[i]);
curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
AGP_PAGE_DESTROY_UNMAP);
}
for (i = 0; i < curr->page_count; i++) {
curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE);
curr->bridge->driver->agp_destroy_page((void *)curr->memory[i],
AGP_PAGE_DESTROY_FREE);
}
}
agp_free_key(curr->key);
Expand Down
6 changes: 4 additions & 2 deletions drivers/char/agp/intel-agp.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
if (curr->page_count == 4)
i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
else {
agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
void *va = gart_to_virt(curr->memory[0]);

agp_bridge->driver->agp_destroy_page(va,
AGP_PAGE_DESTROY_UNMAP);
agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
agp_bridge->driver->agp_destroy_page(va,
AGP_PAGE_DESTROY_FREE);
}
agp_free_page_array(curr);
Expand Down

0 comments on commit da503fa

Please sign in to comment.