Commit 13e242be authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA update

  - added SNDRV_PCM_IOCTL_HWSYNC ioctl
  - changed behaviour of read/write/poll functions
    - prefer waiting than return an error code
  - removed snd_seq_sleep_timeout_in_lock and snd_seq_sleep_in_lock helpers
parent a69156f1
......@@ -129,7 +129,7 @@ enum {
* *
*****************************************************************************/
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3)
typedef unsigned long sndrv_pcm_uframes_t;
typedef long sndrv_pcm_sframes_t;
......@@ -423,6 +423,7 @@ enum {
SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct sndrv_pcm_sw_params),
SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct sndrv_pcm_status),
SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, sndrv_pcm_sframes_t),
SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct sndrv_pcm_channel_info),
SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
......
......@@ -1854,16 +1854,11 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED ||
runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (((avail < runtime->control->avail_min && size > avail) ||
if (((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align))) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -1880,9 +1875,12 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN:
......@@ -1928,10 +1926,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(snd_pcm_substream_t *substream,
cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
if (frames > cont)
frames = cont;
if (frames == 0 && runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
err = -EPIPE;
goto _end_unlock;
}
snd_assert(frames != 0,
spin_unlock_irq(&runtime->lock);
return -EINVAL);
......@@ -2147,21 +2141,16 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
err = -EPIPE;
goto _end_unlock;
}
} else if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (avail < runtime->xfer_align) {
runtime->status->state = SNDRV_PCM_STATE_SETUP;
err = -EPIPE;
goto _end_unlock;
}
} else if ((avail < runtime->control->avail_min && size > avail) ||
(size >= runtime->xfer_align && avail < runtime->xfer_align)) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED } state;
if (nonblock) {
err = -EAGAIN;
goto _end_unlock;
......@@ -2178,9 +2167,12 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(snd_pcm_substream_t *substream, void
spin_unlock_irq(&runtime->lock);
if (schedule_timeout(10 * HZ) == 0) {
spin_lock_irq(&runtime->lock);
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED &&
runtime->status->state != SNDRV_PCM_STATE_PAUSED) {
state = runtime->status->state == SNDRV_PCM_STATE_SUSPENDED ? SUSPENDED : EXPIRED;
break;
}
}
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_XRUN:
......
......@@ -1962,34 +1962,29 @@ snd_pcm_sframes_t snd_pcm_capture_rewind(snd_pcm_substream_t *substream, snd_pcm
return ret;
}
static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_hwsync(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
snd_pcm_sframes_t n;
int err;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_DRAINING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
break;
} else {
err = SNDRV_PCM_STATE_RUNNING ? -EPIPE : -EBADFD;
}
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
/* Fall through */
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
n = snd_pcm_playback_hw_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
err = 0;
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
......@@ -1997,34 +1992,36 @@ static int snd_pcm_playback_delay(snd_pcm_substream_t *substream, snd_pcm_sframe
return err;
}
static int snd_pcm_capture_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
static int snd_pcm_delay(snd_pcm_substream_t *substream, snd_pcm_sframes_t *res)
{
snd_pcm_runtime_t *runtime = substream->runtime;
int err = 0;
int err;
snd_pcm_sframes_t n;
spin_lock_irq(&runtime->lock);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
goto __badfd;
case SNDRV_PCM_STATE_RUNNING:
if (snd_pcm_update_hw_ptr(substream) >= 0) {
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
break;
}
/* Fall through */
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_SUSPENDED:
if (runtime->status->suspended_state == SNDRV_PCM_STATE_RUNNING) {
err = 0;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
if (put_user(n, res))
err = -EFAULT;
} else {
err = -EBADFD;
}
break;
case SNDRV_PCM_STATE_XRUN:
err = -EPIPE;
break;
default:
__badfd:
err = -EBADFD;
break;
}
......@@ -2079,6 +2076,10 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_resume(substream);
case SNDRV_PCM_IOCTL_XRUN:
return snd_pcm_xrun(substream);
case SNDRV_PCM_IOCTL_HWSYNC:
return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_delay(substream, (snd_pcm_sframes_t *) arg);
case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
return snd_pcm_hw_refine_old_user(substream, (struct sndrv_pcm_hw_params_old *) arg);
case SNDRV_PCM_IOCTL_HW_PARAMS_OLD:
......@@ -2159,8 +2160,6 @@ static int snd_pcm_playback_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_playback_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_playback_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_playback_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2228,8 +2227,6 @@ static int snd_pcm_capture_ioctl1(snd_pcm_substream_t *substream,
return snd_pcm_capture_drain(substream);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_capture_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
return snd_pcm_capture_delay(substream, (snd_pcm_sframes_t*) arg);
}
return snd_pcm_common_ioctl1(substream, cmd, arg);
}
......@@ -2326,7 +2323,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
snd_pcm_runtime_t *runtime;
snd_pcm_sframes_t result;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
up(&file->f_dentry->d_inode->i_sem);
#endif
pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
substream = pcm_file->substream;
snd_assert(substream != NULL, result = -ENXIO; goto end);
......@@ -2344,7 +2343,9 @@ static ssize_t snd_pcm_write(struct file *file, const char *buf, size_t count, l
if (result > 0)
result = frames_to_bytes(runtime, result);
end:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
down(&file->f_dentry->d_inode->i_sem);
#endif
return result;
}
......@@ -2449,6 +2450,8 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
avail = snd_pcm_playback_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLOUT | POLLWRNORM;
break;
......@@ -2457,12 +2460,6 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
case SNDRV_PCM_STATE_DRAINING:
mask = 0;
break;
case SNDRV_PCM_STATE_PREPARED:
if (avail > 0) {
mask = POLLOUT | POLLWRNORM;
break;
}
/* Fall through */
default:
mask = POLLOUT | POLLWRNORM | POLLERR;
break;
......@@ -2491,6 +2488,8 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
avail = snd_pcm_capture_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = POLLIN | POLLRDNORM;
break;
......
......@@ -159,9 +159,10 @@ snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
spin_lock_irqsave(&q->lock, *rflags);
if (q->qlen == 0) {
if (blocking) {
snd_seq_sleep_timeout_in_lock(&q->midi_sleep,
&q->lock,
spin_unlock(&q->lock);
interruptible_sleep_on_timeout(&q->midi_sleep,
q->pre_event_timeout);
spin_lock(&q->lock);
}
if (q->qlen == 0) {
spin_unlock_irqrestore(&q->lock, *rflags);
......
......@@ -122,7 +122,9 @@ snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
}
/* wait for echo event */
snd_seq_sleep_timeout_in_lock(&q->sync_sleep, &q->sync_lock, HZ);
spin_unlock(&q->sync_lock);
interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
spin_lock(&q->sync_lock);
if (signal_pending(current)) {
/* interrupted - return 0 to finish sync */
q->sync_event_put = 0;
......
......@@ -135,7 +135,7 @@ EXPORT_SYMBOL(snd_seq_event_port_attach);
EXPORT_SYMBOL(snd_seq_event_port_detach);
/* seq_lock.c */
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
EXPORT_SYMBOL(snd_seq_sleep_in_lock);
EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);
/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
EXPORT_SYMBOL(snd_use_lock_sync_helper);
#endif
......@@ -182,7 +182,9 @@ int snd_seq_fifo_cell_out(fifo_t *f, snd_seq_event_cell_t **cellp, int nonblock)
spin_unlock_irqrestore(&f->lock, flags);
return -EAGAIN;
}
snd_seq_sleep_in_lock(&f->input_sleep, &f->lock);
spin_unlock(&f->lock);
interruptible_sleep_on(&f->input_sleep);
spin_lock(&f->lock);
if (signal_pending(current)) {
spin_unlock_irqrestore(&f->lock, flags);
......
......@@ -25,6 +25,7 @@
#if defined(__SMP__) || defined(CONFIG_SND_DEBUG)
#if 0 /* NOT USED */
/* (interruptible) sleep_on during the specified spinlock */
void snd_seq_sleep_in_lock(wait_queue_head_t *p, spinlock_t *lock)
{
......@@ -60,6 +61,7 @@ long snd_seq_sleep_timeout_in_lock(wait_queue_head_t *p, spinlock_t *lock, long
return timeout;
}
#endif /* NOT USED */
/* wait until all locks are released */
void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
......
......@@ -20,12 +20,6 @@ typedef atomic_t snd_use_lock_t;
void snd_use_lock_sync_helper(snd_use_lock_t *lock, const char *file, int line);
#define snd_use_lock_sync(lockp) snd_use_lock_sync_helper(lockp, __BASE_FILE__, __LINE__)
/* (interruptible) sleep_on during the specified spinlock */
void snd_seq_sleep_in_lock(wait_queue_head_t *p, spinlock_t *lock);
/* (interruptible) sleep_on with timeout during the specified spinlock */
long snd_seq_sleep_timeout_in_lock(wait_queue_head_t *p, spinlock_t *lock, long timeout);
#else /* SMP || CONFIG_SND_DEBUG */
typedef spinlock_t snd_use_lock_t; /* dummy */
......@@ -34,9 +28,6 @@ typedef spinlock_t snd_use_lock_t; /* dummy */
#define snd_use_lock_free(lockp) /**/
#define snd_use_lock_sync(lockp) /**/
#define snd_seq_sleep_in_lock(p,lock) interruptible_sleep_on(p)
#define snd_seq_sleep_timeout_in_lock(p,lock,timeout) interruptible_sleep_on_timeout(p,timeout)
#endif /* SMP || CONFIG_SND_DEBUG */
#endif /* __SND_SEQ_LOCK_H */
......@@ -233,17 +233,21 @@ int snd_seq_cell_alloc(pool_t *pool, snd_seq_event_cell_t **cellp, int nonblock,
goto __error;
}
while (pool->free == NULL && ! nonblock && ! pool->closing) {
spin_unlock(&pool->lock);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
/* change semaphore to allow other clients
to access device file */
if (file)
up(&semaphore_of(file));
snd_seq_sleep_in_lock(&pool->output_sleep, &pool->lock);
#endif
interruptible_sleep_on(&pool->output_sleep);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
/* restore semaphore again */
if (file)
down(&semaphore_of(file));
#endif
spin_lock(&pool->lock);
/* interrupted? */
if (signal_pending(current)) {
err = -ERESTARTSYS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment