aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/backend.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2007-10-14 20:19:16 -0400
committerDave Airlie <airlied@optimus.(none)>2007-10-14 20:32:15 -0400
commita2721e998ede079db10f65e4b42310f79dc8f135 (patch)
tree32963c9bf40f3e0871d4d549bb6c3cf13abbb24c /drivers/char/agp/backend.c
parent23fd50450a34f2558070ceabb0bfebc1c9604af5 (diff)
AGP fix race condition between unmapping and freeing pages
With Andi's clflush fixup, we were getting hangs on server exit, flushing the mappings after freeing each page helped. This showed up a race condition where the pages after being freed could be reused before the agp mappings had been flushed. Flushing after each single page is a bad thing for future drm work, so make the page destroy a two pass unmapping all the pages, flushing the mappings, and then destroying the pages. Signed-off-by: Dave Airlie <airlied@linux.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Diffstat (limited to 'drivers/char/agp/backend.c')
-rw-r--r--drivers/char/agp/backend.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 1b47c89a1b9..832ded20fe7 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -189,9 +189,11 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
189 189
190err_out: 190err_out:
191 if (bridge->driver->needs_scratch_page) { 191 if (bridge->driver->needs_scratch_page) {
192 bridge->driver->agp_destroy_page( 192 bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
193 gart_to_virt(bridge->scratch_page_real)); 193 AGP_PAGE_DESTROY_UNMAP);
194 flush_agp_mappings(); 194 flush_agp_mappings();
195 bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
196 AGP_PAGE_DESTROY_FREE);
195 } 197 }
196 if (got_gatt) 198 if (got_gatt)
197 bridge->driver->free_gatt_table(bridge); 199 bridge->driver->free_gatt_table(bridge);
@@ -215,9 +217,11 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
215 217
216 if (bridge->driver->agp_destroy_page && 218 if (bridge->driver->agp_destroy_page &&
217 bridge->driver->needs_scratch_page) { 219 bridge->driver->needs_scratch_page) {
218 bridge->driver->agp_destroy_page( 220 bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
219 gart_to_virt(bridge->scratch_page_real)); 221 AGP_PAGE_DESTROY_UNMAP);
220 flush_agp_mappings(); 222 flush_agp_mappings();
223 bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
224 AGP_PAGE_DESTROY_FREE);
221 } 225 }
222} 226}
223 227