Commit 28585980 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "A couple of regression fixes and a fix for mutex deadlock at
  hog-unplug, as well as other device-specific fixes:

   - A commit to avoid the spurious unsolicited interrupt on HD-audio
     bus caused a stall at shutdown, so it's reverted now.

   - The recent support of AMD/Nvidia audio component binding caused a
     mutex deadlock; fixed by splitting to another mutex

   - The device hot-unplug and the ALSA timer close combo may lead to
     another mutex deadlock; fixed by moving put_device() calls

   - Usual device-specific small quirks for HD- and USB-audio drivers

   - An old error check fix in FireWire driver"

* tag 'sound-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: timer: Fix mutex deadlock at releasing card
  ALSA: hda - Fix mutex deadlock in HDMI codec driver
  Revert "ALSA: hda: Flush interrupts on disabling"
  ALSA: bebob: Fix prototype of helper function to return negative value
  ALSA: hda/realtek - Fix 2 front mics of codec 0x623
  ALSA: hda/realtek - Add support for ALC623
  ALSA: usb-audio: Add DSD support for Gustard U16/X26 USB Interface
parents e472c64a a3933186
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -226,7 +226,8 @@ static int snd_timer_check_master(struct snd_timer_instance *master)
	return 0;
}

static int snd_timer_close_locked(struct snd_timer_instance *timeri);
static int snd_timer_close_locked(struct snd_timer_instance *timeri,
				  struct device **card_devp_to_put);

/*
 * open a timer instance
@@ -238,6 +239,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
{
	struct snd_timer *timer;
	struct snd_timer_instance *timeri = NULL;
	struct device *card_dev_to_put = NULL;
	int err;

	mutex_lock(&register_mutex);
@@ -261,7 +263,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
		list_add_tail(&timeri->open_list, &snd_timer_slave_list);
		err = snd_timer_check_slave(timeri);
		if (err < 0) {
			snd_timer_close_locked(timeri);
			snd_timer_close_locked(timeri, &card_dev_to_put);
			timeri = NULL;
		}
		goto unlock;
@@ -313,7 +315,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
			timeri = NULL;

			if (timer->card)
				put_device(&timer->card->card_dev);
				card_dev_to_put = &timer->card->card_dev;
			module_put(timer->module);
			goto unlock;
		}
@@ -323,12 +325,15 @@ int snd_timer_open(struct snd_timer_instance **ti,
	timer->num_instances++;
	err = snd_timer_check_master(timeri);
	if (err < 0) {
		snd_timer_close_locked(timeri);
		snd_timer_close_locked(timeri, &card_dev_to_put);
		timeri = NULL;
	}

 unlock:
	mutex_unlock(&register_mutex);
	/* put_device() is called after unlock for avoiding deadlock */
	if (card_dev_to_put)
		put_device(card_dev_to_put);
	*ti = timeri;
	return err;
}
@@ -338,7 +343,8 @@ EXPORT_SYMBOL(snd_timer_open);
 * close a timer instance
 * call this with register_mutex down.
 */
static int snd_timer_close_locked(struct snd_timer_instance *timeri)
static int snd_timer_close_locked(struct snd_timer_instance *timeri,
				  struct device **card_devp_to_put)
{
	struct snd_timer *timer = timeri->timer;
	struct snd_timer_instance *slave, *tmp;
@@ -395,7 +401,7 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
			timer->hw.close(timer);
		/* release a card refcount for safe disconnection */
		if (timer->card)
			put_device(&timer->card->card_dev);
			*card_devp_to_put = &timer->card->card_dev;
		module_put(timer->module);
	}

@@ -407,14 +413,18 @@ static int snd_timer_close_locked(struct snd_timer_instance *timeri)
 */
int snd_timer_close(struct snd_timer_instance *timeri)
{
	struct device *card_dev_to_put = NULL;
	int err;

	if (snd_BUG_ON(!timeri))
		return -ENXIO;

	mutex_lock(&register_mutex);
	err = snd_timer_close_locked(timeri);
	err = snd_timer_close_locked(timeri, &card_dev_to_put);
	mutex_unlock(&register_mutex);
	/* put_device() is called after unlock for avoiding deadlock */
	if (card_dev_to_put)
		put_device(card_dev_to_put);
	return err;
}
EXPORT_SYMBOL(snd_timer_close);
+1 −2
Original line number Diff line number Diff line
@@ -252,8 +252,7 @@ int snd_bebob_stream_get_clock_src(struct snd_bebob *bebob,
	return err;
}

static unsigned int
map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
static int map_data_channels(struct snd_bebob *bebob, struct amdtp_stream *s)
{
	unsigned int sec, sections, ch, channels;
	unsigned int pcm, midi, location;
+0 −2
Original line number Diff line number Diff line
@@ -447,8 +447,6 @@ static void azx_int_disable(struct hdac_bus *bus)
	list_for_each_entry(azx_dev, &bus->stream_list, list)
		snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_INT_MASK, 0);

	synchronize_irq(bus->irq);

	/* disable SIE for all streams */
	snd_hdac_chip_writeb(bus, INTCTL, 0);

+1 −1
Original line number Diff line number Diff line
@@ -1348,9 +1348,9 @@ static int azx_free(struct azx *chip)
	}

	if (bus->chip_init) {
		azx_stop_chip(chip);
		azx_clear_irq_pending(chip);
		azx_stop_all_streams(chip);
		azx_stop_chip(chip);
	}

	if (bus->irq >= 0)
+6 −4
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ struct hdmi_spec {
	struct snd_array pins; /* struct hdmi_spec_per_pin */
	struct hdmi_pcm pcm_rec[16];
	struct mutex pcm_lock;
	struct mutex bind_lock; /* for audio component binding */
	/* pcm_bitmap means which pcms have been assigned to pins*/
	unsigned long pcm_bitmap;
	int pcm_used;	/* counter of pcm_rec[] */
@@ -2258,7 +2259,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
	struct hdmi_spec *spec = codec->spec;
	int pin_idx;

	mutex_lock(&spec->pcm_lock);
	mutex_lock(&spec->bind_lock);
	spec->use_jack_detect = !codec->jackpoll_interval;
	for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
		struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2275,7 +2276,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
			snd_hda_jack_detect_enable_callback(codec, pin_nid,
							    jack_callback);
	}
	mutex_unlock(&spec->pcm_lock);
	mutex_unlock(&spec->bind_lock);
	return 0;
}

@@ -2382,6 +2383,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec)
	spec->ops = generic_standard_hdmi_ops;
	spec->dev_num = 1;	/* initialize to 1 */
	mutex_init(&spec->pcm_lock);
	mutex_init(&spec->bind_lock);
	snd_hdac_register_chmap_ops(&codec->core, &spec->chmap);

	spec->chmap.ops.get_chmap = hdmi_get_chmap;
@@ -2451,7 +2453,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
	int i;

	spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops);
	mutex_lock(&spec->pcm_lock);
	mutex_lock(&spec->bind_lock);
	spec->use_acomp_notifier = use_acomp;
	spec->codec->relaxed_resume = use_acomp;
	/* reprogram each jack detection logic depending on the notifier */
@@ -2461,7 +2463,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp,
					      get_pin(spec, i)->pin_nid,
					      use_acomp);
	}
	mutex_unlock(&spec->pcm_lock);
	mutex_unlock(&spec->bind_lock);
}

/* enable / disable the notifier via master bind / unbind */
Loading