diff options
Diffstat (limited to 'drivers/gpu/drm/msm/sde/sde_hw_interrupts.c')
| -rw-r--r-- | drivers/gpu/drm/msm/sde/sde_hw_interrupts.c | 70 |
1 files changed, 15 insertions, 55 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c index 0fc778e35f88..038b1fc53907 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c @@ -886,8 +886,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]; - /* get the global offset in 'sde_irq_map' */ sde_irq_idx = intr->sde_irq_tbl[reg_idx].sde_irq_idx; if (sde_irq_idx < 0) @@ -904,6 +902,9 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, end_idx > ARRAY_SIZE(sde_irq_map)) continue; + irq_status = SDE_REG_READ(&intr->hw, + intr->sde_irq_tbl[reg_idx].status_off); + /* * Search through matching intr status from irq map. * start_idx and end_idx defined the search range in @@ -924,8 +925,9 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, if (cbfunc) cbfunc(arg, irq_idx); else - intr->ops.clear_intr_status_nolock( - intr, irq_idx); + SDE_REG_WRITE(&intr->hw, + intr->sde_irq_tbl[reg_idx].clr_off, + sde_irq_map[irq_idx].irq_mask); /* * When callback finish, clear the irq_status @@ -977,9 +979,6 @@ static int sde_hw_intr_enable_irq(struct sde_hw_intr *intr, int irq_idx) /* Enabling interrupts with the new mask */ SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask); - /* ensure register write goes through */ - wmb(); - intr->cache_irq_mask[reg_idx] = cache_irq_mask; } spin_unlock_irqrestore(&intr->irq_lock, irq_flags); @@ -1115,40 +1114,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_force_mask(struct sde_hw_intr *intr, int irq_idx, u32 irq_mask) { @@ -1200,12 +1165,20 @@ static void sde_hw_intr_clear_interrupt_status(struct sde_hw_intr *intr, int irq_idx) { unsigned long irq_flags; + int reg_idx; if (!intr) return; + reg_idx = sde_irq_map[irq_idx].reg_idx; + if (reg_idx < 0 || reg_idx > intr->sde_irq_size) { + pr_err("invalid irq reg:%d irq:%d\n", reg_idx, irq_idx); + return; + } + spin_lock_irqsave(&intr->irq_lock, irq_flags); - sde_hw_intr_clear_intr_status_nolock(intr, irq_idx); + SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, + sde_irq_map[irq_idx].irq_mask); spin_unlock_irqrestore(&intr->irq_lock, irq_flags); } @@ -1272,9 +1245,6 @@ static u32 sde_hw_intr_get_interrupt_status(struct sde_hw_intr *intr, SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, intr_status); - /* ensure register writes go through */ - wmb(); - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); return intr_status; @@ -1321,7 +1291,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops) ops->disable_all_irqs = sde_hw_intr_disable_irqs; ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts; 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->clear_intr_status_force_mask = @@ -1469,7 +1438,6 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr) if (intr) { kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); } } @@ -1578,13 +1546,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, goto exit; } - intr->save_irq_status = kcalloc(intr->sde_irq_size, sizeof(u32), - GFP_KERNEL); - if (intr->save_irq_status == NULL) { - ret = -ENOMEM; - goto exit; - } - spin_lock_init(&intr->irq_lock); return intr; @@ -1592,7 +1553,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, exit: kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); return ERR_PTR(ret); } |
