aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/agp/intel-agp.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/intel-agp.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/intel-agp.c')
-rw-r--r--drivers/char/agp/intel-agp.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 7a748fa0dfce..35977bfb6999 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -257,7 +257,7 @@ static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
257} 257}
258 258
259/* Exists to support ARGB cursors */ 259/* Exists to support ARGB cursors */
260static void *i8xx_alloc_pages(void) 260static struct page *i8xx_alloc_pages(void)
261{ 261{
262 struct page *page; 262 struct page *page;
263 263
@@ -272,17 +272,14 @@ static void *i8xx_alloc_pages(void)
272 } 272 }
273 get_page(page); 273 get_page(page);
274 atomic_inc(&agp_bridge->current_memory_agp); 274 atomic_inc(&agp_bridge->current_memory_agp);
275 return page_address(page); 275 return page;
276} 276}
277 277
278static void i8xx_destroy_pages(void *addr) 278static void i8xx_destroy_pages(struct page *page)
279{ 279{
280 struct page *page; 280 if (page == NULL)
281
282 if (addr == NULL)
283 return; 281 return;
284 282
285 page = virt_to_page(addr);
286 set_pages_wb(page, 4); 283 set_pages_wb(page, 4);
287 put_page(page); 284 put_page(page);
288 __free_pages(page, 2); 285 __free_pages(page, 2);
@@ -346,7 +343,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
346 global_cache_flush(); 343 global_cache_flush();
347 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 344 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
348 writel(agp_bridge->driver->mask_memory(agp_bridge, 345 writel(agp_bridge->driver->mask_memory(agp_bridge,
349 mem->memory[i], 346 mem->pages[i],
350 mask_type), 347 mask_type),
351 intel_private.registers+I810_PTE_BASE+(j*4)); 348 intel_private.registers+I810_PTE_BASE+(j*4));
352 } 349 }
@@ -389,37 +386,37 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start,
389static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) 386static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
390{ 387{
391 struct agp_memory *new; 388 struct agp_memory *new;
392 void *addr; 389 struct page *page;
393 390
394 switch (pg_count) { 391 switch (pg_count) {
395 case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge); 392 case 1: page = agp_bridge->driver->agp_alloc_page(agp_bridge);
396 break; 393 break;
397 case 4: 394 case 4:
398 /* kludge to get 4 physical pages for ARGB cursor */ 395 /* kludge to get 4 physical pages for ARGB cursor */
399 addr = i8xx_alloc_pages(); 396 page = i8xx_alloc_pages();
400 break; 397 break;
401 default: 398 default:
402 return NULL; 399 return NULL;
403 } 400 }
404 401
405 if (addr == NULL) 402 if (page == NULL)
406 return NULL; 403 return NULL;
407 404
408 new = agp_create_memory(pg_count); 405 new = agp_create_memory(pg_count);
409 if (new == NULL) 406 if (new == NULL)
410 return NULL; 407 return NULL;
411 408
412 new->memory[0] = virt_to_gart(addr); 409 new->pages[0] = page;
413 if (pg_count == 4) { 410 if (pg_count == 4) {
414 /* kludge to get 4 physical pages for ARGB cursor */ 411 /* kludge to get 4 physical pages for ARGB cursor */
415 new->memory[1] = new->memory[0] + PAGE_SIZE; 412 new->pages[1] = new->pages[0] + 1;
416 new->memory[2] = new->memory[1] + PAGE_SIZE; 413 new->pages[2] = new->pages[1] + 1;
417 new->memory[3] = new->memory[2] + PAGE_SIZE; 414 new->pages[3] = new->pages[2] + 1;
418 } 415 }
419 new->page_count = pg_count; 416 new->page_count = pg_count;
420 new->num_scratch_pages = pg_count; 417 new->num_scratch_pages = pg_count;
421 new->type = AGP_PHYS_MEMORY; 418 new->type = AGP_PHYS_MEMORY;
422 new->physical = new->memory[0]; 419 new->physical = page_to_phys(new->pages[0]);
423 return new; 420 return new;
424} 421}
425 422
@@ -451,13 +448,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
451 agp_free_key(curr->key); 448 agp_free_key(curr->key);
452 if (curr->type == AGP_PHYS_MEMORY) { 449 if (curr->type == AGP_PHYS_MEMORY) {
453 if (curr->page_count == 4) 450 if (curr->page_count == 4)
454 i8xx_destroy_pages(gart_to_virt(curr->memory[0])); 451 i8xx_destroy_pages(curr->pages[0]);
455 else { 452 else {
456 void *va = gart_to_virt(curr->memory[0]); 453 agp_bridge->driver->agp_destroy_page(curr->pages[0],
457
458 agp_bridge->driver->agp_destroy_page(va,
459 AGP_PAGE_DESTROY_UNMAP); 454 AGP_PAGE_DESTROY_UNMAP);
460 agp_bridge->driver->agp_destroy_page(va, 455 agp_bridge->driver->agp_destroy_page(curr->pages[0],
461 AGP_PAGE_DESTROY_FREE); 456 AGP_PAGE_DESTROY_FREE);
462 } 457 }
463 agp_free_page_array(curr); 458 agp_free_page_array(curr);
@@ -466,8 +461,9 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
466} 461}
467 462
468static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, 463static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
469 unsigned long addr, int type) 464 struct page *page, int type)
470{ 465{
466 unsigned long addr = phys_to_gart(page_to_phys(page));
471 /* Type checking must be done elsewhere */ 467 /* Type checking must be done elsewhere */
472 return addr | bridge->driver->masks[type].mask; 468 return addr | bridge->driver->masks[type].mask;
473} 469}
@@ -855,7 +851,7 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
855 851
856 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 852 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
857 writel(agp_bridge->driver->mask_memory(agp_bridge, 853 writel(agp_bridge->driver->mask_memory(agp_bridge,
858 mem->memory[i], mask_type), 854 mem->pages[i], mask_type),
859 intel_private.registers+I810_PTE_BASE+(j*4)); 855 intel_private.registers+I810_PTE_BASE+(j*4));
860 } 856 }
861 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); 857 readl(intel_private.registers+I810_PTE_BASE+((j-1)*4));
@@ -1085,7 +1081,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
1085 1081
1086 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { 1082 for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
1087 writel(agp_bridge->driver->mask_memory(agp_bridge, 1083 writel(agp_bridge->driver->mask_memory(agp_bridge,
1088 mem->memory[i], mask_type), intel_private.gtt+j); 1084 mem->pages[i], mask_type), intel_private.gtt+j);
1089 } 1085 }
1090 1086
1091 readl(intel_private.gtt+j-1); 1087 readl(intel_private.gtt+j-1);
@@ -1200,8 +1196,9 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
1200 * this conditional. 1196 * this conditional.
1201 */ 1197 */
1202static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, 1198static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
1203 unsigned long addr, int type) 1199 struct page *page, int type)
1204{ 1200{
1201 unsigned long addr = phys_to_gart(page_to_phys(page));
1205 /* Shift high bits down */ 1202 /* Shift high bits down */
1206 addr |= (addr >> 28) & 0xf0; 1203 addr |= (addr >> 28) & 0xf0;
1207 1204