diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index 9e4d859b4dba..aeed1422900b 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -42,7 +42,6 @@ const struct snd_sof_dsp_ops sof_apl_ops = { .block_write = sof_block_write, /* doorbell */ - .irq_handler = hda_dsp_ipc_irq_handler, .irq_thread = hda_dsp_ipc_irq_thread, /* ipc */ diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 3541063ba84c..ceca776530af 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -232,7 +232,6 @@ const struct snd_sof_dsp_ops sof_cnl_ops = { .block_write = sof_block_write, /* doorbell */ - .irq_handler = hda_dsp_ipc_irq_handler, .irq_thread = cnl_ipc_irq_thread, /* ipc */ diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 0fd2153c1769..fac9f9762bb2 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -237,14 +237,14 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } -/* is this IRQ for ADSP ? - we only care about IPC here */ -irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context) +/* Check if it is an IPC and disable IPC interrupt if yes */ +bool check_ipc(struct snd_sof_dev *sdev) { - struct snd_sof_dev *sdev = context; - int ret = IRQ_NONE; + bool ret = false; u32 irq_status; - spin_lock(&sdev->hw_lock); + /* The function can be called at irq thread, so use spin_lock_irq */ + spin_lock_irq(&sdev->hw_lock); /* store status */ irq_status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); @@ -260,11 +260,11 @@ irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context) snd_sof_dsp_update_bits_unlocked(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, HDA_DSP_ADSPIC_IPC, 0); - ret = IRQ_WAKE_THREAD; + ret = true; } out: - spin_unlock(&sdev->hw_lock); + spin_unlock_irq(&sdev->hw_lock); return ret; } diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 92643a801f4f..53487b8da027 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -550,22 +550,23 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, return 0; } -irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) +bool is_stream_irq(struct snd_sof_dev *sdev) { - struct hdac_bus *bus = context; - int ret = IRQ_WAKE_THREAD; + struct hdac_bus *bus = sof_to_bus(sdev); + bool ret = true; u32 status; - spin_lock(&bus->reg_lock); + /* The function can be called at irq thread, so use spin_lock_irq */ + spin_lock_irq(&bus->reg_lock); status = snd_hdac_chip_readl(bus, INTSTS); dev_vdbg(bus->dev, "stream irq, INTSTS status: 0x%x\n", status); /* Register inaccessible, ignore it.*/ if (status == 0xffffffff) - ret = IRQ_NONE; + ret = false; - spin_unlock(&bus->reg_lock); + spin_unlock_irq(&bus->reg_lock); return ret; } @@ -603,7 +604,8 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) { - struct hdac_bus *bus = context; + struct snd_sof_dev *sdev = context; + struct hdac_bus *bus = sof_to_bus(sdev); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) u32 rirb_status; #endif diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 4d35e03faef5..527d7f3a27df 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -402,6 +402,28 @@ static const struct sof_intel_dsp_desc return chip_info; } +irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) +{ + struct snd_sof_dev *sdev = context; + + if (check_ipc(sdev) || is_stream_irq(sdev)) + return IRQ_WAKE_THREAD; + + return IRQ_NONE; +} + +irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) +{ + struct snd_sof_dev *sdev = context; + + if (check_ipc(sdev)) + sof_ops(sdev)->irq_thread(irq, sdev); + if (is_stream_irq(sdev)) + hda_dsp_stream_threaded_handler(irq, sdev); + + return IRQ_HANDLED; +} + int hda_dsp_probe(struct snd_sof_dev *sdev) { struct pci_dev *pci = to_pci_dev(sdev->dev); @@ -506,9 +528,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) */ if (hda_use_msi && pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) > 0) { dev_info(sdev->dev, "use msi interrupt mode\n"); - hdev->irq = pci_irq_vector(pci, 0); - /* ipc irq number is the same of hda irq */ - sdev->ipc_irq = hdev->irq; + sdev->ipc_irq = pci_irq_vector(pci, 0); /* initialised to "false" by kzalloc() */ sdev->msi_enabled = true; } @@ -519,28 +539,17 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) * in IO-APIC mode, hda->irq and ipc_irq are using the same * irq number of pci->irq */ - hdev->irq = pci->irq; sdev->ipc_irq = pci->irq; } - dev_dbg(sdev->dev, "using HDA IRQ %d\n", hdev->irq); - ret = request_threaded_irq(hdev->irq, hda_dsp_stream_interrupt, - hda_dsp_stream_threaded_handler, - IRQF_SHARED, "AudioHDA", bus); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to register HDA IRQ %d\n", - hdev->irq); - goto free_irq_vector; - } - dev_dbg(sdev->dev, "using IPC IRQ %d\n", sdev->ipc_irq); - ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_ipc_irq_handler, - sof_ops(sdev)->irq_thread, IRQF_SHARED, - "AudioDSP", sdev); + ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_interrupt_handler, + hda_dsp_interrupt_thread, + IRQF_SHARED, "AudioDSP", sdev); if (ret < 0) { dev_err(sdev->dev, "error: failed to register IPC IRQ %d\n", sdev->ipc_irq); - goto free_hda_irq; + goto free_irq_vector; } pci_set_master(pci); @@ -571,8 +580,6 @@ int hda_dsp_probe(struct snd_sof_dev *sdev) free_ipc_irq: free_irq(sdev->ipc_irq, sdev); -free_hda_irq: - free_irq(hdev->irq, bus); free_irq_vector: if (sdev->msi_enabled) pci_free_irq_vectors(pci); @@ -618,7 +625,6 @@ int hda_dsp_remove(struct snd_sof_dev *sdev) SOF_HDA_PPCTL_GPROCEN, 0); free_irq(sdev->ipc_irq, sdev); - free_irq(hda->irq, bus); if (sdev->msi_enabled) pci_free_irq_vectors(pci); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 97c3fcb23d15..70b96f9ce736 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -406,8 +406,6 @@ struct sof_intel_hda_dev { /* the maximum number of streams (playback + capture) supported */ u32 stream_max; - int irq; - /* PM related */ bool l1_support_changed;/* during suspend, is L1SEN changed or not */ @@ -511,11 +509,12 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params); int hda_dsp_stream_trigger(struct snd_sof_dev *sdev, struct hdac_ext_stream *stream, int cmd); -irqreturn_t hda_dsp_stream_interrupt(int irq, void *context); irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context); int hda_dsp_stream_setup_bdl(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, struct hdac_stream *stream); +bool check_ipc(struct snd_sof_dev *sdev); +bool is_stream_irq(struct snd_sof_dev *sdev); struct hdac_ext_stream * hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction); @@ -540,7 +539,6 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev); int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev); int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); -irqreturn_t hda_dsp_ipc_irq_handler(int irq, void *context); irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir);