aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/generic.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-06-12 00:11:41 -0400
committerDave Airlie <airlied@redhat.com>2009-06-18 20:21:42 -0400
commit07613ba2f464f59949266f4337b75b91eb610795 (patch)
tree8e43a82571686492aba2269c2e7a49c323783af1 /drivers/char/agp/generic.c
parent2908826d045a89805714e0a3055a99dc40565d41 (diff)
agp: switch AGP to use page array instead of unsigned long array
This switches AGP to use an array of pages for tracking the pages allocated to the GART. This should enable GEM on PAE to work a lot better as we can pass highmem pages to the PAT code and it will do the right thing with them. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/char/agp/generic.c')
-rw-r--r--drivers/char/agp/generic.c69
1 files changed, 28 insertions, 41 deletions
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 2224b762b7f..1e8b461b91f 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -95,13 +95,13 @@ EXPORT_SYMBOL(agp_flush_chipset);
95 95
96void agp_alloc_page_array(size_t size, struct agp_memory *mem) 96void 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);
110void agp_free_page_array(struct agp_memory *mem) 110void 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}
118EXPORT_SYMBOL(agp_free_page_array); 118EXPORT_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;
1249out: 1246out:
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}
1254EXPORT_SYMBOL(agp_generic_alloc_pages); 1249EXPORT_SYMBOL(agp_generic_alloc_pages);
1255 1250
1256void *agp_generic_alloc_page(struct agp_bridge_data *bridge) 1251struct 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}
1270EXPORT_SYMBOL(agp_generic_alloc_page); 1265EXPORT_SYMBOL(agp_generic_alloc_page);
1271 1266
1272void agp_generic_destroy_pages(struct agp_memory *mem) 1267void 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}
1302EXPORT_SYMBOL(agp_generic_destroy_pages); 1291EXPORT_SYMBOL(agp_generic_destroy_pages);
1303 1292
1304void agp_generic_destroy_page(void *addr, int flags) 1293void 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)
1361EXPORT_SYMBOL(global_cache_flush); 1347EXPORT_SYMBOL(global_cache_flush);
1362 1348
1363unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge, 1349unsigned 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;