summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyu.z.wang@intel.com>2009-07-23 17:25:49 +0100
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-08-03 09:04:47 +0100
commitff663cf8705bea101d5f73cf471855c85242575e (patch)
tree4b338298e69d2401cab848b4b9082bef07e5d9aa /drivers/char
parent2a4ceb6d3e6a566cb4a9dc8f974177f031d27cd7 (diff)
downloadlinux-3.10-ff663cf8705bea101d5f73cf471855c85242575e.tar.gz
linux-3.10-ff663cf8705bea101d5f73cf471855c85242575e.tar.bz2
linux-3.10-ff663cf8705bea101d5f73cf471855c85242575e.zip
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 ce110a3bf29..17e6d0d3ba3 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -121,6 +121,11 @@ struct agp_bridge_driver {
void (*agp_destroy_pages)(struct agp_memory *);
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
void (*chipset_flush)(struct agp_bridge_data *);
+
+ int (*agp_map_page)(void *addr, dma_addr_t *ret);
+ void (*agp_unmap_page)(void *addr, dma_addr_t dma);
+ int (*agp_map_memory)(struct agp_memory *mem);
+ void (*agp_unmap_memory)(struct agp_memory *mem);
};
struct agp_bridge_data {
@@ -135,6 +140,7 @@ struct agp_bridge_data {
u32 *gatt_table_real;
unsigned long scratch_page;
unsigned long scratch_page_real;
+ dma_addr_t scratch_page_dma;
unsigned long gart_bus_addr;
unsigned long gatt_bus_addr;
u32 mode;
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 3bd7e503de4..19ac3663acd 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)
bridge->scratch_page_real = phys_to_gart(page_to_phys(page));
bridge->scratch_page = bridge->driver->mask_memory(bridge,
phys_to_gart(page_to_phys(page)), 0);
+
+ if (bridge->driver->agp_map_page &&
+ bridge->driver->agp_map_page(phys_to_virt(page_to_phys(page)),
+ &bridge->scratch_page_dma)) {
+ dev_err(&bridge->dev->dev,
+ "unable to dma-map scratch page\n");
+ rc = -ENOMEM;
+ goto err_out_nounmap;
+ }
}
size_value = bridge->driver->fetch_size();
@@ -191,6 +200,13 @@ 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) {
+ void *va = gart_to_virt(bridge->scratch_page_real);
+
+ bridge->driver->agp_unmap_page(va, bridge->scratch_page_dma);
+ }
+err_out_nounmap:
if (bridge->driver->needs_scratch_page) {
void *va = gart_to_virt(bridge->scratch_page_real);
@@ -221,6 +237,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
bridge->driver->needs_scratch_page) {
void *va = gart_to_virt(bridge->scratch_page_real);
+ if (bridge->driver->agp_unmap_page)
+ bridge->driver->agp_unmap_page(va,
+ bridge->scratch_page_dma);
+
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
}
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index a3bcc7ef42f..28f0208c66a 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)
curr->bridge->driver->cache_flush();
curr->is_flushed = true;
}
+
+ if (curr->bridge->driver->agp_map_memory) {
+ ret_val = curr->bridge->driver->agp_map_memory(curr);
+ if (ret_val)
+ return ret_val;
+ }
ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0)
@@ -478,6 +484,9 @@ int agp_unbind_memory(struct agp_memory *curr)
if (ret_val != 0)
return ret_val;
+ if (curr->bridge->driver->agp_unmap_memory)
+ curr->bridge->driver->agp_unmap_memory(curr);
+
curr->is_bound = false;
curr->pg_start = 0;
spin_lock(&curr->bridge->mapped_lock);