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