Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47db35db authored by Ingrid Gallardo's avatar Ingrid Gallardo
Browse files

drm/msm/sde: optimize sde interrupts handling



Current interrupt handler in the sde driver looks
up within a static hash table for the interrupts
that driver needs to service.
Current table holds placeholders for interrupts
which are not in use, this unnecessarily
increments the number of loops to find the
interrupt that needs to be serviced.
This change optimizes the execution by
dynamically allocating the hash table during
initialization with the valid interrupts for
the target, and also prioritize the interrupts
that are most likely to be triggered during
common use cases by adding them at the top of
the table.

Change-Id: I298c6398e1694bb646cb346282f4773246d71946
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent c2cea8f6
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -83,7 +83,8 @@ int sde_core_irq_idx_lookup(struct sde_kms *sde_kms,
			!sde_kms->hw_intr->ops.irq_idx_lookup)
		return -EINVAL;

	return sde_kms->hw_intr->ops.irq_idx_lookup(intr_type,
	return sde_kms->hw_intr->ops.irq_idx_lookup(
			sde_kms->hw_intr, intr_type,
			instance_idx);
}

@@ -104,7 +105,7 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx)
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->sde_irq_map_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}
@@ -171,7 +172,7 @@ static int _sde_core_irq_disable(struct sde_kms *sde_kms, int irq_idx)
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->sde_irq_map_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}
@@ -231,7 +232,7 @@ int sde_core_irq_disable_nolock(struct sde_kms *sde_kms, int irq_idx)
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->sde_irq_map_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}
@@ -304,7 +305,7 @@ int sde_core_irq_register_callback(struct sde_kms *sde_kms, int irq_idx,
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->sde_irq_map_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}
@@ -339,7 +340,7 @@ int sde_core_irq_unregister_callback(struct sde_kms *sde_kms, int irq_idx,
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->sde_irq_map_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}
@@ -482,7 +483,7 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
	spin_lock_init(&sde_kms->irq_obj.cb_lock);

	/* Create irq callbacks for all possible irq_idx */
	sde_kms->irq_obj.total_irqs = sde_kms->hw_intr->irq_idx_tbl_size;
	sde_kms->irq_obj.total_irqs = sde_kms->hw_intr->sde_irq_map_size;
	sde_kms->irq_obj.irq_cb_tbl = kcalloc(sde_kms->irq_obj.total_irqs,
			sizeof(struct list_head), GFP_KERNEL);
	sde_kms->irq_obj.enable_counts = kcalloc(sde_kms->irq_obj.total_irqs,
+2 −2
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ enum {
enum sde_intr_enum {
	MDSS_INTR_SSPP_TOP0_INTR,
	MDSS_INTR_SSPP_TOP0_INTR2,
	MDSS_INTF_TEAR_1_INTR,
	MDSS_INTF_TEAR_2_INTR,
	MDSS_INTR_SSPP_TOP0_HIST_INTR,
	MDSS_INTR_INTF_0_INTR,
	MDSS_INTR_INTF_1_INTR,
@@ -116,8 +118,6 @@ enum sde_intr_enum {
	MDSS_INTR_INTF_4_INTR,
	MDSS_INTR_AD4_0_INTR,
	MDSS_INTR_AD4_1_INTR,
	MDSS_INTF_TEAR_1_INTR,
	MDSS_INTF_TEAR_2_INTR,
	MDSS_INTR_MAX
};

+319 −439

File changed.

Preview size limit exceeded, changes collapsed.

+6 −2
Original line number Diff line number Diff line
@@ -113,11 +113,13 @@ struct sde_hw_intr_ops {
	/**
	 * irq_idx_lookup - Lookup IRQ index on the HW interrupt type
	 *                 Used for all irq related ops
	 * @intr:	HW interrupt handle
	 * @intr_type:		Interrupt type defined in sde_intr_type
	 * @instance_idx:	HW interrupt block instance
	 * @return:		irq_idx or -EINVAL for lookup fail
	 */
	int (*irq_idx_lookup)(
			struct sde_hw_intr *intr,
			enum sde_intr_type intr_type,
			u32 instance_idx);

@@ -286,20 +288,22 @@ struct sde_hw_intr_ops {
 * @ops:              function pointer mapping for IRQ handling
 * @cache_irq_mask:   array of IRQ enable masks reg storage created during init
 * @save_irq_status:  array of IRQ status reg storage created during init
 * @irq_idx_tbl_size: total number of irq_idx mapped in the hw_interrupts
 * @irq_lock:         spinlock for accessing IRQ resources
 * @sde_irq_size:   total number of elements of the sde_irq_tbl
 * @sde_irq_tbl:	table with the registesrs offsets of the sde interrupts
 *		supported by the hw
 * @sde_irq_map_size: total number of elements of the 'sde_irq_map'
 * @sde_irq_map: total number of interrupt bits valid within the irq regs
 */
struct sde_hw_intr {
	struct sde_hw_blk_reg_map hw;
	struct sde_hw_intr_ops ops;
	u32 *cache_irq_mask;
	u32 *save_irq_status;
	u32 irq_idx_tbl_size;
	u32 sde_irq_size;
	struct sde_intr_reg *sde_irq_tbl;
	u32 sde_irq_map_size;
	struct sde_irq_type *sde_irq_map;
	spinlock_t irq_lock;
};