Gentoo Archives: gentoo-commits

From: "Anthony G. Basile" <blueness@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/hardened-patchset:master commit in: 2.6.32/
Date: Tue, 27 Dec 2011 02:29:11
Message-Id: 3c1c918b40f8170dfd158b6bee73fb4fe26e29a6.blueness@gentoo
1 commit: 3c1c918b40f8170dfd158b6bee73fb4fe26e29a6
2 Author: Anthony G. Basile <blueness <AT> gentoo <DOT> org>
3 AuthorDate: Tue Dec 27 02:28:53 2011 +0000
4 Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org>
5 CommitDate: Tue Dec 27 02:28:53 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/hardened-patchset.git;a=commit;h=3c1c918b
7
8 Add patch to bump to 2.6.32.51
9
10 ---
11 2.6.32/0000_README | 4 +
12 2.6.32/1050_linux-2.6.32.51.patch | 588 +++++++++++++++++++++++++++++++++++++
13 2 files changed, 592 insertions(+), 0 deletions(-)
14
15 diff --git a/2.6.32/0000_README b/2.6.32/0000_README
16 index 22c2947..c414b52 100644
17 --- a/2.6.32/0000_README
18 +++ b/2.6.32/0000_README
19 @@ -3,6 +3,10 @@ README
20
21 Individual Patch Descriptions:
22 -----------------------------------------------------------------------------
23 +Patch: 1050_linux-2.6.32.51.patch
24 +From: http://www.kernel.org
25 +Desc: Linux 2.6.32.51
26 +
27 Patch: 4420_grsecurity-2.2.2-2.6.32.51-201112222105.patch
28 From: http://www.grsecurity.net
29 Desc: hardened-sources base patch from upstream grsecurity
30
31 diff --git a/2.6.32/1050_linux-2.6.32.51.patch b/2.6.32/1050_linux-2.6.32.51.patch
32 new file mode 100644
33 index 0000000..e328bd5
34 --- /dev/null
35 +++ b/2.6.32/1050_linux-2.6.32.51.patch
36 @@ -0,0 +1,588 @@
37 +diff --git a/Makefile b/Makefile
38 +index f38986c..1c640ea 100644
39 +--- a/Makefile
40 ++++ b/Makefile
41 +@@ -1,7 +1,7 @@
42 + VERSION = 2
43 + PATCHLEVEL = 6
44 + SUBLEVEL = 32
45 +-EXTRAVERSION = .50
46 ++EXTRAVERSION = .51
47 + NAME = Man-Eating Seals of Antiquity
48 +
49 + # *DOCUMENTATION*
50 +diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
51 +index 24e0e13..6b25227 100644
52 +--- a/arch/arm/mach-davinci/board-dm646x-evm.c
53 ++++ b/arch/arm/mach-davinci/board-dm646x-evm.c
54 +@@ -502,7 +502,7 @@ static int setup_vpif_input_channel_mode(int mux_mode)
55 + int val;
56 + u32 value;
57 +
58 +- if (!vpif_vsclkdis_reg || !cpld_client)
59 ++ if (!vpif_vidclkctl_reg || !cpld_client)
60 + return -ENXIO;
61 +
62 + val = i2c_smbus_read_byte(cpld_client);
63 +@@ -510,7 +510,7 @@ static int setup_vpif_input_channel_mode(int mux_mode)
64 + return val;
65 +
66 + spin_lock_irqsave(&vpif_reg_lock, flags);
67 +- value = __raw_readl(vpif_vsclkdis_reg);
68 ++ value = __raw_readl(vpif_vidclkctl_reg);
69 + if (mux_mode) {
70 + val &= VPIF_INPUT_TWO_CHANNEL;
71 + value |= VIDCH1CLK;
72 +@@ -518,7 +518,7 @@ static int setup_vpif_input_channel_mode(int mux_mode)
73 + val |= VPIF_INPUT_ONE_CHANNEL;
74 + value &= ~VIDCH1CLK;
75 + }
76 +- __raw_writel(value, vpif_vsclkdis_reg);
77 ++ __raw_writel(value, vpif_vidclkctl_reg);
78 + spin_unlock_irqrestore(&vpif_reg_lock, flags);
79 +
80 + err = i2c_smbus_write_byte(cpld_client, val);
81 +diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
82 +index 044897b..829edf0 100644
83 +--- a/arch/x86/oprofile/backtrace.c
84 ++++ b/arch/x86/oprofile/backtrace.c
85 +@@ -11,6 +11,8 @@
86 + #include <linux/oprofile.h>
87 + #include <linux/sched.h>
88 + #include <linux/mm.h>
89 ++#include <linux/highmem.h>
90 ++
91 + #include <asm/ptrace.h>
92 + #include <asm/uaccess.h>
93 + #include <asm/stacktrace.h>
94 +@@ -47,6 +49,42 @@ static struct stacktrace_ops backtrace_ops = {
95 + .address = backtrace_address,
96 + };
97 +
98 ++/* from arch/x86/kernel/cpu/perf_event.c: */
99 ++
100 ++/*
101 ++ * best effort, GUP based copy_from_user() that assumes IRQ or NMI context
102 ++ */
103 ++static unsigned long
104 ++copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
105 ++{
106 ++ unsigned long offset, addr = (unsigned long)from;
107 ++ unsigned long size, len = 0;
108 ++ struct page *page;
109 ++ void *map;
110 ++ int ret;
111 ++
112 ++ do {
113 ++ ret = __get_user_pages_fast(addr, 1, 0, &page);
114 ++ if (!ret)
115 ++ break;
116 ++
117 ++ offset = addr & (PAGE_SIZE - 1);
118 ++ size = min(PAGE_SIZE - offset, n - len);
119 ++
120 ++ map = kmap_atomic(page, KM_USER0);
121 ++ memcpy(to, map+offset, size);
122 ++ kunmap_atomic(map, KM_USER0);
123 ++ put_page(page);
124 ++
125 ++ len += size;
126 ++ to += size;
127 ++ addr += size;
128 ++
129 ++ } while (len < n);
130 ++
131 ++ return len;
132 ++}
133 ++
134 + struct frame_head {
135 + struct frame_head *bp;
136 + unsigned long ret;
137 +@@ -54,12 +92,12 @@ struct frame_head {
138 +
139 + static struct frame_head *dump_user_backtrace(struct frame_head *head)
140 + {
141 ++ /* Also check accessibility of one struct frame_head beyond: */
142 + struct frame_head bufhead[2];
143 ++ unsigned long bytes;
144 +
145 +- /* Also check accessibility of one struct frame_head beyond */
146 +- if (!access_ok(VERIFY_READ, head, sizeof(bufhead)))
147 +- return NULL;
148 +- if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead)))
149 ++ bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
150 ++ if (bytes != sizeof(bufhead))
151 + return NULL;
152 +
153 + oprofile_add_trace(bufhead[0].ret);
154 +diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
155 +index ca6b336..8f0e49b 100644
156 +--- a/arch/x86/oprofile/nmi_int.c
157 ++++ b/arch/x86/oprofile/nmi_int.c
158 +@@ -750,12 +750,12 @@ int __init op_nmi_init(struct oprofile_operations *ops)
159 +
160 + void op_nmi_exit(void)
161 + {
162 +- if (using_nmi) {
163 +- exit_sysfs();
164 ++ if (!using_nmi)
165 ++ return;
166 ++ exit_sysfs();
167 + #ifdef CONFIG_SMP
168 +- unregister_cpu_notifier(&oprofile_cpu_nb);
169 ++ unregister_cpu_notifier(&oprofile_cpu_nb);
170 + #endif
171 +- }
172 + if (model->exit)
173 + model->exit();
174 + }
175 +diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
176 +index 5c4df24..334ccd6 100644
177 +--- a/drivers/oprofile/buffer_sync.c
178 ++++ b/drivers/oprofile/buffer_sync.c
179 +@@ -140,6 +140,13 @@ static struct notifier_block module_load_nb = {
180 + .notifier_call = module_load_notify,
181 + };
182 +
183 ++static void free_all_tasks(void)
184 ++{
185 ++ /* make sure we don't leak task structs */
186 ++ process_task_mortuary();
187 ++ process_task_mortuary();
188 ++}
189 ++
190 + int sync_start(void)
191 + {
192 + int err;
193 +@@ -147,8 +154,6 @@ int sync_start(void)
194 + if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
195 + return -ENOMEM;
196 +
197 +- mutex_lock(&buffer_mutex);
198 +-
199 + err = task_handoff_register(&task_free_nb);
200 + if (err)
201 + goto out1;
202 +@@ -165,7 +170,6 @@ int sync_start(void)
203 + start_cpu_work();
204 +
205 + out:
206 +- mutex_unlock(&buffer_mutex);
207 + return err;
208 + out4:
209 + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
210 +@@ -173,6 +177,7 @@ out3:
211 + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
212 + out2:
213 + task_handoff_unregister(&task_free_nb);
214 ++ free_all_tasks();
215 + out1:
216 + free_cpumask_var(marked_cpus);
217 + goto out;
218 +@@ -181,20 +186,16 @@ out1:
219 +
220 + void sync_stop(void)
221 + {
222 +- /* flush buffers */
223 +- mutex_lock(&buffer_mutex);
224 + end_cpu_work();
225 + unregister_module_notifier(&module_load_nb);
226 + profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
227 + profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
228 + task_handoff_unregister(&task_free_nb);
229 +- mutex_unlock(&buffer_mutex);
230 +- flush_scheduled_work();
231 ++ barrier(); /* do all of the above first */
232 +
233 +- /* make sure we don't leak task structs */
234 +- process_task_mortuary();
235 +- process_task_mortuary();
236 ++ flush_scheduled_work();
237 +
238 ++ free_all_tasks();
239 + free_cpumask_var(marked_cpus);
240 + }
241 +
242 +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
243 +index 9d3d8cf..cec9bff 100644
244 +--- a/drivers/usb/class/cdc-acm.c
245 ++++ b/drivers/usb/class/cdc-acm.c
246 +@@ -1528,6 +1528,16 @@ static struct usb_device_id acm_ids[] = {
247 + },
248 + { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
249 + },
250 ++ /* Motorola H24 HSPA module: */
251 ++ { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */
252 ++ { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */
253 ++ { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */
254 ++ { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */
255 ++ { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */
256 ++ { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */
257 ++ { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */
258 ++ { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */
259 ++
260 + { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
261 + .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
262 + data interface instead of
263 +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
264 +index 8572c79..72ba88f 100644
265 +--- a/fs/ext4/inode.c
266 ++++ b/fs/ext4/inode.c
267 +@@ -3228,7 +3228,7 @@ static int ext4_da_write_end(struct file *file,
268 + */
269 +
270 + new_i_size = pos + copied;
271 +- if (new_i_size > EXT4_I(inode)->i_disksize) {
272 ++ if (copied && new_i_size > EXT4_I(inode)->i_disksize) {
273 + if (ext4_da_should_update_i_disksize(page, end)) {
274 + down_write(&EXT4_I(inode)->i_data_sem);
275 + if (new_i_size > EXT4_I(inode)->i_disksize) {
276 +diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
277 +index 052f214..0609e71 100644
278 +--- a/fs/hfs/btree.c
279 ++++ b/fs/hfs/btree.c
280 +@@ -45,11 +45,26 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
281 + case HFS_EXT_CNID:
282 + hfs_inode_read_fork(tree->inode, mdb->drXTExtRec, mdb->drXTFlSize,
283 + mdb->drXTFlSize, be32_to_cpu(mdb->drXTClpSiz));
284 ++ if (HFS_I(tree->inode)->alloc_blocks >
285 ++ HFS_I(tree->inode)->first_blocks) {
286 ++ printk(KERN_ERR "hfs: invalid btree extent records\n");
287 ++ unlock_new_inode(tree->inode);
288 ++ goto free_inode;
289 ++ }
290 ++
291 + tree->inode->i_mapping->a_ops = &hfs_btree_aops;
292 + break;
293 + case HFS_CAT_CNID:
294 + hfs_inode_read_fork(tree->inode, mdb->drCTExtRec, mdb->drCTFlSize,
295 + mdb->drCTFlSize, be32_to_cpu(mdb->drCTClpSiz));
296 ++
297 ++ if (!HFS_I(tree->inode)->first_blocks) {
298 ++ printk(KERN_ERR "hfs: invalid btree extent records "
299 ++ "(0 size).\n");
300 ++ unlock_new_inode(tree->inode);
301 ++ goto free_inode;
302 ++ }
303 ++
304 + tree->inode->i_mapping->a_ops = &hfs_btree_aops;
305 + break;
306 + default:
307 +@@ -58,11 +73,6 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
308 + }
309 + unlock_new_inode(tree->inode);
310 +
311 +- if (!HFS_I(tree->inode)->first_blocks) {
312 +- printk(KERN_ERR "hfs: invalid btree extent records (0 size).\n");
313 +- goto free_inode;
314 +- }
315 +-
316 + mapping = tree->inode->i_mapping;
317 + page = read_mapping_page(mapping, 0, NULL);
318 + if (IS_ERR(page))
319 +diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
320 +index 45905ff..70713d5 100644
321 +--- a/fs/jbd/journal.c
322 ++++ b/fs/jbd/journal.c
323 +@@ -1070,6 +1070,14 @@ static int journal_get_superblock(journal_t *journal)
324 + goto out;
325 + }
326 +
327 ++ if (be32_to_cpu(sb->s_first) == 0 ||
328 ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
329 ++ printk(KERN_WARNING
330 ++ "JBD: Invalid start block of journal: %u\n",
331 ++ be32_to_cpu(sb->s_first));
332 ++ goto out;
333 ++ }
334 ++
335 + return 0;
336 +
337 + out:
338 +diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
339 +index 17af879..c00de9c 100644
340 +--- a/fs/jbd2/journal.c
341 ++++ b/fs/jbd2/journal.c
342 +@@ -1183,6 +1183,14 @@ static int journal_get_superblock(journal_t *journal)
343 + goto out;
344 + }
345 +
346 ++ if (be32_to_cpu(sb->s_first) == 0 ||
347 ++ be32_to_cpu(sb->s_first) >= journal->j_maxlen) {
348 ++ printk(KERN_WARNING
349 ++ "JBD2: Invalid start block of journal: %u\n",
350 ++ be32_to_cpu(sb->s_first));
351 ++ goto out;
352 ++ }
353 ++
354 + return 0;
355 +
356 + out:
357 +diff --git a/include/linux/log2.h b/include/linux/log2.h
358 +index 25b8086..fd7ff3d 100644
359 +--- a/include/linux/log2.h
360 ++++ b/include/linux/log2.h
361 +@@ -185,7 +185,6 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
362 + #define rounddown_pow_of_two(n) \
363 + ( \
364 + __builtin_constant_p(n) ? ( \
365 +- (n == 1) ? 0 : \
366 + (1UL << ilog2(n))) : \
367 + __rounddown_pow_of_two(n) \
368 + )
369 +diff --git a/kernel/taskstats.c b/kernel/taskstats.c
370 +index b080920..a4ef542 100644
371 +--- a/kernel/taskstats.c
372 ++++ b/kernel/taskstats.c
373 +@@ -592,6 +592,7 @@ static struct genl_ops taskstats_ops = {
374 + .cmd = TASKSTATS_CMD_GET,
375 + .doit = taskstats_user_cmd,
376 + .policy = taskstats_cmd_get_policy,
377 ++ .flags = GENL_ADMIN_PERM,
378 + };
379 +
380 + static struct genl_ops cgroupstats_ops = {
381 +diff --git a/mm/percpu.c b/mm/percpu.c
382 +index 3bfd6e2..c90614a 100644
383 +--- a/mm/percpu.c
384 ++++ b/mm/percpu.c
385 +@@ -110,9 +110,9 @@ static int pcpu_atom_size __read_mostly;
386 + static int pcpu_nr_slots __read_mostly;
387 + static size_t pcpu_chunk_struct_size __read_mostly;
388 +
389 +-/* cpus with the lowest and highest unit numbers */
390 +-static unsigned int pcpu_first_unit_cpu __read_mostly;
391 +-static unsigned int pcpu_last_unit_cpu __read_mostly;
392 ++/* cpus with the lowest and highest unit addresses */
393 ++static unsigned int pcpu_low_unit_cpu __read_mostly;
394 ++static unsigned int pcpu_high_unit_cpu __read_mostly;
395 +
396 + /* the address of the first chunk which starts with the kernel static area */
397 + void *pcpu_base_addr __read_mostly;
398 +@@ -746,8 +746,8 @@ static void pcpu_pre_unmap_flush(struct pcpu_chunk *chunk,
399 + int page_start, int page_end)
400 + {
401 + flush_cache_vunmap(
402 +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
403 +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
404 ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
405 ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
406 + }
407 +
408 + static void __pcpu_unmap_pages(unsigned long addr, int nr_pages)
409 +@@ -809,8 +809,8 @@ static void pcpu_post_unmap_tlb_flush(struct pcpu_chunk *chunk,
410 + int page_start, int page_end)
411 + {
412 + flush_tlb_kernel_range(
413 +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
414 +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
415 ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
416 ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
417 + }
418 +
419 + static int __pcpu_map_pages(unsigned long addr, struct page **pages,
420 +@@ -887,8 +887,8 @@ static void pcpu_post_map_flush(struct pcpu_chunk *chunk,
421 + int page_start, int page_end)
422 + {
423 + flush_cache_vmap(
424 +- pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
425 +- pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
426 ++ pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
427 ++ pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
428 + }
429 +
430 + /**
431 +@@ -1680,7 +1680,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
432 +
433 + for (cpu = 0; cpu < nr_cpu_ids; cpu++)
434 + unit_map[cpu] = UINT_MAX;
435 +- pcpu_first_unit_cpu = NR_CPUS;
436 ++
437 ++ pcpu_low_unit_cpu = NR_CPUS;
438 ++ pcpu_high_unit_cpu = NR_CPUS;
439 +
440 + for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
441 + const struct pcpu_group_info *gi = &ai->groups[group];
442 +@@ -1700,9 +1702,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
443 + unit_map[cpu] = unit + i;
444 + unit_off[cpu] = gi->base_offset + i * ai->unit_size;
445 +
446 +- if (pcpu_first_unit_cpu == NR_CPUS)
447 +- pcpu_first_unit_cpu = cpu;
448 +- pcpu_last_unit_cpu = cpu;
449 ++ /* determine low/high unit_cpu */
450 ++ if (pcpu_low_unit_cpu == NR_CPUS ||
451 ++ unit_off[cpu] < unit_off[pcpu_low_unit_cpu])
452 ++ pcpu_low_unit_cpu = cpu;
453 ++ if (pcpu_high_unit_cpu == NR_CPUS ||
454 ++ unit_off[cpu] > unit_off[pcpu_high_unit_cpu])
455 ++ pcpu_high_unit_cpu = cpu;
456 + }
457 + }
458 + pcpu_nr_units = unit;
459 +diff --git a/mm/util.c b/mm/util.c
460 +index b377ce4..e48b493 100644
461 +--- a/mm/util.c
462 ++++ b/mm/util.c
463 +@@ -233,6 +233,19 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
464 + }
465 + #endif
466 +
467 ++/*
468 ++ * Like get_user_pages_fast() except its IRQ-safe in that it won't fall
469 ++ * back to the regular GUP.
470 ++ * If the architecture not support this fucntion, simply return with no
471 ++ * page pinned
472 ++ */
473 ++int __attribute__((weak)) __get_user_pages_fast(unsigned long start,
474 ++ int nr_pages, int write, struct page **pages)
475 ++{
476 ++ return 0;
477 ++}
478 ++EXPORT_SYMBOL_GPL(__get_user_pages_fast);
479 ++
480 + /**
481 + * get_user_pages_fast() - pin user pages in memory
482 + * @start: starting user address
483 +diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
484 +index faf54c6..9bd850a 100644
485 +--- a/net/xfrm/xfrm_algo.c
486 ++++ b/net/xfrm/xfrm_algo.c
487 +@@ -411,8 +411,8 @@ static struct xfrm_algo_desc ealg_list[] = {
488 + .desc = {
489 + .sadb_alg_id = SADB_X_EALG_AESCTR,
490 + .sadb_alg_ivlen = 8,
491 +- .sadb_alg_minbits = 128,
492 +- .sadb_alg_maxbits = 256
493 ++ .sadb_alg_minbits = 160,
494 ++ .sadb_alg_maxbits = 288
495 + }
496 + },
497 + };
498 +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
499 +index ba44dc0..6419095 100644
500 +--- a/sound/pci/hda/patch_realtek.c
501 ++++ b/sound/pci/hda/patch_realtek.c
502 +@@ -432,6 +432,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
503 + imux = &spec->input_mux[mux_idx];
504 + if (!imux->num_items && mux_idx > 0)
505 + imux = &spec->input_mux[0];
506 ++ if (!imux->num_items)
507 ++ return 0;
508 +
509 + type = get_wcaps_type(get_wcaps(codec, nid));
510 + if (type == AC_WID_AUD_MIX) {
511 +diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
512 +index 1a5ff06..b11ee62 100644
513 +--- a/sound/pci/sis7019.c
514 ++++ b/sound/pci/sis7019.c
515 +@@ -40,6 +40,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}");
516 + static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
517 + static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
518 + static int enable = 1;
519 ++static int codecs = 1;
520 +
521 + module_param(index, int, 0444);
522 + MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator.");
523 +@@ -47,6 +48,8 @@ module_param(id, charp, 0444);
524 + MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator.");
525 + module_param(enable, bool, 0444);
526 + MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator.");
527 ++module_param(codecs, int, 0444);
528 ++MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)");
529 +
530 + static struct pci_device_id snd_sis7019_ids[] = {
531 + { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) },
532 +@@ -139,6 +142,9 @@ struct sis7019 {
533 + dma_addr_t silence_dma_addr;
534 + };
535 +
536 ++/* These values are also used by the module param 'codecs' to indicate
537 ++ * which codecs should be present.
538 ++ */
539 + #define SIS_PRIMARY_CODEC_PRESENT 0x0001
540 + #define SIS_SECONDARY_CODEC_PRESENT 0x0002
541 + #define SIS_TERTIARY_CODEC_PRESENT 0x0004
542 +@@ -1075,6 +1081,7 @@ static int sis_chip_init(struct sis7019 *sis)
543 + {
544 + unsigned long io = sis->ioport;
545 + void __iomem *ioaddr = sis->ioaddr;
546 ++ unsigned long timeout;
547 + u16 status;
548 + int count;
549 + int i;
550 +@@ -1101,21 +1108,45 @@ static int sis_chip_init(struct sis7019 *sis)
551 + while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
552 + udelay(1);
553 +
554 ++ /* Command complete, we can let go of the semaphore now.
555 ++ */
556 ++ outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
557 ++ if (!count)
558 ++ return -EIO;
559 ++
560 + /* Now that we've finished the reset, find out what's attached.
561 ++ * There are some codec/board combinations that take an extremely
562 ++ * long time to come up. 350+ ms has been observed in the field,
563 ++ * so we'll give them up to 500ms.
564 + */
565 +- status = inl(io + SIS_AC97_STATUS);
566 +- if (status & SIS_AC97_STATUS_CODEC_READY)
567 +- sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT;
568 +- if (status & SIS_AC97_STATUS_CODEC2_READY)
569 +- sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT;
570 +- if (status & SIS_AC97_STATUS_CODEC3_READY)
571 +- sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT;
572 +-
573 +- /* All done, let go of the semaphore, and check for errors
574 ++ sis->codecs_present = 0;
575 ++ timeout = msecs_to_jiffies(500) + jiffies;
576 ++ while (time_before_eq(jiffies, timeout)) {
577 ++ status = inl(io + SIS_AC97_STATUS);
578 ++ if (status & SIS_AC97_STATUS_CODEC_READY)
579 ++ sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT;
580 ++ if (status & SIS_AC97_STATUS_CODEC2_READY)
581 ++ sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT;
582 ++ if (status & SIS_AC97_STATUS_CODEC3_READY)
583 ++ sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT;
584 ++
585 ++ if (sis->codecs_present == codecs)
586 ++ break;
587 ++
588 ++ msleep(1);
589 ++ }
590 ++
591 ++ /* All done, check for errors.
592 + */
593 +- outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
594 +- if (!sis->codecs_present || !count)
595 ++ if (!sis->codecs_present) {
596 ++ printk(KERN_ERR "sis7019: could not find any codecs\n");
597 + return -EIO;
598 ++ }
599 ++
600 ++ if (sis->codecs_present != codecs) {
601 ++ printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n",
602 ++ sis->codecs_present, codecs);
603 ++ }
604 +
605 + /* Let the hardware know that the audio driver is alive,
606 + * and enable PCM slots on the AC-link for L/R playback (3 & 4) and
607 +@@ -1387,6 +1418,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci,
608 + if (!enable)
609 + goto error_out;
610 +
611 ++ /* The user can specify which codecs should be present so that we
612 ++ * can wait for them to show up if they are slow to recover from
613 ++ * the AC97 cold reset. We default to a single codec, the primary.
614 ++ *
615 ++ * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2.
616 ++ */
617 ++ codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT |
618 ++ SIS_TERTIARY_CODEC_PRESENT;
619 ++ if (!codecs)
620 ++ codecs = SIS_PRIMARY_CODEC_PRESENT;
621 ++
622 + rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card);
623 + if (rc < 0)
624 + goto error_out;