Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: Intel: avs: Refactor IRQ handling

Merge series from Cezary Rojewski <cezary.rojewski@intel.com>:

The existing code can be both improved and simplified. To make this
change easier to manage, first add new implementation and then remove
deadcode in a separate patch.

Simplification achieved with:

- reduce the amount of resources requested by the driver i.e.: IPC and
CLDMA request_irq() merged into one
- reduce the number of DSP ops from 2 to 1:
irq_handler/thread() vs dsp_interrupt()
- drop ambiguity around CLDMA interrupt, let skl.c handle that
explicitly as it is the only user

With that done, switch to the new implementation and remove unused
members. While the change is non-trivial, from functional perspective
status quo is achieved.

+181 -183
+18 -2
sound/soc/intel/avs/apl.c
··· 8 8 9 9 #include <linux/devcoredump.h> 10 10 #include <linux/slab.h> 11 + #include <sound/hdaudio_ext.h> 11 12 #include "avs.h" 12 13 #include "messages.h" 13 14 #include "path.h" 14 15 #include "topology.h" 16 + 17 + static irqreturn_t avs_apl_dsp_interrupt(struct avs_dev *adev) 18 + { 19 + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); 20 + irqreturn_t ret = IRQ_NONE; 21 + 22 + if (adspis == UINT_MAX) 23 + return ret; 24 + 25 + if (adspis & AVS_ADSP_ADSPIS_IPC) { 26 + avs_skl_ipc_interrupt(adev); 27 + ret = IRQ_HANDLED; 28 + } 29 + 30 + return ret; 31 + } 15 32 16 33 #ifdef CONFIG_DEBUG_FS 17 34 int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, ··· 254 237 .power = avs_dsp_core_power, 255 238 .reset = avs_dsp_core_reset, 256 239 .stall = avs_dsp_core_stall, 257 - .irq_handler = avs_irq_handler, 258 - .irq_thread = avs_skl_irq_thread, 240 + .dsp_interrupt = avs_apl_dsp_interrupt, 259 241 .int_control = avs_dsp_interrupt_control, 260 242 .load_basefw = avs_hda_load_basefw, 261 243 .load_lib = avs_hda_load_library,
+3 -5
sound/soc/intel/avs/avs.h
··· 46 46 int (* const power)(struct avs_dev *, u32, bool); 47 47 int (* const reset)(struct avs_dev *, u32, bool); 48 48 int (* const stall)(struct avs_dev *, u32, bool); 49 - irqreturn_t (* const irq_handler)(struct avs_dev *); 50 - irqreturn_t (* const irq_thread)(struct avs_dev *); 49 + irqreturn_t (* const dsp_interrupt)(struct avs_dev *); 51 50 void (* const int_control)(struct avs_dev *, bool); 52 51 int (* const load_basefw)(struct avs_dev *, struct firmware *); 53 52 int (* const load_lib)(struct avs_dev *, struct firmware *, u32); ··· 244 245 #define AVS_IPC_RET(ret) \ 245 246 (((ret) <= 0) ? (ret) : -AVS_EIPC) 246 247 247 - irqreturn_t avs_irq_handler(struct avs_dev *adev); 248 248 void avs_dsp_process_response(struct avs_dev *adev, u64 header); 249 249 int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, 250 250 struct avs_ipc_msg *reply, int timeout, const char *name); ··· 265 267 int avs_dsp_disable_d0ix(struct avs_dev *adev); 266 268 int avs_dsp_enable_d0ix(struct avs_dev *adev); 267 269 268 - irqreturn_t avs_skl_irq_thread(struct avs_dev *adev); 269 - irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev); 270 + void avs_skl_ipc_interrupt(struct avs_dev *adev); 271 + irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev); 270 272 int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, 271 273 u32 fifo_full_period, unsigned long resource_mask, u32 *priorities); 272 274 int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
+8 -34
sound/soc/intel/avs/cldma.c
··· 248 248 snd_hdac_stream_writel(cl, CL_SPBFCTL, 1); 249 249 } 250 250 251 - static irqreturn_t cldma_irq_handler(int irq, void *dev_id) 251 + void hda_cldma_interrupt(struct hda_cldma *cl) 252 252 { 253 - struct hda_cldma *cl = dev_id; 254 - u32 adspis; 255 - 256 - adspis = snd_hdac_adsp_readl(cl, AVS_ADSP_REG_ADSPIS); 257 - if (adspis == UINT_MAX) 258 - return IRQ_NONE; 259 - if (!(adspis & AVS_ADSP_ADSPIS_CLDMA)) 260 - return IRQ_NONE; 261 - 262 - cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); 263 - dev_warn(cl->dev, "%s sd_status: 0x%08x\n", __func__, cl->sd_status); 264 - 265 253 /* disable CLDMA interrupt */ 266 254 snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); 267 255 268 - complete(&cl->completion); 256 + cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); 257 + dev_dbg(cl->dev, "%s sd_status: 0x%08x\n", __func__, cl->sd_status); 269 258 270 - return IRQ_HANDLED; 259 + complete(&cl->completion); 271 260 } 272 261 273 262 int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, 274 263 unsigned int buffer_size) 275 264 { 276 - struct pci_dev *pci = to_pci_dev(bus->dev); 277 265 int ret; 278 266 279 267 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, buffer_size, &cl->dmab_data); ··· 269 281 return ret; 270 282 271 283 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, bus->dev, BDL_SIZE, &cl->dmab_bdl); 272 - if (ret < 0) 273 - goto alloc_err; 284 + if (ret < 0) { 285 + snd_dma_free_pages(&cl->dmab_data); 286 + return ret; 287 + } 274 288 275 289 cl->dev = bus->dev; 276 290 cl->bus = bus; ··· 280 290 cl->buffer_size = buffer_size; 281 291 cl->sd_addr = dsp_ba + AZX_CL_SD_BASE; 282 292 283 - ret = pci_request_irq(pci, 0, cldma_irq_handler, NULL, cl, "CLDMA"); 284 - if (ret < 0) { 285 - dev_err(cl->dev, "Failed to request CLDMA IRQ handler: %d\n", ret); 286 - goto req_err; 287 - } 288 - 289 293 return 0; 290 - 291 - req_err: 292 - snd_dma_free_pages(&cl->dmab_bdl); 293 - alloc_err: 294 - snd_dma_free_pages(&cl->dmab_data); 295 - 296 - return ret; 297 294 } 298 295 299 296 void hda_cldma_free(struct hda_cldma *cl) 300 297 { 301 - struct pci_dev *pci = to_pci_dev(cl->dev); 302 - 303 - pci_free_irq(pci, 0, cl); 304 298 snd_dma_free_pages(&cl->dmab_data); 305 299 snd_dma_free_pages(&cl->dmab_bdl); 306 300 }
+1
sound/soc/intel/avs/cldma.h
··· 24 24 25 25 void hda_cldma_set_data(struct hda_cldma *cl, void *data, unsigned int size); 26 26 void hda_cldma_setup(struct hda_cldma *cl); 27 + void hda_cldma_interrupt(struct hda_cldma *cl); 27 28 int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, 28 29 unsigned int buffer_size); 29 30 void hda_cldma_free(struct hda_cldma *cl);
+55 -26
sound/soc/intel/avs/cnl.c
··· 10 10 #include "avs.h" 11 11 #include "messages.h" 12 12 13 - irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev) 13 + static void avs_cnl_ipc_interrupt(struct avs_dev *adev) 14 14 { 15 - union avs_reply_msg msg; 16 - u32 hipctdr, hipctdd, hipctda; 15 + const struct avs_spec *spec = adev->spec; 16 + u32 hipc_ack, hipc_rsp; 17 17 18 - hipctdr = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDR); 19 - hipctdd = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDD); 18 + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 19 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0); 20 20 21 - /* Ensure DSP sent new response to process. */ 22 - if (!(hipctdr & CNL_ADSP_HIPCTDR_BUSY)) 23 - return IRQ_NONE; 21 + hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); 22 + hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); 24 23 25 - msg.primary = hipctdr; 26 - msg.ext.val = hipctdd; 27 - avs_dsp_process_response(adev, msg.val); 24 + /* DSP acked host's request. */ 25 + if (hipc_ack & spec->hipc->ack_done_mask) { 26 + complete(&adev->ipc->done_completion); 28 27 29 - /* Tell DSP we accepted its message. */ 30 - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDR, 31 - CNL_ADSP_HIPCTDR_BUSY, CNL_ADSP_HIPCTDR_BUSY); 32 - /* Ack this response. */ 33 - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDA, 34 - CNL_ADSP_HIPCTDA_DONE, CNL_ADSP_HIPCTDA_DONE); 35 - /* HW might have been clock gated, give some time for change to propagate. */ 36 - snd_hdac_adsp_readl_poll(adev, CNL_ADSP_REG_HIPCTDA, hipctda, 37 - !(hipctda & CNL_ADSP_HIPCTDA_DONE), 10, 1000); 38 - /* Unmask busy interrupt. */ 39 - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCCTL, 40 - AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY); 28 + /* Tell DSP it has our attention. */ 29 + snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask, 30 + spec->hipc->ack_done_mask); 31 + } 41 32 42 - return IRQ_HANDLED; 33 + /* DSP sent new response to process. */ 34 + if (hipc_rsp & spec->hipc->rsp_busy_mask) { 35 + union avs_reply_msg msg; 36 + u32 hipctda; 37 + 38 + msg.primary = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDR); 39 + msg.ext.val = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDD); 40 + 41 + avs_dsp_process_response(adev, msg.val); 42 + 43 + /* Tell DSP we accepted its message. */ 44 + snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDR, 45 + CNL_ADSP_HIPCTDR_BUSY, CNL_ADSP_HIPCTDR_BUSY); 46 + /* Ack this response. */ 47 + snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDA, 48 + CNL_ADSP_HIPCTDA_DONE, CNL_ADSP_HIPCTDA_DONE); 49 + /* HW might have been clock gated, give some time for change to propagate. */ 50 + snd_hdac_adsp_readl_poll(adev, CNL_ADSP_REG_HIPCTDA, hipctda, 51 + !(hipctda & CNL_ADSP_HIPCTDA_DONE), 10, 1000); 52 + } 53 + 54 + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 55 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 56 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY); 57 + } 58 + 59 + irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev) 60 + { 61 + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); 62 + irqreturn_t ret = IRQ_NONE; 63 + 64 + if (adspis == UINT_MAX) 65 + return ret; 66 + 67 + if (adspis & AVS_ADSP_ADSPIS_IPC) { 68 + avs_cnl_ipc_interrupt(adev); 69 + ret = IRQ_HANDLED; 70 + } 71 + 72 + return ret; 43 73 } 44 74 45 75 const struct avs_dsp_ops avs_cnl_dsp_ops = { 46 76 .power = avs_dsp_core_power, 47 77 .reset = avs_dsp_core_reset, 48 78 .stall = avs_dsp_core_stall, 49 - .irq_handler = avs_irq_handler, 50 - .irq_thread = avs_cnl_irq_thread, 79 + .dsp_interrupt = avs_cnl_dsp_interrupt, 51 80 .int_control = avs_dsp_interrupt_control, 52 81 .load_basefw = avs_hda_load_basefw, 53 82 .load_lib = avs_hda_load_library,
+40 -45
sound/soc/intel/avs/core.c
··· 257 257 } 258 258 } 259 259 260 - static irqreturn_t hdac_bus_irq_handler(int irq, void *context) 260 + static irqreturn_t avs_hda_interrupt(struct hdac_bus *bus) 261 261 { 262 - struct hdac_bus *bus = context; 263 - u32 mask, int_enable; 262 + irqreturn_t ret = IRQ_NONE; 264 263 u32 status; 265 - int ret = IRQ_NONE; 266 - 267 - if (!pm_runtime_active(bus->dev)) 268 - return ret; 269 - 270 - spin_lock(&bus->reg_lock); 271 264 272 265 status = snd_hdac_chip_readl(bus, INTSTS); 273 - if (status == 0 || status == UINT_MAX) { 274 - spin_unlock(&bus->reg_lock); 275 - return ret; 276 - } 266 + if (snd_hdac_bus_handle_stream_irq(bus, status, hdac_update_stream)) 267 + ret = IRQ_HANDLED; 277 268 278 - /* clear rirb int */ 269 + spin_lock_irq(&bus->reg_lock); 270 + /* Clear RIRB interrupt. */ 279 271 status = snd_hdac_chip_readb(bus, RIRBSTS); 280 272 if (status & RIRB_INT_MASK) { 281 273 if (status & RIRB_INT_RESPONSE) 282 274 snd_hdac_bus_update_rirb(bus); 283 275 snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); 284 - } 285 - 286 - mask = (0x1 << bus->num_streams) - 1; 287 - 288 - status = snd_hdac_chip_readl(bus, INTSTS); 289 - status &= mask; 290 - if (status) { 291 - /* Disable stream interrupts; Re-enable in bottom half */ 292 - int_enable = snd_hdac_chip_readl(bus, INTCTL); 293 - snd_hdac_chip_writel(bus, INTCTL, (int_enable & (~mask))); 294 - ret = IRQ_WAKE_THREAD; 295 - } else { 296 276 ret = IRQ_HANDLED; 297 277 } 298 278 299 - spin_unlock(&bus->reg_lock); 279 + spin_unlock_irq(&bus->reg_lock); 300 280 return ret; 301 281 } 302 282 303 - static irqreturn_t hdac_bus_irq_thread(int irq, void *context) 283 + static irqreturn_t avs_hda_irq_handler(int irq, void *dev_id) 304 284 { 305 - struct hdac_bus *bus = context; 285 + struct hdac_bus *bus = dev_id; 286 + u32 intsts; 287 + 288 + intsts = snd_hdac_chip_readl(bus, INTSTS); 289 + if (intsts == UINT_MAX || !(intsts & AZX_INT_GLOBAL_EN)) 290 + return IRQ_NONE; 291 + 292 + /* Mask GIE, unmasked in irq_thread(). */ 293 + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, 0); 294 + 295 + return IRQ_WAKE_THREAD; 296 + } 297 + 298 + static irqreturn_t avs_hda_irq_thread(int irq, void *dev_id) 299 + { 300 + struct hdac_bus *bus = dev_id; 306 301 u32 status; 307 - u32 int_enable; 308 - u32 mask; 309 - unsigned long flags; 310 302 311 303 status = snd_hdac_chip_readl(bus, INTSTS); 304 + if (status & ~AZX_INT_GLOBAL_EN) 305 + avs_hda_interrupt(bus); 312 306 313 - snd_hdac_bus_handle_stream_irq(bus, status, hdac_update_stream); 314 - 315 - /* Re-enable stream interrupts */ 316 - mask = (0x1 << bus->num_streams) - 1; 317 - spin_lock_irqsave(&bus->reg_lock, flags); 318 - int_enable = snd_hdac_chip_readl(bus, INTCTL); 319 - snd_hdac_chip_writel(bus, INTCTL, (int_enable | mask)); 320 - spin_unlock_irqrestore(&bus->reg_lock, flags); 307 + /* Unmask GIE, masked in irq_handler(). */ 308 + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, AZX_INT_GLOBAL_EN); 321 309 322 310 return IRQ_HANDLED; 323 311 } ··· 314 326 { 315 327 struct avs_dev *adev = dev_id; 316 328 317 - return avs_dsp_op(adev, irq_handler); 329 + return avs_hda_irq_handler(irq, &adev->base.core); 318 330 } 319 331 320 332 static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) 321 333 { 322 334 struct avs_dev *adev = dev_id; 335 + struct hdac_bus *bus = &adev->base.core; 336 + u32 status; 323 337 324 - return avs_dsp_op(adev, irq_thread); 338 + status = readl(bus->ppcap + AZX_REG_PP_PPSTS); 339 + if (status & AZX_PPCTL_PIE) 340 + avs_dsp_op(adev, dsp_interrupt); 341 + 342 + /* Unmask GIE, masked in irq_handler(). */ 343 + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, AZX_INT_GLOBAL_EN); 344 + 345 + return IRQ_HANDLED; 325 346 } 326 347 327 348 static int avs_hdac_acquire_irq(struct avs_dev *adev) ··· 346 349 return ret; 347 350 } 348 351 349 - ret = pci_request_irq(pci, 0, hdac_bus_irq_handler, hdac_bus_irq_thread, bus, 352 + ret = pci_request_irq(pci, 0, avs_hda_irq_handler, avs_hda_irq_thread, bus, 350 353 KBUILD_MODNAME); 351 354 if (ret < 0) { 352 355 dev_err(adev->dev, "Failed to request stream IRQ handler: %d\n", ret); ··· 527 530 snd_hdac_bus_stop_chip(bus); 528 531 snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); 529 532 530 - if (avs_platattr_test(adev, CLDMA)) 531 - pci_free_irq(pci, 0, &code_loader); 532 533 pci_free_irq(pci, 0, adev); 533 534 pci_free_irq(pci, 0, bus); 534 535 pci_free_irq_vectors(pci);
+1 -2
sound/soc/intel/avs/icl.c
··· 188 188 .power = avs_dsp_core_power, 189 189 .reset = avs_dsp_core_reset, 190 190 .stall = avs_dsp_core_stall, 191 - .irq_handler = avs_irq_handler, 192 - .irq_thread = avs_cnl_irq_thread, 191 + .dsp_interrupt = avs_cnl_dsp_interrupt, 193 192 .int_control = avs_dsp_interrupt_control, 194 193 .load_basefw = avs_icl_load_basefw, 195 194 .load_lib = avs_hda_load_library,
-48
sound/soc/intel/avs/ipc.c
··· 301 301 complete(&ipc->busy_completion); 302 302 } 303 303 304 - irqreturn_t avs_irq_handler(struct avs_dev *adev) 305 - { 306 - struct avs_ipc *ipc = adev->ipc; 307 - const struct avs_spec *const spec = adev->spec; 308 - u32 adspis, hipc_rsp, hipc_ack; 309 - irqreturn_t ret = IRQ_NONE; 310 - 311 - adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); 312 - if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC)) 313 - return ret; 314 - 315 - hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); 316 - hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); 317 - 318 - /* DSP acked host's request */ 319 - if (hipc_ack & spec->hipc->ack_done_mask) { 320 - /* 321 - * As an extra precaution, mask done interrupt. Code executed 322 - * due to complete() found below does not assume any masking. 323 - */ 324 - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 325 - AVS_ADSP_HIPCCTL_DONE, 0); 326 - 327 - complete(&ipc->done_completion); 328 - 329 - /* tell DSP it has our attention */ 330 - snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, 331 - spec->hipc->ack_done_mask, 332 - spec->hipc->ack_done_mask); 333 - /* unmask done interrupt */ 334 - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 335 - AVS_ADSP_HIPCCTL_DONE, 336 - AVS_ADSP_HIPCCTL_DONE); 337 - ret = IRQ_HANDLED; 338 - } 339 - 340 - /* DSP sent new response to process */ 341 - if (hipc_rsp & spec->hipc->rsp_busy_mask) { 342 - /* mask busy interrupt */ 343 - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 344 - AVS_ADSP_HIPCCTL_BUSY, 0); 345 - 346 - ret = IRQ_WAKE_THREAD; 347 - } 348 - 349 - return ret; 350 - } 351 - 352 304 static bool avs_ipc_is_busy(struct avs_ipc *ipc) 353 305 { 354 306 struct avs_dev *adev = to_avs_dev(ipc->dev);
+54 -19
sound/soc/intel/avs/skl.c
··· 10 10 #include <linux/slab.h> 11 11 #include <sound/hdaudio_ext.h> 12 12 #include "avs.h" 13 + #include "cldma.h" 13 14 #include "messages.h" 14 15 15 - irqreturn_t avs_skl_irq_thread(struct avs_dev *adev) 16 + void avs_skl_ipc_interrupt(struct avs_dev *adev) 16 17 { 17 - union avs_reply_msg msg; 18 - u32 hipct, hipcte; 18 + const struct avs_spec *spec = adev->spec; 19 + u32 hipc_ack, hipc_rsp; 19 20 20 - hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); 21 - hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); 21 + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 22 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0); 22 23 23 - /* Ensure DSP sent new response to process. */ 24 - if (!(hipct & SKL_ADSP_HIPCT_BUSY)) 25 - return IRQ_NONE; 24 + hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); 25 + hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); 26 26 27 - msg.primary = hipct; 28 - msg.ext.val = hipcte; 29 - avs_dsp_process_response(adev, msg.val); 27 + /* DSP acked host's request. */ 28 + if (hipc_ack & spec->hipc->ack_done_mask) { 29 + complete(&adev->ipc->done_completion); 30 30 31 - /* Tell DSP we accepted its message. */ 32 - snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY); 33 - /* Unmask busy interrupt. */ 34 - snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, AVS_ADSP_HIPCCTL_BUSY, 35 - AVS_ADSP_HIPCCTL_BUSY); 31 + /* Tell DSP it has our attention. */ 32 + snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask, 33 + spec->hipc->ack_done_mask); 34 + } 36 35 37 - return IRQ_HANDLED; 36 + /* DSP sent new response to process */ 37 + if (hipc_rsp & spec->hipc->rsp_busy_mask) { 38 + union avs_reply_msg msg; 39 + 40 + msg.primary = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); 41 + msg.ext.val = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); 42 + 43 + avs_dsp_process_response(adev, msg.val); 44 + 45 + /* Tell DSP we accepted its message. */ 46 + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY, 47 + SKL_ADSP_HIPCT_BUSY); 48 + } 49 + 50 + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, 51 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 52 + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY); 53 + } 54 + 55 + static irqreturn_t avs_skl_dsp_interrupt(struct avs_dev *adev) 56 + { 57 + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); 58 + irqreturn_t ret = IRQ_NONE; 59 + 60 + if (adspis == UINT_MAX) 61 + return ret; 62 + 63 + if (adspis & AVS_ADSP_ADSPIS_CLDMA) { 64 + hda_cldma_interrupt(&code_loader); 65 + ret = IRQ_HANDLED; 66 + } 67 + 68 + if (adspis & AVS_ADSP_ADSPIS_IPC) { 69 + avs_skl_ipc_interrupt(adev); 70 + ret = IRQ_HANDLED; 71 + } 72 + 73 + return ret; 38 74 } 39 75 40 76 static int __maybe_unused ··· 164 128 .power = avs_dsp_core_power, 165 129 .reset = avs_dsp_core_reset, 166 130 .stall = avs_dsp_core_stall, 167 - .irq_handler = avs_irq_handler, 168 - .irq_thread = avs_skl_irq_thread, 131 + .dsp_interrupt = avs_skl_dsp_interrupt, 169 132 .int_control = avs_dsp_interrupt_control, 170 133 .load_basefw = avs_cldma_load_basefw, 171 134 .load_lib = avs_cldma_load_library,
+1 -2
sound/soc/intel/avs/tgl.c
··· 39 39 .power = avs_tgl_dsp_core_power, 40 40 .reset = avs_tgl_dsp_core_reset, 41 41 .stall = avs_tgl_dsp_core_stall, 42 - .irq_handler = avs_irq_handler, 43 - .irq_thread = avs_cnl_irq_thread, 42 + .dsp_interrupt = avs_cnl_dsp_interrupt, 44 43 .int_control = avs_dsp_interrupt_control, 45 44 .load_basefw = avs_icl_load_basefw, 46 45 .load_lib = avs_hda_load_library,