/[linux-patches]/genpatches-2.6/tags/2.6.32-47/1050_linux-2.6.32.51.patch
Gentoo

Contents of /genpatches-2.6/tags/2.6.32-47/1050_linux-2.6.32.51.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20