Annotation of /trunk/kernel-magellan/patches-3.11/0105-3.11.6-all-fixes.patch
Parent Directory | Revision Log
Revision 2313 -
(hide annotations)
(download)
Tue Oct 22 06:44:45 2013 UTC (10 years, 7 months ago) by niro
File size: 73295 byte(s)
Tue Oct 22 06:44:45 2013 UTC (10 years, 7 months ago) by niro
File size: 73295 byte(s)
-linux-3.11.6
1 | niro | 2313 | diff --git a/Makefile b/Makefile |
2 | index 83121b7..e87ba83 100644 | ||
3 | --- a/Makefile | ||
4 | +++ b/Makefile | ||
5 | @@ -1,6 +1,6 @@ | ||
6 | VERSION = 3 | ||
7 | PATCHLEVEL = 11 | ||
8 | -SUBLEVEL = 5 | ||
9 | +SUBLEVEL = 6 | ||
10 | EXTRAVERSION = | ||
11 | NAME = Linux for Workgroups | ||
12 | |||
13 | diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h | ||
14 | index 442ce5d..43de302 100644 | ||
15 | --- a/arch/arc/include/asm/delay.h | ||
16 | +++ b/arch/arc/include/asm/delay.h | ||
17 | @@ -53,11 +53,10 @@ static inline void __udelay(unsigned long usecs) | ||
18 | { | ||
19 | unsigned long loops; | ||
20 | |||
21 | - /* (long long) cast ensures 64 bit MPY - real or emulated | ||
22 | + /* (u64) cast ensures 64 bit MPY - real or emulated | ||
23 | * HZ * 4295 is pre-evaluated by gcc - hence only 2 mpy ops | ||
24 | */ | ||
25 | - loops = ((long long)(usecs * 4295 * HZ) * | ||
26 | - (long long)(loops_per_jiffy)) >> 32; | ||
27 | + loops = ((u64) usecs * 4295 * HZ * loops_per_jiffy) >> 32; | ||
28 | |||
29 | __delay(loops); | ||
30 | } | ||
31 | diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h | ||
32 | index f158197..b6a8c2d 100644 | ||
33 | --- a/arch/arc/include/asm/spinlock.h | ||
34 | +++ b/arch/arc/include/asm/spinlock.h | ||
35 | @@ -45,7 +45,14 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) | ||
36 | |||
37 | static inline void arch_spin_unlock(arch_spinlock_t *lock) | ||
38 | { | ||
39 | - lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__; | ||
40 | + unsigned int tmp = __ARCH_SPIN_LOCK_UNLOCKED__; | ||
41 | + | ||
42 | + __asm__ __volatile__( | ||
43 | + " ex %0, [%1] \n" | ||
44 | + : "+r" (tmp) | ||
45 | + : "r"(&(lock->slock)) | ||
46 | + : "memory"); | ||
47 | + | ||
48 | smp_mb(); | ||
49 | } | ||
50 | |||
51 | diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h | ||
52 | index 3242082..30c9baf 100644 | ||
53 | --- a/arch/arc/include/asm/uaccess.h | ||
54 | +++ b/arch/arc/include/asm/uaccess.h | ||
55 | @@ -43,7 +43,7 @@ | ||
56 | * Because it essentially checks if buffer end is within limit and @len is | ||
57 | * non-ngeative, which implies that buffer start will be within limit too. | ||
58 | * | ||
59 | - * The reason for rewriting being, for majorit yof cases, @len is generally | ||
60 | + * The reason for rewriting being, for majority of cases, @len is generally | ||
61 | * compile time constant, causing first sub-expression to be compile time | ||
62 | * subsumed. | ||
63 | * | ||
64 | @@ -53,7 +53,7 @@ | ||
65 | * | ||
66 | */ | ||
67 | #define __user_ok(addr, sz) (((sz) <= TASK_SIZE) && \ | ||
68 | - (((addr)+(sz)) <= get_fs())) | ||
69 | + ((addr) <= (get_fs() - (sz)))) | ||
70 | #define __access_ok(addr, sz) (unlikely(__kernel_ok) || \ | ||
71 | likely(__user_ok((addr), (sz)))) | ||
72 | |||
73 | diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c | ||
74 | index 3332385..5d76706 100644 | ||
75 | --- a/arch/arc/kernel/ptrace.c | ||
76 | +++ b/arch/arc/kernel/ptrace.c | ||
77 | @@ -102,7 +102,7 @@ static int genregs_set(struct task_struct *target, | ||
78 | REG_IGNORE_ONE(pad2); | ||
79 | REG_IN_CHUNK(callee, efa, cregs); /* callee_regs[r25..r13] */ | ||
80 | REG_IGNORE_ONE(efa); /* efa update invalid */ | ||
81 | - REG_IN_ONE(stop_pc, &ptregs->ret); /* stop_pc: PC update */ | ||
82 | + REG_IGNORE_ONE(stop_pc); /* PC updated via @ret */ | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c | ||
87 | index ee6ef2f..7e95e1a 100644 | ||
88 | --- a/arch/arc/kernel/signal.c | ||
89 | +++ b/arch/arc/kernel/signal.c | ||
90 | @@ -101,7 +101,6 @@ SYSCALL_DEFINE0(rt_sigreturn) | ||
91 | { | ||
92 | struct rt_sigframe __user *sf; | ||
93 | unsigned int magic; | ||
94 | - int err; | ||
95 | struct pt_regs *regs = current_pt_regs(); | ||
96 | |||
97 | /* Always make any pending restarted system calls return -EINTR */ | ||
98 | @@ -119,15 +118,16 @@ SYSCALL_DEFINE0(rt_sigreturn) | ||
99 | if (!access_ok(VERIFY_READ, sf, sizeof(*sf))) | ||
100 | goto badframe; | ||
101 | |||
102 | - err = restore_usr_regs(regs, sf); | ||
103 | - err |= __get_user(magic, &sf->sigret_magic); | ||
104 | - if (err) | ||
105 | + if (__get_user(magic, &sf->sigret_magic)) | ||
106 | goto badframe; | ||
107 | |||
108 | if (unlikely(is_do_ss_needed(magic))) | ||
109 | if (restore_altstack(&sf->uc.uc_stack)) | ||
110 | goto badframe; | ||
111 | |||
112 | + if (restore_usr_regs(regs, sf)) | ||
113 | + goto badframe; | ||
114 | + | ||
115 | /* Don't restart from sigreturn */ | ||
116 | syscall_wont_restart(regs); | ||
117 | |||
118 | @@ -191,6 +191,15 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, | ||
119 | return 1; | ||
120 | |||
121 | /* | ||
122 | + * w/o SA_SIGINFO, struct ucontext is partially populated (only | ||
123 | + * uc_mcontext/uc_sigmask) for kernel's normal user state preservation | ||
124 | + * during signal handler execution. This works for SA_SIGINFO as well | ||
125 | + * although the semantics are now overloaded (the same reg state can be | ||
126 | + * inspected by userland: but are they allowed to fiddle with it ? | ||
127 | + */ | ||
128 | + err |= stash_usr_regs(sf, regs, set); | ||
129 | + | ||
130 | + /* | ||
131 | * SA_SIGINFO requires 3 args to signal handler: | ||
132 | * #1: sig-no (common to any handler) | ||
133 | * #2: struct siginfo | ||
134 | @@ -213,14 +222,6 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, | ||
135 | magic = MAGIC_SIGALTSTK; | ||
136 | } | ||
137 | |||
138 | - /* | ||
139 | - * w/o SA_SIGINFO, struct ucontext is partially populated (only | ||
140 | - * uc_mcontext/uc_sigmask) for kernel's normal user state preservation | ||
141 | - * during signal handler execution. This works for SA_SIGINFO as well | ||
142 | - * although the semantics are now overloaded (the same reg state can be | ||
143 | - * inspected by userland: but are they allowed to fiddle with it ? | ||
144 | - */ | ||
145 | - err |= stash_usr_regs(sf, regs, set); | ||
146 | err |= __put_user(magic, &sf->sigret_magic); | ||
147 | if (err) | ||
148 | return err; | ||
149 | diff --git a/arch/arc/kernel/unaligned.c b/arch/arc/kernel/unaligned.c | ||
150 | index c0f832f..00ad070 100644 | ||
151 | --- a/arch/arc/kernel/unaligned.c | ||
152 | +++ b/arch/arc/kernel/unaligned.c | ||
153 | @@ -233,6 +233,12 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs, | ||
154 | regs->status32 &= ~STATUS_DE_MASK; | ||
155 | } else { | ||
156 | regs->ret += state.instr_len; | ||
157 | + | ||
158 | + /* handle zero-overhead-loop */ | ||
159 | + if ((regs->ret == regs->lp_end) && (regs->lp_count)) { | ||
160 | + regs->ret = regs->lp_start; | ||
161 | + regs->lp_count--; | ||
162 | + } | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h | ||
167 | index bfc198c..863c892 100644 | ||
168 | --- a/arch/arm/include/asm/jump_label.h | ||
169 | +++ b/arch/arm/include/asm/jump_label.h | ||
170 | @@ -16,7 +16,7 @@ | ||
171 | |||
172 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
173 | { | ||
174 | - asm goto("1:\n\t" | ||
175 | + asm_volatile_goto("1:\n\t" | ||
176 | JUMP_LABEL_NOP "\n\t" | ||
177 | ".pushsection __jump_table, \"aw\"\n\t" | ||
178 | ".word 1b, %l[l_yes], %c0\n\t" | ||
179 | diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h | ||
180 | index 4d6d77e..e194f95 100644 | ||
181 | --- a/arch/mips/include/asm/jump_label.h | ||
182 | +++ b/arch/mips/include/asm/jump_label.h | ||
183 | @@ -22,7 +22,7 @@ | ||
184 | |||
185 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
186 | { | ||
187 | - asm goto("1:\tnop\n\t" | ||
188 | + asm_volatile_goto("1:\tnop\n\t" | ||
189 | "nop\n\t" | ||
190 | ".pushsection __jump_table, \"aw\"\n\t" | ||
191 | WORD_INSN " 1b, %l[l_yes], %0\n\t" | ||
192 | diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S | ||
193 | index 4204d76..029e002 100644 | ||
194 | --- a/arch/mips/kernel/octeon_switch.S | ||
195 | +++ b/arch/mips/kernel/octeon_switch.S | ||
196 | @@ -73,7 +73,7 @@ | ||
197 | 3: | ||
198 | |||
199 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) | ||
200 | - PTR_L t8, __stack_chk_guard | ||
201 | + PTR_LA t8, __stack_chk_guard | ||
202 | LONG_L t9, TASK_STACK_CANARY(a1) | ||
203 | LONG_S t9, 0(t8) | ||
204 | #endif | ||
205 | diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S | ||
206 | index 38af83f..20b7b04 100644 | ||
207 | --- a/arch/mips/kernel/r2300_switch.S | ||
208 | +++ b/arch/mips/kernel/r2300_switch.S | ||
209 | @@ -67,7 +67,7 @@ LEAF(resume) | ||
210 | 1: | ||
211 | |||
212 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) | ||
213 | - PTR_L t8, __stack_chk_guard | ||
214 | + PTR_LA t8, __stack_chk_guard | ||
215 | LONG_L t9, TASK_STACK_CANARY(a1) | ||
216 | LONG_S t9, 0(t8) | ||
217 | #endif | ||
218 | diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S | ||
219 | index 921238a..078de5e 100644 | ||
220 | --- a/arch/mips/kernel/r4k_switch.S | ||
221 | +++ b/arch/mips/kernel/r4k_switch.S | ||
222 | @@ -69,7 +69,7 @@ | ||
223 | 1: | ||
224 | |||
225 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) | ||
226 | - PTR_L t8, __stack_chk_guard | ||
227 | + PTR_LA t8, __stack_chk_guard | ||
228 | LONG_L t9, TASK_STACK_CANARY(a1) | ||
229 | LONG_S t9, 0(t8) | ||
230 | #endif | ||
231 | diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c | ||
232 | index 04e47c6..b3f87a3 100644 | ||
233 | --- a/arch/parisc/kernel/traps.c | ||
234 | +++ b/arch/parisc/kernel/traps.c | ||
235 | @@ -805,14 +805,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs) | ||
236 | else { | ||
237 | |||
238 | /* | ||
239 | - * The kernel should never fault on its own address space. | ||
240 | + * The kernel should never fault on its own address space, | ||
241 | + * unless pagefault_disable() was called before. | ||
242 | */ | ||
243 | |||
244 | - if (fault_space == 0) | ||
245 | + if (fault_space == 0 && !in_atomic()) | ||
246 | { | ||
247 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); | ||
248 | parisc_terminate("Kernel Fault", regs, code, fault_address); | ||
249 | - | ||
250 | } | ||
251 | } | ||
252 | |||
253 | diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h | ||
254 | index ae098c4..f016bb6 100644 | ||
255 | --- a/arch/powerpc/include/asm/jump_label.h | ||
256 | +++ b/arch/powerpc/include/asm/jump_label.h | ||
257 | @@ -19,7 +19,7 @@ | ||
258 | |||
259 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
260 | { | ||
261 | - asm goto("1:\n\t" | ||
262 | + asm_volatile_goto("1:\n\t" | ||
263 | "nop\n\t" | ||
264 | ".pushsection __jump_table, \"aw\"\n\t" | ||
265 | JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t" | ||
266 | diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | ||
267 | index b02f91e..7bcd4d6 100644 | ||
268 | --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S | ||
269 | +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | ||
270 | @@ -1054,7 +1054,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | ||
271 | BEGIN_FTR_SECTION | ||
272 | mfspr r8, SPRN_DSCR | ||
273 | ld r7, HSTATE_DSCR(r13) | ||
274 | - std r8, VCPU_DSCR(r7) | ||
275 | + std r8, VCPU_DSCR(r9) | ||
276 | mtspr SPRN_DSCR, r7 | ||
277 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | ||
278 | |||
279 | diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h | ||
280 | index 6c32190..346b1c8 100644 | ||
281 | --- a/arch/s390/include/asm/jump_label.h | ||
282 | +++ b/arch/s390/include/asm/jump_label.h | ||
283 | @@ -15,7 +15,7 @@ | ||
284 | |||
285 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
286 | { | ||
287 | - asm goto("0: brcl 0,0\n" | ||
288 | + asm_volatile_goto("0: brcl 0,0\n" | ||
289 | ".pushsection __jump_table, \"aw\"\n" | ||
290 | ASM_ALIGN "\n" | ||
291 | ASM_PTR " 0b, %l[label], %0\n" | ||
292 | diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h | ||
293 | index 5080d16..ec2e2e2 100644 | ||
294 | --- a/arch/sparc/include/asm/jump_label.h | ||
295 | +++ b/arch/sparc/include/asm/jump_label.h | ||
296 | @@ -9,7 +9,7 @@ | ||
297 | |||
298 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
299 | { | ||
300 | - asm goto("1:\n\t" | ||
301 | + asm_volatile_goto("1:\n\t" | ||
302 | "nop\n\t" | ||
303 | "nop\n\t" | ||
304 | ".pushsection __jump_table, \"aw\"\n\t" | ||
305 | diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h | ||
306 | index 47538a6..7290585 100644 | ||
307 | --- a/arch/x86/include/asm/cpufeature.h | ||
308 | +++ b/arch/x86/include/asm/cpufeature.h | ||
309 | @@ -373,7 +373,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) | ||
310 | * Catch too early usage of this before alternatives | ||
311 | * have run. | ||
312 | */ | ||
313 | - asm goto("1: jmp %l[t_warn]\n" | ||
314 | + asm_volatile_goto("1: jmp %l[t_warn]\n" | ||
315 | "2:\n" | ||
316 | ".section .altinstructions,\"a\"\n" | ||
317 | " .long 1b - .\n" | ||
318 | @@ -386,7 +386,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) | ||
319 | : : "i" (X86_FEATURE_ALWAYS) : : t_warn); | ||
320 | #endif | ||
321 | |||
322 | - asm goto("1: jmp %l[t_no]\n" | ||
323 | + asm_volatile_goto("1: jmp %l[t_no]\n" | ||
324 | "2:\n" | ||
325 | ".section .altinstructions,\"a\"\n" | ||
326 | " .long 1b - .\n" | ||
327 | @@ -448,7 +448,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) | ||
328 | * have. Thus, we force the jump to the widest, 4-byte, signed relative | ||
329 | * offset even though the last would often fit in less bytes. | ||
330 | */ | ||
331 | - asm goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n" | ||
332 | + asm_volatile_goto("1: .byte 0xe9\n .long %l[t_dynamic] - 2f\n" | ||
333 | "2:\n" | ||
334 | ".section .altinstructions,\"a\"\n" | ||
335 | " .long 1b - .\n" /* src offset */ | ||
336 | diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h | ||
337 | index cccd07f..779c2ef 100644 | ||
338 | --- a/arch/x86/include/asm/e820.h | ||
339 | +++ b/arch/x86/include/asm/e820.h | ||
340 | @@ -29,7 +29,7 @@ extern void e820_setup_gap(void); | ||
341 | extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, | ||
342 | unsigned long start_addr, unsigned long long end_addr); | ||
343 | struct setup_data; | ||
344 | -extern void parse_e820_ext(struct setup_data *data); | ||
345 | +extern void parse_e820_ext(u64 phys_addr, u32 data_len); | ||
346 | |||
347 | #if defined(CONFIG_X86_64) || \ | ||
348 | (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) | ||
349 | diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h | ||
350 | index 3a16c14..0297669 100644 | ||
351 | --- a/arch/x86/include/asm/jump_label.h | ||
352 | +++ b/arch/x86/include/asm/jump_label.h | ||
353 | @@ -13,7 +13,7 @@ | ||
354 | |||
355 | static __always_inline bool arch_static_branch(struct static_key *key) | ||
356 | { | ||
357 | - asm goto("1:" | ||
358 | + asm_volatile_goto("1:" | ||
359 | STATIC_KEY_INITIAL_NOP | ||
360 | ".pushsection __jump_table, \"aw\" \n\t" | ||
361 | _ASM_ALIGN "\n\t" | ||
362 | diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c | ||
363 | index d32abea..174da5f 100644 | ||
364 | --- a/arch/x86/kernel/e820.c | ||
365 | +++ b/arch/x86/kernel/e820.c | ||
366 | @@ -658,15 +658,18 @@ __init void e820_setup_gap(void) | ||
367 | * boot_params.e820_map, others are passed via SETUP_E820_EXT node of | ||
368 | * linked list of struct setup_data, which is parsed here. | ||
369 | */ | ||
370 | -void __init parse_e820_ext(struct setup_data *sdata) | ||
371 | +void __init parse_e820_ext(u64 phys_addr, u32 data_len) | ||
372 | { | ||
373 | int entries; | ||
374 | struct e820entry *extmap; | ||
375 | + struct setup_data *sdata; | ||
376 | |||
377 | + sdata = early_memremap(phys_addr, data_len); | ||
378 | entries = sdata->len / sizeof(struct e820entry); | ||
379 | extmap = (struct e820entry *)(sdata->data); | ||
380 | __append_e820_map(extmap, entries); | ||
381 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | ||
382 | + early_iounmap(sdata, data_len); | ||
383 | printk(KERN_INFO "e820: extended physical RAM map:\n"); | ||
384 | e820_print_map("extended"); | ||
385 | } | ||
386 | diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c | ||
387 | index f8ec578..234e1e3 100644 | ||
388 | --- a/arch/x86/kernel/setup.c | ||
389 | +++ b/arch/x86/kernel/setup.c | ||
390 | @@ -426,25 +426,23 @@ static void __init reserve_initrd(void) | ||
391 | static void __init parse_setup_data(void) | ||
392 | { | ||
393 | struct setup_data *data; | ||
394 | - u64 pa_data; | ||
395 | + u64 pa_data, pa_next; | ||
396 | |||
397 | pa_data = boot_params.hdr.setup_data; | ||
398 | while (pa_data) { | ||
399 | - u32 data_len, map_len; | ||
400 | + u32 data_len, map_len, data_type; | ||
401 | |||
402 | map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), | ||
403 | (u64)sizeof(struct setup_data)); | ||
404 | data = early_memremap(pa_data, map_len); | ||
405 | data_len = data->len + sizeof(struct setup_data); | ||
406 | - if (data_len > map_len) { | ||
407 | - early_iounmap(data, map_len); | ||
408 | - data = early_memremap(pa_data, data_len); | ||
409 | - map_len = data_len; | ||
410 | - } | ||
411 | + data_type = data->type; | ||
412 | + pa_next = data->next; | ||
413 | + early_iounmap(data, map_len); | ||
414 | |||
415 | - switch (data->type) { | ||
416 | + switch (data_type) { | ||
417 | case SETUP_E820_EXT: | ||
418 | - parse_e820_ext(data); | ||
419 | + parse_e820_ext(pa_data, data_len); | ||
420 | break; | ||
421 | case SETUP_DTB: | ||
422 | add_dtb(pa_data); | ||
423 | @@ -452,8 +450,7 @@ static void __init parse_setup_data(void) | ||
424 | default: | ||
425 | break; | ||
426 | } | ||
427 | - pa_data = data->next; | ||
428 | - early_iounmap(data, map_len); | ||
429 | + pa_data = pa_next; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | diff --git a/drivers/char/random.c b/drivers/char/random.c | ||
434 | index 0d91fe5..92e6c67 100644 | ||
435 | --- a/drivers/char/random.c | ||
436 | +++ b/drivers/char/random.c | ||
437 | @@ -1462,12 +1462,11 @@ struct ctl_table random_table[] = { | ||
438 | |||
439 | static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; | ||
440 | |||
441 | -static int __init random_int_secret_init(void) | ||
442 | +int random_int_secret_init(void) | ||
443 | { | ||
444 | get_random_bytes(random_int_secret, sizeof(random_int_secret)); | ||
445 | return 0; | ||
446 | } | ||
447 | -late_initcall(random_int_secret_init); | ||
448 | |||
449 | /* | ||
450 | * Get a random word for internal kernel use only. Similar to urandom but | ||
451 | diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h | ||
452 | index 342f1f3..c42d31c 100644 | ||
453 | --- a/drivers/gpu/drm/i915/i915_reg.h | ||
454 | +++ b/drivers/gpu/drm/i915/i915_reg.h | ||
455 | @@ -3791,6 +3791,9 @@ | ||
456 | #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 | ||
457 | #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) | ||
458 | |||
459 | +#define HSW_SCRATCH1 0xb038 | ||
460 | +#define HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE (1<<27) | ||
461 | + | ||
462 | #define HSW_FUSE_STRAP 0x42014 | ||
463 | #define HSW_CDCLK_LIMIT (1 << 24) | ||
464 | |||
465 | @@ -4624,6 +4627,9 @@ | ||
466 | #define GEN7_ROW_CHICKEN2_GT2 0xf4f4 | ||
467 | #define DOP_CLOCK_GATING_DISABLE (1<<0) | ||
468 | |||
469 | +#define HSW_ROW_CHICKEN3 0xe49c | ||
470 | +#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) | ||
471 | + | ||
472 | #define G4X_AUD_VID_DID (dev_priv->info->display_mmio_offset + 0x62020) | ||
473 | #define INTEL_AUDIO_DEVCL 0x808629FB | ||
474 | #define INTEL_AUDIO_DEVBLC 0x80862801 | ||
475 | diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c | ||
476 | index 7fc8a76..90a7c17 100644 | ||
477 | --- a/drivers/gpu/drm/i915/intel_display.c | ||
478 | +++ b/drivers/gpu/drm/i915/intel_display.c | ||
479 | @@ -3890,8 +3890,6 @@ static void intel_connector_check_state(struct intel_connector *connector) | ||
480 | * consider. */ | ||
481 | void intel_connector_dpms(struct drm_connector *connector, int mode) | ||
482 | { | ||
483 | - struct intel_encoder *encoder = intel_attached_encoder(connector); | ||
484 | - | ||
485 | /* All the simple cases only support two dpms states. */ | ||
486 | if (mode != DRM_MODE_DPMS_ON) | ||
487 | mode = DRM_MODE_DPMS_OFF; | ||
488 | @@ -3902,10 +3900,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) | ||
489 | connector->dpms = mode; | ||
490 | |||
491 | /* Only need to change hw state when actually enabled */ | ||
492 | - if (encoder->base.crtc) | ||
493 | - intel_encoder_dpms(encoder, mode); | ||
494 | - else | ||
495 | - WARN_ON(encoder->connectors_active != false); | ||
496 | + if (connector->encoder) | ||
497 | + intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); | ||
498 | |||
499 | intel_modeset_check_state(connector->dev); | ||
500 | } | ||
501 | diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c | ||
502 | index b0e4a0b..cad0482 100644 | ||
503 | --- a/drivers/gpu/drm/i915/intel_pm.c | ||
504 | +++ b/drivers/gpu/drm/i915/intel_pm.c | ||
505 | @@ -3603,8 +3603,6 @@ static void valleyview_enable_rps(struct drm_device *dev) | ||
506 | dev_priv->rps.rpe_delay), | ||
507 | dev_priv->rps.rpe_delay); | ||
508 | |||
509 | - INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); | ||
510 | - | ||
511 | valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); | ||
512 | |||
513 | /* requires MSI enabled */ | ||
514 | @@ -4699,6 +4697,11 @@ static void haswell_init_clock_gating(struct drm_device *dev) | ||
515 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | ||
516 | GEN7_WA_L3_CHICKEN_MODE); | ||
517 | |||
518 | + /* L3 caching of data atomics doesn't work -- disable it. */ | ||
519 | + I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); | ||
520 | + I915_WRITE(HSW_ROW_CHICKEN3, | ||
521 | + _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE)); | ||
522 | + | ||
523 | /* This is required by WaCatErrorRejectionIssue:hsw */ | ||
524 | I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, | ||
525 | I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | | ||
526 | @@ -5562,6 +5565,8 @@ void intel_pm_init(struct drm_device *dev) | ||
527 | |||
528 | INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, | ||
529 | intel_gen6_powersave_work); | ||
530 | + | ||
531 | + INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); | ||
532 | } | ||
533 | |||
534 | int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) | ||
535 | diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c | ||
536 | index 084e694..639b9aa 100644 | ||
537 | --- a/drivers/gpu/drm/radeon/btc_dpm.c | ||
538 | +++ b/drivers/gpu/drm/radeon/btc_dpm.c | ||
539 | @@ -1913,7 +1913,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, | ||
540 | } | ||
541 | j++; | ||
542 | |||
543 | - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
544 | + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
545 | return -EINVAL; | ||
546 | |||
547 | tmp = RREG32(MC_PMG_CMD_MRS); | ||
548 | @@ -1928,7 +1928,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, | ||
549 | } | ||
550 | j++; | ||
551 | |||
552 | - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
553 | + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
554 | return -EINVAL; | ||
555 | break; | ||
556 | case MC_SEQ_RESERVE_M >> 2: | ||
557 | @@ -1942,7 +1942,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, | ||
558 | } | ||
559 | j++; | ||
560 | |||
561 | - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
562 | + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) | ||
563 | return -EINVAL; | ||
564 | break; | ||
565 | default: | ||
566 | diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c | ||
567 | index 94dab1e..8307883 100644 | ||
568 | --- a/drivers/gpu/drm/radeon/evergreen.c | ||
569 | +++ b/drivers/gpu/drm/radeon/evergreen.c | ||
570 | @@ -3126,7 +3126,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | ||
571 | rdev->config.evergreen.sx_max_export_size = 256; | ||
572 | rdev->config.evergreen.sx_max_export_pos_size = 64; | ||
573 | rdev->config.evergreen.sx_max_export_smx_size = 192; | ||
574 | - rdev->config.evergreen.max_hw_contexts = 8; | ||
575 | + rdev->config.evergreen.max_hw_contexts = 4; | ||
576 | rdev->config.evergreen.sq_num_cf_insts = 2; | ||
577 | |||
578 | rdev->config.evergreen.sc_prim_fifo_size = 0x40; | ||
579 | diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h | ||
580 | index 20fd17c..6be00c9 100644 | ||
581 | --- a/drivers/gpu/drm/radeon/evergreend.h | ||
582 | +++ b/drivers/gpu/drm/radeon/evergreend.h | ||
583 | @@ -1494,7 +1494,7 @@ | ||
584 | * 6. COMMAND [29:22] | BYTE_COUNT [20:0] | ||
585 | */ | ||
586 | # define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) | ||
587 | - /* 0 - SRC_ADDR | ||
588 | + /* 0 - DST_ADDR | ||
589 | * 1 - GDS | ||
590 | */ | ||
591 | # define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) | ||
592 | @@ -1509,7 +1509,7 @@ | ||
593 | # define PACKET3_CP_DMA_CP_SYNC (1 << 31) | ||
594 | /* COMMAND */ | ||
595 | # define PACKET3_CP_DMA_DIS_WC (1 << 21) | ||
596 | -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) | ||
597 | +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) | ||
598 | /* 0 - none | ||
599 | * 1 - 8 in 16 | ||
600 | * 2 - 8 in 32 | ||
601 | diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h | ||
602 | index 7c78083..d079cb1 100644 | ||
603 | --- a/drivers/gpu/drm/radeon/r600d.h | ||
604 | +++ b/drivers/gpu/drm/radeon/r600d.h | ||
605 | @@ -1487,7 +1487,7 @@ | ||
606 | */ | ||
607 | # define PACKET3_CP_DMA_CP_SYNC (1 << 31) | ||
608 | /* COMMAND */ | ||
609 | -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) | ||
610 | +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) | ||
611 | /* 0 - none | ||
612 | * 1 - 8 in 16 | ||
613 | * 2 - 8 in 32 | ||
614 | diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c | ||
615 | index f4d6bce..12e8099 100644 | ||
616 | --- a/drivers/gpu/drm/radeon/radeon_test.c | ||
617 | +++ b/drivers/gpu/drm/radeon/radeon_test.c | ||
618 | @@ -36,8 +36,8 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) | ||
619 | struct radeon_bo *vram_obj = NULL; | ||
620 | struct radeon_bo **gtt_obj = NULL; | ||
621 | uint64_t gtt_addr, vram_addr; | ||
622 | - unsigned i, n, size; | ||
623 | - int r, ring; | ||
624 | + unsigned n, size; | ||
625 | + int i, r, ring; | ||
626 | |||
627 | switch (flag) { | ||
628 | case RADEON_TEST_COPY_DMA: | ||
629 | diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c | ||
630 | index 1cfba39..1c23b61 100644 | ||
631 | --- a/drivers/gpu/drm/radeon/si_dpm.c | ||
632 | +++ b/drivers/gpu/drm/radeon/si_dpm.c | ||
633 | @@ -5174,7 +5174,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, | ||
634 | table->mc_reg_table_entry[k].mc_data[j] |= 0x100; | ||
635 | } | ||
636 | j++; | ||
637 | - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
638 | + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
639 | return -EINVAL; | ||
640 | |||
641 | if (!pi->mem_gddr5) { | ||
642 | @@ -5184,7 +5184,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, | ||
643 | table->mc_reg_table_entry[k].mc_data[j] = | ||
644 | (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; | ||
645 | j++; | ||
646 | - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
647 | + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
648 | return -EINVAL; | ||
649 | } | ||
650 | break; | ||
651 | @@ -5197,7 +5197,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, | ||
652 | (temp_reg & 0xffff0000) | | ||
653 | (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); | ||
654 | j++; | ||
655 | - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
656 | + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) | ||
657 | return -EINVAL; | ||
658 | break; | ||
659 | default: | ||
660 | diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h | ||
661 | index 2010d6b..a75d25a 100644 | ||
662 | --- a/drivers/gpu/drm/radeon/sid.h | ||
663 | +++ b/drivers/gpu/drm/radeon/sid.h | ||
664 | @@ -1490,7 +1490,7 @@ | ||
665 | * 6. COMMAND [30:21] | BYTE_COUNT [20:0] | ||
666 | */ | ||
667 | # define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) | ||
668 | - /* 0 - SRC_ADDR | ||
669 | + /* 0 - DST_ADDR | ||
670 | * 1 - GDS | ||
671 | */ | ||
672 | # define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) | ||
673 | @@ -1505,7 +1505,7 @@ | ||
674 | # define PACKET3_CP_DMA_CP_SYNC (1 << 31) | ||
675 | /* COMMAND */ | ||
676 | # define PACKET3_CP_DMA_DIS_WC (1 << 21) | ||
677 | -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) | ||
678 | +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) | ||
679 | /* 0 - none | ||
680 | * 1 - 8 in 16 | ||
681 | * 2 - 8 in 32 | ||
682 | diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c | ||
683 | index 98814d1..3288f13 100644 | ||
684 | --- a/drivers/hwmon/applesmc.c | ||
685 | +++ b/drivers/hwmon/applesmc.c | ||
686 | @@ -230,6 +230,7 @@ static int send_argument(const char *key) | ||
687 | |||
688 | static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | ||
689 | { | ||
690 | + u8 status, data = 0; | ||
691 | int i; | ||
692 | |||
693 | if (send_command(cmd) || send_argument(key)) { | ||
694 | @@ -237,6 +238,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | ||
695 | return -EIO; | ||
696 | } | ||
697 | |||
698 | + /* This has no effect on newer (2012) SMCs */ | ||
699 | if (send_byte(len, APPLESMC_DATA_PORT)) { | ||
700 | pr_warn("%.4s: read len fail\n", key); | ||
701 | return -EIO; | ||
702 | @@ -250,6 +252,17 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | ||
703 | buffer[i] = inb(APPLESMC_DATA_PORT); | ||
704 | } | ||
705 | |||
706 | + /* Read the data port until bit0 is cleared */ | ||
707 | + for (i = 0; i < 16; i++) { | ||
708 | + udelay(APPLESMC_MIN_WAIT); | ||
709 | + status = inb(APPLESMC_CMD_PORT); | ||
710 | + if (!(status & 0x01)) | ||
711 | + break; | ||
712 | + data = inb(APPLESMC_DATA_PORT); | ||
713 | + } | ||
714 | + if (i) | ||
715 | + pr_warn("flushed %d bytes, last value is: %d\n", i, data); | ||
716 | + | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c | ||
721 | index 142b694d..e6b8dcd 100644 | ||
722 | --- a/drivers/i2c/busses/i2c-omap.c | ||
723 | +++ b/drivers/i2c/busses/i2c-omap.c | ||
724 | @@ -944,6 +944,9 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) | ||
725 | /* | ||
726 | * ProDB0017052: Clear ARDY bit twice | ||
727 | */ | ||
728 | + if (stat & OMAP_I2C_STAT_ARDY) | ||
729 | + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ARDY); | ||
730 | + | ||
731 | if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | | ||
732 | OMAP_I2C_STAT_AL)) { | ||
733 | omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY | | ||
734 | diff --git a/drivers/watchdog/kempld_wdt.c b/drivers/watchdog/kempld_wdt.c | ||
735 | index 491419e..5c3d4df 100644 | ||
736 | --- a/drivers/watchdog/kempld_wdt.c | ||
737 | +++ b/drivers/watchdog/kempld_wdt.c | ||
738 | @@ -35,7 +35,7 @@ | ||
739 | #define KEMPLD_WDT_STAGE_TIMEOUT(x) (0x1b + (x) * 4) | ||
740 | #define KEMPLD_WDT_STAGE_CFG(x) (0x18 + (x)) | ||
741 | #define STAGE_CFG_GET_PRESCALER(x) (((x) & 0x30) >> 4) | ||
742 | -#define STAGE_CFG_SET_PRESCALER(x) (((x) & 0x30) << 4) | ||
743 | +#define STAGE_CFG_SET_PRESCALER(x) (((x) & 0x3) << 4) | ||
744 | #define STAGE_CFG_PRESCALER_MASK 0x30 | ||
745 | #define STAGE_CFG_ACTION_MASK 0x7 | ||
746 | #define STAGE_CFG_ASSERT (1 << 3) | ||
747 | diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c | ||
748 | index 4da59b4..381999c 100644 | ||
749 | --- a/drivers/watchdog/ts72xx_wdt.c | ||
750 | +++ b/drivers/watchdog/ts72xx_wdt.c | ||
751 | @@ -310,7 +310,8 @@ static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, | ||
752 | |||
753 | case WDIOC_GETSTATUS: | ||
754 | case WDIOC_GETBOOTSTATUS: | ||
755 | - return put_user(0, p); | ||
756 | + error = put_user(0, p); | ||
757 | + break; | ||
758 | |||
759 | case WDIOC_KEEPALIVE: | ||
760 | ts72xx_wdt_kick(wdt); | ||
761 | diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c | ||
762 | index d3280b2..8220491 100644 | ||
763 | --- a/fs/btrfs/inode.c | ||
764 | +++ b/fs/btrfs/inode.c | ||
765 | @@ -8036,7 +8036,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
766 | |||
767 | |||
768 | /* check for collisions, even if the name isn't there */ | ||
769 | - ret = btrfs_check_dir_item_collision(root, new_dir->i_ino, | ||
770 | + ret = btrfs_check_dir_item_collision(dest, new_dir->i_ino, | ||
771 | new_dentry->d_name.name, | ||
772 | new_dentry->d_name.len); | ||
773 | |||
774 | diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c | ||
775 | index c081e34..03e9beb 100644 | ||
776 | --- a/fs/ext4/xattr.c | ||
777 | +++ b/fs/ext4/xattr.c | ||
778 | @@ -1350,6 +1350,8 @@ retry: | ||
779 | s_min_extra_isize) { | ||
780 | tried_min_extra_isize++; | ||
781 | new_extra_isize = s_min_extra_isize; | ||
782 | + kfree(is); is = NULL; | ||
783 | + kfree(bs); bs = NULL; | ||
784 | goto retry; | ||
785 | } | ||
786 | error = -1; | ||
787 | diff --git a/fs/statfs.c b/fs/statfs.c | ||
788 | index c219e733..083dc0a 100644 | ||
789 | --- a/fs/statfs.c | ||
790 | +++ b/fs/statfs.c | ||
791 | @@ -94,7 +94,7 @@ retry: | ||
792 | |||
793 | int fd_statfs(int fd, struct kstatfs *st) | ||
794 | { | ||
795 | - struct fd f = fdget(fd); | ||
796 | + struct fd f = fdget_raw(fd); | ||
797 | int error = -EBADF; | ||
798 | if (f.file) { | ||
799 | error = vfs_statfs(&f.file->f_path, st); | ||
800 | diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h | ||
801 | index 842de22..ded4299 100644 | ||
802 | --- a/include/linux/compiler-gcc4.h | ||
803 | +++ b/include/linux/compiler-gcc4.h | ||
804 | @@ -65,6 +65,21 @@ | ||
805 | #define __visible __attribute__((externally_visible)) | ||
806 | #endif | ||
807 | |||
808 | +/* | ||
809 | + * GCC 'asm goto' miscompiles certain code sequences: | ||
810 | + * | ||
811 | + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 | ||
812 | + * | ||
813 | + * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. | ||
814 | + * Fixed in GCC 4.8.2 and later versions. | ||
815 | + * | ||
816 | + * (asm goto is automatically volatile - the naming reflects this.) | ||
817 | + */ | ||
818 | +#if GCC_VERSION <= 40801 | ||
819 | +# define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) | ||
820 | +#else | ||
821 | +# define asm_volatile_goto(x...) do { asm goto(x); } while (0) | ||
822 | +#endif | ||
823 | |||
824 | #ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP | ||
825 | #if GCC_VERSION >= 40400 | ||
826 | diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h | ||
827 | index c4d870b..19c19a5 100644 | ||
828 | --- a/include/linux/ipc_namespace.h | ||
829 | +++ b/include/linux/ipc_namespace.h | ||
830 | @@ -22,7 +22,7 @@ struct ipc_ids { | ||
831 | int in_use; | ||
832 | unsigned short seq; | ||
833 | unsigned short seq_max; | ||
834 | - struct rw_semaphore rw_mutex; | ||
835 | + struct rw_semaphore rwsem; | ||
836 | struct idr ipcs_idr; | ||
837 | int next_id; | ||
838 | }; | ||
839 | diff --git a/include/linux/random.h b/include/linux/random.h | ||
840 | index 3b9377d..6312dd9 100644 | ||
841 | --- a/include/linux/random.h | ||
842 | +++ b/include/linux/random.h | ||
843 | @@ -17,6 +17,7 @@ extern void add_interrupt_randomness(int irq, int irq_flags); | ||
844 | extern void get_random_bytes(void *buf, int nbytes); | ||
845 | extern void get_random_bytes_arch(void *buf, int nbytes); | ||
846 | void generate_random_uuid(unsigned char uuid_out[16]); | ||
847 | +extern int random_int_secret_init(void); | ||
848 | |||
849 | #ifndef MODULE | ||
850 | extern const struct file_operations random_fops, urandom_fops; | ||
851 | diff --git a/init/main.c b/init/main.c | ||
852 | index d03d2ec..586cd33 100644 | ||
853 | --- a/init/main.c | ||
854 | +++ b/init/main.c | ||
855 | @@ -75,6 +75,7 @@ | ||
856 | #include <linux/blkdev.h> | ||
857 | #include <linux/elevator.h> | ||
858 | #include <linux/sched_clock.h> | ||
859 | +#include <linux/random.h> | ||
860 | |||
861 | #include <asm/io.h> | ||
862 | #include <asm/bugs.h> | ||
863 | @@ -778,6 +779,7 @@ static void __init do_basic_setup(void) | ||
864 | do_ctors(); | ||
865 | usermodehelper_enable(); | ||
866 | do_initcalls(); | ||
867 | + random_int_secret_init(); | ||
868 | } | ||
869 | |||
870 | static void __init do_pre_smp_initcalls(void) | ||
871 | diff --git a/ipc/msg.c b/ipc/msg.c | ||
872 | index a877c16..558aa91 100644 | ||
873 | --- a/ipc/msg.c | ||
874 | +++ b/ipc/msg.c | ||
875 | @@ -70,8 +70,6 @@ struct msg_sender { | ||
876 | |||
877 | #define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS]) | ||
878 | |||
879 | -#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) | ||
880 | - | ||
881 | static void freeque(struct ipc_namespace *, struct kern_ipc_perm *); | ||
882 | static int newque(struct ipc_namespace *, struct ipc_params *); | ||
883 | #ifdef CONFIG_PROC_FS | ||
884 | @@ -181,7 +179,7 @@ static void msg_rcu_free(struct rcu_head *head) | ||
885 | * @ns: namespace | ||
886 | * @params: ptr to the structure that contains the key and msgflg | ||
887 | * | ||
888 | - * Called with msg_ids.rw_mutex held (writer) | ||
889 | + * Called with msg_ids.rwsem held (writer) | ||
890 | */ | ||
891 | static int newque(struct ipc_namespace *ns, struct ipc_params *params) | ||
892 | { | ||
893 | @@ -267,8 +265,8 @@ static void expunge_all(struct msg_queue *msq, int res) | ||
894 | * removes the message queue from message queue ID IDR, and cleans up all the | ||
895 | * messages associated with this queue. | ||
896 | * | ||
897 | - * msg_ids.rw_mutex (writer) and the spinlock for this message queue are held | ||
898 | - * before freeque() is called. msg_ids.rw_mutex remains locked on exit. | ||
899 | + * msg_ids.rwsem (writer) and the spinlock for this message queue are held | ||
900 | + * before freeque() is called. msg_ids.rwsem remains locked on exit. | ||
901 | */ | ||
902 | static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | ||
903 | { | ||
904 | @@ -278,7 +276,8 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | ||
905 | expunge_all(msq, -EIDRM); | ||
906 | ss_wakeup(&msq->q_senders, 1); | ||
907 | msg_rmid(ns, msq); | ||
908 | - msg_unlock(msq); | ||
909 | + ipc_unlock_object(&msq->q_perm); | ||
910 | + rcu_read_unlock(); | ||
911 | |||
912 | list_for_each_entry_safe(msg, t, &msq->q_messages, m_list) { | ||
913 | atomic_dec(&ns->msg_hdrs); | ||
914 | @@ -289,7 +288,7 @@ static void freeque(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | - * Called with msg_ids.rw_mutex and ipcp locked. | ||
919 | + * Called with msg_ids.rwsem and ipcp locked. | ||
920 | */ | ||
921 | static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) | ||
922 | { | ||
923 | @@ -393,9 +392,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version) | ||
924 | } | ||
925 | |||
926 | /* | ||
927 | - * This function handles some msgctl commands which require the rw_mutex | ||
928 | + * This function handles some msgctl commands which require the rwsem | ||
929 | * to be held in write mode. | ||
930 | - * NOTE: no locks must be held, the rw_mutex is taken inside this function. | ||
931 | + * NOTE: no locks must be held, the rwsem is taken inside this function. | ||
932 | */ | ||
933 | static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | ||
934 | struct msqid_ds __user *buf, int version) | ||
935 | @@ -410,7 +409,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, | ||
936 | return -EFAULT; | ||
937 | } | ||
938 | |||
939 | - down_write(&msg_ids(ns).rw_mutex); | ||
940 | + down_write(&msg_ids(ns).rwsem); | ||
941 | rcu_read_lock(); | ||
942 | |||
943 | ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, | ||
944 | @@ -466,7 +465,7 @@ out_unlock0: | ||
945 | out_unlock1: | ||
946 | rcu_read_unlock(); | ||
947 | out_up: | ||
948 | - up_write(&msg_ids(ns).rw_mutex); | ||
949 | + up_write(&msg_ids(ns).rwsem); | ||
950 | return err; | ||
951 | } | ||
952 | |||
953 | @@ -501,7 +500,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid, | ||
954 | msginfo.msgmnb = ns->msg_ctlmnb; | ||
955 | msginfo.msgssz = MSGSSZ; | ||
956 | msginfo.msgseg = MSGSEG; | ||
957 | - down_read(&msg_ids(ns).rw_mutex); | ||
958 | + down_read(&msg_ids(ns).rwsem); | ||
959 | if (cmd == MSG_INFO) { | ||
960 | msginfo.msgpool = msg_ids(ns).in_use; | ||
961 | msginfo.msgmap = atomic_read(&ns->msg_hdrs); | ||
962 | @@ -512,7 +511,7 @@ static int msgctl_nolock(struct ipc_namespace *ns, int msqid, | ||
963 | msginfo.msgtql = MSGTQL; | ||
964 | } | ||
965 | max_id = ipc_get_maxid(&msg_ids(ns)); | ||
966 | - up_read(&msg_ids(ns).rw_mutex); | ||
967 | + up_read(&msg_ids(ns).rwsem); | ||
968 | if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) | ||
969 | return -EFAULT; | ||
970 | return (max_id < 0) ? 0 : max_id; | ||
971 | diff --git a/ipc/namespace.c b/ipc/namespace.c | ||
972 | index 7ee61bf..aba9a58 100644 | ||
973 | --- a/ipc/namespace.c | ||
974 | +++ b/ipc/namespace.c | ||
975 | @@ -81,7 +81,7 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
976 | int next_id; | ||
977 | int total, in_use; | ||
978 | |||
979 | - down_write(&ids->rw_mutex); | ||
980 | + down_write(&ids->rwsem); | ||
981 | |||
982 | in_use = ids->in_use; | ||
983 | |||
984 | @@ -89,11 +89,12 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
985 | perm = idr_find(&ids->ipcs_idr, next_id); | ||
986 | if (perm == NULL) | ||
987 | continue; | ||
988 | - ipc_lock_by_ptr(perm); | ||
989 | + rcu_read_lock(); | ||
990 | + ipc_lock_object(perm); | ||
991 | free(ns, perm); | ||
992 | total++; | ||
993 | } | ||
994 | - up_write(&ids->rw_mutex); | ||
995 | + up_write(&ids->rwsem); | ||
996 | } | ||
997 | |||
998 | static void free_ipc_ns(struct ipc_namespace *ns) | ||
999 | diff --git a/ipc/sem.c b/ipc/sem.c | ||
1000 | index 87614511..8e2bf30 100644 | ||
1001 | --- a/ipc/sem.c | ||
1002 | +++ b/ipc/sem.c | ||
1003 | @@ -248,12 +248,20 @@ static void merge_queues(struct sem_array *sma) | ||
1004 | * Caller must own sem_perm.lock. | ||
1005 | * New simple ops cannot start, because simple ops first check | ||
1006 | * that sem_perm.lock is free. | ||
1007 | + * that a) sem_perm.lock is free and b) complex_count is 0. | ||
1008 | */ | ||
1009 | static void sem_wait_array(struct sem_array *sma) | ||
1010 | { | ||
1011 | int i; | ||
1012 | struct sem *sem; | ||
1013 | |||
1014 | + if (sma->complex_count) { | ||
1015 | + /* The thread that increased sma->complex_count waited on | ||
1016 | + * all sem->lock locks. Thus we don't need to wait again. | ||
1017 | + */ | ||
1018 | + return; | ||
1019 | + } | ||
1020 | + | ||
1021 | for (i = 0; i < sma->sem_nsems; i++) { | ||
1022 | sem = sma->sem_base + i; | ||
1023 | spin_unlock_wait(&sem->lock); | ||
1024 | @@ -365,7 +373,7 @@ static inline void sem_unlock(struct sem_array *sma, int locknum) | ||
1025 | } | ||
1026 | |||
1027 | /* | ||
1028 | - * sem_lock_(check_) routines are called in the paths where the rw_mutex | ||
1029 | + * sem_lock_(check_) routines are called in the paths where the rwsem | ||
1030 | * is not held. | ||
1031 | * | ||
1032 | * The caller holds the RCU read lock. | ||
1033 | @@ -464,7 +472,7 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | ||
1034 | * @ns: namespace | ||
1035 | * @params: ptr to the structure that contains key, semflg and nsems | ||
1036 | * | ||
1037 | - * Called with sem_ids.rw_mutex held (as a writer) | ||
1038 | + * Called with sem_ids.rwsem held (as a writer) | ||
1039 | */ | ||
1040 | |||
1041 | static int newary(struct ipc_namespace *ns, struct ipc_params *params) | ||
1042 | @@ -529,7 +537,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params) | ||
1043 | |||
1044 | |||
1045 | /* | ||
1046 | - * Called with sem_ids.rw_mutex and ipcp locked. | ||
1047 | + * Called with sem_ids.rwsem and ipcp locked. | ||
1048 | */ | ||
1049 | static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg) | ||
1050 | { | ||
1051 | @@ -540,7 +548,7 @@ static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg) | ||
1052 | } | ||
1053 | |||
1054 | /* | ||
1055 | - * Called with sem_ids.rw_mutex and ipcp locked. | ||
1056 | + * Called with sem_ids.rwsem and ipcp locked. | ||
1057 | */ | ||
1058 | static inline int sem_more_checks(struct kern_ipc_perm *ipcp, | ||
1059 | struct ipc_params *params) | ||
1060 | @@ -910,6 +918,24 @@ again: | ||
1061 | } | ||
1062 | |||
1063 | /** | ||
1064 | + * set_semotime(sma, sops) - set sem_otime | ||
1065 | + * @sma: semaphore array | ||
1066 | + * @sops: operations that modified the array, may be NULL | ||
1067 | + * | ||
1068 | + * sem_otime is replicated to avoid cache line trashing. | ||
1069 | + * This function sets one instance to the current time. | ||
1070 | + */ | ||
1071 | +static void set_semotime(struct sem_array *sma, struct sembuf *sops) | ||
1072 | +{ | ||
1073 | + if (sops == NULL) { | ||
1074 | + sma->sem_base[0].sem_otime = get_seconds(); | ||
1075 | + } else { | ||
1076 | + sma->sem_base[sops[0].sem_num].sem_otime = | ||
1077 | + get_seconds(); | ||
1078 | + } | ||
1079 | +} | ||
1080 | + | ||
1081 | +/** | ||
1082 | * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue | ||
1083 | * @sma: semaphore array | ||
1084 | * @sops: operations that were performed | ||
1085 | @@ -959,17 +985,10 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | - if (otime) { | ||
1090 | - if (sops == NULL) { | ||
1091 | - sma->sem_base[0].sem_otime = get_seconds(); | ||
1092 | - } else { | ||
1093 | - sma->sem_base[sops[0].sem_num].sem_otime = | ||
1094 | - get_seconds(); | ||
1095 | - } | ||
1096 | - } | ||
1097 | + if (otime) | ||
1098 | + set_semotime(sma, sops); | ||
1099 | } | ||
1100 | |||
1101 | - | ||
1102 | /* The following counts are associated to each semaphore: | ||
1103 | * semncnt number of tasks waiting on semval being nonzero | ||
1104 | * semzcnt number of tasks waiting on semval being zero | ||
1105 | @@ -1031,8 +1050,8 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum) | ||
1106 | return semzcnt; | ||
1107 | } | ||
1108 | |||
1109 | -/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked | ||
1110 | - * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex | ||
1111 | +/* Free a semaphore set. freeary() is called with sem_ids.rwsem locked | ||
1112 | + * as a writer and the spinlock for this semaphore set hold. sem_ids.rwsem | ||
1113 | * remains locked on exit. | ||
1114 | */ | ||
1115 | static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | ||
1116 | @@ -1152,7 +1171,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, | ||
1117 | seminfo.semmnu = SEMMNU; | ||
1118 | seminfo.semmap = SEMMAP; | ||
1119 | seminfo.semume = SEMUME; | ||
1120 | - down_read(&sem_ids(ns).rw_mutex); | ||
1121 | + down_read(&sem_ids(ns).rwsem); | ||
1122 | if (cmd == SEM_INFO) { | ||
1123 | seminfo.semusz = sem_ids(ns).in_use; | ||
1124 | seminfo.semaem = ns->used_sems; | ||
1125 | @@ -1161,7 +1180,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, | ||
1126 | seminfo.semaem = SEMAEM; | ||
1127 | } | ||
1128 | max_id = ipc_get_maxid(&sem_ids(ns)); | ||
1129 | - up_read(&sem_ids(ns).rw_mutex); | ||
1130 | + up_read(&sem_ids(ns).rwsem); | ||
1131 | if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) | ||
1132 | return -EFAULT; | ||
1133 | return (max_id < 0) ? 0: max_id; | ||
1134 | @@ -1467,9 +1486,9 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version) | ||
1135 | } | ||
1136 | |||
1137 | /* | ||
1138 | - * This function handles some semctl commands which require the rw_mutex | ||
1139 | + * This function handles some semctl commands which require the rwsem | ||
1140 | * to be held in write mode. | ||
1141 | - * NOTE: no locks must be held, the rw_mutex is taken inside this function. | ||
1142 | + * NOTE: no locks must be held, the rwsem is taken inside this function. | ||
1143 | */ | ||
1144 | static int semctl_down(struct ipc_namespace *ns, int semid, | ||
1145 | int cmd, int version, void __user *p) | ||
1146 | @@ -1484,7 +1503,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid, | ||
1147 | return -EFAULT; | ||
1148 | } | ||
1149 | |||
1150 | - down_write(&sem_ids(ns).rw_mutex); | ||
1151 | + down_write(&sem_ids(ns).rwsem); | ||
1152 | rcu_read_lock(); | ||
1153 | |||
1154 | ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd, | ||
1155 | @@ -1523,7 +1542,7 @@ out_unlock0: | ||
1156 | out_unlock1: | ||
1157 | rcu_read_unlock(); | ||
1158 | out_up: | ||
1159 | - up_write(&sem_ids(ns).rw_mutex); | ||
1160 | + up_write(&sem_ids(ns).rwsem); | ||
1161 | return err; | ||
1162 | } | ||
1163 | |||
1164 | @@ -1831,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | ||
1165 | |||
1166 | error = perform_atomic_semop(sma, sops, nsops, un, | ||
1167 | task_tgid_vnr(current)); | ||
1168 | - if (error <= 0) { | ||
1169 | - if (alter && error == 0) | ||
1170 | + if (error == 0) { | ||
1171 | + /* If the operation was successful, then do | ||
1172 | + * the required updates. | ||
1173 | + */ | ||
1174 | + if (alter) | ||
1175 | do_smart_update(sma, sops, nsops, 1, &tasks); | ||
1176 | - | ||
1177 | - goto out_unlock_free; | ||
1178 | + else | ||
1179 | + set_semotime(sma, sops); | ||
1180 | } | ||
1181 | + if (error <= 0) | ||
1182 | + goto out_unlock_free; | ||
1183 | |||
1184 | /* We need to sleep on this operation, so we put the current | ||
1185 | * task into the pending queue and go to sleep. | ||
1186 | @@ -2095,6 +2119,14 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it) | ||
1187 | struct sem_array *sma = it; | ||
1188 | time_t sem_otime; | ||
1189 | |||
1190 | + /* | ||
1191 | + * The proc interface isn't aware of sem_lock(), it calls | ||
1192 | + * ipc_lock_object() directly (in sysvipc_find_ipc). | ||
1193 | + * In order to stay compatible with sem_lock(), we must wait until | ||
1194 | + * all simple semop() calls have left their critical regions. | ||
1195 | + */ | ||
1196 | + sem_wait_array(sma); | ||
1197 | + | ||
1198 | sem_otime = get_semotime(sma); | ||
1199 | |||
1200 | return seq_printf(s, | ||
1201 | diff --git a/ipc/shm.c b/ipc/shm.c | ||
1202 | index 2d6833d..d697396 100644 | ||
1203 | --- a/ipc/shm.c | ||
1204 | +++ b/ipc/shm.c | ||
1205 | @@ -19,6 +19,9 @@ | ||
1206 | * namespaces support | ||
1207 | * OpenVZ, SWsoft Inc. | ||
1208 | * Pavel Emelianov <xemul@openvz.org> | ||
1209 | + * | ||
1210 | + * Better ipc lock (kern_ipc_perm.lock) handling | ||
1211 | + * Davidlohr Bueso <davidlohr.bueso@hp.com>, June 2013. | ||
1212 | */ | ||
1213 | |||
1214 | #include <linux/slab.h> | ||
1215 | @@ -80,8 +83,8 @@ void shm_init_ns(struct ipc_namespace *ns) | ||
1216 | } | ||
1217 | |||
1218 | /* | ||
1219 | - * Called with shm_ids.rw_mutex (writer) and the shp structure locked. | ||
1220 | - * Only shm_ids.rw_mutex remains locked on exit. | ||
1221 | + * Called with shm_ids.rwsem (writer) and the shp structure locked. | ||
1222 | + * Only shm_ids.rwsem remains locked on exit. | ||
1223 | */ | ||
1224 | static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) | ||
1225 | { | ||
1226 | @@ -124,8 +127,28 @@ void __init shm_init (void) | ||
1227 | IPC_SHM_IDS, sysvipc_shm_proc_show); | ||
1228 | } | ||
1229 | |||
1230 | +static inline struct shmid_kernel *shm_obtain_object(struct ipc_namespace *ns, int id) | ||
1231 | +{ | ||
1232 | + struct kern_ipc_perm *ipcp = ipc_obtain_object(&shm_ids(ns), id); | ||
1233 | + | ||
1234 | + if (IS_ERR(ipcp)) | ||
1235 | + return ERR_CAST(ipcp); | ||
1236 | + | ||
1237 | + return container_of(ipcp, struct shmid_kernel, shm_perm); | ||
1238 | +} | ||
1239 | + | ||
1240 | +static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace *ns, int id) | ||
1241 | +{ | ||
1242 | + struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&shm_ids(ns), id); | ||
1243 | + | ||
1244 | + if (IS_ERR(ipcp)) | ||
1245 | + return ERR_CAST(ipcp); | ||
1246 | + | ||
1247 | + return container_of(ipcp, struct shmid_kernel, shm_perm); | ||
1248 | +} | ||
1249 | + | ||
1250 | /* | ||
1251 | - * shm_lock_(check_) routines are called in the paths where the rw_mutex | ||
1252 | + * shm_lock_(check_) routines are called in the paths where the rwsem | ||
1253 | * is not necessarily held. | ||
1254 | */ | ||
1255 | static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id) | ||
1256 | @@ -144,17 +167,6 @@ static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp) | ||
1257 | ipc_lock_object(&ipcp->shm_perm); | ||
1258 | } | ||
1259 | |||
1260 | -static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns, | ||
1261 | - int id) | ||
1262 | -{ | ||
1263 | - struct kern_ipc_perm *ipcp = ipc_lock_check(&shm_ids(ns), id); | ||
1264 | - | ||
1265 | - if (IS_ERR(ipcp)) | ||
1266 | - return (struct shmid_kernel *)ipcp; | ||
1267 | - | ||
1268 | - return container_of(ipcp, struct shmid_kernel, shm_perm); | ||
1269 | -} | ||
1270 | - | ||
1271 | static void shm_rcu_free(struct rcu_head *head) | ||
1272 | { | ||
1273 | struct ipc_rcu *p = container_of(head, struct ipc_rcu, rcu); | ||
1274 | @@ -191,7 +203,7 @@ static void shm_open(struct vm_area_struct *vma) | ||
1275 | * @ns: namespace | ||
1276 | * @shp: struct to free | ||
1277 | * | ||
1278 | - * It has to be called with shp and shm_ids.rw_mutex (writer) locked, | ||
1279 | + * It has to be called with shp and shm_ids.rwsem (writer) locked, | ||
1280 | * but returns with shp unlocked and freed. | ||
1281 | */ | ||
1282 | static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) | ||
1283 | @@ -238,7 +250,7 @@ static void shm_close(struct vm_area_struct *vma) | ||
1284 | struct shmid_kernel *shp; | ||
1285 | struct ipc_namespace *ns = sfd->ns; | ||
1286 | |||
1287 | - down_write(&shm_ids(ns).rw_mutex); | ||
1288 | + down_write(&shm_ids(ns).rwsem); | ||
1289 | /* remove from the list of attaches of the shm segment */ | ||
1290 | shp = shm_lock(ns, sfd->id); | ||
1291 | BUG_ON(IS_ERR(shp)); | ||
1292 | @@ -249,10 +261,10 @@ static void shm_close(struct vm_area_struct *vma) | ||
1293 | shm_destroy(ns, shp); | ||
1294 | else | ||
1295 | shm_unlock(shp); | ||
1296 | - up_write(&shm_ids(ns).rw_mutex); | ||
1297 | + up_write(&shm_ids(ns).rwsem); | ||
1298 | } | ||
1299 | |||
1300 | -/* Called with ns->shm_ids(ns).rw_mutex locked */ | ||
1301 | +/* Called with ns->shm_ids(ns).rwsem locked */ | ||
1302 | static int shm_try_destroy_current(int id, void *p, void *data) | ||
1303 | { | ||
1304 | struct ipc_namespace *ns = data; | ||
1305 | @@ -283,7 +295,7 @@ static int shm_try_destroy_current(int id, void *p, void *data) | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | -/* Called with ns->shm_ids(ns).rw_mutex locked */ | ||
1310 | +/* Called with ns->shm_ids(ns).rwsem locked */ | ||
1311 | static int shm_try_destroy_orphaned(int id, void *p, void *data) | ||
1312 | { | ||
1313 | struct ipc_namespace *ns = data; | ||
1314 | @@ -294,7 +306,7 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data) | ||
1315 | * We want to destroy segments without users and with already | ||
1316 | * exit'ed originating process. | ||
1317 | * | ||
1318 | - * As shp->* are changed under rw_mutex, it's safe to skip shp locking. | ||
1319 | + * As shp->* are changed under rwsem, it's safe to skip shp locking. | ||
1320 | */ | ||
1321 | if (shp->shm_creator != NULL) | ||
1322 | return 0; | ||
1323 | @@ -308,10 +320,10 @@ static int shm_try_destroy_orphaned(int id, void *p, void *data) | ||
1324 | |||
1325 | void shm_destroy_orphaned(struct ipc_namespace *ns) | ||
1326 | { | ||
1327 | - down_write(&shm_ids(ns).rw_mutex); | ||
1328 | + down_write(&shm_ids(ns).rwsem); | ||
1329 | if (shm_ids(ns).in_use) | ||
1330 | idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_orphaned, ns); | ||
1331 | - up_write(&shm_ids(ns).rw_mutex); | ||
1332 | + up_write(&shm_ids(ns).rwsem); | ||
1333 | } | ||
1334 | |||
1335 | |||
1336 | @@ -323,10 +335,10 @@ void exit_shm(struct task_struct *task) | ||
1337 | return; | ||
1338 | |||
1339 | /* Destroy all already created segments, but not mapped yet */ | ||
1340 | - down_write(&shm_ids(ns).rw_mutex); | ||
1341 | + down_write(&shm_ids(ns).rwsem); | ||
1342 | if (shm_ids(ns).in_use) | ||
1343 | idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns); | ||
1344 | - up_write(&shm_ids(ns).rw_mutex); | ||
1345 | + up_write(&shm_ids(ns).rwsem); | ||
1346 | } | ||
1347 | |||
1348 | static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
1349 | @@ -460,7 +472,7 @@ static const struct vm_operations_struct shm_vm_ops = { | ||
1350 | * @ns: namespace | ||
1351 | * @params: ptr to the structure that contains key, size and shmflg | ||
1352 | * | ||
1353 | - * Called with shm_ids.rw_mutex held as a writer. | ||
1354 | + * Called with shm_ids.rwsem held as a writer. | ||
1355 | */ | ||
1356 | |||
1357 | static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | ||
1358 | @@ -567,7 +579,7 @@ no_file: | ||
1359 | } | ||
1360 | |||
1361 | /* | ||
1362 | - * Called with shm_ids.rw_mutex and ipcp locked. | ||
1363 | + * Called with shm_ids.rwsem and ipcp locked. | ||
1364 | */ | ||
1365 | static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg) | ||
1366 | { | ||
1367 | @@ -578,7 +590,7 @@ static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg) | ||
1368 | } | ||
1369 | |||
1370 | /* | ||
1371 | - * Called with shm_ids.rw_mutex and ipcp locked. | ||
1372 | + * Called with shm_ids.rwsem and ipcp locked. | ||
1373 | */ | ||
1374 | static inline int shm_more_checks(struct kern_ipc_perm *ipcp, | ||
1375 | struct ipc_params *params) | ||
1376 | @@ -691,7 +703,7 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf | ||
1377 | |||
1378 | /* | ||
1379 | * Calculate and add used RSS and swap pages of a shm. | ||
1380 | - * Called with shm_ids.rw_mutex held as a reader | ||
1381 | + * Called with shm_ids.rwsem held as a reader | ||
1382 | */ | ||
1383 | static void shm_add_rss_swap(struct shmid_kernel *shp, | ||
1384 | unsigned long *rss_add, unsigned long *swp_add) | ||
1385 | @@ -718,7 +730,7 @@ static void shm_add_rss_swap(struct shmid_kernel *shp, | ||
1386 | } | ||
1387 | |||
1388 | /* | ||
1389 | - * Called with shm_ids.rw_mutex held as a reader | ||
1390 | + * Called with shm_ids.rwsem held as a reader | ||
1391 | */ | ||
1392 | static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, | ||
1393 | unsigned long *swp) | ||
1394 | @@ -747,9 +759,9 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, | ||
1395 | } | ||
1396 | |||
1397 | /* | ||
1398 | - * This function handles some shmctl commands which require the rw_mutex | ||
1399 | + * This function handles some shmctl commands which require the rwsem | ||
1400 | * to be held in write mode. | ||
1401 | - * NOTE: no locks must be held, the rw_mutex is taken inside this function. | ||
1402 | + * NOTE: no locks must be held, the rwsem is taken inside this function. | ||
1403 | */ | ||
1404 | static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | ||
1405 | struct shmid_ds __user *buf, int version) | ||
1406 | @@ -764,14 +776,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | ||
1407 | return -EFAULT; | ||
1408 | } | ||
1409 | |||
1410 | - down_write(&shm_ids(ns).rw_mutex); | ||
1411 | + down_write(&shm_ids(ns).rwsem); | ||
1412 | rcu_read_lock(); | ||
1413 | |||
1414 | - ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd, | ||
1415 | - &shmid64.shm_perm, 0); | ||
1416 | + ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, | ||
1417 | + &shmid64.shm_perm, 0); | ||
1418 | if (IS_ERR(ipcp)) { | ||
1419 | err = PTR_ERR(ipcp); | ||
1420 | - /* the ipc lock is not held upon failure */ | ||
1421 | goto out_unlock1; | ||
1422 | } | ||
1423 | |||
1424 | @@ -779,14 +790,16 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | ||
1425 | |||
1426 | err = security_shm_shmctl(shp, cmd); | ||
1427 | if (err) | ||
1428 | - goto out_unlock0; | ||
1429 | + goto out_unlock1; | ||
1430 | |||
1431 | switch (cmd) { | ||
1432 | case IPC_RMID: | ||
1433 | + ipc_lock_object(&shp->shm_perm); | ||
1434 | /* do_shm_rmid unlocks the ipc object and rcu */ | ||
1435 | do_shm_rmid(ns, ipcp); | ||
1436 | goto out_up; | ||
1437 | case IPC_SET: | ||
1438 | + ipc_lock_object(&shp->shm_perm); | ||
1439 | err = ipc_update_perm(&shmid64.shm_perm, ipcp); | ||
1440 | if (err) | ||
1441 | goto out_unlock0; | ||
1442 | @@ -794,6 +807,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, | ||
1443 | break; | ||
1444 | default: | ||
1445 | err = -EINVAL; | ||
1446 | + goto out_unlock1; | ||
1447 | } | ||
1448 | |||
1449 | out_unlock0: | ||
1450 | @@ -801,33 +815,28 @@ out_unlock0: | ||
1451 | out_unlock1: | ||
1452 | rcu_read_unlock(); | ||
1453 | out_up: | ||
1454 | - up_write(&shm_ids(ns).rw_mutex); | ||
1455 | + up_write(&shm_ids(ns).rwsem); | ||
1456 | return err; | ||
1457 | } | ||
1458 | |||
1459 | -SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1460 | +static int shmctl_nolock(struct ipc_namespace *ns, int shmid, | ||
1461 | + int cmd, int version, void __user *buf) | ||
1462 | { | ||
1463 | + int err; | ||
1464 | struct shmid_kernel *shp; | ||
1465 | - int err, version; | ||
1466 | - struct ipc_namespace *ns; | ||
1467 | |||
1468 | - if (cmd < 0 || shmid < 0) { | ||
1469 | - err = -EINVAL; | ||
1470 | - goto out; | ||
1471 | + /* preliminary security checks for *_INFO */ | ||
1472 | + if (cmd == IPC_INFO || cmd == SHM_INFO) { | ||
1473 | + err = security_shm_shmctl(NULL, cmd); | ||
1474 | + if (err) | ||
1475 | + return err; | ||
1476 | } | ||
1477 | |||
1478 | - version = ipc_parse_version(&cmd); | ||
1479 | - ns = current->nsproxy->ipc_ns; | ||
1480 | - | ||
1481 | - switch (cmd) { /* replace with proc interface ? */ | ||
1482 | + switch (cmd) { | ||
1483 | case IPC_INFO: | ||
1484 | { | ||
1485 | struct shminfo64 shminfo; | ||
1486 | |||
1487 | - err = security_shm_shmctl(NULL, cmd); | ||
1488 | - if (err) | ||
1489 | - return err; | ||
1490 | - | ||
1491 | memset(&shminfo, 0, sizeof(shminfo)); | ||
1492 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; | ||
1493 | shminfo.shmmax = ns->shm_ctlmax; | ||
1494 | @@ -837,9 +846,9 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1495 | if(copy_shminfo_to_user (buf, &shminfo, version)) | ||
1496 | return -EFAULT; | ||
1497 | |||
1498 | - down_read(&shm_ids(ns).rw_mutex); | ||
1499 | + down_read(&shm_ids(ns).rwsem); | ||
1500 | err = ipc_get_maxid(&shm_ids(ns)); | ||
1501 | - up_read(&shm_ids(ns).rw_mutex); | ||
1502 | + up_read(&shm_ids(ns).rwsem); | ||
1503 | |||
1504 | if(err<0) | ||
1505 | err = 0; | ||
1506 | @@ -849,19 +858,15 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1507 | { | ||
1508 | struct shm_info shm_info; | ||
1509 | |||
1510 | - err = security_shm_shmctl(NULL, cmd); | ||
1511 | - if (err) | ||
1512 | - return err; | ||
1513 | - | ||
1514 | memset(&shm_info, 0, sizeof(shm_info)); | ||
1515 | - down_read(&shm_ids(ns).rw_mutex); | ||
1516 | + down_read(&shm_ids(ns).rwsem); | ||
1517 | shm_info.used_ids = shm_ids(ns).in_use; | ||
1518 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); | ||
1519 | shm_info.shm_tot = ns->shm_tot; | ||
1520 | shm_info.swap_attempts = 0; | ||
1521 | shm_info.swap_successes = 0; | ||
1522 | err = ipc_get_maxid(&shm_ids(ns)); | ||
1523 | - up_read(&shm_ids(ns).rw_mutex); | ||
1524 | + up_read(&shm_ids(ns).rwsem); | ||
1525 | if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { | ||
1526 | err = -EFAULT; | ||
1527 | goto out; | ||
1528 | @@ -876,27 +881,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1529 | struct shmid64_ds tbuf; | ||
1530 | int result; | ||
1531 | |||
1532 | + rcu_read_lock(); | ||
1533 | if (cmd == SHM_STAT) { | ||
1534 | - shp = shm_lock(ns, shmid); | ||
1535 | + shp = shm_obtain_object(ns, shmid); | ||
1536 | if (IS_ERR(shp)) { | ||
1537 | err = PTR_ERR(shp); | ||
1538 | - goto out; | ||
1539 | + goto out_unlock; | ||
1540 | } | ||
1541 | result = shp->shm_perm.id; | ||
1542 | } else { | ||
1543 | - shp = shm_lock_check(ns, shmid); | ||
1544 | + shp = shm_obtain_object_check(ns, shmid); | ||
1545 | if (IS_ERR(shp)) { | ||
1546 | err = PTR_ERR(shp); | ||
1547 | - goto out; | ||
1548 | + goto out_unlock; | ||
1549 | } | ||
1550 | result = 0; | ||
1551 | } | ||
1552 | + | ||
1553 | err = -EACCES; | ||
1554 | if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) | ||
1555 | goto out_unlock; | ||
1556 | + | ||
1557 | err = security_shm_shmctl(shp, cmd); | ||
1558 | if (err) | ||
1559 | goto out_unlock; | ||
1560 | + | ||
1561 | memset(&tbuf, 0, sizeof(tbuf)); | ||
1562 | kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); | ||
1563 | tbuf.shm_segsz = shp->shm_segsz; | ||
1564 | @@ -906,43 +915,76 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1565 | tbuf.shm_cpid = shp->shm_cprid; | ||
1566 | tbuf.shm_lpid = shp->shm_lprid; | ||
1567 | tbuf.shm_nattch = shp->shm_nattch; | ||
1568 | - shm_unlock(shp); | ||
1569 | - if(copy_shmid_to_user (buf, &tbuf, version)) | ||
1570 | + rcu_read_unlock(); | ||
1571 | + | ||
1572 | + if (copy_shmid_to_user(buf, &tbuf, version)) | ||
1573 | err = -EFAULT; | ||
1574 | else | ||
1575 | err = result; | ||
1576 | goto out; | ||
1577 | } | ||
1578 | + default: | ||
1579 | + return -EINVAL; | ||
1580 | + } | ||
1581 | + | ||
1582 | +out_unlock: | ||
1583 | + rcu_read_unlock(); | ||
1584 | +out: | ||
1585 | + return err; | ||
1586 | +} | ||
1587 | + | ||
1588 | +SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1589 | +{ | ||
1590 | + struct shmid_kernel *shp; | ||
1591 | + int err, version; | ||
1592 | + struct ipc_namespace *ns; | ||
1593 | + | ||
1594 | + if (cmd < 0 || shmid < 0) | ||
1595 | + return -EINVAL; | ||
1596 | + | ||
1597 | + version = ipc_parse_version(&cmd); | ||
1598 | + ns = current->nsproxy->ipc_ns; | ||
1599 | + | ||
1600 | + switch (cmd) { | ||
1601 | + case IPC_INFO: | ||
1602 | + case SHM_INFO: | ||
1603 | + case SHM_STAT: | ||
1604 | + case IPC_STAT: | ||
1605 | + return shmctl_nolock(ns, shmid, cmd, version, buf); | ||
1606 | + case IPC_RMID: | ||
1607 | + case IPC_SET: | ||
1608 | + return shmctl_down(ns, shmid, cmd, buf, version); | ||
1609 | case SHM_LOCK: | ||
1610 | case SHM_UNLOCK: | ||
1611 | { | ||
1612 | struct file *shm_file; | ||
1613 | |||
1614 | - shp = shm_lock_check(ns, shmid); | ||
1615 | + rcu_read_lock(); | ||
1616 | + shp = shm_obtain_object_check(ns, shmid); | ||
1617 | if (IS_ERR(shp)) { | ||
1618 | err = PTR_ERR(shp); | ||
1619 | - goto out; | ||
1620 | + goto out_unlock1; | ||
1621 | } | ||
1622 | |||
1623 | audit_ipc_obj(&(shp->shm_perm)); | ||
1624 | + err = security_shm_shmctl(shp, cmd); | ||
1625 | + if (err) | ||
1626 | + goto out_unlock1; | ||
1627 | |||
1628 | + ipc_lock_object(&shp->shm_perm); | ||
1629 | if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { | ||
1630 | kuid_t euid = current_euid(); | ||
1631 | err = -EPERM; | ||
1632 | if (!uid_eq(euid, shp->shm_perm.uid) && | ||
1633 | !uid_eq(euid, shp->shm_perm.cuid)) | ||
1634 | - goto out_unlock; | ||
1635 | + goto out_unlock0; | ||
1636 | if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) | ||
1637 | - goto out_unlock; | ||
1638 | + goto out_unlock0; | ||
1639 | } | ||
1640 | |||
1641 | - err = security_shm_shmctl(shp, cmd); | ||
1642 | - if (err) | ||
1643 | - goto out_unlock; | ||
1644 | - | ||
1645 | shm_file = shp->shm_file; | ||
1646 | if (is_file_hugepages(shm_file)) | ||
1647 | - goto out_unlock; | ||
1648 | + goto out_unlock0; | ||
1649 | |||
1650 | if (cmd == SHM_LOCK) { | ||
1651 | struct user_struct *user = current_user(); | ||
1652 | @@ -951,32 +993,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) | ||
1653 | shp->shm_perm.mode |= SHM_LOCKED; | ||
1654 | shp->mlock_user = user; | ||
1655 | } | ||
1656 | - goto out_unlock; | ||
1657 | + goto out_unlock0; | ||
1658 | } | ||
1659 | |||
1660 | /* SHM_UNLOCK */ | ||
1661 | if (!(shp->shm_perm.mode & SHM_LOCKED)) | ||
1662 | - goto out_unlock; | ||
1663 | + goto out_unlock0; | ||
1664 | shmem_lock(shm_file, 0, shp->mlock_user); | ||
1665 | shp->shm_perm.mode &= ~SHM_LOCKED; | ||
1666 | shp->mlock_user = NULL; | ||
1667 | get_file(shm_file); | ||
1668 | - shm_unlock(shp); | ||
1669 | + ipc_unlock_object(&shp->shm_perm); | ||
1670 | + rcu_read_unlock(); | ||
1671 | shmem_unlock_mapping(shm_file->f_mapping); | ||
1672 | + | ||
1673 | fput(shm_file); | ||
1674 | - goto out; | ||
1675 | - } | ||
1676 | - case IPC_RMID: | ||
1677 | - case IPC_SET: | ||
1678 | - err = shmctl_down(ns, shmid, cmd, buf, version); | ||
1679 | return err; | ||
1680 | + } | ||
1681 | default: | ||
1682 | return -EINVAL; | ||
1683 | } | ||
1684 | |||
1685 | -out_unlock: | ||
1686 | - shm_unlock(shp); | ||
1687 | -out: | ||
1688 | +out_unlock0: | ||
1689 | + ipc_unlock_object(&shp->shm_perm); | ||
1690 | +out_unlock1: | ||
1691 | + rcu_read_unlock(); | ||
1692 | return err; | ||
1693 | } | ||
1694 | |||
1695 | @@ -1044,10 +1085,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, | ||
1696 | * additional creator id... | ||
1697 | */ | ||
1698 | ns = current->nsproxy->ipc_ns; | ||
1699 | - shp = shm_lock_check(ns, shmid); | ||
1700 | + rcu_read_lock(); | ||
1701 | + shp = shm_obtain_object_check(ns, shmid); | ||
1702 | if (IS_ERR(shp)) { | ||
1703 | err = PTR_ERR(shp); | ||
1704 | - goto out; | ||
1705 | + goto out_unlock; | ||
1706 | } | ||
1707 | |||
1708 | err = -EACCES; | ||
1709 | @@ -1058,24 +1100,31 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, | ||
1710 | if (err) | ||
1711 | goto out_unlock; | ||
1712 | |||
1713 | + ipc_lock_object(&shp->shm_perm); | ||
1714 | path = shp->shm_file->f_path; | ||
1715 | path_get(&path); | ||
1716 | shp->shm_nattch++; | ||
1717 | size = i_size_read(path.dentry->d_inode); | ||
1718 | - shm_unlock(shp); | ||
1719 | + ipc_unlock_object(&shp->shm_perm); | ||
1720 | + rcu_read_unlock(); | ||
1721 | |||
1722 | err = -ENOMEM; | ||
1723 | sfd = kzalloc(sizeof(*sfd), GFP_KERNEL); | ||
1724 | - if (!sfd) | ||
1725 | - goto out_put_dentry; | ||
1726 | + if (!sfd) { | ||
1727 | + path_put(&path); | ||
1728 | + goto out_nattch; | ||
1729 | + } | ||
1730 | |||
1731 | file = alloc_file(&path, f_mode, | ||
1732 | is_file_hugepages(shp->shm_file) ? | ||
1733 | &shm_file_operations_huge : | ||
1734 | &shm_file_operations); | ||
1735 | err = PTR_ERR(file); | ||
1736 | - if (IS_ERR(file)) | ||
1737 | - goto out_free; | ||
1738 | + if (IS_ERR(file)) { | ||
1739 | + kfree(sfd); | ||
1740 | + path_put(&path); | ||
1741 | + goto out_nattch; | ||
1742 | + } | ||
1743 | |||
1744 | file->private_data = sfd; | ||
1745 | file->f_mapping = shp->shm_file->f_mapping; | ||
1746 | @@ -1101,7 +1150,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr, | ||
1747 | addr > current->mm->start_stack - size - PAGE_SIZE * 5) | ||
1748 | goto invalid; | ||
1749 | } | ||
1750 | - | ||
1751 | + | ||
1752 | addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate); | ||
1753 | *raddr = addr; | ||
1754 | err = 0; | ||
1755 | @@ -1116,7 +1165,7 @@ out_fput: | ||
1756 | fput(file); | ||
1757 | |||
1758 | out_nattch: | ||
1759 | - down_write(&shm_ids(ns).rw_mutex); | ||
1760 | + down_write(&shm_ids(ns).rwsem); | ||
1761 | shp = shm_lock(ns, shmid); | ||
1762 | BUG_ON(IS_ERR(shp)); | ||
1763 | shp->shm_nattch--; | ||
1764 | @@ -1124,20 +1173,13 @@ out_nattch: | ||
1765 | shm_destroy(ns, shp); | ||
1766 | else | ||
1767 | shm_unlock(shp); | ||
1768 | - up_write(&shm_ids(ns).rw_mutex); | ||
1769 | - | ||
1770 | -out: | ||
1771 | + up_write(&shm_ids(ns).rwsem); | ||
1772 | return err; | ||
1773 | |||
1774 | out_unlock: | ||
1775 | - shm_unlock(shp); | ||
1776 | - goto out; | ||
1777 | - | ||
1778 | -out_free: | ||
1779 | - kfree(sfd); | ||
1780 | -out_put_dentry: | ||
1781 | - path_put(&path); | ||
1782 | - goto out_nattch; | ||
1783 | + rcu_read_unlock(); | ||
1784 | +out: | ||
1785 | + return err; | ||
1786 | } | ||
1787 | |||
1788 | SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) | ||
1789 | @@ -1242,8 +1284,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) | ||
1790 | #else /* CONFIG_MMU */ | ||
1791 | /* under NOMMU conditions, the exact address to be destroyed must be | ||
1792 | * given */ | ||
1793 | - retval = -EINVAL; | ||
1794 | - if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) { | ||
1795 | + if (vma && vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) { | ||
1796 | do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start); | ||
1797 | retval = 0; | ||
1798 | } | ||
1799 | diff --git a/ipc/util.c b/ipc/util.c | ||
1800 | index 0c6566b..fdb8ae7 100644 | ||
1801 | --- a/ipc/util.c | ||
1802 | +++ b/ipc/util.c | ||
1803 | @@ -15,6 +15,14 @@ | ||
1804 | * Jun 2006 - namespaces ssupport | ||
1805 | * OpenVZ, SWsoft Inc. | ||
1806 | * Pavel Emelianov <xemul@openvz.org> | ||
1807 | + * | ||
1808 | + * General sysv ipc locking scheme: | ||
1809 | + * when doing ipc id lookups, take the ids->rwsem | ||
1810 | + * rcu_read_lock() | ||
1811 | + * obtain the ipc object (kern_ipc_perm) | ||
1812 | + * perform security, capabilities, auditing and permission checks, etc. | ||
1813 | + * acquire the ipc lock (kern_ipc_perm.lock) throught ipc_lock_object() | ||
1814 | + * perform data updates (ie: SET, RMID, LOCK/UNLOCK commands) | ||
1815 | */ | ||
1816 | |||
1817 | #include <linux/mm.h> | ||
1818 | @@ -119,7 +127,7 @@ __initcall(ipc_init); | ||
1819 | |||
1820 | void ipc_init_ids(struct ipc_ids *ids) | ||
1821 | { | ||
1822 | - init_rwsem(&ids->rw_mutex); | ||
1823 | + init_rwsem(&ids->rwsem); | ||
1824 | |||
1825 | ids->in_use = 0; | ||
1826 | ids->seq = 0; | ||
1827 | @@ -174,7 +182,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | ||
1828 | * @ids: Identifier set | ||
1829 | * @key: The key to find | ||
1830 | * | ||
1831 | - * Requires ipc_ids.rw_mutex locked. | ||
1832 | + * Requires ipc_ids.rwsem locked. | ||
1833 | * Returns the LOCKED pointer to the ipc structure if found or NULL | ||
1834 | * if not. | ||
1835 | * If key is found ipc points to the owning ipc structure | ||
1836 | @@ -197,7 +205,8 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) | ||
1837 | continue; | ||
1838 | } | ||
1839 | |||
1840 | - ipc_lock_by_ptr(ipc); | ||
1841 | + rcu_read_lock(); | ||
1842 | + ipc_lock_object(ipc); | ||
1843 | return ipc; | ||
1844 | } | ||
1845 | |||
1846 | @@ -208,7 +217,7 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) | ||
1847 | * ipc_get_maxid - get the last assigned id | ||
1848 | * @ids: IPC identifier set | ||
1849 | * | ||
1850 | - * Called with ipc_ids.rw_mutex held. | ||
1851 | + * Called with ipc_ids.rwsem held. | ||
1852 | */ | ||
1853 | |||
1854 | int ipc_get_maxid(struct ipc_ids *ids) | ||
1855 | @@ -246,7 +255,7 @@ int ipc_get_maxid(struct ipc_ids *ids) | ||
1856 | * is returned. The 'new' entry is returned in a locked state on success. | ||
1857 | * On failure the entry is not locked and a negative err-code is returned. | ||
1858 | * | ||
1859 | - * Called with writer ipc_ids.rw_mutex held. | ||
1860 | + * Called with writer ipc_ids.rwsem held. | ||
1861 | */ | ||
1862 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | ||
1863 | { | ||
1864 | @@ -312,9 +321,9 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
1865 | { | ||
1866 | int err; | ||
1867 | |||
1868 | - down_write(&ids->rw_mutex); | ||
1869 | + down_write(&ids->rwsem); | ||
1870 | err = ops->getnew(ns, params); | ||
1871 | - up_write(&ids->rw_mutex); | ||
1872 | + up_write(&ids->rwsem); | ||
1873 | return err; | ||
1874 | } | ||
1875 | |||
1876 | @@ -331,7 +340,7 @@ static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
1877 | * | ||
1878 | * On success, the IPC id is returned. | ||
1879 | * | ||
1880 | - * It is called with ipc_ids.rw_mutex and ipcp->lock held. | ||
1881 | + * It is called with ipc_ids.rwsem and ipcp->lock held. | ||
1882 | */ | ||
1883 | static int ipc_check_perms(struct ipc_namespace *ns, | ||
1884 | struct kern_ipc_perm *ipcp, | ||
1885 | @@ -376,7 +385,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
1886 | * Take the lock as a writer since we are potentially going to add | ||
1887 | * a new entry + read locks are not "upgradable" | ||
1888 | */ | ||
1889 | - down_write(&ids->rw_mutex); | ||
1890 | + down_write(&ids->rwsem); | ||
1891 | ipcp = ipc_findkey(ids, params->key); | ||
1892 | if (ipcp == NULL) { | ||
1893 | /* key not used */ | ||
1894 | @@ -402,7 +411,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
1895 | } | ||
1896 | ipc_unlock(ipcp); | ||
1897 | } | ||
1898 | - up_write(&ids->rw_mutex); | ||
1899 | + up_write(&ids->rwsem); | ||
1900 | |||
1901 | return err; | ||
1902 | } | ||
1903 | @@ -413,7 +422,7 @@ static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
1904 | * @ids: IPC identifier set | ||
1905 | * @ipcp: ipc perm structure containing the identifier to remove | ||
1906 | * | ||
1907 | - * ipc_ids.rw_mutex (as a writer) and the spinlock for this ID are held | ||
1908 | + * ipc_ids.rwsem (as a writer) and the spinlock for this ID are held | ||
1909 | * before this function is called, and remain locked on the exit. | ||
1910 | */ | ||
1911 | |||
1912 | @@ -613,7 +622,7 @@ struct kern_ipc_perm *ipc_obtain_object(struct ipc_ids *ids, int id) | ||
1913 | } | ||
1914 | |||
1915 | /** | ||
1916 | - * ipc_lock - Lock an ipc structure without rw_mutex held | ||
1917 | + * ipc_lock - Lock an ipc structure without rwsem held | ||
1918 | * @ids: IPC identifier set | ||
1919 | * @id: ipc id to look for | ||
1920 | * | ||
1921 | @@ -669,22 +678,6 @@ out: | ||
1922 | return out; | ||
1923 | } | ||
1924 | |||
1925 | -struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id) | ||
1926 | -{ | ||
1927 | - struct kern_ipc_perm *out; | ||
1928 | - | ||
1929 | - out = ipc_lock(ids, id); | ||
1930 | - if (IS_ERR(out)) | ||
1931 | - return out; | ||
1932 | - | ||
1933 | - if (ipc_checkid(out, id)) { | ||
1934 | - ipc_unlock(out); | ||
1935 | - return ERR_PTR(-EIDRM); | ||
1936 | - } | ||
1937 | - | ||
1938 | - return out; | ||
1939 | -} | ||
1940 | - | ||
1941 | /** | ||
1942 | * ipcget - Common sys_*get() code | ||
1943 | * @ns : namsepace | ||
1944 | @@ -725,7 +718,7 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) | ||
1945 | } | ||
1946 | |||
1947 | /** | ||
1948 | - * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd | ||
1949 | + * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd | ||
1950 | * @ns: the ipc namespace | ||
1951 | * @ids: the table of ids where to look for the ipc | ||
1952 | * @id: the id of the ipc to retrieve | ||
1953 | @@ -738,29 +731,13 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) | ||
1954 | * It must be called without any lock held and | ||
1955 | * - retrieves the ipc with the given id in the given table. | ||
1956 | * - performs some audit and permission check, depending on the given cmd | ||
1957 | - * - returns the ipc with the ipc lock held in case of success | ||
1958 | - * or an err-code without any lock held otherwise. | ||
1959 | + * - returns a pointer to the ipc object or otherwise, the corresponding error. | ||
1960 | * | ||
1961 | - * Call holding the both the rw_mutex and the rcu read lock. | ||
1962 | + * Call holding the both the rwsem and the rcu read lock. | ||
1963 | */ | ||
1964 | -struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | ||
1965 | - struct ipc_ids *ids, int id, int cmd, | ||
1966 | - struct ipc64_perm *perm, int extra_perm) | ||
1967 | -{ | ||
1968 | - struct kern_ipc_perm *ipcp; | ||
1969 | - | ||
1970 | - ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm); | ||
1971 | - if (IS_ERR(ipcp)) | ||
1972 | - goto out; | ||
1973 | - | ||
1974 | - spin_lock(&ipcp->lock); | ||
1975 | -out: | ||
1976 | - return ipcp; | ||
1977 | -} | ||
1978 | - | ||
1979 | struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns, | ||
1980 | - struct ipc_ids *ids, int id, int cmd, | ||
1981 | - struct ipc64_perm *perm, int extra_perm) | ||
1982 | + struct ipc_ids *ids, int id, int cmd, | ||
1983 | + struct ipc64_perm *perm, int extra_perm) | ||
1984 | { | ||
1985 | kuid_t euid; | ||
1986 | int err = -EPERM; | ||
1987 | @@ -838,7 +815,8 @@ static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos, | ||
1988 | ipc = idr_find(&ids->ipcs_idr, pos); | ||
1989 | if (ipc != NULL) { | ||
1990 | *new_pos = pos + 1; | ||
1991 | - ipc_lock_by_ptr(ipc); | ||
1992 | + rcu_read_lock(); | ||
1993 | + ipc_lock_object(ipc); | ||
1994 | return ipc; | ||
1995 | } | ||
1996 | } | ||
1997 | @@ -876,7 +854,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) | ||
1998 | * Take the lock - this will be released by the corresponding | ||
1999 | * call to stop(). | ||
2000 | */ | ||
2001 | - down_read(&ids->rw_mutex); | ||
2002 | + down_read(&ids->rwsem); | ||
2003 | |||
2004 | /* pos < 0 is invalid */ | ||
2005 | if (*pos < 0) | ||
2006 | @@ -903,7 +881,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it) | ||
2007 | |||
2008 | ids = &iter->ns->ids[iface->ids]; | ||
2009 | /* Release the lock we took in start() */ | ||
2010 | - up_read(&ids->rw_mutex); | ||
2011 | + up_read(&ids->rwsem); | ||
2012 | } | ||
2013 | |||
2014 | static int sysvipc_proc_show(struct seq_file *s, void *it) | ||
2015 | diff --git a/ipc/util.h b/ipc/util.h | ||
2016 | index 25299e7..f2f5036 100644 | ||
2017 | --- a/ipc/util.h | ||
2018 | +++ b/ipc/util.h | ||
2019 | @@ -101,10 +101,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | ||
2020 | #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) | ||
2021 | #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER) | ||
2022 | |||
2023 | -/* must be called with ids->rw_mutex acquired for writing */ | ||
2024 | +/* must be called with ids->rwsem acquired for writing */ | ||
2025 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); | ||
2026 | |||
2027 | -/* must be called with ids->rw_mutex acquired for reading */ | ||
2028 | +/* must be called with ids->rwsem acquired for reading */ | ||
2029 | int ipc_get_maxid(struct ipc_ids *); | ||
2030 | |||
2031 | /* must be called with both locks acquired. */ | ||
2032 | @@ -139,9 +139,6 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out); | ||
2033 | struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns, | ||
2034 | struct ipc_ids *ids, int id, int cmd, | ||
2035 | struct ipc64_perm *perm, int extra_perm); | ||
2036 | -struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | ||
2037 | - struct ipc_ids *ids, int id, int cmd, | ||
2038 | - struct ipc64_perm *perm, int extra_perm); | ||
2039 | |||
2040 | #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION | ||
2041 | /* On IA-64, we always use the "64-bit version" of the IPC structures. */ | ||
2042 | @@ -182,19 +179,12 @@ static inline void ipc_assert_locked_object(struct kern_ipc_perm *perm) | ||
2043 | assert_spin_locked(&perm->lock); | ||
2044 | } | ||
2045 | |||
2046 | -static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm) | ||
2047 | -{ | ||
2048 | - rcu_read_lock(); | ||
2049 | - ipc_lock_object(perm); | ||
2050 | -} | ||
2051 | - | ||
2052 | static inline void ipc_unlock(struct kern_ipc_perm *perm) | ||
2053 | { | ||
2054 | ipc_unlock_object(perm); | ||
2055 | rcu_read_unlock(); | ||
2056 | } | ||
2057 | |||
2058 | -struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); | ||
2059 | struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id); | ||
2060 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
2061 | struct ipc_ops *ops, struct ipc_params *params); | ||
2062 | diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c | ||
2063 | index 45850f6..4865756 100644 | ||
2064 | --- a/sound/pci/hda/patch_hdmi.c | ||
2065 | +++ b/sound/pci/hda/patch_hdmi.c | ||
2066 | @@ -930,6 +930,14 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | ||
2067 | } | ||
2068 | |||
2069 | /* | ||
2070 | + * always configure channel mapping, it may have been changed by the | ||
2071 | + * user in the meantime | ||
2072 | + */ | ||
2073 | + hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | ||
2074 | + channels, per_pin->chmap, | ||
2075 | + per_pin->chmap_set); | ||
2076 | + | ||
2077 | + /* | ||
2078 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | ||
2079 | * sizeof(*dp_ai) to avoid partial match/update problems when | ||
2080 | * the user switches between HDMI/DP monitors. | ||
2081 | @@ -940,20 +948,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, | ||
2082 | "pin=%d channels=%d\n", | ||
2083 | pin_nid, | ||
2084 | channels); | ||
2085 | - hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | ||
2086 | - channels, per_pin->chmap, | ||
2087 | - per_pin->chmap_set); | ||
2088 | hdmi_stop_infoframe_trans(codec, pin_nid); | ||
2089 | hdmi_fill_audio_infoframe(codec, pin_nid, | ||
2090 | ai.bytes, sizeof(ai)); | ||
2091 | hdmi_start_infoframe_trans(codec, pin_nid); | ||
2092 | - } else { | ||
2093 | - /* For non-pcm audio switch, setup new channel mapping | ||
2094 | - * accordingly */ | ||
2095 | - if (per_pin->non_pcm != non_pcm) | ||
2096 | - hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | ||
2097 | - channels, per_pin->chmap, | ||
2098 | - per_pin->chmap_set); | ||
2099 | } | ||
2100 | |||
2101 | per_pin->non_pcm = non_pcm; | ||
2102 | diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c | ||
2103 | index 389db4c..1383f38 100644 | ||
2104 | --- a/sound/pci/hda/patch_realtek.c | ||
2105 | +++ b/sound/pci/hda/patch_realtek.c | ||
2106 | @@ -3308,6 +3308,15 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, | ||
2107 | } | ||
2108 | } | ||
2109 | |||
2110 | +static void alc290_fixup_mono_speakers(struct hda_codec *codec, | ||
2111 | + const struct hda_fixup *fix, int action) | ||
2112 | +{ | ||
2113 | + if (action == HDA_FIXUP_ACT_PRE_PROBE) | ||
2114 | + /* Remove DAC node 0x03, as it seems to be | ||
2115 | + giving mono output */ | ||
2116 | + snd_hda_override_wcaps(codec, 0x03, 0); | ||
2117 | +} | ||
2118 | + | ||
2119 | enum { | ||
2120 | ALC269_FIXUP_SONY_VAIO, | ||
2121 | ALC275_FIXUP_SONY_VAIO_GPIO2, | ||
2122 | @@ -3331,9 +3340,12 @@ enum { | ||
2123 | ALC269_FIXUP_HP_GPIO_LED, | ||
2124 | ALC269_FIXUP_INV_DMIC, | ||
2125 | ALC269_FIXUP_LENOVO_DOCK, | ||
2126 | + ALC286_FIXUP_SONY_MIC_NO_PRESENCE, | ||
2127 | ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, | ||
2128 | ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, | ||
2129 | ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, | ||
2130 | + ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | ||
2131 | + ALC290_FIXUP_MONO_SPEAKERS, | ||
2132 | ALC269_FIXUP_HEADSET_MODE, | ||
2133 | ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, | ||
2134 | ALC269_FIXUP_ASUS_X101_FUNC, | ||
2135 | @@ -3521,6 +3533,15 @@ static const struct hda_fixup alc269_fixups[] = { | ||
2136 | .chained = true, | ||
2137 | .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC | ||
2138 | }, | ||
2139 | + [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = { | ||
2140 | + .type = HDA_FIXUP_PINS, | ||
2141 | + .v.pins = (const struct hda_pintbl[]) { | ||
2142 | + { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
2143 | + { } | ||
2144 | + }, | ||
2145 | + .chained = true, | ||
2146 | + .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC | ||
2147 | + }, | ||
2148 | [ALC269_FIXUP_HEADSET_MODE] = { | ||
2149 | .type = HDA_FIXUP_FUNC, | ||
2150 | .v.func = alc_fixup_headset_mode, | ||
2151 | @@ -3529,6 +3550,13 @@ static const struct hda_fixup alc269_fixups[] = { | ||
2152 | .type = HDA_FIXUP_FUNC, | ||
2153 | .v.func = alc_fixup_headset_mode_no_hp_mic, | ||
2154 | }, | ||
2155 | + [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = { | ||
2156 | + .type = HDA_FIXUP_PINS, | ||
2157 | + .v.pins = (const struct hda_pintbl[]) { | ||
2158 | + { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */ | ||
2159 | + { } | ||
2160 | + }, | ||
2161 | + }, | ||
2162 | [ALC269_FIXUP_ASUS_X101_FUNC] = { | ||
2163 | .type = HDA_FIXUP_FUNC, | ||
2164 | .v.func = alc269_fixup_x101_headset_mic, | ||
2165 | @@ -3595,6 +3623,12 @@ static const struct hda_fixup alc269_fixups[] = { | ||
2166 | { } | ||
2167 | }, | ||
2168 | }, | ||
2169 | + [ALC290_FIXUP_MONO_SPEAKERS] = { | ||
2170 | + .type = HDA_FIXUP_FUNC, | ||
2171 | + .v.func = alc290_fixup_mono_speakers, | ||
2172 | + .chained = true, | ||
2173 | + .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, | ||
2174 | + }, | ||
2175 | }; | ||
2176 | |||
2177 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | ||
2178 | @@ -3631,6 +3665,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | ||
2179 | SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
2180 | SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
2181 | SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), | ||
2182 | + SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_MONO_SPEAKERS), | ||
2183 | SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
2184 | SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), | ||
2185 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), | ||
2186 | @@ -3651,6 +3686,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | ||
2187 | SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | ||
2188 | SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), | ||
2189 | SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), | ||
2190 | + SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE), | ||
2191 | SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), | ||
2192 | SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | ||
2193 | SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), | ||
2194 | @@ -4345,6 +4381,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { | ||
2195 | SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | ||
2196 | SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), | ||
2197 | SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), | ||
2198 | + SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_ASUS_MODE4), | ||
2199 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | ||
2200 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | ||
2201 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), | ||
2202 | diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c | ||
2203 | index 63fb521..6234a51 100644 | ||
2204 | --- a/sound/usb/usx2y/usbusx2yaudio.c | ||
2205 | +++ b/sound/usb/usx2y/usbusx2yaudio.c | ||
2206 | @@ -299,19 +299,6 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, | ||
2207 | usX2Y_clients_stop(usX2Y); | ||
2208 | } | ||
2209 | |||
2210 | -static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, | ||
2211 | - struct snd_usX2Y_substream *subs, struct urb *urb) | ||
2212 | -{ | ||
2213 | - snd_printk(KERN_ERR | ||
2214 | -"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" | ||
2215 | -"Most probably some urb of usb-frame %i is still missing.\n" | ||
2216 | -"Cause could be too long delays in usb-hcd interrupt handling.\n", | ||
2217 | - usb_get_current_frame_number(usX2Y->dev), | ||
2218 | - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", | ||
2219 | - usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); | ||
2220 | - usX2Y_clients_stop(usX2Y); | ||
2221 | -} | ||
2222 | - | ||
2223 | static void i_usX2Y_urb_complete(struct urb *urb) | ||
2224 | { | ||
2225 | struct snd_usX2Y_substream *subs = urb->context; | ||
2226 | @@ -328,12 +315,9 @@ static void i_usX2Y_urb_complete(struct urb *urb) | ||
2227 | usX2Y_error_urb_status(usX2Y, subs, urb); | ||
2228 | return; | ||
2229 | } | ||
2230 | - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) | ||
2231 | - subs->completed_urb = urb; | ||
2232 | - else { | ||
2233 | - usX2Y_error_sequence(usX2Y, subs, urb); | ||
2234 | - return; | ||
2235 | - } | ||
2236 | + | ||
2237 | + subs->completed_urb = urb; | ||
2238 | + | ||
2239 | { | ||
2240 | struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], | ||
2241 | *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; | ||
2242 | diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c | ||
2243 | index f2a1acd..814d0e8 100644 | ||
2244 | --- a/sound/usb/usx2y/usx2yhwdeppcm.c | ||
2245 | +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | ||
2246 | @@ -244,13 +244,8 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) | ||
2247 | usX2Y_error_urb_status(usX2Y, subs, urb); | ||
2248 | return; | ||
2249 | } | ||
2250 | - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) | ||
2251 | - subs->completed_urb = urb; | ||
2252 | - else { | ||
2253 | - usX2Y_error_sequence(usX2Y, subs, urb); | ||
2254 | - return; | ||
2255 | - } | ||
2256 | |||
2257 | + subs->completed_urb = urb; | ||
2258 | capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; | ||
2259 | capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; | ||
2260 | playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; |