Commit ff663cf8 authored by Zhenyu Wang's avatar Zhenyu Wang Committed by David Woodhouse

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: default avatarZhenyu Wang <zhenyu.z.wang@intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 2a4ceb6d
...@@ -121,6 +121,11 @@ struct agp_bridge_driver { ...@@ -121,6 +121,11 @@ struct agp_bridge_driver {
void (*agp_destroy_pages)(struct agp_memory *); void (*agp_destroy_pages)(struct agp_memory *);
int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
void (*chipset_flush)(struct agp_bridge_data *); 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 { struct agp_bridge_data {
...@@ -135,6 +140,7 @@ struct agp_bridge_data { ...@@ -135,6 +140,7 @@ struct agp_bridge_data {
u32 *gatt_table_real; u32 *gatt_table_real;
unsigned long scratch_page; unsigned long scratch_page;
unsigned long scratch_page_real; unsigned long scratch_page_real;
dma_addr_t scratch_page_dma;
unsigned long gart_bus_addr; unsigned long gart_bus_addr;
unsigned long gatt_bus_addr; unsigned long gatt_bus_addr;
u32 mode; u32 mode;
......
...@@ -152,6 +152,15 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -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_real = phys_to_gart(page_to_phys(page));
bridge->scratch_page = bridge->driver->mask_memory(bridge, bridge->scratch_page = bridge->driver->mask_memory(bridge,
phys_to_gart(page_to_phys(page)), 0); 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(); size_value = bridge->driver->fetch_size();
...@@ -191,6 +200,13 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) ...@@ -191,6 +200,13 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
return 0; return 0;
err_out: 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) { if (bridge->driver->needs_scratch_page) {
void *va = gart_to_virt(bridge->scratch_page_real); void *va = gart_to_virt(bridge->scratch_page_real);
...@@ -221,6 +237,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) ...@@ -221,6 +237,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
bridge->driver->needs_scratch_page) { bridge->driver->needs_scratch_page) {
void *va = gart_to_virt(bridge->scratch_page_real); 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_UNMAP);
bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
} }
......
...@@ -437,6 +437,12 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) ...@@ -437,6 +437,12 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start)
curr->bridge->driver->cache_flush(); curr->bridge->driver->cache_flush();
curr->is_flushed = true; 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); ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
if (ret_val != 0) if (ret_val != 0)
...@@ -478,6 +484,9 @@ int agp_unbind_memory(struct agp_memory *curr) ...@@ -478,6 +484,9 @@ int agp_unbind_memory(struct agp_memory *curr)
if (ret_val != 0) if (ret_val != 0)
return ret_val; return ret_val;
if (curr->bridge->driver->agp_unmap_memory)
curr->bridge->driver->agp_unmap_memory(curr);
curr->is_bound = false; curr->is_bound = false;
curr->pg_start = 0; curr->pg_start = 0;
spin_lock(&curr->bridge->mapped_lock); spin_lock(&curr->bridge->mapped_lock);
......
...@@ -79,9 +79,13 @@ struct agp_memory { ...@@ -79,9 +79,13 @@ struct agp_memory {
u32 physical; u32 physical;
bool is_bound; bool is_bound;
bool is_flushed; bool is_flushed;
bool vmalloc_flag; bool vmalloc_flag;
bool sg_vmalloc_flag;
/* list of agp_memory mapped to the aperture */ /* list of agp_memory mapped to the aperture */
struct list_head mapped_list; struct list_head mapped_list;
/* DMA-mapped addresses */
struct scatterlist *sg_list;
int num_sg;
}; };
#define AGP_NORMAL_MEMORY 0 #define AGP_NORMAL_MEMORY 0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment