diff options
54 files changed, 2528 insertions, 282 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 08def8deb5f5..ecad946920d1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1882,6 +1882,12 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1882 | Format: { 0 | 1 } | 1882 | Format: { 0 | 1 } |
1883 | See arch/parisc/kernel/pdc_chassis.c | 1883 | See arch/parisc/kernel/pdc_chassis.c |
1884 | 1884 | ||
1885 | percpu_alloc= [X86] Select which percpu first chunk allocator to use. | ||
1886 | Allowed values are one of "lpage", "embed" and "4k". | ||
1887 | See comments in arch/x86/kernel/setup_percpu.c for | ||
1888 | details on each allocator. This parameter is primarily | ||
1889 | for debugging and performance comparison. | ||
1890 | |||
1885 | pf. [PARIDE] | 1891 | pf. [PARIDE] |
1886 | See Documentation/blockdev/paride.txt. | 1892 | See Documentation/blockdev/paride.txt. |
1887 | 1893 | ||
diff --git a/Documentation/powerpc/dts-bindings/fsl/esdhc.txt b/Documentation/powerpc/dts-bindings/fsl/esdhc.txt index 5093ddf900da..3ed3797b5086 100644 --- a/Documentation/powerpc/dts-bindings/fsl/esdhc.txt +++ b/Documentation/powerpc/dts-bindings/fsl/esdhc.txt | |||
@@ -10,6 +10,8 @@ Required properties: | |||
10 | - interrupts : should contain eSDHC interrupt. | 10 | - interrupts : should contain eSDHC interrupt. |
11 | - interrupt-parent : interrupt source phandle. | 11 | - interrupt-parent : interrupt source phandle. |
12 | - clock-frequency : specifies eSDHC base clock frequency. | 12 | - clock-frequency : specifies eSDHC base clock frequency. |
13 | - sdhci,1-bit-only : (optional) specifies that a controller can | ||
14 | only handle 1-bit data transfers. | ||
13 | 15 | ||
14 | Example: | 16 | Example: |
15 | 17 | ||
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index de8e10a94103..0d8d23581c44 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
@@ -139,6 +139,7 @@ ALC883/888 | |||
139 | acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) | 139 | acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) |
140 | acer-aspire Acer Aspire 9810 | 140 | acer-aspire Acer Aspire 9810 |
141 | acer-aspire-4930g Acer Aspire 4930G | 141 | acer-aspire-4930g Acer Aspire 4930G |
142 | acer-aspire-6530g Acer Aspire 6530G | ||
142 | acer-aspire-8930g Acer Aspire 8930G | 143 | acer-aspire-8930g Acer Aspire 8930G |
143 | medion Medion Laptops | 144 | medion Medion Laptops |
144 | medion-md2 Medion MD2 | 145 | medion-md2 Medion MD2 |
diff --git a/MAINTAINERS b/MAINTAINERS index dc226e78612c..1d4704300c1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1010,6 +1010,13 @@ W: http://www.at91.com/ | |||
1010 | S: Maintained | 1010 | S: Maintained |
1011 | F: drivers/mmc/host/at91_mci.c | 1011 | F: drivers/mmc/host/at91_mci.c |
1012 | 1012 | ||
1013 | ATMEL AT91 / AT32 MCI DRIVER | ||
1014 | P: Nicolas Ferre | ||
1015 | M: nicolas.ferre@atmel.com | ||
1016 | S: Maintained | ||
1017 | F: drivers/mmc/host/atmel-mci.c | ||
1018 | F: drivers/mmc/host/atmel-mci-regs.h | ||
1019 | |||
1013 | ATMEL AT91 / AT32 SERIAL DRIVER | 1020 | ATMEL AT91 / AT32 SERIAL DRIVER |
1014 | P: Haavard Skinnemoen | 1021 | P: Haavard Skinnemoen |
1015 | M: hskinnemoen@atmel.com | 1022 | M: hskinnemoen@atmel.com |
@@ -5094,6 +5101,13 @@ L: sdhci-devel@lists.ossman.eu | |||
5094 | S: Maintained | 5101 | S: Maintained |
5095 | F: drivers/mmc/host/sdhci.* | 5102 | F: drivers/mmc/host/sdhci.* |
5096 | 5103 | ||
5104 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER | ||
5105 | P: Ben Dooks | ||
5106 | M: ben-linux@fluff.org | ||
5107 | L: sdhci-devel@lists.ossman.eu | ||
5108 | S: Maintained | ||
5109 | F: drivers/mmc/host/sdhci-s3c.c | ||
5110 | |||
5097 | SECURITY SUBSYSTEM | 5111 | SECURITY SUBSYSTEM |
5098 | P: James Morris | 5112 | P: James Morris |
5099 | M: jmorris@namei.org | 5113 | M: jmorris@namei.org |
@@ -6216,6 +6230,14 @@ S: Maintained | |||
6216 | F: Documentation/i2c/busses/i2c-viapro | 6230 | F: Documentation/i2c/busses/i2c-viapro |
6217 | F: drivers/i2c/busses/i2c-viapro.c | 6231 | F: drivers/i2c/busses/i2c-viapro.c |
6218 | 6232 | ||
6233 | VIA SD/MMC CARD CONTROLLER DRIVER | ||
6234 | P: Joseph Chan | ||
6235 | M: JosephChan@via.com.tw | ||
6236 | P: Harald Welte | ||
6237 | M: HaraldWelte@viatech.com | ||
6238 | S: Maintained | ||
6239 | F: drivers/mmc/host/via-sdmmc.c | ||
6240 | |||
6219 | VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER | 6241 | VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER |
6220 | P: Joseph Chan | 6242 | P: Joseph Chan |
6221 | M: JosephChan@via.com.tw | 6243 | M: JosephChan@via.com.tw |
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c index 4829f96585b1..00a31deaa96e 100644 --- a/arch/alpha/mm/fault.c +++ b/arch/alpha/mm/fault.c | |||
@@ -146,7 +146,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, | |||
146 | /* If for any reason at all we couldn't handle the fault, | 146 | /* If for any reason at all we couldn't handle the fault, |
147 | make sure we exit gracefully rather than endlessly redo | 147 | make sure we exit gracefully rather than endlessly redo |
148 | the fault. */ | 148 | the fault. */ |
149 | fault = handle_mm_fault(mm, vma, address, cause > 0); | 149 | fault = handle_mm_fault(mm, vma, address, cause > 0 ? FAULT_FLAG_WRITE : 0); |
150 | up_read(&mm->mmap_sem); | 150 | up_read(&mm->mmap_sem); |
151 | if (unlikely(fault & VM_FAULT_ERROR)) { | 151 | if (unlikely(fault & VM_FAULT_ERROR)) { |
152 | if (fault & VM_FAULT_OOM) | 152 | if (fault & VM_FAULT_OOM) |
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 0455557a2899..6fdcbb709827 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -208,7 +208,7 @@ good_area: | |||
208 | * than endlessly redo the fault. | 208 | * than endlessly redo the fault. |
209 | */ | 209 | */ |
210 | survive: | 210 | survive: |
211 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11)); | 211 | fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, (fsr & (1 << 11)) ? FAULT_FLAG_WRITE : 0); |
212 | if (unlikely(fault & VM_FAULT_ERROR)) { | 212 | if (unlikely(fault & VM_FAULT_ERROR)) { |
213 | if (fault & VM_FAULT_OOM) | 213 | if (fault & VM_FAULT_OOM) |
214 | goto out_of_memory; | 214 | goto out_of_memory; |
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index 62d4abbaa654..b61d86d3debf 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c | |||
@@ -133,7 +133,7 @@ good_area: | |||
133 | * fault. | 133 | * fault. |
134 | */ | 134 | */ |
135 | survive: | 135 | survive: |
136 | fault = handle_mm_fault(mm, vma, address, writeaccess); | 136 | fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); |
137 | if (unlikely(fault & VM_FAULT_ERROR)) { | 137 | if (unlikely(fault & VM_FAULT_ERROR)) { |
138 | if (fault & VM_FAULT_OOM) | 138 | if (fault & VM_FAULT_OOM) |
139 | goto out_of_memory; | 139 | goto out_of_memory; |
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c index c4c76db90f9c..f925115e3250 100644 --- a/arch/cris/mm/fault.c +++ b/arch/cris/mm/fault.c | |||
@@ -163,7 +163,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs, | |||
163 | * the fault. | 163 | * the fault. |
164 | */ | 164 | */ |
165 | 165 | ||
166 | fault = handle_mm_fault(mm, vma, address, writeaccess & 1); | 166 | fault = handle_mm_fault(mm, vma, address, (writeaccess & 1) ? FAULT_FLAG_WRITE : 0); |
167 | if (unlikely(fault & VM_FAULT_ERROR)) { | 167 | if (unlikely(fault & VM_FAULT_ERROR)) { |
168 | if (fault & VM_FAULT_OOM) | 168 | if (fault & VM_FAULT_OOM) |
169 | goto out_of_memory; | 169 | goto out_of_memory; |
diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 05093d41d98e..30f5d100a81c 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c | |||
@@ -163,7 +163,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear | |||
163 | * make sure we exit gracefully rather than endlessly redo | 163 | * make sure we exit gracefully rather than endlessly redo |
164 | * the fault. | 164 | * the fault. |
165 | */ | 165 | */ |
166 | fault = handle_mm_fault(mm, vma, ear0, write); | 166 | fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0); |
167 | if (unlikely(fault & VM_FAULT_ERROR)) { | 167 | if (unlikely(fault & VM_FAULT_ERROR)) { |
168 | if (fault & VM_FAULT_OOM) | 168 | if (fault & VM_FAULT_OOM) |
169 | goto out_of_memory; | 169 | goto out_of_memory; |
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 23088bed111e..19261a99e623 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c | |||
@@ -154,7 +154,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re | |||
154 | * sure we exit gracefully rather than endlessly redo the | 154 | * sure we exit gracefully rather than endlessly redo the |
155 | * fault. | 155 | * fault. |
156 | */ | 156 | */ |
157 | fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) != 0); | 157 | fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0); |
158 | if (unlikely(fault & VM_FAULT_ERROR)) { | 158 | if (unlikely(fault & VM_FAULT_ERROR)) { |
159 | /* | 159 | /* |
160 | * We ran out of memory, or some other thing happened | 160 | * We ran out of memory, or some other thing happened |
diff --git a/arch/m32r/mm/fault.c b/arch/m32r/mm/fault.c index 4a71df4c1b30..7274b47f4c22 100644 --- a/arch/m32r/mm/fault.c +++ b/arch/m32r/mm/fault.c | |||
@@ -196,7 +196,7 @@ survive: | |||
196 | */ | 196 | */ |
197 | addr = (address & PAGE_MASK); | 197 | addr = (address & PAGE_MASK); |
198 | set_thread_fault_code(error_code); | 198 | set_thread_fault_code(error_code); |
199 | fault = handle_mm_fault(mm, vma, addr, write); | 199 | fault = handle_mm_fault(mm, vma, addr, write ? FAULT_FLAG_WRITE : 0); |
200 | if (unlikely(fault & VM_FAULT_ERROR)) { | 200 | if (unlikely(fault & VM_FAULT_ERROR)) { |
201 | if (fault & VM_FAULT_OOM) | 201 | if (fault & VM_FAULT_OOM) |
202 | goto out_of_memory; | 202 | goto out_of_memory; |
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index f493f03231d5..d0e35cf99fc6 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c | |||
@@ -155,7 +155,7 @@ good_area: | |||
155 | */ | 155 | */ |
156 | 156 | ||
157 | survive: | 157 | survive: |
158 | fault = handle_mm_fault(mm, vma, address, write); | 158 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
159 | #ifdef DEBUG | 159 | #ifdef DEBUG |
160 | printk("handle_mm_fault returns %d\n",fault); | 160 | printk("handle_mm_fault returns %d\n",fault); |
161 | #endif | 161 | #endif |
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c index 5e67cd1fab40..956607a63f4c 100644 --- a/arch/microblaze/mm/fault.c +++ b/arch/microblaze/mm/fault.c | |||
@@ -232,7 +232,7 @@ good_area: | |||
232 | * the fault. | 232 | * the fault. |
233 | */ | 233 | */ |
234 | survive: | 234 | survive: |
235 | fault = handle_mm_fault(mm, vma, address, is_write); | 235 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); |
236 | if (unlikely(fault & VM_FAULT_ERROR)) { | 236 | if (unlikely(fault & VM_FAULT_ERROR)) { |
237 | if (fault & VM_FAULT_OOM) | 237 | if (fault & VM_FAULT_OOM) |
238 | goto out_of_memory; | 238 | goto out_of_memory; |
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 55767ad9f00e..6751ce9ede9e 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c | |||
@@ -102,7 +102,7 @@ good_area: | |||
102 | * make sure we exit gracefully rather than endlessly redo | 102 | * make sure we exit gracefully rather than endlessly redo |
103 | * the fault. | 103 | * the fault. |
104 | */ | 104 | */ |
105 | fault = handle_mm_fault(mm, vma, address, write); | 105 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
106 | if (unlikely(fault & VM_FAULT_ERROR)) { | 106 | if (unlikely(fault & VM_FAULT_ERROR)) { |
107 | if (fault & VM_FAULT_OOM) | 107 | if (fault & VM_FAULT_OOM) |
108 | goto out_of_memory; | 108 | goto out_of_memory; |
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c index 33cf25025dac..a62e1e138bc1 100644 --- a/arch/mn10300/mm/fault.c +++ b/arch/mn10300/mm/fault.c | |||
@@ -258,7 +258,7 @@ good_area: | |||
258 | * make sure we exit gracefully rather than endlessly redo | 258 | * make sure we exit gracefully rather than endlessly redo |
259 | * the fault. | 259 | * the fault. |
260 | */ | 260 | */ |
261 | fault = handle_mm_fault(mm, vma, address, write); | 261 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
262 | if (unlikely(fault & VM_FAULT_ERROR)) { | 262 | if (unlikely(fault & VM_FAULT_ERROR)) { |
263 | if (fault & VM_FAULT_OOM) | 263 | if (fault & VM_FAULT_OOM) |
264 | goto out_of_memory; | 264 | goto out_of_memory; |
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 92c7fa4ecc3f..bfb6dd6ab380 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c | |||
@@ -202,7 +202,7 @@ good_area: | |||
202 | * fault. | 202 | * fault. |
203 | */ | 203 | */ |
204 | 204 | ||
205 | fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0); | 205 | fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0); |
206 | if (unlikely(fault & VM_FAULT_ERROR)) { | 206 | if (unlikely(fault & VM_FAULT_ERROR)) { |
207 | /* | 207 | /* |
208 | * We hit a shared mapping outside of the file, or some | 208 | * We hit a shared mapping outside of the file, or some |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 5beffc8f481e..830bef0a1131 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -302,7 +302,7 @@ good_area: | |||
302 | * the fault. | 302 | * the fault. |
303 | */ | 303 | */ |
304 | survive: | 304 | survive: |
305 | ret = handle_mm_fault(mm, vma, address, is_write); | 305 | ret = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); |
306 | if (unlikely(ret & VM_FAULT_ERROR)) { | 306 | if (unlikely(ret & VM_FAULT_ERROR)) { |
307 | if (ret & VM_FAULT_OOM) | 307 | if (ret & VM_FAULT_OOM) |
308 | goto out_of_memory; | 308 | goto out_of_memory; |
diff --git a/arch/powerpc/platforms/cell/spu_fault.c b/arch/powerpc/platforms/cell/spu_fault.c index 95d8dadf2d87..d06ba87f1a19 100644 --- a/arch/powerpc/platforms/cell/spu_fault.c +++ b/arch/powerpc/platforms/cell/spu_fault.c | |||
@@ -70,7 +70,7 @@ int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, | |||
70 | } | 70 | } |
71 | 71 | ||
72 | ret = 0; | 72 | ret = 0; |
73 | *flt = handle_mm_fault(mm, vma, ea, is_write); | 73 | *flt = handle_mm_fault(mm, vma, ea, is_write ? FAULT_FLAG_WRITE : 0); |
74 | if (unlikely(*flt & VM_FAULT_ERROR)) { | 74 | if (unlikely(*flt & VM_FAULT_ERROR)) { |
75 | if (*flt & VM_FAULT_OOM) { | 75 | if (*flt & VM_FAULT_OOM) { |
76 | ret = -ENOMEM; | 76 | ret = -ENOMEM; |
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index b0b84c35b0ad..cb5d59eab0ee 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -66,7 +66,7 @@ static int __handle_fault(struct mm_struct *mm, unsigned long address, | |||
66 | } | 66 | } |
67 | 67 | ||
68 | survive: | 68 | survive: |
69 | fault = handle_mm_fault(mm, vma, address, write_access); | 69 | fault = handle_mm_fault(mm, vma, address, write_access ? FAULT_FLAG_WRITE : 0); |
70 | if (unlikely(fault & VM_FAULT_ERROR)) { | 70 | if (unlikely(fault & VM_FAULT_ERROR)) { |
71 | if (fault & VM_FAULT_OOM) | 71 | if (fault & VM_FAULT_OOM) |
72 | goto out_of_memory; | 72 | goto out_of_memory; |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 220a152c836c..74eb26bf1970 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -352,7 +352,7 @@ good_area: | |||
352 | * make sure we exit gracefully rather than endlessly redo | 352 | * make sure we exit gracefully rather than endlessly redo |
353 | * the fault. | 353 | * the fault. |
354 | */ | 354 | */ |
355 | fault = handle_mm_fault(mm, vma, address, write); | 355 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
356 | if (unlikely(fault & VM_FAULT_ERROR)) { | 356 | if (unlikely(fault & VM_FAULT_ERROR)) { |
357 | if (fault & VM_FAULT_OOM) { | 357 | if (fault & VM_FAULT_OOM) { |
358 | up_read(&mm->mmap_sem); | 358 | up_read(&mm->mmap_sem); |
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 2c50f80fc332..cc8ddbdf3d7a 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c | |||
@@ -133,7 +133,7 @@ good_area: | |||
133 | * the fault. | 133 | * the fault. |
134 | */ | 134 | */ |
135 | survive: | 135 | survive: |
136 | fault = handle_mm_fault(mm, vma, address, writeaccess); | 136 | fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); |
137 | if (unlikely(fault & VM_FAULT_ERROR)) { | 137 | if (unlikely(fault & VM_FAULT_ERROR)) { |
138 | if (fault & VM_FAULT_OOM) | 138 | if (fault & VM_FAULT_OOM) |
139 | goto out_of_memory; | 139 | goto out_of_memory; |
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index 7876997ba19a..fcbb6e135cef 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c | |||
@@ -187,7 +187,7 @@ good_area: | |||
187 | * the fault. | 187 | * the fault. |
188 | */ | 188 | */ |
189 | survive: | 189 | survive: |
190 | fault = handle_mm_fault(mm, vma, address, writeaccess); | 190 | fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); |
191 | if (unlikely(fault & VM_FAULT_ERROR)) { | 191 | if (unlikely(fault & VM_FAULT_ERROR)) { |
192 | if (fault & VM_FAULT_OOM) | 192 | if (fault & VM_FAULT_OOM) |
193 | goto out_of_memory; | 193 | goto out_of_memory; |
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c index 12e447fc8542..a5e30c642ee3 100644 --- a/arch/sparc/mm/fault_32.c +++ b/arch/sparc/mm/fault_32.c | |||
@@ -241,7 +241,7 @@ good_area: | |||
241 | * make sure we exit gracefully rather than endlessly redo | 241 | * make sure we exit gracefully rather than endlessly redo |
242 | * the fault. | 242 | * the fault. |
243 | */ | 243 | */ |
244 | fault = handle_mm_fault(mm, vma, address, write); | 244 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
245 | if (unlikely(fault & VM_FAULT_ERROR)) { | 245 | if (unlikely(fault & VM_FAULT_ERROR)) { |
246 | if (fault & VM_FAULT_OOM) | 246 | if (fault & VM_FAULT_OOM) |
247 | goto out_of_memory; | 247 | goto out_of_memory; |
@@ -484,7 +484,7 @@ good_area: | |||
484 | if(!(vma->vm_flags & (VM_READ | VM_EXEC))) | 484 | if(!(vma->vm_flags & (VM_READ | VM_EXEC))) |
485 | goto bad_area; | 485 | goto bad_area; |
486 | } | 486 | } |
487 | switch (handle_mm_fault(mm, vma, address, write)) { | 487 | switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) { |
488 | case VM_FAULT_SIGBUS: | 488 | case VM_FAULT_SIGBUS: |
489 | case VM_FAULT_OOM: | 489 | case VM_FAULT_OOM: |
490 | goto do_sigbus; | 490 | goto do_sigbus; |
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 4ab8993b0863..e5620b27c8bf 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -398,7 +398,7 @@ good_area: | |||
398 | goto bad_area; | 398 | goto bad_area; |
399 | } | 399 | } |
400 | 400 | ||
401 | fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE)); | 401 | fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0); |
402 | if (unlikely(fault & VM_FAULT_ERROR)) { | 402 | if (unlikely(fault & VM_FAULT_ERROR)) { |
403 | if (fault & VM_FAULT_OOM) | 403 | if (fault & VM_FAULT_OOM) |
404 | goto out_of_memory; | 404 | goto out_of_memory; |
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 7384d8accfe7..637c6505dc00 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c | |||
@@ -65,7 +65,7 @@ good_area: | |||
65 | do { | 65 | do { |
66 | int fault; | 66 | int fault; |
67 | 67 | ||
68 | fault = handle_mm_fault(mm, vma, address, is_write); | 68 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); |
69 | if (unlikely(fault & VM_FAULT_ERROR)) { | 69 | if (unlikely(fault & VM_FAULT_ERROR)) { |
70 | if (fault & VM_FAULT_OOM) { | 70 | if (fault & VM_FAULT_OOM) { |
71 | goto out_of_memory; | 71 | goto out_of_memory; |
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index caba99601703..eb0566e83319 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S | |||
@@ -845,7 +845,7 @@ ENTRY(aesni_cbc_enc) | |||
845 | */ | 845 | */ |
846 | ENTRY(aesni_cbc_dec) | 846 | ENTRY(aesni_cbc_dec) |
847 | cmp $16, LEN | 847 | cmp $16, LEN |
848 | jb .Lcbc_dec_ret | 848 | jb .Lcbc_dec_just_ret |
849 | mov 480(KEYP), KLEN | 849 | mov 480(KEYP), KLEN |
850 | add $240, KEYP | 850 | add $240, KEYP |
851 | movups (IVP), IV | 851 | movups (IVP), IV |
@@ -891,6 +891,7 @@ ENTRY(aesni_cbc_dec) | |||
891 | add $16, OUTP | 891 | add $16, OUTP |
892 | cmp $16, LEN | 892 | cmp $16, LEN |
893 | jge .Lcbc_dec_loop1 | 893 | jge .Lcbc_dec_loop1 |
894 | movups IV, (IVP) | ||
895 | .Lcbc_dec_ret: | 894 | .Lcbc_dec_ret: |
895 | movups IV, (IVP) | ||
896 | .Lcbc_dec_just_ret: | ||
896 | ret | 897 | ret |
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 4e663398f77f..c580c5ec1cad 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c | |||
@@ -198,6 +198,7 @@ static int ecb_encrypt(struct blkcipher_desc *desc, | |||
198 | 198 | ||
199 | blkcipher_walk_init(&walk, dst, src, nbytes); | 199 | blkcipher_walk_init(&walk, dst, src, nbytes); |
200 | err = blkcipher_walk_virt(desc, &walk); | 200 | err = blkcipher_walk_virt(desc, &walk); |
201 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
201 | 202 | ||
202 | kernel_fpu_begin(); | 203 | kernel_fpu_begin(); |
203 | while ((nbytes = walk.nbytes)) { | 204 | while ((nbytes = walk.nbytes)) { |
@@ -221,6 +222,7 @@ static int ecb_decrypt(struct blkcipher_desc *desc, | |||
221 | 222 | ||
222 | blkcipher_walk_init(&walk, dst, src, nbytes); | 223 | blkcipher_walk_init(&walk, dst, src, nbytes); |
223 | err = blkcipher_walk_virt(desc, &walk); | 224 | err = blkcipher_walk_virt(desc, &walk); |
225 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
224 | 226 | ||
225 | kernel_fpu_begin(); | 227 | kernel_fpu_begin(); |
226 | while ((nbytes = walk.nbytes)) { | 228 | while ((nbytes = walk.nbytes)) { |
@@ -266,6 +268,7 @@ static int cbc_encrypt(struct blkcipher_desc *desc, | |||
266 | 268 | ||
267 | blkcipher_walk_init(&walk, dst, src, nbytes); | 269 | blkcipher_walk_init(&walk, dst, src, nbytes); |
268 | err = blkcipher_walk_virt(desc, &walk); | 270 | err = blkcipher_walk_virt(desc, &walk); |
271 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
269 | 272 | ||
270 | kernel_fpu_begin(); | 273 | kernel_fpu_begin(); |
271 | while ((nbytes = walk.nbytes)) { | 274 | while ((nbytes = walk.nbytes)) { |
@@ -289,6 +292,7 @@ static int cbc_decrypt(struct blkcipher_desc *desc, | |||
289 | 292 | ||
290 | blkcipher_walk_init(&walk, dst, src, nbytes); | 293 | blkcipher_walk_init(&walk, dst, src, nbytes); |
291 | err = blkcipher_walk_virt(desc, &walk); | 294 | err = blkcipher_walk_virt(desc, &walk); |
295 | desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; | ||
292 | 296 | ||
293 | kernel_fpu_begin(); | 297 | kernel_fpu_begin(); |
294 | while ((nbytes = walk.nbytes)) { | 298 | while ((nbytes = walk.nbytes)) { |
diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c index 5f9781a3815f..daef6cd2b45d 100644 --- a/arch/x86/crypto/fpu.c +++ b/arch/x86/crypto/fpu.c | |||
@@ -48,7 +48,7 @@ static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in, | |||
48 | struct blkcipher_desc desc = { | 48 | struct blkcipher_desc desc = { |
49 | .tfm = child, | 49 | .tfm = child, |
50 | .info = desc_in->info, | 50 | .info = desc_in->info, |
51 | .flags = desc_in->flags, | 51 | .flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP, |
52 | }; | 52 | }; |
53 | 53 | ||
54 | kernel_fpu_begin(); | 54 | kernel_fpu_begin(); |
@@ -67,7 +67,7 @@ static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in, | |||
67 | struct blkcipher_desc desc = { | 67 | struct blkcipher_desc desc = { |
68 | .tfm = child, | 68 | .tfm = child, |
69 | .info = desc_in->info, | 69 | .info = desc_in->info, |
70 | .flags = desc_in->flags, | 70 | .flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP, |
71 | }; | 71 | }; |
72 | 72 | ||
73 | kernel_fpu_begin(); | 73 | kernel_fpu_begin(); |
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 02ecb30982a3..103f1ddb0d85 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #else /* ...!ASSEMBLY */ | 43 | #else /* ...!ASSEMBLY */ |
44 | 44 | ||
45 | #include <linux/kernel.h> | ||
45 | #include <linux/stringify.h> | 46 | #include <linux/stringify.h> |
46 | 47 | ||
47 | #ifdef CONFIG_SMP | 48 | #ifdef CONFIG_SMP |
@@ -155,6 +156,15 @@ do { \ | |||
155 | /* We can use this directly for local CPU (faster). */ | 156 | /* We can use this directly for local CPU (faster). */ |
156 | DECLARE_PER_CPU(unsigned long, this_cpu_off); | 157 | DECLARE_PER_CPU(unsigned long, this_cpu_off); |
157 | 158 | ||
159 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
160 | void *pcpu_lpage_remapped(void *kaddr); | ||
161 | #else | ||
162 | static inline void *pcpu_lpage_remapped(void *kaddr) | ||
163 | { | ||
164 | return NULL; | ||
165 | } | ||
166 | #endif | ||
167 | |||
158 | #endif /* !__ASSEMBLY__ */ | 168 | #endif /* !__ASSEMBLY__ */ |
159 | 169 | ||
160 | #ifdef CONFIG_SMP | 170 | #ifdef CONFIG_SMP |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 9c3f0823e6aa..29a3eef7cf4a 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
@@ -124,7 +124,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* | 126 | /* |
127 | * Remap allocator | 127 | * Large page remap allocator |
128 | * | 128 | * |
129 | * This allocator uses PMD page as unit. A PMD page is allocated for | 129 | * This allocator uses PMD page as unit. A PMD page is allocated for |
130 | * each cpu and each is remapped into vmalloc area using PMD mapping. | 130 | * each cpu and each is remapped into vmalloc area using PMD mapping. |
@@ -137,105 +137,185 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, | |||
137 | * better than only using 4k mappings while still being NUMA friendly. | 137 | * better than only using 4k mappings while still being NUMA friendly. |
138 | */ | 138 | */ |
139 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 139 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
140 | static size_t pcpur_size __initdata; | 140 | struct pcpul_ent { |
141 | static void **pcpur_ptrs __initdata; | 141 | unsigned int cpu; |
142 | void *ptr; | ||
143 | }; | ||
144 | |||
145 | static size_t pcpul_size; | ||
146 | static struct pcpul_ent *pcpul_map; | ||
147 | static struct vm_struct pcpul_vm; | ||
142 | 148 | ||
143 | static struct page * __init pcpur_get_page(unsigned int cpu, int pageno) | 149 | static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) |
144 | { | 150 | { |
145 | size_t off = (size_t)pageno << PAGE_SHIFT; | 151 | size_t off = (size_t)pageno << PAGE_SHIFT; |
146 | 152 | ||
147 | if (off >= pcpur_size) | 153 | if (off >= pcpul_size) |
148 | return NULL; | 154 | return NULL; |
149 | 155 | ||
150 | return virt_to_page(pcpur_ptrs[cpu] + off); | 156 | return virt_to_page(pcpul_map[cpu].ptr + off); |
151 | } | 157 | } |
152 | 158 | ||
153 | static ssize_t __init setup_pcpu_remap(size_t static_size) | 159 | static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) |
154 | { | 160 | { |
155 | static struct vm_struct vm; | 161 | size_t map_size, dyn_size; |
156 | size_t ptrs_size, dyn_size; | ||
157 | unsigned int cpu; | 162 | unsigned int cpu; |
163 | int i, j; | ||
158 | ssize_t ret; | 164 | ssize_t ret; |
159 | 165 | ||
160 | /* | 166 | if (!chosen) { |
161 | * If large page isn't supported, there's no benefit in doing | 167 | size_t vm_size = VMALLOC_END - VMALLOC_START; |
162 | * this. Also, on non-NUMA, embedding is better. | 168 | size_t tot_size = num_possible_cpus() * PMD_SIZE; |
163 | * | 169 | |
164 | * NOTE: disabled for now. | 170 | /* on non-NUMA, embedding is better */ |
165 | */ | 171 | if (!pcpu_need_numa()) |
166 | if (true || !cpu_has_pse || !pcpu_need_numa()) | 172 | return -EINVAL; |
173 | |||
174 | /* don't consume more than 20% of vmalloc area */ | ||
175 | if (tot_size > vm_size / 5) { | ||
176 | pr_info("PERCPU: too large chunk size %zuMB for " | ||
177 | "large page remap\n", tot_size >> 20); | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /* need PSE */ | ||
183 | if (!cpu_has_pse) { | ||
184 | pr_warning("PERCPU: lpage allocator requires PSE\n"); | ||
167 | return -EINVAL; | 185 | return -EINVAL; |
186 | } | ||
168 | 187 | ||
169 | /* | 188 | /* |
170 | * Currently supports only single page. Supporting multiple | 189 | * Currently supports only single page. Supporting multiple |
171 | * pages won't be too difficult if it ever becomes necessary. | 190 | * pages won't be too difficult if it ever becomes necessary. |
172 | */ | 191 | */ |
173 | pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + | 192 | pcpul_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + |
174 | PERCPU_DYNAMIC_RESERVE); | 193 | PERCPU_DYNAMIC_RESERVE); |
175 | if (pcpur_size > PMD_SIZE) { | 194 | if (pcpul_size > PMD_SIZE) { |
176 | pr_warning("PERCPU: static data is larger than large page, " | 195 | pr_warning("PERCPU: static data is larger than large page, " |
177 | "can't use large page\n"); | 196 | "can't use large page\n"); |
178 | return -EINVAL; | 197 | return -EINVAL; |
179 | } | 198 | } |
180 | dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; | 199 | dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; |
181 | 200 | ||
182 | /* allocate pointer array and alloc large pages */ | 201 | /* allocate pointer array and alloc large pages */ |
183 | ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); | 202 | map_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpul_map[0])); |
184 | pcpur_ptrs = alloc_bootmem(ptrs_size); | 203 | pcpul_map = alloc_bootmem(map_size); |
185 | 204 | ||
186 | for_each_possible_cpu(cpu) { | 205 | for_each_possible_cpu(cpu) { |
187 | pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); | 206 | pcpul_map[cpu].cpu = cpu; |
188 | if (!pcpur_ptrs[cpu]) | 207 | pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE, |
208 | PMD_SIZE); | ||
209 | if (!pcpul_map[cpu].ptr) { | ||
210 | pr_warning("PERCPU: failed to allocate large page " | ||
211 | "for cpu%u\n", cpu); | ||
189 | goto enomem; | 212 | goto enomem; |
213 | } | ||
190 | 214 | ||
191 | /* | 215 | /* |
192 | * Only use pcpur_size bytes and give back the rest. | 216 | * Only use pcpul_size bytes and give back the rest. |
193 | * | 217 | * |
194 | * Ingo: The 2MB up-rounding bootmem is needed to make | 218 | * Ingo: The 2MB up-rounding bootmem is needed to make |
195 | * sure the partial 2MB page is still fully RAM - it's | 219 | * sure the partial 2MB page is still fully RAM - it's |
196 | * not well-specified to have a PAT-incompatible area | 220 | * not well-specified to have a PAT-incompatible area |
197 | * (unmapped RAM, device memory, etc.) in that hole. | 221 | * (unmapped RAM, device memory, etc.) in that hole. |
198 | */ | 222 | */ |
199 | free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size), | 223 | free_bootmem(__pa(pcpul_map[cpu].ptr + pcpul_size), |
200 | PMD_SIZE - pcpur_size); | 224 | PMD_SIZE - pcpul_size); |
201 | 225 | ||
202 | memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size); | 226 | memcpy(pcpul_map[cpu].ptr, __per_cpu_load, static_size); |
203 | } | 227 | } |
204 | 228 | ||
205 | /* allocate address and map */ | 229 | /* allocate address and map */ |
206 | vm.flags = VM_ALLOC; | 230 | pcpul_vm.flags = VM_ALLOC; |
207 | vm.size = num_possible_cpus() * PMD_SIZE; | 231 | pcpul_vm.size = num_possible_cpus() * PMD_SIZE; |
208 | vm_area_register_early(&vm, PMD_SIZE); | 232 | vm_area_register_early(&pcpul_vm, PMD_SIZE); |
209 | 233 | ||
210 | for_each_possible_cpu(cpu) { | 234 | for_each_possible_cpu(cpu) { |
211 | pmd_t *pmd; | 235 | pmd_t *pmd, pmd_v; |
212 | 236 | ||
213 | pmd = populate_extra_pmd((unsigned long)vm.addr | 237 | pmd = populate_extra_pmd((unsigned long)pcpul_vm.addr + |
214 | + cpu * PMD_SIZE); | 238 | cpu * PMD_SIZE); |
215 | set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])), | 239 | pmd_v = pfn_pmd(page_to_pfn(virt_to_page(pcpul_map[cpu].ptr)), |
216 | PAGE_KERNEL_LARGE)); | 240 | PAGE_KERNEL_LARGE); |
241 | set_pmd(pmd, pmd_v); | ||
217 | } | 242 | } |
218 | 243 | ||
219 | /* we're ready, commit */ | 244 | /* we're ready, commit */ |
220 | pr_info("PERCPU: Remapped at %p with large pages, static data " | 245 | pr_info("PERCPU: Remapped at %p with large pages, static data " |
221 | "%zu bytes\n", vm.addr, static_size); | 246 | "%zu bytes\n", pcpul_vm.addr, static_size); |
222 | 247 | ||
223 | ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, | 248 | ret = pcpu_setup_first_chunk(pcpul_get_page, static_size, |
224 | PERCPU_FIRST_CHUNK_RESERVE, dyn_size, | 249 | PERCPU_FIRST_CHUNK_RESERVE, dyn_size, |
225 | PMD_SIZE, vm.addr, NULL); | 250 | PMD_SIZE, pcpul_vm.addr, NULL); |
226 | goto out_free_ar; | 251 | |
252 | /* sort pcpul_map array for pcpu_lpage_remapped() */ | ||
253 | for (i = 0; i < num_possible_cpus() - 1; i++) | ||
254 | for (j = i + 1; j < num_possible_cpus(); j++) | ||
255 | if (pcpul_map[i].ptr > pcpul_map[j].ptr) { | ||
256 | struct pcpul_ent tmp = pcpul_map[i]; | ||
257 | pcpul_map[i] = pcpul_map[j]; | ||
258 | pcpul_map[j] = tmp; | ||
259 | } | ||
260 | |||
261 | return ret; | ||
227 | 262 | ||
228 | enomem: | 263 | enomem: |
229 | for_each_possible_cpu(cpu) | 264 | for_each_possible_cpu(cpu) |
230 | if (pcpur_ptrs[cpu]) | 265 | if (pcpul_map[cpu].ptr) |
231 | free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE); | 266 | free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size); |
232 | ret = -ENOMEM; | 267 | free_bootmem(__pa(pcpul_map), map_size); |
233 | out_free_ar: | 268 | return -ENOMEM; |
234 | free_bootmem(__pa(pcpur_ptrs), ptrs_size); | 269 | } |
235 | return ret; | 270 | |
271 | /** | ||
272 | * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area | ||
273 | * @kaddr: the kernel address in question | ||
274 | * | ||
275 | * Determine whether @kaddr falls in the pcpul recycled area. This is | ||
276 | * used by pageattr to detect VM aliases and break up the pcpu PMD | ||
277 | * mapping such that the same physical page is not mapped under | ||
278 | * different attributes. | ||
279 | * | ||
280 | * The recycled area is always at the tail of a partially used PMD | ||
281 | * page. | ||
282 | * | ||
283 | * RETURNS: | ||
284 | * Address of corresponding remapped pcpu address if match is found; | ||
285 | * otherwise, NULL. | ||
286 | */ | ||
287 | void *pcpu_lpage_remapped(void *kaddr) | ||
288 | { | ||
289 | void *pmd_addr = (void *)((unsigned long)kaddr & PMD_MASK); | ||
290 | unsigned long offset = (unsigned long)kaddr & ~PMD_MASK; | ||
291 | int left = 0, right = num_possible_cpus() - 1; | ||
292 | int pos; | ||
293 | |||
294 | /* pcpul in use at all? */ | ||
295 | if (!pcpul_map) | ||
296 | return NULL; | ||
297 | |||
298 | /* okay, perform binary search */ | ||
299 | while (left <= right) { | ||
300 | pos = (left + right) / 2; | ||
301 | |||
302 | if (pcpul_map[pos].ptr < pmd_addr) | ||
303 | left = pos + 1; | ||
304 | else if (pcpul_map[pos].ptr > pmd_addr) | ||
305 | right = pos - 1; | ||
306 | else { | ||
307 | /* it shouldn't be in the area for the first chunk */ | ||
308 | WARN_ON(offset < pcpul_size); | ||
309 | |||
310 | return pcpul_vm.addr + | ||
311 | pcpul_map[pos].cpu * PMD_SIZE + offset; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | return NULL; | ||
236 | } | 316 | } |
237 | #else | 317 | #else |
238 | static ssize_t __init setup_pcpu_remap(size_t static_size) | 318 | static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) |
239 | { | 319 | { |
240 | return -EINVAL; | 320 | return -EINVAL; |
241 | } | 321 | } |
@@ -249,7 +329,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) | |||
249 | * mapping so that it can use PMD mapping without additional TLB | 329 | * mapping so that it can use PMD mapping without additional TLB |
250 | * pressure. | 330 | * pressure. |
251 | */ | 331 | */ |
252 | static ssize_t __init setup_pcpu_embed(size_t static_size) | 332 | static ssize_t __init setup_pcpu_embed(size_t static_size, bool chosen) |
253 | { | 333 | { |
254 | size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; | 334 | size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; |
255 | 335 | ||
@@ -258,7 +338,7 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) | |||
258 | * this. Also, embedding allocation doesn't play well with | 338 | * this. Also, embedding allocation doesn't play well with |
259 | * NUMA. | 339 | * NUMA. |
260 | */ | 340 | */ |
261 | if (!cpu_has_pse || pcpu_need_numa()) | 341 | if (!chosen && (!cpu_has_pse || pcpu_need_numa())) |
262 | return -EINVAL; | 342 | return -EINVAL; |
263 | 343 | ||
264 | return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, | 344 | return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, |
@@ -308,8 +388,11 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) | |||
308 | void *ptr; | 388 | void *ptr; |
309 | 389 | ||
310 | ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); | 390 | ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); |
311 | if (!ptr) | 391 | if (!ptr) { |
392 | pr_warning("PERCPU: failed to allocate " | ||
393 | "4k page for cpu%u\n", cpu); | ||
312 | goto enomem; | 394 | goto enomem; |
395 | } | ||
313 | 396 | ||
314 | memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); | 397 | memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); |
315 | pcpu4k_pages[j++] = virt_to_page(ptr); | 398 | pcpu4k_pages[j++] = virt_to_page(ptr); |
@@ -333,6 +416,16 @@ out_free_ar: | |||
333 | return ret; | 416 | return ret; |
334 | } | 417 | } |
335 | 418 | ||
419 | /* for explicit first chunk allocator selection */ | ||
420 | static char pcpu_chosen_alloc[16] __initdata; | ||
421 | |||
422 | static int __init percpu_alloc_setup(char *str) | ||
423 | { | ||
424 | strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1); | ||
425 | return 0; | ||
426 | } | ||
427 | early_param("percpu_alloc", percpu_alloc_setup); | ||
428 | |||
336 | static inline void setup_percpu_segment(int cpu) | 429 | static inline void setup_percpu_segment(int cpu) |
337 | { | 430 | { |
338 | #ifdef CONFIG_X86_32 | 431 | #ifdef CONFIG_X86_32 |
@@ -346,11 +439,6 @@ static inline void setup_percpu_segment(int cpu) | |||
346 | #endif | 439 | #endif |
347 | } | 440 | } |
348 | 441 | ||
349 | /* | ||
350 | * Great future plan: | ||
351 | * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. | ||
352 | * Always point %gs to its beginning | ||
353 | */ | ||
354 | void __init setup_per_cpu_areas(void) | 442 | void __init setup_per_cpu_areas(void) |
355 | { | 443 | { |
356 | size_t static_size = __per_cpu_end - __per_cpu_start; | 444 | size_t static_size = __per_cpu_end - __per_cpu_start; |
@@ -367,9 +455,26 @@ void __init setup_per_cpu_areas(void) | |||
367 | * of large page mappings. Please read comments on top of | 455 | * of large page mappings. Please read comments on top of |
368 | * each allocator for details. | 456 | * each allocator for details. |
369 | */ | 457 | */ |
370 | ret = setup_pcpu_remap(static_size); | 458 | ret = -EINVAL; |
371 | if (ret < 0) | 459 | if (strlen(pcpu_chosen_alloc)) { |
372 | ret = setup_pcpu_embed(static_size); | 460 | if (strcmp(pcpu_chosen_alloc, "4k")) { |
461 | if (!strcmp(pcpu_chosen_alloc, "lpage")) | ||
462 | ret = setup_pcpu_lpage(static_size, true); | ||
463 | else if (!strcmp(pcpu_chosen_alloc, "embed")) | ||
464 | ret = setup_pcpu_embed(static_size, true); | ||
465 | else | ||
466 | pr_warning("PERCPU: unknown allocator %s " | ||
467 | "specified\n", pcpu_chosen_alloc); | ||
468 | if (ret < 0) | ||
469 | pr_warning("PERCPU: %s allocator failed (%zd), " | ||
470 | "falling back to 4k\n", | ||
471 | pcpu_chosen_alloc, ret); | ||
472 | } | ||
473 | } else { | ||
474 | ret = setup_pcpu_lpage(static_size, false); | ||
475 | if (ret < 0) | ||
476 | ret = setup_pcpu_embed(static_size, false); | ||
477 | } | ||
373 | if (ret < 0) | 478 | if (ret < 0) |
374 | ret = setup_pcpu_4k(static_size); | 479 | ret = setup_pcpu_4k(static_size); |
375 | if (ret < 0) | 480 | if (ret < 0) |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index c403526d5d15..78a5fff857be 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -1113,7 +1113,7 @@ good_area: | |||
1113 | * make sure we exit gracefully rather than endlessly redo | 1113 | * make sure we exit gracefully rather than endlessly redo |
1114 | * the fault: | 1114 | * the fault: |
1115 | */ | 1115 | */ |
1116 | fault = handle_mm_fault(mm, vma, address, write); | 1116 | fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); |
1117 | 1117 | ||
1118 | if (unlikely(fault & VM_FAULT_ERROR)) { | 1118 | if (unlikely(fault & VM_FAULT_ERROR)) { |
1119 | mm_fault_error(regs, error_code, address, fault); | 1119 | mm_fault_error(regs, error_code, address, fault); |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 3cfe9ced8a4c..1b734d7a8966 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
14 | #include <linux/pfn.h> | ||
14 | 15 | ||
15 | #include <asm/e820.h> | 16 | #include <asm/e820.h> |
16 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
@@ -681,8 +682,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias); | |||
681 | static int cpa_process_alias(struct cpa_data *cpa) | 682 | static int cpa_process_alias(struct cpa_data *cpa) |
682 | { | 683 | { |
683 | struct cpa_data alias_cpa; | 684 | struct cpa_data alias_cpa; |
684 | int ret = 0; | 685 | unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT); |
685 | unsigned long temp_cpa_vaddr, vaddr; | 686 | unsigned long vaddr, remapped; |
687 | int ret; | ||
686 | 688 | ||
687 | if (cpa->pfn >= max_pfn_mapped) | 689 | if (cpa->pfn >= max_pfn_mapped) |
688 | return 0; | 690 | return 0; |
@@ -706,42 +708,55 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
706 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) { | 708 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) { |
707 | 709 | ||
708 | alias_cpa = *cpa; | 710 | alias_cpa = *cpa; |
709 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 711 | alias_cpa.vaddr = &laddr; |
710 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
711 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | 712 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); |
712 | 713 | ||
713 | |||
714 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | 714 | ret = __change_page_attr_set_clr(&alias_cpa, 0); |
715 | if (ret) | ||
716 | return ret; | ||
715 | } | 717 | } |
716 | 718 | ||
717 | #ifdef CONFIG_X86_64 | 719 | #ifdef CONFIG_X86_64 |
718 | if (ret) | ||
719 | return ret; | ||
720 | /* | 720 | /* |
721 | * No need to redo, when the primary call touched the high | 721 | * If the primary call didn't touch the high mapping already |
722 | * mapping already: | 722 | * and the physical address is inside the kernel map, we need |
723 | */ | ||
724 | if (within(vaddr, (unsigned long) _text, _brk_end)) | ||
725 | return 0; | ||
726 | |||
727 | /* | ||
728 | * If the physical address is inside the kernel map, we need | ||
729 | * to touch the high mapped kernel as well: | 723 | * to touch the high mapped kernel as well: |
730 | */ | 724 | */ |
731 | if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) | 725 | if (!within(vaddr, (unsigned long)_text, _brk_end) && |
732 | return 0; | 726 | within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) { |
727 | unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + | ||
728 | __START_KERNEL_map - phys_base; | ||
729 | alias_cpa = *cpa; | ||
730 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
731 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | ||
733 | 732 | ||
734 | alias_cpa = *cpa; | 733 | /* |
735 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; | 734 | * The high mapping range is imprecise, so ignore the |
736 | alias_cpa.vaddr = &temp_cpa_vaddr; | 735 | * return value. |
737 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | 736 | */ |
737 | __change_page_attr_set_clr(&alias_cpa, 0); | ||
738 | } | ||
739 | #endif | ||
738 | 740 | ||
739 | /* | 741 | /* |
740 | * The high mapping range is imprecise, so ignore the return value. | 742 | * If the PMD page was partially used for per-cpu remapping, |
743 | * the recycled area needs to be split and modified. Because | ||
744 | * the area is always proper subset of a PMD page | ||
745 | * cpa->numpages is guaranteed to be 1 for these areas, so | ||
746 | * there's no need to loop over and check for further remaps. | ||
741 | */ | 747 | */ |
742 | __change_page_attr_set_clr(&alias_cpa, 0); | 748 | remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr); |
743 | #endif | 749 | if (remapped) { |
744 | return ret; | 750 | WARN_ON(cpa->numpages > 1); |
751 | alias_cpa = *cpa; | ||
752 | alias_cpa.vaddr = &remapped; | ||
753 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | ||
754 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | ||
755 | if (ret) | ||
756 | return ret; | ||
757 | } | ||
758 | |||
759 | return 0; | ||
745 | } | 760 | } |
746 | 761 | ||
747 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | 762 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) |
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index bdd860d93f72..bc0733359a88 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c | |||
@@ -106,7 +106,7 @@ good_area: | |||
106 | * the fault. | 106 | * the fault. |
107 | */ | 107 | */ |
108 | survive: | 108 | survive: |
109 | fault = handle_mm_fault(mm, vma, address, is_write); | 109 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); |
110 | if (unlikely(fault & VM_FAULT_ERROR)) { | 110 | if (unlikely(fault & VM_FAULT_ERROR)) { |
111 | if (fault & VM_FAULT_OOM) | 111 | if (fault & VM_FAULT_OOM) |
112 | goto out_of_memory; | 112 | goto out_of_memory; |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 87f92c39b5f0..a9952b1236b0 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -18,9 +18,22 @@ | |||
18 | #include <linux/percpu.h> | 18 | #include <linux/percpu.h> |
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <asm/byteorder.h> | 20 | #include <asm/byteorder.h> |
21 | #include <asm/processor.h> | ||
21 | #include <asm/i387.h> | 22 | #include <asm/i387.h> |
22 | #include "padlock.h" | 23 | #include "padlock.h" |
23 | 24 | ||
25 | /* | ||
26 | * Number of data blocks actually fetched for each xcrypt insn. | ||
27 | * Processors with prefetch errata will fetch extra blocks. | ||
28 | */ | ||
29 | static unsigned int ecb_fetch_blocks = 2; | ||
30 | #define MAX_ECB_FETCH_BLOCKS (8) | ||
31 | #define ecb_fetch_bytes (ecb_fetch_blocks * AES_BLOCK_SIZE) | ||
32 | |||
33 | static unsigned int cbc_fetch_blocks = 1; | ||
34 | #define MAX_CBC_FETCH_BLOCKS (4) | ||
35 | #define cbc_fetch_bytes (cbc_fetch_blocks * AES_BLOCK_SIZE) | ||
36 | |||
24 | /* Control word. */ | 37 | /* Control word. */ |
25 | struct cword { | 38 | struct cword { |
26 | unsigned int __attribute__ ((__packed__)) | 39 | unsigned int __attribute__ ((__packed__)) |
@@ -172,73 +185,111 @@ static inline void padlock_store_cword(struct cword *cword) | |||
172 | * should be used only inside the irq_ts_save/restore() context | 185 | * should be used only inside the irq_ts_save/restore() context |
173 | */ | 186 | */ |
174 | 187 | ||
175 | static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key, | 188 | static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key, |
176 | struct cword *control_word) | 189 | struct cword *control_word, int count) |
177 | { | 190 | { |
178 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ | 191 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ |
179 | : "+S"(input), "+D"(output) | 192 | : "+S"(input), "+D"(output) |
180 | : "d"(control_word), "b"(key), "c"(1)); | 193 | : "d"(control_word), "b"(key), "c"(count)); |
194 | } | ||
195 | |||
196 | static inline u8 *rep_xcrypt_cbc(const u8 *input, u8 *output, void *key, | ||
197 | u8 *iv, struct cword *control_word, int count) | ||
198 | { | ||
199 | asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ | ||
200 | : "+S" (input), "+D" (output), "+a" (iv) | ||
201 | : "d" (control_word), "b" (key), "c" (count)); | ||
202 | return iv; | ||
181 | } | 203 | } |
182 | 204 | ||
183 | static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword) | 205 | static void ecb_crypt_copy(const u8 *in, u8 *out, u32 *key, |
206 | struct cword *cword, int count) | ||
184 | { | 207 | { |
185 | u8 buf[AES_BLOCK_SIZE * 2 + PADLOCK_ALIGNMENT - 1]; | 208 | /* |
209 | * Padlock prefetches extra data so we must provide mapped input buffers. | ||
210 | * Assume there are at least 16 bytes of stack already in use. | ||
211 | */ | ||
212 | u8 buf[AES_BLOCK_SIZE * (MAX_ECB_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1]; | ||
213 | u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); | ||
214 | |||
215 | memcpy(tmp, in, count * AES_BLOCK_SIZE); | ||
216 | rep_xcrypt_ecb(tmp, out, key, cword, count); | ||
217 | } | ||
218 | |||
219 | static u8 *cbc_crypt_copy(const u8 *in, u8 *out, u32 *key, | ||
220 | u8 *iv, struct cword *cword, int count) | ||
221 | { | ||
222 | /* | ||
223 | * Padlock prefetches extra data so we must provide mapped input buffers. | ||
224 | * Assume there are at least 16 bytes of stack already in use. | ||
225 | */ | ||
226 | u8 buf[AES_BLOCK_SIZE * (MAX_CBC_FETCH_BLOCKS - 1) + PADLOCK_ALIGNMENT - 1]; | ||
186 | u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); | 227 | u8 *tmp = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT); |
187 | 228 | ||
188 | memcpy(tmp, in, AES_BLOCK_SIZE); | 229 | memcpy(tmp, in, count * AES_BLOCK_SIZE); |
189 | padlock_xcrypt(tmp, out, key, cword); | 230 | return rep_xcrypt_cbc(tmp, out, key, iv, cword, count); |
190 | } | 231 | } |
191 | 232 | ||
192 | static inline void aes_crypt(const u8 *in, u8 *out, u32 *key, | 233 | static inline void ecb_crypt(const u8 *in, u8 *out, u32 *key, |
193 | struct cword *cword) | 234 | struct cword *cword, int count) |
194 | { | 235 | { |
195 | /* padlock_xcrypt requires at least two blocks of data. */ | 236 | /* Padlock in ECB mode fetches at least ecb_fetch_bytes of data. |
196 | if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) & | 237 | * We could avoid some copying here but it's probably not worth it. |
197 | (PAGE_SIZE - 1)))) { | 238 | */ |
198 | aes_crypt_copy(in, out, key, cword); | 239 | if (unlikely(((unsigned long)in & PAGE_SIZE) + ecb_fetch_bytes > PAGE_SIZE)) { |
240 | ecb_crypt_copy(in, out, key, cword, count); | ||
199 | return; | 241 | return; |
200 | } | 242 | } |
201 | 243 | ||
202 | padlock_xcrypt(in, out, key, cword); | 244 | rep_xcrypt_ecb(in, out, key, cword, count); |
245 | } | ||
246 | |||
247 | static inline u8 *cbc_crypt(const u8 *in, u8 *out, u32 *key, | ||
248 | u8 *iv, struct cword *cword, int count) | ||
249 | { | ||
250 | /* Padlock in CBC mode fetches at least cbc_fetch_bytes of data. */ | ||
251 | if (unlikely(((unsigned long)in & PAGE_SIZE) + cbc_fetch_bytes > PAGE_SIZE)) | ||
252 | return cbc_crypt_copy(in, out, key, iv, cword, count); | ||
253 | |||
254 | return rep_xcrypt_cbc(in, out, key, iv, cword, count); | ||
203 | } | 255 | } |
204 | 256 | ||
205 | static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, | 257 | static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, |
206 | void *control_word, u32 count) | 258 | void *control_word, u32 count) |
207 | { | 259 | { |
208 | if (count == 1) { | 260 | u32 initial = count & (ecb_fetch_blocks - 1); |
209 | aes_crypt(input, output, key, control_word); | 261 | |
262 | if (count < ecb_fetch_blocks) { | ||
263 | ecb_crypt(input, output, key, control_word, count); | ||
210 | return; | 264 | return; |
211 | } | 265 | } |
212 | 266 | ||
213 | asm volatile ("test $1, %%cl;" | 267 | if (initial) |
214 | "je 1f;" | 268 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ |
215 | #ifndef CONFIG_X86_64 | 269 | : "+S"(input), "+D"(output) |
216 | "lea -1(%%ecx), %%eax;" | 270 | : "d"(control_word), "b"(key), "c"(initial)); |
217 | "mov $1, %%ecx;" | 271 | |
218 | #else | 272 | asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ |
219 | "lea -1(%%rcx), %%rax;" | ||
220 | "mov $1, %%rcx;" | ||
221 | #endif | ||
222 | ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */ | ||
223 | #ifndef CONFIG_X86_64 | ||
224 | "mov %%eax, %%ecx;" | ||
225 | #else | ||
226 | "mov %%rax, %%rcx;" | ||
227 | #endif | ||
228 | "1:" | ||
229 | ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ | ||
230 | : "+S"(input), "+D"(output) | 273 | : "+S"(input), "+D"(output) |
231 | : "d"(control_word), "b"(key), "c"(count) | 274 | : "d"(control_word), "b"(key), "c"(count - initial)); |
232 | : "ax"); | ||
233 | } | 275 | } |
234 | 276 | ||
235 | static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, | 277 | static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, |
236 | u8 *iv, void *control_word, u32 count) | 278 | u8 *iv, void *control_word, u32 count) |
237 | { | 279 | { |
238 | /* rep xcryptcbc */ | 280 | u32 initial = count & (cbc_fetch_blocks - 1); |
239 | asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" | 281 | |
282 | if (count < cbc_fetch_blocks) | ||
283 | return cbc_crypt(input, output, key, iv, control_word, count); | ||
284 | |||
285 | if (initial) | ||
286 | asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ | ||
287 | : "+S" (input), "+D" (output), "+a" (iv) | ||
288 | : "d" (control_word), "b" (key), "c" (count)); | ||
289 | |||
290 | asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ | ||
240 | : "+S" (input), "+D" (output), "+a" (iv) | 291 | : "+S" (input), "+D" (output), "+a" (iv) |
241 | : "d" (control_word), "b" (key), "c" (count)); | 292 | : "d" (control_word), "b" (key), "c" (count-initial)); |
242 | return iv; | 293 | return iv; |
243 | } | 294 | } |
244 | 295 | ||
@@ -249,7 +300,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | |||
249 | 300 | ||
250 | padlock_reset_key(&ctx->cword.encrypt); | 301 | padlock_reset_key(&ctx->cword.encrypt); |
251 | ts_state = irq_ts_save(); | 302 | ts_state = irq_ts_save(); |
252 | aes_crypt(in, out, ctx->E, &ctx->cword.encrypt); | 303 | ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1); |
253 | irq_ts_restore(ts_state); | 304 | irq_ts_restore(ts_state); |
254 | padlock_store_cword(&ctx->cword.encrypt); | 305 | padlock_store_cword(&ctx->cword.encrypt); |
255 | } | 306 | } |
@@ -261,7 +312,7 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | |||
261 | 312 | ||
262 | padlock_reset_key(&ctx->cword.encrypt); | 313 | padlock_reset_key(&ctx->cword.encrypt); |
263 | ts_state = irq_ts_save(); | 314 | ts_state = irq_ts_save(); |
264 | aes_crypt(in, out, ctx->D, &ctx->cword.decrypt); | 315 | ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1); |
265 | irq_ts_restore(ts_state); | 316 | irq_ts_restore(ts_state); |
266 | padlock_store_cword(&ctx->cword.encrypt); | 317 | padlock_store_cword(&ctx->cword.encrypt); |
267 | } | 318 | } |
@@ -454,6 +505,7 @@ static struct crypto_alg cbc_aes_alg = { | |||
454 | static int __init padlock_init(void) | 505 | static int __init padlock_init(void) |
455 | { | 506 | { |
456 | int ret; | 507 | int ret; |
508 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
457 | 509 | ||
458 | if (!cpu_has_xcrypt) { | 510 | if (!cpu_has_xcrypt) { |
459 | printk(KERN_NOTICE PFX "VIA PadLock not detected.\n"); | 511 | printk(KERN_NOTICE PFX "VIA PadLock not detected.\n"); |
@@ -476,6 +528,12 @@ static int __init padlock_init(void) | |||
476 | 528 | ||
477 | printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); | 529 | printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); |
478 | 530 | ||
531 | if (c->x86 == 6 && c->x86_model == 15 && c->x86_mask == 2) { | ||
532 | ecb_fetch_blocks = MAX_ECB_FETCH_BLOCKS; | ||
533 | cbc_fetch_blocks = MAX_CBC_FETCH_BLOCKS; | ||
534 | printk(KERN_NOTICE PFX "VIA Nano stepping 2 detected: enabling workaround.\n"); | ||
535 | } | ||
536 | |||
479 | out: | 537 | out: |
480 | return ret; | 538 | return ret; |
481 | 539 | ||
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 40111a6d8d5b..891ef18bd77b 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -94,6 +94,31 @@ config MMC_SDHCI_PLTFM | |||
94 | 94 | ||
95 | If unsure, say N. | 95 | If unsure, say N. |
96 | 96 | ||
97 | config MMC_SDHCI_S3C | ||
98 | tristate "SDHCI support on Samsung S3C SoC" | ||
99 | depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX) | ||
100 | help | ||
101 | This selects the Secure Digital Host Controller Interface (SDHCI) | ||
102 | often referrered to as the HSMMC block in some of the Samsung S3C | ||
103 | range of SoC. | ||
104 | |||
105 | Note, due to the problems with DMA, the DMA support is only | ||
106 | available with CONFIG_EXPERIMENTAL is selected. | ||
107 | |||
108 | If you have a controller with this interface, say Y or M here. | ||
109 | |||
110 | If unsure, say N. | ||
111 | |||
112 | config MMC_SDHCI_S3C_DMA | ||
113 | bool "DMA support on S3C SDHCI" | ||
114 | depends on MMC_SDHCI_S3C && EXPERIMENTAL | ||
115 | help | ||
116 | Enable DMA support on the Samsung S3C SDHCI glue. The DMA | ||
117 | has proved to be problematic if the controller encounters | ||
118 | certain errors, and thus should be treated with care. | ||
119 | |||
120 | YMMV. | ||
121 | |||
97 | config MMC_OMAP | 122 | config MMC_OMAP |
98 | tristate "TI OMAP Multimedia Card Interface support" | 123 | tristate "TI OMAP Multimedia Card Interface support" |
99 | depends on ARCH_OMAP | 124 | depends on ARCH_OMAP |
@@ -265,3 +290,14 @@ config MMC_CB710 | |||
265 | This driver can also be built as a module. If so, the module | 290 | This driver can also be built as a module. If so, the module |
266 | will be called cb710-mmc. | 291 | will be called cb710-mmc. |
267 | 292 | ||
293 | config MMC_VIA_SDMMC | ||
294 | tristate "VIA SD/MMC Card Reader Driver" | ||
295 | depends on PCI | ||
296 | help | ||
297 | This selects the VIA SD/MMC Card Reader driver, say Y or M here. | ||
298 | VIA provides one multi-functional card reader which integrated into | ||
299 | some motherboards manufactured by VIA. This card reader supports | ||
300 | SD/MMC/SDHC. | ||
301 | If you have a controller with this interface, say Y or M here. | ||
302 | |||
303 | If unsure, say N. | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 79da397c5fea..cf153f628457 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | |||
15 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o | 15 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o |
16 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | 16 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o |
17 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o | 17 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o |
18 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | ||
18 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 19 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
19 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 20 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
20 | obj-$(CONFIG_MMC_OMAP) += omap.o | 21 | obj-$(CONFIG_MMC_OMAP) += omap.o |
@@ -31,6 +32,7 @@ obj-$(CONFIG_MMC_S3C) += s3cmci.o | |||
31 | obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o | 32 | obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o |
32 | obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o | 33 | obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o |
33 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o | 34 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o |
35 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | ||
34 | 36 | ||
35 | ifeq ($(CONFIG_CB710_DEBUG),y) | 37 | ifeq ($(CONFIG_CB710_DEBUG),y) |
36 | CFLAGS-cb710-mmc += -DDEBUG | 38 | CFLAGS-cb710-mmc += -DDEBUG |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 4eb4f37544ab..8c08cd7efa7f 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -794,7 +794,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, | |||
794 | host->mem->start + host->sdidata); | 794 | host->mem->start + host->sdidata); |
795 | 795 | ||
796 | if (!setup_ok) { | 796 | if (!setup_ok) { |
797 | s3c2410_dma_config(host->dma, 4, 0); | 797 | s3c2410_dma_config(host->dma, 4); |
798 | s3c2410_dma_set_buffdone_fn(host->dma, | 798 | s3c2410_dma_set_buffdone_fn(host->dma, |
799 | s3cmci_dma_done_callback); | 799 | s3cmci_dma_done_callback); |
800 | s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); | 800 | s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); |
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c index 128c614d11aa..d79fa55c3b89 100644 --- a/drivers/mmc/host/sdhci-of.c +++ b/drivers/mmc/host/sdhci-of.c | |||
@@ -250,6 +250,9 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev, | |||
250 | host->ops = &sdhci_of_data->ops; | 250 | host->ops = &sdhci_of_data->ops; |
251 | } | 251 | } |
252 | 252 | ||
253 | if (of_get_property(np, "sdhci,1-bit-only", NULL)) | ||
254 | host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; | ||
255 | |||
253 | clk = of_get_property(np, "clock-frequency", &size); | 256 | clk = of_get_property(np, "clock-frequency", &size); |
254 | if (clk && size == sizeof(*clk) && *clk) | 257 | if (clk && size == sizeof(*clk) && *clk) |
255 | of_host->clock = *clk; | 258 | of_host->clock = *clk; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 65be27995d5c..2f15cc17d887 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -284,6 +284,18 @@ static const struct sdhci_pci_fixes sdhci_jmicron = { | |||
284 | .resume = jmicron_resume, | 284 | .resume = jmicron_resume, |
285 | }; | 285 | }; |
286 | 286 | ||
287 | static int via_probe(struct sdhci_pci_chip *chip) | ||
288 | { | ||
289 | if (chip->pdev->revision == 0x10) | ||
290 | chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER; | ||
291 | |||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | static const struct sdhci_pci_fixes sdhci_via = { | ||
296 | .probe = via_probe, | ||
297 | }; | ||
298 | |||
287 | static const struct pci_device_id pci_ids[] __devinitdata = { | 299 | static const struct pci_device_id pci_ids[] __devinitdata = { |
288 | { | 300 | { |
289 | .vendor = PCI_VENDOR_ID_RICOH, | 301 | .vendor = PCI_VENDOR_ID_RICOH, |
@@ -349,6 +361,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
349 | .driver_data = (kernel_ulong_t)&sdhci_jmicron, | 361 | .driver_data = (kernel_ulong_t)&sdhci_jmicron, |
350 | }, | 362 | }, |
351 | 363 | ||
364 | { | ||
365 | .vendor = PCI_VENDOR_ID_VIA, | ||
366 | .device = 0x95d0, | ||
367 | .subvendor = PCI_ANY_ID, | ||
368 | .subdevice = PCI_ANY_ID, | ||
369 | .driver_data = (kernel_ulong_t)&sdhci_via, | ||
370 | }, | ||
371 | |||
352 | { /* Generic SD host controller */ | 372 | { /* Generic SD host controller */ |
353 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 373 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
354 | }, | 374 | }, |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c new file mode 100644 index 000000000000..50997d2a63e7 --- /dev/null +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* linux/drivers/mmc/host/sdhci-s3c.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * SDHCI (HSMMC) support for Samsung SoC | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <linux/mmc/host.h> | ||
22 | |||
23 | #include <plat/sdhci.h> | ||
24 | #include <plat/regs-sdhci.h> | ||
25 | |||
26 | #include "sdhci.h" | ||
27 | |||
28 | #define MAX_BUS_CLK (4) | ||
29 | |||
30 | /** | ||
31 | * struct sdhci_s3c - S3C SDHCI instance | ||
32 | * @host: The SDHCI host created | ||
33 | * @pdev: The platform device we where created from. | ||
34 | * @ioarea: The resource created when we claimed the IO area. | ||
35 | * @pdata: The platform data for this controller. | ||
36 | * @cur_clk: The index of the current bus clock. | ||
37 | * @clk_io: The clock for the internal bus interface. | ||
38 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. | ||
39 | */ | ||
40 | struct sdhci_s3c { | ||
41 | struct sdhci_host *host; | ||
42 | struct platform_device *pdev; | ||
43 | struct resource *ioarea; | ||
44 | struct s3c_sdhci_platdata *pdata; | ||
45 | unsigned int cur_clk; | ||
46 | |||
47 | struct clk *clk_io; | ||
48 | struct clk *clk_bus[MAX_BUS_CLK]; | ||
49 | }; | ||
50 | |||
51 | static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host) | ||
52 | { | ||
53 | return sdhci_priv(host); | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * get_curclk - convert ctrl2 register to clock source number | ||
58 | * @ctrl2: Control2 register value. | ||
59 | */ | ||
60 | static u32 get_curclk(u32 ctrl2) | ||
61 | { | ||
62 | ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
63 | ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
64 | |||
65 | return ctrl2; | ||
66 | } | ||
67 | |||
68 | static void sdhci_s3c_check_sclk(struct sdhci_host *host) | ||
69 | { | ||
70 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
71 | u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | ||
72 | |||
73 | if (get_curclk(tmp) != ourhost->cur_clk) { | ||
74 | dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n"); | ||
75 | |||
76 | tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
77 | tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
78 | writel(tmp, host->ioaddr + 0x80); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * sdhci_s3c_get_max_clk - callback to get maximum clock frequency. | ||
84 | * @host: The SDHCI host instance. | ||
85 | * | ||
86 | * Callback to return the maximum clock rate acheivable by the controller. | ||
87 | */ | ||
88 | static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) | ||
89 | { | ||
90 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
91 | struct clk *busclk; | ||
92 | unsigned int rate, max; | ||
93 | int clk; | ||
94 | |||
95 | /* note, a reset will reset the clock source */ | ||
96 | |||
97 | sdhci_s3c_check_sclk(host); | ||
98 | |||
99 | for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { | ||
100 | busclk = ourhost->clk_bus[clk]; | ||
101 | if (!busclk) | ||
102 | continue; | ||
103 | |||
104 | rate = clk_get_rate(busclk); | ||
105 | if (rate > max) | ||
106 | max = rate; | ||
107 | } | ||
108 | |||
109 | return max; | ||
110 | } | ||
111 | |||
112 | static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host) | ||
113 | { | ||
114 | return sdhci_s3c_get_max_clk(host) / 1000000; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * sdhci_s3c_consider_clock - consider one the bus clocks for current setting | ||
119 | * @ourhost: Our SDHCI instance. | ||
120 | * @src: The source clock index. | ||
121 | * @wanted: The clock frequency wanted. | ||
122 | */ | ||
123 | static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | ||
124 | unsigned int src, | ||
125 | unsigned int wanted) | ||
126 | { | ||
127 | unsigned long rate; | ||
128 | struct clk *clksrc = ourhost->clk_bus[src]; | ||
129 | int div; | ||
130 | |||
131 | if (!clksrc) | ||
132 | return UINT_MAX; | ||
133 | |||
134 | rate = clk_get_rate(clksrc); | ||
135 | |||
136 | for (div = 1; div < 256; div *= 2) { | ||
137 | if ((rate / div) <= wanted) | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", | ||
142 | src, rate, wanted, rate / div); | ||
143 | |||
144 | return (wanted - (rate / div)); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * sdhci_s3c_set_clock - callback on clock change | ||
149 | * @host: The SDHCI host being changed | ||
150 | * @clock: The clock rate being requested. | ||
151 | * | ||
152 | * When the card's clock is going to be changed, look at the new frequency | ||
153 | * and find the best clock source to go with it. | ||
154 | */ | ||
155 | static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | ||
156 | { | ||
157 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
158 | unsigned int best = UINT_MAX; | ||
159 | unsigned int delta; | ||
160 | int best_src = 0; | ||
161 | int src; | ||
162 | u32 ctrl; | ||
163 | |||
164 | /* don't bother if the clock is going off. */ | ||
165 | if (clock == 0) | ||
166 | return; | ||
167 | |||
168 | for (src = 0; src < MAX_BUS_CLK; src++) { | ||
169 | delta = sdhci_s3c_consider_clock(ourhost, src, clock); | ||
170 | if (delta < best) { | ||
171 | best = delta; | ||
172 | best_src = src; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | dev_dbg(&ourhost->pdev->dev, | ||
177 | "selected source %d, clock %d, delta %d\n", | ||
178 | best_src, clock, best); | ||
179 | |||
180 | /* select the new clock source */ | ||
181 | |||
182 | if (ourhost->cur_clk != best_src) { | ||
183 | struct clk *clk = ourhost->clk_bus[best_src]; | ||
184 | |||
185 | /* turn clock off to card before changing clock source */ | ||
186 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | ||
187 | |||
188 | ourhost->cur_clk = best_src; | ||
189 | host->max_clk = clk_get_rate(clk); | ||
190 | host->timeout_clk = sdhci_s3c_get_timeout_clk(host); | ||
191 | |||
192 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | ||
193 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | ||
194 | ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT; | ||
195 | writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2); | ||
196 | } | ||
197 | |||
198 | /* reconfigure the hardware for new clock rate */ | ||
199 | |||
200 | { | ||
201 | struct mmc_ios ios; | ||
202 | |||
203 | ios.clock = clock; | ||
204 | |||
205 | if (ourhost->pdata->cfg_card) | ||
206 | (ourhost->pdata->cfg_card)(ourhost->pdev, host->ioaddr, | ||
207 | &ios, NULL); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static struct sdhci_ops sdhci_s3c_ops = { | ||
212 | .get_max_clock = sdhci_s3c_get_max_clk, | ||
213 | .get_timeout_clock = sdhci_s3c_get_timeout_clk, | ||
214 | .set_clock = sdhci_s3c_set_clock, | ||
215 | }; | ||
216 | |||
217 | static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | ||
218 | { | ||
219 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | ||
220 | struct device *dev = &pdev->dev; | ||
221 | struct sdhci_host *host; | ||
222 | struct sdhci_s3c *sc; | ||
223 | struct resource *res; | ||
224 | int ret, irq, ptr, clks; | ||
225 | |||
226 | if (!pdata) { | ||
227 | dev_err(dev, "no device data specified\n"); | ||
228 | return -ENOENT; | ||
229 | } | ||
230 | |||
231 | irq = platform_get_irq(pdev, 0); | ||
232 | if (irq < 0) { | ||
233 | dev_err(dev, "no irq specified\n"); | ||
234 | return irq; | ||
235 | } | ||
236 | |||
237 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
238 | if (!res) { | ||
239 | dev_err(dev, "no memory specified\n"); | ||
240 | return -ENOENT; | ||
241 | } | ||
242 | |||
243 | host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); | ||
244 | if (IS_ERR(host)) { | ||
245 | dev_err(dev, "sdhci_alloc_host() failed\n"); | ||
246 | return PTR_ERR(host); | ||
247 | } | ||
248 | |||
249 | sc = sdhci_priv(host); | ||
250 | |||
251 | sc->host = host; | ||
252 | sc->pdev = pdev; | ||
253 | sc->pdata = pdata; | ||
254 | |||
255 | platform_set_drvdata(pdev, host); | ||
256 | |||
257 | sc->clk_io = clk_get(dev, "hsmmc"); | ||
258 | if (IS_ERR(sc->clk_io)) { | ||
259 | dev_err(dev, "failed to get io clock\n"); | ||
260 | ret = PTR_ERR(sc->clk_io); | ||
261 | goto err_io_clk; | ||
262 | } | ||
263 | |||
264 | /* enable the local io clock and keep it running for the moment. */ | ||
265 | clk_enable(sc->clk_io); | ||
266 | |||
267 | for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
268 | struct clk *clk; | ||
269 | char *name = pdata->clocks[ptr]; | ||
270 | |||
271 | if (name == NULL) | ||
272 | continue; | ||
273 | |||
274 | clk = clk_get(dev, name); | ||
275 | if (IS_ERR(clk)) { | ||
276 | dev_err(dev, "failed to get clock %s\n", name); | ||
277 | continue; | ||
278 | } | ||
279 | |||
280 | clks++; | ||
281 | sc->clk_bus[ptr] = clk; | ||
282 | clk_enable(clk); | ||
283 | |||
284 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | ||
285 | ptr, name, clk_get_rate(clk)); | ||
286 | } | ||
287 | |||
288 | if (clks == 0) { | ||
289 | dev_err(dev, "failed to find any bus clocks\n"); | ||
290 | ret = -ENOENT; | ||
291 | goto err_no_busclks; | ||
292 | } | ||
293 | |||
294 | sc->ioarea = request_mem_region(res->start, resource_size(res), | ||
295 | mmc_hostname(host->mmc)); | ||
296 | if (!sc->ioarea) { | ||
297 | dev_err(dev, "failed to reserve register area\n"); | ||
298 | ret = -ENXIO; | ||
299 | goto err_req_regs; | ||
300 | } | ||
301 | |||
302 | host->ioaddr = ioremap_nocache(res->start, resource_size(res)); | ||
303 | if (!host->ioaddr) { | ||
304 | dev_err(dev, "failed to map registers\n"); | ||
305 | ret = -ENXIO; | ||
306 | goto err_req_regs; | ||
307 | } | ||
308 | |||
309 | /* Ensure we have minimal gpio selected CMD/CLK/Detect */ | ||
310 | if (pdata->cfg_gpio) | ||
311 | pdata->cfg_gpio(pdev, pdata->max_width); | ||
312 | |||
313 | host->hw_name = "samsung-hsmmc"; | ||
314 | host->ops = &sdhci_s3c_ops; | ||
315 | host->quirks = 0; | ||
316 | host->irq = irq; | ||
317 | |||
318 | /* Setup quirks for the controller */ | ||
319 | |||
320 | /* Currently with ADMA enabled we are getting some length | ||
321 | * interrupts that are not being dealt with, do disable | ||
322 | * ADMA until this is sorted out. */ | ||
323 | host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; | ||
324 | host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE; | ||
325 | |||
326 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA | ||
327 | |||
328 | /* we currently see overruns on errors, so disable the SDMA | ||
329 | * support as well. */ | ||
330 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | ||
331 | |||
332 | /* PIO currently has problems with multi-block IO */ | ||
333 | host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; | ||
334 | |||
335 | #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ | ||
336 | |||
337 | /* It seems we do not get an DATA transfer complete on non-busy | ||
338 | * transfers, not sure if this is a problem with this specific | ||
339 | * SDHCI block, or a missing configuration that needs to be set. */ | ||
340 | host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; | ||
341 | |||
342 | host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | | ||
343 | SDHCI_QUIRK_32BIT_DMA_SIZE); | ||
344 | |||
345 | ret = sdhci_add_host(host); | ||
346 | if (ret) { | ||
347 | dev_err(dev, "sdhci_add_host() failed\n"); | ||
348 | goto err_add_host; | ||
349 | } | ||
350 | |||
351 | return 0; | ||
352 | |||
353 | err_add_host: | ||
354 | release_resource(sc->ioarea); | ||
355 | kfree(sc->ioarea); | ||
356 | |||
357 | err_req_regs: | ||
358 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
359 | clk_disable(sc->clk_bus[ptr]); | ||
360 | clk_put(sc->clk_bus[ptr]); | ||
361 | } | ||
362 | |||
363 | err_no_busclks: | ||
364 | clk_disable(sc->clk_io); | ||
365 | clk_put(sc->clk_io); | ||
366 | |||
367 | err_io_clk: | ||
368 | sdhci_free_host(host); | ||
369 | |||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | ||
374 | { | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | #ifdef CONFIG_PM | ||
379 | |||
380 | static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm) | ||
381 | { | ||
382 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
383 | |||
384 | sdhci_suspend_host(host, pm); | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static int sdhci_s3c_resume(struct platform_device *dev) | ||
389 | { | ||
390 | struct sdhci_host *host = platform_get_drvdata(dev); | ||
391 | |||
392 | sdhci_resume_host(host); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | #else | ||
397 | #define sdhci_s3c_suspend NULL | ||
398 | #define sdhci_s3c_resume NULL | ||
399 | #endif | ||
400 | |||
401 | static struct platform_driver sdhci_s3c_driver = { | ||
402 | .probe = sdhci_s3c_probe, | ||
403 | .remove = __devexit_p(sdhci_s3c_remove), | ||
404 | .suspend = sdhci_s3c_suspend, | ||
405 | .resume = sdhci_s3c_resume, | ||
406 | .driver = { | ||
407 | .owner = THIS_MODULE, | ||
408 | .name = "s3c-sdhci", | ||
409 | }, | ||
410 | }; | ||
411 | |||
412 | static int __init sdhci_s3c_init(void) | ||
413 | { | ||
414 | return platform_driver_register(&sdhci_s3c_driver); | ||
415 | } | ||
416 | |||
417 | static void __exit sdhci_s3c_exit(void) | ||
418 | { | ||
419 | platform_driver_unregister(&sdhci_s3c_driver); | ||
420 | } | ||
421 | |||
422 | module_init(sdhci_s3c_init); | ||
423 | module_exit(sdhci_s3c_exit); | ||
424 | |||
425 | MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue"); | ||
426 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | ||
427 | MODULE_LICENSE("GPL v2"); | ||
428 | MODULE_ALIAS("platform:s3c-sdhci"); | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 35789c6edc19..6779b4ecab18 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -584,7 +584,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
584 | * longer to time out, but that's much better than having a too-short | 584 | * longer to time out, but that's much better than having a too-short |
585 | * timeout value. | 585 | * timeout value. |
586 | */ | 586 | */ |
587 | if ((host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)) | 587 | if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) |
588 | return 0xE; | 588 | return 0xE; |
589 | 589 | ||
590 | /* timeout in us */ | 590 | /* timeout in us */ |
@@ -1051,12 +1051,19 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
1051 | * At least the Marvell CaFe chip gets confused if we set the voltage | 1051 | * At least the Marvell CaFe chip gets confused if we set the voltage |
1052 | * and set turn on power at the same time, so set the voltage first. | 1052 | * and set turn on power at the same time, so set the voltage first. |
1053 | */ | 1053 | */ |
1054 | if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) | 1054 | if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) |
1055 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1055 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1056 | 1056 | ||
1057 | pwr |= SDHCI_POWER_ON; | 1057 | pwr |= SDHCI_POWER_ON; |
1058 | 1058 | ||
1059 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1059 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1060 | |||
1061 | /* | ||
1062 | * Some controllers need an extra 10ms delay of 10ms before they | ||
1063 | * can apply clock after applying power | ||
1064 | */ | ||
1065 | if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER) | ||
1066 | mdelay(10); | ||
1060 | } | 1067 | } |
1061 | 1068 | ||
1062 | /*****************************************************************************\ | 1069 | /*****************************************************************************\ |
@@ -1382,6 +1389,35 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
1382 | sdhci_finish_command(host); | 1389 | sdhci_finish_command(host); |
1383 | } | 1390 | } |
1384 | 1391 | ||
1392 | #ifdef DEBUG | ||
1393 | static void sdhci_show_adma_error(struct sdhci_host *host) | ||
1394 | { | ||
1395 | const char *name = mmc_hostname(host->mmc); | ||
1396 | u8 *desc = host->adma_desc; | ||
1397 | __le32 *dma; | ||
1398 | __le16 *len; | ||
1399 | u8 attr; | ||
1400 | |||
1401 | sdhci_dumpregs(host); | ||
1402 | |||
1403 | while (true) { | ||
1404 | dma = (__le32 *)(desc + 4); | ||
1405 | len = (__le16 *)(desc + 2); | ||
1406 | attr = *desc; | ||
1407 | |||
1408 | DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", | ||
1409 | name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr); | ||
1410 | |||
1411 | desc += 8; | ||
1412 | |||
1413 | if (attr & 2) | ||
1414 | break; | ||
1415 | } | ||
1416 | } | ||
1417 | #else | ||
1418 | static void sdhci_show_adma_error(struct sdhci_host *host) { } | ||
1419 | #endif | ||
1420 | |||
1385 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | 1421 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |
1386 | { | 1422 | { |
1387 | BUG_ON(intmask == 0); | 1423 | BUG_ON(intmask == 0); |
@@ -1411,8 +1447,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1411 | host->data->error = -ETIMEDOUT; | 1447 | host->data->error = -ETIMEDOUT; |
1412 | else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) | 1448 | else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) |
1413 | host->data->error = -EILSEQ; | 1449 | host->data->error = -EILSEQ; |
1414 | else if (intmask & SDHCI_INT_ADMA_ERROR) | 1450 | else if (intmask & SDHCI_INT_ADMA_ERROR) { |
1451 | printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); | ||
1452 | sdhci_show_adma_error(host); | ||
1415 | host->data->error = -EIO; | 1453 | host->data->error = -EIO; |
1454 | } | ||
1416 | 1455 | ||
1417 | if (host->data->error) | 1456 | if (host->data->error) |
1418 | sdhci_finish_data(host); | 1457 | sdhci_finish_data(host); |
@@ -1729,7 +1768,10 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1729 | mmc->ops = &sdhci_ops; | 1768 | mmc->ops = &sdhci_ops; |
1730 | mmc->f_min = host->max_clk / 256; | 1769 | mmc->f_min = host->max_clk / 256; |
1731 | mmc->f_max = host->max_clk; | 1770 | mmc->f_max = host->max_clk; |
1732 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 1771 | mmc->caps = MMC_CAP_SDIO_IRQ; |
1772 | |||
1773 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | ||
1774 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1733 | 1775 | ||
1734 | if (caps & SDHCI_CAN_DO_HISPD) | 1776 | if (caps & SDHCI_CAN_DO_HISPD) |
1735 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1777 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
@@ -1802,7 +1844,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1802 | /* | 1844 | /* |
1803 | * Maximum block count. | 1845 | * Maximum block count. |
1804 | */ | 1846 | */ |
1805 | mmc->max_blk_count = 65535; | 1847 | mmc->max_blk_count = (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535; |
1806 | 1848 | ||
1807 | /* | 1849 | /* |
1808 | * Init tasklets. | 1850 | * Init tasklets. |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 2de08349c3ca..831ddf7dcb49 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -226,6 +226,12 @@ struct sdhci_host { | |||
226 | #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) | 226 | #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) |
227 | /* Controller has to be forced to use block size of 2048 bytes */ | 227 | /* Controller has to be forced to use block size of 2048 bytes */ |
228 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | 228 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) |
229 | /* Controller cannot do multi-block transfers */ | ||
230 | #define SDHCI_QUIRK_NO_MULTIBLOCK (1<<21) | ||
231 | /* Controller can only handle 1-bit data transfers */ | ||
232 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) | ||
233 | /* Controller needs 10ms delay between applying power and clock */ | ||
234 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | ||
229 | 235 | ||
230 | int irq; /* Device IRQ */ | 236 | int irq; /* Device IRQ */ |
231 | void __iomem * ioaddr; /* Mapped address */ | 237 | void __iomem * ioaddr; /* Mapped address */ |
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c new file mode 100644 index 000000000000..632858a94376 --- /dev/null +++ b/drivers/mmc/host/via-sdmmc.c | |||
@@ -0,0 +1,1362 @@ | |||
1 | /* | ||
2 | * drivers/mmc/host/via-sdmmc.c - VIA SD/MMC Card Reader driver | ||
3 | * Copyright (c) 2008, VIA Technologies Inc. All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or (at | ||
8 | * your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/pci.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | #include <linux/highmem.h> | ||
14 | #include <linux/delay.h> | ||
15 | |||
16 | #include <linux/mmc/host.h> | ||
17 | |||
18 | #define DRV_NAME "via_sdmmc" | ||
19 | |||
20 | #define PCI_DEVICE_ID_VIA_9530 0x9530 | ||
21 | |||
22 | #define VIA_CRDR_SDC_OFF 0x200 | ||
23 | #define VIA_CRDR_DDMA_OFF 0x400 | ||
24 | #define VIA_CRDR_PCICTRL_OFF 0x600 | ||
25 | |||
26 | #define VIA_CRDR_MIN_CLOCK 375000 | ||
27 | #define VIA_CRDR_MAX_CLOCK 48000000 | ||
28 | |||
29 | /* | ||
30 | * PCI registers | ||
31 | */ | ||
32 | |||
33 | #define VIA_CRDR_PCI_WORK_MODE 0x40 | ||
34 | #define VIA_CRDR_PCI_DBG_MODE 0x41 | ||
35 | |||
36 | /* | ||
37 | * SDC MMIO Registers | ||
38 | */ | ||
39 | |||
40 | #define VIA_CRDR_SDCTRL 0x0 | ||
41 | #define VIA_CRDR_SDCTRL_START 0x01 | ||
42 | #define VIA_CRDR_SDCTRL_WRITE 0x04 | ||
43 | #define VIA_CRDR_SDCTRL_SINGLE_WR 0x10 | ||
44 | #define VIA_CRDR_SDCTRL_SINGLE_RD 0x20 | ||
45 | #define VIA_CRDR_SDCTRL_MULTI_WR 0x30 | ||
46 | #define VIA_CRDR_SDCTRL_MULTI_RD 0x40 | ||
47 | #define VIA_CRDR_SDCTRL_STOP 0x70 | ||
48 | |||
49 | #define VIA_CRDR_SDCTRL_RSP_NONE 0x0 | ||
50 | #define VIA_CRDR_SDCTRL_RSP_R1 0x10000 | ||
51 | #define VIA_CRDR_SDCTRL_RSP_R2 0x20000 | ||
52 | #define VIA_CRDR_SDCTRL_RSP_R3 0x30000 | ||
53 | #define VIA_CRDR_SDCTRL_RSP_R1B 0x90000 | ||
54 | |||
55 | #define VIA_CRDR_SDCARG 0x4 | ||
56 | |||
57 | #define VIA_CRDR_SDBUSMODE 0x8 | ||
58 | #define VIA_CRDR_SDMODE_4BIT 0x02 | ||
59 | #define VIA_CRDR_SDMODE_CLK_ON 0x40 | ||
60 | |||
61 | #define VIA_CRDR_SDBLKLEN 0xc | ||
62 | /* | ||
63 | * Bit 0 -Bit 10 : Block length. So, the maximum block length should be 2048. | ||
64 | * Bit 11 - Bit 13 : Reserved. | ||
65 | * GPIDET : Select GPI pin to detect card, GPI means CR_CD# in top design. | ||
66 | * INTEN : Enable SD host interrupt. | ||
67 | * Bit 16 - Bit 31 : Block count. So, the maximun block count should be 65536. | ||
68 | */ | ||
69 | #define VIA_CRDR_SDBLKLEN_GPIDET 0x2000 | ||
70 | #define VIA_CRDR_SDBLKLEN_INTEN 0x8000 | ||
71 | #define VIA_CRDR_MAX_BLOCK_COUNT 65536 | ||
72 | #define VIA_CRDR_MAX_BLOCK_LENGTH 2048 | ||
73 | |||
74 | #define VIA_CRDR_SDRESP0 0x10 | ||
75 | #define VIA_CRDR_SDRESP1 0x14 | ||
76 | #define VIA_CRDR_SDRESP2 0x18 | ||
77 | #define VIA_CRDR_SDRESP3 0x1c | ||
78 | |||
79 | #define VIA_CRDR_SDCURBLKCNT 0x20 | ||
80 | |||
81 | #define VIA_CRDR_SDINTMASK 0x24 | ||
82 | /* | ||
83 | * MBDIE : Multiple Blocks transfer Done Interrupt Enable | ||
84 | * BDDIE : Block Data transfer Done Interrupt Enable | ||
85 | * CIRIE : Card Insertion or Removal Interrupt Enable | ||
86 | * CRDIE : Command-Response transfer Done Interrupt Enable | ||
87 | * CRTOIE : Command-Response response TimeOut Interrupt Enable | ||
88 | * ASCRDIE : Auto Stop Command-Response transfer Done Interrupt Enable | ||
89 | * DTIE : Data access Timeout Interrupt Enable | ||
90 | * SCIE : reSponse CRC error Interrupt Enable | ||
91 | * RCIE : Read data CRC error Interrupt Enable | ||
92 | * WCIE : Write data CRC error Interrupt Enable | ||
93 | */ | ||
94 | #define VIA_CRDR_SDINTMASK_MBDIE 0x10 | ||
95 | #define VIA_CRDR_SDINTMASK_BDDIE 0x20 | ||
96 | #define VIA_CRDR_SDINTMASK_CIRIE 0x80 | ||
97 | #define VIA_CRDR_SDINTMASK_CRDIE 0x200 | ||
98 | #define VIA_CRDR_SDINTMASK_CRTOIE 0x400 | ||
99 | #define VIA_CRDR_SDINTMASK_ASCRDIE 0x800 | ||
100 | #define VIA_CRDR_SDINTMASK_DTIE 0x1000 | ||
101 | #define VIA_CRDR_SDINTMASK_SCIE 0x2000 | ||
102 | #define VIA_CRDR_SDINTMASK_RCIE 0x4000 | ||
103 | #define VIA_CRDR_SDINTMASK_WCIE 0x8000 | ||
104 | |||
105 | #define VIA_CRDR_SDACTIVE_INTMASK \ | ||
106 | (VIA_CRDR_SDINTMASK_MBDIE | VIA_CRDR_SDINTMASK_CIRIE \ | ||
107 | | VIA_CRDR_SDINTMASK_CRDIE | VIA_CRDR_SDINTMASK_CRTOIE \ | ||
108 | | VIA_CRDR_SDINTMASK_DTIE | VIA_CRDR_SDINTMASK_SCIE \ | ||
109 | | VIA_CRDR_SDINTMASK_RCIE | VIA_CRDR_SDINTMASK_WCIE) | ||
110 | |||
111 | #define VIA_CRDR_SDSTATUS 0x28 | ||
112 | /* | ||
113 | * CECC : Reserved | ||
114 | * WP : SD card Write Protect status | ||
115 | * SLOTD : Reserved | ||
116 | * SLOTG : SD SLOT status(Gpi pin status) | ||
117 | * MBD : Multiple Blocks transfer Done interrupt status | ||
118 | * BDD : Block Data transfer Done interrupt status | ||
119 | * CD : Reserved | ||
120 | * CIR : Card Insertion or Removal interrupt detected on GPI pin | ||
121 | * IO : Reserved | ||
122 | * CRD : Command-Response transfer Done interrupt status | ||
123 | * CRTO : Command-Response response TimeOut interrupt status | ||
124 | * ASCRDIE : Auto Stop Command-Response transfer Done interrupt status | ||
125 | * DT : Data access Timeout interrupt status | ||
126 | * SC : reSponse CRC error interrupt status | ||
127 | * RC : Read data CRC error interrupt status | ||
128 | * WC : Write data CRC error interrupt status | ||
129 | */ | ||
130 | #define VIA_CRDR_SDSTS_CECC 0x01 | ||
131 | #define VIA_CRDR_SDSTS_WP 0x02 | ||
132 | #define VIA_CRDR_SDSTS_SLOTD 0x04 | ||
133 | #define VIA_CRDR_SDSTS_SLOTG 0x08 | ||
134 | #define VIA_CRDR_SDSTS_MBD 0x10 | ||
135 | #define VIA_CRDR_SDSTS_BDD 0x20 | ||
136 | #define VIA_CRDR_SDSTS_CD 0x40 | ||
137 | #define VIA_CRDR_SDSTS_CIR 0x80 | ||
138 | #define VIA_CRDR_SDSTS_IO 0x100 | ||
139 | #define VIA_CRDR_SDSTS_CRD 0x200 | ||
140 | #define VIA_CRDR_SDSTS_CRTO 0x400 | ||
141 | #define VIA_CRDR_SDSTS_ASCRDIE 0x800 | ||
142 | #define VIA_CRDR_SDSTS_DT 0x1000 | ||
143 | #define VIA_CRDR_SDSTS_SC 0x2000 | ||
144 | #define VIA_CRDR_SDSTS_RC 0x4000 | ||
145 | #define VIA_CRDR_SDSTS_WC 0x8000 | ||
146 | |||
147 | #define VIA_CRDR_SDSTS_IGN_MASK\ | ||
148 | (VIA_CRDR_SDSTS_BDD | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_IO) | ||
149 | #define VIA_CRDR_SDSTS_INT_MASK \ | ||
150 | (VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_BDD | VIA_CRDR_SDSTS_CD \ | ||
151 | | VIA_CRDR_SDSTS_CIR | VIA_CRDR_SDSTS_IO | VIA_CRDR_SDSTS_CRD \ | ||
152 | | VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_DT \ | ||
153 | | VIA_CRDR_SDSTS_SC | VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC) | ||
154 | #define VIA_CRDR_SDSTS_W1C_MASK \ | ||
155 | (VIA_CRDR_SDSTS_CECC | VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_BDD \ | ||
156 | | VIA_CRDR_SDSTS_CD | VIA_CRDR_SDSTS_CIR | VIA_CRDR_SDSTS_CRD \ | ||
157 | | VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_ASCRDIE | VIA_CRDR_SDSTS_DT \ | ||
158 | | VIA_CRDR_SDSTS_SC | VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC) | ||
159 | #define VIA_CRDR_SDSTS_CMD_MASK \ | ||
160 | (VIA_CRDR_SDSTS_CRD | VIA_CRDR_SDSTS_CRTO | VIA_CRDR_SDSTS_SC) | ||
161 | #define VIA_CRDR_SDSTS_DATA_MASK\ | ||
162 | (VIA_CRDR_SDSTS_MBD | VIA_CRDR_SDSTS_DT \ | ||
163 | | VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC) | ||
164 | |||
165 | #define VIA_CRDR_SDSTATUS2 0x2a | ||
166 | /* | ||
167 | * CFE : Enable SD host automatic Clock FReezing | ||
168 | */ | ||
169 | #define VIA_CRDR_SDSTS_CFE 0x80 | ||
170 | |||
171 | #define VIA_CRDR_SDRSPTMO 0x2C | ||
172 | |||
173 | #define VIA_CRDR_SDCLKSEL 0x30 | ||
174 | |||
175 | #define VIA_CRDR_SDEXTCTRL 0x34 | ||
176 | #define VIS_CRDR_SDEXTCTRL_AUTOSTOP_SD 0x01 | ||
177 | #define VIS_CRDR_SDEXTCTRL_SHIFT_9 0x02 | ||
178 | #define VIS_CRDR_SDEXTCTRL_MMC_8BIT 0x04 | ||
179 | #define VIS_CRDR_SDEXTCTRL_RELD_BLK 0x08 | ||
180 | #define VIS_CRDR_SDEXTCTRL_BAD_CMDA 0x10 | ||
181 | #define VIS_CRDR_SDEXTCTRL_BAD_DATA 0x20 | ||
182 | #define VIS_CRDR_SDEXTCTRL_AUTOSTOP_SPI 0x40 | ||
183 | #define VIA_CRDR_SDEXTCTRL_HISPD 0x80 | ||
184 | /* 0x38-0xFF reserved */ | ||
185 | |||
186 | /* | ||
187 | * Data DMA Control Registers | ||
188 | */ | ||
189 | |||
190 | #define VIA_CRDR_DMABASEADD 0x0 | ||
191 | #define VIA_CRDR_DMACOUNTER 0x4 | ||
192 | |||
193 | #define VIA_CRDR_DMACTRL 0x8 | ||
194 | /* | ||
195 | * DIR :Transaction Direction | ||
196 | * 0 : From card to memory | ||
197 | * 1 : From memory to card | ||
198 | */ | ||
199 | #define VIA_CRDR_DMACTRL_DIR 0x100 | ||
200 | #define VIA_CRDR_DMACTRL_ENIRQ 0x10000 | ||
201 | #define VIA_CRDR_DMACTRL_SFTRST 0x1000000 | ||
202 | |||
203 | #define VIA_CRDR_DMASTS 0xc | ||
204 | |||
205 | #define VIA_CRDR_DMASTART 0x10 | ||
206 | /*0x14-0xFF reserved*/ | ||
207 | |||
208 | /* | ||
209 | * PCI Control Registers | ||
210 | */ | ||
211 | |||
212 | /*0x0 - 0x1 reserved*/ | ||
213 | #define VIA_CRDR_PCICLKGATT 0x2 | ||
214 | /* | ||
215 | * SFTRST : | ||
216 | * 0 : Soft reset all the controller and it will be de-asserted automatically | ||
217 | * 1 : Soft reset is de-asserted | ||
218 | */ | ||
219 | #define VIA_CRDR_PCICLKGATT_SFTRST 0x01 | ||
220 | /* | ||
221 | * 3V3 : Pad power select | ||
222 | * 0 : 1.8V | ||
223 | * 1 : 3.3V | ||
224 | * NOTE : No mater what the actual value should be, this bit always | ||
225 | * read as 0. This is a hardware bug. | ||
226 | */ | ||
227 | #define VIA_CRDR_PCICLKGATT_3V3 0x10 | ||
228 | /* | ||
229 | * PAD_PWRON : Pad Power on/off select | ||
230 | * 0 : Power off | ||
231 | * 1 : Power on | ||
232 | * NOTE : No mater what the actual value should be, this bit always | ||
233 | * read as 0. This is a hardware bug. | ||
234 | */ | ||
235 | #define VIA_CRDR_PCICLKGATT_PAD_PWRON 0x20 | ||
236 | |||
237 | #define VIA_CRDR_PCISDCCLK 0x5 | ||
238 | |||
239 | #define VIA_CRDR_PCIDMACLK 0x7 | ||
240 | #define VIA_CRDR_PCIDMACLK_SDC 0x2 | ||
241 | |||
242 | #define VIA_CRDR_PCIINTCTRL 0x8 | ||
243 | #define VIA_CRDR_PCIINTCTRL_SDCIRQEN 0x04 | ||
244 | |||
245 | #define VIA_CRDR_PCIINTSTATUS 0x9 | ||
246 | #define VIA_CRDR_PCIINTSTATUS_SDC 0x04 | ||
247 | |||
248 | #define VIA_CRDR_PCITMOCTRL 0xa | ||
249 | #define VIA_CRDR_PCITMOCTRL_NO 0x0 | ||
250 | #define VIA_CRDR_PCITMOCTRL_32US 0x1 | ||
251 | #define VIA_CRDR_PCITMOCTRL_256US 0x2 | ||
252 | #define VIA_CRDR_PCITMOCTRL_1024US 0x3 | ||
253 | #define VIA_CRDR_PCITMOCTRL_256MS 0x4 | ||
254 | #define VIA_CRDR_PCITMOCTRL_512MS 0x5 | ||
255 | #define VIA_CRDR_PCITMOCTRL_1024MS 0x6 | ||
256 | |||
257 | /*0xB-0xFF reserved*/ | ||
258 | |||
259 | enum PCI_HOST_CLK_CONTROL { | ||
260 | PCI_CLK_375K = 0x03, | ||
261 | PCI_CLK_8M = 0x04, | ||
262 | PCI_CLK_12M = 0x00, | ||
263 | PCI_CLK_16M = 0x05, | ||
264 | PCI_CLK_24M = 0x01, | ||
265 | PCI_CLK_33M = 0x06, | ||
266 | PCI_CLK_48M = 0x02 | ||
267 | }; | ||
268 | |||
269 | struct sdhcreg { | ||
270 | u32 sdcontrol_reg; | ||
271 | u32 sdcmdarg_reg; | ||
272 | u32 sdbusmode_reg; | ||
273 | u32 sdblklen_reg; | ||
274 | u32 sdresp_reg[4]; | ||
275 | u32 sdcurblkcnt_reg; | ||
276 | u32 sdintmask_reg; | ||
277 | u32 sdstatus_reg; | ||
278 | u32 sdrsptmo_reg; | ||
279 | u32 sdclksel_reg; | ||
280 | u32 sdextctrl_reg; | ||
281 | }; | ||
282 | |||
283 | struct pcictrlreg { | ||
284 | u8 reserve[2]; | ||
285 | u8 pciclkgat_reg; | ||
286 | u8 pcinfcclk_reg; | ||
287 | u8 pcimscclk_reg; | ||
288 | u8 pcisdclk_reg; | ||
289 | u8 pcicaclk_reg; | ||
290 | u8 pcidmaclk_reg; | ||
291 | u8 pciintctrl_reg; | ||
292 | u8 pciintstatus_reg; | ||
293 | u8 pcitmoctrl_reg; | ||
294 | u8 Resv; | ||
295 | }; | ||
296 | |||
297 | struct via_crdr_mmc_host { | ||
298 | struct mmc_host *mmc; | ||
299 | struct mmc_request *mrq; | ||
300 | struct mmc_command *cmd; | ||
301 | struct mmc_data *data; | ||
302 | |||
303 | void __iomem *mmiobase; | ||
304 | void __iomem *sdhc_mmiobase; | ||
305 | void __iomem *ddma_mmiobase; | ||
306 | void __iomem *pcictrl_mmiobase; | ||
307 | |||
308 | struct pcictrlreg pm_pcictrl_reg; | ||
309 | struct sdhcreg pm_sdhc_reg; | ||
310 | |||
311 | struct work_struct carddet_work; | ||
312 | struct tasklet_struct finish_tasklet; | ||
313 | |||
314 | struct timer_list timer; | ||
315 | spinlock_t lock; | ||
316 | u8 power; | ||
317 | int reject; | ||
318 | unsigned int quirks; | ||
319 | }; | ||
320 | |||
321 | /* some devices need a very long delay for power to stabilize */ | ||
322 | #define VIA_CRDR_QUIRK_300MS_PWRDELAY 0x0001 | ||
323 | |||
324 | static struct pci_device_id via_ids[] = { | ||
325 | {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_9530, | ||
326 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, | ||
327 | {0,} | ||
328 | }; | ||
329 | |||
330 | MODULE_DEVICE_TABLE(pci, via_ids); | ||
331 | |||
332 | static void via_print_sdchc(struct via_crdr_mmc_host *host) | ||
333 | { | ||
334 | void __iomem *addrbase = host->sdhc_mmiobase; | ||
335 | |||
336 | pr_debug("SDC MMIO Registers:\n"); | ||
337 | pr_debug("SDCONTROL=%08x, SDCMDARG=%08x, SDBUSMODE=%08x\n", | ||
338 | readl(addrbase + VIA_CRDR_SDCTRL), | ||
339 | readl(addrbase + VIA_CRDR_SDCARG), | ||
340 | readl(addrbase + VIA_CRDR_SDBUSMODE)); | ||
341 | pr_debug("SDBLKLEN=%08x, SDCURBLKCNT=%08x, SDINTMASK=%08x\n", | ||
342 | readl(addrbase + VIA_CRDR_SDBLKLEN), | ||
343 | readl(addrbase + VIA_CRDR_SDCURBLKCNT), | ||
344 | readl(addrbase + VIA_CRDR_SDINTMASK)); | ||
345 | pr_debug("SDSTATUS=%08x, SDCLKSEL=%08x, SDEXTCTRL=%08x\n", | ||
346 | readl(addrbase + VIA_CRDR_SDSTATUS), | ||
347 | readl(addrbase + VIA_CRDR_SDCLKSEL), | ||
348 | readl(addrbase + VIA_CRDR_SDEXTCTRL)); | ||
349 | } | ||
350 | |||
351 | static void via_print_pcictrl(struct via_crdr_mmc_host *host) | ||
352 | { | ||
353 | void __iomem *addrbase = host->pcictrl_mmiobase; | ||
354 | |||
355 | pr_debug("PCI Control Registers:\n"); | ||
356 | pr_debug("PCICLKGATT=%02x, PCISDCCLK=%02x, PCIDMACLK=%02x\n", | ||
357 | readb(addrbase + VIA_CRDR_PCICLKGATT), | ||
358 | readb(addrbase + VIA_CRDR_PCISDCCLK), | ||
359 | readb(addrbase + VIA_CRDR_PCIDMACLK)); | ||
360 | pr_debug("PCIINTCTRL=%02x, PCIINTSTATUS=%02x\n", | ||
361 | readb(addrbase + VIA_CRDR_PCIINTCTRL), | ||
362 | readb(addrbase + VIA_CRDR_PCIINTSTATUS)); | ||
363 | } | ||
364 | |||
365 | static void via_save_pcictrlreg(struct via_crdr_mmc_host *host) | ||
366 | { | ||
367 | struct pcictrlreg *pm_pcictrl_reg; | ||
368 | void __iomem *addrbase; | ||
369 | |||
370 | pm_pcictrl_reg = &(host->pm_pcictrl_reg); | ||
371 | addrbase = host->pcictrl_mmiobase; | ||
372 | |||
373 | pm_pcictrl_reg->pciclkgat_reg = readb(addrbase + VIA_CRDR_PCICLKGATT); | ||
374 | pm_pcictrl_reg->pciclkgat_reg |= | ||
375 | VIA_CRDR_PCICLKGATT_3V3 | VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
376 | pm_pcictrl_reg->pcisdclk_reg = readb(addrbase + VIA_CRDR_PCISDCCLK); | ||
377 | pm_pcictrl_reg->pcidmaclk_reg = readb(addrbase + VIA_CRDR_PCIDMACLK); | ||
378 | pm_pcictrl_reg->pciintctrl_reg = readb(addrbase + VIA_CRDR_PCIINTCTRL); | ||
379 | pm_pcictrl_reg->pciintstatus_reg = | ||
380 | readb(addrbase + VIA_CRDR_PCIINTSTATUS); | ||
381 | pm_pcictrl_reg->pcitmoctrl_reg = readb(addrbase + VIA_CRDR_PCITMOCTRL); | ||
382 | } | ||
383 | |||
384 | static void via_restore_pcictrlreg(struct via_crdr_mmc_host *host) | ||
385 | { | ||
386 | struct pcictrlreg *pm_pcictrl_reg; | ||
387 | void __iomem *addrbase; | ||
388 | |||
389 | pm_pcictrl_reg = &(host->pm_pcictrl_reg); | ||
390 | addrbase = host->pcictrl_mmiobase; | ||
391 | |||
392 | writeb(pm_pcictrl_reg->pciclkgat_reg, addrbase + VIA_CRDR_PCICLKGATT); | ||
393 | writeb(pm_pcictrl_reg->pcisdclk_reg, addrbase + VIA_CRDR_PCISDCCLK); | ||
394 | writeb(pm_pcictrl_reg->pcidmaclk_reg, addrbase + VIA_CRDR_PCIDMACLK); | ||
395 | writeb(pm_pcictrl_reg->pciintctrl_reg, addrbase + VIA_CRDR_PCIINTCTRL); | ||
396 | writeb(pm_pcictrl_reg->pciintstatus_reg, | ||
397 | addrbase + VIA_CRDR_PCIINTSTATUS); | ||
398 | writeb(pm_pcictrl_reg->pcitmoctrl_reg, addrbase + VIA_CRDR_PCITMOCTRL); | ||
399 | } | ||
400 | |||
401 | static void via_save_sdcreg(struct via_crdr_mmc_host *host) | ||
402 | { | ||
403 | struct sdhcreg *pm_sdhc_reg; | ||
404 | void __iomem *addrbase; | ||
405 | |||
406 | pm_sdhc_reg = &(host->pm_sdhc_reg); | ||
407 | addrbase = host->sdhc_mmiobase; | ||
408 | |||
409 | pm_sdhc_reg->sdcontrol_reg = readl(addrbase + VIA_CRDR_SDCTRL); | ||
410 | pm_sdhc_reg->sdcmdarg_reg = readl(addrbase + VIA_CRDR_SDCARG); | ||
411 | pm_sdhc_reg->sdbusmode_reg = readl(addrbase + VIA_CRDR_SDBUSMODE); | ||
412 | pm_sdhc_reg->sdblklen_reg = readl(addrbase + VIA_CRDR_SDBLKLEN); | ||
413 | pm_sdhc_reg->sdcurblkcnt_reg = readl(addrbase + VIA_CRDR_SDCURBLKCNT); | ||
414 | pm_sdhc_reg->sdintmask_reg = readl(addrbase + VIA_CRDR_SDINTMASK); | ||
415 | pm_sdhc_reg->sdstatus_reg = readl(addrbase + VIA_CRDR_SDSTATUS); | ||
416 | pm_sdhc_reg->sdrsptmo_reg = readl(addrbase + VIA_CRDR_SDRSPTMO); | ||
417 | pm_sdhc_reg->sdclksel_reg = readl(addrbase + VIA_CRDR_SDCLKSEL); | ||
418 | pm_sdhc_reg->sdextctrl_reg = readl(addrbase + VIA_CRDR_SDEXTCTRL); | ||
419 | } | ||
420 | |||
421 | static void via_restore_sdcreg(struct via_crdr_mmc_host *host) | ||
422 | { | ||
423 | struct sdhcreg *pm_sdhc_reg; | ||
424 | void __iomem *addrbase; | ||
425 | |||
426 | pm_sdhc_reg = &(host->pm_sdhc_reg); | ||
427 | addrbase = host->sdhc_mmiobase; | ||
428 | |||
429 | writel(pm_sdhc_reg->sdcontrol_reg, addrbase + VIA_CRDR_SDCTRL); | ||
430 | writel(pm_sdhc_reg->sdcmdarg_reg, addrbase + VIA_CRDR_SDCARG); | ||
431 | writel(pm_sdhc_reg->sdbusmode_reg, addrbase + VIA_CRDR_SDBUSMODE); | ||
432 | writel(pm_sdhc_reg->sdblklen_reg, addrbase + VIA_CRDR_SDBLKLEN); | ||
433 | writel(pm_sdhc_reg->sdcurblkcnt_reg, addrbase + VIA_CRDR_SDCURBLKCNT); | ||
434 | writel(pm_sdhc_reg->sdintmask_reg, addrbase + VIA_CRDR_SDINTMASK); | ||
435 | writel(pm_sdhc_reg->sdstatus_reg, addrbase + VIA_CRDR_SDSTATUS); | ||
436 | writel(pm_sdhc_reg->sdrsptmo_reg, addrbase + VIA_CRDR_SDRSPTMO); | ||
437 | writel(pm_sdhc_reg->sdclksel_reg, addrbase + VIA_CRDR_SDCLKSEL); | ||
438 | writel(pm_sdhc_reg->sdextctrl_reg, addrbase + VIA_CRDR_SDEXTCTRL); | ||
439 | } | ||
440 | |||
441 | static void via_pwron_sleep(struct via_crdr_mmc_host *sdhost) | ||
442 | { | ||
443 | if (sdhost->quirks & VIA_CRDR_QUIRK_300MS_PWRDELAY) | ||
444 | msleep(300); | ||
445 | else | ||
446 | msleep(3); | ||
447 | } | ||
448 | |||
449 | static void via_set_ddma(struct via_crdr_mmc_host *host, | ||
450 | dma_addr_t dmaaddr, u32 count, int dir, int enirq) | ||
451 | { | ||
452 | void __iomem *addrbase; | ||
453 | u32 ctrl_data = 0; | ||
454 | |||
455 | if (enirq) | ||
456 | ctrl_data |= VIA_CRDR_DMACTRL_ENIRQ; | ||
457 | |||
458 | if (dir) | ||
459 | ctrl_data |= VIA_CRDR_DMACTRL_DIR; | ||
460 | |||
461 | addrbase = host->ddma_mmiobase; | ||
462 | |||
463 | writel(dmaaddr, addrbase + VIA_CRDR_DMABASEADD); | ||
464 | writel(count, addrbase + VIA_CRDR_DMACOUNTER); | ||
465 | writel(ctrl_data, addrbase + VIA_CRDR_DMACTRL); | ||
466 | writel(0x01, addrbase + VIA_CRDR_DMASTART); | ||
467 | |||
468 | /* It seems that our DMA can not work normally with 375kHz clock */ | ||
469 | /* FIXME: don't brute-force 8MHz but use PIO at 375kHz !! */ | ||
470 | addrbase = host->pcictrl_mmiobase; | ||
471 | if (readb(addrbase + VIA_CRDR_PCISDCCLK) == PCI_CLK_375K) { | ||
472 | dev_info(host->mmc->parent, "forcing card speed to 8MHz\n"); | ||
473 | writeb(PCI_CLK_8M, addrbase + VIA_CRDR_PCISDCCLK); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | static void via_sdc_preparedata(struct via_crdr_mmc_host *host, | ||
478 | struct mmc_data *data) | ||
479 | { | ||
480 | void __iomem *addrbase; | ||
481 | u32 blk_reg; | ||
482 | int count; | ||
483 | |||
484 | WARN_ON(host->data); | ||
485 | |||
486 | /* Sanity checks */ | ||
487 | BUG_ON(data->blksz > host->mmc->max_blk_size); | ||
488 | BUG_ON(data->blocks > host->mmc->max_blk_count); | ||
489 | |||
490 | host->data = data; | ||
491 | |||
492 | count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
493 | ((data->flags & MMC_DATA_READ) ? | ||
494 | PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE)); | ||
495 | BUG_ON(count != 1); | ||
496 | |||
497 | via_set_ddma(host, sg_dma_address(data->sg), sg_dma_len(data->sg), | ||
498 | (data->flags & MMC_DATA_WRITE) ? 1 : 0, 1); | ||
499 | |||
500 | addrbase = host->sdhc_mmiobase; | ||
501 | |||
502 | blk_reg = data->blksz - 1; | ||
503 | blk_reg |= VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN; | ||
504 | blk_reg |= (data->blocks) << 16; | ||
505 | |||
506 | writel(blk_reg, addrbase + VIA_CRDR_SDBLKLEN); | ||
507 | } | ||
508 | |||
509 | static void via_sdc_get_response(struct via_crdr_mmc_host *host, | ||
510 | struct mmc_command *cmd) | ||
511 | { | ||
512 | void __iomem *addrbase = host->sdhc_mmiobase; | ||
513 | u32 dwdata0 = readl(addrbase + VIA_CRDR_SDRESP0); | ||
514 | u32 dwdata1 = readl(addrbase + VIA_CRDR_SDRESP1); | ||
515 | u32 dwdata2 = readl(addrbase + VIA_CRDR_SDRESP2); | ||
516 | u32 dwdata3 = readl(addrbase + VIA_CRDR_SDRESP3); | ||
517 | |||
518 | if (cmd->flags & MMC_RSP_136) { | ||
519 | cmd->resp[0] = ((u8) (dwdata1)) | | ||
520 | (((u8) (dwdata0 >> 24)) << 8) | | ||
521 | (((u8) (dwdata0 >> 16)) << 16) | | ||
522 | (((u8) (dwdata0 >> 8)) << 24); | ||
523 | |||
524 | cmd->resp[1] = ((u8) (dwdata2)) | | ||
525 | (((u8) (dwdata1 >> 24)) << 8) | | ||
526 | (((u8) (dwdata1 >> 16)) << 16) | | ||
527 | (((u8) (dwdata1 >> 8)) << 24); | ||
528 | |||
529 | cmd->resp[2] = ((u8) (dwdata3)) | | ||
530 | (((u8) (dwdata2 >> 24)) << 8) | | ||
531 | (((u8) (dwdata2 >> 16)) << 16) | | ||
532 | (((u8) (dwdata2 >> 8)) << 24); | ||
533 | |||
534 | cmd->resp[3] = 0xff | | ||
535 | ((((u8) (dwdata3 >> 24))) << 8) | | ||
536 | (((u8) (dwdata3 >> 16)) << 16) | | ||
537 | (((u8) (dwdata3 >> 8)) << 24); | ||
538 | } else { | ||
539 | dwdata0 >>= 8; | ||
540 | cmd->resp[0] = ((dwdata0 & 0xff) << 24) | | ||
541 | (((dwdata0 >> 8) & 0xff) << 16) | | ||
542 | (((dwdata0 >> 16) & 0xff) << 8) | (dwdata1 & 0xff); | ||
543 | |||
544 | dwdata1 >>= 8; | ||
545 | cmd->resp[1] = ((dwdata1 & 0xff) << 24) | | ||
546 | (((dwdata1 >> 8) & 0xff) << 16) | | ||
547 | (((dwdata1 >> 16) & 0xff) << 8); | ||
548 | } | ||
549 | } | ||
550 | |||
551 | static void via_sdc_send_command(struct via_crdr_mmc_host *host, | ||
552 | struct mmc_command *cmd) | ||
553 | { | ||
554 | void __iomem *addrbase; | ||
555 | struct mmc_data *data; | ||
556 | u32 cmdctrl = 0; | ||
557 | |||
558 | WARN_ON(host->cmd); | ||
559 | |||
560 | data = cmd->data; | ||
561 | mod_timer(&host->timer, jiffies + HZ); | ||
562 | host->cmd = cmd; | ||
563 | |||
564 | /*Command index*/ | ||
565 | cmdctrl = cmd->opcode << 8; | ||
566 | |||
567 | /*Response type*/ | ||
568 | switch (mmc_resp_type(cmd)) { | ||
569 | case MMC_RSP_NONE: | ||
570 | cmdctrl |= VIA_CRDR_SDCTRL_RSP_NONE; | ||
571 | break; | ||
572 | case MMC_RSP_R1: | ||
573 | cmdctrl |= VIA_CRDR_SDCTRL_RSP_R1; | ||
574 | break; | ||
575 | case MMC_RSP_R1B: | ||
576 | cmdctrl |= VIA_CRDR_SDCTRL_RSP_R1B; | ||
577 | break; | ||
578 | case MMC_RSP_R2: | ||
579 | cmdctrl |= VIA_CRDR_SDCTRL_RSP_R2; | ||
580 | break; | ||
581 | case MMC_RSP_R3: | ||
582 | cmdctrl |= VIA_CRDR_SDCTRL_RSP_R3; | ||
583 | break; | ||
584 | default: | ||
585 | pr_err("%s: cmd->flag is not valid\n", mmc_hostname(host->mmc)); | ||
586 | break; | ||
587 | } | ||
588 | |||
589 | if (!(cmd->data)) | ||
590 | goto nodata; | ||
591 | |||
592 | via_sdc_preparedata(host, data); | ||
593 | |||
594 | /*Command control*/ | ||
595 | if (data->blocks > 1) { | ||
596 | if (data->flags & MMC_DATA_WRITE) { | ||
597 | cmdctrl |= VIA_CRDR_SDCTRL_WRITE; | ||
598 | cmdctrl |= VIA_CRDR_SDCTRL_MULTI_WR; | ||
599 | } else { | ||
600 | cmdctrl |= VIA_CRDR_SDCTRL_MULTI_RD; | ||
601 | } | ||
602 | } else { | ||
603 | if (data->flags & MMC_DATA_WRITE) { | ||
604 | cmdctrl |= VIA_CRDR_SDCTRL_WRITE; | ||
605 | cmdctrl |= VIA_CRDR_SDCTRL_SINGLE_WR; | ||
606 | } else { | ||
607 | cmdctrl |= VIA_CRDR_SDCTRL_SINGLE_RD; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | nodata: | ||
612 | if (cmd == host->mrq->stop) | ||
613 | cmdctrl |= VIA_CRDR_SDCTRL_STOP; | ||
614 | |||
615 | cmdctrl |= VIA_CRDR_SDCTRL_START; | ||
616 | |||
617 | addrbase = host->sdhc_mmiobase; | ||
618 | writel(cmd->arg, addrbase + VIA_CRDR_SDCARG); | ||
619 | writel(cmdctrl, addrbase + VIA_CRDR_SDCTRL); | ||
620 | } | ||
621 | |||
622 | static void via_sdc_finish_data(struct via_crdr_mmc_host *host) | ||
623 | { | ||
624 | struct mmc_data *data; | ||
625 | |||
626 | BUG_ON(!host->data); | ||
627 | |||
628 | data = host->data; | ||
629 | host->data = NULL; | ||
630 | |||
631 | if (data->error) | ||
632 | data->bytes_xfered = 0; | ||
633 | else | ||
634 | data->bytes_xfered = data->blocks * data->blksz; | ||
635 | |||
636 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | ||
637 | ((data->flags & MMC_DATA_READ) ? | ||
638 | PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE)); | ||
639 | |||
640 | if (data->stop) | ||
641 | via_sdc_send_command(host, data->stop); | ||
642 | else | ||
643 | tasklet_schedule(&host->finish_tasklet); | ||
644 | } | ||
645 | |||
646 | static void via_sdc_finish_command(struct via_crdr_mmc_host *host) | ||
647 | { | ||
648 | via_sdc_get_response(host, host->cmd); | ||
649 | |||
650 | host->cmd->error = 0; | ||
651 | |||
652 | if (!host->cmd->data) | ||
653 | tasklet_schedule(&host->finish_tasklet); | ||
654 | |||
655 | host->cmd = NULL; | ||
656 | } | ||
657 | |||
658 | static void via_sdc_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
659 | { | ||
660 | void __iomem *addrbase; | ||
661 | struct via_crdr_mmc_host *host; | ||
662 | unsigned long flags; | ||
663 | u16 status; | ||
664 | |||
665 | host = mmc_priv(mmc); | ||
666 | |||
667 | spin_lock_irqsave(&host->lock, flags); | ||
668 | |||
669 | addrbase = host->pcictrl_mmiobase; | ||
670 | writeb(VIA_CRDR_PCIDMACLK_SDC, addrbase + VIA_CRDR_PCIDMACLK); | ||
671 | |||
672 | status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS); | ||
673 | status &= VIA_CRDR_SDSTS_W1C_MASK; | ||
674 | writew(status, host->sdhc_mmiobase + VIA_CRDR_SDSTATUS); | ||
675 | |||
676 | WARN_ON(host->mrq != NULL); | ||
677 | host->mrq = mrq; | ||
678 | |||
679 | status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS); | ||
680 | if (!(status & VIA_CRDR_SDSTS_SLOTG) || host->reject) { | ||
681 | host->mrq->cmd->error = -ENOMEDIUM; | ||
682 | tasklet_schedule(&host->finish_tasklet); | ||
683 | } else { | ||
684 | via_sdc_send_command(host, mrq->cmd); | ||
685 | } | ||
686 | |||
687 | mmiowb(); | ||
688 | spin_unlock_irqrestore(&host->lock, flags); | ||
689 | } | ||
690 | |||
691 | static void via_sdc_set_power(struct via_crdr_mmc_host *host, | ||
692 | unsigned short power, unsigned int on) | ||
693 | { | ||
694 | unsigned long flags; | ||
695 | u8 gatt; | ||
696 | |||
697 | spin_lock_irqsave(&host->lock, flags); | ||
698 | |||
699 | host->power = (1 << power); | ||
700 | |||
701 | gatt = readb(host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
702 | if (host->power == MMC_VDD_165_195) | ||
703 | gatt &= ~VIA_CRDR_PCICLKGATT_3V3; | ||
704 | else | ||
705 | gatt |= VIA_CRDR_PCICLKGATT_3V3; | ||
706 | if (on) | ||
707 | gatt |= VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
708 | else | ||
709 | gatt &= ~VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
710 | writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
711 | |||
712 | mmiowb(); | ||
713 | spin_unlock_irqrestore(&host->lock, flags); | ||
714 | |||
715 | via_pwron_sleep(host); | ||
716 | } | ||
717 | |||
718 | static void via_sdc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
719 | { | ||
720 | struct via_crdr_mmc_host *host; | ||
721 | unsigned long flags; | ||
722 | void __iomem *addrbase; | ||
723 | u32 org_data, sdextctrl; | ||
724 | u8 clock; | ||
725 | |||
726 | host = mmc_priv(mmc); | ||
727 | |||
728 | spin_lock_irqsave(&host->lock, flags); | ||
729 | |||
730 | addrbase = host->sdhc_mmiobase; | ||
731 | org_data = readl(addrbase + VIA_CRDR_SDBUSMODE); | ||
732 | sdextctrl = readl(addrbase + VIA_CRDR_SDEXTCTRL); | ||
733 | |||
734 | if (ios->bus_width == MMC_BUS_WIDTH_1) | ||
735 | org_data &= ~VIA_CRDR_SDMODE_4BIT; | ||
736 | else | ||
737 | org_data |= VIA_CRDR_SDMODE_4BIT; | ||
738 | |||
739 | if (ios->power_mode == MMC_POWER_OFF) | ||
740 | org_data &= ~VIA_CRDR_SDMODE_CLK_ON; | ||
741 | else | ||
742 | org_data |= VIA_CRDR_SDMODE_CLK_ON; | ||
743 | |||
744 | if (ios->timing == MMC_TIMING_SD_HS) | ||
745 | sdextctrl |= VIA_CRDR_SDEXTCTRL_HISPD; | ||
746 | else | ||
747 | sdextctrl &= ~VIA_CRDR_SDEXTCTRL_HISPD; | ||
748 | |||
749 | writel(org_data, addrbase + VIA_CRDR_SDBUSMODE); | ||
750 | writel(sdextctrl, addrbase + VIA_CRDR_SDEXTCTRL); | ||
751 | |||
752 | if (ios->clock >= 48000000) | ||
753 | clock = PCI_CLK_48M; | ||
754 | else if (ios->clock >= 33000000) | ||
755 | clock = PCI_CLK_33M; | ||
756 | else if (ios->clock >= 24000000) | ||
757 | clock = PCI_CLK_24M; | ||
758 | else if (ios->clock >= 16000000) | ||
759 | clock = PCI_CLK_16M; | ||
760 | else if (ios->clock >= 12000000) | ||
761 | clock = PCI_CLK_12M; | ||
762 | else if (ios->clock >= 8000000) | ||
763 | clock = PCI_CLK_8M; | ||
764 | else | ||
765 | clock = PCI_CLK_375K; | ||
766 | |||
767 | addrbase = host->pcictrl_mmiobase; | ||
768 | if (readb(addrbase + VIA_CRDR_PCISDCCLK) != clock) | ||
769 | writeb(clock, addrbase + VIA_CRDR_PCISDCCLK); | ||
770 | |||
771 | mmiowb(); | ||
772 | spin_unlock_irqrestore(&host->lock, flags); | ||
773 | |||
774 | if (ios->power_mode != MMC_POWER_OFF) | ||
775 | via_sdc_set_power(host, ios->vdd, 1); | ||
776 | else | ||
777 | via_sdc_set_power(host, ios->vdd, 0); | ||
778 | } | ||
779 | |||
780 | static int via_sdc_get_ro(struct mmc_host *mmc) | ||
781 | { | ||
782 | struct via_crdr_mmc_host *host; | ||
783 | unsigned long flags; | ||
784 | u16 status; | ||
785 | |||
786 | host = mmc_priv(mmc); | ||
787 | |||
788 | spin_lock_irqsave(&host->lock, flags); | ||
789 | |||
790 | status = readw(host->sdhc_mmiobase + VIA_CRDR_SDSTATUS); | ||
791 | |||
792 | spin_unlock_irqrestore(&host->lock, flags); | ||
793 | |||
794 | return !(status & VIA_CRDR_SDSTS_WP); | ||
795 | } | ||
796 | |||
797 | static const struct mmc_host_ops via_sdc_ops = { | ||
798 | .request = via_sdc_request, | ||
799 | .set_ios = via_sdc_set_ios, | ||
800 | .get_ro = via_sdc_get_ro, | ||
801 | }; | ||
802 | |||
803 | static void via_reset_pcictrl(struct via_crdr_mmc_host *host) | ||
804 | { | ||
805 | void __iomem *addrbase; | ||
806 | unsigned long flags; | ||
807 | u8 gatt; | ||
808 | |||
809 | addrbase = host->pcictrl_mmiobase; | ||
810 | |||
811 | spin_lock_irqsave(&host->lock, flags); | ||
812 | |||
813 | via_save_pcictrlreg(host); | ||
814 | via_save_sdcreg(host); | ||
815 | |||
816 | spin_unlock_irqrestore(&host->lock, flags); | ||
817 | |||
818 | gatt = VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
819 | if (host->power == MMC_VDD_165_195) | ||
820 | gatt &= VIA_CRDR_PCICLKGATT_3V3; | ||
821 | else | ||
822 | gatt |= VIA_CRDR_PCICLKGATT_3V3; | ||
823 | writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
824 | via_pwron_sleep(host); | ||
825 | gatt |= VIA_CRDR_PCICLKGATT_SFTRST; | ||
826 | writeb(gatt, host->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
827 | msleep(3); | ||
828 | |||
829 | spin_lock_irqsave(&host->lock, flags); | ||
830 | |||
831 | via_restore_pcictrlreg(host); | ||
832 | via_restore_sdcreg(host); | ||
833 | |||
834 | mmiowb(); | ||
835 | spin_unlock_irqrestore(&host->lock, flags); | ||
836 | } | ||
837 | |||
838 | static void via_sdc_cmd_isr(struct via_crdr_mmc_host *host, u16 intmask) | ||
839 | { | ||
840 | BUG_ON(intmask == 0); | ||
841 | |||
842 | if (!host->cmd) { | ||
843 | pr_err("%s: Got command interrupt 0x%x even " | ||
844 | "though no command operation was in progress.\n", | ||
845 | mmc_hostname(host->mmc), intmask); | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | if (intmask & VIA_CRDR_SDSTS_CRTO) | ||
850 | host->cmd->error = -ETIMEDOUT; | ||
851 | else if (intmask & VIA_CRDR_SDSTS_SC) | ||
852 | host->cmd->error = -EILSEQ; | ||
853 | |||
854 | if (host->cmd->error) | ||
855 | tasklet_schedule(&host->finish_tasklet); | ||
856 | else if (intmask & VIA_CRDR_SDSTS_CRD) | ||
857 | via_sdc_finish_command(host); | ||
858 | } | ||
859 | |||
860 | static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask) | ||
861 | { | ||
862 | BUG_ON(intmask == 0); | ||
863 | |||
864 | if (intmask & VIA_CRDR_SDSTS_DT) | ||
865 | host->data->error = -ETIMEDOUT; | ||
866 | else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)) | ||
867 | host->data->error = -EILSEQ; | ||
868 | |||
869 | via_sdc_finish_data(host); | ||
870 | } | ||
871 | |||
872 | static irqreturn_t via_sdc_isr(int irq, void *dev_id) | ||
873 | { | ||
874 | struct via_crdr_mmc_host *sdhost = dev_id; | ||
875 | void __iomem *addrbase; | ||
876 | u8 pci_status; | ||
877 | u16 sd_status; | ||
878 | irqreturn_t result; | ||
879 | |||
880 | if (!sdhost) | ||
881 | return IRQ_NONE; | ||
882 | |||
883 | spin_lock(&sdhost->lock); | ||
884 | |||
885 | addrbase = sdhost->pcictrl_mmiobase; | ||
886 | pci_status = readb(addrbase + VIA_CRDR_PCIINTSTATUS); | ||
887 | if (!(pci_status & VIA_CRDR_PCIINTSTATUS_SDC)) { | ||
888 | result = IRQ_NONE; | ||
889 | goto out; | ||
890 | } | ||
891 | |||
892 | addrbase = sdhost->sdhc_mmiobase; | ||
893 | sd_status = readw(addrbase + VIA_CRDR_SDSTATUS); | ||
894 | sd_status &= VIA_CRDR_SDSTS_INT_MASK; | ||
895 | sd_status &= ~VIA_CRDR_SDSTS_IGN_MASK; | ||
896 | if (!sd_status) { | ||
897 | result = IRQ_NONE; | ||
898 | goto out; | ||
899 | } | ||
900 | |||
901 | if (sd_status & VIA_CRDR_SDSTS_CIR) { | ||
902 | writew(sd_status & VIA_CRDR_SDSTS_CIR, | ||
903 | addrbase + VIA_CRDR_SDSTATUS); | ||
904 | |||
905 | schedule_work(&sdhost->carddet_work); | ||
906 | } | ||
907 | |||
908 | sd_status &= ~VIA_CRDR_SDSTS_CIR; | ||
909 | if (sd_status & VIA_CRDR_SDSTS_CMD_MASK) { | ||
910 | writew(sd_status & VIA_CRDR_SDSTS_CMD_MASK, | ||
911 | addrbase + VIA_CRDR_SDSTATUS); | ||
912 | via_sdc_cmd_isr(sdhost, sd_status & VIA_CRDR_SDSTS_CMD_MASK); | ||
913 | } | ||
914 | if (sd_status & VIA_CRDR_SDSTS_DATA_MASK) { | ||
915 | writew(sd_status & VIA_CRDR_SDSTS_DATA_MASK, | ||
916 | addrbase + VIA_CRDR_SDSTATUS); | ||
917 | via_sdc_data_isr(sdhost, sd_status & VIA_CRDR_SDSTS_DATA_MASK); | ||
918 | } | ||
919 | |||
920 | sd_status &= ~(VIA_CRDR_SDSTS_CMD_MASK | VIA_CRDR_SDSTS_DATA_MASK); | ||
921 | if (sd_status) { | ||
922 | pr_err("%s: Unexpected interrupt 0x%x\n", | ||
923 | mmc_hostname(sdhost->mmc), sd_status); | ||
924 | writew(sd_status, addrbase + VIA_CRDR_SDSTATUS); | ||
925 | } | ||
926 | |||
927 | result = IRQ_HANDLED; | ||
928 | |||
929 | mmiowb(); | ||
930 | out: | ||
931 | spin_unlock(&sdhost->lock); | ||
932 | |||
933 | return result; | ||
934 | } | ||
935 | |||
936 | static void via_sdc_timeout(unsigned long ulongdata) | ||
937 | { | ||
938 | struct via_crdr_mmc_host *sdhost; | ||
939 | unsigned long flags; | ||
940 | |||
941 | sdhost = (struct via_crdr_mmc_host *)ulongdata; | ||
942 | |||
943 | spin_lock_irqsave(&sdhost->lock, flags); | ||
944 | |||
945 | if (sdhost->mrq) { | ||
946 | pr_err("%s: Timeout waiting for hardware interrupt." | ||
947 | "cmd:0x%x\n", mmc_hostname(sdhost->mmc), | ||
948 | sdhost->mrq->cmd->opcode); | ||
949 | |||
950 | if (sdhost->data) { | ||
951 | writel(VIA_CRDR_DMACTRL_SFTRST, | ||
952 | sdhost->ddma_mmiobase + VIA_CRDR_DMACTRL); | ||
953 | sdhost->data->error = -ETIMEDOUT; | ||
954 | via_sdc_finish_data(sdhost); | ||
955 | } else { | ||
956 | if (sdhost->cmd) | ||
957 | sdhost->cmd->error = -ETIMEDOUT; | ||
958 | else | ||
959 | sdhost->mrq->cmd->error = -ETIMEDOUT; | ||
960 | tasklet_schedule(&sdhost->finish_tasklet); | ||
961 | } | ||
962 | } | ||
963 | |||
964 | mmiowb(); | ||
965 | spin_unlock_irqrestore(&sdhost->lock, flags); | ||
966 | } | ||
967 | |||
968 | static void via_sdc_tasklet_finish(unsigned long param) | ||
969 | { | ||
970 | struct via_crdr_mmc_host *host; | ||
971 | unsigned long flags; | ||
972 | struct mmc_request *mrq; | ||
973 | |||
974 | host = (struct via_crdr_mmc_host *)param; | ||
975 | |||
976 | spin_lock_irqsave(&host->lock, flags); | ||
977 | |||
978 | del_timer(&host->timer); | ||
979 | mrq = host->mrq; | ||
980 | host->mrq = NULL; | ||
981 | host->cmd = NULL; | ||
982 | host->data = NULL; | ||
983 | |||
984 | spin_unlock_irqrestore(&host->lock, flags); | ||
985 | |||
986 | mmc_request_done(host->mmc, mrq); | ||
987 | } | ||
988 | |||
989 | static void via_sdc_card_detect(struct work_struct *work) | ||
990 | { | ||
991 | struct via_crdr_mmc_host *host; | ||
992 | void __iomem *addrbase; | ||
993 | unsigned long flags; | ||
994 | u16 status; | ||
995 | |||
996 | host = container_of(work, struct via_crdr_mmc_host, carddet_work); | ||
997 | |||
998 | addrbase = host->ddma_mmiobase; | ||
999 | writel(VIA_CRDR_DMACTRL_SFTRST, addrbase + VIA_CRDR_DMACTRL); | ||
1000 | |||
1001 | spin_lock_irqsave(&host->lock, flags); | ||
1002 | |||
1003 | addrbase = host->pcictrl_mmiobase; | ||
1004 | writeb(VIA_CRDR_PCIDMACLK_SDC, addrbase + VIA_CRDR_PCIDMACLK); | ||
1005 | |||
1006 | addrbase = host->sdhc_mmiobase; | ||
1007 | status = readw(addrbase + VIA_CRDR_SDSTATUS); | ||
1008 | if (!(status & VIA_CRDR_SDSTS_SLOTG)) { | ||
1009 | if (host->mrq) { | ||
1010 | pr_err("%s: Card removed during transfer!\n", | ||
1011 | mmc_hostname(host->mmc)); | ||
1012 | host->mrq->cmd->error = -ENOMEDIUM; | ||
1013 | tasklet_schedule(&host->finish_tasklet); | ||
1014 | } | ||
1015 | |||
1016 | mmiowb(); | ||
1017 | spin_unlock_irqrestore(&host->lock, flags); | ||
1018 | |||
1019 | via_reset_pcictrl(host); | ||
1020 | |||
1021 | spin_lock_irqsave(&host->lock, flags); | ||
1022 | } | ||
1023 | |||
1024 | mmiowb(); | ||
1025 | spin_unlock_irqrestore(&host->lock, flags); | ||
1026 | |||
1027 | via_print_pcictrl(host); | ||
1028 | via_print_sdchc(host); | ||
1029 | |||
1030 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | ||
1031 | } | ||
1032 | |||
1033 | static void via_init_mmc_host(struct via_crdr_mmc_host *host) | ||
1034 | { | ||
1035 | struct mmc_host *mmc = host->mmc; | ||
1036 | void __iomem *addrbase; | ||
1037 | u32 lenreg; | ||
1038 | u32 status; | ||
1039 | |||
1040 | init_timer(&host->timer); | ||
1041 | host->timer.data = (unsigned long)host; | ||
1042 | host->timer.function = via_sdc_timeout; | ||
1043 | |||
1044 | spin_lock_init(&host->lock); | ||
1045 | |||
1046 | mmc->f_min = VIA_CRDR_MIN_CLOCK; | ||
1047 | mmc->f_max = VIA_CRDR_MAX_CLOCK; | ||
1048 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; | ||
1049 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED; | ||
1050 | mmc->ops = &via_sdc_ops; | ||
1051 | |||
1052 | /*Hardware cannot do scatter lists*/ | ||
1053 | mmc->max_hw_segs = 1; | ||
1054 | mmc->max_phys_segs = 1; | ||
1055 | |||
1056 | mmc->max_blk_size = VIA_CRDR_MAX_BLOCK_LENGTH; | ||
1057 | mmc->max_blk_count = VIA_CRDR_MAX_BLOCK_COUNT; | ||
1058 | |||
1059 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; | ||
1060 | mmc->max_req_size = mmc->max_seg_size; | ||
1061 | |||
1062 | INIT_WORK(&host->carddet_work, via_sdc_card_detect); | ||
1063 | |||
1064 | tasklet_init(&host->finish_tasklet, via_sdc_tasklet_finish, | ||
1065 | (unsigned long)host); | ||
1066 | |||
1067 | addrbase = host->sdhc_mmiobase; | ||
1068 | writel(0x0, addrbase + VIA_CRDR_SDINTMASK); | ||
1069 | msleep(1); | ||
1070 | |||
1071 | lenreg = VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN; | ||
1072 | writel(lenreg, addrbase + VIA_CRDR_SDBLKLEN); | ||
1073 | |||
1074 | status = readw(addrbase + VIA_CRDR_SDSTATUS); | ||
1075 | status &= VIA_CRDR_SDSTS_W1C_MASK; | ||
1076 | writew(status, addrbase + VIA_CRDR_SDSTATUS); | ||
1077 | |||
1078 | status = readw(addrbase + VIA_CRDR_SDSTATUS2); | ||
1079 | status |= VIA_CRDR_SDSTS_CFE; | ||
1080 | writew(status, addrbase + VIA_CRDR_SDSTATUS2); | ||
1081 | |||
1082 | writeb(0x0, addrbase + VIA_CRDR_SDEXTCTRL); | ||
1083 | |||
1084 | writel(VIA_CRDR_SDACTIVE_INTMASK, addrbase + VIA_CRDR_SDINTMASK); | ||
1085 | msleep(1); | ||
1086 | } | ||
1087 | |||
1088 | static int __devinit via_sd_probe(struct pci_dev *pcidev, | ||
1089 | const struct pci_device_id *id) | ||
1090 | { | ||
1091 | struct mmc_host *mmc; | ||
1092 | struct via_crdr_mmc_host *sdhost; | ||
1093 | u32 base, len; | ||
1094 | u8 rev, gatt; | ||
1095 | int ret; | ||
1096 | |||
1097 | pci_read_config_byte(pcidev, PCI_CLASS_REVISION, &rev); | ||
1098 | pr_info(DRV_NAME | ||
1099 | ": VIA SDMMC controller found at %s [%04x:%04x] (rev %x)\n", | ||
1100 | pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device, | ||
1101 | (int)rev); | ||
1102 | |||
1103 | ret = pci_enable_device(pcidev); | ||
1104 | if (ret) | ||
1105 | return ret; | ||
1106 | |||
1107 | ret = pci_request_regions(pcidev, DRV_NAME); | ||
1108 | if (ret) | ||
1109 | goto disable; | ||
1110 | |||
1111 | pci_write_config_byte(pcidev, VIA_CRDR_PCI_WORK_MODE, 0); | ||
1112 | pci_write_config_byte(pcidev, VIA_CRDR_PCI_DBG_MODE, 0); | ||
1113 | |||
1114 | mmc = mmc_alloc_host(sizeof(struct via_crdr_mmc_host), &pcidev->dev); | ||
1115 | if (!mmc) { | ||
1116 | ret = -ENOMEM; | ||
1117 | goto release; | ||
1118 | } | ||
1119 | |||
1120 | sdhost = mmc_priv(mmc); | ||
1121 | sdhost->mmc = mmc; | ||
1122 | dev_set_drvdata(&pcidev->dev, sdhost); | ||
1123 | |||
1124 | len = pci_resource_len(pcidev, 0); | ||
1125 | base = pci_resource_start(pcidev, 0); | ||
1126 | sdhost->mmiobase = ioremap_nocache(base, len); | ||
1127 | if (!sdhost->mmiobase) { | ||
1128 | ret = -ENOMEM; | ||
1129 | goto free_mmc_host; | ||
1130 | } | ||
1131 | |||
1132 | sdhost->sdhc_mmiobase = | ||
1133 | sdhost->mmiobase + VIA_CRDR_SDC_OFF; | ||
1134 | sdhost->ddma_mmiobase = | ||
1135 | sdhost->mmiobase + VIA_CRDR_DDMA_OFF; | ||
1136 | sdhost->pcictrl_mmiobase = | ||
1137 | sdhost->mmiobase + VIA_CRDR_PCICTRL_OFF; | ||
1138 | |||
1139 | sdhost->power = MMC_VDD_165_195; | ||
1140 | |||
1141 | gatt = VIA_CRDR_PCICLKGATT_3V3 | VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
1142 | writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1143 | via_pwron_sleep(sdhost); | ||
1144 | gatt |= VIA_CRDR_PCICLKGATT_SFTRST; | ||
1145 | writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1146 | msleep(3); | ||
1147 | |||
1148 | via_init_mmc_host(sdhost); | ||
1149 | |||
1150 | ret = | ||
1151 | request_irq(pcidev->irq, via_sdc_isr, IRQF_SHARED, DRV_NAME, | ||
1152 | sdhost); | ||
1153 | if (ret) | ||
1154 | goto unmap; | ||
1155 | |||
1156 | writeb(VIA_CRDR_PCIINTCTRL_SDCIRQEN, | ||
1157 | sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL); | ||
1158 | writeb(VIA_CRDR_PCITMOCTRL_1024MS, | ||
1159 | sdhost->pcictrl_mmiobase + VIA_CRDR_PCITMOCTRL); | ||
1160 | |||
1161 | /* device-specific quirks */ | ||
1162 | if (pcidev->subsystem_vendor == PCI_VENDOR_ID_LENOVO && | ||
1163 | pcidev->subsystem_device == 0x3891) | ||
1164 | sdhost->quirks = VIA_CRDR_QUIRK_300MS_PWRDELAY; | ||
1165 | |||
1166 | mmc_add_host(mmc); | ||
1167 | |||
1168 | return 0; | ||
1169 | |||
1170 | unmap: | ||
1171 | iounmap(sdhost->mmiobase); | ||
1172 | free_mmc_host: | ||
1173 | dev_set_drvdata(&pcidev->dev, NULL); | ||
1174 | mmc_free_host(mmc); | ||
1175 | release: | ||
1176 | pci_release_regions(pcidev); | ||
1177 | disable: | ||
1178 | pci_disable_device(pcidev); | ||
1179 | |||
1180 | return ret; | ||
1181 | } | ||
1182 | |||
1183 | static void __devexit via_sd_remove(struct pci_dev *pcidev) | ||
1184 | { | ||
1185 | struct via_crdr_mmc_host *sdhost = pci_get_drvdata(pcidev); | ||
1186 | unsigned long flags; | ||
1187 | u8 gatt; | ||
1188 | |||
1189 | spin_lock_irqsave(&sdhost->lock, flags); | ||
1190 | |||
1191 | /* Ensure we don't accept more commands from mmc layer */ | ||
1192 | sdhost->reject = 1; | ||
1193 | |||
1194 | /* Disable generating further interrupts */ | ||
1195 | writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL); | ||
1196 | mmiowb(); | ||
1197 | |||
1198 | if (sdhost->mrq) { | ||
1199 | printk(KERN_ERR "%s: Controller removed during " | ||
1200 | "transfer\n", mmc_hostname(sdhost->mmc)); | ||
1201 | |||
1202 | /* make sure all DMA is stopped */ | ||
1203 | writel(VIA_CRDR_DMACTRL_SFTRST, | ||
1204 | sdhost->ddma_mmiobase + VIA_CRDR_DMACTRL); | ||
1205 | mmiowb(); | ||
1206 | sdhost->mrq->cmd->error = -ENOMEDIUM; | ||
1207 | if (sdhost->mrq->stop) | ||
1208 | sdhost->mrq->stop->error = -ENOMEDIUM; | ||
1209 | tasklet_schedule(&sdhost->finish_tasklet); | ||
1210 | } | ||
1211 | spin_unlock_irqrestore(&sdhost->lock, flags); | ||
1212 | |||
1213 | mmc_remove_host(sdhost->mmc); | ||
1214 | |||
1215 | free_irq(pcidev->irq, sdhost); | ||
1216 | |||
1217 | del_timer_sync(&sdhost->timer); | ||
1218 | |||
1219 | tasklet_kill(&sdhost->finish_tasklet); | ||
1220 | |||
1221 | /* switch off power */ | ||
1222 | gatt = readb(sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1223 | gatt &= ~VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
1224 | writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1225 | |||
1226 | iounmap(sdhost->mmiobase); | ||
1227 | dev_set_drvdata(&pcidev->dev, NULL); | ||
1228 | mmc_free_host(sdhost->mmc); | ||
1229 | pci_release_regions(pcidev); | ||
1230 | pci_disable_device(pcidev); | ||
1231 | |||
1232 | pr_info(DRV_NAME | ||
1233 | ": VIA SDMMC controller at %s [%04x:%04x] has been removed\n", | ||
1234 | pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device); | ||
1235 | } | ||
1236 | |||
1237 | #ifdef CONFIG_PM | ||
1238 | |||
1239 | static void via_init_sdc_pm(struct via_crdr_mmc_host *host) | ||
1240 | { | ||
1241 | struct sdhcreg *pm_sdhcreg; | ||
1242 | void __iomem *addrbase; | ||
1243 | u32 lenreg; | ||
1244 | u16 status; | ||
1245 | |||
1246 | pm_sdhcreg = &(host->pm_sdhc_reg); | ||
1247 | addrbase = host->sdhc_mmiobase; | ||
1248 | |||
1249 | writel(0x0, addrbase + VIA_CRDR_SDINTMASK); | ||
1250 | |||
1251 | lenreg = VIA_CRDR_SDBLKLEN_GPIDET | VIA_CRDR_SDBLKLEN_INTEN; | ||
1252 | writel(lenreg, addrbase + VIA_CRDR_SDBLKLEN); | ||
1253 | |||
1254 | status = readw(addrbase + VIA_CRDR_SDSTATUS); | ||
1255 | status &= VIA_CRDR_SDSTS_W1C_MASK; | ||
1256 | writew(status, addrbase + VIA_CRDR_SDSTATUS); | ||
1257 | |||
1258 | status = readw(addrbase + VIA_CRDR_SDSTATUS2); | ||
1259 | status |= VIA_CRDR_SDSTS_CFE; | ||
1260 | writew(status, addrbase + VIA_CRDR_SDSTATUS2); | ||
1261 | |||
1262 | writel(pm_sdhcreg->sdcontrol_reg, addrbase + VIA_CRDR_SDCTRL); | ||
1263 | writel(pm_sdhcreg->sdcmdarg_reg, addrbase + VIA_CRDR_SDCARG); | ||
1264 | writel(pm_sdhcreg->sdintmask_reg, addrbase + VIA_CRDR_SDINTMASK); | ||
1265 | writel(pm_sdhcreg->sdrsptmo_reg, addrbase + VIA_CRDR_SDRSPTMO); | ||
1266 | writel(pm_sdhcreg->sdclksel_reg, addrbase + VIA_CRDR_SDCLKSEL); | ||
1267 | writel(pm_sdhcreg->sdextctrl_reg, addrbase + VIA_CRDR_SDEXTCTRL); | ||
1268 | |||
1269 | via_print_pcictrl(host); | ||
1270 | via_print_sdchc(host); | ||
1271 | } | ||
1272 | |||
1273 | static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state) | ||
1274 | { | ||
1275 | struct via_crdr_mmc_host *host; | ||
1276 | int ret = 0; | ||
1277 | |||
1278 | host = pci_get_drvdata(pcidev); | ||
1279 | |||
1280 | via_save_pcictrlreg(host); | ||
1281 | via_save_sdcreg(host); | ||
1282 | |||
1283 | ret = mmc_suspend_host(host->mmc, state); | ||
1284 | |||
1285 | pci_save_state(pcidev); | ||
1286 | pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); | ||
1287 | pci_disable_device(pcidev); | ||
1288 | pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); | ||
1289 | |||
1290 | return ret; | ||
1291 | } | ||
1292 | |||
1293 | static int via_sd_resume(struct pci_dev *pcidev) | ||
1294 | { | ||
1295 | struct via_crdr_mmc_host *sdhost; | ||
1296 | int ret = 0; | ||
1297 | u8 gatt; | ||
1298 | |||
1299 | sdhost = pci_get_drvdata(pcidev); | ||
1300 | |||
1301 | gatt = VIA_CRDR_PCICLKGATT_PAD_PWRON; | ||
1302 | if (sdhost->power == MMC_VDD_165_195) | ||
1303 | gatt &= ~VIA_CRDR_PCICLKGATT_3V3; | ||
1304 | else | ||
1305 | gatt |= VIA_CRDR_PCICLKGATT_3V3; | ||
1306 | writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1307 | via_pwron_sleep(sdhost); | ||
1308 | gatt |= VIA_CRDR_PCICLKGATT_SFTRST; | ||
1309 | writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); | ||
1310 | msleep(3); | ||
1311 | |||
1312 | msleep(100); | ||
1313 | |||
1314 | pci_set_power_state(pcidev, PCI_D0); | ||
1315 | pci_restore_state(pcidev); | ||
1316 | ret = pci_enable_device(pcidev); | ||
1317 | if (ret) | ||
1318 | return ret; | ||
1319 | |||
1320 | via_restore_pcictrlreg(sdhost); | ||
1321 | via_init_sdc_pm(sdhost); | ||
1322 | |||
1323 | ret = mmc_resume_host(sdhost->mmc); | ||
1324 | |||
1325 | return ret; | ||
1326 | } | ||
1327 | |||
1328 | #else /* CONFIG_PM */ | ||
1329 | |||
1330 | #define via_sd_suspend NULL | ||
1331 | #define via_sd_resume NULL | ||
1332 | |||
1333 | #endif /* CONFIG_PM */ | ||
1334 | |||
1335 | static struct pci_driver via_sd_driver = { | ||
1336 | .name = DRV_NAME, | ||
1337 | .id_table = via_ids, | ||
1338 | .probe = via_sd_probe, | ||
1339 | .remove = __devexit_p(via_sd_remove), | ||
1340 | .suspend = via_sd_suspend, | ||
1341 | .resume = via_sd_resume, | ||
1342 | }; | ||
1343 | |||
1344 | static int __init via_sd_drv_init(void) | ||
1345 | { | ||
1346 | pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver " | ||
1347 | "(C) 2008 VIA Technologies, Inc.\n"); | ||
1348 | |||
1349 | return pci_register_driver(&via_sd_driver); | ||
1350 | } | ||
1351 | |||
1352 | static void __exit via_sd_drv_exit(void) | ||
1353 | { | ||
1354 | pci_unregister_driver(&via_sd_driver); | ||
1355 | } | ||
1356 | |||
1357 | module_init(via_sd_drv_init); | ||
1358 | module_exit(via_sd_drv_exit); | ||
1359 | |||
1360 | MODULE_LICENSE("GPL"); | ||
1361 | MODULE_AUTHOR("VIA Technologies Inc."); | ||
1362 | MODULE_DESCRIPTION("VIA SD/MMC Card Interface driver"); | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index cf260d848eb9..d006e93d5c93 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -810,11 +810,11 @@ extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end); | |||
810 | 810 | ||
811 | #ifdef CONFIG_MMU | 811 | #ifdef CONFIG_MMU |
812 | extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 812 | extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
813 | unsigned long address, int write_access); | 813 | unsigned long address, unsigned int flags); |
814 | #else | 814 | #else |
815 | static inline int handle_mm_fault(struct mm_struct *mm, | 815 | static inline int handle_mm_fault(struct mm_struct *mm, |
816 | struct vm_area_struct *vma, unsigned long address, | 816 | struct vm_area_struct *vma, unsigned long address, |
817 | int write_access) | 817 | unsigned int flags) |
818 | { | 818 | { |
819 | /* should never happen if there's no MMU */ | 819 | /* should never happen if there's no MMU */ |
820 | BUG(); | 820 | BUG(); |
diff --git a/ipc/util.h b/ipc/util.h index ab3ebf2621b9..764b51a37a6a 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #ifndef _IPC_UTIL_H | 10 | #ifndef _IPC_UTIL_H |
11 | #define _IPC_UTIL_H | 11 | #define _IPC_UTIL_H |
12 | 12 | ||
13 | #include <linux/unistd.h> | ||
13 | #include <linux/err.h> | 14 | #include <linux/err.h> |
14 | 15 | ||
15 | #define SEQ_MULTIPLIER (IPCMNI) | 16 | #define SEQ_MULTIPLIER (IPCMNI) |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 6b0c2d8a2129..23067ab1a73c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -472,7 +472,7 @@ config LOCKDEP | |||
472 | bool | 472 | bool |
473 | depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT | 473 | depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT |
474 | select STACKTRACE | 474 | select STACKTRACE |
475 | select FRAME_POINTER if !X86 && !MIPS && !PPC && !ARM_UNWIND && !S390 | 475 | select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 |
476 | select KALLSYMS | 476 | select KALLSYMS |
477 | select KALLSYMS_ALL | 477 | select KALLSYMS_ALL |
478 | 478 | ||
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index ad65fc0317d9..3b93129a968c 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -262,11 +262,12 @@ static struct dma_debug_entry *hash_bucket_find(struct hash_bucket *bucket, | |||
262 | */ | 262 | */ |
263 | matches += 1; | 263 | matches += 1; |
264 | match_lvl = 0; | 264 | match_lvl = 0; |
265 | entry->size == ref->size ? ++match_lvl : match_lvl; | 265 | entry->size == ref->size ? ++match_lvl : 0; |
266 | entry->type == ref->type ? ++match_lvl : match_lvl; | 266 | entry->type == ref->type ? ++match_lvl : 0; |
267 | entry->direction == ref->direction ? ++match_lvl : match_lvl; | 267 | entry->direction == ref->direction ? ++match_lvl : 0; |
268 | entry->sg_call_ents == ref->sg_call_ents ? ++match_lvl : 0; | ||
268 | 269 | ||
269 | if (match_lvl == 3) { | 270 | if (match_lvl == 4) { |
270 | /* perfect-fit - return the result */ | 271 | /* perfect-fit - return the result */ |
271 | return entry; | 272 | return entry; |
272 | } else if (match_lvl > last_lvl) { | 273 | } else if (match_lvl > last_lvl) { |
@@ -873,72 +874,68 @@ static void check_for_illegal_area(struct device *dev, void *addr, u64 size) | |||
873 | "[addr=%p] [size=%llu]\n", addr, size); | 874 | "[addr=%p] [size=%llu]\n", addr, size); |
874 | } | 875 | } |
875 | 876 | ||
876 | static void check_sync(struct device *dev, dma_addr_t addr, | 877 | static void check_sync(struct device *dev, |
877 | u64 size, u64 offset, int direction, bool to_cpu) | 878 | struct dma_debug_entry *ref, |
879 | bool to_cpu) | ||
878 | { | 880 | { |
879 | struct dma_debug_entry ref = { | ||
880 | .dev = dev, | ||
881 | .dev_addr = addr, | ||
882 | .size = size, | ||
883 | .direction = direction, | ||
884 | }; | ||
885 | struct dma_debug_entry *entry; | 881 | struct dma_debug_entry *entry; |
886 | struct hash_bucket *bucket; | 882 | struct hash_bucket *bucket; |
887 | unsigned long flags; | 883 | unsigned long flags; |
888 | 884 | ||
889 | bucket = get_hash_bucket(&ref, &flags); | 885 | bucket = get_hash_bucket(ref, &flags); |
890 | 886 | ||
891 | entry = hash_bucket_find(bucket, &ref); | 887 | entry = hash_bucket_find(bucket, ref); |
892 | 888 | ||
893 | if (!entry) { | 889 | if (!entry) { |
894 | err_printk(dev, NULL, "DMA-API: device driver tries " | 890 | err_printk(dev, NULL, "DMA-API: device driver tries " |
895 | "to sync DMA memory it has not allocated " | 891 | "to sync DMA memory it has not allocated " |
896 | "[device address=0x%016llx] [size=%llu bytes]\n", | 892 | "[device address=0x%016llx] [size=%llu bytes]\n", |
897 | (unsigned long long)addr, size); | 893 | (unsigned long long)ref->dev_addr, ref->size); |
898 | goto out; | 894 | goto out; |
899 | } | 895 | } |
900 | 896 | ||
901 | if ((offset + size) > entry->size) { | 897 | if (ref->size > entry->size) { |
902 | err_printk(dev, entry, "DMA-API: device driver syncs" | 898 | err_printk(dev, entry, "DMA-API: device driver syncs" |
903 | " DMA memory outside allocated range " | 899 | " DMA memory outside allocated range " |
904 | "[device address=0x%016llx] " | 900 | "[device address=0x%016llx] " |
905 | "[allocation size=%llu bytes] [sync offset=%llu] " | 901 | "[allocation size=%llu bytes] " |
906 | "[sync size=%llu]\n", entry->dev_addr, entry->size, | 902 | "[sync offset+size=%llu]\n", |
907 | offset, size); | 903 | entry->dev_addr, entry->size, |
904 | ref->size); | ||
908 | } | 905 | } |
909 | 906 | ||
910 | if (direction != entry->direction) { | 907 | if (ref->direction != entry->direction) { |
911 | err_printk(dev, entry, "DMA-API: device driver syncs " | 908 | err_printk(dev, entry, "DMA-API: device driver syncs " |
912 | "DMA memory with different direction " | 909 | "DMA memory with different direction " |
913 | "[device address=0x%016llx] [size=%llu bytes] " | 910 | "[device address=0x%016llx] [size=%llu bytes] " |
914 | "[mapped with %s] [synced with %s]\n", | 911 | "[mapped with %s] [synced with %s]\n", |
915 | (unsigned long long)addr, entry->size, | 912 | (unsigned long long)ref->dev_addr, entry->size, |
916 | dir2name[entry->direction], | 913 | dir2name[entry->direction], |
917 | dir2name[direction]); | 914 | dir2name[ref->direction]); |
918 | } | 915 | } |
919 | 916 | ||
920 | if (entry->direction == DMA_BIDIRECTIONAL) | 917 | if (entry->direction == DMA_BIDIRECTIONAL) |
921 | goto out; | 918 | goto out; |
922 | 919 | ||
923 | if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) && | 920 | if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) && |
924 | !(direction == DMA_TO_DEVICE)) | 921 | !(ref->direction == DMA_TO_DEVICE)) |
925 | err_printk(dev, entry, "DMA-API: device driver syncs " | 922 | err_printk(dev, entry, "DMA-API: device driver syncs " |
926 | "device read-only DMA memory for cpu " | 923 | "device read-only DMA memory for cpu " |
927 | "[device address=0x%016llx] [size=%llu bytes] " | 924 | "[device address=0x%016llx] [size=%llu bytes] " |
928 | "[mapped with %s] [synced with %s]\n", | 925 | "[mapped with %s] [synced with %s]\n", |
929 | (unsigned long long)addr, entry->size, | 926 | (unsigned long long)ref->dev_addr, entry->size, |
930 | dir2name[entry->direction], | 927 | dir2name[entry->direction], |
931 | dir2name[direction]); | 928 | dir2name[ref->direction]); |
932 | 929 | ||
933 | if (!to_cpu && !(entry->direction == DMA_TO_DEVICE) && | 930 | if (!to_cpu && !(entry->direction == DMA_TO_DEVICE) && |
934 | !(direction == DMA_FROM_DEVICE)) | 931 | !(ref->direction == DMA_FROM_DEVICE)) |
935 | err_printk(dev, entry, "DMA-API: device driver syncs " | 932 | err_printk(dev, entry, "DMA-API: device driver syncs " |
936 | "device write-only DMA memory to device " | 933 | "device write-only DMA memory to device " |
937 | "[device address=0x%016llx] [size=%llu bytes] " | 934 | "[device address=0x%016llx] [size=%llu bytes] " |
938 | "[mapped with %s] [synced with %s]\n", | 935 | "[mapped with %s] [synced with %s]\n", |
939 | (unsigned long long)addr, entry->size, | 936 | (unsigned long long)ref->dev_addr, entry->size, |
940 | dir2name[entry->direction], | 937 | dir2name[entry->direction], |
941 | dir2name[direction]); | 938 | dir2name[ref->direction]); |
942 | 939 | ||
943 | out: | 940 | out: |
944 | put_hash_bucket(bucket, &flags); | 941 | put_hash_bucket(bucket, &flags); |
@@ -1036,19 +1033,16 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg, | |||
1036 | } | 1033 | } |
1037 | EXPORT_SYMBOL(debug_dma_map_sg); | 1034 | EXPORT_SYMBOL(debug_dma_map_sg); |
1038 | 1035 | ||
1039 | static int get_nr_mapped_entries(struct device *dev, struct scatterlist *s) | 1036 | static int get_nr_mapped_entries(struct device *dev, |
1037 | struct dma_debug_entry *ref) | ||
1040 | { | 1038 | { |
1041 | struct dma_debug_entry *entry, ref; | 1039 | struct dma_debug_entry *entry; |
1042 | struct hash_bucket *bucket; | 1040 | struct hash_bucket *bucket; |
1043 | unsigned long flags; | 1041 | unsigned long flags; |
1044 | int mapped_ents; | 1042 | int mapped_ents; |
1045 | 1043 | ||
1046 | ref.dev = dev; | 1044 | bucket = get_hash_bucket(ref, &flags); |
1047 | ref.dev_addr = sg_dma_address(s); | 1045 | entry = hash_bucket_find(bucket, ref); |
1048 | ref.size = sg_dma_len(s), | ||
1049 | |||
1050 | bucket = get_hash_bucket(&ref, &flags); | ||
1051 | entry = hash_bucket_find(bucket, &ref); | ||
1052 | mapped_ents = 0; | 1046 | mapped_ents = 0; |
1053 | 1047 | ||
1054 | if (entry) | 1048 | if (entry) |
@@ -1076,16 +1070,14 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist, | |||
1076 | .dev_addr = sg_dma_address(s), | 1070 | .dev_addr = sg_dma_address(s), |
1077 | .size = sg_dma_len(s), | 1071 | .size = sg_dma_len(s), |
1078 | .direction = dir, | 1072 | .direction = dir, |
1079 | .sg_call_ents = 0, | 1073 | .sg_call_ents = nelems, |
1080 | }; | 1074 | }; |
1081 | 1075 | ||
1082 | if (mapped_ents && i >= mapped_ents) | 1076 | if (mapped_ents && i >= mapped_ents) |
1083 | break; | 1077 | break; |
1084 | 1078 | ||
1085 | if (!i) { | 1079 | if (!i) |
1086 | ref.sg_call_ents = nelems; | 1080 | mapped_ents = get_nr_mapped_entries(dev, &ref); |
1087 | mapped_ents = get_nr_mapped_entries(dev, s); | ||
1088 | } | ||
1089 | 1081 | ||
1090 | check_unmap(&ref); | 1082 | check_unmap(&ref); |
1091 | } | 1083 | } |
@@ -1140,10 +1132,19 @@ EXPORT_SYMBOL(debug_dma_free_coherent); | |||
1140 | void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | 1132 | void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, |
1141 | size_t size, int direction) | 1133 | size_t size, int direction) |
1142 | { | 1134 | { |
1135 | struct dma_debug_entry ref; | ||
1136 | |||
1143 | if (unlikely(global_disable)) | 1137 | if (unlikely(global_disable)) |
1144 | return; | 1138 | return; |
1145 | 1139 | ||
1146 | check_sync(dev, dma_handle, size, 0, direction, true); | 1140 | ref.type = dma_debug_single; |
1141 | ref.dev = dev; | ||
1142 | ref.dev_addr = dma_handle; | ||
1143 | ref.size = size; | ||
1144 | ref.direction = direction; | ||
1145 | ref.sg_call_ents = 0; | ||
1146 | |||
1147 | check_sync(dev, &ref, true); | ||
1147 | } | 1148 | } |
1148 | EXPORT_SYMBOL(debug_dma_sync_single_for_cpu); | 1149 | EXPORT_SYMBOL(debug_dma_sync_single_for_cpu); |
1149 | 1150 | ||
@@ -1151,10 +1152,19 @@ void debug_dma_sync_single_for_device(struct device *dev, | |||
1151 | dma_addr_t dma_handle, size_t size, | 1152 | dma_addr_t dma_handle, size_t size, |
1152 | int direction) | 1153 | int direction) |
1153 | { | 1154 | { |
1155 | struct dma_debug_entry ref; | ||
1156 | |||
1154 | if (unlikely(global_disable)) | 1157 | if (unlikely(global_disable)) |
1155 | return; | 1158 | return; |
1156 | 1159 | ||
1157 | check_sync(dev, dma_handle, size, 0, direction, false); | 1160 | ref.type = dma_debug_single; |
1161 | ref.dev = dev; | ||
1162 | ref.dev_addr = dma_handle; | ||
1163 | ref.size = size; | ||
1164 | ref.direction = direction; | ||
1165 | ref.sg_call_ents = 0; | ||
1166 | |||
1167 | check_sync(dev, &ref, false); | ||
1158 | } | 1168 | } |
1159 | EXPORT_SYMBOL(debug_dma_sync_single_for_device); | 1169 | EXPORT_SYMBOL(debug_dma_sync_single_for_device); |
1160 | 1170 | ||
@@ -1163,10 +1173,19 @@ void debug_dma_sync_single_range_for_cpu(struct device *dev, | |||
1163 | unsigned long offset, size_t size, | 1173 | unsigned long offset, size_t size, |
1164 | int direction) | 1174 | int direction) |
1165 | { | 1175 | { |
1176 | struct dma_debug_entry ref; | ||
1177 | |||
1166 | if (unlikely(global_disable)) | 1178 | if (unlikely(global_disable)) |
1167 | return; | 1179 | return; |
1168 | 1180 | ||
1169 | check_sync(dev, dma_handle, size, offset, direction, true); | 1181 | ref.type = dma_debug_single; |
1182 | ref.dev = dev; | ||
1183 | ref.dev_addr = dma_handle; | ||
1184 | ref.size = offset + size; | ||
1185 | ref.direction = direction; | ||
1186 | ref.sg_call_ents = 0; | ||
1187 | |||
1188 | check_sync(dev, &ref, true); | ||
1170 | } | 1189 | } |
1171 | EXPORT_SYMBOL(debug_dma_sync_single_range_for_cpu); | 1190 | EXPORT_SYMBOL(debug_dma_sync_single_range_for_cpu); |
1172 | 1191 | ||
@@ -1175,10 +1194,19 @@ void debug_dma_sync_single_range_for_device(struct device *dev, | |||
1175 | unsigned long offset, | 1194 | unsigned long offset, |
1176 | size_t size, int direction) | 1195 | size_t size, int direction) |
1177 | { | 1196 | { |
1197 | struct dma_debug_entry ref; | ||
1198 | |||
1178 | if (unlikely(global_disable)) | 1199 | if (unlikely(global_disable)) |
1179 | return; | 1200 | return; |
1180 | 1201 | ||
1181 | check_sync(dev, dma_handle, size, offset, direction, false); | 1202 | ref.type = dma_debug_single; |
1203 | ref.dev = dev; | ||
1204 | ref.dev_addr = dma_handle; | ||
1205 | ref.size = offset + size; | ||
1206 | ref.direction = direction; | ||
1207 | ref.sg_call_ents = 0; | ||
1208 | |||
1209 | check_sync(dev, &ref, false); | ||
1182 | } | 1210 | } |
1183 | EXPORT_SYMBOL(debug_dma_sync_single_range_for_device); | 1211 | EXPORT_SYMBOL(debug_dma_sync_single_range_for_device); |
1184 | 1212 | ||
@@ -1192,14 +1220,24 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | |||
1192 | return; | 1220 | return; |
1193 | 1221 | ||
1194 | for_each_sg(sg, s, nelems, i) { | 1222 | for_each_sg(sg, s, nelems, i) { |
1223 | |||
1224 | struct dma_debug_entry ref = { | ||
1225 | .type = dma_debug_sg, | ||
1226 | .dev = dev, | ||
1227 | .paddr = sg_phys(s), | ||
1228 | .dev_addr = sg_dma_address(s), | ||
1229 | .size = sg_dma_len(s), | ||
1230 | .direction = direction, | ||
1231 | .sg_call_ents = nelems, | ||
1232 | }; | ||
1233 | |||
1195 | if (!i) | 1234 | if (!i) |
1196 | mapped_ents = get_nr_mapped_entries(dev, s); | 1235 | mapped_ents = get_nr_mapped_entries(dev, &ref); |
1197 | 1236 | ||
1198 | if (i >= mapped_ents) | 1237 | if (i >= mapped_ents) |
1199 | break; | 1238 | break; |
1200 | 1239 | ||
1201 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, | 1240 | check_sync(dev, &ref, true); |
1202 | direction, true); | ||
1203 | } | 1241 | } |
1204 | } | 1242 | } |
1205 | EXPORT_SYMBOL(debug_dma_sync_sg_for_cpu); | 1243 | EXPORT_SYMBOL(debug_dma_sync_sg_for_cpu); |
@@ -1214,14 +1252,23 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, | |||
1214 | return; | 1252 | return; |
1215 | 1253 | ||
1216 | for_each_sg(sg, s, nelems, i) { | 1254 | for_each_sg(sg, s, nelems, i) { |
1255 | |||
1256 | struct dma_debug_entry ref = { | ||
1257 | .type = dma_debug_sg, | ||
1258 | .dev = dev, | ||
1259 | .paddr = sg_phys(s), | ||
1260 | .dev_addr = sg_dma_address(s), | ||
1261 | .size = sg_dma_len(s), | ||
1262 | .direction = direction, | ||
1263 | .sg_call_ents = nelems, | ||
1264 | }; | ||
1217 | if (!i) | 1265 | if (!i) |
1218 | mapped_ents = get_nr_mapped_entries(dev, s); | 1266 | mapped_ents = get_nr_mapped_entries(dev, &ref); |
1219 | 1267 | ||
1220 | if (i >= mapped_ents) | 1268 | if (i >= mapped_ents) |
1221 | break; | 1269 | break; |
1222 | 1270 | ||
1223 | check_sync(dev, sg_dma_address(s), sg_dma_len(s), 0, | 1271 | check_sync(dev, &ref, false); |
1224 | direction, false); | ||
1225 | } | 1272 | } |
1226 | } | 1273 | } |
1227 | EXPORT_SYMBOL(debug_dma_sync_sg_for_device); | 1274 | EXPORT_SYMBOL(debug_dma_sync_sg_for_device); |
diff --git a/mm/memory.c b/mm/memory.c index d5d1653d60a6..98bcb90d5957 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1310,8 +1310,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
1310 | cond_resched(); | 1310 | cond_resched(); |
1311 | while (!(page = follow_page(vma, start, foll_flags))) { | 1311 | while (!(page = follow_page(vma, start, foll_flags))) { |
1312 | int ret; | 1312 | int ret; |
1313 | ret = handle_mm_fault(mm, vma, start, | 1313 | |
1314 | foll_flags & FOLL_WRITE); | 1314 | /* FOLL_WRITE matches FAULT_FLAG_WRITE! */ |
1315 | ret = handle_mm_fault(mm, vma, start, foll_flags & FOLL_WRITE); | ||
1315 | if (ret & VM_FAULT_ERROR) { | 1316 | if (ret & VM_FAULT_ERROR) { |
1316 | if (ret & VM_FAULT_OOM) | 1317 | if (ret & VM_FAULT_OOM) |
1317 | return i ? i : -ENOMEM; | 1318 | return i ? i : -ENOMEM; |
@@ -2496,7 +2497,7 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | |||
2496 | */ | 2497 | */ |
2497 | static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | 2498 | static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, |
2498 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2499 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2499 | int write_access, pte_t orig_pte) | 2500 | unsigned int flags, pte_t orig_pte) |
2500 | { | 2501 | { |
2501 | spinlock_t *ptl; | 2502 | spinlock_t *ptl; |
2502 | struct page *page; | 2503 | struct page *page; |
@@ -2572,9 +2573,9 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2572 | 2573 | ||
2573 | inc_mm_counter(mm, anon_rss); | 2574 | inc_mm_counter(mm, anon_rss); |
2574 | pte = mk_pte(page, vma->vm_page_prot); | 2575 | pte = mk_pte(page, vma->vm_page_prot); |
2575 | if (write_access && reuse_swap_page(page)) { | 2576 | if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) { |
2576 | pte = maybe_mkwrite(pte_mkdirty(pte), vma); | 2577 | pte = maybe_mkwrite(pte_mkdirty(pte), vma); |
2577 | write_access = 0; | 2578 | flags &= ~FAULT_FLAG_WRITE; |
2578 | } | 2579 | } |
2579 | flush_icache_page(vma, page); | 2580 | flush_icache_page(vma, page); |
2580 | set_pte_at(mm, address, page_table, pte); | 2581 | set_pte_at(mm, address, page_table, pte); |
@@ -2587,7 +2588,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2587 | try_to_free_swap(page); | 2588 | try_to_free_swap(page); |
2588 | unlock_page(page); | 2589 | unlock_page(page); |
2589 | 2590 | ||
2590 | if (write_access) { | 2591 | if (flags & FAULT_FLAG_WRITE) { |
2591 | ret |= do_wp_page(mm, vma, address, page_table, pmd, ptl, pte); | 2592 | ret |= do_wp_page(mm, vma, address, page_table, pmd, ptl, pte); |
2592 | if (ret & VM_FAULT_ERROR) | 2593 | if (ret & VM_FAULT_ERROR) |
2593 | ret &= VM_FAULT_ERROR; | 2594 | ret &= VM_FAULT_ERROR; |
@@ -2616,7 +2617,7 @@ out_page: | |||
2616 | */ | 2617 | */ |
2617 | static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | 2618 | static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, |
2618 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2619 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2619 | int write_access) | 2620 | unsigned int flags) |
2620 | { | 2621 | { |
2621 | struct page *page; | 2622 | struct page *page; |
2622 | spinlock_t *ptl; | 2623 | spinlock_t *ptl; |
@@ -2776,7 +2777,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2776 | * due to the bad i386 page protection. But it's valid | 2777 | * due to the bad i386 page protection. But it's valid |
2777 | * for other architectures too. | 2778 | * for other architectures too. |
2778 | * | 2779 | * |
2779 | * Note that if write_access is true, we either now have | 2780 | * Note that if FAULT_FLAG_WRITE is set, we either now have |
2780 | * an exclusive copy of the page, or this is a shared mapping, | 2781 | * an exclusive copy of the page, or this is a shared mapping, |
2781 | * so we can make it writable and dirty to avoid having to | 2782 | * so we can make it writable and dirty to avoid having to |
2782 | * handle that later. | 2783 | * handle that later. |
@@ -2847,11 +2848,10 @@ unwritable_page: | |||
2847 | 2848 | ||
2848 | static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 2849 | static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
2849 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2850 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2850 | int write_access, pte_t orig_pte) | 2851 | unsigned int flags, pte_t orig_pte) |
2851 | { | 2852 | { |
2852 | pgoff_t pgoff = (((address & PAGE_MASK) | 2853 | pgoff_t pgoff = (((address & PAGE_MASK) |
2853 | - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | 2854 | - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
2854 | unsigned int flags = (write_access ? FAULT_FLAG_WRITE : 0); | ||
2855 | 2855 | ||
2856 | pte_unmap(page_table); | 2856 | pte_unmap(page_table); |
2857 | return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); | 2857 | return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte); |
@@ -2868,12 +2868,12 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2868 | */ | 2868 | */ |
2869 | static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 2869 | static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
2870 | unsigned long address, pte_t *page_table, pmd_t *pmd, | 2870 | unsigned long address, pte_t *page_table, pmd_t *pmd, |
2871 | int write_access, pte_t orig_pte) | 2871 | unsigned int flags, pte_t orig_pte) |
2872 | { | 2872 | { |
2873 | unsigned int flags = FAULT_FLAG_NONLINEAR | | ||
2874 | (write_access ? FAULT_FLAG_WRITE : 0); | ||
2875 | pgoff_t pgoff; | 2873 | pgoff_t pgoff; |
2876 | 2874 | ||
2875 | flags |= FAULT_FLAG_NONLINEAR; | ||
2876 | |||
2877 | if (!pte_unmap_same(mm, pmd, page_table, orig_pte)) | 2877 | if (!pte_unmap_same(mm, pmd, page_table, orig_pte)) |
2878 | return 0; | 2878 | return 0; |
2879 | 2879 | ||
@@ -2904,7 +2904,7 @@ static int do_nonlinear_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2904 | */ | 2904 | */ |
2905 | static inline int handle_pte_fault(struct mm_struct *mm, | 2905 | static inline int handle_pte_fault(struct mm_struct *mm, |
2906 | struct vm_area_struct *vma, unsigned long address, | 2906 | struct vm_area_struct *vma, unsigned long address, |
2907 | pte_t *pte, pmd_t *pmd, int write_access) | 2907 | pte_t *pte, pmd_t *pmd, unsigned int flags) |
2908 | { | 2908 | { |
2909 | pte_t entry; | 2909 | pte_t entry; |
2910 | spinlock_t *ptl; | 2910 | spinlock_t *ptl; |
@@ -2915,30 +2915,30 @@ static inline int handle_pte_fault(struct mm_struct *mm, | |||
2915 | if (vma->vm_ops) { | 2915 | if (vma->vm_ops) { |
2916 | if (likely(vma->vm_ops->fault)) | 2916 | if (likely(vma->vm_ops->fault)) |
2917 | return do_linear_fault(mm, vma, address, | 2917 | return do_linear_fault(mm, vma, address, |
2918 | pte, pmd, write_access, entry); | 2918 | pte, pmd, flags, entry); |
2919 | } | 2919 | } |
2920 | return do_anonymous_page(mm, vma, address, | 2920 | return do_anonymous_page(mm, vma, address, |
2921 | pte, pmd, write_access); | 2921 | pte, pmd, flags); |
2922 | } | 2922 | } |
2923 | if (pte_file(entry)) | 2923 | if (pte_file(entry)) |
2924 | return do_nonlinear_fault(mm, vma, address, | 2924 | return do_nonlinear_fault(mm, vma, address, |
2925 | pte, pmd, write_access, entry); | 2925 | pte, pmd, flags, entry); |
2926 | return do_swap_page(mm, vma, address, | 2926 | return do_swap_page(mm, vma, address, |
2927 | pte, pmd, write_access, entry); | 2927 | pte, pmd, flags, entry); |
2928 | } | 2928 | } |
2929 | 2929 | ||
2930 | ptl = pte_lockptr(mm, pmd); | 2930 | ptl = pte_lockptr(mm, pmd); |
2931 | spin_lock(ptl); | 2931 | spin_lock(ptl); |
2932 | if (unlikely(!pte_same(*pte, entry))) | 2932 | if (unlikely(!pte_same(*pte, entry))) |
2933 | goto unlock; | 2933 | goto unlock; |
2934 | if (write_access) { | 2934 | if (flags & FAULT_FLAG_WRITE) { |
2935 | if (!pte_write(entry)) | 2935 | if (!pte_write(entry)) |
2936 | return do_wp_page(mm, vma, address, | 2936 | return do_wp_page(mm, vma, address, |
2937 | pte, pmd, ptl, entry); | 2937 | pte, pmd, ptl, entry); |
2938 | entry = pte_mkdirty(entry); | 2938 | entry = pte_mkdirty(entry); |
2939 | } | 2939 | } |
2940 | entry = pte_mkyoung(entry); | 2940 | entry = pte_mkyoung(entry); |
2941 | if (ptep_set_access_flags(vma, address, pte, entry, write_access)) { | 2941 | if (ptep_set_access_flags(vma, address, pte, entry, flags & FAULT_FLAG_WRITE)) { |
2942 | update_mmu_cache(vma, address, entry); | 2942 | update_mmu_cache(vma, address, entry); |
2943 | } else { | 2943 | } else { |
2944 | /* | 2944 | /* |
@@ -2947,7 +2947,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, | |||
2947 | * This still avoids useless tlb flushes for .text page faults | 2947 | * This still avoids useless tlb flushes for .text page faults |
2948 | * with threads. | 2948 | * with threads. |
2949 | */ | 2949 | */ |
2950 | if (write_access) | 2950 | if (flags & FAULT_FLAG_WRITE) |
2951 | flush_tlb_page(vma, address); | 2951 | flush_tlb_page(vma, address); |
2952 | } | 2952 | } |
2953 | unlock: | 2953 | unlock: |
@@ -2959,7 +2959,7 @@ unlock: | |||
2959 | * By the time we get here, we already hold the mm semaphore | 2959 | * By the time we get here, we already hold the mm semaphore |
2960 | */ | 2960 | */ |
2961 | int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | 2961 | int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, |
2962 | unsigned long address, int write_access) | 2962 | unsigned long address, unsigned int flags) |
2963 | { | 2963 | { |
2964 | pgd_t *pgd; | 2964 | pgd_t *pgd; |
2965 | pud_t *pud; | 2965 | pud_t *pud; |
@@ -2971,7 +2971,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2971 | count_vm_event(PGFAULT); | 2971 | count_vm_event(PGFAULT); |
2972 | 2972 | ||
2973 | if (unlikely(is_vm_hugetlb_page(vma))) | 2973 | if (unlikely(is_vm_hugetlb_page(vma))) |
2974 | return hugetlb_fault(mm, vma, address, write_access); | 2974 | return hugetlb_fault(mm, vma, address, flags); |
2975 | 2975 | ||
2976 | pgd = pgd_offset(mm, address); | 2976 | pgd = pgd_offset(mm, address); |
2977 | pud = pud_alloc(mm, pgd, address); | 2977 | pud = pud_alloc(mm, pgd, address); |
@@ -2984,7 +2984,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2984 | if (!pte) | 2984 | if (!pte) |
2985 | return VM_FAULT_OOM; | 2985 | return VM_FAULT_OOM; |
2986 | 2986 | ||
2987 | return handle_pte_fault(mm, vma, address, pte, pmd, write_access); | 2987 | return handle_pte_fault(mm, vma, address, pte, pmd, flags); |
2988 | } | 2988 | } |
2989 | 2989 | ||
2990 | #ifndef __PAGETABLE_PUD_FOLDED | 2990 | #ifndef __PAGETABLE_PUD_FOLDED |
diff --git a/mm/percpu.c b/mm/percpu.c index c0b2c1a76e81..b70f2acd8853 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
@@ -549,14 +549,14 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) | |||
549 | * @chunk: chunk of interest | 549 | * @chunk: chunk of interest |
550 | * @page_start: page index of the first page to unmap | 550 | * @page_start: page index of the first page to unmap |
551 | * @page_end: page index of the last page to unmap + 1 | 551 | * @page_end: page index of the last page to unmap + 1 |
552 | * @flush: whether to flush cache and tlb or not | 552 | * @flush_tlb: whether to flush tlb or not |
553 | * | 553 | * |
554 | * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. | 554 | * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. |
555 | * If @flush is true, vcache is flushed before unmapping and tlb | 555 | * If @flush is true, vcache is flushed before unmapping and tlb |
556 | * after. | 556 | * after. |
557 | */ | 557 | */ |
558 | static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | 558 | static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, |
559 | bool flush) | 559 | bool flush_tlb) |
560 | { | 560 | { |
561 | unsigned int last = num_possible_cpus() - 1; | 561 | unsigned int last = num_possible_cpus() - 1; |
562 | unsigned int cpu; | 562 | unsigned int cpu; |
@@ -569,9 +569,8 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | |||
569 | * the whole region at once rather than doing it for each cpu. | 569 | * the whole region at once rather than doing it for each cpu. |
570 | * This could be an overkill but is more scalable. | 570 | * This could be an overkill but is more scalable. |
571 | */ | 571 | */ |
572 | if (flush) | 572 | flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), |
573 | flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), | 573 | pcpu_chunk_addr(chunk, last, page_end)); |
574 | pcpu_chunk_addr(chunk, last, page_end)); | ||
575 | 574 | ||
576 | for_each_possible_cpu(cpu) | 575 | for_each_possible_cpu(cpu) |
577 | unmap_kernel_range_noflush( | 576 | unmap_kernel_range_noflush( |
@@ -579,7 +578,7 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | |||
579 | (page_end - page_start) << PAGE_SHIFT); | 578 | (page_end - page_start) << PAGE_SHIFT); |
580 | 579 | ||
581 | /* ditto as flush_cache_vunmap() */ | 580 | /* ditto as flush_cache_vunmap() */ |
582 | if (flush) | 581 | if (flush_tlb) |
583 | flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), | 582 | flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), |
584 | pcpu_chunk_addr(chunk, last, page_end)); | 583 | pcpu_chunk_addr(chunk, last, page_end)); |
585 | } | 584 | } |
@@ -1234,6 +1233,7 @@ static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) | |||
1234 | ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, | 1233 | ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, |
1235 | ssize_t dyn_size, ssize_t unit_size) | 1234 | ssize_t dyn_size, ssize_t unit_size) |
1236 | { | 1235 | { |
1236 | size_t chunk_size; | ||
1237 | unsigned int cpu; | 1237 | unsigned int cpu; |
1238 | 1238 | ||
1239 | /* determine parameters and allocate */ | 1239 | /* determine parameters and allocate */ |
@@ -1248,11 +1248,15 @@ ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, | |||
1248 | } else | 1248 | } else |
1249 | pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); | 1249 | pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); |
1250 | 1250 | ||
1251 | pcpue_ptr = __alloc_bootmem_nopanic( | 1251 | chunk_size = pcpue_unit_size * num_possible_cpus(); |
1252 | num_possible_cpus() * pcpue_unit_size, | 1252 | |
1253 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | 1253 | pcpue_ptr = __alloc_bootmem_nopanic(chunk_size, PAGE_SIZE, |
1254 | if (!pcpue_ptr) | 1254 | __pa(MAX_DMA_ADDRESS)); |
1255 | if (!pcpue_ptr) { | ||
1256 | pr_warning("PERCPU: failed to allocate %zu bytes for " | ||
1257 | "embedding\n", chunk_size); | ||
1255 | return -ENOMEM; | 1258 | return -ENOMEM; |
1259 | } | ||
1256 | 1260 | ||
1257 | /* return the leftover and copy */ | 1261 | /* return the leftover and copy */ |
1258 | for_each_possible_cpu(cpu) { | 1262 | for_each_possible_cpu(cpu) { |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 562403a23488..462e2cedaa6a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -972,8 +972,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr | |||
972 | snd_hda_codec_read(codec, nid, 0, | 972 | snd_hda_codec_read(codec, nid, 0, |
973 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 973 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
974 | } | 974 | } |
975 | if (bus->modelname) | ||
976 | codec->modelname = kstrdup(bus->modelname, GFP_KERNEL); | ||
977 | 975 | ||
978 | /* power-up all before initialization */ | 976 | /* power-up all before initialization */ |
979 | hda_set_power_state(codec, | 977 | hda_set_power_state(codec, |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d22b26068014..bf4b78a74a8f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -224,6 +224,7 @@ enum { | |||
224 | ALC883_ACER, | 224 | ALC883_ACER, |
225 | ALC883_ACER_ASPIRE, | 225 | ALC883_ACER_ASPIRE, |
226 | ALC888_ACER_ASPIRE_4930G, | 226 | ALC888_ACER_ASPIRE_4930G, |
227 | ALC888_ACER_ASPIRE_6530G, | ||
227 | ALC888_ACER_ASPIRE_8930G, | 228 | ALC888_ACER_ASPIRE_8930G, |
228 | ALC883_MEDION, | 229 | ALC883_MEDION, |
229 | ALC883_MEDION_MD2, | 230 | ALC883_MEDION_MD2, |
@@ -970,7 +971,7 @@ static void alc_automute_pin(struct hda_codec *codec) | |||
970 | } | 971 | } |
971 | } | 972 | } |
972 | 973 | ||
973 | #if 0 /* it's broken in some acses -- temporarily disabled */ | 974 | #if 0 /* it's broken in some cases -- temporarily disabled */ |
974 | static void alc_mic_automute(struct hda_codec *codec) | 975 | static void alc_mic_automute(struct hda_codec *codec) |
975 | { | 976 | { |
976 | struct alc_spec *spec = codec->spec; | 977 | struct alc_spec *spec = codec->spec; |
@@ -1170,7 +1171,7 @@ static int alc_subsystem_id(struct hda_codec *codec, | |||
1170 | 1171 | ||
1171 | /* invalid SSID, check the special NID pin defcfg instead */ | 1172 | /* invalid SSID, check the special NID pin defcfg instead */ |
1172 | /* | 1173 | /* |
1173 | * 31~30 : port conetcivity | 1174 | * 31~30 : port connectivity |
1174 | * 29~21 : reserve | 1175 | * 29~21 : reserve |
1175 | * 20 : PCBEEP input | 1176 | * 20 : PCBEEP input |
1176 | * 19~16 : Check sum (15:1) | 1177 | * 19~16 : Check sum (15:1) |
@@ -1471,6 +1472,25 @@ static struct hda_verb alc888_acer_aspire_4930g_verbs[] = { | |||
1471 | }; | 1472 | }; |
1472 | 1473 | ||
1473 | /* | 1474 | /* |
1475 | * ALC888 Acer Aspire 6530G model | ||
1476 | */ | ||
1477 | |||
1478 | static struct hda_verb alc888_acer_aspire_6530g_verbs[] = { | ||
1479 | /* Bias voltage on for external mic port */ | ||
1480 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80}, | ||
1481 | /* Enable unsolicited event for HP jack */ | ||
1482 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
1483 | /* Enable speaker output */ | ||
1484 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
1485 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1486 | /* Enable headphone output */ | ||
1487 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP}, | ||
1488 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1489 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1490 | { } | ||
1491 | }; | ||
1492 | |||
1493 | /* | ||
1474 | * ALC889 Acer Aspire 8930G model | 1494 | * ALC889 Acer Aspire 8930G model |
1475 | */ | 1495 | */ |
1476 | 1496 | ||
@@ -1544,6 +1564,25 @@ static struct hda_input_mux alc888_2_capture_sources[2] = { | |||
1544 | } | 1564 | } |
1545 | }; | 1565 | }; |
1546 | 1566 | ||
1567 | static struct hda_input_mux alc888_acer_aspire_6530_sources[2] = { | ||
1568 | /* Interal mic only available on one ADC */ | ||
1569 | { | ||
1570 | .num_items = 3, | ||
1571 | .items = { | ||
1572 | { "Ext Mic", 0x0 }, | ||
1573 | { "CD", 0x4 }, | ||
1574 | { "Int Mic", 0xb }, | ||
1575 | }, | ||
1576 | }, | ||
1577 | { | ||
1578 | .num_items = 2, | ||
1579 | .items = { | ||
1580 | { "Ext Mic", 0x0 }, | ||
1581 | { "CD", 0x4 }, | ||
1582 | }, | ||
1583 | } | ||
1584 | }; | ||
1585 | |||
1547 | static struct hda_input_mux alc889_capture_sources[3] = { | 1586 | static struct hda_input_mux alc889_capture_sources[3] = { |
1548 | /* Digital mic only available on first "ADC" */ | 1587 | /* Digital mic only available on first "ADC" */ |
1549 | { | 1588 | { |
@@ -6347,7 +6386,7 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = { | |||
6347 | }; | 6386 | }; |
6348 | 6387 | ||
6349 | /* | 6388 | /* |
6350 | * macbook pro ALC885 can switch LineIn to LineOut without loosing Mic | 6389 | * macbook pro ALC885 can switch LineIn to LineOut without losing Mic |
6351 | */ | 6390 | */ |
6352 | 6391 | ||
6353 | /* | 6392 | /* |
@@ -7047,7 +7086,7 @@ static struct hda_verb alc882_auto_init_verbs[] = { | |||
7047 | #define alc882_loopbacks alc880_loopbacks | 7086 | #define alc882_loopbacks alc880_loopbacks |
7048 | #endif | 7087 | #endif |
7049 | 7088 | ||
7050 | /* pcm configuration: identiacal with ALC880 */ | 7089 | /* pcm configuration: identical with ALC880 */ |
7051 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback | 7090 | #define alc882_pcm_analog_playback alc880_pcm_analog_playback |
7052 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture | 7091 | #define alc882_pcm_analog_capture alc880_pcm_analog_capture |
7053 | #define alc882_pcm_digital_playback alc880_pcm_digital_playback | 7092 | #define alc882_pcm_digital_playback alc880_pcm_digital_playback |
@@ -8068,7 +8107,7 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = { | |||
8068 | { } /* end */ | 8107 | { } /* end */ |
8069 | }; | 8108 | }; |
8070 | 8109 | ||
8071 | static struct snd_kcontrol_new alc883_tagra_mixer[] = { | 8110 | static struct snd_kcontrol_new alc883_targa_mixer[] = { |
8072 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8111 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8073 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 8112 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
8074 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 8113 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
@@ -8088,7 +8127,7 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = { | |||
8088 | { } /* end */ | 8127 | { } /* end */ |
8089 | }; | 8128 | }; |
8090 | 8129 | ||
8091 | static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = { | 8130 | static struct snd_kcontrol_new alc883_targa_2ch_mixer[] = { |
8092 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8131 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8093 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 8132 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
8094 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | 8133 | HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), |
@@ -8153,6 +8192,19 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = { | |||
8153 | { } /* end */ | 8192 | { } /* end */ |
8154 | }; | 8193 | }; |
8155 | 8194 | ||
8195 | static struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = { | ||
8196 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
8197 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
8198 | HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
8199 | HDA_BIND_MUTE("LFE Playback Switch", 0x0f, 2, HDA_INPUT), | ||
8200 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
8201 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
8202 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
8203 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8204 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
8205 | { } /* end */ | ||
8206 | }; | ||
8207 | |||
8156 | static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = { | 8208 | static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = { |
8157 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 8209 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
8158 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 8210 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
@@ -8417,7 +8469,7 @@ static struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = { | |||
8417 | { } /* end */ | 8469 | { } /* end */ |
8418 | }; | 8470 | }; |
8419 | 8471 | ||
8420 | static struct hda_verb alc883_tagra_verbs[] = { | 8472 | static struct hda_verb alc883_targa_verbs[] = { |
8421 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 8473 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
8422 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 8474 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
8423 | 8475 | ||
@@ -8626,8 +8678,8 @@ static void alc883_medion_md2_init_hook(struct hda_codec *codec) | |||
8626 | } | 8678 | } |
8627 | 8679 | ||
8628 | /* toggle speaker-output according to the hp-jack state */ | 8680 | /* toggle speaker-output according to the hp-jack state */ |
8629 | #define alc883_tagra_init_hook alc882_targa_init_hook | 8681 | #define alc883_targa_init_hook alc882_targa_init_hook |
8630 | #define alc883_tagra_unsol_event alc882_targa_unsol_event | 8682 | #define alc883_targa_unsol_event alc882_targa_unsol_event |
8631 | 8683 | ||
8632 | static void alc883_clevo_m720_mic_automute(struct hda_codec *codec) | 8684 | static void alc883_clevo_m720_mic_automute(struct hda_codec *codec) |
8633 | { | 8685 | { |
@@ -8957,7 +9009,7 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res) | |||
8957 | #define alc883_loopbacks alc880_loopbacks | 9009 | #define alc883_loopbacks alc880_loopbacks |
8958 | #endif | 9010 | #endif |
8959 | 9011 | ||
8960 | /* pcm configuration: identiacal with ALC880 */ | 9012 | /* pcm configuration: identical with ALC880 */ |
8961 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback | 9013 | #define alc883_pcm_analog_playback alc880_pcm_analog_playback |
8962 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture | 9014 | #define alc883_pcm_analog_capture alc880_pcm_analog_capture |
8963 | #define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | 9015 | #define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture |
@@ -8978,6 +9030,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
8978 | [ALC883_ACER] = "acer", | 9030 | [ALC883_ACER] = "acer", |
8979 | [ALC883_ACER_ASPIRE] = "acer-aspire", | 9031 | [ALC883_ACER_ASPIRE] = "acer-aspire", |
8980 | [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g", | 9032 | [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g", |
9033 | [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g", | ||
8981 | [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g", | 9034 | [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g", |
8982 | [ALC883_MEDION] = "medion", | 9035 | [ALC883_MEDION] = "medion", |
8983 | [ALC883_MEDION_MD2] = "medion-md2", | 9036 | [ALC883_MEDION_MD2] = "medion-md2", |
@@ -9021,7 +9074,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
9021 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", | 9074 | SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G", |
9022 | ALC888_ACER_ASPIRE_4930G), | 9075 | ALC888_ACER_ASPIRE_4930G), |
9023 | SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", | 9076 | SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G", |
9024 | ALC888_ACER_ASPIRE_4930G), | 9077 | ALC888_ACER_ASPIRE_6530G), |
9025 | /* default Acer -- disabled as it causes more problems. | 9078 | /* default Acer -- disabled as it causes more problems. |
9026 | * model=auto should work fine now | 9079 | * model=auto should work fine now |
9027 | */ | 9080 | */ |
@@ -9069,6 +9122,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
9069 | SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG), | 9122 | SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG), |
9070 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), | 9123 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), |
9071 | SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), | 9124 | SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), |
9125 | SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG), | ||
9072 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), | 9126 | SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), |
9073 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), | 9127 | SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), |
9074 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), | 9128 | SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), |
@@ -9165,8 +9219,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
9165 | .input_mux = &alc883_capture_source, | 9219 | .input_mux = &alc883_capture_source, |
9166 | }, | 9220 | }, |
9167 | [ALC883_TARGA_DIG] = { | 9221 | [ALC883_TARGA_DIG] = { |
9168 | .mixers = { alc883_tagra_mixer, alc883_chmode_mixer }, | 9222 | .mixers = { alc883_targa_mixer, alc883_chmode_mixer }, |
9169 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, | 9223 | .init_verbs = { alc883_init_verbs, alc883_targa_verbs}, |
9170 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 9224 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
9171 | .dac_nids = alc883_dac_nids, | 9225 | .dac_nids = alc883_dac_nids, |
9172 | .dig_out_nid = ALC883_DIGOUT_NID, | 9226 | .dig_out_nid = ALC883_DIGOUT_NID, |
@@ -9174,12 +9228,12 @@ static struct alc_config_preset alc883_presets[] = { | |||
9174 | .channel_mode = alc883_3ST_6ch_modes, | 9228 | .channel_mode = alc883_3ST_6ch_modes, |
9175 | .need_dac_fix = 1, | 9229 | .need_dac_fix = 1, |
9176 | .input_mux = &alc883_capture_source, | 9230 | .input_mux = &alc883_capture_source, |
9177 | .unsol_event = alc883_tagra_unsol_event, | 9231 | .unsol_event = alc883_targa_unsol_event, |
9178 | .init_hook = alc883_tagra_init_hook, | 9232 | .init_hook = alc883_targa_init_hook, |
9179 | }, | 9233 | }, |
9180 | [ALC883_TARGA_2ch_DIG] = { | 9234 | [ALC883_TARGA_2ch_DIG] = { |
9181 | .mixers = { alc883_tagra_2ch_mixer}, | 9235 | .mixers = { alc883_targa_2ch_mixer}, |
9182 | .init_verbs = { alc883_init_verbs, alc883_tagra_verbs}, | 9236 | .init_verbs = { alc883_init_verbs, alc883_targa_verbs}, |
9183 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 9237 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
9184 | .dac_nids = alc883_dac_nids, | 9238 | .dac_nids = alc883_dac_nids, |
9185 | .adc_nids = alc883_adc_nids_alt, | 9239 | .adc_nids = alc883_adc_nids_alt, |
@@ -9188,13 +9242,13 @@ static struct alc_config_preset alc883_presets[] = { | |||
9188 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | 9242 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), |
9189 | .channel_mode = alc883_3ST_2ch_modes, | 9243 | .channel_mode = alc883_3ST_2ch_modes, |
9190 | .input_mux = &alc883_capture_source, | 9244 | .input_mux = &alc883_capture_source, |
9191 | .unsol_event = alc883_tagra_unsol_event, | 9245 | .unsol_event = alc883_targa_unsol_event, |
9192 | .init_hook = alc883_tagra_init_hook, | 9246 | .init_hook = alc883_targa_init_hook, |
9193 | }, | 9247 | }, |
9194 | [ALC883_TARGA_8ch_DIG] = { | 9248 | [ALC883_TARGA_8ch_DIG] = { |
9195 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, | 9249 | .mixers = { alc883_base_mixer, alc883_chmode_mixer }, |
9196 | .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs, | 9250 | .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs, |
9197 | alc883_tagra_verbs }, | 9251 | alc883_targa_verbs }, |
9198 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 9252 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
9199 | .dac_nids = alc883_dac_nids, | 9253 | .dac_nids = alc883_dac_nids, |
9200 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev), | 9254 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev), |
@@ -9206,8 +9260,8 @@ static struct alc_config_preset alc883_presets[] = { | |||
9206 | .channel_mode = alc883_4ST_8ch_modes, | 9260 | .channel_mode = alc883_4ST_8ch_modes, |
9207 | .need_dac_fix = 1, | 9261 | .need_dac_fix = 1, |
9208 | .input_mux = &alc883_capture_source, | 9262 | .input_mux = &alc883_capture_source, |
9209 | .unsol_event = alc883_tagra_unsol_event, | 9263 | .unsol_event = alc883_targa_unsol_event, |
9210 | .init_hook = alc883_tagra_init_hook, | 9264 | .init_hook = alc883_targa_init_hook, |
9211 | }, | 9265 | }, |
9212 | [ALC883_ACER] = { | 9266 | [ALC883_ACER] = { |
9213 | .mixers = { alc883_base_mixer }, | 9267 | .mixers = { alc883_base_mixer }, |
@@ -9255,6 +9309,24 @@ static struct alc_config_preset alc883_presets[] = { | |||
9255 | .unsol_event = alc_automute_amp_unsol_event, | 9309 | .unsol_event = alc_automute_amp_unsol_event, |
9256 | .init_hook = alc888_acer_aspire_4930g_init_hook, | 9310 | .init_hook = alc888_acer_aspire_4930g_init_hook, |
9257 | }, | 9311 | }, |
9312 | [ALC888_ACER_ASPIRE_6530G] = { | ||
9313 | .mixers = { alc888_acer_aspire_6530_mixer }, | ||
9314 | .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs, | ||
9315 | alc888_acer_aspire_6530g_verbs }, | ||
9316 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
9317 | .dac_nids = alc883_dac_nids, | ||
9318 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev), | ||
9319 | .adc_nids = alc883_adc_nids_rev, | ||
9320 | .capsrc_nids = alc883_capsrc_nids_rev, | ||
9321 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
9322 | .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), | ||
9323 | .channel_mode = alc883_3ST_2ch_modes, | ||
9324 | .num_mux_defs = | ||
9325 | ARRAY_SIZE(alc888_2_capture_sources), | ||
9326 | .input_mux = alc888_acer_aspire_6530_sources, | ||
9327 | .unsol_event = alc_automute_amp_unsol_event, | ||
9328 | .init_hook = alc888_acer_aspire_4930g_init_hook, | ||
9329 | }, | ||
9258 | [ALC888_ACER_ASPIRE_8930G] = { | 9330 | [ALC888_ACER_ASPIRE_8930G] = { |
9259 | .mixers = { alc888_base_mixer, | 9331 | .mixers = { alc888_base_mixer, |
9260 | alc883_chmode_mixer }, | 9332 | alc883_chmode_mixer }, |
@@ -9361,7 +9433,7 @@ static struct alc_config_preset alc883_presets[] = { | |||
9361 | .init_hook = alc888_lenovo_ms7195_front_automute, | 9433 | .init_hook = alc888_lenovo_ms7195_front_automute, |
9362 | }, | 9434 | }, |
9363 | [ALC883_HAIER_W66] = { | 9435 | [ALC883_HAIER_W66] = { |
9364 | .mixers = { alc883_tagra_2ch_mixer}, | 9436 | .mixers = { alc883_targa_2ch_mixer}, |
9365 | .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs}, | 9437 | .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs}, |
9366 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | 9438 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), |
9367 | .dac_nids = alc883_dac_nids, | 9439 | .dac_nids = alc883_dac_nids, |
@@ -11131,7 +11203,7 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { | |||
11131 | #define alc262_loopbacks alc880_loopbacks | 11203 | #define alc262_loopbacks alc880_loopbacks |
11132 | #endif | 11204 | #endif |
11133 | 11205 | ||
11134 | /* pcm configuration: identiacal with ALC880 */ | 11206 | /* pcm configuration: identical with ALC880 */ |
11135 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback | 11207 | #define alc262_pcm_analog_playback alc880_pcm_analog_playback |
11136 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture | 11208 | #define alc262_pcm_analog_capture alc880_pcm_analog_capture |
11137 | #define alc262_pcm_digital_playback alc880_pcm_digital_playback | 11209 | #define alc262_pcm_digital_playback alc880_pcm_digital_playback |
@@ -12286,7 +12358,7 @@ static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) | |||
12286 | AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); | 12358 | AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); |
12287 | } | 12359 | } |
12288 | 12360 | ||
12289 | /* pcm configuration: identiacal with ALC880 */ | 12361 | /* pcm configuration: identical with ALC880 */ |
12290 | #define alc268_pcm_analog_playback alc880_pcm_analog_playback | 12362 | #define alc268_pcm_analog_playback alc880_pcm_analog_playback |
12291 | #define alc268_pcm_analog_capture alc880_pcm_analog_capture | 12363 | #define alc268_pcm_analog_capture alc880_pcm_analog_capture |
12292 | #define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | 12364 | #define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture |
@@ -13197,7 +13269,7 @@ static int alc269_auto_create_analog_input_ctls(struct alc_spec *spec, | |||
13197 | #define alc269_loopbacks alc880_loopbacks | 13269 | #define alc269_loopbacks alc880_loopbacks |
13198 | #endif | 13270 | #endif |
13199 | 13271 | ||
13200 | /* pcm configuration: identiacal with ALC880 */ | 13272 | /* pcm configuration: identical with ALC880 */ |
13201 | #define alc269_pcm_analog_playback alc880_pcm_analog_playback | 13273 | #define alc269_pcm_analog_playback alc880_pcm_analog_playback |
13202 | #define alc269_pcm_analog_capture alc880_pcm_analog_capture | 13274 | #define alc269_pcm_analog_capture alc880_pcm_analog_capture |
13203 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback | 13275 | #define alc269_pcm_digital_playback alc880_pcm_digital_playback |
@@ -14059,7 +14131,7 @@ static void alc861_toshiba_unsol_event(struct hda_codec *codec, | |||
14059 | alc861_toshiba_automute(codec); | 14131 | alc861_toshiba_automute(codec); |
14060 | } | 14132 | } |
14061 | 14133 | ||
14062 | /* pcm configuration: identiacal with ALC880 */ | 14134 | /* pcm configuration: identical with ALC880 */ |
14063 | #define alc861_pcm_analog_playback alc880_pcm_analog_playback | 14135 | #define alc861_pcm_analog_playback alc880_pcm_analog_playback |
14064 | #define alc861_pcm_analog_capture alc880_pcm_analog_capture | 14136 | #define alc861_pcm_analog_capture alc880_pcm_analog_capture |
14065 | #define alc861_pcm_digital_playback alc880_pcm_digital_playback | 14137 | #define alc861_pcm_digital_playback alc880_pcm_digital_playback |
@@ -14582,7 +14654,7 @@ static hda_nid_t alc861vd_dac_nids[4] = { | |||
14582 | 14654 | ||
14583 | /* dac_nids for ALC660vd are in a different order - according to | 14655 | /* dac_nids for ALC660vd are in a different order - according to |
14584 | * Realtek's driver. | 14656 | * Realtek's driver. |
14585 | * This should probably tesult in a different mixer for 6stack models | 14657 | * This should probably result in a different mixer for 6stack models |
14586 | * of ALC660vd codecs, but for now there is only 3stack mixer | 14658 | * of ALC660vd codecs, but for now there is only 3stack mixer |
14587 | * - and it is the same as in 861vd. | 14659 | * - and it is the same as in 861vd. |
14588 | * adc_nids in ALC660vd are (is) the same as in 861vd | 14660 | * adc_nids in ALC660vd are (is) the same as in 861vd |
@@ -15027,7 +15099,7 @@ static void alc861vd_dallas_init_hook(struct hda_codec *codec) | |||
15027 | #define alc861vd_loopbacks alc880_loopbacks | 15099 | #define alc861vd_loopbacks alc880_loopbacks |
15028 | #endif | 15100 | #endif |
15029 | 15101 | ||
15030 | /* pcm configuration: identiacal with ALC880 */ | 15102 | /* pcm configuration: identical with ALC880 */ |
15031 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback | 15103 | #define alc861vd_pcm_analog_playback alc880_pcm_analog_playback |
15032 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture | 15104 | #define alc861vd_pcm_analog_capture alc880_pcm_analog_capture |
15033 | #define alc861vd_pcm_digital_playback alc880_pcm_digital_playback | 15105 | #define alc861vd_pcm_digital_playback alc880_pcm_digital_playback |
@@ -15206,7 +15278,7 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec) | |||
15206 | hda_nid_t pin; | 15278 | hda_nid_t pin; |
15207 | 15279 | ||
15208 | pin = spec->autocfg.hp_pins[0]; | 15280 | pin = spec->autocfg.hp_pins[0]; |
15209 | if (pin) /* connect to front and use dac 0 */ | 15281 | if (pin) /* connect to front and use dac 0 */ |
15210 | alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 15282 | alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
15211 | pin = spec->autocfg.speaker_pins[0]; | 15283 | pin = spec->autocfg.speaker_pins[0]; |
15212 | if (pin) | 15284 | if (pin) |
@@ -16669,7 +16741,7 @@ static struct snd_kcontrol_new alc272_nc10_mixer[] = { | |||
16669 | #endif | 16741 | #endif |
16670 | 16742 | ||
16671 | 16743 | ||
16672 | /* pcm configuration: identiacal with ALC880 */ | 16744 | /* pcm configuration: identical with ALC880 */ |
16673 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback | 16745 | #define alc662_pcm_analog_playback alc880_pcm_analog_playback |
16674 | #define alc662_pcm_analog_capture alc880_pcm_analog_capture | 16746 | #define alc662_pcm_analog_capture alc880_pcm_analog_capture |
16675 | #define alc662_pcm_digital_playback alc880_pcm_digital_playback | 16747 | #define alc662_pcm_digital_playback alc880_pcm_digital_playback |
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index fa336616152e..938a58a5a244 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c | |||
@@ -297,9 +297,9 @@ static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | |||
297 | static bool filter(struct dma_chan *chan, void *param) | 297 | static bool filter(struct dma_chan *chan, void *param) |
298 | { | 298 | { |
299 | struct txx9aclc_dmadata *dmadata = param; | 299 | struct txx9aclc_dmadata *dmadata = param; |
300 | char devname[BUS_ID_SIZE + 2]; | 300 | char devname[20 + 2]; /* FIXME: old BUS_ID_SIZE + 2 */ |
301 | 301 | ||
302 | sprintf(devname, "%s.%d", dmadata->dma_res->name, | 302 | snprintf(devname, sizeof(devname), "%s.%d", dmadata->dma_res->name, |
303 | (int)dmadata->dma_res->start); | 303 | (int)dmadata->dma_res->start); |
304 | if (strcmp(dev_name(chan->device->dev), devname) == 0) { | 304 | if (strcmp(dev_name(chan->device->dev), devname) == 0) { |
305 | chan->private = &dmadata->dma_slave; | 305 | chan->private = &dmadata->dma_slave; |
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index b14451342166..8f9b60c5d74c 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c | |||
@@ -199,8 +199,9 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) | |||
199 | dev->period_out_count[index] = BYTES_PER_SAMPLE + 1; | 199 | dev->period_out_count[index] = BYTES_PER_SAMPLE + 1; |
200 | dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; | 200 | dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; |
201 | } else { | 201 | } else { |
202 | dev->period_in_count[index] = BYTES_PER_SAMPLE; | 202 | int in_pos = (dev->spec.data_alignment == 2) ? 0 : 2; |
203 | dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE; | 203 | dev->period_in_count[index] = BYTES_PER_SAMPLE + in_pos; |
204 | dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE + in_pos; | ||
204 | } | 205 | } |
205 | 206 | ||
206 | if (dev->streaming) | 207 | if (dev->streaming) |
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 22406245a98b..0e5db719de24 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "input.h" | 35 | #include "input.h" |
36 | 36 | ||
37 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 37 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
38 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.16"); | 38 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.17"); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 40 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," |
41 | "{Native Instruments, RigKontrol3}," | 41 | "{Native Instruments, RigKontrol3}," |