diff --git a/msm/sde/sde_core_irq.c b/msm/sde/sde_core_irq.c index fff3920f45..cb17596256 100644 --- a/msm/sde/sde_core_irq.c +++ b/msm/sde/sde_core_irq.c @@ -616,15 +616,6 @@ int sde_core_irq_domain_fini(struct sde_kms *sde_kms) irqreturn_t sde_core_irq(struct sde_kms *sde_kms) { - /* - * Read interrupt status from all sources. Interrupt status are - * stored within hw_intr. - * Function will also clear the interrupt status after reading. - * Individual interrupt status bit will only get stored if it - * is enabled. - */ - sde_kms->hw_intr->ops.get_interrupt_statuses(sde_kms->hw_intr); - /* * Dispatch to HW driver to handle interrupt lookup that is being * fired. When matching interrupt is located, HW driver will call to @@ -632,6 +623,7 @@ irqreturn_t sde_core_irq(struct sde_kms *sde_kms) * sde_core_irq_callback_handler will perform the registered function * callback, and do the interrupt status clearing once the registered * callback is finished. + * Function will also clear the interrupt status after reading. */ sde_kms->hw_intr->ops.dispatch_irqs( sde_kms->hw_intr, diff --git a/msm/sde/sde_hw_interrupts.c b/msm/sde/sde_hw_interrupts.c index ceac3e02bd..a3da29b5df 100644 --- a/msm/sde/sde_hw_interrupts.c +++ b/msm/sde/sde_hw_interrupts.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -415,6 +415,7 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, int start_idx; int end_idx; u32 irq_status; + u32 enable_mask; unsigned long irq_flags; if (!intr) @@ -427,8 +428,6 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, */ spin_lock_irqsave(&intr->irq_lock, irq_flags); for (reg_idx = 0; reg_idx < intr->sde_irq_size; reg_idx++) { - irq_status = intr->save_irq_status[reg_idx]; - /* * Each Interrupt register has dynamic range of indexes, * initialized during hw_intr_init when sde_irq_tbl is created. @@ -440,6 +439,20 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, end_idx > intr->sde_irq_map_size) continue; + /* Read interrupt status */ + irq_status = SDE_REG_READ(&intr->hw, intr->sde_irq_tbl[reg_idx].status_off); + + /* Read enable mask */ + enable_mask = SDE_REG_READ(&intr->hw, intr->sde_irq_tbl[reg_idx].en_off); + + /* and clear the interrupt */ + if (irq_status) + SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, + irq_status); + + /* Finally update IRQ status based on enable mask */ + irq_status &= enable_mask; + /* * Search through matching intr status from irq map. * start_idx and end_idx defined the search range in @@ -474,6 +487,10 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, ~intr->sde_irq_map[irq_idx].irq_mask; } } + + /* ensure register writes go through */ + wmb(); + spin_unlock_irqrestore(&intr->irq_lock, irq_flags); } @@ -620,40 +637,6 @@ static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr, return 0; } -static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr) -{ - int i; - u32 enable_mask; - unsigned long irq_flags; - - if (!intr) - return; - - spin_lock_irqsave(&intr->irq_lock, irq_flags); - for (i = 0; i < intr->sde_irq_size; i++) { - /* Read interrupt status */ - intr->save_irq_status[i] = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].status_off); - - /* Read enable mask */ - enable_mask = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].en_off); - - /* and clear the interrupt */ - if (intr->save_irq_status[i]) - SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[i].clr_off, - intr->save_irq_status[i]); - - /* Finally update IRQ status based on enable mask */ - intr->save_irq_status[i] &= enable_mask; - } - - /* ensure register writes go through */ - wmb(); - - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); -} - static void sde_hw_intr_clear_intr_status_nolock(struct sde_hw_intr *intr, int irq_idx) { @@ -856,7 +839,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops) ops->clear_all_irqs = sde_hw_intr_clear_irqs; ops->disable_all_irqs = sde_hw_intr_disable_irqs; ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources; - ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses; ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status; ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock; ops->get_interrupt_status = sde_hw_intr_get_interrupt_status; @@ -881,7 +863,6 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr) kfree(intr->sde_irq_tbl); kfree(intr->sde_irq_map); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); } } @@ -1151,13 +1132,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, goto exit; } - intr->save_irq_status = kcalloc(intr->sde_irq_size, - sizeof(*intr->save_irq_status), GFP_KERNEL); - if (intr->save_irq_status == NULL) { - ret = -ENOMEM; - goto exit; - } - spin_lock_init(&intr->irq_lock); exit: diff --git a/msm/sde/sde_hw_interrupts.h b/msm/sde/sde_hw_interrupts.h index aab65a510f..71a4049771 100644 --- a/msm/sde/sde_hw_interrupts.h +++ b/msm/sde/sde_hw_interrupts.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved. */ @@ -170,14 +170,6 @@ struct sde_hw_intr_ops { void (*cbfunc)(void *arg, int irq_idx), void *arg); - /** - * get_interrupt_statuses - Gets and store value from all interrupt - * status registers that are currently fired. - * @intr: HW interrupt handle - */ - void (*get_interrupt_statuses)( - struct sde_hw_intr *intr); - /** * clear_interrupt_status - Clears HW interrupt status based on given * lookup IRQ index