Gentoo Archives: gentoo-commits

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