diff --git a/sound/hda/common/controller.c b/sound/hda/common/controller.c index 89e63a53d683..a847546753db 100644 --- a/sound/hda/common/controller.c +++ b/sound/hda/common/controller.c @@ -97,6 +97,8 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) trace_azx_pcm_close(chip, azx_dev); scoped_guard(mutex, &chip->open_mutex) { + if (chip->ops->pcm_close) + chip->ops->pcm_close(chip, azx_dev); azx_release_device(azx_dev); if (hinfo->ops.close) hinfo->ops.close(hinfo, apcm->codec, substream); diff --git a/sound/hda/common/hda_controller.h b/sound/hda/common/hda_controller.h index bc8ee4cc2401..38227f82e704 100644 --- a/sound/hda/common/hda_controller.h +++ b/sound/hda/common/hda_controller.h @@ -78,6 +78,8 @@ struct hda_controller_ops { int (*position_check)(struct azx *chip, struct azx_dev *azx_dev); /* enable/disable the link power */ int (*link_power)(struct azx *chip, bool enable); + /* additional hook for PCM */ + void (*pcm_close)(struct azx *chip, struct azx_dev *azx_dev); }; struct azx_pcm { diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c index 01477bd4fcb9..4b03c64e72ab 100644 --- a/sound/hda/controllers/intel.c +++ b/sound/hda/controllers/intel.c @@ -761,16 +761,27 @@ static void azx_irq_pending_work(struct work_struct *work) } /* clear irq_pending flags and assure no on-going workq */ +static void hda_intel_stream_clear_irq_pending(struct azx_dev *azx_dev) +{ + struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev); + + istream->irq_pending = false; + cancel_work_sync(&istream->irq_pending_work); +} + +/* called at PCM close */ +static void hda_intel_pcm_close(struct azx *chip, struct azx_dev *azx_dev) +{ + hda_intel_stream_clear_irq_pending(azx_dev); +} + static void azx_clear_irq_pending(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); struct hdac_stream *s; list_for_each_entry(s, &bus->stream_list, list) { - struct azx_dev *azx_dev = stream_to_azx_dev(s); - struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev); - istream->irq_pending = false; - cancel_work_sync(&istream->irq_pending_work); + hda_intel_stream_clear_irq_pending(stream_to_azx_dev(s)); } } @@ -2131,6 +2142,7 @@ static const struct dmi_system_id driver_denylist_dmi[] = { static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .position_check = azx_position_check, + .pcm_close = hda_intel_pcm_close, }; static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);