diff options
Diffstat (limited to 'drivers/char/agp/i460-agp.c')
-rw-r--r-- | drivers/char/agp/i460-agp.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 10da687d131a..60cc35bb5db7 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
@@ -60,6 +60,9 @@ | |||
60 | */ | 60 | */ |
61 | #define WR_FLUSH_GATT(index) RD_GATT(index) | 61 | #define WR_FLUSH_GATT(index) RD_GATT(index) |
62 | 62 | ||
63 | static unsigned long i460_mask_memory (struct agp_bridge_data *bridge, | ||
64 | unsigned long addr, int type); | ||
65 | |||
63 | static struct { | 66 | static struct { |
64 | void *gatt; /* ioremap'd GATT area */ | 67 | void *gatt; /* ioremap'd GATT area */ |
65 | 68 | ||
@@ -74,6 +77,7 @@ static struct { | |||
74 | unsigned long *alloced_map; /* bitmap of kernel-pages in use */ | 77 | unsigned long *alloced_map; /* bitmap of kernel-pages in use */ |
75 | int refcount; /* number of kernel pages using the large page */ | 78 | int refcount; /* number of kernel pages using the large page */ |
76 | u64 paddr; /* physical address of large page */ | 79 | u64 paddr; /* physical address of large page */ |
80 | struct page *page; /* page pointer */ | ||
77 | } *lp_desc; | 81 | } *lp_desc; |
78 | } i460; | 82 | } i460; |
79 | 83 | ||
@@ -294,7 +298,7 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem, | |||
294 | void *temp; | 298 | void *temp; |
295 | 299 | ||
296 | pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n", | 300 | pr_debug("i460_insert_memory_small_io_page(mem=%p, pg_start=%ld, type=%d, paddr0=0x%lx)\n", |
297 | mem, pg_start, type, mem->memory[0]); | 301 | mem, pg_start, type, page_to_phys(mem->pages[0])); |
298 | 302 | ||
299 | if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES) | 303 | if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES) |
300 | return -EINVAL; | 304 | return -EINVAL; |
@@ -321,10 +325,9 @@ static int i460_insert_memory_small_io_page (struct agp_memory *mem, | |||
321 | 325 | ||
322 | io_page_size = 1UL << I460_IO_PAGE_SHIFT; | 326 | io_page_size = 1UL << I460_IO_PAGE_SHIFT; |
323 | for (i = 0, j = io_pg_start; i < mem->page_count; i++) { | 327 | for (i = 0, j = io_pg_start; i < mem->page_count; i++) { |
324 | paddr = mem->memory[i]; | 328 | paddr = phys_to_gart(page_to_phys(mem->pages[i])); |
325 | for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) | 329 | for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) |
326 | WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge, | 330 | WR_GATT(j, i460_mask_memory(agp_bridge, paddr, mem->type)); |
327 | paddr, mem->type)); | ||
328 | } | 331 | } |
329 | WR_FLUSH_GATT(j - 1); | 332 | WR_FLUSH_GATT(j - 1); |
330 | return 0; | 333 | return 0; |
@@ -364,10 +367,9 @@ static int i460_alloc_large_page (struct lp_desc *lp) | |||
364 | { | 367 | { |
365 | unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT; | 368 | unsigned long order = I460_IO_PAGE_SHIFT - PAGE_SHIFT; |
366 | size_t map_size; | 369 | size_t map_size; |
367 | void *lpage; | ||
368 | 370 | ||
369 | lpage = (void *) __get_free_pages(GFP_KERNEL, order); | 371 | lp->page = alloc_pages(GFP_KERNEL, order); |
370 | if (!lpage) { | 372 | if (!lp->page) { |
371 | printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); | 373 | printk(KERN_ERR PFX "Couldn't alloc 4M GART page...\n"); |
372 | return -ENOMEM; | 374 | return -ENOMEM; |
373 | } | 375 | } |
@@ -375,12 +377,12 @@ static int i460_alloc_large_page (struct lp_desc *lp) | |||
375 | map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8; | 377 | map_size = ((I460_KPAGES_PER_IOPAGE + BITS_PER_LONG - 1) & -BITS_PER_LONG)/8; |
376 | lp->alloced_map = kzalloc(map_size, GFP_KERNEL); | 378 | lp->alloced_map = kzalloc(map_size, GFP_KERNEL); |
377 | if (!lp->alloced_map) { | 379 | if (!lp->alloced_map) { |
378 | free_pages((unsigned long) lpage, order); | 380 | __free_pages(lp->page, order); |
379 | printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); | 381 | printk(KERN_ERR PFX "Out of memory, we're in trouble...\n"); |
380 | return -ENOMEM; | 382 | return -ENOMEM; |
381 | } | 383 | } |
382 | 384 | ||
383 | lp->paddr = virt_to_gart(lpage); | 385 | lp->paddr = phys_to_gart(page_to_phys(lp->page)); |
384 | lp->refcount = 0; | 386 | lp->refcount = 0; |
385 | atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); | 387 | atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); |
386 | return 0; | 388 | return 0; |
@@ -391,7 +393,7 @@ static void i460_free_large_page (struct lp_desc *lp) | |||
391 | kfree(lp->alloced_map); | 393 | kfree(lp->alloced_map); |
392 | lp->alloced_map = NULL; | 394 | lp->alloced_map = NULL; |
393 | 395 | ||
394 | free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); | 396 | __free_pages(lp->page, I460_IO_PAGE_SHIFT - PAGE_SHIFT); |
395 | atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); | 397 | atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); |
396 | } | 398 | } |
397 | 399 | ||
@@ -439,8 +441,8 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem, | |||
439 | if (i460_alloc_large_page(lp) < 0) | 441 | if (i460_alloc_large_page(lp) < 0) |
440 | return -ENOMEM; | 442 | return -ENOMEM; |
441 | pg = lp - i460.lp_desc; | 443 | pg = lp - i460.lp_desc; |
442 | WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge, | 444 | WR_GATT(pg, i460_mask_memory(agp_bridge, |
443 | lp->paddr, 0)); | 445 | lp->paddr, 0)); |
444 | WR_FLUSH_GATT(pg); | 446 | WR_FLUSH_GATT(pg); |
445 | } | 447 | } |
446 | 448 | ||
@@ -448,7 +450,7 @@ static int i460_insert_memory_large_io_page (struct agp_memory *mem, | |||
448 | idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); | 450 | idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); |
449 | idx++, i++) | 451 | idx++, i++) |
450 | { | 452 | { |
451 | mem->memory[i] = lp->paddr + idx*PAGE_SIZE; | 453 | mem->pages[i] = lp->page; |
452 | __set_bit(idx, lp->alloced_map); | 454 | __set_bit(idx, lp->alloced_map); |
453 | ++lp->refcount; | 455 | ++lp->refcount; |
454 | } | 456 | } |
@@ -463,7 +465,7 @@ static int i460_remove_memory_large_io_page (struct agp_memory *mem, | |||
463 | struct lp_desc *start, *end, *lp; | 465 | struct lp_desc *start, *end, *lp; |
464 | void *temp; | 466 | void *temp; |
465 | 467 | ||
466 | temp = agp_bridge->driver->current_size; | 468 | temp = agp_bridge->current_size; |
467 | num_entries = A_SIZE_8(temp)->num_entries; | 469 | num_entries = A_SIZE_8(temp)->num_entries; |
468 | 470 | ||
469 | /* Figure out what pg_start means in terms of our large GART pages */ | 471 | /* Figure out what pg_start means in terms of our large GART pages */ |
@@ -477,7 +479,7 @@ static int i460_remove_memory_large_io_page (struct agp_memory *mem, | |||
477 | idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); | 479 | idx < ((lp == end) ? (end_offset + 1) : I460_KPAGES_PER_IOPAGE); |
478 | idx++, i++) | 480 | idx++, i++) |
479 | { | 481 | { |
480 | mem->memory[i] = 0; | 482 | mem->pages[i] = NULL; |
481 | __clear_bit(idx, lp->alloced_map); | 483 | __clear_bit(idx, lp->alloced_map); |
482 | --lp->refcount; | 484 | --lp->refcount; |
483 | } | 485 | } |
@@ -521,7 +523,7 @@ static int i460_remove_memory (struct agp_memory *mem, | |||
521 | * Let's just hope nobody counts on the allocated AGP memory being there before bind time | 523 | * Let's just hope nobody counts on the allocated AGP memory being there before bind time |
522 | * (I don't think current drivers do)... | 524 | * (I don't think current drivers do)... |
523 | */ | 525 | */ |
524 | static void *i460_alloc_page (struct agp_bridge_data *bridge) | 526 | static struct page *i460_alloc_page (struct agp_bridge_data *bridge) |
525 | { | 527 | { |
526 | void *page; | 528 | void *page; |
527 | 529 | ||
@@ -534,7 +536,7 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge) | |||
534 | return page; | 536 | return page; |
535 | } | 537 | } |
536 | 538 | ||
537 | static void i460_destroy_page (void *page, int flags) | 539 | static void i460_destroy_page (struct page *page, int flags) |
538 | { | 540 | { |
539 | if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { | 541 | if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { |
540 | agp_generic_destroy_page(page, flags); | 542 | agp_generic_destroy_page(page, flags); |
@@ -544,13 +546,20 @@ static void i460_destroy_page (void *page, int flags) | |||
544 | #endif /* I460_LARGE_IO_PAGES */ | 546 | #endif /* I460_LARGE_IO_PAGES */ |
545 | 547 | ||
546 | static unsigned long i460_mask_memory (struct agp_bridge_data *bridge, | 548 | static unsigned long i460_mask_memory (struct agp_bridge_data *bridge, |
547 | unsigned long addr, int type) | 549 | unsigned long addr, int type) |
548 | { | 550 | { |
549 | /* Make sure the returned address is a valid GATT entry */ | 551 | /* Make sure the returned address is a valid GATT entry */ |
550 | return bridge->driver->masks[0].mask | 552 | return bridge->driver->masks[0].mask |
551 | | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12); | 553 | | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xfffff000) >> 12); |
552 | } | 554 | } |
553 | 555 | ||
556 | static unsigned long i460_page_mask_memory(struct agp_bridge_data *bridge, | ||
557 | struct page *page, int type) | ||
558 | { | ||
559 | unsigned long addr = phys_to_gart(page_to_phys(page)); | ||
560 | return i460_mask_memory(bridge, addr, type); | ||
561 | } | ||
562 | |||
554 | const struct agp_bridge_driver intel_i460_driver = { | 563 | const struct agp_bridge_driver intel_i460_driver = { |
555 | .owner = THIS_MODULE, | 564 | .owner = THIS_MODULE, |
556 | .aperture_sizes = i460_sizes, | 565 | .aperture_sizes = i460_sizes, |
@@ -560,7 +569,7 @@ const struct agp_bridge_driver intel_i460_driver = { | |||
560 | .fetch_size = i460_fetch_size, | 569 | .fetch_size = i460_fetch_size, |
561 | .cleanup = i460_cleanup, | 570 | .cleanup = i460_cleanup, |
562 | .tlb_flush = i460_tlb_flush, | 571 | .tlb_flush = i460_tlb_flush, |
563 | .mask_memory = i460_mask_memory, | 572 | .mask_memory = i460_page_mask_memory, |
564 | .masks = i460_masks, | 573 | .masks = i460_masks, |
565 | .agp_enable = agp_generic_enable, | 574 | .agp_enable = agp_generic_enable, |
566 | .cache_flush = global_cache_flush, | 575 | .cache_flush = global_cache_flush, |