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

Commit b92a1589 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add interrupt disable function without lock"

parents 511b791b 0693000f
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -202,6 +202,44 @@ int sde_core_irq_disable(struct sde_kms *sde_kms, int *irq_idxs, u32 irq_count)
	return ret;
}

/**
 * sde_core_irq_disable_nolock - disable core interrupt given by the index
 *                               without lock
 * @sde_kms:		Pointer to sde kms context
 * @irq_idx:		interrupt index
 */
int sde_core_irq_disable_nolock(struct sde_kms *sde_kms, int irq_idx)
{
	int ret = 0;

	if (!sde_kms || !sde_kms->hw_intr || !sde_kms->irq_obj.enable_counts) {
		SDE_ERROR("invalid params\n");
		return -EINVAL;
	}

	if (irq_idx < 0 || irq_idx >= sde_kms->hw_intr->irq_idx_tbl_size) {
		SDE_ERROR("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	SDE_DEBUG("irq_idx=%d enable_count=%d\n", irq_idx,
			atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));

	SDE_EVT32(irq_idx,
			atomic_read(&sde_kms->irq_obj.enable_counts[irq_idx]));
	if (atomic_dec_return(&sde_kms->irq_obj.enable_counts[irq_idx]) == 0) {
		ret = sde_kms->hw_intr->ops.disable_irq_nolock(
				sde_kms->hw_intr,
				irq_idx);
		if (ret)
			SDE_ERROR("Fail to disable IRQ for irq_idx:%d\n",
					irq_idx);
		SDE_DEBUG("irq_idx=%d ret=%d\n", irq_idx, ret);
	}

	return ret;
}

u32 sde_core_irq_read_nolock(struct sde_kms *sde_kms, int irq_idx, bool clear)
{
	if (!sde_kms || !sde_kms->hw_intr ||
+13 −0
Original line number Diff line number Diff line
@@ -101,6 +101,19 @@ int sde_core_irq_disable(
		int *irq_idxs,
		uint32_t irq_count);

/**
 * sde_core_irq_disable_nolock - no lock version of sde_core_irq_disable
 * @sde_kms:		SDE handle
 * @irq_idx:		Irq index
 * @return:		0 for success disabling IRQ, otherwise failure
 *
 * This function increments count on each enable and decrements on each
 * disable.  Interrupts is disabled if count is 0 after decrement.
 */
int sde_core_irq_disable_nolock(
		struct sde_kms *sde_kms,
		int irq_idx);

/**
 * sde_core_irq_read - IRQ helper function for reading IRQ status
 * @sde_kms:		SDE handle
+21 −4
Original line number Diff line number Diff line
@@ -910,10 +910,9 @@ static int sde_hw_intr_enable_irq(struct sde_hw_intr *intr, int irq_idx)
	return 0;
}

static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
static int sde_hw_intr_disable_irq_nolock(struct sde_hw_intr *intr, int irq_idx)
{
	int reg_idx;
	unsigned long irq_flags;
	const struct sde_intr_reg *reg;
	const struct sde_irq_type *irq;
	const char *dbgstr = NULL;
@@ -931,7 +930,6 @@ static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
	reg_idx = irq->reg_idx;
	reg = &sde_intr_set[reg_idx];

	spin_lock_irqsave(&intr->irq_lock, irq_flags);
	cache_irq_mask = intr->cache_irq_mask[reg_idx];
	if ((cache_irq_mask & irq->irq_mask) == 0) {
		dbgstr = "SDE IRQ is already cleared:";
@@ -949,7 +947,6 @@ static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)

		intr->cache_irq_mask[reg_idx] = cache_irq_mask;
	}
	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);

	pr_debug("%s MASK:0x%.8x, CACHE-MASK:0x%.8x\n", dbgstr,
			irq->irq_mask, cache_irq_mask);
@@ -957,6 +954,25 @@ static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
	return 0;
}

static int sde_hw_intr_disable_irq(struct sde_hw_intr *intr, int irq_idx)
{
	unsigned long irq_flags;

	if (!intr)
		return -EINVAL;

	if (irq_idx < 0 || irq_idx >= ARRAY_SIZE(sde_irq_map)) {
		pr_err("invalid IRQ index: [%d]\n", irq_idx);
		return -EINVAL;
	}

	spin_lock_irqsave(&intr->irq_lock, irq_flags);
	sde_hw_intr_disable_irq_nolock(intr, irq_idx);
	spin_unlock_irqrestore(&intr->irq_lock, irq_flags);

	return 0;
}

static int sde_hw_intr_clear_irqs(struct sde_hw_intr *intr)
{
	int i;
@@ -1141,6 +1157,7 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops)
	ops->irq_idx_lookup = sde_hw_intr_irqidx_lookup;
	ops->enable_irq = sde_hw_intr_enable_irq;
	ops->disable_irq = sde_hw_intr_disable_irq;
	ops->disable_irq_nolock = sde_hw_intr_disable_irq_nolock;
	ops->dispatch_irqs = sde_hw_intr_dispatch_irq;
	ops->clear_all_irqs = sde_hw_intr_clear_irqs;
	ops->disable_all_irqs = sde_hw_intr_disable_irqs;
+10 −0
Original line number Diff line number Diff line
@@ -138,6 +138,16 @@ struct sde_hw_intr_ops {
			struct sde_hw_intr *intr,
			int irq_idx);

	/**
	 * disable_irq_nolock - Disable IRQ based on IRQ index without lock
	 * @intr:	HW interrupt handle
	 * @irq_idx:	Lookup irq index return from irq_idx_lookup
	 * @return:	0 for success, otherwise failure
	 */
	int (*disable_irq_nolock)(
			struct sde_hw_intr *intr,
			int irq_idx);

	/**
	 * clear_all_irqs - Clears all the interrupts (i.e. acknowledges
	 *                  any asserted IRQs). Useful during reset.