Skip to content

Commit 3ee8da8

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: ALSA: hda - Fix the cmd cache keys for amp verbs ALSA: add missing definitions(letters) to HD-Audio.txt ALSA: hda - Add quirk mask for Fujitsu Amilo laptops with ALC883 [ALSA] intel8x0: add one retry to the ac97_clock measurement routine [ALSA] intel8x0: fix wrong conditions in ac97_clock measure routine ALSA: hda - Avoid call of snd_jack_report at release ALSA: add private_data to struct snd_jack ALSA: snd-usb-caiaq: rename files to remove redundant information in file pathes ALSA: snd-usb-caiaq: clean up header includes ALSA: sound/pci: use memdup_user() ALSA: sound/usb: use memdup_user() ALSA: sound/isa: use memdup_user() ALSA: sound/core: use memdup_user() [ALSA] intel8x0: do not use zero value from PICB register [ALSA] intel8x0: an attempt to make ac97_clock measurement more reliable [ALSA] pcm-midlevel: Add more strict buffer position checks based on jiffies [ALSA] hda_intel: fix unexpected ring buffer positions ASoC: Disable S3C64xx support in Kconfig ASoC: magician: remove un-necessary #include of pxa-regs.h and hardware.h
2 parents a2c252e + 9dd175f commit 3ee8da8

35 files changed

+317
-279
lines changed

Documentation/sound/alsa/HD-Audio.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,15 @@ PCI SSID look-up.
169169
What `model` option values are available depends on the codec chip.
170170
Check your codec chip from the codec proc file (see "Codec Proc-File"
171171
section below). It will show the vendor/product name of your codec
172-
chip. Then, see Documentation/sound/alsa/HD-Audio-Modelstxt file,
172+
chip. Then, see Documentation/sound/alsa/HD-Audio-Models.txt file,
173173
the section of HD-audio driver. You can find a list of codecs
174174
and `model` options belonging to each codec. For example, for Realtek
175175
ALC262 codec chip, pass `model=ultra` for devices that are compatible
176176
with Samsung Q1 Ultra.
177177

178178
Thus, the first thing you can do for any brand-new, unsupported and
179179
non-working HD-audio hardware is to check HD-audio codec and several
180-
different `model` option values. If you have a luck, some of them
180+
different `model` option values. If you have any luck, some of them
181181
might suit with your device well.
182182

183183
Some codecs such as ALC880 have a special model option `model=test`.

include/sound/jack.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ struct snd_jack {
5050
int type;
5151
const char *id;
5252
char name[100];
53+
void *private_data;
54+
void (*private_free)(struct snd_jack *);
5355
};
5456

5557
#ifdef CONFIG_SND_JACK

include/sound/pcm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,8 @@ struct snd_pcm_runtime {
268268
int overrange;
269269
snd_pcm_uframes_t avail_max;
270270
snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
271-
snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
271+
snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
272+
unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
272273

273274
/* -- HW params -- */
274275
snd_pcm_access_t access; /* access mode */

sound/core/control.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -723,14 +723,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,
723723
{
724724
struct snd_ctl_elem_value *control;
725725
int result;
726-
727-
control = kmalloc(sizeof(*control), GFP_KERNEL);
728-
if (control == NULL)
729-
return -ENOMEM;
730-
if (copy_from_user(control, _control, sizeof(*control))) {
731-
kfree(control);
732-
return -EFAULT;
733-
}
726+
727+
control = memdup_user(_control, sizeof(*control));
728+
if (IS_ERR(control))
729+
return PTR_ERR(control);
730+
734731
snd_power_lock(card);
735732
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
736733
if (result >= 0)
@@ -784,13 +781,10 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
784781
struct snd_card *card;
785782
int result;
786783

787-
control = kmalloc(sizeof(*control), GFP_KERNEL);
788-
if (control == NULL)
789-
return -ENOMEM;
790-
if (copy_from_user(control, _control, sizeof(*control))) {
791-
kfree(control);
792-
return -EFAULT;
793-
}
784+
control = memdup_user(_control, sizeof(*control));
785+
if (IS_ERR(control))
786+
return PTR_ERR(control);
787+
794788
card = file->card;
795789
snd_power_lock(card);
796790
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
@@ -916,13 +910,10 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
916910
if (op_flag > 0) {
917911
if (size > 1024 * 128) /* sane value */
918912
return -EINVAL;
919-
new_data = kmalloc(size, GFP_KERNEL);
920-
if (new_data == NULL)
921-
return -ENOMEM;
922-
if (copy_from_user(new_data, tlv, size)) {
923-
kfree(new_data);
924-
return -EFAULT;
925-
}
913+
914+
new_data = memdup_user(tlv, size);
915+
if (IS_ERR(new_data))
916+
return PTR_ERR(new_data);
926917
change = ue->tlv_data_size != size;
927918
if (!change)
928919
change = memcmp(ue->tlv_data, new_data, size);

sound/core/jack.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ static int snd_jack_dev_free(struct snd_device *device)
3535
{
3636
struct snd_jack *jack = device->device_data;
3737

38+
if (jack->private_free)
39+
jack->private_free(jack);
40+
3841
/* If the input device is registered with the input subsystem
3942
* then we need to use a different deallocator. */
4043
if (jack->registered)

sound/core/pcm_compat.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,11 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
232232
if (! (runtime = substream->runtime))
233233
return -ENOTTY;
234234

235-
data = kmalloc(sizeof(*data), GFP_KERNEL);
236-
if (data == NULL)
237-
return -ENOMEM;
238235
/* only fifo_size is different, so just copy all */
239-
if (copy_from_user(data, data32, sizeof(*data32))) {
240-
err = -EFAULT;
241-
goto error;
242-
}
236+
data = memdup_user(data32, sizeof(*data32));
237+
if (IS_ERR(data))
238+
return PTR_ERR(data);
239+
243240
if (refine)
244241
err = snd_pcm_hw_refine(substream, data);
245242
else

sound/core/pcm_lib.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,11 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
209209
{
210210
struct snd_pcm_runtime *runtime = substream->runtime;
211211
snd_pcm_uframes_t pos;
212-
snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
213-
snd_pcm_sframes_t delta;
212+
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base;
213+
snd_pcm_sframes_t hdelta, delta;
214+
unsigned long jdelta;
214215

216+
old_hw_ptr = runtime->status->hw_ptr;
215217
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
216218
if (pos == SNDRV_PCM_POS_XRUN) {
217219
xrun(substream);
@@ -247,7 +249,30 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
247249
new_hw_ptr = hw_base + pos;
248250
}
249251
}
250-
if (delta > runtime->period_size) {
252+
hdelta = new_hw_ptr - old_hw_ptr;
253+
jdelta = jiffies - runtime->hw_ptr_jiffies;
254+
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
255+
delta = jdelta /
256+
(((runtime->period_size * HZ) / runtime->rate)
257+
+ HZ/100);
258+
hw_ptr_error(substream,
259+
"hw_ptr skipping! [Q] "
260+
"(pos=%ld, delta=%ld, period=%ld, "
261+
"jdelta=%lu/%lu/%lu)\n",
262+
(long)pos, (long)hdelta,
263+
(long)runtime->period_size, jdelta,
264+
((hdelta * HZ) / runtime->rate), delta);
265+
hw_ptr_interrupt = runtime->hw_ptr_interrupt +
266+
runtime->period_size * delta;
267+
if (hw_ptr_interrupt >= runtime->boundary)
268+
hw_ptr_interrupt -= runtime->boundary;
269+
/* rebase to interrupt position */
270+
hw_base = new_hw_ptr = hw_ptr_interrupt;
271+
/* align hw_base to buffer_size */
272+
hw_base -= hw_base % runtime->buffer_size;
273+
delta = 0;
274+
}
275+
if (delta > runtime->period_size + runtime->period_size / 2) {
251276
hw_ptr_error(substream,
252277
"Lost interrupts? "
253278
"(stream=%i, delta=%ld, intr_ptr=%ld)\n",
@@ -263,6 +288,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
263288

264289
runtime->hw_ptr_base = hw_base;
265290
runtime->status->hw_ptr = new_hw_ptr;
291+
runtime->hw_ptr_jiffies = jiffies;
266292
runtime->hw_ptr_interrupt = hw_ptr_interrupt;
267293

268294
return snd_pcm_update_hw_ptr_post(substream, runtime);
@@ -275,6 +301,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
275301
snd_pcm_uframes_t pos;
276302
snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
277303
snd_pcm_sframes_t delta;
304+
unsigned long jdelta;
278305

279306
old_hw_ptr = runtime->status->hw_ptr;
280307
pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
@@ -286,27 +313,29 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
286313
new_hw_ptr = hw_base + pos;
287314

288315
delta = new_hw_ptr - old_hw_ptr;
316+
jdelta = jiffies - runtime->hw_ptr_jiffies;
289317
if (delta < 0) {
290318
delta += runtime->buffer_size;
291319
if (delta < 0) {
292320
hw_ptr_error(substream,
293321
"Unexpected hw_pointer value [2] "
294-
"(stream=%i, pos=%ld, old_ptr=%ld)\n",
322+
"(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n",
295323
substream->stream, (long)pos,
296-
(long)old_hw_ptr);
324+
(long)old_hw_ptr, jdelta);
297325
return 0;
298326
}
299327
hw_base += runtime->buffer_size;
300328
if (hw_base >= runtime->boundary)
301329
hw_base = 0;
302330
new_hw_ptr = hw_base + pos;
303331
}
304-
if (delta > runtime->period_size && runtime->periods > 1) {
332+
if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
305333
hw_ptr_error(substream,
306334
"hw_ptr skipping! "
307-
"(pos=%ld, delta=%ld, period=%ld)\n",
335+
"(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
308336
(long)pos, (long)delta,
309-
(long)runtime->period_size);
337+
(long)runtime->period_size, jdelta,
338+
((delta * HZ) / runtime->rate));
310339
return 0;
311340
}
312341
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
@@ -315,6 +344,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
315344

316345
runtime->hw_ptr_base = hw_base;
317346
runtime->status->hw_ptr = new_hw_ptr;
347+
runtime->hw_ptr_jiffies = jiffies;
318348

319349
return snd_pcm_update_hw_ptr_post(substream, runtime);
320350
}
@@ -1441,6 +1471,7 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
14411471
runtime->status->hw_ptr %= runtime->buffer_size;
14421472
else
14431473
runtime->status->hw_ptr = 0;
1474+
runtime->hw_ptr_jiffies = jiffies;
14441475
snd_pcm_stream_unlock_irqrestore(substream, flags);
14451476
return 0;
14461477
}

sound/core/pcm_native.c

Lines changed: 35 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -327,21 +327,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
327327
struct snd_pcm_hw_params *params;
328328
int err;
329329

330-
params = kmalloc(sizeof(*params), GFP_KERNEL);
331-
if (!params) {
332-
err = -ENOMEM;
333-
goto out;
334-
}
335-
if (copy_from_user(params, _params, sizeof(*params))) {
336-
err = -EFAULT;
337-
goto out;
338-
}
330+
params = memdup_user(_params, sizeof(*params));
331+
if (IS_ERR(params))
332+
return PTR_ERR(params);
333+
339334
err = snd_pcm_hw_refine(substream, params);
340335
if (copy_to_user(_params, params, sizeof(*params))) {
341336
if (!err)
342337
err = -EFAULT;
343338
}
344-
out:
339+
345340
kfree(params);
346341
return err;
347342
}
@@ -465,21 +460,16 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
465460
struct snd_pcm_hw_params *params;
466461
int err;
467462

468-
params = kmalloc(sizeof(*params), GFP_KERNEL);
469-
if (!params) {
470-
err = -ENOMEM;
471-
goto out;
472-
}
473-
if (copy_from_user(params, _params, sizeof(*params))) {
474-
err = -EFAULT;
475-
goto out;
476-
}
463+
params = memdup_user(_params, sizeof(*params));
464+
if (IS_ERR(params))
465+
return PTR_ERR(params);
466+
477467
err = snd_pcm_hw_params(substream, params);
478468
if (copy_to_user(_params, params, sizeof(*params))) {
479469
if (!err)
480470
err = -EFAULT;
481471
}
482-
out:
472+
483473
kfree(params);
484474
return err;
485475
}
@@ -2593,13 +2583,11 @@ static int snd_pcm_playback_ioctl1(struct file *file,
25932583
return -EFAULT;
25942584
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
25952585
return -EFAULT;
2596-
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
2597-
if (bufs == NULL)
2598-
return -ENOMEM;
2599-
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
2600-
kfree(bufs);
2601-
return -EFAULT;
2602-
}
2586+
2587+
bufs = memdup_user(xfern.bufs,
2588+
sizeof(void *) * runtime->channels);
2589+
if (IS_ERR(bufs))
2590+
return PTR_ERR(bufs);
26032591
result = snd_pcm_lib_writev(substream, bufs, xfern.frames);
26042592
kfree(bufs);
26052593
__put_user(result, &_xfern->result);
@@ -2675,13 +2663,11 @@ static int snd_pcm_capture_ioctl1(struct file *file,
26752663
return -EFAULT;
26762664
if (copy_from_user(&xfern, _xfern, sizeof(xfern)))
26772665
return -EFAULT;
2678-
bufs = kmalloc(sizeof(void *) * runtime->channels, GFP_KERNEL);
2679-
if (bufs == NULL)
2680-
return -ENOMEM;
2681-
if (copy_from_user(bufs, xfern.bufs, sizeof(void *) * runtime->channels)) {
2682-
kfree(bufs);
2683-
return -EFAULT;
2684-
}
2666+
2667+
bufs = memdup_user(xfern.bufs,
2668+
sizeof(void *) * runtime->channels);
2669+
if (IS_ERR(bufs))
2670+
return PTR_ERR(bufs);
26852671
result = snd_pcm_lib_readv(substream, bufs, xfern.frames);
26862672
kfree(bufs);
26872673
__put_user(result, &_xfern->result);
@@ -3312,18 +3298,12 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
33123298
int err;
33133299

33143300
params = kmalloc(sizeof(*params), GFP_KERNEL);
3315-
if (!params) {
3316-
err = -ENOMEM;
3317-
goto out;
3318-
}
3319-
oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
3320-
if (!oparams) {
3321-
err = -ENOMEM;
3322-
goto out;
3323-
}
3301+
if (!params)
3302+
return -ENOMEM;
33243303

3325-
if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
3326-
err = -EFAULT;
3304+
oparams = memdup_user(_oparams, sizeof(*oparams));
3305+
if (IS_ERR(oparams)) {
3306+
err = PTR_ERR(oparams);
33273307
goto out;
33283308
}
33293309
snd_pcm_hw_convert_from_old_params(params, oparams);
@@ -3333,9 +3313,10 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
33333313
if (!err)
33343314
err = -EFAULT;
33353315
}
3316+
3317+
kfree(oparams);
33363318
out:
33373319
kfree(params);
3338-
kfree(oparams);
33393320
return err;
33403321
}
33413322

@@ -3347,17 +3328,12 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
33473328
int err;
33483329

33493330
params = kmalloc(sizeof(*params), GFP_KERNEL);
3350-
if (!params) {
3351-
err = -ENOMEM;
3352-
goto out;
3353-
}
3354-
oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
3355-
if (!oparams) {
3356-
err = -ENOMEM;
3357-
goto out;
3358-
}
3359-
if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
3360-
err = -EFAULT;
3331+
if (!params)
3332+
return -ENOMEM;
3333+
3334+
oparams = memdup_user(_oparams, sizeof(*oparams));
3335+
if (IS_ERR(oparams)) {
3336+
err = PTR_ERR(oparams);
33613337
goto out;
33623338
}
33633339
snd_pcm_hw_convert_from_old_params(params, oparams);
@@ -3367,9 +3343,10 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
33673343
if (!err)
33683344
err = -EFAULT;
33693345
}
3346+
3347+
kfree(oparams);
33703348
out:
33713349
kfree(params);
3372-
kfree(oparams);
33733350
return err;
33743351
}
33753352
#endif /* CONFIG_SND_SUPPORT_OLD_API */

0 commit comments

Comments
 (0)