Contents of /trunk/kernel-alx/patches-3.12/0116-3.12.17-all-fixes.patch
Parent Directory | Revision Log
Revision 2431 -
(show annotations)
(download)
Tue May 13 11:02:45 2014 UTC (10 years, 4 months ago) by niro
File size: 64354 byte(s)
Tue May 13 11:02:45 2014 UTC (10 years, 4 months ago) by niro
File size: 64354 byte(s)
-linux-3.12.17
1 | diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 |
2 | index d29dea0f3232..7b0dcdb57173 100644 |
3 | --- a/Documentation/i2c/busses/i2c-i801 |
4 | +++ b/Documentation/i2c/busses/i2c-i801 |
5 | @@ -25,6 +25,7 @@ Supported adapters: |
6 | * Intel Avoton (SOC) |
7 | * Intel Wellsburg (PCH) |
8 | * Intel Coleto Creek (PCH) |
9 | + * Intel Wildcat Point-LP (PCH) |
10 | Datasheets: Publicly available at the Intel website |
11 | |
12 | On Intel Patsburg and later chipsets, both the normal host SMBus controller |
13 | diff --git a/Makefile b/Makefile |
14 | index 4aab3be88e9b..fbd1ee8afea8 100644 |
15 | --- a/Makefile |
16 | +++ b/Makefile |
17 | @@ -1,6 +1,6 @@ |
18 | VERSION = 3 |
19 | PATCHLEVEL = 12 |
20 | -SUBLEVEL = 16 |
21 | +SUBLEVEL = 17 |
22 | EXTRAVERSION = |
23 | NAME = One Giant Leap for Frogkind |
24 | |
25 | diff --git a/arch/s390/kernel/vdso32/clock_gettime.S b/arch/s390/kernel/vdso32/clock_gettime.S |
26 | index 5be8e472f57d..65fc3979c2f1 100644 |
27 | --- a/arch/s390/kernel/vdso32/clock_gettime.S |
28 | +++ b/arch/s390/kernel/vdso32/clock_gettime.S |
29 | @@ -46,18 +46,13 @@ __kernel_clock_gettime: |
30 | jnm 3f |
31 | a %r0,__VDSO_TK_MULT(%r5) |
32 | 3: alr %r0,%r2 |
33 | - al %r0,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */ |
34 | - al %r1,__VDSO_XTIME_NSEC+4(%r5) |
35 | - brc 12,4f |
36 | - ahi %r0,1 |
37 | -4: al %r0,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic.nsec */ |
38 | + al %r0,__VDSO_WTOM_NSEC(%r5) |
39 | al %r1,__VDSO_WTOM_NSEC+4(%r5) |
40 | brc 12,5f |
41 | ahi %r0,1 |
42 | 5: l %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */ |
43 | srdl %r0,0(%r2) /* >> tk->shift */ |
44 | - l %r2,__VDSO_XTIME_SEC+4(%r5) |
45 | - al %r2,__VDSO_WTOM_SEC+4(%r5) |
46 | + l %r2,__VDSO_WTOM_SEC+4(%r5) |
47 | cl %r4,__VDSO_UPD_COUNT+4(%r5) /* check update counter */ |
48 | jne 1b |
49 | basr %r5,0 |
50 | diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S |
51 | index 0add1072ba30..c09cda31c894 100644 |
52 | --- a/arch/s390/kernel/vdso64/clock_gettime.S |
53 | +++ b/arch/s390/kernel/vdso64/clock_gettime.S |
54 | @@ -35,13 +35,11 @@ __kernel_clock_gettime: |
55 | jnz 0b |
56 | stck 48(%r15) /* Store TOD clock */ |
57 | lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */ |
58 | - lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */ |
59 | - alg %r0,__VDSO_WTOM_SEC(%r5) /* + wall_to_monotonic.sec */ |
60 | + lg %r0,__VDSO_WTOM_SEC(%r5) |
61 | lg %r1,48(%r15) |
62 | sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */ |
63 | msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */ |
64 | - alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */ |
65 | - alg %r1,__VDSO_WTOM_NSEC(%r5) /* + wall_to_monotonic.nsec */ |
66 | + alg %r1,__VDSO_WTOM_NSEC(%r5) |
67 | srlg %r1,%r1,0(%r2) /* >> tk->shift */ |
68 | clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ |
69 | jne 0b |
70 | diff --git a/arch/x86/crypto/sha256_ssse3_glue.c b/arch/x86/crypto/sha256_ssse3_glue.c |
71 | index 50226c4b86ed..e52947f80e68 100644 |
72 | --- a/arch/x86/crypto/sha256_ssse3_glue.c |
73 | +++ b/arch/x86/crypto/sha256_ssse3_glue.c |
74 | @@ -281,7 +281,7 @@ static int __init sha256_ssse3_mod_init(void) |
75 | /* allow AVX to override SSSE3, it's a little faster */ |
76 | if (avx_usable()) { |
77 | #ifdef CONFIG_AS_AVX2 |
78 | - if (boot_cpu_has(X86_FEATURE_AVX2)) |
79 | + if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_BMI2)) |
80 | sha256_transform_asm = sha256_transform_rorx; |
81 | else |
82 | #endif |
83 | diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h |
84 | index 5ad38ad07890..bbc8b12fa443 100644 |
85 | --- a/arch/x86/include/asm/pgtable.h |
86 | +++ b/arch/x86/include/asm/pgtable.h |
87 | @@ -445,20 +445,10 @@ static inline int pte_same(pte_t a, pte_t b) |
88 | return a.pte == b.pte; |
89 | } |
90 | |
91 | -static inline int pteval_present(pteval_t pteval) |
92 | -{ |
93 | - /* |
94 | - * Yes Linus, _PAGE_PROTNONE == _PAGE_NUMA. Expressing it this |
95 | - * way clearly states that the intent is that protnone and numa |
96 | - * hinting ptes are considered present for the purposes of |
97 | - * pagetable operations like zapping, protection changes, gup etc. |
98 | - */ |
99 | - return pteval & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_NUMA); |
100 | -} |
101 | - |
102 | static inline int pte_present(pte_t a) |
103 | { |
104 | - return pteval_present(pte_flags(a)); |
105 | + return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE | |
106 | + _PAGE_NUMA); |
107 | } |
108 | |
109 | #define pte_accessible pte_accessible |
110 | diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h |
111 | index d35f24e231cd..1306d117967d 100644 |
112 | --- a/arch/x86/include/asm/topology.h |
113 | +++ b/arch/x86/include/asm/topology.h |
114 | @@ -119,9 +119,10 @@ static inline void setup_node_to_cpumask_map(void) { } |
115 | |
116 | extern const struct cpumask *cpu_coregroup_mask(int cpu); |
117 | |
118 | -#ifdef ENABLE_TOPO_DEFINES |
119 | #define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) |
120 | #define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) |
121 | + |
122 | +#ifdef ENABLE_TOPO_DEFINES |
123 | #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) |
124 | #define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) |
125 | #endif |
126 | diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c |
127 | index 266ca912f62e..5ecf65117e6f 100644 |
128 | --- a/arch/x86/mm/srat.c |
129 | +++ b/arch/x86/mm/srat.c |
130 | @@ -42,15 +42,25 @@ static __init inline int srat_disabled(void) |
131 | return acpi_numa < 0; |
132 | } |
133 | |
134 | -/* Callback for SLIT parsing */ |
135 | +/* |
136 | + * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for |
137 | + * I/O localities since SRAT does not list them. I/O localities are |
138 | + * not supported at this point. |
139 | + */ |
140 | void __init acpi_numa_slit_init(struct acpi_table_slit *slit) |
141 | { |
142 | int i, j; |
143 | |
144 | - for (i = 0; i < slit->locality_count; i++) |
145 | - for (j = 0; j < slit->locality_count; j++) |
146 | + for (i = 0; i < slit->locality_count; i++) { |
147 | + if (pxm_to_node(i) == NUMA_NO_NODE) |
148 | + continue; |
149 | + for (j = 0; j < slit->locality_count; j++) { |
150 | + if (pxm_to_node(j) == NUMA_NO_NODE) |
151 | + continue; |
152 | numa_set_distance(pxm_to_node(i), pxm_to_node(j), |
153 | slit->entry[slit->locality_count * i + j]); |
154 | + } |
155 | + } |
156 | } |
157 | |
158 | /* Callback for Proximity Domain -> x2APIC mapping */ |
159 | diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c |
160 | index d5af43af64dc..fdc3ba28ca38 100644 |
161 | --- a/arch/x86/xen/mmu.c |
162 | +++ b/arch/x86/xen/mmu.c |
163 | @@ -365,7 +365,7 @@ void xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr, |
164 | /* Assume pteval_t is equivalent to all the other *val_t types. */ |
165 | static pteval_t pte_mfn_to_pfn(pteval_t val) |
166 | { |
167 | - if (pteval_present(val)) { |
168 | + if (val & _PAGE_PRESENT) { |
169 | unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; |
170 | unsigned long pfn = mfn_to_pfn(mfn); |
171 | |
172 | @@ -381,7 +381,7 @@ static pteval_t pte_mfn_to_pfn(pteval_t val) |
173 | |
174 | static pteval_t pte_pfn_to_mfn(pteval_t val) |
175 | { |
176 | - if (pteval_present(val)) { |
177 | + if (val & _PAGE_PRESENT) { |
178 | unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT; |
179 | pteval_t flags = val & PTE_FLAGS_MASK; |
180 | unsigned long mfn; |
181 | diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h |
182 | index f86dc5fcc4ad..d9351ee19f18 100644 |
183 | --- a/crypto/asymmetric_keys/x509_parser.h |
184 | +++ b/crypto/asymmetric_keys/x509_parser.h |
185 | @@ -9,6 +9,7 @@ |
186 | * 2 of the Licence, or (at your option) any later version. |
187 | */ |
188 | |
189 | +#include <linux/time.h> |
190 | #include <crypto/public_key.h> |
191 | |
192 | struct x509_certificate { |
193 | diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c |
194 | index d2515435e23f..8fb295350efb 100644 |
195 | --- a/drivers/block/aoe/aoecmd.c |
196 | +++ b/drivers/block/aoe/aoecmd.c |
197 | @@ -905,7 +905,7 @@ bio_pageinc(struct bio *bio) |
198 | /* Non-zero page count for non-head members of |
199 | * compound pages is no longer allowed by the kernel. |
200 | */ |
201 | - page = compound_trans_head(bv->bv_page); |
202 | + page = compound_head(bv->bv_page); |
203 | atomic_inc(&page->_count); |
204 | } |
205 | } |
206 | @@ -918,7 +918,7 @@ bio_pagedec(struct bio *bio) |
207 | int i; |
208 | |
209 | bio_for_each_segment(bv, bio, i) { |
210 | - page = compound_trans_head(bv->bv_page); |
211 | + page = compound_head(bv->bv_page); |
212 | atomic_dec(&page->_count); |
213 | } |
214 | } |
215 | diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c |
216 | index 1f7b4caefb6e..c7fa2e420d49 100644 |
217 | --- a/drivers/gpu/drm/i915/i915_gem_gtt.c |
218 | +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c |
219 | @@ -536,7 +536,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) |
220 | dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, |
221 | dev_priv->gtt.base.start / PAGE_SIZE, |
222 | dev_priv->gtt.base.total / PAGE_SIZE, |
223 | - false); |
224 | + true); |
225 | } |
226 | |
227 | void i915_gem_restore_gtt_mappings(struct drm_device *dev) |
228 | diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c |
229 | index 8160fbddbcfe..200e8564c59d 100644 |
230 | --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c |
231 | +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c |
232 | @@ -66,6 +66,7 @@ bool nouveau_is_v1_dsm(void) { |
233 | #define NOUVEAU_DSM_HAS_MUX 0x1 |
234 | #define NOUVEAU_DSM_HAS_OPT 0x2 |
235 | |
236 | +#ifdef CONFIG_VGA_SWITCHEROO |
237 | static const char nouveau_dsm_muid[] = { |
238 | 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D, |
239 | 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4, |
240 | @@ -378,6 +379,11 @@ void nouveau_unregister_dsm_handler(void) |
241 | if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected) |
242 | vga_switcheroo_unregister_handler(); |
243 | } |
244 | +#else |
245 | +void nouveau_register_dsm_handler(void) {} |
246 | +void nouveau_unregister_dsm_handler(void) {} |
247 | +void nouveau_switcheroo_optimus_dsm(void) {} |
248 | +#endif |
249 | |
250 | /* retrieve the ROM in 4k blocks */ |
251 | static int nouveau_rom_call(acpi_handle rom_handle, uint8_t *bios, |
252 | diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig |
253 | index cd30d98ac510..4e901081e287 100644 |
254 | --- a/drivers/i2c/busses/Kconfig |
255 | +++ b/drivers/i2c/busses/Kconfig |
256 | @@ -109,6 +109,7 @@ config I2C_I801 |
257 | Avoton (SOC) |
258 | Wellsburg (PCH) |
259 | Coleto Creek (PCH) |
260 | + Wildcat Point-LP (PCH) |
261 | |
262 | This driver can also be built as a module. If so, the module |
263 | will be called i2c-i801. |
264 | diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c |
265 | index b2b8aa9adc0e..c5121459196b 100644 |
266 | --- a/drivers/i2c/busses/i2c-cpm.c |
267 | +++ b/drivers/i2c/busses/i2c-cpm.c |
268 | @@ -40,7 +40,9 @@ |
269 | #include <linux/i2c.h> |
270 | #include <linux/io.h> |
271 | #include <linux/dma-mapping.h> |
272 | +#include <linux/of_address.h> |
273 | #include <linux/of_device.h> |
274 | +#include <linux/of_irq.h> |
275 | #include <linux/of_platform.h> |
276 | #include <sysdev/fsl_soc.h> |
277 | #include <asm/cpm.h> |
278 | diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c |
279 | index 4296d1721272..737e29866887 100644 |
280 | --- a/drivers/i2c/busses/i2c-i801.c |
281 | +++ b/drivers/i2c/busses/i2c-i801.c |
282 | @@ -59,6 +59,7 @@ |
283 | Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes |
284 | Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes |
285 | Coleto Creek (PCH) 0x23b0 32 hard yes yes yes |
286 | + Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes |
287 | |
288 | Features supported by this driver: |
289 | Software PEC no |
290 | @@ -177,6 +178,7 @@ |
291 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e |
292 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f |
293 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 |
294 | +#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2 |
295 | |
296 | struct i801_mux_config { |
297 | char *gpio_chip; |
298 | @@ -819,6 +821,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { |
299 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) }, |
300 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) }, |
301 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) }, |
302 | + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, |
303 | { 0, } |
304 | }; |
305 | |
306 | diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c |
307 | index d47bb0f267f7..53235814ea0f 100644 |
308 | --- a/drivers/idle/intel_idle.c |
309 | +++ b/drivers/idle/intel_idle.c |
310 | @@ -1,7 +1,7 @@ |
311 | /* |
312 | * intel_idle.c - native hardware idle loop for modern Intel processors |
313 | * |
314 | - * Copyright (c) 2010, Intel Corporation. |
315 | + * Copyright (c) 2013, Intel Corporation. |
316 | * Len Brown <len.brown@intel.com> |
317 | * |
318 | * This program is free software; you can redistribute it and/or modify it |
319 | @@ -329,6 +329,22 @@ static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = { |
320 | { |
321 | .enter = NULL } |
322 | }; |
323 | +static struct cpuidle_state avn_cstates[] __initdata = { |
324 | + { |
325 | + .name = "C1-AVN", |
326 | + .desc = "MWAIT 0x00", |
327 | + .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TIME_VALID, |
328 | + .exit_latency = 2, |
329 | + .target_residency = 2, |
330 | + .enter = &intel_idle }, |
331 | + { |
332 | + .name = "C6-AVN", |
333 | + .desc = "MWAIT 0x51", |
334 | + .flags = MWAIT2flg(0x51) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, |
335 | + .exit_latency = 15, |
336 | + .target_residency = 45, |
337 | + .enter = &intel_idle }, |
338 | +}; |
339 | |
340 | /** |
341 | * intel_idle |
342 | @@ -465,6 +481,11 @@ static const struct idle_cpu idle_cpu_hsw = { |
343 | .disable_promotion_to_c1e = true, |
344 | }; |
345 | |
346 | +static const struct idle_cpu idle_cpu_avn = { |
347 | + .state_table = avn_cstates, |
348 | + .disable_promotion_to_c1e = true, |
349 | +}; |
350 | + |
351 | #define ICPU(model, cpu) \ |
352 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } |
353 | |
354 | @@ -486,6 +507,7 @@ static const struct x86_cpu_id intel_idle_ids[] = { |
355 | ICPU(0x3f, idle_cpu_hsw), |
356 | ICPU(0x45, idle_cpu_hsw), |
357 | ICPU(0x46, idle_cpu_hsw), |
358 | + ICPU(0x4D, idle_cpu_avn), |
359 | {} |
360 | }; |
361 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); |
362 | diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c |
363 | index 888a81a7ea3d..0aaea7ad6cee 100644 |
364 | --- a/drivers/input/mouse/cypress_ps2.c |
365 | +++ b/drivers/input/mouse/cypress_ps2.c |
366 | @@ -410,7 +410,6 @@ static int cypress_set_input_params(struct input_dev *input, |
367 | __clear_bit(REL_X, input->relbit); |
368 | __clear_bit(REL_Y, input->relbit); |
369 | |
370 | - __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
371 | __set_bit(EV_KEY, input->evbit); |
372 | __set_bit(BTN_LEFT, input->keybit); |
373 | __set_bit(BTN_RIGHT, input->keybit); |
374 | diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c |
375 | index 26386f9d2569..d8d49d10f9bb 100644 |
376 | --- a/drivers/input/mouse/synaptics.c |
377 | +++ b/drivers/input/mouse/synaptics.c |
378 | @@ -265,11 +265,22 @@ static int synaptics_identify(struct psmouse *psmouse) |
379 | * Read touchpad resolution and maximum reported coordinates |
380 | * Resolution is left zero if touchpad does not support the query |
381 | */ |
382 | + |
383 | +static const int *quirk_min_max; |
384 | + |
385 | static int synaptics_resolution(struct psmouse *psmouse) |
386 | { |
387 | struct synaptics_data *priv = psmouse->private; |
388 | unsigned char resp[3]; |
389 | |
390 | + if (quirk_min_max) { |
391 | + priv->x_min = quirk_min_max[0]; |
392 | + priv->x_max = quirk_min_max[1]; |
393 | + priv->y_min = quirk_min_max[2]; |
394 | + priv->y_max = quirk_min_max[3]; |
395 | + return 0; |
396 | + } |
397 | + |
398 | if (SYN_ID_MAJOR(priv->identity) < 4) |
399 | return 0; |
400 | |
401 | @@ -1485,10 +1496,54 @@ static const struct dmi_system_id olpc_dmi_table[] __initconst = { |
402 | { } |
403 | }; |
404 | |
405 | +static const struct dmi_system_id min_max_dmi_table[] __initconst = { |
406 | +#if defined(CONFIG_DMI) |
407 | + { |
408 | + /* Lenovo ThinkPad Helix */ |
409 | + .matches = { |
410 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
411 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Helix"), |
412 | + }, |
413 | + .driver_data = (int []){1024, 5052, 2258, 4832}, |
414 | + }, |
415 | + { |
416 | + /* Lenovo ThinkPad X240 */ |
417 | + .matches = { |
418 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
419 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X240"), |
420 | + }, |
421 | + .driver_data = (int []){1232, 5710, 1156, 4696}, |
422 | + }, |
423 | + { |
424 | + /* Lenovo ThinkPad T440s */ |
425 | + .matches = { |
426 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
427 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T440"), |
428 | + }, |
429 | + .driver_data = (int []){1024, 5112, 2024, 4832}, |
430 | + }, |
431 | + { |
432 | + /* Lenovo ThinkPad T540p */ |
433 | + .matches = { |
434 | + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
435 | + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T540"), |
436 | + }, |
437 | + .driver_data = (int []){1024, 5056, 2058, 4832}, |
438 | + }, |
439 | +#endif |
440 | + { } |
441 | +}; |
442 | + |
443 | void __init synaptics_module_init(void) |
444 | { |
445 | + const struct dmi_system_id *min_max_dmi; |
446 | + |
447 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); |
448 | broken_olpc_ec = dmi_check_system(olpc_dmi_table); |
449 | + |
450 | + min_max_dmi = dmi_first_match(min_max_dmi_table); |
451 | + if (min_max_dmi) |
452 | + quirk_min_max = min_max_dmi->driver_data; |
453 | } |
454 | |
455 | static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode) |
456 | diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c |
457 | index 4c842c320c2e..b604564dec5c 100644 |
458 | --- a/drivers/input/mousedev.c |
459 | +++ b/drivers/input/mousedev.c |
460 | @@ -67,7 +67,6 @@ struct mousedev { |
461 | struct device dev; |
462 | struct cdev cdev; |
463 | bool exist; |
464 | - bool is_mixdev; |
465 | |
466 | struct list_head mixdev_node; |
467 | bool opened_by_mixdev; |
468 | @@ -77,6 +76,9 @@ struct mousedev { |
469 | int old_x[4], old_y[4]; |
470 | int frac_dx, frac_dy; |
471 | unsigned long touch; |
472 | + |
473 | + int (*open_device)(struct mousedev *mousedev); |
474 | + void (*close_device)(struct mousedev *mousedev); |
475 | }; |
476 | |
477 | enum mousedev_emul { |
478 | @@ -116,9 +118,6 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; |
479 | static struct mousedev *mousedev_mix; |
480 | static LIST_HEAD(mousedev_mix_list); |
481 | |
482 | -static void mixdev_open_devices(void); |
483 | -static void mixdev_close_devices(void); |
484 | - |
485 | #define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03]) |
486 | #define fy(i) (mousedev->old_y[(mousedev->pkt_count - (i)) & 03]) |
487 | |
488 | @@ -428,9 +427,7 @@ static int mousedev_open_device(struct mousedev *mousedev) |
489 | if (retval) |
490 | return retval; |
491 | |
492 | - if (mousedev->is_mixdev) |
493 | - mixdev_open_devices(); |
494 | - else if (!mousedev->exist) |
495 | + if (!mousedev->exist) |
496 | retval = -ENODEV; |
497 | else if (!mousedev->open++) { |
498 | retval = input_open_device(&mousedev->handle); |
499 | @@ -446,9 +443,7 @@ static void mousedev_close_device(struct mousedev *mousedev) |
500 | { |
501 | mutex_lock(&mousedev->mutex); |
502 | |
503 | - if (mousedev->is_mixdev) |
504 | - mixdev_close_devices(); |
505 | - else if (mousedev->exist && !--mousedev->open) |
506 | + if (mousedev->exist && !--mousedev->open) |
507 | input_close_device(&mousedev->handle); |
508 | |
509 | mutex_unlock(&mousedev->mutex); |
510 | @@ -459,21 +454,29 @@ static void mousedev_close_device(struct mousedev *mousedev) |
511 | * stream. Note that this function is called with mousedev_mix->mutex |
512 | * held. |
513 | */ |
514 | -static void mixdev_open_devices(void) |
515 | +static int mixdev_open_devices(struct mousedev *mixdev) |
516 | { |
517 | - struct mousedev *mousedev; |
518 | + int error; |
519 | + |
520 | + error = mutex_lock_interruptible(&mixdev->mutex); |
521 | + if (error) |
522 | + return error; |
523 | |
524 | - if (mousedev_mix->open++) |
525 | - return; |
526 | + if (!mixdev->open++) { |
527 | + struct mousedev *mousedev; |
528 | |
529 | - list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
530 | - if (!mousedev->opened_by_mixdev) { |
531 | - if (mousedev_open_device(mousedev)) |
532 | - continue; |
533 | + list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
534 | + if (!mousedev->opened_by_mixdev) { |
535 | + if (mousedev_open_device(mousedev)) |
536 | + continue; |
537 | |
538 | - mousedev->opened_by_mixdev = true; |
539 | + mousedev->opened_by_mixdev = true; |
540 | + } |
541 | } |
542 | } |
543 | + |
544 | + mutex_unlock(&mixdev->mutex); |
545 | + return 0; |
546 | } |
547 | |
548 | /* |
549 | @@ -481,19 +484,22 @@ static void mixdev_open_devices(void) |
550 | * device. Note that this function is called with mousedev_mix->mutex |
551 | * held. |
552 | */ |
553 | -static void mixdev_close_devices(void) |
554 | +static void mixdev_close_devices(struct mousedev *mixdev) |
555 | { |
556 | - struct mousedev *mousedev; |
557 | + mutex_lock(&mixdev->mutex); |
558 | |
559 | - if (--mousedev_mix->open) |
560 | - return; |
561 | + if (!--mixdev->open) { |
562 | + struct mousedev *mousedev; |
563 | |
564 | - list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
565 | - if (mousedev->opened_by_mixdev) { |
566 | - mousedev->opened_by_mixdev = false; |
567 | - mousedev_close_device(mousedev); |
568 | + list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { |
569 | + if (mousedev->opened_by_mixdev) { |
570 | + mousedev->opened_by_mixdev = false; |
571 | + mousedev_close_device(mousedev); |
572 | + } |
573 | } |
574 | } |
575 | + |
576 | + mutex_unlock(&mixdev->mutex); |
577 | } |
578 | |
579 | |
580 | @@ -522,7 +528,7 @@ static int mousedev_release(struct inode *inode, struct file *file) |
581 | mousedev_detach_client(mousedev, client); |
582 | kfree(client); |
583 | |
584 | - mousedev_close_device(mousedev); |
585 | + mousedev->close_device(mousedev); |
586 | |
587 | return 0; |
588 | } |
589 | @@ -550,7 +556,7 @@ static int mousedev_open(struct inode *inode, struct file *file) |
590 | client->mousedev = mousedev; |
591 | mousedev_attach_client(mousedev, client); |
592 | |
593 | - error = mousedev_open_device(mousedev); |
594 | + error = mousedev->open_device(mousedev); |
595 | if (error) |
596 | goto err_free_client; |
597 | |
598 | @@ -861,16 +867,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev, |
599 | |
600 | if (mixdev) { |
601 | dev_set_name(&mousedev->dev, "mice"); |
602 | + |
603 | + mousedev->open_device = mixdev_open_devices; |
604 | + mousedev->close_device = mixdev_close_devices; |
605 | } else { |
606 | int dev_no = minor; |
607 | /* Normalize device number if it falls into legacy range */ |
608 | if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS) |
609 | dev_no -= MOUSEDEV_MINOR_BASE; |
610 | dev_set_name(&mousedev->dev, "mouse%d", dev_no); |
611 | + |
612 | + mousedev->open_device = mousedev_open_device; |
613 | + mousedev->close_device = mousedev_close_device; |
614 | } |
615 | |
616 | mousedev->exist = true; |
617 | - mousedev->is_mixdev = mixdev; |
618 | mousedev->handle.dev = input_get_device(dev); |
619 | mousedev->handle.name = dev_name(&mousedev->dev); |
620 | mousedev->handle.handler = handler; |
621 | @@ -919,7 +930,7 @@ static void mousedev_destroy(struct mousedev *mousedev) |
622 | device_del(&mousedev->dev); |
623 | mousedev_cleanup(mousedev); |
624 | input_free_minor(MINOR(mousedev->dev.devt)); |
625 | - if (!mousedev->is_mixdev) |
626 | + if (mousedev != mousedev_mix) |
627 | input_unregister_handle(&mousedev->handle); |
628 | put_device(&mousedev->dev); |
629 | } |
630 | diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c |
631 | index a6debe13d5b9..44a1fb6fa4a0 100644 |
632 | --- a/drivers/input/tablet/wacom_sys.c |
633 | +++ b/drivers/input/tablet/wacom_sys.c |
634 | @@ -722,7 +722,7 @@ static int wacom_led_control(struct wacom *wacom) |
635 | return -ENOMEM; |
636 | |
637 | if (wacom->wacom_wac.features.type >= INTUOS5S && |
638 | - wacom->wacom_wac.features.type <= INTUOS5L) { |
639 | + wacom->wacom_wac.features.type <= INTUOSPL) { |
640 | /* |
641 | * Touch Ring and crop mark LED luminance may take on |
642 | * one of four values: |
643 | @@ -984,6 +984,9 @@ static int wacom_initialize_leds(struct wacom *wacom) |
644 | case INTUOS5S: |
645 | case INTUOS5: |
646 | case INTUOS5L: |
647 | + case INTUOSPS: |
648 | + case INTUOSPM: |
649 | + case INTUOSPL: |
650 | wacom->led.select[0] = 0; |
651 | wacom->led.select[1] = 0; |
652 | wacom->led.llv = 32; |
653 | @@ -1027,6 +1030,9 @@ static void wacom_destroy_leds(struct wacom *wacom) |
654 | case INTUOS5S: |
655 | case INTUOS5: |
656 | case INTUOS5L: |
657 | + case INTUOSPS: |
658 | + case INTUOSPM: |
659 | + case INTUOSPL: |
660 | sysfs_remove_group(&wacom->intf->dev.kobj, |
661 | &intuos5_led_attr_group); |
662 | break; |
663 | @@ -1305,7 +1311,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i |
664 | * HID descriptor. If this is the touch interface (wMaxPacketSize |
665 | * of WACOM_PKGLEN_BBTOUCH3), override the table values. |
666 | */ |
667 | - if (features->type >= INTUOS5S && features->type <= INTUOS5L) { |
668 | + if (features->type >= INTUOS5S && features->type <= INTUOSPL) { |
669 | if (endpoint->wMaxPacketSize == WACOM_PKGLEN_BBTOUCH3) { |
670 | features->device_type = BTN_TOOL_FINGER; |
671 | features->pktlen = WACOM_PKGLEN_BBTOUCH3; |
672 | diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c |
673 | index c59b797eeafa..0091bdedb240 100644 |
674 | --- a/drivers/input/tablet/wacom_wac.c |
675 | +++ b/drivers/input/tablet/wacom_wac.c |
676 | @@ -621,14 +621,14 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) |
677 | } else { |
678 | input_report_abs(input, ABS_MISC, 0); |
679 | } |
680 | - } else if (features->type >= INTUOS5S && features->type <= INTUOS5L) { |
681 | + } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { |
682 | int i; |
683 | |
684 | /* Touch ring mode switch has no capacitive sensor */ |
685 | input_report_key(input, BTN_0, (data[3] & 0x01)); |
686 | |
687 | /* |
688 | - * ExpressKeys on Intuos5 have a capacitive sensor in |
689 | + * ExpressKeys on Intuos5/Intuos Pro have a capacitive sensor in |
690 | * addition to the mechanical switch. Switch data is |
691 | * stored in data[4], capacitive data in data[5]. |
692 | */ |
693 | @@ -716,7 +716,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) |
694 | features->type == INTUOS4 || |
695 | features->type == INTUOS4S || |
696 | features->type == INTUOS5 || |
697 | - features->type == INTUOS5S)) { |
698 | + features->type == INTUOS5S || |
699 | + features->type == INTUOSPM || |
700 | + features->type == INTUOSPS)) { |
701 | |
702 | return 0; |
703 | } |
704 | @@ -769,8 +771,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) |
705 | |
706 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
707 | /* I4 mouse */ |
708 | - if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || |
709 | - (features->type >= INTUOS5S && features->type <= INTUOS5L)) { |
710 | + if (features->type >= INTUOS4S && features->type <= INTUOSPL) { |
711 | input_report_key(input, BTN_LEFT, data[6] & 0x01); |
712 | input_report_key(input, BTN_MIDDLE, data[6] & 0x02); |
713 | input_report_key(input, BTN_RIGHT, data[6] & 0x04); |
714 | @@ -797,7 +798,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) |
715 | } |
716 | } |
717 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || |
718 | - features->type == INTUOS4L || features->type == INTUOS5L) && |
719 | + features->type == INTUOS4L || features->type == INTUOS5L || |
720 | + features->type == INTUOSPL) && |
721 | wacom->tool[idx] == BTN_TOOL_LENS) { |
722 | /* Lens cursor packets */ |
723 | input_report_key(input, BTN_LEFT, data[8] & 0x01); |
724 | @@ -1107,6 +1109,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) |
725 | |
726 | static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) |
727 | { |
728 | + struct wacom_features *features = &wacom->features; |
729 | struct input_dev *input = wacom->input; |
730 | bool touch = data[1] & 0x80; |
731 | int slot = input_mt_get_slot_by_key(input, data[0]); |
732 | @@ -1122,14 +1125,23 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) |
733 | if (touch) { |
734 | int x = (data[2] << 4) | (data[4] >> 4); |
735 | int y = (data[3] << 4) | (data[4] & 0x0f); |
736 | - int a = data[5]; |
737 | + int width, height; |
738 | |
739 | - // "a" is a scaled-down area which we assume is roughly |
740 | - // circular and which can be described as: a=(pi*r^2)/C. |
741 | - int x_res = input_abs_get_res(input, ABS_X); |
742 | - int y_res = input_abs_get_res(input, ABS_Y); |
743 | - int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); |
744 | - int height = width * y_res / x_res; |
745 | + if (features->type >= INTUOSPS && features->type <= INTUOSPL) { |
746 | + width = data[5]; |
747 | + height = data[6]; |
748 | + } else { |
749 | + /* |
750 | + * "a" is a scaled-down area which we assume is |
751 | + * roughly circular and which can be described as: |
752 | + * a=(pi*r^2)/C. |
753 | + */ |
754 | + int a = data[5]; |
755 | + int x_res = input_abs_get_res(input, ABS_X); |
756 | + int y_res = input_abs_get_res(input, ABS_Y); |
757 | + width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); |
758 | + height = width * y_res / x_res; |
759 | + } |
760 | |
761 | input_report_abs(input, ABS_MT_POSITION_X, x); |
762 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
763 | @@ -1337,6 +1349,9 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
764 | case INTUOS5S: |
765 | case INTUOS5: |
766 | case INTUOS5L: |
767 | + case INTUOSPS: |
768 | + case INTUOSPM: |
769 | + case INTUOSPL: |
770 | if (len == WACOM_PKGLEN_BBTOUCH3) |
771 | sync = wacom_bpt3_touch(wacom_wac); |
772 | else |
773 | @@ -1420,7 +1435,7 @@ void wacom_setup_device_quirks(struct wacom_features *features) |
774 | |
775 | /* these device have multiple inputs */ |
776 | if (features->type >= WIRELESS || |
777 | - (features->type >= INTUOS5S && features->type <= INTUOS5L) || |
778 | + (features->type >= INTUOS5S && features->type <= INTUOSPL) || |
779 | (features->oVid && features->oPid)) |
780 | features->quirks |= WACOM_QUIRK_MULTI_INPUT; |
781 | |
782 | @@ -1627,6 +1642,8 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, |
783 | |
784 | case INTUOS5: |
785 | case INTUOS5L: |
786 | + case INTUOSPM: |
787 | + case INTUOSPL: |
788 | if (features->device_type == BTN_TOOL_PEN) { |
789 | __set_bit(BTN_7, input_dev->keybit); |
790 | __set_bit(BTN_8, input_dev->keybit); |
791 | @@ -1634,6 +1651,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, |
792 | /* fall through */ |
793 | |
794 | case INTUOS5S: |
795 | + case INTUOSPS: |
796 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
797 | |
798 | if (features->device_type == BTN_TOOL_PEN) { |
799 | @@ -1952,6 +1970,18 @@ static const struct wacom_features wacom_features_0x29 = |
800 | static const struct wacom_features wacom_features_0x2A = |
801 | { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, |
802 | 63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
803 | +static const struct wacom_features wacom_features_0x314 = |
804 | + { "Wacom Intuos Pro S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, |
805 | + 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
806 | + .touch_max = 16 }; |
807 | +static const struct wacom_features wacom_features_0x315 = |
808 | + { "Wacom Intuos Pro M", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, |
809 | + 63, INTUOSPM, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
810 | + .touch_max = 16 }; |
811 | +static const struct wacom_features wacom_features_0x317 = |
812 | + { "Wacom Intuos Pro L", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, |
813 | + 63, INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, |
814 | + .touch_max = 16 }; |
815 | static const struct wacom_features wacom_features_0xF4 = |
816 | { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, |
817 | 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; |
818 | @@ -2259,6 +2289,9 @@ const struct usb_device_id wacom_ids[] = { |
819 | { USB_DEVICE_WACOM(0x300) }, |
820 | { USB_DEVICE_WACOM(0x301) }, |
821 | { USB_DEVICE_WACOM(0x304) }, |
822 | + { USB_DEVICE_DETAILED(0x314, USB_CLASS_HID, 0, 0) }, |
823 | + { USB_DEVICE_DETAILED(0x315, USB_CLASS_HID, 0, 0) }, |
824 | + { USB_DEVICE_DETAILED(0x317, USB_CLASS_HID, 0, 0) }, |
825 | { USB_DEVICE_WACOM(0x4001) }, |
826 | { USB_DEVICE_WACOM(0x47) }, |
827 | { USB_DEVICE_WACOM(0xF4) }, |
828 | diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h |
829 | index dfc9e08e7f70..d6dec5800791 100644 |
830 | --- a/drivers/input/tablet/wacom_wac.h |
831 | +++ b/drivers/input/tablet/wacom_wac.h |
832 | @@ -76,6 +76,9 @@ enum { |
833 | INTUOS5S, |
834 | INTUOS5, |
835 | INTUOS5L, |
836 | + INTUOSPS, |
837 | + INTUOSPM, |
838 | + INTUOSPL, |
839 | WACOM_21UX2, |
840 | WACOM_22HD, |
841 | DTK, |
842 | diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c |
843 | index e35bac7cfdf1..71d9cad02704 100644 |
844 | --- a/drivers/net/ethernet/marvell/mvneta.c |
845 | +++ b/drivers/net/ethernet/marvell/mvneta.c |
846 | @@ -88,8 +88,9 @@ |
847 | #define MVNETA_TX_IN_PRGRS BIT(1) |
848 | #define MVNETA_TX_FIFO_EMPTY BIT(8) |
849 | #define MVNETA_RX_MIN_FRAME_SIZE 0x247c |
850 | -#define MVNETA_SGMII_SERDES_CFG 0x24A0 |
851 | +#define MVNETA_SERDES_CFG 0x24A0 |
852 | #define MVNETA_SGMII_SERDES_PROTO 0x0cc7 |
853 | +#define MVNETA_RGMII_SERDES_PROTO 0x0667 |
854 | #define MVNETA_TYPE_PRIO 0x24bc |
855 | #define MVNETA_FORCE_UNI BIT(21) |
856 | #define MVNETA_TXQ_CMD_1 0x24e4 |
857 | @@ -121,7 +122,7 @@ |
858 | #define MVNETA_GMAC_MAX_RX_SIZE_MASK 0x7ffc |
859 | #define MVNETA_GMAC0_PORT_ENABLE BIT(0) |
860 | #define MVNETA_GMAC_CTRL_2 0x2c08 |
861 | -#define MVNETA_GMAC2_PSC_ENABLE BIT(3) |
862 | +#define MVNETA_GMAC2_PCS_ENABLE BIT(3) |
863 | #define MVNETA_GMAC2_PORT_RGMII BIT(4) |
864 | #define MVNETA_GMAC2_PORT_RESET BIT(6) |
865 | #define MVNETA_GMAC_STATUS 0x2c10 |
866 | @@ -665,35 +666,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp, |
867 | mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); |
868 | } |
869 | |
870 | - |
871 | - |
872 | -/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ |
873 | -static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) |
874 | -{ |
875 | - u32 val; |
876 | - |
877 | - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
878 | - |
879 | - if (enable) |
880 | - val |= MVNETA_GMAC2_PORT_RGMII; |
881 | - else |
882 | - val &= ~MVNETA_GMAC2_PORT_RGMII; |
883 | - |
884 | - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); |
885 | -} |
886 | - |
887 | -/* Config SGMII port */ |
888 | -static void mvneta_port_sgmii_config(struct mvneta_port *pp) |
889 | -{ |
890 | - u32 val; |
891 | - |
892 | - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
893 | - val |= MVNETA_GMAC2_PSC_ENABLE; |
894 | - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); |
895 | - |
896 | - mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); |
897 | -} |
898 | - |
899 | /* Start the Ethernet port RX and TX activity */ |
900 | static void mvneta_port_up(struct mvneta_port *pp) |
901 | { |
902 | @@ -2723,12 +2695,15 @@ static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) |
903 | mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); |
904 | |
905 | if (phy_mode == PHY_INTERFACE_MODE_SGMII) |
906 | - mvneta_port_sgmii_config(pp); |
907 | + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); |
908 | + else |
909 | + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_RGMII_SERDES_PROTO); |
910 | |
911 | - mvneta_gmac_rgmii_set(pp, 1); |
912 | + val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
913 | + |
914 | + val |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; |
915 | |
916 | /* Cancel Port Reset */ |
917 | - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); |
918 | val &= ~MVNETA_GMAC2_PORT_RESET; |
919 | mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); |
920 | |
921 | diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c |
922 | index 4fb7a8f83c8a..54af4e933695 100644 |
923 | --- a/drivers/vfio/vfio_iommu_type1.c |
924 | +++ b/drivers/vfio/vfio_iommu_type1.c |
925 | @@ -186,12 +186,12 @@ static bool is_invalid_reserved_pfn(unsigned long pfn) |
926 | if (pfn_valid(pfn)) { |
927 | bool reserved; |
928 | struct page *tail = pfn_to_page(pfn); |
929 | - struct page *head = compound_trans_head(tail); |
930 | + struct page *head = compound_head(tail); |
931 | reserved = !!(PageReserved(head)); |
932 | if (head != tail) { |
933 | /* |
934 | * "head" is not a dangling pointer |
935 | - * (compound_trans_head takes care of that) |
936 | + * (compound_head takes care of that) |
937 | * but the hugepage may have been split |
938 | * from under us (and we may not hold a |
939 | * reference count on the head page so it can |
940 | diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c |
941 | index dacaf74256a3..8659eb160b4d 100644 |
942 | --- a/drivers/video/fbmem.c |
943 | +++ b/drivers/video/fbmem.c |
944 | @@ -1916,6 +1916,9 @@ int fb_get_options(const char *name, char **option) |
945 | options = opt + name_len + 1; |
946 | } |
947 | } |
948 | + /* No match, pass global option */ |
949 | + if (!options && option && fb_mode_option) |
950 | + options = kstrdup(fb_mode_option, GFP_KERNEL); |
951 | if (options && !strncmp(options, "off", 3)) |
952 | retval = 1; |
953 | |
954 | diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c |
955 | index b232908a6192..4c437efa9d91 100644 |
956 | --- a/drivers/xen/balloon.c |
957 | +++ b/drivers/xen/balloon.c |
958 | @@ -405,11 +405,25 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) |
959 | state = BP_EAGAIN; |
960 | break; |
961 | } |
962 | + scrub_page(page); |
963 | |
964 | - pfn = page_to_pfn(page); |
965 | - frame_list[i] = pfn_to_mfn(pfn); |
966 | + frame_list[i] = page_to_pfn(page); |
967 | + } |
968 | |
969 | - scrub_page(page); |
970 | + /* |
971 | + * Ensure that ballooned highmem pages don't have kmaps. |
972 | + * |
973 | + * Do this before changing the p2m as kmap_flush_unused() |
974 | + * reads PTEs to obtain pages (and hence needs the original |
975 | + * p2m entry). |
976 | + */ |
977 | + kmap_flush_unused(); |
978 | + |
979 | + /* Update direct mapping, invalidate P2M, and add to balloon. */ |
980 | + for (i = 0; i < nr_pages; i++) { |
981 | + pfn = frame_list[i]; |
982 | + frame_list[i] = pfn_to_mfn(pfn); |
983 | + page = pfn_to_page(pfn); |
984 | |
985 | /* |
986 | * Ballooned out frames are effectively replaced with |
987 | @@ -433,11 +447,9 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) |
988 | } |
989 | put_balloon_scratch_page(); |
990 | |
991 | - balloon_append(pfn_to_page(pfn)); |
992 | + balloon_append(page); |
993 | } |
994 | |
995 | - /* Ensure that ballooned highmem pages don't have kmaps. */ |
996 | - kmap_flush_unused(); |
997 | flush_tlb_all(); |
998 | |
999 | set_xen_guest_handle(reservation.extent_start, frame_list); |
1000 | diff --git a/fs/dcache.c b/fs/dcache.c |
1001 | index 4021e0172602..30b38e23caa7 100644 |
1002 | --- a/fs/dcache.c |
1003 | +++ b/fs/dcache.c |
1004 | @@ -2846,9 +2846,9 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) |
1005 | u32 dlen = ACCESS_ONCE(name->len); |
1006 | char *p; |
1007 | |
1008 | - if (*buflen < dlen + 1) |
1009 | - return -ENAMETOOLONG; |
1010 | *buflen -= dlen + 1; |
1011 | + if (*buflen < 0) |
1012 | + return -ENAMETOOLONG; |
1013 | p = *buffer -= dlen + 1; |
1014 | *p++ = '/'; |
1015 | while (dlen--) { |
1016 | diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c |
1017 | index d90909ec6aa6..a5e34dd6a32c 100644 |
1018 | --- a/fs/dlm/lowcomms.c |
1019 | +++ b/fs/dlm/lowcomms.c |
1020 | @@ -649,6 +649,7 @@ static void process_sctp_notification(struct connection *con, |
1021 | struct msghdr *msg, char *buf) |
1022 | { |
1023 | union sctp_notification *sn = (union sctp_notification *)buf; |
1024 | + struct linger linger; |
1025 | |
1026 | switch (sn->sn_header.sn_type) { |
1027 | case SCTP_SEND_FAILED: |
1028 | @@ -727,6 +728,13 @@ static void process_sctp_notification(struct connection *con, |
1029 | } |
1030 | add_sock(new_con->sock, new_con); |
1031 | |
1032 | + linger.l_onoff = 1; |
1033 | + linger.l_linger = 0; |
1034 | + ret = kernel_setsockopt(new_con->sock, SOL_SOCKET, SO_LINGER, |
1035 | + (char *)&linger, sizeof(linger)); |
1036 | + if (ret < 0) |
1037 | + log_print("set socket option SO_LINGER failed"); |
1038 | + |
1039 | log_print("connecting to %d sctp association %d", |
1040 | nodeid, (int)sn->sn_assoc_change.sac_assoc_id); |
1041 | |
1042 | diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c |
1043 | index 55fe412b2410..786bf0708904 100644 |
1044 | --- a/fs/ext4/inode.c |
1045 | +++ b/fs/ext4/inode.c |
1046 | @@ -38,6 +38,7 @@ |
1047 | #include <linux/slab.h> |
1048 | #include <linux/ratelimit.h> |
1049 | #include <linux/aio.h> |
1050 | +#include <linux/bitops.h> |
1051 | |
1052 | #include "ext4_jbd2.h" |
1053 | #include "xattr.h" |
1054 | @@ -3922,18 +3923,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc) |
1055 | void ext4_set_inode_flags(struct inode *inode) |
1056 | { |
1057 | unsigned int flags = EXT4_I(inode)->i_flags; |
1058 | + unsigned int new_fl = 0; |
1059 | |
1060 | - inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); |
1061 | if (flags & EXT4_SYNC_FL) |
1062 | - inode->i_flags |= S_SYNC; |
1063 | + new_fl |= S_SYNC; |
1064 | if (flags & EXT4_APPEND_FL) |
1065 | - inode->i_flags |= S_APPEND; |
1066 | + new_fl |= S_APPEND; |
1067 | if (flags & EXT4_IMMUTABLE_FL) |
1068 | - inode->i_flags |= S_IMMUTABLE; |
1069 | + new_fl |= S_IMMUTABLE; |
1070 | if (flags & EXT4_NOATIME_FL) |
1071 | - inode->i_flags |= S_NOATIME; |
1072 | + new_fl |= S_NOATIME; |
1073 | if (flags & EXT4_DIRSYNC_FL) |
1074 | - inode->i_flags |= S_DIRSYNC; |
1075 | + new_fl |= S_DIRSYNC; |
1076 | + set_mask_bits(&inode->i_flags, |
1077 | + S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl); |
1078 | } |
1079 | |
1080 | /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ |
1081 | diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c |
1082 | index e1959efad64f..b5ebc2d7d80d 100644 |
1083 | --- a/fs/fscache/object-list.c |
1084 | +++ b/fs/fscache/object-list.c |
1085 | @@ -50,6 +50,8 @@ void fscache_objlist_add(struct fscache_object *obj) |
1086 | struct fscache_object *xobj; |
1087 | struct rb_node **p = &fscache_object_list.rb_node, *parent = NULL; |
1088 | |
1089 | + ASSERT(RB_EMPTY_NODE(&obj->objlist_link)); |
1090 | + |
1091 | write_lock(&fscache_object_list_lock); |
1092 | |
1093 | while (*p) { |
1094 | @@ -75,6 +77,9 @@ void fscache_objlist_add(struct fscache_object *obj) |
1095 | */ |
1096 | void fscache_objlist_remove(struct fscache_object *obj) |
1097 | { |
1098 | + if (RB_EMPTY_NODE(&obj->objlist_link)) |
1099 | + return; |
1100 | + |
1101 | write_lock(&fscache_object_list_lock); |
1102 | |
1103 | BUG_ON(RB_EMPTY_ROOT(&fscache_object_list)); |
1104 | diff --git a/fs/fscache/object.c b/fs/fscache/object.c |
1105 | index 86d75a60b20c..fec41344dacc 100644 |
1106 | --- a/fs/fscache/object.c |
1107 | +++ b/fs/fscache/object.c |
1108 | @@ -314,6 +314,9 @@ void fscache_object_init(struct fscache_object *object, |
1109 | object->cache = cache; |
1110 | object->cookie = cookie; |
1111 | object->parent = NULL; |
1112 | +#ifdef CONFIG_FSCACHE_OBJECT_LIST |
1113 | + RB_CLEAR_NODE(&object->objlist_link); |
1114 | +#endif |
1115 | |
1116 | object->oob_event_mask = 0; |
1117 | for (t = object->oob_table; t->events; t++) |
1118 | diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c |
1119 | index e81a1cae81b5..140280623348 100644 |
1120 | --- a/fs/nfs/dir.c |
1121 | +++ b/fs/nfs/dir.c |
1122 | @@ -276,6 +276,15 @@ out_eof: |
1123 | return -EBADCOOKIE; |
1124 | } |
1125 | |
1126 | +static bool |
1127 | +nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi) |
1128 | +{ |
1129 | + if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) |
1130 | + return false; |
1131 | + smp_rmb(); |
1132 | + return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags); |
1133 | +} |
1134 | + |
1135 | static |
1136 | int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) |
1137 | { |
1138 | @@ -289,8 +298,8 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des |
1139 | struct nfs_open_dir_context *ctx = desc->file->private_data; |
1140 | |
1141 | new_pos = desc->current_index + i; |
1142 | - if (ctx->attr_gencount != nfsi->attr_gencount |
1143 | - || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { |
1144 | + if (ctx->attr_gencount != nfsi->attr_gencount || |
1145 | + !nfs_readdir_inode_mapping_valid(nfsi)) { |
1146 | ctx->duped = 0; |
1147 | ctx->attr_gencount = nfsi->attr_gencount; |
1148 | } else if (new_pos < desc->ctx->pos) { |
1149 | @@ -1139,7 +1148,13 @@ out_zap_parent: |
1150 | if (inode && S_ISDIR(inode->i_mode)) { |
1151 | /* Purge readdir caches. */ |
1152 | nfs_zap_caches(inode); |
1153 | - if (dentry->d_flags & DCACHE_DISCONNECTED) |
1154 | + /* |
1155 | + * We can't d_drop the root of a disconnected tree: |
1156 | + * its d_hash is on the s_anon list and d_drop() would hide |
1157 | + * it from shrink_dcache_for_unmount(), leading to busy |
1158 | + * inodes on unmount and further oopses. |
1159 | + */ |
1160 | + if (IS_ROOT(dentry)) |
1161 | goto out_valid; |
1162 | } |
1163 | /* If we have submounts, don't unhash ! */ |
1164 | diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c |
1165 | index 91ff089d3412..af5f3ffcb157 100644 |
1166 | --- a/fs/nfs/direct.c |
1167 | +++ b/fs/nfs/direct.c |
1168 | @@ -223,14 +223,31 @@ out: |
1169 | * Synchronous I/O uses a stack-allocated iocb. Thus we can't trust |
1170 | * the iocb is still valid here if this is a synchronous request. |
1171 | */ |
1172 | -static void nfs_direct_complete(struct nfs_direct_req *dreq) |
1173 | +static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) |
1174 | { |
1175 | + struct inode *inode = dreq->inode; |
1176 | + |
1177 | + if (dreq->iocb && write) { |
1178 | + loff_t pos = dreq->iocb->ki_pos + dreq->count; |
1179 | + |
1180 | + spin_lock(&inode->i_lock); |
1181 | + if (i_size_read(inode) < pos) |
1182 | + i_size_write(inode, pos); |
1183 | + spin_unlock(&inode->i_lock); |
1184 | + } |
1185 | + |
1186 | + if (write) |
1187 | + nfs_zap_mapping(inode, inode->i_mapping); |
1188 | + |
1189 | + inode_dio_done(inode); |
1190 | + |
1191 | if (dreq->iocb) { |
1192 | long res = (long) dreq->error; |
1193 | if (!res) |
1194 | res = (long) dreq->count; |
1195 | aio_complete(dreq->iocb, res, 0); |
1196 | } |
1197 | + |
1198 | complete_all(&dreq->completion); |
1199 | |
1200 | nfs_direct_req_release(dreq); |
1201 | @@ -273,7 +290,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) |
1202 | } |
1203 | out_put: |
1204 | if (put_dreq(dreq)) |
1205 | - nfs_direct_complete(dreq); |
1206 | + nfs_direct_complete(dreq, false); |
1207 | hdr->release(hdr); |
1208 | } |
1209 | |
1210 | @@ -403,6 +420,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, |
1211 | loff_t pos, bool uio) |
1212 | { |
1213 | struct nfs_pageio_descriptor desc; |
1214 | + struct inode *inode = dreq->inode; |
1215 | ssize_t result = -EINVAL; |
1216 | size_t requested_bytes = 0; |
1217 | unsigned long seg; |
1218 | @@ -411,6 +429,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, |
1219 | &nfs_direct_read_completion_ops); |
1220 | get_dreq(dreq); |
1221 | desc.pg_dreq = dreq; |
1222 | + atomic_inc(&inode->i_dio_count); |
1223 | |
1224 | for (seg = 0; seg < nr_segs; seg++) { |
1225 | const struct iovec *vec = &iov[seg]; |
1226 | @@ -430,12 +449,13 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, |
1227 | * generic layer handle the completion. |
1228 | */ |
1229 | if (requested_bytes == 0) { |
1230 | + inode_dio_done(inode); |
1231 | nfs_direct_req_release(dreq); |
1232 | return result < 0 ? result : -EIO; |
1233 | } |
1234 | |
1235 | if (put_dreq(dreq)) |
1236 | - nfs_direct_complete(dreq); |
1237 | + nfs_direct_complete(dreq, false); |
1238 | return 0; |
1239 | } |
1240 | |
1241 | @@ -473,12 +493,6 @@ out: |
1242 | return result; |
1243 | } |
1244 | |
1245 | -static void nfs_inode_dio_write_done(struct inode *inode) |
1246 | -{ |
1247 | - nfs_zap_mapping(inode, inode->i_mapping); |
1248 | - inode_dio_done(inode); |
1249 | -} |
1250 | - |
1251 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) |
1252 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) |
1253 | { |
1254 | @@ -594,8 +608,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) |
1255 | nfs_direct_write_reschedule(dreq); |
1256 | break; |
1257 | default: |
1258 | - nfs_inode_dio_write_done(dreq->inode); |
1259 | - nfs_direct_complete(dreq); |
1260 | + nfs_direct_complete(dreq, true); |
1261 | } |
1262 | } |
1263 | |
1264 | @@ -611,8 +624,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) |
1265 | |
1266 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
1267 | { |
1268 | - nfs_inode_dio_write_done(inode); |
1269 | - nfs_direct_complete(dreq); |
1270 | + nfs_direct_complete(dreq, true); |
1271 | } |
1272 | #endif |
1273 | |
1274 | diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c |
1275 | index 0ee22ab9ef97..fdeeb28f287b 100644 |
1276 | --- a/fs/nfs/inode.c |
1277 | +++ b/fs/nfs/inode.c |
1278 | @@ -988,11 +988,11 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map |
1279 | if (ret < 0) |
1280 | return ret; |
1281 | } |
1282 | - spin_lock(&inode->i_lock); |
1283 | - nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
1284 | - if (S_ISDIR(inode->i_mode)) |
1285 | + if (S_ISDIR(inode->i_mode)) { |
1286 | + spin_lock(&inode->i_lock); |
1287 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
1288 | - spin_unlock(&inode->i_lock); |
1289 | + spin_unlock(&inode->i_lock); |
1290 | + } |
1291 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
1292 | nfs_fscache_wait_on_invalidate(inode); |
1293 | |
1294 | @@ -1018,6 +1018,7 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) |
1295 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) |
1296 | { |
1297 | struct nfs_inode *nfsi = NFS_I(inode); |
1298 | + unsigned long *bitlock = &nfsi->flags; |
1299 | int ret = 0; |
1300 | |
1301 | /* swapfiles are not supposed to be shared. */ |
1302 | @@ -1029,12 +1030,46 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) |
1303 | if (ret < 0) |
1304 | goto out; |
1305 | } |
1306 | - if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
1307 | - trace_nfs_invalidate_mapping_enter(inode); |
1308 | - ret = nfs_invalidate_mapping(inode, mapping); |
1309 | - trace_nfs_invalidate_mapping_exit(inode, ret); |
1310 | + |
1311 | + /* |
1312 | + * We must clear NFS_INO_INVALID_DATA first to ensure that |
1313 | + * invalidations that come in while we're shooting down the mappings |
1314 | + * are respected. But, that leaves a race window where one revalidator |
1315 | + * can clear the flag, and then another checks it before the mapping |
1316 | + * gets invalidated. Fix that by serializing access to this part of |
1317 | + * the function. |
1318 | + * |
1319 | + * At the same time, we need to allow other tasks to see whether we |
1320 | + * might be in the middle of invalidating the pages, so we only set |
1321 | + * the bit lock here if it looks like we're going to be doing that. |
1322 | + */ |
1323 | + for (;;) { |
1324 | + ret = wait_on_bit(bitlock, NFS_INO_INVALIDATING, |
1325 | + nfs_wait_bit_killable, TASK_KILLABLE); |
1326 | + if (ret) |
1327 | + goto out; |
1328 | + spin_lock(&inode->i_lock); |
1329 | + if (test_bit(NFS_INO_INVALIDATING, bitlock)) { |
1330 | + spin_unlock(&inode->i_lock); |
1331 | + continue; |
1332 | + } |
1333 | + if (nfsi->cache_validity & NFS_INO_INVALID_DATA) |
1334 | + break; |
1335 | + spin_unlock(&inode->i_lock); |
1336 | + goto out; |
1337 | } |
1338 | |
1339 | + set_bit(NFS_INO_INVALIDATING, bitlock); |
1340 | + smp_wmb(); |
1341 | + nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
1342 | + spin_unlock(&inode->i_lock); |
1343 | + trace_nfs_invalidate_mapping_enter(inode); |
1344 | + ret = nfs_invalidate_mapping(inode, mapping); |
1345 | + trace_nfs_invalidate_mapping_exit(inode, ret); |
1346 | + |
1347 | + clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); |
1348 | + smp_mb__after_clear_bit(); |
1349 | + wake_up_bit(bitlock, NFS_INO_INVALIDATING); |
1350 | out: |
1351 | return ret; |
1352 | } |
1353 | diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h |
1354 | index 28842abafab4..fdfd59157dce 100644 |
1355 | --- a/fs/nfs/nfs4_fs.h |
1356 | +++ b/fs/nfs/nfs4_fs.h |
1357 | @@ -249,6 +249,7 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser |
1358 | extern int nfs41_setup_sequence(struct nfs4_session *session, |
1359 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
1360 | struct rpc_task *task); |
1361 | +extern int nfs41_sequence_done(struct rpc_task *, struct nfs4_sequence_res *); |
1362 | extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); |
1363 | extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); |
1364 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, |
1365 | diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c |
1366 | index b86464ba25e1..394b0a0c54bf 100644 |
1367 | --- a/fs/nfs/nfs4filelayout.c |
1368 | +++ b/fs/nfs/nfs4filelayout.c |
1369 | @@ -335,8 +335,11 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data) |
1370 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); |
1371 | |
1372 | if (test_bit(NFS_IOHDR_REDO, &rdata->header->flags) && |
1373 | - task->tk_status == 0) |
1374 | + task->tk_status == 0) { |
1375 | + if (rdata->res.seq_res.sr_slot != NULL) |
1376 | + nfs41_sequence_done(task, &rdata->res.seq_res); |
1377 | return; |
1378 | + } |
1379 | |
1380 | /* Note this may cause RPC to be resent */ |
1381 | rdata->header->mds_ops->rpc_call_done(task, data); |
1382 | @@ -442,8 +445,11 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data) |
1383 | struct nfs_write_data *wdata = data; |
1384 | |
1385 | if (test_bit(NFS_IOHDR_REDO, &wdata->header->flags) && |
1386 | - task->tk_status == 0) |
1387 | + task->tk_status == 0) { |
1388 | + if (wdata->res.seq_res.sr_slot != NULL) |
1389 | + nfs41_sequence_done(task, &wdata->res.seq_res); |
1390 | return; |
1391 | + } |
1392 | |
1393 | /* Note this may cause RPC to be resent */ |
1394 | wdata->header->mds_ops->rpc_call_done(task, data); |
1395 | @@ -1216,17 +1222,17 @@ static void filelayout_recover_commit_reqs(struct list_head *dst, |
1396 | struct pnfs_commit_bucket *b; |
1397 | int i; |
1398 | |
1399 | - /* NOTE cinfo->lock is NOT held, relying on fact that this is |
1400 | - * only called on single thread per dreq. |
1401 | - * Can't take the lock because need to do pnfs_put_lseg |
1402 | - */ |
1403 | + spin_lock(cinfo->lock); |
1404 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { |
1405 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { |
1406 | + spin_unlock(cinfo->lock); |
1407 | pnfs_put_lseg(b->wlseg); |
1408 | b->wlseg = NULL; |
1409 | + spin_lock(cinfo->lock); |
1410 | } |
1411 | } |
1412 | cinfo->ds->nwritten = 0; |
1413 | + spin_unlock(cinfo->lock); |
1414 | } |
1415 | |
1416 | static unsigned int |
1417 | diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c |
1418 | index c7c295e556ed..efac602edb37 100644 |
1419 | --- a/fs/nfs/nfs4filelayoutdev.c |
1420 | +++ b/fs/nfs/nfs4filelayoutdev.c |
1421 | @@ -95,7 +95,7 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2) |
1422 | b6 = (struct sockaddr_in6 *)addr2; |
1423 | |
1424 | /* LINKLOCAL addresses must have matching scope_id */ |
1425 | - if (ipv6_addr_scope(&a6->sin6_addr) == |
1426 | + if (ipv6_addr_src_scope(&a6->sin6_addr) == |
1427 | IPV6_ADDR_SCOPE_LINKLOCAL && |
1428 | a6->sin6_scope_id != b6->sin6_scope_id) |
1429 | return false; |
1430 | diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c |
1431 | index 5a5fb98edb8a..bcd42fbc04e7 100644 |
1432 | --- a/fs/nfs/nfs4proc.c |
1433 | +++ b/fs/nfs/nfs4proc.c |
1434 | @@ -585,7 +585,7 @@ out_unlock: |
1435 | nfs41_server_notify_highest_slotid_update(session->clp); |
1436 | } |
1437 | |
1438 | -static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
1439 | +int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
1440 | { |
1441 | struct nfs4_session *session; |
1442 | struct nfs4_slot *slot; |
1443 | @@ -685,6 +685,7 @@ out_retry: |
1444 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
1445 | return 0; |
1446 | } |
1447 | +EXPORT_SYMBOL_GPL(nfs41_sequence_done); |
1448 | |
1449 | static int nfs4_sequence_done(struct rpc_task *task, |
1450 | struct nfs4_sequence_res *res) |
1451 | @@ -7273,7 +7274,14 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) |
1452 | return; |
1453 | |
1454 | server = NFS_SERVER(lrp->args.inode); |
1455 | - if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { |
1456 | + switch (task->tk_status) { |
1457 | + default: |
1458 | + task->tk_status = 0; |
1459 | + case 0: |
1460 | + break; |
1461 | + case -NFS4ERR_DELAY: |
1462 | + if (nfs4_async_handle_error(task, server, NULL) != -EAGAIN) |
1463 | + break; |
1464 | rpc_restart_call_prepare(task); |
1465 | return; |
1466 | } |
1467 | diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h |
1468 | index 89fe741e58b1..59f838cdc009 100644 |
1469 | --- a/fs/nfs/nfstrace.h |
1470 | +++ b/fs/nfs/nfstrace.h |
1471 | @@ -36,6 +36,7 @@ |
1472 | __print_flags(v, "|", \ |
1473 | { 1 << NFS_INO_ADVISE_RDPLUS, "ADVISE_RDPLUS" }, \ |
1474 | { 1 << NFS_INO_STALE, "STALE" }, \ |
1475 | + { 1 << NFS_INO_INVALIDATING, "INVALIDATING" }, \ |
1476 | { 1 << NFS_INO_FLUSHING, "FLUSHING" }, \ |
1477 | { 1 << NFS_INO_FSCACHE, "FSCACHE" }, \ |
1478 | { 1 << NFS_INO_COMMIT, "COMMIT" }, \ |
1479 | diff --git a/fs/nfs/write.c b/fs/nfs/write.c |
1480 | index 28466be64eeb..c6aa89f92558 100644 |
1481 | --- a/fs/nfs/write.c |
1482 | +++ b/fs/nfs/write.c |
1483 | @@ -909,9 +909,14 @@ bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx) |
1484 | */ |
1485 | static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) |
1486 | { |
1487 | + struct nfs_inode *nfsi = NFS_I(inode); |
1488 | + |
1489 | if (nfs_have_delegated_attributes(inode)) |
1490 | goto out; |
1491 | - if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) |
1492 | + if (nfsi->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) |
1493 | + return false; |
1494 | + smp_rmb(); |
1495 | + if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) |
1496 | return false; |
1497 | out: |
1498 | return PageUptodate(page) != 0; |
1499 | diff --git a/fs/proc/page.c b/fs/proc/page.c |
1500 | index b8730d9ebaee..2a8cc94bb641 100644 |
1501 | --- a/fs/proc/page.c |
1502 | +++ b/fs/proc/page.c |
1503 | @@ -121,7 +121,7 @@ u64 stable_page_flags(struct page *page) |
1504 | * just checks PG_head/PG_tail, so we need to check PageLRU to make |
1505 | * sure a given page is a thp, not a non-huge compound page. |
1506 | */ |
1507 | - else if (PageTransCompound(page) && PageLRU(compound_trans_head(page))) |
1508 | + else if (PageTransCompound(page) && PageLRU(compound_head(page))) |
1509 | u |= 1 << KPF_THP; |
1510 | |
1511 | /* |
1512 | diff --git a/include/linux/bitops.h b/include/linux/bitops.h |
1513 | index a3b6b82108b9..c1dde8e00d25 100644 |
1514 | --- a/include/linux/bitops.h |
1515 | +++ b/include/linux/bitops.h |
1516 | @@ -185,6 +185,21 @@ static inline unsigned long __ffs64(u64 word) |
1517 | |
1518 | #ifdef __KERNEL__ |
1519 | |
1520 | +#ifndef set_mask_bits |
1521 | +#define set_mask_bits(ptr, _mask, _bits) \ |
1522 | +({ \ |
1523 | + const typeof(*ptr) mask = (_mask), bits = (_bits); \ |
1524 | + typeof(*ptr) old, new; \ |
1525 | + \ |
1526 | + do { \ |
1527 | + old = ACCESS_ONCE(*ptr); \ |
1528 | + new = (old & ~mask) | bits; \ |
1529 | + } while (cmpxchg(ptr, old, new) != old); \ |
1530 | + \ |
1531 | + new; \ |
1532 | +}) |
1533 | +#endif |
1534 | + |
1535 | #ifndef find_last_bit |
1536 | /** |
1537 | * find_last_bit - find the last set bit in a memory region |
1538 | diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h |
1539 | index 3935428c57cf..a291552ab767 100644 |
1540 | --- a/include/linux/huge_mm.h |
1541 | +++ b/include/linux/huge_mm.h |
1542 | @@ -156,23 +156,6 @@ static inline int hpage_nr_pages(struct page *page) |
1543 | return HPAGE_PMD_NR; |
1544 | return 1; |
1545 | } |
1546 | -static inline struct page *compound_trans_head(struct page *page) |
1547 | -{ |
1548 | - if (PageTail(page)) { |
1549 | - struct page *head; |
1550 | - head = page->first_page; |
1551 | - smp_rmb(); |
1552 | - /* |
1553 | - * head may be a dangling pointer. |
1554 | - * __split_huge_page_refcount clears PageTail before |
1555 | - * overwriting first_page, so if PageTail is still |
1556 | - * there it means the head pointer isn't dangling. |
1557 | - */ |
1558 | - if (PageTail(page)) |
1559 | - return head; |
1560 | - } |
1561 | - return page; |
1562 | -} |
1563 | |
1564 | extern int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, |
1565 | unsigned long addr, pmd_t pmd, pmd_t *pmdp); |
1566 | @@ -202,7 +185,6 @@ static inline int split_huge_page(struct page *page) |
1567 | do { } while (0) |
1568 | #define split_huge_page_pmd_mm(__mm, __address, __pmd) \ |
1569 | do { } while (0) |
1570 | -#define compound_trans_head(page) compound_head(page) |
1571 | static inline int hugepage_madvise(struct vm_area_struct *vma, |
1572 | unsigned long *vm_flags, int advice) |
1573 | { |
1574 | diff --git a/include/linux/mm.h b/include/linux/mm.h |
1575 | index 648bcb007eba..073734339583 100644 |
1576 | --- a/include/linux/mm.h |
1577 | +++ b/include/linux/mm.h |
1578 | @@ -371,8 +371,18 @@ static inline void compound_unlock_irqrestore(struct page *page, |
1579 | |
1580 | static inline struct page *compound_head(struct page *page) |
1581 | { |
1582 | - if (unlikely(PageTail(page))) |
1583 | - return page->first_page; |
1584 | + if (unlikely(PageTail(page))) { |
1585 | + struct page *head = page->first_page; |
1586 | + |
1587 | + /* |
1588 | + * page->first_page may be a dangling pointer to an old |
1589 | + * compound page, so recheck that it is still a tail |
1590 | + * page before returning. |
1591 | + */ |
1592 | + smp_rmb(); |
1593 | + if (likely(PageTail(page))) |
1594 | + return head; |
1595 | + } |
1596 | return page; |
1597 | } |
1598 | |
1599 | diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h |
1600 | index 3ea4cde8701c..a632498d42fa 100644 |
1601 | --- a/include/linux/nfs_fs.h |
1602 | +++ b/include/linux/nfs_fs.h |
1603 | @@ -215,6 +215,7 @@ struct nfs_inode { |
1604 | #define NFS_INO_ADVISE_RDPLUS (0) /* advise readdirplus */ |
1605 | #define NFS_INO_STALE (1) /* possible stale inode */ |
1606 | #define NFS_INO_ACL_LRU_SET (2) /* Inode is on the LRU list */ |
1607 | +#define NFS_INO_INVALIDATING (3) /* inode is being invalidated */ |
1608 | #define NFS_INO_FLUSHING (4) /* inode is flushing out data */ |
1609 | #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ |
1610 | #define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ |
1611 | diff --git a/mm/ksm.c b/mm/ksm.c |
1612 | index 0bea2b262a47..c78fff1e9eae 100644 |
1613 | --- a/mm/ksm.c |
1614 | +++ b/mm/ksm.c |
1615 | @@ -444,7 +444,7 @@ static void break_cow(struct rmap_item *rmap_item) |
1616 | static struct page *page_trans_compound_anon(struct page *page) |
1617 | { |
1618 | if (PageTransCompound(page)) { |
1619 | - struct page *head = compound_trans_head(page); |
1620 | + struct page *head = compound_head(page); |
1621 | /* |
1622 | * head may actually be splitted and freed from under |
1623 | * us but it's ok here. |
1624 | diff --git a/mm/memory-failure.c b/mm/memory-failure.c |
1625 | index de476c2f8827..5ea3cf734138 100644 |
1626 | --- a/mm/memory-failure.c |
1627 | +++ b/mm/memory-failure.c |
1628 | @@ -1659,7 +1659,7 @@ int soft_offline_page(struct page *page, int flags) |
1629 | { |
1630 | int ret; |
1631 | unsigned long pfn = page_to_pfn(page); |
1632 | - struct page *hpage = compound_trans_head(page); |
1633 | + struct page *hpage = compound_head(page); |
1634 | |
1635 | if (PageHWPoison(page)) { |
1636 | pr_info("soft offline: %#lx page already poisoned\n", pfn); |
1637 | diff --git a/mm/page_alloc.c b/mm/page_alloc.c |
1638 | index 06f847933eeb..6fca39097766 100644 |
1639 | --- a/mm/page_alloc.c |
1640 | +++ b/mm/page_alloc.c |
1641 | @@ -369,9 +369,11 @@ void prep_compound_page(struct page *page, unsigned long order) |
1642 | __SetPageHead(page); |
1643 | for (i = 1; i < nr_pages; i++) { |
1644 | struct page *p = page + i; |
1645 | - __SetPageTail(p); |
1646 | set_page_count(p, 0); |
1647 | p->first_page = page; |
1648 | + /* Make sure p->first_page is always valid for PageTail() */ |
1649 | + smp_wmb(); |
1650 | + __SetPageTail(p); |
1651 | } |
1652 | } |
1653 | |
1654 | diff --git a/mm/swap.c b/mm/swap.c |
1655 | index 0c8f7a471925..aa4da5d9401d 100644 |
1656 | --- a/mm/swap.c |
1657 | +++ b/mm/swap.c |
1658 | @@ -84,7 +84,7 @@ static void put_compound_page(struct page *page) |
1659 | { |
1660 | if (unlikely(PageTail(page))) { |
1661 | /* __split_huge_page_refcount can run under us */ |
1662 | - struct page *page_head = compound_trans_head(page); |
1663 | + struct page *page_head = compound_head(page); |
1664 | |
1665 | if (likely(page != page_head && |
1666 | get_page_unless_zero(page_head))) { |
1667 | @@ -222,7 +222,7 @@ bool __get_page_tail(struct page *page) |
1668 | */ |
1669 | unsigned long flags; |
1670 | bool got = false; |
1671 | - struct page *page_head = compound_trans_head(page); |
1672 | + struct page *page_head = compound_head(page); |
1673 | |
1674 | if (likely(page != page_head && get_page_unless_zero(page_head))) { |
1675 | /* Ref to put_compound_page() comment. */ |
1676 | diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c |
1677 | index 4c8e5c0aa1ab..d585626d7676 100644 |
1678 | --- a/net/netfilter/ipvs/ip_vs_conn.c |
1679 | +++ b/net/netfilter/ipvs/ip_vs_conn.c |
1680 | @@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, |
1681 | cp->protocol = p->protocol; |
1682 | ip_vs_addr_set(p->af, &cp->caddr, p->caddr); |
1683 | cp->cport = p->cport; |
1684 | - ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr); |
1685 | - cp->vport = p->vport; |
1686 | - /* proto should only be IPPROTO_IP if d_addr is a fwmark */ |
1687 | + /* proto should only be IPPROTO_IP if p->vaddr is a fwmark */ |
1688 | ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, |
1689 | - &cp->daddr, daddr); |
1690 | + &cp->vaddr, p->vaddr); |
1691 | + cp->vport = p->vport; |
1692 | + ip_vs_addr_set(p->af, &cp->daddr, daddr); |
1693 | cp->dport = dport; |
1694 | cp->flags = flags; |
1695 | cp->fwmark = fwmark; |
1696 | diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c |
1697 | index a99b6c3427b0..59359bec328a 100644 |
1698 | --- a/net/netfilter/nf_conntrack_proto_dccp.c |
1699 | +++ b/net/netfilter/nf_conntrack_proto_dccp.c |
1700 | @@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, |
1701 | const char *msg; |
1702 | u_int8_t state; |
1703 | |
1704 | - dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); |
1705 | + dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
1706 | BUG_ON(dh == NULL); |
1707 | |
1708 | state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; |
1709 | @@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, |
1710 | u_int8_t type, old_state, new_state; |
1711 | enum ct_dccp_roles role; |
1712 | |
1713 | - dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); |
1714 | + dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
1715 | BUG_ON(dh == NULL); |
1716 | type = dh->dccph_type; |
1717 | |
1718 | @@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, |
1719 | unsigned int cscov; |
1720 | const char *msg; |
1721 | |
1722 | - dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); |
1723 | + dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); |
1724 | if (dh == NULL) { |
1725 | msg = "nf_ct_dccp: short packet "; |
1726 | goto out_invalid; |
1727 | diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c |
1728 | index a7f9821d1760..bb035f8451c6 100644 |
1729 | --- a/net/sunrpc/auth_gss/auth_gss.c |
1730 | +++ b/net/sunrpc/auth_gss/auth_gss.c |
1731 | @@ -1508,7 +1508,7 @@ out: |
1732 | static int |
1733 | gss_refresh_null(struct rpc_task *task) |
1734 | { |
1735 | - return -EACCES; |
1736 | + return 0; |
1737 | } |
1738 | |
1739 | static __be32 * |
1740 | diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c |
1741 | index 7d4ccfa48008..31da88bf6c1c 100644 |
1742 | --- a/sound/pci/hda/hda_generic.c |
1743 | +++ b/sound/pci/hda/hda_generic.c |
1744 | @@ -3264,7 +3264,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol, |
1745 | mutex_unlock(&codec->control_mutex); |
1746 | snd_hda_codec_flush_cache(codec); /* flush the updates */ |
1747 | if (err >= 0 && spec->cap_sync_hook) |
1748 | - spec->cap_sync_hook(codec, ucontrol); |
1749 | + spec->cap_sync_hook(codec, kcontrol, ucontrol); |
1750 | return err; |
1751 | } |
1752 | |
1753 | @@ -3385,7 +3385,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol, |
1754 | return ret; |
1755 | |
1756 | if (spec->cap_sync_hook) |
1757 | - spec->cap_sync_hook(codec, ucontrol); |
1758 | + spec->cap_sync_hook(codec, kcontrol, ucontrol); |
1759 | |
1760 | return ret; |
1761 | } |
1762 | @@ -3790,7 +3790,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx, |
1763 | return 0; |
1764 | snd_hda_activate_path(codec, path, true, false); |
1765 | if (spec->cap_sync_hook) |
1766 | - spec->cap_sync_hook(codec, NULL); |
1767 | + spec->cap_sync_hook(codec, NULL, NULL); |
1768 | path_power_down_sync(codec, old_path); |
1769 | return 1; |
1770 | } |
1771 | @@ -5233,7 +5233,7 @@ static void init_input_src(struct hda_codec *codec) |
1772 | } |
1773 | |
1774 | if (spec->cap_sync_hook) |
1775 | - spec->cap_sync_hook(codec, NULL); |
1776 | + spec->cap_sync_hook(codec, NULL, NULL); |
1777 | } |
1778 | |
1779 | /* set right pin controls for digital I/O */ |
1780 | diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h |
1781 | index 0929a06df812..a1095de808c8 100644 |
1782 | --- a/sound/pci/hda/hda_generic.h |
1783 | +++ b/sound/pci/hda/hda_generic.h |
1784 | @@ -274,6 +274,7 @@ struct hda_gen_spec { |
1785 | void (*init_hook)(struct hda_codec *codec); |
1786 | void (*automute_hook)(struct hda_codec *codec); |
1787 | void (*cap_sync_hook)(struct hda_codec *codec, |
1788 | + struct snd_kcontrol *kcontrol, |
1789 | struct snd_ctl_elem_value *ucontrol); |
1790 | |
1791 | /* PCM hooks */ |
1792 | diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c |
1793 | index 96f07ce56603..fde381d02afd 100644 |
1794 | --- a/sound/pci/hda/patch_conexant.c |
1795 | +++ b/sound/pci/hda/patch_conexant.c |
1796 | @@ -3282,7 +3282,8 @@ static void cxt_update_headset_mode(struct hda_codec *codec) |
1797 | } |
1798 | |
1799 | static void cxt_update_headset_mode_hook(struct hda_codec *codec, |
1800 | - struct snd_ctl_elem_value *ucontrol) |
1801 | + struct snd_kcontrol *kcontrol, |
1802 | + struct snd_ctl_elem_value *ucontrol) |
1803 | { |
1804 | cxt_update_headset_mode(codec); |
1805 | } |
1806 | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c |
1807 | index deddee9c1565..6a32c857f704 100644 |
1808 | --- a/sound/pci/hda/patch_realtek.c |
1809 | +++ b/sound/pci/hda/patch_realtek.c |
1810 | @@ -695,7 +695,8 @@ static void alc_inv_dmic_sync(struct hda_codec *codec, bool force) |
1811 | } |
1812 | |
1813 | static void alc_inv_dmic_hook(struct hda_codec *codec, |
1814 | - struct snd_ctl_elem_value *ucontrol) |
1815 | + struct snd_kcontrol *kcontrol, |
1816 | + struct snd_ctl_elem_value *ucontrol) |
1817 | { |
1818 | alc_inv_dmic_sync(codec, false); |
1819 | } |
1820 | @@ -3141,7 +3142,8 @@ static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled) |
1821 | |
1822 | /* turn on/off mic-mute LED per capture hook */ |
1823 | static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, |
1824 | - struct snd_ctl_elem_value *ucontrol) |
1825 | + struct snd_kcontrol *kcontrol, |
1826 | + struct snd_ctl_elem_value *ucontrol) |
1827 | { |
1828 | struct alc_spec *spec = codec->spec; |
1829 | unsigned int oldval = spec->gpio_led; |
1830 | @@ -3403,7 +3405,8 @@ static void alc_update_headset_mode(struct hda_codec *codec) |
1831 | } |
1832 | |
1833 | static void alc_update_headset_mode_hook(struct hda_codec *codec, |
1834 | - struct snd_ctl_elem_value *ucontrol) |
1835 | + struct snd_kcontrol *kcontrol, |
1836 | + struct snd_ctl_elem_value *ucontrol) |
1837 | { |
1838 | alc_update_headset_mode(codec); |
1839 | } |
1840 | diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c |
1841 | index 6133423821d1..d761c0b879c9 100644 |
1842 | --- a/sound/pci/hda/patch_sigmatel.c |
1843 | +++ b/sound/pci/hda/patch_sigmatel.c |
1844 | @@ -195,7 +195,7 @@ struct sigmatel_spec { |
1845 | int default_polarity; |
1846 | |
1847 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ |
1848 | - bool mic_mute_led_on; /* current mic mute state */ |
1849 | + unsigned int mic_enabled; /* current mic mute state (bitmask) */ |
1850 | |
1851 | /* stream */ |
1852 | unsigned int stream_delay; |
1853 | @@ -325,19 +325,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, |
1854 | |
1855 | /* hook for controlling mic-mute LED GPIO */ |
1856 | static void stac_capture_led_hook(struct hda_codec *codec, |
1857 | - struct snd_ctl_elem_value *ucontrol) |
1858 | + struct snd_kcontrol *kcontrol, |
1859 | + struct snd_ctl_elem_value *ucontrol) |
1860 | { |
1861 | struct sigmatel_spec *spec = codec->spec; |
1862 | - bool mute; |
1863 | + unsigned int mask; |
1864 | + bool cur_mute, prev_mute; |
1865 | |
1866 | - if (!ucontrol) |
1867 | + if (!kcontrol || !ucontrol) |
1868 | return; |
1869 | |
1870 | - mute = !(ucontrol->value.integer.value[0] || |
1871 | - ucontrol->value.integer.value[1]); |
1872 | - if (spec->mic_mute_led_on != mute) { |
1873 | - spec->mic_mute_led_on = mute; |
1874 | - if (mute) |
1875 | + mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
1876 | + prev_mute = !spec->mic_enabled; |
1877 | + if (ucontrol->value.integer.value[0] || |
1878 | + ucontrol->value.integer.value[1]) |
1879 | + spec->mic_enabled |= mask; |
1880 | + else |
1881 | + spec->mic_enabled &= ~mask; |
1882 | + cur_mute = !spec->mic_enabled; |
1883 | + if (cur_mute != prev_mute) { |
1884 | + if (cur_mute) |
1885 | spec->gpio_data |= spec->mic_mute_led_gpio; |
1886 | else |
1887 | spec->gpio_data &= ~spec->mic_mute_led_gpio; |
1888 | @@ -3974,7 +3981,7 @@ static void stac_setup_gpio(struct hda_codec *codec) |
1889 | if (spec->mic_mute_led_gpio) { |
1890 | spec->gpio_mask |= spec->mic_mute_led_gpio; |
1891 | spec->gpio_dir |= spec->mic_mute_led_gpio; |
1892 | - spec->mic_mute_led_on = true; |
1893 | + spec->mic_enabled = 0; |
1894 | spec->gpio_data |= spec->mic_mute_led_gpio; |
1895 | |
1896 | spec->gen.cap_sync_hook = stac_capture_led_hook; |