diff options
-rw-r--r-- | arch/x86/mm/pat.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 3d68ef6d2266..de36c886cd38 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -704,21 +704,18 @@ int track_pfn_vma_copy(struct vm_area_struct *vma) | |||
704 | int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, | 704 | int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, |
705 | unsigned long pfn, unsigned long size) | 705 | unsigned long pfn, unsigned long size) |
706 | { | 706 | { |
707 | resource_size_t paddr = (resource_size_t)pfn << PAGE_SHIFT; | ||
707 | unsigned long flags; | 708 | unsigned long flags; |
708 | resource_size_t paddr; | ||
709 | unsigned long vma_size = vma->vm_end - vma->vm_start; | ||
710 | 709 | ||
711 | if (is_linear_pfn_mapping(vma)) { | 710 | /* reserve the whole chunk starting from paddr */ |
712 | /* reserve the whole chunk starting from vm_pgoff */ | 711 | if (is_linear_pfn_mapping(vma)) |
713 | paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT; | 712 | return reserve_pfn_range(paddr, size, prot, 0); |
714 | return reserve_pfn_range(paddr, vma_size, prot, 0); | ||
715 | } | ||
716 | 713 | ||
717 | if (!pat_enabled) | 714 | if (!pat_enabled) |
718 | return 0; | 715 | return 0; |
719 | 716 | ||
720 | /* for vm_insert_pfn and friends, we set prot based on lookup */ | 717 | /* for vm_insert_pfn and friends, we set prot based on lookup */ |
721 | flags = lookup_memtype(pfn << PAGE_SHIFT); | 718 | flags = lookup_memtype(paddr); |
722 | *prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) | | 719 | *prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) | |
723 | flags); | 720 | flags); |
724 | 721 | ||
@@ -728,20 +725,28 @@ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, | |||
728 | /* | 725 | /* |
729 | * untrack_pfn_vma is called while unmapping a pfnmap for a region. | 726 | * untrack_pfn_vma is called while unmapping a pfnmap for a region. |
730 | * untrack can be called for a specific region indicated by pfn and size or | 727 | * untrack can be called for a specific region indicated by pfn and size or |
731 | * can be for the entire vma (in which case size can be zero). | 728 | * can be for the entire vma (in which case pfn, size are zero). |
732 | */ | 729 | */ |
733 | void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn, | 730 | void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn, |
734 | unsigned long size) | 731 | unsigned long size) |
735 | { | 732 | { |
736 | resource_size_t paddr; | 733 | resource_size_t paddr; |
737 | unsigned long vma_size = vma->vm_end - vma->vm_start; | 734 | unsigned long prot; |
738 | 735 | ||
739 | if (is_linear_pfn_mapping(vma)) { | 736 | if (!is_linear_pfn_mapping(vma)) |
740 | /* free the whole chunk starting from vm_pgoff */ | ||
741 | paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT; | ||
742 | free_pfn_range(paddr, vma_size); | ||
743 | return; | 737 | return; |
738 | |||
739 | /* free the chunk starting from pfn or the whole chunk */ | ||
740 | paddr = (resource_size_t)pfn << PAGE_SHIFT; | ||
741 | if (!paddr && !size) { | ||
742 | if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) { | ||
743 | WARN_ON_ONCE(1); | ||
744 | return; | ||
745 | } | ||
746 | |||
747 | size = vma->vm_end - vma->vm_start; | ||
744 | } | 748 | } |
749 | free_pfn_range(paddr, size); | ||
745 | } | 750 | } |
746 | 751 | ||
747 | pgprot_t pgprot_writecombine(pgprot_t prot) | 752 | pgprot_t pgprot_writecombine(pgprot_t prot) |