diff options
Diffstat (limited to 'drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c')
-rw-r--r-- | drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 172 |
1 files changed, 101 insertions, 71 deletions
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index e3c50439f80a..946dd0135dff 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -6,6 +6,8 @@ #include <linux/debugfs.h> #include <linux/slab.h> +#include <drm/drm_managed.h> + #include "dpu_core_irq.h" #include "dpu_kms.h" #include "dpu_hw_interrupts.h" @@ -197,27 +199,40 @@ static const struct dpu_intr_reg dpu_intr_set_7xxx[] = { }, }; -#define DPU_IRQ_REG(irq_idx) (irq_idx / 32) -#define DPU_IRQ_MASK(irq_idx) (BIT(irq_idx % 32)) +#define DPU_IRQ_MASK(irq_idx) (BIT(DPU_IRQ_BIT(irq_idx))) + +static inline bool dpu_core_irq_is_valid(unsigned int irq_idx) +{ + return irq_idx && irq_idx <= DPU_NUM_IRQS; +} + +static inline struct dpu_hw_intr_entry *dpu_core_irq_get_entry(struct dpu_hw_intr *intr, + unsigned int irq_idx) +{ + return &intr->irq_tbl[irq_idx - 1]; +} /** * dpu_core_irq_callback_handler - dispatch core interrupts * @dpu_kms: Pointer to DPU's KMS structure * @irq_idx: interrupt index */ -static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, int irq_idx) +static void dpu_core_irq_callback_handler(struct dpu_kms *dpu_kms, unsigned int irq_idx) { - VERB("irq_idx=%d\n", irq_idx); + struct dpu_hw_intr_entry *irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); - if (!dpu_kms->hw_intr->irq_tbl[irq_idx].cb) - DRM_ERROR("no registered cb, idx:%d\n", irq_idx); + VERB("IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); - atomic_inc(&dpu_kms->hw_intr->irq_tbl[irq_idx].count); + if (!irq_entry->cb) + DRM_ERROR("no registered cb, IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); + + atomic_inc(&irq_entry->count); /* * Perform registered function callback */ - dpu_kms->hw_intr->irq_tbl[irq_idx].cb(dpu_kms->hw_intr->irq_tbl[irq_idx].arg, irq_idx); + irq_entry->cb(irq_entry->arg); } irqreturn_t dpu_core_irq(struct msm_kms *kms) @@ -225,7 +240,7 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms) struct dpu_kms *dpu_kms = to_dpu_kms(kms); struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; - int irq_idx; + unsigned int irq_idx; u32 irq_status; u32 enable_mask; int bit; @@ -281,7 +296,8 @@ irqreturn_t dpu_core_irq(struct msm_kms *kms) return IRQ_HANDLED; } -static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) +static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, + unsigned int irq_idx) { int reg_idx; const struct dpu_intr_reg *reg; @@ -291,8 +307,9 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) if (!intr) return -EINVAL; - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } @@ -328,13 +345,15 @@ static int dpu_hw_intr_enable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("DPU IRQ %d %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, + pr_debug("DPU IRQ=[%d, %d] %senabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; } -static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) +static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, + unsigned int irq_idx) { int reg_idx; const struct dpu_intr_reg *reg; @@ -344,8 +363,9 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) if (!intr) return -EINVAL; - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } @@ -377,7 +397,8 @@ static int dpu_hw_intr_disable_irq_locked(struct dpu_hw_intr *intr, int irq_idx) intr->cache_irq_mask[reg_idx] = cache_irq_mask; } - pr_debug("DPU IRQ %d %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", irq_idx, dbgstr, + pr_debug("DPU IRQ=[%d, %d] %sdisabled: MASK:0x%.8lx, CACHE-MASK:0x%.8x\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), dbgstr, DPU_IRQ_MASK(irq_idx), cache_irq_mask); return 0; @@ -419,7 +440,8 @@ static void dpu_disable_all_irqs(struct dpu_kms *dpu_kms) wmb(); } -u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) +u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, + unsigned int irq_idx) { struct dpu_hw_intr *intr = dpu_kms->hw_intr; int reg_idx; @@ -429,14 +451,8 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) if (!intr) return 0; - if (irq_idx < 0) { - DPU_ERROR("[%pS] invalid irq_idx=%d\n", - __builtin_return_address(0), irq_idx); - return 0; - } - - if (irq_idx < 0 || irq_idx >= intr->total_irqs) { - pr_err("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + pr_err("invalid IRQ=[%d, %d]\n", DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } @@ -458,17 +474,17 @@ u32 dpu_core_irq_read(struct dpu_kms *dpu_kms, int irq_idx) return intr_status; } -struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, - const struct dpu_mdss_cfg *m) +struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev, + void __iomem *addr, + const struct dpu_mdss_cfg *m) { struct dpu_hw_intr *intr; - int nirq = MDP_INTR_MAX * 32; unsigned int i; if (!addr || !m) return ERR_PTR(-EINVAL); - intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL); + intr = drmm_kzalloc(dev, sizeof(*intr), GFP_KERNEL); if (!intr) return ERR_PTR(-ENOMEM); @@ -479,8 +495,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, intr->hw.blk_addr = addr + m->mdp[0].base; - intr->total_irqs = nirq; - intr->irq_mask = BIT(MDP_SSPP_TOP0_INTR) | BIT(MDP_SSPP_TOP0_INTR2) | BIT(MDP_SSPP_TOP0_HIST_INTR); @@ -492,7 +506,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, intr->irq_mask |= BIT(MDP_INTFn_INTR(intf->id)); - if (intf->intr_tear_rd_ptr != -1) + if (intf->intr_tear_rd_ptr) intr->irq_mask |= BIT(DPU_IRQ_REG(intf->intr_tear_rd_ptr)); } @@ -501,81 +515,87 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr, return intr; } -void dpu_hw_intr_destroy(struct dpu_hw_intr *intr) -{ - kfree(intr); -} - -int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx, - void (*irq_cb)(void *arg, int irq_idx), - void *irq_arg) +int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, + unsigned int irq_idx, + void (*irq_cb)(void *arg), + void *irq_arg) { + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int ret; if (!irq_cb) { - DPU_ERROR("invalid ird_idx:%d irq_cb:%ps\n", irq_idx, irq_cb); + DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); return -EINVAL; } - if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) { - DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + DPU_ERROR("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } - VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx); + VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0), + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - if (unlikely(WARN_ON(dpu_kms->hw_intr->irq_tbl[irq_idx].cb))) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); + if (unlikely(WARN_ON(irq_entry->cb))) { spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); return -EBUSY; } - trace_dpu_core_irq_register_callback(irq_idx, irq_cb); - dpu_kms->hw_intr->irq_tbl[irq_idx].arg = irq_arg; - dpu_kms->hw_intr->irq_tbl[irq_idx].cb = irq_cb; + trace_dpu_core_irq_register_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); + irq_entry->arg = irq_arg; + irq_entry->cb = irq_cb; ret = dpu_hw_intr_enable_irq_locked( dpu_kms->hw_intr, irq_idx); if (ret) - DPU_ERROR("Fail to enable IRQ for irq_idx:%d\n", - irq_idx); + DPU_ERROR("Failed/ to enable IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_irq_register_success(irq_idx); + trace_dpu_irq_register_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } -int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx) +int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, + unsigned int irq_idx) { + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int ret; - if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) { - DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx); + if (!dpu_core_irq_is_valid(irq_idx)) { + DPU_ERROR("invalid IRQ=[%d, %d]\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } - VERB("[%pS] irq_idx=%d\n", __builtin_return_address(0), irq_idx); + VERB("[%pS] IRQ=[%d, %d]\n", __builtin_return_address(0), + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_core_irq_unregister_callback(irq_idx); + trace_dpu_core_irq_unregister_callback(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); ret = dpu_hw_intr_disable_irq_locked(dpu_kms->hw_intr, irq_idx); if (ret) - DPU_ERROR("Fail to disable IRQ for irq_idx:%d: %d\n", - irq_idx, ret); + DPU_ERROR("Failed to disable IRQ=[%d, %d]: %d\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), ret); - dpu_kms->hw_intr->irq_tbl[irq_idx].cb = NULL; - dpu_kms->hw_intr->irq_tbl[irq_idx].arg = NULL; + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, irq_idx); + irq_entry->cb = NULL; + irq_entry->arg = NULL; spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); - trace_dpu_irq_unregister_success(irq_idx); + trace_dpu_irq_unregister_success(DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return 0; } @@ -584,18 +604,21 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx) static int dpu_debugfs_core_irq_show(struct seq_file *s, void *v) { struct dpu_kms *dpu_kms = s->private; + struct dpu_hw_intr_entry *irq_entry; unsigned long irq_flags; int i, irq_count; void *cb; - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) { + for (i = 1; i <= DPU_NUM_IRQS; i++) { spin_lock_irqsave(&dpu_kms->hw_intr->irq_lock, irq_flags); - irq_count = atomic_read(&dpu_kms->hw_intr->irq_tbl[i].count); - cb = dpu_kms->hw_intr->irq_tbl[i].cb; + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + irq_count = atomic_read(&irq_entry->count); + cb = irq_entry->cb; spin_unlock_irqrestore(&dpu_kms->hw_intr->irq_lock, irq_flags); if (irq_count || cb) - seq_printf(s, "idx:%d irq:%d cb:%ps\n", i, irq_count, cb); + seq_printf(s, "IRQ=[%d, %d] count:%d cb:%ps\n", + DPU_IRQ_REG(i), DPU_IRQ_BIT(i), irq_count, cb); } return 0; @@ -614,6 +637,7 @@ void dpu_debugfs_core_irq_init(struct dpu_kms *dpu_kms, void dpu_core_irq_preinstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); + struct dpu_hw_intr_entry *irq_entry; int i; pm_runtime_get_sync(&dpu_kms->pdev->dev); @@ -621,22 +645,28 @@ void dpu_core_irq_preinstall(struct msm_kms *kms) dpu_disable_all_irqs(dpu_kms); pm_runtime_put_sync(&dpu_kms->pdev->dev); - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) - atomic_set(&dpu_kms->hw_intr->irq_tbl[i].count, 0); + for (i = 1; i <= DPU_NUM_IRQS; i++) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + atomic_set(&irq_entry->count, 0); + } } void dpu_core_irq_uninstall(struct msm_kms *kms) { struct dpu_kms *dpu_kms = to_dpu_kms(kms); + struct dpu_hw_intr_entry *irq_entry; int i; if (!dpu_kms->hw_intr) return; pm_runtime_get_sync(&dpu_kms->pdev->dev); - for (i = 0; i < dpu_kms->hw_intr->total_irqs; i++) - if (dpu_kms->hw_intr->irq_tbl[i].cb) - DPU_ERROR("irq_idx=%d still enabled/registered\n", i); + for (i = 1; i <= DPU_NUM_IRQS; i++) { + irq_entry = dpu_core_irq_get_entry(dpu_kms->hw_intr, i); + if (irq_entry->cb) + DPU_ERROR("IRQ=[%d, %d] still enabled/registered\n", + DPU_IRQ_REG(i), DPU_IRQ_BIT(i)); + } dpu_clear_irqs(dpu_kms); dpu_disable_all_irqs(dpu_kms); |