Commit 4cf7d905 authored by Peter Wächtler's avatar Peter Wächtler Committed by Linus Torvalds

[PATCH] oss/dmabuf.c - convert cli to spinlocks

parent 5790711c
......@@ -199,6 +199,7 @@ static int open_dmap(struct audio_operations *adev, int mode, struct dma_buffpar
return -EBUSY;
}
dma_init_buffers(dmap);
spin_lock_init(&dmap->lock);
dmap->open_mode = mode;
dmap->subdivision = dmap->underrun_count = 0;
dmap->fragment_size = 0;
......@@ -319,7 +320,7 @@ int DMAbuf_open(int dev, int mode)
adev->dmap_out->bytes_in_use);
return 0;
}
/* MUST not hold the spinlock */
void DMAbuf_reset(int dev)
{
if (audio_devs[dev]->open_mode & OPEN_WRITE)
......@@ -341,15 +342,17 @@ static void dma_reset_output(int dev)
/*
* First wait until the current fragment has been played completely
*/
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
adev->dmap_out->flags |= DMA_SYNCING;
adev->dmap_out->underrun_count = 0;
if (!signal_pending(current) && adev->dmap_out->qlen &&
adev->dmap_out->underrun_count == 0)
adev->dmap_out->underrun_count == 0){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
/*
......@@ -366,10 +369,10 @@ static void dma_reset_output(int dev)
disable_dma(dmap->dma);
release_dma_lock(f);
restore_flags(flags);
dmap->byte_counter = 0;
reorganize_buffers(dev, adev->dmap_out, 0);
dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0;
spin_unlock_irqrestore(&dmap->lock,flags);
}
static void dma_reset_input(int dev)
......@@ -378,20 +381,19 @@ static void dma_reset_input(int dev)
unsigned long flags;
struct dma_buffparms *dmap = adev->dmap_in;
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
if (!(adev->flags & DMA_DUPLEX) || !adev->d->halt_input)
adev->d->halt_io(dev);
else
adev->d->halt_input(dev);
adev->dmap_in->flags &= ~DMA_STARTED;
restore_flags(flags);
dmap->qlen = dmap->qhead = dmap->qtail = dmap->user_counter = 0;
dmap->byte_counter = 0;
reorganize_buffers(dev, adev->dmap_in, 1);
spin_unlock_irqrestore(&dmap->lock,flags);
}
/* MUST be called with holding the dmap->lock */
void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -432,8 +434,7 @@ int DMAbuf_sync(int dev)
if (adev->dmap_out->dma_mode == DMODE_OUTPUT) {
dmap = adev->dmap_out;
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
if (dmap->qlen > 0 && !(dmap->flags & DMA_ACTIVE))
DMAbuf_launch_output(dev, dmap);
adev->dmap_out->flags |= DMA_SYNCING;
......@@ -441,31 +442,33 @@ int DMAbuf_sync(int dev)
while (!signal_pending(current) && n++ <= adev->dmap_out->nbufs &&
adev->dmap_out->qlen && adev->dmap_out->underrun_count == 0) {
long t = dmabuf_timeout(dmap);
t = interruptible_sleep_on_timeout(&adev->out_sleeper,
t);
spin_unlock_irqrestore(&dmap->lock,flags);
t = interruptible_sleep_on_timeout(&adev->out_sleeper, t);
spin_lock_irqsave(&dmap->lock,flags);
if (!t) {
adev->dmap_out->flags &= ~DMA_SYNCING;
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return adev->dmap_out->qlen;
}
}
adev->dmap_out->flags &= ~(DMA_SYNCING | DMA_ACTIVE);
restore_flags(flags);
/*
* Some devices such as GUS have huge amount of on board RAM for the
* audio data. We have to wait until the device has finished playing.
*/
save_flags(flags);
cli();
/* still holding the lock */
if (adev->d->local_qlen) { /* Device has hidden buffers */
while (!signal_pending(current) &&
adev->d->local_qlen(dev))
adev->d->local_qlen(dev)){
spin_unlock_irqrestore(&dmap->lock,flags);
interruptible_sleep_on_timeout(&adev->out_sleeper,
dmabuf_timeout(dmap));
spin_lock_irqsave(&dmap->lock,flags);
}
restore_flags(flags);
}
spin_unlock_irqrestore(&dmap->lock,flags);
}
adev->dmap_out->dma_mode = DMODE_NONE;
return adev->dmap_out->qlen;
......@@ -474,23 +477,26 @@ int DMAbuf_sync(int dev)
int DMAbuf_release(int dev, int mode)
{
struct audio_operations *adev = audio_devs[dev];
struct dma_buffparms *dmap;
unsigned long flags;
dmap = adev->dmap_out;
if (adev->open_mode & OPEN_WRITE)
adev->dmap_out->closing = 1;
if (adev->open_mode & OPEN_READ)
adev->dmap_in->closing = 1;
if (adev->open_mode & OPEN_READ){
adev->dmap_in->closing = 1;
dmap = adev->dmap_in;
}
if (adev->open_mode & OPEN_WRITE)
if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED))
if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT))
DMAbuf_sync(dev);
if (adev->dmap_out->dma_mode == DMODE_OUTPUT)
memset(adev->dmap_out->raw_buf, adev->dmap_out->neutral_byte, adev->dmap_out->bytes_in_use);
save_flags(flags);
cli();
DMAbuf_reset(dev);
spin_lock_irqsave(&dmap->lock,flags);
adev->d->close(dev);
if (adev->open_mode & OPEN_WRITE)
......@@ -501,10 +507,10 @@ int DMAbuf_release(int dev, int mode)
(adev->flags & DMA_DUPLEX)))
close_dmap(adev, adev->dmap_in);
adev->open_mode = 0;
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return 0;
}
/* called with dmap->lock dold */
int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -515,8 +521,12 @@ int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap)
if (!(adev->enable_bits & PCM_ENABLE_INPUT))
return 0;
if (dmap->dma_mode == DMODE_OUTPUT) { /* Direction change */
unsigned long flags;
/* release lock - it's not recursive */
spin_unlock_irqrestore(&dmap->lock,flags);
DMAbuf_sync(dev);
DMAbuf_reset(dev);
spin_lock_irqsave(&dmap->lock,flags);
dmap->dma_mode = DMODE_NONE;
}
if (!dmap->dma_mode) {
......@@ -538,7 +548,7 @@ int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap)
}
return 0;
}
/* aquires lock */
int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -549,34 +559,36 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
if (!(adev->open_mode & OPEN_READ))
return -EIO;
spin_lock_irqsave(&dmap->lock,flags);
if (dmap->needs_reorg)
reorganize_buffers(dev, dmap, 0);
save_flags(flags);
cli();
if (adev->dmap_in->mapping_flags & DMA_MAP_MAPPED) {
/* printk(KERN_WARNING "Sound: Can't read from mmapped device (1)\n");*/
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return -EINVAL;
} else while (dmap->qlen <= 0 && n++ < 10) {
long timeout = MAX_SCHEDULE_TIMEOUT;
if (!(adev->enable_bits & PCM_ENABLE_INPUT) || !adev->go) {
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return -EAGAIN;
}
if ((err = DMAbuf_activate_recording(dev, dmap)) < 0) {
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return err;
}
/* Wait for the next block */
if (dontblock) {
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return -EAGAIN;
}
if ((go = adev->go))
timeout = dmabuf_timeout(dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
timeout = interruptible_sleep_on_timeout(&adev->in_sleeper,
timeout);
spin_lock_irqsave(&dmap->lock,flags);
if (!timeout) {
/* FIXME: include device name */
err = -EIO;
......@@ -585,7 +597,7 @@ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock)
} else
err = -EINTR;
}
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
if (dmap->qlen <= 0)
return err ? err : -EINTR;
......@@ -617,7 +629,7 @@ int DMAbuf_rmchars(int dev, int buff_no, int c)
return 0;
}
/* MUST be called with dmap->lock hold */
int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction)
{
/*
......@@ -626,11 +638,8 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
*/
int pos;
unsigned long flags;
unsigned long f;
save_flags(flags);
cli();
if (!(dmap->flags & DMA_ACTIVE))
pos = 0;
else {
......@@ -667,7 +676,6 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
release_dma_lock(f);
}
restore_flags(flags);
/* printk( "%04x ", pos); */
return pos;
......@@ -698,7 +706,7 @@ void DMAbuf_start_devices(unsigned int devmask)
adev->d->trigger(dev,adev->enable_bits * adev->go);
}
}
/* via poll called without a lock ?*/
int DMAbuf_space_in_queue(int dev)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -735,7 +743,7 @@ int DMAbuf_space_in_queue(int dev)
return 0;
return max - len;
}
/* MUST not hold the spinlock - this function may sleep */
static int output_sleep(int dev, int dontblock)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -770,12 +778,11 @@ static int output_sleep(int dev, int dontblock)
}
return err;
}
/* called with the lock held */
static int find_output_space(int dev, char **buf, int *size)
{
struct audio_operations *adev = audio_devs[dev];
struct dma_buffparms *dmap = adev->dmap_out;
unsigned long flags;
unsigned long active_offs;
long len, offs;
int maxfrags;
......@@ -784,8 +791,6 @@ static int find_output_space(int dev, char **buf, int *size)
*buf = dmap->raw_buf;
if (!(maxfrags = DMAbuf_space_in_queue(dev)) && !occupied_bytes)
return 0;
save_flags(flags);
cli();
#ifdef BE_CONSERVATIVE
active_offs = dmap->byte_counter + dmap->qhead * dmap->fragment_size;
......@@ -799,7 +804,6 @@ static int find_output_space(int dev, char **buf, int *size)
offs = (dmap->user_counter % dmap->bytes_in_use) & ~SAMPLE_ROUNDUP;
if (offs < 0 || offs >= dmap->bytes_in_use) {
restore_flags(flags);
printk(KERN_ERR "Sound: Got unexpected offs %ld. Giving up.\n", offs);
printk("Counter = %ld, bytes=%d\n", dmap->user_counter, dmap->bytes_in_use);
return 0;
......@@ -811,16 +815,14 @@ static int find_output_space(int dev, char **buf, int *size)
if ((offs + len) > dmap->bytes_in_use)
len = dmap->bytes_in_use - offs;
if (len < 0) {
restore_flags(flags);
return 0;
}
if (len > ((maxfrags * dmap->fragment_size) - occupied_bytes))
len = (maxfrags * dmap->fragment_size) - occupied_bytes;
*size = len & ~SAMPLE_ROUNDUP;
restore_flags(flags);
return (*size > 0);
}
/* aquires lock */
int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -828,39 +830,45 @@ int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock)
int err = -EIO;
struct dma_buffparms *dmap = adev->dmap_out;
if (dmap->needs_reorg)
reorganize_buffers(dev, dmap, 0);
if (dmap->mapping_flags & DMA_MAP_MAPPED) {
/* printk(KERN_DEBUG "Sound: Can't write to mmapped device (3)\n");*/
return -EINVAL;
}
spin_lock_irqsave(&dmap->lock,flags);
if (dmap->needs_reorg)
reorganize_buffers(dev, dmap, 0);
if (dmap->dma_mode == DMODE_INPUT) { /* Direction change */
spin_unlock_irqrestore(&dmap->lock,flags);
DMAbuf_reset(dev);
dmap->dma_mode = DMODE_NONE;
spin_lock_irqsave(&dmap->lock,flags);
}
dmap->dma_mode = DMODE_OUTPUT;
save_flags(flags);
cli();
while (find_output_space(dev, buf, size) <= 0) {
spin_unlock_irqrestore(&dmap->lock,flags);
if ((err = output_sleep(dev, dontblock)) < 0) {
restore_flags(flags);
return err;
}
spin_lock_irqsave(&dmap->lock,flags);
}
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
return 0;
}
/* has to aquire dmap->lock */
int DMAbuf_move_wrpointer(int dev, int l)
{
struct audio_operations *adev = audio_devs[dev];
struct dma_buffparms *dmap = adev->dmap_out;
unsigned long ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size;
unsigned long ptr;
unsigned long end_ptr, p;
int post = (dmap->flags & DMA_POST);
int post;
unsigned long flags;
spin_lock_irqsave(&dmap->lock,flags);
post= (dmap->flags & DMA_POST);
ptr = (dmap->user_counter / dmap->fragment_size) * dmap->fragment_size;
dmap->flags &= ~DMA_POST;
dmap->cfrag = -1;
......@@ -890,7 +898,7 @@ int DMAbuf_move_wrpointer(int dev, int l)
dmap->counts[dmap->qtail] = dmap->user_counter - ptr;
/*
* Let the low level driver to perform some postprocessing to
* Let the low level driver perform some postprocessing to
* the written data.
*/
if (adev->d->postprocess_write)
......@@ -899,6 +907,8 @@ int DMAbuf_move_wrpointer(int dev, int l)
if (!(dmap->flags & DMA_ACTIVE))
if (dmap->qlen > 1 || (dmap->qlen > 0 && (post || dmap->qlen >= dmap->nbufs - 1)))
DMAbuf_launch_output(dev, dmap);
spin_unlock_irqrestore(&dmap->lock,flags);
return 0;
}
......@@ -945,11 +955,10 @@ static void finish_output_interrupt(int dev, struct dma_buffparms *dmap)
wake_up(&adev->out_sleeper);
wake_up(&adev->poll_sleeper);
}
/* called with dmap->lock held in irq context*/
static void do_outputintr(int dev, int dummy)
{
struct audio_operations *adev = audio_devs[dev];
unsigned long flags;
struct dma_buffparms *dmap = adev->dmap_out;
int this_fragment;
......@@ -977,8 +986,6 @@ static void do_outputintr(int dev, int dummy)
finish_output_interrupt(dev, dmap);
return;
}
save_flags(flags);
cli();
dmap->qlen--;
this_fragment = dmap->qhead;
......@@ -1014,18 +1021,16 @@ static void do_outputintr(int dev, int dummy)
}
if (dmap->qlen > 0)
DMAbuf_launch_output(dev, dmap);
restore_flags(flags);
finish_output_interrupt(dev, dmap);
}
/* called in irq context */
void DMAbuf_outputintr(int dev, int notify_only)
{
struct audio_operations *adev = audio_devs[dev];
unsigned long flags;
struct dma_buffparms *dmap = adev->dmap_out;
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
if (!(dmap->flags & DMA_NODMA)) {
int chan = dmap->dma, pos, n;
unsigned long f;
......@@ -1049,9 +1054,9 @@ void DMAbuf_outputintr(int dev, int notify_only)
}
else
do_outputintr(dev, notify_only);
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
}
/* called with dmap->lock held in irq context */
static void do_inputintr(int dev)
{
struct audio_operations *adev = audio_devs[dev];
......@@ -1117,15 +1122,14 @@ static void do_inputintr(int dev)
wake_up(&adev->poll_sleeper);
}
}
/* called in irq context */
void DMAbuf_inputintr(int dev)
{
struct audio_operations *adev = audio_devs[dev];
struct dma_buffparms *dmap = adev->dmap_in;
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
if (!(dmap->flags & DMA_NODMA)) {
int chan = dmap->dma, pos, n;
......@@ -1149,7 +1153,7 @@ void DMAbuf_inputintr(int dev)
do_inputintr(dev);
} else
do_inputintr(dev);
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
}
int DMAbuf_open_dma(int dev)
......@@ -1240,10 +1244,9 @@ static unsigned int poll_input(struct file * file, int dev, poll_table *wait)
!dmap->qlen && adev->go) {
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&dmap->lock,flags);
DMAbuf_activate_recording(dev, dmap);
restore_flags(flags);
spin_unlock_irqrestore(&dmap->lock,flags);
}
return 0;
}
......
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