diff options
author | Shaohua Li <shaohua.li@intel.com> | 2008-08-04 02:51:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-15 10:30:45 -0400 |
commit | 1ac2f7d55b7ee1613c90631e87fea22ec06781e5 (patch) | |
tree | 1f93aaed49cf60982b11fbf38fc6e331643a5c08 /arch/x86/mm/pageattr.c | |
parent | 012f09e7942716d5f4339f1fd9a831a485bb1d4a (diff) |
introduce two APIs for page attribute
Introduce two APIs for page attribute. flushing tlb/cache in every page
attribute is expensive. AGP gart usually will do a lot of operations to
change a page to uc, new APIs can reduce flush.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Cc: airlied@linux.ie
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 65c6e46bf059..2c5c18c2464d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -752,12 +752,12 @@ static inline int cache_attr(pgprot_t attr) | |||
752 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); | 752 | (_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD); |
753 | } | 753 | } |
754 | 754 | ||
755 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | 755 | static int do_change_page_attr_set_clr(unsigned long addr, int numpages, |
756 | pgprot_t mask_set, pgprot_t mask_clr, | 756 | pgprot_t mask_set, pgprot_t mask_clr, |
757 | int force_split) | 757 | int force_split, int *tlb_flush) |
758 | { | 758 | { |
759 | struct cpa_data cpa; | 759 | struct cpa_data cpa; |
760 | int ret, cache, checkalias; | 760 | int ret, checkalias; |
761 | 761 | ||
762 | /* | 762 | /* |
763 | * Check, if we are requested to change a not supported | 763 | * Check, if we are requested to change a not supported |
@@ -792,9 +792,22 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
792 | /* | 792 | /* |
793 | * Check whether we really changed something: | 793 | * Check whether we really changed something: |
794 | */ | 794 | */ |
795 | if (!cpa.flushtlb) | 795 | *tlb_flush = cpa.flushtlb; |
796 | goto out; | 796 | cpa_fill_pool(NULL); |
797 | |||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | static int change_page_attr_set_clr(unsigned long addr, int numpages, | ||
802 | pgprot_t mask_set, pgprot_t mask_clr, | ||
803 | int force_split) | ||
804 | { | ||
805 | int cache, flush_cache = 0, ret; | ||
797 | 806 | ||
807 | ret = do_change_page_attr_set_clr(addr, numpages, mask_set, mask_clr, | ||
808 | force_split, &flush_cache); | ||
809 | if (!flush_cache) | ||
810 | goto out; | ||
798 | /* | 811 | /* |
799 | * No need to flush, when we did not set any of the caching | 812 | * No need to flush, when we did not set any of the caching |
800 | * attributes: | 813 | * attributes: |
@@ -811,10 +824,7 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages, | |||
811 | cpa_flush_range(addr, numpages, cache); | 824 | cpa_flush_range(addr, numpages, cache); |
812 | else | 825 | else |
813 | cpa_flush_all(cache); | 826 | cpa_flush_all(cache); |
814 | |||
815 | out: | 827 | out: |
816 | cpa_fill_pool(NULL); | ||
817 | |||
818 | return ret; | 828 | return ret; |
819 | } | 829 | } |
820 | 830 | ||
@@ -852,6 +862,30 @@ int set_memory_uc(unsigned long addr, int numpages) | |||
852 | } | 862 | } |
853 | EXPORT_SYMBOL(set_memory_uc); | 863 | EXPORT_SYMBOL(set_memory_uc); |
854 | 864 | ||
865 | int set_memory_uc_noflush(unsigned long addr, int numpages) | ||
866 | { | ||
867 | int flush; | ||
868 | /* | ||
869 | * for now UC MINUS. see comments in ioremap_nocache() | ||
870 | */ | ||
871 | if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, | ||
872 | _PAGE_CACHE_UC_MINUS, NULL)) | ||
873 | return -EINVAL; | ||
874 | /* | ||
875 | * for now UC MINUS. see comments in ioremap_nocache() | ||
876 | */ | ||
877 | return do_change_page_attr_set_clr(addr, numpages, | ||
878 | __pgprot(_PAGE_CACHE_UC_MINUS), | ||
879 | __pgprot(0), 0, &flush); | ||
880 | } | ||
881 | EXPORT_SYMBOL(set_memory_uc_noflush); | ||
882 | |||
883 | void set_memory_flush_all(void) | ||
884 | { | ||
885 | cpa_flush_all(1); | ||
886 | } | ||
887 | EXPORT_SYMBOL(set_memory_flush_all); | ||
888 | |||
855 | int _set_memory_wc(unsigned long addr, int numpages) | 889 | int _set_memory_wc(unsigned long addr, int numpages) |
856 | { | 890 | { |
857 | return change_page_attr_set(addr, numpages, | 891 | return change_page_attr_set(addr, numpages, |
@@ -926,6 +960,14 @@ int set_pages_uc(struct page *page, int numpages) | |||
926 | } | 960 | } |
927 | EXPORT_SYMBOL(set_pages_uc); | 961 | EXPORT_SYMBOL(set_pages_uc); |
928 | 962 | ||
963 | int set_pages_uc_noflush(struct page *page, int numpages) | ||
964 | { | ||
965 | unsigned long addr = (unsigned long)page_address(page); | ||
966 | |||
967 | return set_memory_uc_noflush(addr, numpages); | ||
968 | } | ||
969 | EXPORT_SYMBOL(set_pages_uc_noflush); | ||
970 | |||
929 | int set_pages_wb(struct page *page, int numpages) | 971 | int set_pages_wb(struct page *page, int numpages) |
930 | { | 972 | { |
931 | unsigned long addr = (unsigned long)page_address(page); | 973 | unsigned long addr = (unsigned long)page_address(page); |