AGP force use of scratch page
Hi, Attached is a patch which force the use of the scratch page for all AGP bridges, only tested on SIS or Intel bridges, i am bit skeptical for alpha bridges. If you prefer i can just force this for x86 PPC bridge for which we can easily get tester. Cheers, Jerome From 5b2469a7149280fb6866345cb6d3d395ee400cd8 Mon Sep 17 00:00:00 2001 From: Jerome Glisse jgli...@redhat.com Date: Thu, 1 Apr 2010 16:46:15 +0200 Subject: [PATCH] agp: force use of scratch page It seems that some AGP hardware can induce activity on bus after reporting being idle with the memory (preteching maybe). As new infrastructure for GPU is dynamicly binding/unbinding memory this result in hardware possibly trying to access invalid memory to avoid this situation the patch for the use of the scratch page mecanism for all the AGP driver. It remove the needs_scratch_page flags and fix the insert_memory/remove_memory to deal properly with scratch_page. Been tested on intel sis agp bridges. Signed-off-by: Jerome Glisse jgli...@redhat.com --- drivers/char/agp/agp.h |1 - drivers/char/agp/backend.c | 57 +- drivers/char/agp/hp-agp.c |2 +- drivers/char/agp/i460-agp.c |2 +- drivers/char/agp/intel-agp.c| 30 +++- drivers/char/agp/parisc-agp.c |2 +- drivers/char/agp/sgi-agp.c |5 +-- drivers/char/agp/uninorth-agp.c |3 +- 8 files changed, 42 insertions(+), 60 deletions(-) diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 870f12c..db68c7b 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -100,7 +100,6 @@ struct agp_bridge_driver { int num_aperture_sizes; enum aper_size_type size_type; bool cant_use_aperture; - bool needs_scratch_page; const struct gatt_mask *masks; int (*fetch_size)(void); int (*configure)(void); diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index c3ab46d..fed5e46 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -136,35 +136,32 @@ static int agp_find_max(void) static int agp_backend_initialize(struct agp_bridge_data *bridge) { int size_value, rc, got_gatt=0, got_keylist=0; + struct page *page; + void *va; bridge-max_memory_agp = agp_find_max(); bridge-version = agp_current_version; - if (bridge-driver-needs_scratch_page) { - struct page *page = bridge-driver-agp_alloc_page(bridge); - - if (!page) { - dev_err(bridge-dev-dev, + page = bridge-driver-agp_alloc_page(bridge); + if (!page) { + dev_err(bridge-dev-dev, can't get memory for scratch page\n); - return -ENOMEM; - } - - bridge-scratch_page_page = page; - if (bridge-driver-agp_map_page) { - if (bridge-driver-agp_map_page(page, - bridge-scratch_page_dma)) { - dev_err(bridge-dev-dev, + return -ENOMEM; + } + bridge-scratch_page_page = page; + if (bridge-driver-agp_map_page) { + if (bridge-driver-agp_map_page(page, + bridge-scratch_page_dma)) { + dev_err(bridge-dev-dev, unable to dma-map scratch page\n); - rc = -ENOMEM; - goto err_out_nounmap; - } - } else { - bridge-scratch_page_dma = page_to_phys(page); + rc = -ENOMEM; + goto err_out_nounmap; } - - bridge-scratch_page = bridge-driver-mask_memory(bridge, - bridge-scratch_page_dma, 0); + } else { + bridge-scratch_page_dma = page_to_phys(page); } + bridge-scratch_page = bridge-driver-mask_memory(bridge, + bridge-scratch_page_dma, 0); size_value = bridge-driver-fetch_size(); if (size_value == 0) { @@ -203,18 +200,15 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return 0; err_out: - if (bridge-driver-needs_scratch_page - bridge-driver-agp_unmap_page) { + if (bridge-driver-agp_unmap_page) { bridge-driver-agp_unmap_page(bridge-scratch_page_page, bridge-scratch_page_dma); } err_out_nounmap: - if (bridge-driver-needs_scratch_page) { - void *va = page_address(bridge-scratch_page_page); + va = page_address(bridge-scratch_page_page); + bridge-driver-agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); + bridge-driver-agp_destroy_page(va
Re: AGP force use of scratch page
On Thu, 2010-04-01 at 16:54 +0200, Jerome Glisse wrote: From: Jerome Glisse jgli...@redhat.com Date: Thu, 1 Apr 2010 16:46:15 +0200 Subject: [PATCH] agp: force use of scratch page It seems that some AGP hardware can induce activity on bus after reporting being idle with the memory (preteching maybe). As new infrastructure for GPU is dynamicly binding/unbinding memory this result in hardware possibly trying to access invalid memory to avoid this situation the patch for the use of the scratch page mecanism for all the AGP driver. It remove the needs_scratch_page flags and fix the insert_memory/remove_memory to deal properly with scratch_page. Been tested on intel sis agp bridges. Signed-off-by: Jerome Glisse jgli...@redhat.com Please don't attach patches but use git send-email or so for easier review. diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index c3ab46d..fed5e46 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -136,35 +136,32 @@ static int agp_find_max(void) static int agp_backend_initialize(struct agp_bridge_data *bridge) { int size_value, rc, got_gatt=0, got_keylist=0; + struct page *page; + void *va; bridge-max_memory_agp = agp_find_max(); bridge-version = agp_current_version; - if (bridge-driver-needs_scratch_page) { - struct page *page = bridge-driver-agp_alloc_page(bridge); - - if (!page) { - dev_err(bridge-dev-dev, + page = bridge-driver-agp_alloc_page(bridge); + if (!page) { + dev_err(bridge-dev-dev, can't get memory for scratch page\n); - return -ENOMEM; - } - - bridge-scratch_page_page = page; - if (bridge-driver-agp_map_page) { - if (bridge-driver-agp_map_page(page, - bridge-scratch_page_dma)) { - dev_err(bridge-dev-dev, + return -ENOMEM; + } + bridge-scratch_page_page = page; + if (bridge-driver-agp_map_page) { + if (bridge-driver-agp_map_page(page, + bridge-scratch_page_dma)) { + dev_err(bridge-dev-dev, unable to dma-map scratch page\n); - rc = -ENOMEM; - goto err_out_nounmap; - } - } else { - bridge-scratch_page_dma = page_to_phys(page); + rc = -ENOMEM; + goto err_out_nounmap; } - - bridge-scratch_page = bridge-driver-mask_memory(bridge, -bridge-scratch_page_dma, 0); + } else { + bridge-scratch_page_dma = page_to_phys(page); } + bridge-scratch_page = bridge-driver-mask_memory(bridge, + bridge-scratch_page_dma, 0); size_value = bridge-driver-fetch_size(); if (size_value == 0) { @@ -203,18 +200,15 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) return 0; err_out: - if (bridge-driver-needs_scratch_page - bridge-driver-agp_unmap_page) { + if (bridge-driver-agp_unmap_page) { bridge-driver-agp_unmap_page(bridge-scratch_page_page, bridge-scratch_page_dma); } err_out_nounmap: - if (bridge-driver-needs_scratch_page) { - void *va = page_address(bridge-scratch_page_page); + va = page_address(bridge-scratch_page_page); + bridge-driver-agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); + bridge-driver-agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); - 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); if (got_keylist) { @@ -227,6 +221,8 @@ err_out_nounmap: /* cannot be __exit b/c as it could be called from __init code */ static void agp_backend_cleanup(struct agp_bridge_data *bridge) { + void *va; + if (bridge-driver-cleanup) bridge-driver-cleanup(); if (bridge-driver-free_gatt_table) @@ -235,9 +231,8 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) vfree(bridge-key_list); bridge-key_list = NULL; - if (bridge-driver-agp_destroy_page - bridge-driver-needs_scratch_page) { - void *va = page_address(bridge-scratch_page_page); + if (bridge-driver-agp_destroy_page) { + va = page_address(bridge-scratch_page_page); if (bridge-driver-agp_unmap_page) bridge-driver-agp_unmap_page(bridge