diff options
Diffstat (limited to 'drivers/char/drm/drm_vm.c')
-rw-r--r-- | drivers/char/drm/drm_vm.c | 92 |
1 files changed, 28 insertions, 64 deletions
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 621220f3f372..ced4215e2275 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -73,12 +73,13 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
73 | r_list = list_entry(list, drm_map_list_t, head); | 73 | r_list = list_entry(list, drm_map_list_t, head); |
74 | map = r_list->map; | 74 | map = r_list->map; |
75 | if (!map) continue; | 75 | if (!map) continue; |
76 | if (map->offset == VM_OFFSET(vma)) break; | 76 | if (r_list->user_token == VM_OFFSET(vma)) |
77 | break; | ||
77 | } | 78 | } |
78 | 79 | ||
79 | if (map && map->type == _DRM_AGP) { | 80 | if (map && map->type == _DRM_AGP) { |
80 | unsigned long offset = address - vma->vm_start; | 81 | unsigned long offset = address - vma->vm_start; |
81 | unsigned long baddr = VM_OFFSET(vma) + offset; | 82 | unsigned long baddr = map->offset + offset; |
82 | struct drm_agp_mem *agpmem; | 83 | struct drm_agp_mem *agpmem; |
83 | struct page *page; | 84 | struct page *page; |
84 | 85 | ||
@@ -210,6 +211,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
210 | } | 211 | } |
211 | 212 | ||
212 | if(!found_maps) { | 213 | if(!found_maps) { |
214 | drm_dma_handle_t dmah; | ||
215 | |||
213 | switch (map->type) { | 216 | switch (map->type) { |
214 | case _DRM_REGISTERS: | 217 | case _DRM_REGISTERS: |
215 | case _DRM_FRAME_BUFFER: | 218 | case _DRM_FRAME_BUFFER: |
@@ -228,6 +231,12 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) | |||
228 | case _DRM_AGP: | 231 | case _DRM_AGP: |
229 | case _DRM_SCATTER_GATHER: | 232 | case _DRM_SCATTER_GATHER: |
230 | break; | 233 | break; |
234 | case _DRM_CONSISTENT: | ||
235 | dmah.vaddr = map->handle; | ||
236 | dmah.busaddr = map->offset; | ||
237 | dmah.size = map->size; | ||
238 | __drm_pci_free(dev, &dmah); | ||
239 | break; | ||
231 | } | 240 | } |
232 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 241 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
233 | } | 242 | } |
@@ -296,7 +305,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, | |||
296 | 305 | ||
297 | 306 | ||
298 | offset = address - vma->vm_start; | 307 | offset = address - vma->vm_start; |
299 | map_offset = map->offset - dev->sg->handle; | 308 | map_offset = map->offset - (unsigned long)dev->sg->virtual; |
300 | page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); | 309 | page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); |
301 | page = entry->pagelist[page_offset]; | 310 | page = entry->pagelist[page_offset]; |
302 | get_page(page); | 311 | get_page(page); |
@@ -305,8 +314,6 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, | |||
305 | } | 314 | } |
306 | 315 | ||
307 | 316 | ||
308 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) | ||
309 | |||
310 | static struct page *drm_vm_nopage(struct vm_area_struct *vma, | 317 | static struct page *drm_vm_nopage(struct vm_area_struct *vma, |
311 | unsigned long address, | 318 | unsigned long address, |
312 | int *type) { | 319 | int *type) { |
@@ -335,35 +342,6 @@ static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, | |||
335 | return drm_do_vm_sg_nopage(vma, address); | 342 | return drm_do_vm_sg_nopage(vma, address); |
336 | } | 343 | } |
337 | 344 | ||
338 | #else /* LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,0) */ | ||
339 | |||
340 | static struct page *drm_vm_nopage(struct vm_area_struct *vma, | ||
341 | unsigned long address, | ||
342 | int unused) { | ||
343 | return drm_do_vm_nopage(vma, address); | ||
344 | } | ||
345 | |||
346 | static struct page *drm_vm_shm_nopage(struct vm_area_struct *vma, | ||
347 | unsigned long address, | ||
348 | int unused) { | ||
349 | return drm_do_vm_shm_nopage(vma, address); | ||
350 | } | ||
351 | |||
352 | static struct page *drm_vm_dma_nopage(struct vm_area_struct *vma, | ||
353 | unsigned long address, | ||
354 | int unused) { | ||
355 | return drm_do_vm_dma_nopage(vma, address); | ||
356 | } | ||
357 | |||
358 | static struct page *drm_vm_sg_nopage(struct vm_area_struct *vma, | ||
359 | unsigned long address, | ||
360 | int unused) { | ||
361 | return drm_do_vm_sg_nopage(vma, address); | ||
362 | } | ||
363 | |||
364 | #endif | ||
365 | |||
366 | |||
367 | /** AGP virtual memory operations */ | 345 | /** AGP virtual memory operations */ |
368 | static struct vm_operations_struct drm_vm_ops = { | 346 | static struct vm_operations_struct drm_vm_ops = { |
369 | .nopage = drm_vm_nopage, | 347 | .nopage = drm_vm_nopage, |
@@ -487,11 +465,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
487 | 465 | ||
488 | vma->vm_ops = &drm_vm_dma_ops; | 466 | vma->vm_ops = &drm_vm_dma_ops; |
489 | 467 | ||
490 | #if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ | ||
491 | vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ | ||
492 | #else | ||
493 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 468 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |
494 | #endif | ||
495 | 469 | ||
496 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 470 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
497 | drm_vm_open(vma); | 471 | drm_vm_open(vma); |
@@ -560,13 +534,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
560 | for performance, even if the list was a | 534 | for performance, even if the list was a |
561 | bit longer. */ | 535 | bit longer. */ |
562 | list_for_each(list, &dev->maplist->head) { | 536 | list_for_each(list, &dev->maplist->head) { |
563 | unsigned long off; | ||
564 | 537 | ||
565 | r_list = list_entry(list, drm_map_list_t, head); | 538 | r_list = list_entry(list, drm_map_list_t, head); |
566 | map = r_list->map; | 539 | map = r_list->map; |
567 | if (!map) continue; | 540 | if (!map) continue; |
568 | off = dev->driver->get_map_ofs(map); | 541 | if (r_list->user_token == VM_OFFSET(vma)) |
569 | if (off == VM_OFFSET(vma)) break; | 542 | break; |
570 | } | 543 | } |
571 | 544 | ||
572 | if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) | 545 | if (!map || ((map->flags&_DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) |
@@ -605,17 +578,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
605 | /* fall through to _DRM_FRAME_BUFFER... */ | 578 | /* fall through to _DRM_FRAME_BUFFER... */ |
606 | case _DRM_FRAME_BUFFER: | 579 | case _DRM_FRAME_BUFFER: |
607 | case _DRM_REGISTERS: | 580 | case _DRM_REGISTERS: |
608 | if (VM_OFFSET(vma) >= __pa(high_memory)) { | ||
609 | #if defined(__i386__) || defined(__x86_64__) | 581 | #if defined(__i386__) || defined(__x86_64__) |
610 | if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { | 582 | if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) { |
611 | pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; | 583 | pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; |
612 | pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; | 584 | pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT; |
613 | } | 585 | } |
614 | #elif defined(__powerpc__) | 586 | #elif defined(__powerpc__) |
615 | pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE | _PAGE_GUARDED; | 587 | pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; |
588 | if (map->type == _DRM_REGISTERS) | ||
589 | pgprot_val(vma->vm_page_prot) |= _PAGE_GUARDED; | ||
616 | #endif | 590 | #endif |
617 | vma->vm_flags |= VM_IO; /* not in core dump */ | 591 | vma->vm_flags |= VM_IO; /* not in core dump */ |
618 | } | ||
619 | #if defined(__ia64__) | 592 | #if defined(__ia64__) |
620 | if (efi_range_is_wc(vma->vm_start, vma->vm_end - | 593 | if (efi_range_is_wc(vma->vm_start, vma->vm_end - |
621 | vma->vm_start)) | 594 | vma->vm_start)) |
@@ -628,12 +601,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
628 | offset = dev->driver->get_reg_ofs(dev); | 601 | offset = dev->driver->get_reg_ofs(dev); |
629 | #ifdef __sparc__ | 602 | #ifdef __sparc__ |
630 | if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, | 603 | if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, |
631 | (VM_OFFSET(vma) + offset) >> PAGE_SHIFT, | 604 | (map->offset + offset) >> PAGE_SHIFT, |
632 | vma->vm_end - vma->vm_start, | 605 | vma->vm_end - vma->vm_start, |
633 | vma->vm_page_prot)) | 606 | vma->vm_page_prot)) |
634 | #else | 607 | #else |
635 | if (io_remap_pfn_range(vma, vma->vm_start, | 608 | if (io_remap_pfn_range(vma, vma->vm_start, |
636 | (VM_OFFSET(vma) + offset) >> PAGE_SHIFT, | 609 | (map->offset + offset) >> PAGE_SHIFT, |
637 | vma->vm_end - vma->vm_start, | 610 | vma->vm_end - vma->vm_start, |
638 | vma->vm_page_prot)) | 611 | vma->vm_page_prot)) |
639 | #endif | 612 | #endif |
@@ -641,37 +614,28 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
641 | DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," | 614 | DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," |
642 | " offset = 0x%lx\n", | 615 | " offset = 0x%lx\n", |
643 | map->type, | 616 | map->type, |
644 | vma->vm_start, vma->vm_end, VM_OFFSET(vma) + offset); | 617 | vma->vm_start, vma->vm_end, map->offset + offset); |
645 | vma->vm_ops = &drm_vm_ops; | 618 | vma->vm_ops = &drm_vm_ops; |
646 | break; | 619 | break; |
647 | case _DRM_SHM: | 620 | case _DRM_SHM: |
621 | case _DRM_CONSISTENT: | ||
622 | /* Consistent memory is really like shared memory. It's only | ||
623 | * allocate in a different way */ | ||
648 | vma->vm_ops = &drm_vm_shm_ops; | 624 | vma->vm_ops = &drm_vm_shm_ops; |
649 | vma->vm_private_data = (void *)map; | 625 | vma->vm_private_data = (void *)map; |
650 | /* Don't let this area swap. Change when | 626 | /* Don't let this area swap. Change when |
651 | DRM_KERNEL advisory is supported. */ | 627 | DRM_KERNEL advisory is supported. */ |
652 | #if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ | ||
653 | vma->vm_flags |= VM_LOCKED; | ||
654 | #else | ||
655 | vma->vm_flags |= VM_RESERVED; | 628 | vma->vm_flags |= VM_RESERVED; |
656 | #endif | ||
657 | break; | 629 | break; |
658 | case _DRM_SCATTER_GATHER: | 630 | case _DRM_SCATTER_GATHER: |
659 | vma->vm_ops = &drm_vm_sg_ops; | 631 | vma->vm_ops = &drm_vm_sg_ops; |
660 | vma->vm_private_data = (void *)map; | 632 | vma->vm_private_data = (void *)map; |
661 | #if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ | ||
662 | vma->vm_flags |= VM_LOCKED; | ||
663 | #else | ||
664 | vma->vm_flags |= VM_RESERVED; | 633 | vma->vm_flags |= VM_RESERVED; |
665 | #endif | ||
666 | break; | 634 | break; |
667 | default: | 635 | default: |
668 | return -EINVAL; /* This should never happen. */ | 636 | return -EINVAL; /* This should never happen. */ |
669 | } | 637 | } |
670 | #if LINUX_VERSION_CODE <= 0x02040e /* KERNEL_VERSION(2,4,14) */ | ||
671 | vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */ | ||
672 | #else | ||
673 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 638 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |
674 | #endif | ||
675 | 639 | ||
676 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 640 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
677 | drm_vm_open(vma); | 641 | drm_vm_open(vma); |