Commit 9024d50a authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] fix locking for rawmidi trigger callbacks

Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
Use spin_lock_irqsave() instead of spin_lock() in places where we
could be interrupted by another hardware interrupt that could call
the rawmidi trigger callback that could try to take the same lock.

Additionally, remove locking code that is no longer needed now that
the trigger callback is no longer called recursively from the rawmidi
'event' handler.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent 0e65c6fa
......@@ -86,9 +86,6 @@ struct _snd_mpu401 {
spinlock_t output_lock;
spinlock_t timer_lock;
atomic_t rx_loop;
atomic_t tx_loop;
struct timer_list timer;
void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
......
......@@ -92,24 +92,21 @@ static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
{
spin_lock(&mpu->input_lock);
unsigned long flags;
spin_lock_irqsave(&mpu->input_lock, flags);
if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
atomic_dec(&mpu->rx_loop);
snd_mpu401_uart_input_read(mpu);
atomic_inc(&mpu->rx_loop);
} else {
snd_mpu401_uart_clear_rx(mpu);
}
spin_unlock(&mpu->input_lock);
spin_unlock_irqrestore(&mpu->input_lock, flags);
/* ok. for better Tx performance try do some output when input is done */
if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
if (spin_trylock(&mpu->output_lock)) {
atomic_dec(&mpu->tx_loop);
snd_mpu401_uart_output_write(mpu);
atomic_inc(&mpu->tx_loop);
spin_unlock(&mpu->output_lock);
}
spin_lock_irqsave(&mpu->output_lock, flags);
snd_mpu401_uart_output_write(mpu);
spin_unlock_irqrestore(&mpu->output_lock, flags);
}
}
......@@ -137,13 +134,14 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
*/
static void snd_mpu401_uart_timer(unsigned long data)
{
unsigned long flags;
mpu401_t *mpu = (mpu401_t *)data;
spin_lock(&mpu->timer_lock);
spin_lock_irqsave(&mpu->timer_lock, flags);
/*mpu->mode |= MPU401_MODE_TIMER;*/
mpu->timer.expires = 1 + jiffies;
add_timer(&mpu->timer);
spin_unlock(&mpu->timer_lock);
spin_unlock_irqrestore(&mpu->timer_lock, flags);
if (mpu->rmidi)
_snd_mpu401_uart_interrupt(mpu);
}
......@@ -243,7 +241,6 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
}
mpu->substream_input = substream;
atomic_set(&mpu->rx_loop, 1);
set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
return 0;
}
......@@ -261,7 +258,6 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
}
mpu->substream_output = substream;
atomic_set(&mpu->tx_loop, 1);
set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
return 0;
}
......@@ -314,16 +310,9 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
}
/* read data in advance */
/* prevent double enter via rawmidi->event callback */
if (atomic_dec_and_test(&mpu->rx_loop)) {
local_irq_save(flags);
if (spin_trylock(&mpu->input_lock)) {
snd_mpu401_uart_input_read(mpu);
spin_unlock(&mpu->input_lock);
}
local_irq_restore(flags);
}
atomic_inc(&mpu->rx_loop);
spin_trylock_irqsave(&mpu->input_lock, flags);
snd_mpu401_uart_input_read(mpu);
spin_unlock_irqrestore(&mpu->input_lock, flags);
} else {
if (mpu->irq < 0)
snd_mpu401_uart_remove_timer(mpu, 1);
......@@ -405,16 +394,9 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
snd_mpu401_uart_add_timer(mpu, 0);
/* output pending data */
/* prevent double enter via rawmidi->event callback */
if (atomic_dec_and_test(&mpu->tx_loop)) {
local_irq_save(flags);
if (spin_trylock(&mpu->output_lock)) {
snd_mpu401_uart_output_write(mpu);
spin_unlock(&mpu->output_lock);
}
local_irq_restore(flags);
}
atomic_inc(&mpu->tx_loop);
spin_lock_irqsave(&mpu->output_lock, flags);
snd_mpu401_uart_output_write(mpu);
spin_unlock_irqrestore(&mpu->output_lock, flags);
} else {
snd_mpu401_uart_remove_timer(mpu, 0);
clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
......
......@@ -413,10 +413,11 @@ static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
static void snd_mtpav_output_timer(unsigned long data)
{
unsigned long flags;
mtpav_t *chip = (mtpav_t *)data;
int p;
spin_lock(&chip->spinlock);
spin_lock_irqsave(&chip->spinlock, flags);
/* reprogram timer */
chip->timer.expires = 1 + jiffies;
add_timer(&chip->timer);
......@@ -426,7 +427,7 @@ static void snd_mtpav_output_timer(unsigned long data)
if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
snd_mtpav_output_port_write(portp, portp->output);
}
spin_unlock(&chip->spinlock);
spin_unlock_irqrestore(&chip->spinlock, flags);
}
/* spinlock held! */
......@@ -514,9 +515,7 @@ static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
portp = &mcrd->ports[mcrd->inmidiport];
if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
spin_unlock(&mcrd->spinlock);
snd_rawmidi_receive(portp->input, &inbyte, 1);
spin_lock(&mcrd->spinlock);
}
}
......@@ -581,12 +580,13 @@ static void snd_mtpav_read_bytes(mtpav_t * mcrd)
static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
mtpav_t *mcard = dev_id;
//printk("irqh()\n");
spin_lock(&mcard->spinlock);
spin_lock_irqsave(&mcard->spinlock, flags);
snd_mtpav_read_bytes(mcard);
spin_unlock(&mcard->spinlock);
spin_unlock_irqrestore(&mcard->spinlock, flags);
return IRQ_HANDLED;
}
......
......@@ -292,30 +292,32 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
*/
static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
snd_uart16550_t *uart;
uart = (snd_uart16550_t *) dev_id;
spin_lock(&uart->open_lock);
spin_lock_irqsave(&uart->open_lock, flags);
if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
spin_unlock(&uart->open_lock);
spin_unlock_irqrestore(&uart->open_lock, flags);
return IRQ_NONE;
}
inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */
snd_uart16550_io_loop(uart);
spin_unlock(&uart->open_lock);
spin_unlock_irqrestore(&uart->open_lock, flags);
return IRQ_HANDLED;
}
/* When the polling mode, this function calls snd_uart16550_io_loop. */
static void snd_uart16550_buffer_timer(unsigned long data)
{
unsigned long flags;
snd_uart16550_t *uart;
uart = (snd_uart16550_t *)data;
spin_lock(&uart->open_lock);
spin_lock_irqsave(&uart->open_lock, flags);
snd_uart16550_del_timer(uart);
snd_uart16550_io_loop(uart);
spin_unlock(&uart->open_lock);
spin_unlock_irqrestore(&uart->open_lock, flags);
}
/*
......
......@@ -46,20 +46,16 @@ irqreturn_t snd_sb8dsp_midi_interrupt(sb_t * chip)
inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */
return IRQ_NONE;
}
spin_lock(&chip->midi_input_lock);
while (max-- > 0) {
spin_lock(&chip->midi_input_lock);
if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
byte = inb(SBP(chip, READ));
if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
spin_unlock(&chip->midi_input_lock);
snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
} else {
spin_unlock(&chip->midi_input_lock);
}
} else {
spin_unlock(&chip->midi_input_lock);
}
}
spin_unlock(&chip->midi_input_lock);
return IRQ_HANDLED;
}
......
......@@ -413,8 +413,8 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
return;
}
spin_lock_irqsave (&midi->virtual, flags);
while (--max) {
spin_lock_irqsave (&midi->virtual, flags);
if (input_avail (midi)) {
byte = read_data (midi);
......@@ -433,21 +433,17 @@ snd_wavefront_midi_interrupt (snd_wavefront_card_t *card)
}
if (substream == NULL) {
spin_unlock_irqrestore (&midi->virtual, flags);
continue;
}
if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
spin_unlock_irqrestore (&midi->virtual, flags);
snd_rawmidi_receive(substream, &byte, 1);
} else {
spin_unlock_irqrestore (&midi->virtual, flags);
}
} else {
spin_unlock_irqrestore (&midi->virtual, flags);
break;
}
}
spin_unlock_irqrestore (&midi->virtual, flags);
snd_wavefront_midi_output_write(card);
}
......
......@@ -697,10 +697,11 @@ static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
{
unsigned long flags;
cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
cs4281_t *chip = snd_pcm_substream_chip(substream);
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dma->valDCR |= BA0_DCR_MSK;
......@@ -727,13 +728,13 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
dma->valFCR &= ~BA0_FCR_FEN;
break;
default:
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return -EINVAL;
}
snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}
......@@ -1847,6 +1848,7 @@ static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
cs4281_t *chip = dev_id;
unsigned long flags;
unsigned int status, dma, val;
cs4281_dma_t *cdma;
......@@ -1862,7 +1864,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
for (dma = 0; dma < 4; dma++)
if (status & BA0_HISR_DMA(dma)) {
cdma = &chip->dma[dma];
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
/* ack DMA IRQ */
val = snd_cs4281_peekBA0(chip, cdma->regHDSR);
/* workaround, sometimes CS4281 acknowledges */
......@@ -1871,16 +1873,16 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) {
cdma->frag--;
chip->spurious_dhtc_irq++;
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
continue;
}
if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) {
cdma->frag--;
chip->spurious_dtc_irq++;
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
continue;
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
snd_pcm_period_elapsed(cdma->substream);
}
}
......@@ -1888,14 +1890,12 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((status & BA0_HISR_MIDI) && chip->rmidi) {
unsigned char c;
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) {
c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & BA0_MIDCR_RIE) == 0)
continue;
spin_unlock(&chip->reg_lock);
snd_rawmidi_receive(chip->midi_input, &c, 1);
spin_lock(&chip->reg_lock);
}
while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
if ((chip->midcr & BA0_MIDCR_TIE) == 0)
......@@ -1907,7 +1907,7 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
}
snd_cs4281_pokeBA0(chip, BA0_MIDWP, c);
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
/* EOI to the PCI part... reenables interrupts */
......
......@@ -765,6 +765,9 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
int cmd)
{
#ifndef CONFIG_SND_CS46XX_NEW_DSP
unsigned long flags;
#endif
cs46xx_t *chip = snd_pcm_substream_chip(substream);
/*snd_pcm_runtime_t *runtime = substream->runtime;*/
int result = 0;
......@@ -789,7 +792,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream);
#else
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
if (substream->runtime->periods != CS46XX_FRAGS)
snd_cs46xx_playback_transfer(substream);
{ unsigned int tmp;
......@@ -797,7 +800,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
tmp &= 0x0000ffff;
snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
#endif
break;
case SNDRV_PCM_TRIGGER_STOP:
......@@ -810,13 +813,13 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
if (!cpcm->pcm_channel->unlinked)
cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
#else
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
{ unsigned int tmp;
tmp = snd_cs46xx_peek(chip, BA1_PCTL);
tmp &= 0x0000ffff;
snd_cs46xx_poke(chip, BA1_PCTL, tmp);
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
#endif
break;
default:
......@@ -830,11 +833,12 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
int cmd)
{
unsigned long flags;
cs46xx_t *chip = snd_pcm_substream_chip(substream);
unsigned int tmp;
int result = 0;
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
......@@ -852,7 +856,7 @@ static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
result = -EINVAL;
break;
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return result;
}
......@@ -1149,6 +1153,7 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
cs46xx_t *chip = dev_id;
u32 status1;
#ifdef CONFIG_SND_CS46XX_NEW_DSP
......@@ -1212,14 +1217,12 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
if ((status1 & HISR_MIDI) && chip->rmidi) {
unsigned char c;
spin_lock(&chip->reg_lock);
spin_lock_irqsave(&chip->reg_lock, flags);
while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
if ((chip->midcr & MIDCR_RIE) == 0)
continue;
spin_unlock(&chip->reg_lock);
snd_rawmidi_receive(chip->midi_input, &c, 1);
spin_lock(&chip->reg_lock);
}
while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
if ((chip->midcr & MIDCR_TIE) == 0)
......@@ -1231,7 +1234,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
}
snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
}
spin_unlock(&chip->reg_lock);
spin_unlock_irqrestore(&chip->reg_lock, flags);
}
/*
* EOI to the PCI part....reenables interrupts
......
......@@ -1265,6 +1265,7 @@ static void mpu401_clear_rx(emu10k1x_t *emu, emu10k1x_midi_t *mpu)
static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, unsigned int status)
{
unsigned long flags;
unsigned char byte;
if (midi->rmidi == NULL) {
......@@ -1278,15 +1279,13 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
mpu401_clear_rx(emu, midi);
} else {
byte = mpu401_read_data(emu, midi);
spin_unlock(&midi->input_lock);
if (midi->substream_input)
snd_rawmidi_receive(midi->substream_input, &byte, 1);
spin_lock(&midi->input_lock);
}
}
spin_unlock(&midi->input_lock);
spin_lock(&midi->output_lock);
spin_lock_irqsave(&midi->output_lock, flags);
if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
if (midi->substream_output &&
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
......@@ -1295,7 +1294,7 @@ static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, u
snd_emu10k1x_intr_disable(emu, midi->tx_enable);
}
}
spin_unlock(&midi->output_lock);
spin_unlock_irqrestore(&midi->output_lock, flags);
}
static void snd_emu10k1x_midi_interrupt(emu10k1x_t *emu, unsigned int status)
......
......@@ -73,6 +73,7 @@ static void mpu401_clear_rx(emu10k1_t *emu, emu10k1_midi_t *mpu)
static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsigned int status)
{
unsigned long flags;
unsigned char byte;
if (midi->rmidi == NULL) {
......@@ -86,15 +87,13 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
mpu401_clear_rx(emu, midi);
} else {
byte = mpu401_read_data(emu, midi);
spin_unlock(&midi->input_lock);
if (midi->substream_input)
snd_rawmidi_receive(midi->substream_input, &byte, 1);
spin_lock(&midi->input_lock);
}
}
spin_unlock(&midi->input_lock);
spin_lock(&midi->output_lock);
spin_lock_irqsave(&midi->output_lock, flags);
if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
if (midi->substream_output &&
snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
......@@ -103,7 +102,7 @@ static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsi
snd_emu10k1_intr_disable(emu, midi->tx_enable);
}
}
spin_unlock(&midi->output_lock);
spin_unlock_irqrestore(&midi->output_lock, flags);
}
static void snd_emu10k1_midi_interrupt(emu10k1_t *emu, unsigned int status)
......
......@@ -754,6 +754,8 @@ static void snd_es1371_dac2_rate(ensoniq_t * ensoniq, unsigned int rate)
static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
{
unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
......@@ -773,13 +775,13 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
} else if (s == ensoniq->capture_substream)
return -EINVAL;
}
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
ensoniq->sctrl |= what;
else
ensoniq->sctrl &= ~what;
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
break;
}
case SNDRV_PCM_TRIGGER_START:
......@@ -801,13 +803,13 @@ static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
snd_pcm_trigger_done(s, substream);
}
}
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (cmd == SNDRV_PCM_TRIGGER_START)
ensoniq->ctrl |= what;
else
ensoniq->ctrl &= ~what;
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
break;
}
default:
......@@ -956,10 +958,11 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * substream)
{
unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC1_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC1_SIZE)));
......@@ -967,16 +970,17 @@ static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * sub
} else {
ptr = 0;
}
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
return ptr;
}
static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * substream)
{
unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC2_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC2_SIZE)));
......@@ -984,16 +988,17 @@ static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * sub
} else {
ptr = 0;
}
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
return ptr;
}
static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * substream)
{
unsigned long flags;
ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
size_t ptr;
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
if (inl(ES_REG(ensoniq, CONTROL)) & ES_ADC_EN) {
outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, ADC_SIZE)));
......@@ -1001,7 +1006,7 @@ static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * subst
} else {
ptr = 0;
}
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
return ptr;
}
......@@ -2030,27 +2035,26 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
{
unsigned long flags;
snd_rawmidi_t * rmidi = ensoniq->rmidi;
unsigned char status, mask, byte;
if (rmidi == NULL)
return;
/* do Rx at first */
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0;
while (mask) {
status = inb(ES_REG(ensoniq, UART_STATUS));
if ((status & mask) == 0)
break;
byte = inb(ES_REG(ensoniq, UART_DATA));
spin_unlock(&ensoniq->reg_lock);
snd_rawmidi_receive(ensoniq->midi_input, &byte, 1);
spin_lock(&ensoniq->reg_lock);
}
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
/* do Tx at second */
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
mask = ensoniq->uartm & ES_MODE_OUTPUT ? ES_TXRDY : 0;
while (mask) {
status = inb(ES_REG(ensoniq, UART_STATUS));
......@@ -2064,7 +2068,7 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
outb(byte, ES_REG(ensoniq, UART_DATA));
}
}
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
}
static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
......@@ -2231,6 +2235,7 @@ static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmi
static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long flags;
ensoniq_t *ensoniq = dev_id;
unsigned int status, sctrl;
......@@ -2241,7 +2246,7 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs
if (!(status & ES_INTR))
return IRQ_NONE;
spin_lock(&ensoniq->reg_lock);
spin_lock_irqsave(&ensoniq->reg_lock, flags);
sctrl = ensoniq->sctrl;
if (status & ES_DAC1)
sctrl &= ~ES_P1_INT_EN;
......@@ -2251,7 +2256,7 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs
sctrl &= ~ES_R1_INT_EN;
outl(sctrl, ES_REG(ensoniq, SERIAL));
outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
spin_unlock(&ensoniq->reg_lock);
spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
if (status & ES_UART)
snd_ensoniq_midi_interrupt(ensoniq);
......
......@@ -3905,6 +3905,7 @@ static int snd_hdsp_ioctl(snd_pcm_substream_t *substream,
static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
{
unsigned long flags;
hdsp_t *hdsp = snd_pcm_substream_chip(substream);
snd_pcm_substream_t *other;
int running;
......@@ -3924,7 +3925,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
return -EIO;
}
spin_lock(&hdsp->lock);
spin_lock_irqsave(&hdsp->lock, flags);
running = hdsp->running;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
......@@ -3935,7 +3936,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
break;
default:
snd_BUG();
spin_unlock(&hdsp->lock);
spin_unlock_irqrestore(&hdsp->lock, flags);
return -EINVAL;
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
......@@ -3977,7 +3978,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
else if (hdsp->running && !running)
hdsp_stop_audio(hdsp);
hdsp->running = running;
spin_unlock(&hdsp->lock);
spin_unlock_irqrestore(&hdsp->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