diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/agp.h | 6 | ||||
-rw-r--r-- | drivers/char/agp/backend.c | 20 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 9 |
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 | ||
126 | struct agp_bridge_data { | 131 | struct 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 | ||
193 | err_out: | 202 | err_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 | } | ||
209 | err_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); |