diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-11-01 05:11:07 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-11-01 05:11:07 -0500 |
commit | e87a3dd33eab30b4db539500064a9584867e4f2c (patch) | |
tree | 2f7ad16e46ae30518ff63bb5391b63f7f7cc74dd /sound/core | |
parent | b14f5de731ae657d498d18d713c6431bfbeefb4b (diff) | |
parent | 3d00941371a765779c4e3509214c7e5793cce1fe (diff) |
Merge branch 'fix/misc' into topic/misc
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/pcm.c | 5 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 81 |
2 files changed, 27 insertions, 59 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 0c1440121c22..c69c60b2a48a 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -953,11 +953,12 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
953 | struct snd_pcm_substream *substream; | 953 | struct snd_pcm_substream *substream; |
954 | struct snd_pcm_notify *notify; | 954 | struct snd_pcm_notify *notify; |
955 | char str[16]; | 955 | char str[16]; |
956 | struct snd_pcm *pcm = device->device_data; | 956 | struct snd_pcm *pcm; |
957 | struct device *dev; | 957 | struct device *dev; |
958 | 958 | ||
959 | if (snd_BUG_ON(!pcm || !device)) | 959 | if (snd_BUG_ON(!device || !device->device_data)) |
960 | return -ENXIO; | 960 | return -ENXIO; |
961 | pcm = device->device_data; | ||
961 | mutex_lock(®ister_mutex); | 962 | mutex_lock(®ister_mutex); |
962 | err = snd_pcm_add(pcm); | 963 | err = snd_pcm_add(pcm); |
963 | if (err) { | 964 | if (err) { |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59e5fbe6af51..ab73edf2c89a 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1387,11 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = { | |||
1387 | .post_action = snd_pcm_post_drain_init | 1387 | .post_action = snd_pcm_post_drain_init |
1388 | }; | 1388 | }; |
1389 | 1389 | ||
1390 | struct drain_rec { | ||
1391 | struct snd_pcm_substream *substream; | ||
1392 | wait_queue_t wait; | ||
1393 | }; | ||
1394 | |||
1395 | static int snd_pcm_drop(struct snd_pcm_substream *substream); | 1390 | static int snd_pcm_drop(struct snd_pcm_substream *substream); |
1396 | 1391 | ||
1397 | /* | 1392 | /* |
@@ -1407,10 +1402,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1407 | struct snd_card *card; | 1402 | struct snd_card *card; |
1408 | struct snd_pcm_runtime *runtime; | 1403 | struct snd_pcm_runtime *runtime; |
1409 | struct snd_pcm_substream *s; | 1404 | struct snd_pcm_substream *s; |
1405 | wait_queue_t wait; | ||
1410 | int result = 0; | 1406 | int result = 0; |
1411 | int i, num_drecs; | ||
1412 | int nonblock = 0; | 1407 | int nonblock = 0; |
1413 | struct drain_rec *drec, drec_tmp, *d; | ||
1414 | 1408 | ||
1415 | card = substream->pcm->card; | 1409 | card = substream->pcm->card; |
1416 | runtime = substream->runtime; | 1410 | runtime = substream->runtime; |
@@ -1433,38 +1427,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1433 | } else if (substream->f_flags & O_NONBLOCK) | 1427 | } else if (substream->f_flags & O_NONBLOCK) |
1434 | nonblock = 1; | 1428 | nonblock = 1; |
1435 | 1429 | ||
1436 | if (nonblock) | ||
1437 | goto lock; /* no need to allocate waitqueues */ | ||
1438 | |||
1439 | /* allocate temporary record for drain sync */ | ||
1440 | down_read(&snd_pcm_link_rwsem); | 1430 | down_read(&snd_pcm_link_rwsem); |
1441 | if (snd_pcm_stream_linked(substream)) { | ||
1442 | drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL); | ||
1443 | if (! drec) { | ||
1444 | up_read(&snd_pcm_link_rwsem); | ||
1445 | snd_power_unlock(card); | ||
1446 | return -ENOMEM; | ||
1447 | } | ||
1448 | } else | ||
1449 | drec = &drec_tmp; | ||
1450 | |||
1451 | /* count only playback streams */ | ||
1452 | num_drecs = 0; | ||
1453 | snd_pcm_group_for_each_entry(s, substream) { | ||
1454 | runtime = s->runtime; | ||
1455 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
1456 | d = &drec[num_drecs++]; | ||
1457 | d->substream = s; | ||
1458 | init_waitqueue_entry(&d->wait, current); | ||
1459 | add_wait_queue(&runtime->sleep, &d->wait); | ||
1460 | } | ||
1461 | } | ||
1462 | up_read(&snd_pcm_link_rwsem); | ||
1463 | |||
1464 | lock: | ||
1465 | snd_pcm_stream_lock_irq(substream); | 1431 | snd_pcm_stream_lock_irq(substream); |
1466 | /* resume pause */ | 1432 | /* resume pause */ |
1467 | if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) | 1433 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) |
1468 | snd_pcm_pause(substream, 0); | 1434 | snd_pcm_pause(substream, 0); |
1469 | 1435 | ||
1470 | /* pre-start/stop - all running streams are changed to DRAINING state */ | 1436 | /* pre-start/stop - all running streams are changed to DRAINING state */ |
@@ -1479,25 +1445,35 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1479 | 1445 | ||
1480 | for (;;) { | 1446 | for (;;) { |
1481 | long tout; | 1447 | long tout; |
1448 | struct snd_pcm_runtime *to_check; | ||
1482 | if (signal_pending(current)) { | 1449 | if (signal_pending(current)) { |
1483 | result = -ERESTARTSYS; | 1450 | result = -ERESTARTSYS; |
1484 | break; | 1451 | break; |
1485 | } | 1452 | } |
1486 | /* all finished? */ | 1453 | /* find a substream to drain */ |
1487 | for (i = 0; i < num_drecs; i++) { | 1454 | to_check = NULL; |
1488 | runtime = drec[i].substream->runtime; | 1455 | snd_pcm_group_for_each_entry(s, substream) { |
1489 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) | 1456 | if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) |
1457 | continue; | ||
1458 | runtime = s->runtime; | ||
1459 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | ||
1460 | to_check = runtime; | ||
1490 | break; | 1461 | break; |
1462 | } | ||
1491 | } | 1463 | } |
1492 | if (i == num_drecs) | 1464 | if (!to_check) |
1493 | break; /* yes, all drained */ | 1465 | break; /* all drained */ |
1494 | 1466 | init_waitqueue_entry(&wait, current); | |
1467 | add_wait_queue(&to_check->sleep, &wait); | ||
1495 | set_current_state(TASK_INTERRUPTIBLE); | 1468 | set_current_state(TASK_INTERRUPTIBLE); |
1496 | snd_pcm_stream_unlock_irq(substream); | 1469 | snd_pcm_stream_unlock_irq(substream); |
1470 | up_read(&snd_pcm_link_rwsem); | ||
1497 | snd_power_unlock(card); | 1471 | snd_power_unlock(card); |
1498 | tout = schedule_timeout(10 * HZ); | 1472 | tout = schedule_timeout(10 * HZ); |
1499 | snd_power_lock(card); | 1473 | snd_power_lock(card); |
1474 | down_read(&snd_pcm_link_rwsem); | ||
1500 | snd_pcm_stream_lock_irq(substream); | 1475 | snd_pcm_stream_lock_irq(substream); |
1476 | remove_wait_queue(&to_check->sleep, &wait); | ||
1501 | if (tout == 0) { | 1477 | if (tout == 0) { |
1502 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | 1478 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
1503 | result = -ESTRPIPE; | 1479 | result = -ESTRPIPE; |
@@ -1512,16 +1488,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1512 | 1488 | ||
1513 | unlock: | 1489 | unlock: |
1514 | snd_pcm_stream_unlock_irq(substream); | 1490 | snd_pcm_stream_unlock_irq(substream); |
1515 | 1491 | up_read(&snd_pcm_link_rwsem); | |
1516 | if (!nonblock) { | ||
1517 | for (i = 0; i < num_drecs; i++) { | ||
1518 | d = &drec[i]; | ||
1519 | runtime = d->substream->runtime; | ||
1520 | remove_wait_queue(&runtime->sleep, &d->wait); | ||
1521 | } | ||
1522 | if (drec != &drec_tmp) | ||
1523 | kfree(drec); | ||
1524 | } | ||
1525 | snd_power_unlock(card); | 1492 | snd_power_unlock(card); |
1526 | 1493 | ||
1527 | return result; | 1494 | return result; |
@@ -3018,7 +2985,7 @@ static int snd_pcm_mmap_status_fault(struct vm_area_struct *area, | |||
3018 | return 0; | 2985 | return 0; |
3019 | } | 2986 | } |
3020 | 2987 | ||
3021 | static struct vm_operations_struct snd_pcm_vm_ops_status = | 2988 | static const struct vm_operations_struct snd_pcm_vm_ops_status = |
3022 | { | 2989 | { |
3023 | .fault = snd_pcm_mmap_status_fault, | 2990 | .fault = snd_pcm_mmap_status_fault, |
3024 | }; | 2991 | }; |
@@ -3057,7 +3024,7 @@ static int snd_pcm_mmap_control_fault(struct vm_area_struct *area, | |||
3057 | return 0; | 3024 | return 0; |
3058 | } | 3025 | } |
3059 | 3026 | ||
3060 | static struct vm_operations_struct snd_pcm_vm_ops_control = | 3027 | static const struct vm_operations_struct snd_pcm_vm_ops_control = |
3061 | { | 3028 | { |
3062 | .fault = snd_pcm_mmap_control_fault, | 3029 | .fault = snd_pcm_mmap_control_fault, |
3063 | }; | 3030 | }; |
@@ -3127,7 +3094,7 @@ static int snd_pcm_mmap_data_fault(struct vm_area_struct *area, | |||
3127 | return 0; | 3094 | return 0; |
3128 | } | 3095 | } |
3129 | 3096 | ||
3130 | static struct vm_operations_struct snd_pcm_vm_ops_data = | 3097 | static const struct vm_operations_struct snd_pcm_vm_ops_data = |
3131 | { | 3098 | { |
3132 | .open = snd_pcm_mmap_data_open, | 3099 | .open = snd_pcm_mmap_data_open, |
3133 | .close = snd_pcm_mmap_data_close, | 3100 | .close = snd_pcm_mmap_data_close, |
@@ -3151,7 +3118,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3151 | * mmap the DMA buffer on I/O memory area | 3118 | * mmap the DMA buffer on I/O memory area |
3152 | */ | 3119 | */ |
3153 | #if SNDRV_PCM_INFO_MMAP_IOMEM | 3120 | #if SNDRV_PCM_INFO_MMAP_IOMEM |
3154 | static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = | 3121 | static const struct vm_operations_struct snd_pcm_vm_ops_data_mmio = |
3155 | { | 3122 | { |
3156 | .open = snd_pcm_mmap_data_open, | 3123 | .open = snd_pcm_mmap_data_open, |
3157 | .close = snd_pcm_mmap_data_close, | 3124 | .close = snd_pcm_mmap_data_close, |