AGP force use of scratch page

2010-04-01 Thread Jerome Glisse
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

2010-04-01 Thread Michel Dänzer
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