aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyu.z.wang@intel.com>2009-07-23 12:25:49 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-08-03 04:04:47 -0400
commitff663cf8705bea101d5f73cf471855c85242575e (patch)
tree4b338298e69d2401cab848b4b9082bef07e5d9aa /drivers/char
parent2a4ceb6d3e6a566cb4a9dc8f974177f031d27cd7 (diff)
agp: Add generic support for graphics dma remapping
New driver hooks for support graphics memory dma remapping are introduced in this patch. It makes generic code can tell if current device needs dma remapping, then call driver provided interfaces for mapping and unmapping. Change has also been made to handle scratch_page in remapping case. Signed-off-by: Zhenyu Wang <zhenyu.z.wang@intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/agp/agp.h6
-rw-r--r--drivers/char/agp/backend.c20
-rw-r--r--drivers/char/agp/generic.c9
3 files changed, 35 insertions, 0 deletions
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ce110a3bf298..17e6d0d3ba36 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -121,6 +121,11 @@ struct agp_bridge_driver {
121 void (*agp_destroy_pages)(struct agp_memory *); 121 void (*agp_destroy_pages)(struct agp_memory *);
122 int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); 122 int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
123 void (*chipset_flush)(struct agp_bridge_data *); 123 void (*chipset_flush)(struct agp_bridge_data *);
124
125 int (*agp_map_page)(void *addr, dma_addr_t *ret);
126 void (*agp_unmap_page)(void *addr, dma_addr_t dma);
127 int (*agp_map_memory)(struct agp_memory *mem);
128 void (*agp_unmap_memory)(struct agp_memory *mem);
124}; 129};
125 130
126struct agp_bridge_data { 131struct agp_bridge_data {
@@ -135,6 +140,7 @@ struct agp_bridge_data {
135 u32 *gatt_table_real; 140 u32 *gatt_table_real;
136 unsigned long scratch_page; 141 unsigned long scratch_page;
137 unsigned long scratch_page_real; 142 unsigned long scratch_page_real;
143 dma_addr_t scratch_page_dma;
138 unsigned long gart_bus_addr; 144 unsigned long gart_bus_addr;
139 unsigned long gatt_bus_addr; 145 unsigned long gatt_bus_addr;
140 u32 mode; 146 u32 mode;
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 3bd7e503de41..19ac3663acdc 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -152,6 +152,15 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
152 bridge->scratch_page_real = phys_to_gart(page_to_phys(page)); 152 bridge->scratch_page_real = phys_to_gart(page_to_phys(page));
153 bridge->scratch_page = bridge->driver->mask_memory(bridge, 153 bridge->scratch_page = bridge->driver->mask_memory(bridge,
154 phys_to_gart(page_to_phys(page)), 0); 154 phys_to_gart(page_to_phys(page)), 0);
155
156 if (bridge->driver->agp_map_page &&
157 bridge->driver->agp_map_page(phys_to_virt(page_to_phys(page)),
158 &bridge->scratch_page_dma)) {
159 dev_err(&bridge->dev->dev,
160 "unable to dma-map scratch page\n");
161 rc = -ENOMEM;
162 goto err_out_nounmap;
163 }
155 } 164 }
156 165
157 size_value = bridge->driver->fetch_size(); 166 size_value = bridge->driver->fetch_size();
@@ -191,6 +200,13 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
191 return 0; 200 return 0;
192 201
193err_out: 202err_out:
203 if (bridge->driver->needs_scratch_page &&
204 bridge->driver->agp_unmap_page) {
205 void *va = gart_to_virt(bridge->scratch_page_real);
206
207 bridge->driver->agp_unmap_page(va, bridge->scratch_page_dma);
208 }
209err_out_nounmap:
194 if (bridge->driver->needs_scratch_page) { 210 if (bridge->driver->needs_scratch_page) {
195 void *va = gart_to_virt(bridge->scratch_page_real); 211 void *va = gart_to_virt(bridge->scratch_page_real);
196 212
@@ -221,6 +237,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
221 bridge->driver->needs_scratch_page) { 237 bridge->driver->needs_scratch_page) {
222 void *va = gart_to_virt(bridge->scratch_page_real); 238 void *va = gart_to_virt(bridge->scratch_page_real);
223 239
240 if (bridge->driver->agp_unmap_page)
241 bridge->driver->agp_unmap_page(va,
242 bridge->scratch_page_dma);
243
224 bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); 244 bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
225 bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); 245 bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
226 } 246 }
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index a3bcc7ef42f9..28f0208c66a6 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -437,6 +437,12 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
437 curr->bridge->driver->cache_flush(); 437 curr->bridge->driver->cache_flush();
438 curr->is_flushed = true; 438 curr->is_flushed = true;
439 } 439 }
440
441 if (curr->bridge->driver->agp_map_memory) {
442 ret_val = curr->bridge->driver->agp_map_memory(curr);
443 if (ret_val)
444 return ret_val;
445 }
440 ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type); 446 ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
441 447
442 if (ret_val != 0) 448 if (ret_val != 0)
@@ -478,6 +484,9 @@ int agp_unbind_memory(struct agp_memory *curr)
478 if (ret_val != 0) 484 if (ret_val != 0)
479 return ret_val; 485 return ret_val;
480 486
487 if (curr->bridge->driver->agp_unmap_memory)
488 curr->bridge->driver->agp_unmap_memory(curr);
489
481 curr->is_bound = false; 490 curr->is_bound = false;
482 curr->pg_start = 0; 491 curr->pg_start = 0;
483 spin_lock(&curr->bridge->mapped_lock); 492 spin_lock(&curr->bridge->mapped_lock);