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

Commit d69f5b83 authored by Sachin Bhayare's avatar Sachin Bhayare Committed by Krishna Manikandan
Browse files

msm: mdss: clear MDP3 DMA read ptr intr if detected before clk disable



Before disabling the DMA read ptr interrupt and turning off the clks,
there is a possibility that some other CPU might have received
READ_PTR ISR few microseconds before and started to process it.
By the time the ISR reaches the register read instructions,
the clks might be disabled and cause NOC error. To avoid such cases,
check for the intr status after disabling the ISR and clear the irq
before disabling the clks.

Change-Id: Idcc412bea6711e5bb62903c546ce54ff8243eadc
Signed-off-by: default avatarSachin Bhayare <sachin.bhayare@codeaurora.org>
parent 05bc74dd
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -159,7 +159,6 @@ static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
		spin_unlock(&mdata->irq_lock);
		return IRQ_HANDLED;
	}

	mdp_status = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
	mdp_interrupt = mdp_status;
	pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
@@ -2293,10 +2292,30 @@ static int mdp3_panel_register_done(struct mdss_panel_data *pdata)
	return rc;
}

/* mdp3_clear_irq() - Clear interrupt
 * @ interrupt_mask : interrupt mask
 *
 * This function clear sync irq for command mode panel.
 * When system is entering in idle screen state.
 */
void mdp3_clear_irq(u32 interrupt_mask)
{
	unsigned long flag;
	u32 irq_status = 0;

	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
	irq_status = interrupt_mask &
		MDP3_REG_READ(MDP3_REG_INTR_STATUS);
	if (irq_status)
		MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, irq_status);
	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);

}

/* mdp3_autorefresh_disable() - Disable Auto refresh
 * @ panel_info : pointer to panel configuration structure
 *
 * This function displable Auto refresh block for command mode panel.
 * This function disable Auto refresh block for command mode panel.
 */
int mdp3_autorefresh_disable(struct mdss_panel_info *panel_info)
{
+1 −1
Original line number Diff line number Diff line
@@ -264,7 +264,7 @@ u64 mdp3_clk_round_off(u64 clk_rate);

void mdp3_calc_dma_res(struct mdss_panel_info *panel_info, u64 *clk_rate,
		u64 *ab, u64 *ib, uint32_t bpp);

void mdp3_clear_irq(u32 interrupt_mask);

#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
+18 −10
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ static void mdp3_dispatch_clk_off(struct work_struct *work)

	mutex_lock(&session->lock);
	if (session->vsync_enabled ||
		atomic_read(&session->vsync_countdown) != 0) {
		atomic_read(&session->vsync_countdown) > 0) {
		mutex_unlock(&session->lock);
		pr_debug("Ignoring clk shut down\n");
		return;
@@ -201,7 +201,6 @@ retry_dma_done:
			}
		}
	}

	mdp3_ctrl_vsync_enable(session->mfd, 0);
	mdp3_ctrl_clk_enable(session->mfd, 0);
	mutex_unlock(&session->lock);
@@ -226,6 +225,7 @@ void vsync_count_down(void *arg)
{
	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
	/* We are counting down to turn off clocks */
	if (atomic_read(&session->vsync_countdown) > 0)
		atomic_dec(&session->vsync_countdown);
	if (atomic_read(&session->vsync_countdown) == 0)
		schedule_work(&session->clk_off_work);
@@ -243,6 +243,7 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
	struct mdp3_session_data *mdp3_session;
	struct mdp3_notification vsync_client;
	struct mdp3_notification *arg = NULL;
	bool mod_vsync_timer = false;

	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
@@ -258,7 +259,7 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
		vsync_client.handler = vsync_notify_handler;
		vsync_client.arg = mdp3_session;
		arg = &vsync_client;
	} else if (atomic_read(&mdp3_session->vsync_countdown)) {
	} else if (atomic_read(&mdp3_session->vsync_countdown) > 0) {
		/*
		 * Now that vsync is no longer needed we will
		 * shutdown dsi clocks as soon as cnt down == 0
@@ -270,6 +271,18 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
		enable = 1;
	}

	if (enable) {
		if (mdp3_session->status == 1 &&
			(mdp3_session->vsync_before_commit ||
			!mdp3_session->intf->active)) {
			mod_vsync_timer = true;
		} else if (!mdp3_session->clk_on) {
			/* Enable clocks before enabling the vsync interrupt */
			mdp3_ctrl_reset_countdown(mdp3_session, mfd);
			mdp3_ctrl_clk_enable(mfd, 1);
		}
	}

	mdp3_clk_enable(1, 0);
	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
	mdp3_clk_enable(0, 0);
@@ -278,14 +291,9 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
	 * Need to fake vsync whenever dsi interface is not
	 * active or when dsi clocks are currently off
	 */
	if (enable && mdp3_session->status == 1
			&& (mdp3_session->vsync_before_commit ||
			!mdp3_session->intf->active)) {
	if (mod_vsync_timer) {
		mod_timer(&mdp3_session->vsync_timer,
			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
	} else if (enable && !mdp3_session->clk_on) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_clk_enable(mfd, 1);
	} else if (!enable) {
		del_timer(&mdp3_session->vsync_timer);
	}
+6 −0
Original line number Diff line number Diff line
@@ -153,6 +153,12 @@ void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type)
			irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
			irq_bit += dma->dma_sel;
			mdp3_irq_disable(irq_bit);
			/*
			 * Clear read pointer interrupt before disabling clocks.
			 * Else pending ISR handling will result in NOC error
			 * since the clock will be disable after this point.
			 */
			mdp3_clear_irq(irq_bit);
		}

		if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {