diff options
Diffstat (limited to 'drivers/char/agp/generic.c')
| -rw-r--r-- | drivers/char/agp/generic.c | 69 |
1 files changed, 28 insertions, 41 deletions
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 2224b762b7fb..1e8b461b91f1 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
| @@ -95,13 +95,13 @@ EXPORT_SYMBOL(agp_flush_chipset); | |||
| 95 | 95 | ||
| 96 | void agp_alloc_page_array(size_t size, struct agp_memory *mem) | 96 | void agp_alloc_page_array(size_t size, struct agp_memory *mem) |
| 97 | { | 97 | { |
| 98 | mem->memory = NULL; | 98 | mem->pages = NULL; |
| 99 | mem->vmalloc_flag = false; | 99 | mem->vmalloc_flag = false; |
| 100 | 100 | ||
| 101 | if (size <= 2*PAGE_SIZE) | 101 | if (size <= 2*PAGE_SIZE) |
| 102 | mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY); | 102 | mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NORETRY); |
| 103 | if (mem->memory == NULL) { | 103 | if (mem->pages == NULL) { |
| 104 | mem->memory = vmalloc(size); | 104 | mem->pages = vmalloc(size); |
| 105 | mem->vmalloc_flag = true; | 105 | mem->vmalloc_flag = true; |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| @@ -110,9 +110,9 @@ EXPORT_SYMBOL(agp_alloc_page_array); | |||
| 110 | void agp_free_page_array(struct agp_memory *mem) | 110 | void agp_free_page_array(struct agp_memory *mem) |
| 111 | { | 111 | { |
| 112 | if (mem->vmalloc_flag) { | 112 | if (mem->vmalloc_flag) { |
| 113 | vfree(mem->memory); | 113 | vfree(mem->pages); |
| 114 | } else { | 114 | } else { |
| 115 | kfree(mem->memory); | 115 | kfree(mem->pages); |
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | EXPORT_SYMBOL(agp_free_page_array); | 118 | EXPORT_SYMBOL(agp_free_page_array); |
| @@ -136,7 +136,7 @@ static struct agp_memory *agp_create_user_memory(unsigned long num_agp_pages) | |||
| 136 | 136 | ||
| 137 | agp_alloc_page_array(alloc_size, new); | 137 | agp_alloc_page_array(alloc_size, new); |
| 138 | 138 | ||
| 139 | if (new->memory == NULL) { | 139 | if (new->pages == NULL) { |
| 140 | agp_free_key(new->key); | 140 | agp_free_key(new->key); |
| 141 | kfree(new); | 141 | kfree(new); |
| 142 | return NULL; | 142 | return NULL; |
| @@ -162,7 +162,7 @@ struct agp_memory *agp_create_memory(int scratch_pages) | |||
| 162 | 162 | ||
| 163 | agp_alloc_page_array(PAGE_SIZE * scratch_pages, new); | 163 | agp_alloc_page_array(PAGE_SIZE * scratch_pages, new); |
| 164 | 164 | ||
| 165 | if (new->memory == NULL) { | 165 | if (new->pages == NULL) { |
| 166 | agp_free_key(new->key); | 166 | agp_free_key(new->key); |
| 167 | kfree(new); | 167 | kfree(new); |
| 168 | return NULL; | 168 | return NULL; |
| @@ -206,15 +206,13 @@ void agp_free_memory(struct agp_memory *curr) | |||
| 206 | } else { | 206 | } else { |
| 207 | 207 | ||
| 208 | for (i = 0; i < curr->page_count; i++) { | 208 | for (i = 0; i < curr->page_count; i++) { |
| 209 | curr->memory[i] = (unsigned long)gart_to_virt( | ||
| 210 | curr->memory[i]); | ||
| 211 | curr->bridge->driver->agp_destroy_page( | 209 | curr->bridge->driver->agp_destroy_page( |
| 212 | (void *)curr->memory[i], | 210 | curr->pages[i], |
| 213 | AGP_PAGE_DESTROY_UNMAP); | 211 | AGP_PAGE_DESTROY_UNMAP); |
| 214 | } | 212 | } |
| 215 | for (i = 0; i < curr->page_count; i++) { | 213 | for (i = 0; i < curr->page_count; i++) { |
| 216 | curr->bridge->driver->agp_destroy_page( | 214 | curr->bridge->driver->agp_destroy_page( |
| 217 | (void *)curr->memory[i], | 215 | curr->pages[i], |
| 218 | AGP_PAGE_DESTROY_FREE); | 216 | AGP_PAGE_DESTROY_FREE); |
| 219 | } | 217 | } |
| 220 | } | 218 | } |
| @@ -282,13 +280,13 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, | |||
| 282 | } | 280 | } |
| 283 | 281 | ||
| 284 | for (i = 0; i < page_count; i++) { | 282 | for (i = 0; i < page_count; i++) { |
| 285 | void *addr = bridge->driver->agp_alloc_page(bridge); | 283 | struct page *page = bridge->driver->agp_alloc_page(bridge); |
| 286 | 284 | ||
| 287 | if (addr == NULL) { | 285 | if (page == NULL) { |
| 288 | agp_free_memory(new); | 286 | agp_free_memory(new); |
| 289 | return NULL; | 287 | return NULL; |
| 290 | } | 288 | } |
| 291 | new->memory[i] = virt_to_gart(addr); | 289 | new->pages[i] = page; |
| 292 | new->page_count++; | 290 | new->page_count++; |
| 293 | } | 291 | } |
| 294 | new->bridge = bridge; | 292 | new->bridge = bridge; |
| @@ -1134,7 +1132,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
| 1134 | } | 1132 | } |
| 1135 | 1133 | ||
| 1136 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 1134 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
| 1137 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type), | 1135 | writel(bridge->driver->mask_memory(bridge, mem->pages[i], mask_type), |
| 1138 | bridge->gatt_table+j); | 1136 | bridge->gatt_table+j); |
| 1139 | } | 1137 | } |
| 1140 | readl(bridge->gatt_table+j-1); /* PCI Posting. */ | 1138 | readl(bridge->gatt_table+j-1); /* PCI Posting. */ |
| @@ -1204,7 +1202,7 @@ struct agp_memory *agp_generic_alloc_user(size_t page_count, int type) | |||
| 1204 | return NULL; | 1202 | return NULL; |
| 1205 | 1203 | ||
| 1206 | for (i = 0; i < page_count; i++) | 1204 | for (i = 0; i < page_count; i++) |
| 1207 | new->memory[i] = 0; | 1205 | new->pages[i] = 0; |
| 1208 | new->page_count = 0; | 1206 | new->page_count = 0; |
| 1209 | new->type = type; | 1207 | new->type = type; |
| 1210 | new->num_scratch_pages = pages; | 1208 | new->num_scratch_pages = pages; |
| @@ -1237,23 +1235,20 @@ int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *m | |||
| 1237 | get_page(page); | 1235 | get_page(page); |
| 1238 | atomic_inc(&agp_bridge->current_memory_agp); | 1236 | atomic_inc(&agp_bridge->current_memory_agp); |
| 1239 | 1237 | ||
| 1240 | /* set_memory_array_uc() needs virtual address */ | 1238 | mem->pages[i] = page; |
| 1241 | mem->memory[i] = (unsigned long)page_address(page); | ||
| 1242 | mem->page_count++; | 1239 | mem->page_count++; |
| 1243 | } | 1240 | } |
| 1244 | 1241 | ||
| 1245 | #ifdef CONFIG_X86 | 1242 | #ifdef CONFIG_X86 |
| 1246 | set_memory_array_uc(mem->memory, num_pages); | 1243 | set_pages_array_uc(mem->pages, num_pages); |
| 1247 | #endif | 1244 | #endif |
| 1248 | ret = 0; | 1245 | ret = 0; |
| 1249 | out: | 1246 | out: |
| 1250 | for (i = 0; i < mem->page_count; i++) | ||
| 1251 | mem->memory[i] = virt_to_gart((void *)mem->memory[i]); | ||
| 1252 | return ret; | 1247 | return ret; |
| 1253 | } | 1248 | } |
| 1254 | EXPORT_SYMBOL(agp_generic_alloc_pages); | 1249 | EXPORT_SYMBOL(agp_generic_alloc_pages); |
| 1255 | 1250 | ||
| 1256 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | 1251 | struct page *agp_generic_alloc_page(struct agp_bridge_data *bridge) |
| 1257 | { | 1252 | { |
| 1258 | struct page * page; | 1253 | struct page * page; |
| 1259 | 1254 | ||
| @@ -1265,56 +1260,47 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | |||
| 1265 | 1260 | ||
| 1266 | get_page(page); | 1261 | get_page(page); |
| 1267 | atomic_inc(&agp_bridge->current_memory_agp); | 1262 | atomic_inc(&agp_bridge->current_memory_agp); |
| 1268 | return page_address(page); | 1263 | return page; |
| 1269 | } | 1264 | } |
| 1270 | EXPORT_SYMBOL(agp_generic_alloc_page); | 1265 | EXPORT_SYMBOL(agp_generic_alloc_page); |
| 1271 | 1266 | ||
| 1272 | void agp_generic_destroy_pages(struct agp_memory *mem) | 1267 | void agp_generic_destroy_pages(struct agp_memory *mem) |
| 1273 | { | 1268 | { |
| 1274 | int i; | 1269 | int i; |
| 1275 | void *addr; | ||
| 1276 | struct page *page; | 1270 | struct page *page; |
| 1277 | 1271 | ||
| 1278 | if (!mem) | 1272 | if (!mem) |
| 1279 | return; | 1273 | return; |
| 1280 | 1274 | ||
| 1281 | for (i = 0; i < mem->page_count; i++) | ||
| 1282 | mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]); | ||
| 1283 | |||
| 1284 | #ifdef CONFIG_X86 | 1275 | #ifdef CONFIG_X86 |
| 1285 | set_memory_array_wb(mem->memory, mem->page_count); | 1276 | set_pages_array_wb(mem->pages, mem->page_count); |
| 1286 | #endif | 1277 | #endif |
| 1287 | 1278 | ||
| 1288 | for (i = 0; i < mem->page_count; i++) { | 1279 | for (i = 0; i < mem->page_count; i++) { |
| 1289 | addr = (void *)mem->memory[i]; | 1280 | page = mem->pages[i]; |
| 1290 | page = virt_to_page(addr); | ||
| 1291 | 1281 | ||
| 1292 | #ifndef CONFIG_X86 | 1282 | #ifndef CONFIG_X86 |
| 1293 | unmap_page_from_agp(page); | 1283 | unmap_page_from_agp(page); |
| 1294 | #endif | 1284 | #endif |
| 1295 | |||
| 1296 | put_page(page); | 1285 | put_page(page); |
| 1297 | free_page((unsigned long)addr); | 1286 | __free_page(page); |
| 1298 | atomic_dec(&agp_bridge->current_memory_agp); | 1287 | atomic_dec(&agp_bridge->current_memory_agp); |
| 1299 | mem->memory[i] = 0; | 1288 | mem->pages[i] = NULL; |
| 1300 | } | 1289 | } |
| 1301 | } | 1290 | } |
| 1302 | EXPORT_SYMBOL(agp_generic_destroy_pages); | 1291 | EXPORT_SYMBOL(agp_generic_destroy_pages); |
| 1303 | 1292 | ||
| 1304 | void agp_generic_destroy_page(void *addr, int flags) | 1293 | void agp_generic_destroy_page(struct page *page, int flags) |
| 1305 | { | 1294 | { |
| 1306 | struct page *page; | 1295 | if (page == NULL) |
| 1307 | |||
| 1308 | if (addr == NULL) | ||
| 1309 | return; | 1296 | return; |
| 1310 | 1297 | ||
| 1311 | page = virt_to_page(addr); | ||
| 1312 | if (flags & AGP_PAGE_DESTROY_UNMAP) | 1298 | if (flags & AGP_PAGE_DESTROY_UNMAP) |
| 1313 | unmap_page_from_agp(page); | 1299 | unmap_page_from_agp(page); |
| 1314 | 1300 | ||
| 1315 | if (flags & AGP_PAGE_DESTROY_FREE) { | 1301 | if (flags & AGP_PAGE_DESTROY_FREE) { |
| 1316 | put_page(page); | 1302 | put_page(page); |
| 1317 | free_page((unsigned long)addr); | 1303 | __free_page(page); |
| 1318 | atomic_dec(&agp_bridge->current_memory_agp); | 1304 | atomic_dec(&agp_bridge->current_memory_agp); |
| 1319 | } | 1305 | } |
| 1320 | } | 1306 | } |
| @@ -1361,8 +1347,9 @@ void global_cache_flush(void) | |||
| 1361 | EXPORT_SYMBOL(global_cache_flush); | 1347 | EXPORT_SYMBOL(global_cache_flush); |
| 1362 | 1348 | ||
| 1363 | unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, | 1349 | unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, |
| 1364 | unsigned long addr, int type) | 1350 | struct page *page, int type) |
| 1365 | { | 1351 | { |
| 1352 | unsigned long addr = phys_to_gart(page_to_phys(page)); | ||
| 1366 | /* memory type is ignored in the generic routine */ | 1353 | /* memory type is ignored in the generic routine */ |
| 1367 | if (bridge->driver->masks) | 1354 | if (bridge->driver->masks) |
| 1368 | return addr | bridge->driver->masks[0].mask; | 1355 | return addr | bridge->driver->masks[0].mask; |
