aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pat.c33
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)
704int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot, 704int 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 */
733void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn, 730void 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
747pgprot_t pgprot_writecombine(pgprot_t prot) 752pgprot_t pgprot_writecombine(pgprot_t prot)