diff options
-rw-r--r-- | arch/x86/mm/pageattr-test.c | 7 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 219 | ||||
-rw-r--r-- | arch/x86/mm/pat.c | 4 | ||||
-rw-r--r-- | drivers/char/agp/agp.h | 5 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 97 | ||||
-rw-r--r-- | drivers/char/agp/intel-agp.c | 28 | ||||
-rw-r--r-- | include/asm-x86/cacheflush.h | 3 | ||||
-rw-r--r-- | mm/highmem.c | 5 |
8 files changed, 305 insertions, 63 deletions
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c index d4aa503caaa2..7c3017287119 100644 --- a/arch/x86/mm/pageattr-test.c +++ b/arch/x86/mm/pageattr-test.c | |||
@@ -118,6 +118,7 @@ static int pageattr_test(void) | |||
118 | unsigned int level; | 118 | unsigned int level; |
119 | int i, k; | 119 | int i, k; |
120 | int err; | 120 | int err; |
121 | unsigned long test_addr; | ||
121 | 122 | ||
122 | if (print) | 123 | if (print) |
123 | printk(KERN_INFO "CPA self-test:\n"); | 124 | printk(KERN_INFO "CPA self-test:\n"); |
@@ -172,7 +173,8 @@ static int pageattr_test(void) | |||
172 | continue; | 173 | continue; |
173 | } | 174 | } |
174 | 175 | ||
175 | err = change_page_attr_set(addr[i], len[i], PAGE_TESTBIT); | 176 | test_addr = addr[i]; |
177 | err = change_page_attr_set(&test_addr, len[i], PAGE_TESTBIT, 0); | ||
176 | if (err < 0) { | 178 | if (err < 0) { |
177 | printk(KERN_ERR "CPA %d failed %d\n", i, err); | 179 | printk(KERN_ERR "CPA %d failed %d\n", i, err); |
178 | failed++; | 180 | failed++; |
@@ -204,7 +206,8 @@ static int pageattr_test(void) | |||
204 | failed++; | 206 | failed++; |
205 | continue; | 207 | continue; |
206 | } | 208 | } |
207 | err = change_page_attr_clear(addr[i], len[i], PAGE_TESTBIT); | 209 | test_addr = addr[i]; |
210 | err = change_page_attr_clear(&test_addr, len[i], PAGE_TESTBIT, 0); | ||
208 | if (err < 0) { | 211 | if (err < 0) { |
209 | printk(KERN_ERR "CPA reverting failed: %d\n", err); | 212 | printk(KERN_ERR "CPA reverting failed: %d\n", err); |
210 | failed++; | 213 | failed++; |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 43e2f8483e4f..1785591808bd 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -25,15 +25,19 @@ | |||
25 | * The current flushing context - we pass it instead of 5 arguments: | 25 | * The current flushing context - we pass it instead of 5 arguments: |
26 | */ | 26 | */ |
27 | struct cpa_data { | 27 | struct cpa_data { |
28 | unsigned long vaddr; | 28 | unsigned long *vaddr; |
29 | pgprot_t mask_set; | 29 | pgprot_t mask_set; |
30 | pgprot_t mask_clr; | 30 | pgprot_t mask_clr; |
31 | int numpages; | 31 | int numpages; |
32 | int flushtlb; | 32 | int flags; |
33 | unsigned long pfn; | 33 | unsigned long pfn; |
34 | unsigned force_split : 1; | 34 | unsigned force_split : 1; |
35 | int curpage; | ||
35 | }; | 36 | }; |
36 | 37 | ||
38 | #define CPA_FLUSHTLB 1 | ||
39 | #define CPA_ARRAY 2 | ||
40 | |||
37 | #ifdef CONFIG_PROC_FS | 41 | #ifdef CONFIG_PROC_FS |
38 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; | 42 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; |
39 | 43 | ||
@@ -190,6 +194,41 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) | |||
190 | } | 194 | } |
191 | } | 195 | } |
192 | 196 | ||
197 | static void cpa_flush_array(unsigned long *start, int numpages, int cache) | ||
198 | { | ||
199 | unsigned int i, level; | ||
200 | unsigned long *addr; | ||
201 | |||
202 | BUG_ON(irqs_disabled()); | ||
203 | |||
204 | on_each_cpu(__cpa_flush_range, NULL, 1); | ||
205 | |||
206 | if (!cache) | ||
207 | return; | ||
208 | |||
209 | /* 4M threshold */ | ||
210 | if (numpages >= 1024) { | ||
211 | if (boot_cpu_data.x86_model >= 4) | ||
212 | wbinvd(); | ||
213 | return; | ||
214 | } | ||
215 | /* | ||
216 | * We only need to flush on one CPU, | ||
217 | * clflush is a MESI-coherent instruction that | ||
218 | * will cause all other CPUs to flush the same | ||
219 | * cachelines: | ||
220 | */ | ||
221 | for (i = 0, addr = start; i < numpages; i++, addr++) { | ||
222 | pte_t *pte = lookup_address(*addr, &level); | ||
223 | |||
224 | /* | ||
225 | * Only flush present addresses: | ||
226 | */ | ||
227 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) | ||
228 | clflush_cache_range((void *) *addr, PAGE_SIZE); | ||
229 | } | ||
230 | } | ||
231 | |||
193 | /* | 232 | /* |
194 | * Certain areas of memory on x86 require very specific protection flags, | 233 | * Certain areas of memory on x86 require very specific protection flags, |
195 | * for example the BIOS area or kernel text. Callers don't always get this | 234 | * for example the BIOS area or kernel text. Callers don't always get this |
@@ -398,7 +437,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
398 | */ | 437 | */ |
399 | new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); | 438 | new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot)); |
400 | __set_pmd_pte(kpte, address, new_pte); | 439 | __set_pmd_pte(kpte, address, new_pte); |
401 | cpa->flushtlb = 1; | 440 | cpa->flags |= CPA_FLUSHTLB; |
402 | do_split = 0; | 441 | do_split = 0; |
403 | } | 442 | } |
404 | 443 | ||
@@ -584,11 +623,16 @@ out_unlock: | |||
584 | 623 | ||
585 | static int __change_page_attr(struct cpa_data *cpa, int primary) | 624 | static int __change_page_attr(struct cpa_data *cpa, int primary) |
586 | { | 625 | { |
587 | unsigned long address = cpa->vaddr; | 626 | unsigned long address; |
588 | int do_split, err; | 627 | int do_split, err; |
589 | unsigned int level; | 628 | unsigned int level; |
590 | pte_t *kpte, old_pte; | 629 | pte_t *kpte, old_pte; |
591 | 630 | ||
631 | if (cpa->flags & CPA_ARRAY) | ||
632 | address = cpa->vaddr[cpa->curpage]; | ||
633 | else | ||
634 | address = *cpa->vaddr; | ||
635 | |||
592 | repeat: | 636 | repeat: |
593 | kpte = lookup_address(address, &level); | 637 | kpte = lookup_address(address, &level); |
594 | if (!kpte) | 638 | if (!kpte) |
@@ -600,7 +644,7 @@ repeat: | |||
600 | return 0; | 644 | return 0; |
601 | WARN(1, KERN_WARNING "CPA: called for zero pte. " | 645 | WARN(1, KERN_WARNING "CPA: called for zero pte. " |
602 | "vaddr = %lx cpa->vaddr = %lx\n", address, | 646 | "vaddr = %lx cpa->vaddr = %lx\n", address, |
603 | cpa->vaddr); | 647 | *cpa->vaddr); |
604 | return -EINVAL; | 648 | return -EINVAL; |
605 | } | 649 | } |
606 | 650 | ||
@@ -626,7 +670,7 @@ repeat: | |||
626 | */ | 670 | */ |
627 | if (pte_val(old_pte) != pte_val(new_pte)) { | 671 | if (pte_val(old_pte) != pte_val(new_pte)) { |
628 | set_pte_atomic(kpte, new_pte); | 672 | set_pte_atomic(kpte, new_pte); |
629 | cpa->flushtlb = 1; | 673 | cpa->flags |= CPA_FLUSHTLB; |
630 | } | 674 | } |
631 | cpa->numpages = 1; | 675 | cpa->numpages = 1; |
632 | return 0; | 676 | return 0; |
@@ -650,7 +694,7 @@ repeat: | |||
650 | */ | 694 | */ |
651 | err = split_large_page(kpte, address); | 695 | err = split_large_page(kpte, address); |
652 | if (!err) { | 696 | if (!err) { |
653 | cpa->flushtlb = 1; | 697 | cpa->flags |= CPA_FLUSHTLB; |
654 | goto repeat; | 698 | goto repeat; |
655 | } | 699 | } |
656 | 700 | ||
@@ -663,6 +707,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
663 | { | 707 | { |
664 | struct cpa_data alias_cpa; | 708 | struct cpa_data alias_cpa; |
665 | int ret = 0; | 709 | int ret = 0; |
710 | unsigned long temp_cpa_vaddr, vaddr; | ||
666 | 711 | ||
667 | if (cpa->pfn >= max_pfn_mapped) | 712 | if (cpa->pfn >= max_pfn_mapped) |
668 | return 0; | 713 | return 0; |
@@ -675,16 +720,24 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
675 | * No need to redo, when the primary call touched the direct | 720 | * No need to redo, when the primary call touched the direct |
676 | * mapping already: | 721 | * mapping already: |
677 | */ | 722 | */ |
678 | if (!(within(cpa->vaddr, PAGE_OFFSET, | 723 | if (cpa->flags & CPA_ARRAY) |
724 | vaddr = cpa->vaddr[cpa->curpage]; | ||
725 | else | ||
726 | vaddr = *cpa->vaddr; | ||
727 | |||
728 | if (!(within(vaddr, PAGE_OFFSET, | ||
679 | PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) | 729 | PAGE_OFFSET + (max_low_pfn_mapped << PAGE_SHIFT)) |
680 | #ifdef CONFIG_X86_64 | 730 | #ifdef CONFIG_X86_64 |
681 | || within(cpa->vaddr, PAGE_OFFSET + (1UL<<32), | 731 | || within(vaddr, PAGE_OFFSET + (1UL<<32), |
682 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) | 732 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)) |
683 | #endif | 733 | #endif |
684 | )) { | 734 | )) { |
685 | 735 | ||
686 | alias_cpa = *cpa; | 736 | alias_cpa = *cpa; |
687 | alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 737 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); |
738 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
739 | alias_cpa.flags &= ~CPA_ARRAY; | ||
740 | |||
688 | 741 | ||
689 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | 742 | ret = __change_page_attr_set_clr(&alias_cpa, 0); |
690 | } | 743 | } |
@@ -696,7 +749,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
696 | * No need to redo, when the primary call touched the high | 749 | * No need to redo, when the primary call touched the high |
697 | * mapping already: | 750 | * mapping already: |
698 | */ | 751 | */ |
699 | if (within(cpa->vaddr, (unsigned long) _text, (unsigned long) _end)) | 752 | if (within(vaddr, (unsigned long) _text, (unsigned long) _end)) |
700 | return 0; | 753 | return 0; |
701 | 754 | ||
702 | /* | 755 | /* |
@@ -707,8 +760,9 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
707 | return 0; | 760 | return 0; |
708 | 761 | ||
709 | alias_cpa = *cpa; | 762 | alias_cpa = *cpa; |
710 | alias_cpa.vaddr = | 763 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; |
711 | (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; | 764 | alias_cpa.vaddr = &temp_cpa_vaddr; |
765 | alias_cpa.flags &= ~CPA_ARRAY; | ||
712 | 766 | ||
713 | /* | 767 | /* |
714 | * The high mapping range is imprecise, so ignore the return value. | 768 | * The high mapping range is imprecise, so ignore the return value. |
@@ -728,6 +782,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
728 | * preservation check. | 782 | * preservation check. |
729 | */ | 783 | */ |
730 | cpa->numpages = numpages; | 784 | cpa->numpages = numpages; |
785 | /* for array changes, we can't use large page */ | ||
786 | if (cpa->flags & CPA_ARRAY) | ||
787 | cpa->numpages = 1; | ||
731 | 788 | ||
732 | ret = __change_page_attr(cpa, checkalias); | 789 | ret = __change_page_attr(cpa, checkalias); |
733 | if (ret) | 790 | if (ret) |
@@ -746,7 +803,11 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
746 | */ | 803 | */ |
747 | BUG_ON(cpa->numpages > numpages); | 804 | BUG_ON(cpa->numpages > numpages); |
748 | numpages -= cpa->numpages; | 805 | numpages -= cpa->numpages; |
749 | cpa->vaddr += cpa->numpages * PAGE_SIZE; | 806 | if (cpa->flags & CPA_ARRAY) |
807 | cpa->curpage++; | ||
808 | else | ||
809 | *cpa->vaddr += cpa->numpages * PAGE_SIZE; | ||
810 | |||
750 | } | 811 | } |
751 | return 0; | 812 | return 0; |
752 | } | 813 | } |
@@ -757,9 +818,9 @@ static inline int cache_attr(pgprot_t attr) | |||
757 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); | 818 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); |
758 | } | 819 | } |
759 | 820 | ||
760 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | 821 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, |
761 | pgprot_t mask_set, pgprot_t mask_clr, | 822 | pgprot_t mask_set, pgprot_t mask_clr, |
762 | int force_split) | 823 | int force_split, int array) |
763 | { | 824 | { |
764 | struct cpa_data cpa; | 825 | struct cpa_data cpa; |
765 | int ret, cache, checkalias; | 826 | int ret, cache, checkalias; |
@@ -774,21 +835,38 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
774 | return 0; | 835 | return 0; |
775 | 836 | ||
776 | /* Ensure we are PAGE_SIZE aligned */ | 837 | /* Ensure we are PAGE_SIZE aligned */ |
777 | if (addr & ~PAGE_MASK) { | 838 | if (!array) { |
778 | addr &= PAGE_MASK; | 839 | if (*addr & ~PAGE_MASK) { |
779 | /* | 840 | *addr &= PAGE_MASK; |
780 | * People should not be passing in unaligned addresses: | 841 | /* |
781 | */ | 842 | * People should not be passing in unaligned addresses: |
782 | WARN_ON_ONCE(1); | 843 | */ |
844 | WARN_ON_ONCE(1); | ||
845 | } | ||
846 | } else { | ||
847 | int i; | ||
848 | for (i = 0; i < numpages; i++) { | ||
849 | if (addr[i] & ~PAGE_MASK) { | ||
850 | addr[i] &= PAGE_MASK; | ||
851 | WARN_ON_ONCE(1); | ||
852 | } | ||
853 | } | ||
783 | } | 854 | } |
784 | 855 | ||
856 | /* Must avoid aliasing mappings in the highmem code */ | ||
857 | kmap_flush_unused(); | ||
858 | |||
785 | cpa.vaddr = addr; | 859 | cpa.vaddr = addr; |
786 | cpa.numpages = numpages; | 860 | cpa.numpages = numpages; |
787 | cpa.mask_set = mask_set; | 861 | cpa.mask_set = mask_set; |
788 | cpa.mask_clr = mask_clr; | 862 | cpa.mask_clr = mask_clr; |
789 | cpa.flushtlb = 0; | 863 | cpa.flags = 0; |
864 | cpa.curpage = 0; | ||
790 | cpa.force_split = force_split; | 865 | cpa.force_split = force_split; |
791 | 866 | ||
867 | if (array) | ||
868 | cpa.flags |= CPA_ARRAY; | ||
869 | |||
792 | /* No alias checking for _NX bit modifications */ | 870 | /* No alias checking for _NX bit modifications */ |
793 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; | 871 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; |
794 | 872 | ||
@@ -797,7 +875,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
797 | /* | 875 | /* |
798 | * Check whether we really changed something: | 876 | * Check whether we really changed something: |
799 | */ | 877 | */ |
800 | if (!cpa.flushtlb) | 878 | if (!(cpa.flags & CPA_FLUSHTLB)) |
801 | goto out; | 879 | goto out; |
802 | 880 | ||
803 | /* | 881 | /* |
@@ -812,9 +890,12 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
812 | * error case we fall back to cpa_flush_all (which uses | 890 | * error case we fall back to cpa_flush_all (which uses |
813 | * wbindv): | 891 | * wbindv): |
814 | */ | 892 | */ |
815 | if (!ret && cpu_has_clflush) | 893 | if (!ret && cpu_has_clflush) { |
816 | cpa_flush_range(addr, numpages, cache); | 894 | if (cpa.flags & CPA_ARRAY) |
817 | else | 895 | cpa_flush_array(addr, numpages, cache); |
896 | else | ||
897 | cpa_flush_range(*addr, numpages, cache); | ||
898 | } else | ||
818 | cpa_flush_all(cache); | 899 | cpa_flush_all(cache); |
819 | 900 | ||
820 | out: | 901 | out: |
@@ -823,16 +904,18 @@ out: | |||
823 | return ret; | 904 | return ret; |
824 | } | 905 | } |
825 | 906 | ||
826 | static inline int change_page_attr_set(unsigned long addr, int numpages, | 907 | static inline int change_page_attr_set(unsigned long *addr, int numpages, |
827 | pgprot_t mask) | 908 | pgprot_t mask, int array) |
828 | { | 909 | { |
829 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0); | 910 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0, |
911 | array); | ||
830 | } | 912 | } |
831 | 913 | ||
832 | static inline int change_page_attr_clear(unsigned long addr, int numpages, | 914 | static inline int change_page_attr_clear(unsigned long *addr, int numpages, |
833 | pgprot_t mask) | 915 | pgprot_t mask, int array) |
834 | { | 916 | { |
835 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0); | 917 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0, |
918 | array); | ||
836 | } | 919 | } |
837 | 920 | ||
838 | int _set_memory_uc(unsigned long addr, int numpages) | 921 | int _set_memory_uc(unsigned long addr, int numpages) |
@@ -840,8 +923,8 @@ int _set_memory_uc(unsigned long addr, int numpages) | |||
840 | /* | 923 | /* |
841 | * for now UC MINUS. see comments in ioremap_nocache() | 924 | * for now UC MINUS. see comments in ioremap_nocache() |
842 | */ | 925 | */ |
843 | return change_page_attr_set(addr, numpages, | 926 | return change_page_attr_set(&addr, numpages, |
844 | __pgprot(_PAGE_CACHE_UC_MINUS)); | 927 | __pgprot(_PAGE_CACHE_UC_MINUS), 0); |
845 | } | 928 | } |
846 | 929 | ||
847 | int set_memory_uc(unsigned long addr, int numpages) | 930 | int set_memory_uc(unsigned long addr, int numpages) |
@@ -857,10 +940,31 @@ int set_memory_uc(unsigned long addr, int numpages) | |||
857 | } | 940 | } |
858 | EXPORT_SYMBOL(set_memory_uc); | 941 | EXPORT_SYMBOL(set_memory_uc); |
859 | 942 | ||
943 | int set_memory_array_uc(unsigned long *addr, int addrinarray) | ||
944 | { | ||
945 | int i; | ||
946 | /* | ||
947 | * for now UC MINUS. see comments in ioremap_nocache() | ||
948 | */ | ||
949 | for (i = 0; i < addrinarray; i++) { | ||
950 | if (reserve_memtype(addr[i], addr[i] + PAGE_SIZE, | ||
951 | _PAGE_CACHE_UC_MINUS, NULL)) | ||
952 | goto out; | ||
953 | } | ||
954 | |||
955 | return change_page_attr_set(addr, addrinarray, | ||
956 | __pgprot(_PAGE_CACHE_UC_MINUS), 1); | ||
957 | out: | ||
958 | while (--i >= 0) | ||
959 | free_memtype(addr[i], addr[i] + PAGE_SIZE); | ||
960 | return -EINVAL; | ||
961 | } | ||
962 | EXPORT_SYMBOL(set_memory_array_uc); | ||
963 | |||
860 | int _set_memory_wc(unsigned long addr, int numpages) | 964 | int _set_memory_wc(unsigned long addr, int numpages) |
861 | { | 965 | { |
862 | return change_page_attr_set(addr, numpages, | 966 | return change_page_attr_set(&addr, numpages, |
863 | __pgprot(_PAGE_CACHE_WC)); | 967 | __pgprot(_PAGE_CACHE_WC), 0); |
864 | } | 968 | } |
865 | 969 | ||
866 | int set_memory_wc(unsigned long addr, int numpages) | 970 | int set_memory_wc(unsigned long addr, int numpages) |
@@ -878,8 +982,8 @@ EXPORT_SYMBOL(set_memory_wc); | |||
878 | 982 | ||
879 | int _set_memory_wb(unsigned long addr, int numpages) | 983 | int _set_memory_wb(unsigned long addr, int numpages) |
880 | { | 984 | { |
881 | return change_page_attr_clear(addr, numpages, | 985 | return change_page_attr_clear(&addr, numpages, |
882 | __pgprot(_PAGE_CACHE_MASK)); | 986 | __pgprot(_PAGE_CACHE_MASK), 0); |
883 | } | 987 | } |
884 | 988 | ||
885 | int set_memory_wb(unsigned long addr, int numpages) | 989 | int set_memory_wb(unsigned long addr, int numpages) |
@@ -890,37 +994,48 @@ int set_memory_wb(unsigned long addr, int numpages) | |||
890 | } | 994 | } |
891 | EXPORT_SYMBOL(set_memory_wb); | 995 | EXPORT_SYMBOL(set_memory_wb); |
892 | 996 | ||
997 | int set_memory_array_wb(unsigned long *addr, int addrinarray) | ||
998 | { | ||
999 | int i; | ||
1000 | for (i = 0; i < addrinarray; i++) | ||
1001 | free_memtype(addr[i], addr[i] + PAGE_SIZE); | ||
1002 | |||
1003 | return change_page_attr_clear(addr, addrinarray, | ||
1004 | __pgprot(_PAGE_CACHE_MASK), 1); | ||
1005 | } | ||
1006 | EXPORT_SYMBOL(set_memory_array_wb); | ||
1007 | |||
893 | int set_memory_x(unsigned long addr, int numpages) | 1008 | int set_memory_x(unsigned long addr, int numpages) |
894 | { | 1009 | { |
895 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX)); | 1010 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_NX), 0); |
896 | } | 1011 | } |
897 | EXPORT_SYMBOL(set_memory_x); | 1012 | EXPORT_SYMBOL(set_memory_x); |
898 | 1013 | ||
899 | int set_memory_nx(unsigned long addr, int numpages) | 1014 | int set_memory_nx(unsigned long addr, int numpages) |
900 | { | 1015 | { |
901 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX)); | 1016 | return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_NX), 0); |
902 | } | 1017 | } |
903 | EXPORT_SYMBOL(set_memory_nx); | 1018 | EXPORT_SYMBOL(set_memory_nx); |
904 | 1019 | ||
905 | int set_memory_ro(unsigned long addr, int numpages) | 1020 | int set_memory_ro(unsigned long addr, int numpages) |
906 | { | 1021 | { |
907 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); | 1022 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_RW), 0); |
908 | } | 1023 | } |
909 | 1024 | ||
910 | int set_memory_rw(unsigned long addr, int numpages) | 1025 | int set_memory_rw(unsigned long addr, int numpages) |
911 | { | 1026 | { |
912 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); | 1027 | return change_page_attr_set(&addr, numpages, __pgprot(_PAGE_RW), 0); |
913 | } | 1028 | } |
914 | 1029 | ||
915 | int set_memory_np(unsigned long addr, int numpages) | 1030 | int set_memory_np(unsigned long addr, int numpages) |
916 | { | 1031 | { |
917 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); | 1032 | return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0); |
918 | } | 1033 | } |
919 | 1034 | ||
920 | int set_memory_4k(unsigned long addr, int numpages) | 1035 | int set_memory_4k(unsigned long addr, int numpages) |
921 | { | 1036 | { |
922 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), | 1037 | return change_page_attr_set_clr(&addr, numpages, __pgprot(0), |
923 | __pgprot(0), 1); | 1038 | __pgprot(0), 1, 0); |
924 | } | 1039 | } |
925 | 1040 | ||
926 | int set_pages_uc(struct page *page, int numpages) | 1041 | int set_pages_uc(struct page *page, int numpages) |
@@ -973,20 +1088,24 @@ int set_pages_rw(struct page *page, int numpages) | |||
973 | 1088 | ||
974 | static int __set_pages_p(struct page *page, int numpages) | 1089 | static int __set_pages_p(struct page *page, int numpages) |
975 | { | 1090 | { |
976 | struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), | 1091 | unsigned long tempaddr = (unsigned long) page_address(page); |
1092 | struct cpa_data cpa = { .vaddr = &tempaddr, | ||
977 | .numpages = numpages, | 1093 | .numpages = numpages, |
978 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), | 1094 | .mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
979 | .mask_clr = __pgprot(0)}; | 1095 | .mask_clr = __pgprot(0), |
1096 | .flags = 0}; | ||
980 | 1097 | ||
981 | return __change_page_attr_set_clr(&cpa, 1); | 1098 | return __change_page_attr_set_clr(&cpa, 1); |
982 | } | 1099 | } |
983 | 1100 | ||
984 | static int __set_pages_np(struct page *page, int numpages) | 1101 | static int __set_pages_np(struct page *page, int numpages) |
985 | { | 1102 | { |
986 | struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page), | 1103 | unsigned long tempaddr = (unsigned long) page_address(page); |
1104 | struct cpa_data cpa = { .vaddr = &tempaddr, | ||
987 | .numpages = numpages, | 1105 | .numpages = numpages, |
988 | .mask_set = __pgprot(0), | 1106 | .mask_set = __pgprot(0), |
989 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)}; | 1107 | .mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW), |
1108 | .flags = 0}; | ||
990 | 1109 | ||
991 | return __change_page_attr_set_clr(&cpa, 1); | 1110 | return __change_page_attr_set_clr(&cpa, 1); |
992 | } | 1111 | } |
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 2a50e0fa64a5..f049b1d6ebdf 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -514,7 +514,7 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) | |||
514 | free_memtype(addr, addr + size); | 514 | free_memtype(addr, addr + size); |
515 | } | 515 | } |
516 | 516 | ||
517 | #if defined(CONFIG_DEBUG_FS) | 517 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) |
518 | 518 | ||
519 | /* get Nth element of the linked list */ | 519 | /* get Nth element of the linked list */ |
520 | static struct memtype *memtype_get_idx(loff_t pos) | 520 | static struct memtype *memtype_get_idx(loff_t pos) |
@@ -598,4 +598,4 @@ static int __init pat_memtype_list_init(void) | |||
598 | 598 | ||
599 | late_initcall(pat_memtype_list_init); | 599 | late_initcall(pat_memtype_list_init); |
600 | 600 | ||
601 | #endif /* CONFIG_DEBUG_FS */ | 601 | #endif /* CONFIG_DEBUG_FS && CONFIG_X86_PAT */ |
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 4bada0e8b812..46f507531177 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -116,7 +116,9 @@ struct agp_bridge_driver { | |||
116 | struct agp_memory *(*alloc_by_type) (size_t, int); | 116 | struct agp_memory *(*alloc_by_type) (size_t, int); |
117 | void (*free_by_type)(struct agp_memory *); | 117 | void (*free_by_type)(struct agp_memory *); |
118 | void *(*agp_alloc_page)(struct agp_bridge_data *); | 118 | void *(*agp_alloc_page)(struct agp_bridge_data *); |
119 | int (*agp_alloc_pages)(struct agp_bridge_data *, struct agp_memory *, size_t); | ||
119 | void (*agp_destroy_page)(void *, int flags); | 120 | void (*agp_destroy_page)(void *, int flags); |
121 | void (*agp_destroy_pages)(struct agp_memory *); | ||
120 | int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); | 122 | int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); |
121 | void (*chipset_flush)(struct agp_bridge_data *); | 123 | void (*chipset_flush)(struct agp_bridge_data *); |
122 | }; | 124 | }; |
@@ -277,7 +279,10 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type); | |||
277 | struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); | 279 | struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); |
278 | void agp_generic_free_by_type(struct agp_memory *curr); | 280 | void agp_generic_free_by_type(struct agp_memory *curr); |
279 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge); | 281 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge); |
282 | int agp_generic_alloc_pages(struct agp_bridge_data *agp_bridge, | ||
283 | struct agp_memory *memory, size_t page_count); | ||
280 | void agp_generic_destroy_page(void *addr, int flags); | 284 | void agp_generic_destroy_page(void *addr, int flags); |
285 | void agp_generic_destroy_pages(struct agp_memory *memory); | ||
281 | void agp_free_key(int key); | 286 | void agp_free_key(int key); |
282 | int agp_num_entries(void); | 287 | int agp_num_entries(void); |
283 | u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command); | 288 | u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command); |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 118dbde25dc7..10d6cbd7c05e 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -201,14 +201,22 @@ void agp_free_memory(struct agp_memory *curr) | |||
201 | return; | 201 | return; |
202 | } | 202 | } |
203 | if (curr->page_count != 0) { | 203 | if (curr->page_count != 0) { |
204 | for (i = 0; i < curr->page_count; i++) { | 204 | if (curr->bridge->driver->agp_destroy_pages) { |
205 | curr->memory[i] = (unsigned long)gart_to_virt(curr->memory[i]); | 205 | curr->bridge->driver->agp_destroy_pages(curr); |
206 | curr->bridge->driver->agp_destroy_page((void *)curr->memory[i], | 206 | } else { |
207 | AGP_PAGE_DESTROY_UNMAP); | 207 | |
208 | } | 208 | for (i = 0; i < curr->page_count; i++) { |
209 | for (i = 0; i < curr->page_count; i++) { | 209 | curr->memory[i] = (unsigned long)gart_to_virt( |
210 | curr->bridge->driver->agp_destroy_page((void *)curr->memory[i], | 210 | curr->memory[i]); |
211 | AGP_PAGE_DESTROY_FREE); | 211 | curr->bridge->driver->agp_destroy_page( |
212 | (void *)curr->memory[i], | ||
213 | AGP_PAGE_DESTROY_UNMAP); | ||
214 | } | ||
215 | for (i = 0; i < curr->page_count; i++) { | ||
216 | curr->bridge->driver->agp_destroy_page( | ||
217 | (void *)curr->memory[i], | ||
218 | AGP_PAGE_DESTROY_FREE); | ||
219 | } | ||
212 | } | 220 | } |
213 | } | 221 | } |
214 | agp_free_key(curr->key); | 222 | agp_free_key(curr->key); |
@@ -264,6 +272,15 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, | |||
264 | if (new == NULL) | 272 | if (new == NULL) |
265 | return NULL; | 273 | return NULL; |
266 | 274 | ||
275 | if (bridge->driver->agp_alloc_pages) { | ||
276 | if (bridge->driver->agp_alloc_pages(bridge, new, page_count)) { | ||
277 | agp_free_memory(new); | ||
278 | return NULL; | ||
279 | } | ||
280 | new->bridge = bridge; | ||
281 | return new; | ||
282 | } | ||
283 | |||
267 | for (i = 0; i < page_count; i++) { | 284 | for (i = 0; i < page_count; i++) { |
268 | void *addr = bridge->driver->agp_alloc_page(bridge); | 285 | void *addr = bridge->driver->agp_alloc_page(bridge); |
269 | 286 | ||
@@ -1203,6 +1220,39 @@ EXPORT_SYMBOL(agp_generic_alloc_user); | |||
1203 | * against a maximum value. | 1220 | * against a maximum value. |
1204 | */ | 1221 | */ |
1205 | 1222 | ||
1223 | int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *mem, size_t num_pages) | ||
1224 | { | ||
1225 | struct page * page; | ||
1226 | int i, ret = -ENOMEM; | ||
1227 | |||
1228 | for (i = 0; i < num_pages; i++) { | ||
1229 | page = alloc_page(GFP_KERNEL | GFP_DMA32); | ||
1230 | /* agp_free_memory() needs gart address */ | ||
1231 | if (page == NULL) | ||
1232 | goto out; | ||
1233 | |||
1234 | #ifndef CONFIG_X86 | ||
1235 | map_page_into_agp(page); | ||
1236 | #endif | ||
1237 | get_page(page); | ||
1238 | atomic_inc(&agp_bridge->current_memory_agp); | ||
1239 | |||
1240 | /* set_memory_array_uc() needs virtual address */ | ||
1241 | mem->memory[i] = (unsigned long)page_address(page); | ||
1242 | mem->page_count++; | ||
1243 | } | ||
1244 | |||
1245 | #ifdef CONFIG_X86 | ||
1246 | set_memory_array_uc(mem->memory, num_pages); | ||
1247 | #endif | ||
1248 | ret = 0; | ||
1249 | out: | ||
1250 | for (i = 0; i < mem->page_count; i++) | ||
1251 | mem->memory[i] = virt_to_gart((void *)mem->memory[i]); | ||
1252 | return ret; | ||
1253 | } | ||
1254 | EXPORT_SYMBOL(agp_generic_alloc_pages); | ||
1255 | |||
1206 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | 1256 | void *agp_generic_alloc_page(struct agp_bridge_data *bridge) |
1207 | { | 1257 | { |
1208 | struct page * page; | 1258 | struct page * page; |
@@ -1219,6 +1269,37 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) | |||
1219 | } | 1269 | } |
1220 | EXPORT_SYMBOL(agp_generic_alloc_page); | 1270 | EXPORT_SYMBOL(agp_generic_alloc_page); |
1221 | 1271 | ||
1272 | void agp_generic_destroy_pages(struct agp_memory *mem) | ||
1273 | { | ||
1274 | int i; | ||
1275 | void *addr; | ||
1276 | struct page *page; | ||
1277 | |||
1278 | if (!mem) | ||
1279 | return; | ||
1280 | |||
1281 | for (i = 0; i < mem->page_count; i++) | ||
1282 | mem->memory[i] = (unsigned long)gart_to_virt(mem->memory[i]); | ||
1283 | |||
1284 | #ifdef CONFIG_X86 | ||
1285 | set_memory_array_wb(mem->memory, mem->page_count); | ||
1286 | #endif | ||
1287 | |||
1288 | for (i = 0; i < mem->page_count; i++) { | ||
1289 | addr = (void *)mem->memory[i]; | ||
1290 | page = virt_to_page(addr); | ||
1291 | |||
1292 | #ifndef CONFIG_X86 | ||
1293 | unmap_page_from_agp(page); | ||
1294 | #endif | ||
1295 | |||
1296 | put_page(page); | ||
1297 | free_page((unsigned long)addr); | ||
1298 | atomic_dec(&agp_bridge->current_memory_agp); | ||
1299 | mem->memory[i] = 0; | ||
1300 | } | ||
1301 | } | ||
1302 | EXPORT_SYMBOL(agp_generic_destroy_pages); | ||
1222 | 1303 | ||
1223 | void agp_generic_destroy_page(void *addr, int flags) | 1304 | void agp_generic_destroy_page(void *addr, int flags) |
1224 | { | 1305 | { |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 016fdf0623a4..043e36628d6d 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -1711,7 +1711,9 @@ static const struct agp_bridge_driver intel_generic_driver = { | |||
1711 | .alloc_by_type = agp_generic_alloc_by_type, | 1711 | .alloc_by_type = agp_generic_alloc_by_type, |
1712 | .free_by_type = agp_generic_free_by_type, | 1712 | .free_by_type = agp_generic_free_by_type, |
1713 | .agp_alloc_page = agp_generic_alloc_page, | 1713 | .agp_alloc_page = agp_generic_alloc_page, |
1714 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1714 | .agp_destroy_page = agp_generic_destroy_page, | 1715 | .agp_destroy_page = agp_generic_destroy_page, |
1716 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1715 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1717 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1716 | }; | 1718 | }; |
1717 | 1719 | ||
@@ -1736,7 +1738,9 @@ static const struct agp_bridge_driver intel_810_driver = { | |||
1736 | .alloc_by_type = intel_i810_alloc_by_type, | 1738 | .alloc_by_type = intel_i810_alloc_by_type, |
1737 | .free_by_type = intel_i810_free_by_type, | 1739 | .free_by_type = intel_i810_free_by_type, |
1738 | .agp_alloc_page = agp_generic_alloc_page, | 1740 | .agp_alloc_page = agp_generic_alloc_page, |
1741 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1739 | .agp_destroy_page = agp_generic_destroy_page, | 1742 | .agp_destroy_page = agp_generic_destroy_page, |
1743 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1740 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1744 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1741 | }; | 1745 | }; |
1742 | 1746 | ||
@@ -1760,7 +1764,9 @@ static const struct agp_bridge_driver intel_815_driver = { | |||
1760 | .alloc_by_type = agp_generic_alloc_by_type, | 1764 | .alloc_by_type = agp_generic_alloc_by_type, |
1761 | .free_by_type = agp_generic_free_by_type, | 1765 | .free_by_type = agp_generic_free_by_type, |
1762 | .agp_alloc_page = agp_generic_alloc_page, | 1766 | .agp_alloc_page = agp_generic_alloc_page, |
1767 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1763 | .agp_destroy_page = agp_generic_destroy_page, | 1768 | .agp_destroy_page = agp_generic_destroy_page, |
1769 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1764 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1770 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1765 | }; | 1771 | }; |
1766 | 1772 | ||
@@ -1785,7 +1791,9 @@ static const struct agp_bridge_driver intel_830_driver = { | |||
1785 | .alloc_by_type = intel_i830_alloc_by_type, | 1791 | .alloc_by_type = intel_i830_alloc_by_type, |
1786 | .free_by_type = intel_i810_free_by_type, | 1792 | .free_by_type = intel_i810_free_by_type, |
1787 | .agp_alloc_page = agp_generic_alloc_page, | 1793 | .agp_alloc_page = agp_generic_alloc_page, |
1794 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1788 | .agp_destroy_page = agp_generic_destroy_page, | 1795 | .agp_destroy_page = agp_generic_destroy_page, |
1796 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1789 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1797 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1790 | .chipset_flush = intel_i830_chipset_flush, | 1798 | .chipset_flush = intel_i830_chipset_flush, |
1791 | }; | 1799 | }; |
@@ -1810,7 +1818,9 @@ static const struct agp_bridge_driver intel_820_driver = { | |||
1810 | .alloc_by_type = agp_generic_alloc_by_type, | 1818 | .alloc_by_type = agp_generic_alloc_by_type, |
1811 | .free_by_type = agp_generic_free_by_type, | 1819 | .free_by_type = agp_generic_free_by_type, |
1812 | .agp_alloc_page = agp_generic_alloc_page, | 1820 | .agp_alloc_page = agp_generic_alloc_page, |
1821 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1813 | .agp_destroy_page = agp_generic_destroy_page, | 1822 | .agp_destroy_page = agp_generic_destroy_page, |
1823 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1814 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1824 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1815 | }; | 1825 | }; |
1816 | 1826 | ||
@@ -1834,7 +1844,9 @@ static const struct agp_bridge_driver intel_830mp_driver = { | |||
1834 | .alloc_by_type = agp_generic_alloc_by_type, | 1844 | .alloc_by_type = agp_generic_alloc_by_type, |
1835 | .free_by_type = agp_generic_free_by_type, | 1845 | .free_by_type = agp_generic_free_by_type, |
1836 | .agp_alloc_page = agp_generic_alloc_page, | 1846 | .agp_alloc_page = agp_generic_alloc_page, |
1847 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1837 | .agp_destroy_page = agp_generic_destroy_page, | 1848 | .agp_destroy_page = agp_generic_destroy_page, |
1849 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1838 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1850 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1839 | }; | 1851 | }; |
1840 | 1852 | ||
@@ -1858,7 +1870,9 @@ static const struct agp_bridge_driver intel_840_driver = { | |||
1858 | .alloc_by_type = agp_generic_alloc_by_type, | 1870 | .alloc_by_type = agp_generic_alloc_by_type, |
1859 | .free_by_type = agp_generic_free_by_type, | 1871 | .free_by_type = agp_generic_free_by_type, |
1860 | .agp_alloc_page = agp_generic_alloc_page, | 1872 | .agp_alloc_page = agp_generic_alloc_page, |
1873 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1861 | .agp_destroy_page = agp_generic_destroy_page, | 1874 | .agp_destroy_page = agp_generic_destroy_page, |
1875 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1862 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1876 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1863 | }; | 1877 | }; |
1864 | 1878 | ||
@@ -1882,7 +1896,9 @@ static const struct agp_bridge_driver intel_845_driver = { | |||
1882 | .alloc_by_type = agp_generic_alloc_by_type, | 1896 | .alloc_by_type = agp_generic_alloc_by_type, |
1883 | .free_by_type = agp_generic_free_by_type, | 1897 | .free_by_type = agp_generic_free_by_type, |
1884 | .agp_alloc_page = agp_generic_alloc_page, | 1898 | .agp_alloc_page = agp_generic_alloc_page, |
1899 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1885 | .agp_destroy_page = agp_generic_destroy_page, | 1900 | .agp_destroy_page = agp_generic_destroy_page, |
1901 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1886 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1902 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1887 | .chipset_flush = intel_i830_chipset_flush, | 1903 | .chipset_flush = intel_i830_chipset_flush, |
1888 | }; | 1904 | }; |
@@ -1907,7 +1923,9 @@ static const struct agp_bridge_driver intel_850_driver = { | |||
1907 | .alloc_by_type = agp_generic_alloc_by_type, | 1923 | .alloc_by_type = agp_generic_alloc_by_type, |
1908 | .free_by_type = agp_generic_free_by_type, | 1924 | .free_by_type = agp_generic_free_by_type, |
1909 | .agp_alloc_page = agp_generic_alloc_page, | 1925 | .agp_alloc_page = agp_generic_alloc_page, |
1926 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1910 | .agp_destroy_page = agp_generic_destroy_page, | 1927 | .agp_destroy_page = agp_generic_destroy_page, |
1928 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1911 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1929 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1912 | }; | 1930 | }; |
1913 | 1931 | ||
@@ -1931,7 +1949,9 @@ static const struct agp_bridge_driver intel_860_driver = { | |||
1931 | .alloc_by_type = agp_generic_alloc_by_type, | 1949 | .alloc_by_type = agp_generic_alloc_by_type, |
1932 | .free_by_type = agp_generic_free_by_type, | 1950 | .free_by_type = agp_generic_free_by_type, |
1933 | .agp_alloc_page = agp_generic_alloc_page, | 1951 | .agp_alloc_page = agp_generic_alloc_page, |
1952 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1934 | .agp_destroy_page = agp_generic_destroy_page, | 1953 | .agp_destroy_page = agp_generic_destroy_page, |
1954 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1935 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 1955 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
1936 | }; | 1956 | }; |
1937 | 1957 | ||
@@ -1956,7 +1976,9 @@ static const struct agp_bridge_driver intel_915_driver = { | |||
1956 | .alloc_by_type = intel_i830_alloc_by_type, | 1976 | .alloc_by_type = intel_i830_alloc_by_type, |
1957 | .free_by_type = intel_i810_free_by_type, | 1977 | .free_by_type = intel_i810_free_by_type, |
1958 | .agp_alloc_page = agp_generic_alloc_page, | 1978 | .agp_alloc_page = agp_generic_alloc_page, |
1979 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1959 | .agp_destroy_page = agp_generic_destroy_page, | 1980 | .agp_destroy_page = agp_generic_destroy_page, |
1981 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1960 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 1982 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1961 | .chipset_flush = intel_i915_chipset_flush, | 1983 | .chipset_flush = intel_i915_chipset_flush, |
1962 | }; | 1984 | }; |
@@ -1982,7 +2004,9 @@ static const struct agp_bridge_driver intel_i965_driver = { | |||
1982 | .alloc_by_type = intel_i830_alloc_by_type, | 2004 | .alloc_by_type = intel_i830_alloc_by_type, |
1983 | .free_by_type = intel_i810_free_by_type, | 2005 | .free_by_type = intel_i810_free_by_type, |
1984 | .agp_alloc_page = agp_generic_alloc_page, | 2006 | .agp_alloc_page = agp_generic_alloc_page, |
2007 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
1985 | .agp_destroy_page = agp_generic_destroy_page, | 2008 | .agp_destroy_page = agp_generic_destroy_page, |
2009 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
1986 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 2010 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
1987 | .chipset_flush = intel_i915_chipset_flush, | 2011 | .chipset_flush = intel_i915_chipset_flush, |
1988 | }; | 2012 | }; |
@@ -2007,7 +2031,9 @@ static const struct agp_bridge_driver intel_7505_driver = { | |||
2007 | .alloc_by_type = agp_generic_alloc_by_type, | 2031 | .alloc_by_type = agp_generic_alloc_by_type, |
2008 | .free_by_type = agp_generic_free_by_type, | 2032 | .free_by_type = agp_generic_free_by_type, |
2009 | .agp_alloc_page = agp_generic_alloc_page, | 2033 | .agp_alloc_page = agp_generic_alloc_page, |
2034 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
2010 | .agp_destroy_page = agp_generic_destroy_page, | 2035 | .agp_destroy_page = agp_generic_destroy_page, |
2036 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
2011 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 2037 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
2012 | }; | 2038 | }; |
2013 | 2039 | ||
@@ -2032,7 +2058,9 @@ static const struct agp_bridge_driver intel_g33_driver = { | |||
2032 | .alloc_by_type = intel_i830_alloc_by_type, | 2058 | .alloc_by_type = intel_i830_alloc_by_type, |
2033 | .free_by_type = intel_i810_free_by_type, | 2059 | .free_by_type = intel_i810_free_by_type, |
2034 | .agp_alloc_page = agp_generic_alloc_page, | 2060 | .agp_alloc_page = agp_generic_alloc_page, |
2061 | .agp_alloc_pages = agp_generic_alloc_pages, | ||
2035 | .agp_destroy_page = agp_generic_destroy_page, | 2062 | .agp_destroy_page = agp_generic_destroy_page, |
2063 | .agp_destroy_pages = agp_generic_destroy_pages, | ||
2036 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, | 2064 | .agp_type_to_mask_type = intel_i830_type_to_mask_type, |
2037 | .chipset_flush = intel_i915_chipset_flush, | 2065 | .chipset_flush = intel_i915_chipset_flush, |
2038 | }; | 2066 | }; |
diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index f4c0ab50d2c2..0a5f71817b3e 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h | |||
@@ -66,6 +66,9 @@ int set_memory_rw(unsigned long addr, int numpages); | |||
66 | int set_memory_np(unsigned long addr, int numpages); | 66 | int set_memory_np(unsigned long addr, int numpages); |
67 | int set_memory_4k(unsigned long addr, int numpages); | 67 | int set_memory_4k(unsigned long addr, int numpages); |
68 | 68 | ||
69 | int set_memory_array_uc(unsigned long *addr, int addrinarray); | ||
70 | int set_memory_array_wb(unsigned long *addr, int addrinarray); | ||
71 | |||
69 | /* | 72 | /* |
70 | * For legacy compatibility with the old APIs, a few functions | 73 | * For legacy compatibility with the old APIs, a few functions |
71 | * are provided that work on a "struct page". | 74 | * are provided that work on a "struct page". |
diff --git a/mm/highmem.c b/mm/highmem.c index e16e1523b688..b36b83b920ff 100644 --- a/mm/highmem.c +++ b/mm/highmem.c | |||
@@ -70,6 +70,7 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); | |||
70 | static void flush_all_zero_pkmaps(void) | 70 | static void flush_all_zero_pkmaps(void) |
71 | { | 71 | { |
72 | int i; | 72 | int i; |
73 | int need_flush = 0; | ||
73 | 74 | ||
74 | flush_cache_kmaps(); | 75 | flush_cache_kmaps(); |
75 | 76 | ||
@@ -101,8 +102,10 @@ static void flush_all_zero_pkmaps(void) | |||
101 | &pkmap_page_table[i]); | 102 | &pkmap_page_table[i]); |
102 | 103 | ||
103 | set_page_address(page, NULL); | 104 | set_page_address(page, NULL); |
105 | need_flush = 1; | ||
104 | } | 106 | } |
105 | flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); | 107 | if (need_flush) |
108 | flush_tlb_kernel_range(PKMAP_ADDR(0), PKMAP_ADDR(LAST_PKMAP)); | ||
106 | } | 109 | } |
107 | 110 | ||
108 | /** | 111 | /** |