diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2017-05-02 05:02:41 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2017-05-02 05:02:41 -0400 |
| commit | 4d6ca227c768b50b05cf183974b40abe444e9d0c (patch) | |
| tree | bf953d8e895281053548b9967a2c4b58d641df00 /lib/ioremap.c | |
| parent | 800f3eef8ebc1264e9c135bfa892c8ae41fa4792 (diff) | |
| parent | af22a610bc38508d5ea760507d31be6b6983dfa8 (diff) | |
Merge branch 'for-4.12/asus' into for-linus
Diffstat (limited to 'lib/ioremap.c')
| -rw-r--r-- | lib/ioremap.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/lib/ioremap.c b/lib/ioremap.c index a3e14ce92a56..4bb30206b942 100644 --- a/lib/ioremap.c +++ b/lib/ioremap.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <asm/pgtable.h> | 14 | #include <asm/pgtable.h> |
| 15 | 15 | ||
| 16 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP | 16 | #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP |
| 17 | static int __read_mostly ioremap_p4d_capable; | ||
| 17 | static int __read_mostly ioremap_pud_capable; | 18 | static int __read_mostly ioremap_pud_capable; |
| 18 | static int __read_mostly ioremap_pmd_capable; | 19 | static int __read_mostly ioremap_pmd_capable; |
| 19 | static int __read_mostly ioremap_huge_disabled; | 20 | static int __read_mostly ioremap_huge_disabled; |
| @@ -35,6 +36,11 @@ void __init ioremap_huge_init(void) | |||
| 35 | } | 36 | } |
| 36 | } | 37 | } |
| 37 | 38 | ||
| 39 | static inline int ioremap_p4d_enabled(void) | ||
| 40 | { | ||
| 41 | return ioremap_p4d_capable; | ||
| 42 | } | ||
| 43 | |||
| 38 | static inline int ioremap_pud_enabled(void) | 44 | static inline int ioremap_pud_enabled(void) |
| 39 | { | 45 | { |
| 40 | return ioremap_pud_capable; | 46 | return ioremap_pud_capable; |
| @@ -46,6 +52,7 @@ static inline int ioremap_pmd_enabled(void) | |||
| 46 | } | 52 | } |
| 47 | 53 | ||
| 48 | #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */ | 54 | #else /* !CONFIG_HAVE_ARCH_HUGE_VMAP */ |
| 55 | static inline int ioremap_p4d_enabled(void) { return 0; } | ||
| 49 | static inline int ioremap_pud_enabled(void) { return 0; } | 56 | static inline int ioremap_pud_enabled(void) { return 0; } |
| 50 | static inline int ioremap_pmd_enabled(void) { return 0; } | 57 | static inline int ioremap_pmd_enabled(void) { return 0; } |
| 51 | #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ | 58 | #endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ |
| @@ -94,14 +101,14 @@ static inline int ioremap_pmd_range(pud_t *pud, unsigned long addr, | |||
| 94 | return 0; | 101 | return 0; |
| 95 | } | 102 | } |
| 96 | 103 | ||
| 97 | static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr, | 104 | static inline int ioremap_pud_range(p4d_t *p4d, unsigned long addr, |
| 98 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) | 105 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) |
| 99 | { | 106 | { |
| 100 | pud_t *pud; | 107 | pud_t *pud; |
| 101 | unsigned long next; | 108 | unsigned long next; |
| 102 | 109 | ||
| 103 | phys_addr -= addr; | 110 | phys_addr -= addr; |
| 104 | pud = pud_alloc(&init_mm, pgd, addr); | 111 | pud = pud_alloc(&init_mm, p4d, addr); |
| 105 | if (!pud) | 112 | if (!pud) |
| 106 | return -ENOMEM; | 113 | return -ENOMEM; |
| 107 | do { | 114 | do { |
| @@ -120,6 +127,32 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr, | |||
| 120 | return 0; | 127 | return 0; |
| 121 | } | 128 | } |
| 122 | 129 | ||
| 130 | static inline int ioremap_p4d_range(pgd_t *pgd, unsigned long addr, | ||
| 131 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) | ||
| 132 | { | ||
| 133 | p4d_t *p4d; | ||
| 134 | unsigned long next; | ||
| 135 | |||
| 136 | phys_addr -= addr; | ||
| 137 | p4d = p4d_alloc(&init_mm, pgd, addr); | ||
| 138 | if (!p4d) | ||
| 139 | return -ENOMEM; | ||
| 140 | do { | ||
| 141 | next = p4d_addr_end(addr, end); | ||
| 142 | |||
| 143 | if (ioremap_p4d_enabled() && | ||
| 144 | ((next - addr) == P4D_SIZE) && | ||
| 145 | IS_ALIGNED(phys_addr + addr, P4D_SIZE)) { | ||
| 146 | if (p4d_set_huge(p4d, phys_addr + addr, prot)) | ||
| 147 | continue; | ||
| 148 | } | ||
| 149 | |||
| 150 | if (ioremap_pud_range(p4d, addr, next, phys_addr + addr, prot)) | ||
| 151 | return -ENOMEM; | ||
| 152 | } while (p4d++, addr = next, addr != end); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 123 | int ioremap_page_range(unsigned long addr, | 156 | int ioremap_page_range(unsigned long addr, |
| 124 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) | 157 | unsigned long end, phys_addr_t phys_addr, pgprot_t prot) |
| 125 | { | 158 | { |
| @@ -135,7 +168,7 @@ int ioremap_page_range(unsigned long addr, | |||
| 135 | pgd = pgd_offset_k(addr); | 168 | pgd = pgd_offset_k(addr); |
| 136 | do { | 169 | do { |
| 137 | next = pgd_addr_end(addr, end); | 170 | next = pgd_addr_end(addr, end); |
| 138 | err = ioremap_pud_range(pgd, addr, next, phys_addr+addr, prot); | 171 | err = ioremap_p4d_range(pgd, addr, next, phys_addr+addr, prot); |
| 139 | if (err) | 172 | if (err) |
| 140 | break; | 173 | break; |
| 141 | } while (pgd++, addr = next, addr != end); | 174 | } while (pgd++, addr = next, addr != end); |
