Commit d0d642a5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "Just a few fixes that have been gathered since the previous pull:

   - An additional fix for potential PCM deadlocks

   - A series of HD-audio CS8409 codec patches for new models

   - Other device specific fixes for HD-audio, ASoC mediatek, Intel,
     fsl, rockchip"

* tag 'sound-fix-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: pcm: Fix potential AB/BA lock with buffer_mutex and mmap_lock
  ALSA: hda: Avoid unsol event during RPM suspending
  ALSA: hda/realtek: Fix audio regression on Mi Notebook Pro 2020
  ALSA: hda/cs8409: Add new Dolphin HW variants
  ALSA: hda/cs8409: Disable HSBIAS_SENSE_EN for Cyborg
  ALSA: hda/cs8409: Support new Warlock MLK Variants
  ALSA: hda/cs8409: Fix Full Scale Volume setting for all variants
  ALSA: hda/cs8409: Re-order quirk table into ascending order
  ALSA: hda/cs8409: Fix Warlock to use mono mic configuration
  ALSA: cs4236: fix an incorrect NULL check on list iterator
  ALSA: hda/realtek: Enable headset mic on Lenovo P360
  ASoC: SOF: Intel: Fix build error without SND_SOC_SOF_PCI_DEV
  ALSA: hda/realtek: Add mute and micmut LED support for Zbook Fury 17 G9
  ASoC: rockchip: i2s_tdm: Fixup config for SND_SOC_DAIFMT_DSP_A/B
  ASoC: fsl-asoc-card: Fix jack_event() always return 0
  ASoC: mediatek: mt6358: add missing EXPORT_SYMBOLs
parents 26803bac bc55cfd5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -402,6 +402,7 @@ struct snd_pcm_runtime {
	struct fasync_struct *fasync;
	bool stop_operating;		/* sync_stop will be called */
	struct mutex buffer_mutex;	/* protect for buffer changes */
	atomic_t buffer_accessing;	/* >0: in r/w operation, <0: blocked */

	/* -- private section -- */
	void *private_data;
+1 −0
Original line number Diff line number Diff line
@@ -970,6 +970,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,

	runtime->status->state = SNDRV_PCM_STATE_OPEN;
	mutex_init(&runtime->buffer_mutex);
	atomic_set(&runtime->buffer_accessing, 0);

	substream->runtime = runtime;
	substream->private_data = pcm->private_data;
+5 −4
Original line number Diff line number Diff line
@@ -1906,11 +1906,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
		if (avail >= runtime->twake)
			break;
		snd_pcm_stream_unlock_irq(substream);
		mutex_unlock(&runtime->buffer_mutex);

		tout = schedule_timeout(wait_time);

		mutex_lock(&runtime->buffer_mutex);
		snd_pcm_stream_lock_irq(substream);
		set_current_state(TASK_INTERRUPTIBLE);
		switch (runtime->status->state) {
@@ -2221,7 +2219,6 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,

	nonblock = !!(substream->f_flags & O_NONBLOCK);

	mutex_lock(&runtime->buffer_mutex);
	snd_pcm_stream_lock_irq(substream);
	err = pcm_accessible_state(runtime);
	if (err < 0)
@@ -2276,6 +2273,10 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
			err = -EINVAL;
			goto _end_unlock;
		}
		if (!atomic_inc_unless_negative(&runtime->buffer_accessing)) {
			err = -EBUSY;
			goto _end_unlock;
		}
		snd_pcm_stream_unlock_irq(substream);
		if (!is_playback)
			snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_CPU);
@@ -2284,6 +2285,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
		if (is_playback)
			snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
		snd_pcm_stream_lock_irq(substream);
		atomic_dec(&runtime->buffer_accessing);
		if (err < 0)
			goto _end_unlock;
		err = pcm_accessible_state(runtime);
@@ -2313,7 +2315,6 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
	if (xfer > 0 && err >= 0)
		snd_pcm_update_state(substream, runtime);
	snd_pcm_stream_unlock_irq(substream);
	mutex_unlock(&runtime->buffer_mutex);
	return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
EXPORT_SYMBOL(__snd_pcm_lib_xfer);
+32 −7
Original line number Diff line number Diff line
@@ -685,6 +685,24 @@ static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
	return 0;
}

/* acquire buffer_mutex; if it's in r/w operation, return -EBUSY, otherwise
 * block the further r/w operations
 */
static int snd_pcm_buffer_access_lock(struct snd_pcm_runtime *runtime)
{
	if (!atomic_dec_unless_positive(&runtime->buffer_accessing))
		return -EBUSY;
	mutex_lock(&runtime->buffer_mutex);
	return 0; /* keep buffer_mutex, unlocked by below */
}

/* release buffer_mutex and clear r/w access flag */
static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
{
	mutex_unlock(&runtime->buffer_mutex);
	atomic_inc(&runtime->buffer_accessing);
}

#if IS_ENABLED(CONFIG_SND_PCM_OSS)
#define is_oss_stream(substream)	((substream)->oss.oss)
#else
@@ -695,14 +713,16 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime;
	int err = 0, usecs;
	int err, usecs;
	unsigned int bits;
	snd_pcm_uframes_t frames;

	if (PCM_RUNTIME_CHECK(substream))
		return -ENXIO;
	runtime = substream->runtime;
	mutex_lock(&runtime->buffer_mutex);
	err = snd_pcm_buffer_access_lock(runtime);
	if (err < 0)
		return err;
	snd_pcm_stream_lock_irq(substream);
	switch (runtime->status->state) {
	case SNDRV_PCM_STATE_OPEN:
@@ -820,7 +840,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
			snd_pcm_lib_free_pages(substream);
	}
 unlock:
	mutex_unlock(&runtime->buffer_mutex);
	snd_pcm_buffer_access_unlock(runtime);
	return err;
}

@@ -865,7 +885,9 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
	if (PCM_RUNTIME_CHECK(substream))
		return -ENXIO;
	runtime = substream->runtime;
	mutex_lock(&runtime->buffer_mutex);
	result = snd_pcm_buffer_access_lock(runtime);
	if (result < 0)
		return result;
	snd_pcm_stream_lock_irq(substream);
	switch (runtime->status->state) {
	case SNDRV_PCM_STATE_SETUP:
@@ -884,7 +906,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
	cpu_latency_qos_remove_request(&substream->latency_pm_qos_req);
 unlock:
	mutex_unlock(&runtime->buffer_mutex);
	snd_pcm_buffer_access_unlock(runtime);
	return result;
}

@@ -1369,12 +1391,15 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,

	/* Guarantee the group members won't change during non-atomic action */
	down_read(&snd_pcm_link_rwsem);
	mutex_lock(&substream->runtime->buffer_mutex);
	res = snd_pcm_buffer_access_lock(substream->runtime);
	if (res < 0)
		goto unlock;
	if (snd_pcm_stream_linked(substream))
		res = snd_pcm_action_group(ops, substream, state, false);
	else
		res = snd_pcm_action_single(ops, substream, state);
	mutex_unlock(&substream->runtime->buffer_mutex);
	snd_pcm_buffer_access_unlock(substream->runtime);
 unlock:
	up_read(&snd_pcm_link_rwsem);
	return res;
}
+5 −3
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
	static int dev;
	int err;
	struct snd_card *card;
	struct pnp_dev *cdev;
	struct pnp_dev *cdev, *iter;
	char cid[PNP_ID_LEN];

	if (pnp_device_is_isapnp(pdev))
@@ -510,10 +510,12 @@ static int snd_cs423x_pnpbios_detect(struct pnp_dev *pdev,
	strcpy(cid, pdev->id[0].id);
	cid[5] = '1';
	cdev = NULL;
	list_for_each_entry(cdev, &(pdev->protocol->devices), protocol_list) {
		if (!strcmp(cdev->id[0].id, cid))
	list_for_each_entry(iter, &(pdev->protocol->devices), protocol_list) {
		if (!strcmp(iter->id[0].id, cid)) {
			cdev = iter;
			break;
		}
	}
	err = snd_cs423x_card_new(&pdev->dev, dev, &card);
	if (err < 0)
		return err;
Loading