Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b73cfe5 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: pdaudiocf: Use nonatomic PCM ops



Like other fixes, convert the tasklet to a threaded irq and replace
spinlock with mutex appropriately.  ak4117_lock remains as spinlock
since it's called in another spinlock context from ak4117 driver.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 6336c20c
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ static void snd_pdacf_detach(struct pcmcia_device *p_dev);

static void pdacf_release(struct pcmcia_device *link)
{
	free_irq(link->irq, link->priv);
	pcmcia_disable_device(link);
}

@@ -220,11 +221,13 @@ static int pdacf_config(struct pcmcia_device *link)

	ret = pcmcia_request_io(link);
	if (ret)
		goto failed;
		goto failed_preirq;

	ret = pcmcia_request_irq(link, pdacf_interrupt);
	ret = request_threaded_irq(link->irq, pdacf_interrupt,
				   pdacf_threaded_irq,
				   IRQF_SHARED, link->devname, link->priv);
	if (ret)
		goto failed;
		goto failed_preirq;

	ret = pcmcia_enable_device(link);
	if (ret)
@@ -237,6 +240,8 @@ static int pdacf_config(struct pcmcia_device *link)
	return 0;

 failed:
	free_irq(link->irq, link->priv);
failed_preirq:
	pcmcia_disable_device(link);
	return -ENODEV;
}
+2 −3
Original line number Diff line number Diff line
@@ -88,10 +88,9 @@ struct snd_pdacf {
	unsigned long port;
	int irq;

	spinlock_t reg_lock;
	struct mutex reg_lock;
	unsigned short regmap[8];
	unsigned short suspend_reg_scr;
	struct tasklet_struct tq;

	spinlock_t ak4117_lock;
	struct ak4117 *ak4117;
@@ -136,7 +135,7 @@ int snd_pdacf_resume(struct snd_pdacf *chip);
#endif
int snd_pdacf_pcm_new(struct snd_pdacf *chip);
irqreturn_t pdacf_interrupt(int irq, void *dev);
void pdacf_tasklet(unsigned long private_data);
irqreturn_t pdacf_threaded_irq(int irq, void *dev);
void pdacf_reinit(struct snd_pdacf *chip, int resume);

#endif /* __PDAUDIOCF_H */
+3 −5
Original line number Diff line number Diff line
@@ -162,9 +162,8 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
	if (chip == NULL)
		return NULL;
	chip->card = card;
	spin_lock_init(&chip->reg_lock);
	mutex_init(&chip->reg_lock);
	spin_lock_init(&chip->ak4117_lock);
	tasklet_init(&chip->tq, pdacf_tasklet, (unsigned long)chip);
	card->private_data = chip;

	pdacf_proc_init(chip);
@@ -174,19 +173,18 @@ struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
static void snd_pdacf_ak4117_change(struct ak4117 *ak4117, unsigned char c0, unsigned char c1)
{
	struct snd_pdacf *chip = ak4117->change_callback_private;
	unsigned long flags;
	u16 val;

	if (!(c0 & AK4117_UNLCK))
		return;
	spin_lock_irqsave(&chip->reg_lock, flags);
	mutex_lock(&chip->reg_lock);
	val = chip->regmap[PDAUDIOCF_REG_SCR>>1];
	if (ak4117->rcs0 & AK4117_UNLCK)
		val |= PDAUDIOCF_BLUE_LED_OFF;
	else
		val &= ~PDAUDIOCF_BLUE_LED_OFF;
	pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, val);
	spin_unlock_irqrestore(&chip->reg_lock, flags);
	mutex_unlock(&chip->reg_lock);
}

int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
+12 −11
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
{
	struct snd_pdacf *chip = dev;
	unsigned short stat;
	bool wake_thread = false;

	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
				  PDAUDIOCF_STAT_IS_CONFIGURED|
@@ -41,13 +42,13 @@ irqreturn_t pdacf_interrupt(int irq, void *dev)
		if (stat & PDAUDIOCF_IRQOVR)	/* should never happen */
			snd_printk(KERN_ERR "PDAUDIOCF SRAM buffer overrun detected!\n");
		if (chip->pcm_substream)
			tasklet_schedule(&chip->tq);
			wake_thread = true;
		if (!(stat & PDAUDIOCF_IRQAKM))
			stat |= PDAUDIOCF_IRQAKM;	/* check rate */
	}
	if (get_irq_regs() != NULL)
		snd_ak4117_check_rate_and_errors(chip->ak4117, 0);
	return IRQ_HANDLED;
	return wake_thread ? IRQ_WAKE_THREAD : IRQ_HANDLED;
}

static inline void pdacf_transfer_mono16(u16 *dst, u16 xor, unsigned int size, unsigned long rdp_port)
@@ -256,16 +257,16 @@ static void pdacf_transfer(struct snd_pdacf *chip, unsigned int size, unsigned i
	}
}

void pdacf_tasklet(unsigned long private_data)
irqreturn_t pdacf_threaded_irq(int irq, void *dev)
{
	struct snd_pdacf *chip = (struct snd_pdacf *) private_data;
	struct snd_pdacf *chip = dev;
	int size, off, cont, rdp, wdp;

	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
		return;
		return IRQ_HANDLED;
	
	if (chip->pcm_substream == NULL || chip->pcm_substream->runtime == NULL || !snd_pcm_running(chip->pcm_substream))
		return;
		return IRQ_HANDLED;

	rdp = inw(chip->port + PDAUDIOCF_REG_RDP);
	wdp = inw(chip->port + PDAUDIOCF_REG_WDP);
@@ -311,15 +312,15 @@ void pdacf_tasklet(unsigned long private_data)
		size -= cont;
	}
#endif
	spin_lock(&chip->reg_lock);
	mutex_lock(&chip->reg_lock);
	while (chip->pcm_tdone >= chip->pcm_period) {
		chip->pcm_hwptr += chip->pcm_period;
		chip->pcm_hwptr %= chip->pcm_size;
		chip->pcm_tdone -= chip->pcm_period;
		spin_unlock(&chip->reg_lock);
		mutex_unlock(&chip->reg_lock);
		snd_pcm_period_elapsed(chip->pcm_substream);
		spin_lock(&chip->reg_lock);
		mutex_lock(&chip->reg_lock);
	}
	spin_unlock(&chip->reg_lock);
	/* printk(KERN_DEBUG "TASKLET: end\n"); */
	mutex_unlock(&chip->reg_lock);
	return IRQ_HANDLED;
}
+3 −2
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
	default:
		return -EINVAL;
	}
	spin_lock(&chip->reg_lock);
	mutex_lock(&chip->reg_lock);
	chip->pcm_running += inc;
	tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
	if (chip->pcm_running) {
@@ -91,7 +91,7 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
	tmp |= val;
	pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
      __end:
	spin_unlock(&chip->reg_lock);
	mutex_unlock(&chip->reg_lock);
	snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
	return ret;
}
@@ -296,6 +296,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)

	pcm->private_data = chip;
	pcm->info_flags = 0;
	pcm->nonatomic = true;
	strcpy(pcm->name, chip->card->shortname);
	chip->pcm = pcm;