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

Commit 70798b70 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs: Logic to check UIC command timeout errors genuineness"

parents e5825f9f 84864682
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -3168,6 +3168,8 @@ ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
	/* Write UIC Cmd */
	ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK,
		      REG_UIC_COMMAND);
	/* Make sure that UIC command is committed immediately */
	wmb();
}

/**
@@ -5110,6 +5112,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
	u8 status;
	int ret;
	bool reenable_intr = false;
	int wait_retries = 6; /* Allows 3secs max wait time */

	mutex_lock(&hba->uic_cmd_mutex);
	init_completion(&uic_async_done);
@@ -5136,11 +5139,42 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
		goto out;
	}

more_wait:
	if (!wait_for_completion_timeout(hba->uic_async_done,
					 msecs_to_jiffies(UIC_CMD_TIMEOUT))) {
		u32 intr_status = 0;
		s64 ts_since_last_intr;

		dev_err(hba->dev,
			"pwr ctrl cmd 0x%x with mode 0x%x completion timeout\n",
			cmd->command, cmd->argument3);
		/*
		 * The controller must have triggered interrupt but ISR couldn't
		 * run due to interrupt starvation.
		 * Or ISR must have executed just after the timeout
		 * (which clears IS registers)
		 * If either of these two cases is true, then
		 * wait for little more time for completion.
		 */
		intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
		ts_since_last_intr = ktime_ms_delta(ktime_get(),
						hba->ufs_stats.last_intr_ts);

		if ((intr_status & UFSHCD_UIC_PWR_MASK) ||
		    ((hba->ufs_stats.last_intr_status & UFSHCD_UIC_PWR_MASK) &&
		     (ts_since_last_intr < (s64)UIC_CMD_TIMEOUT))) {
			dev_info(hba->dev, "IS:0x%08x last_intr_sts:0x%08x last_intr_ts:%lld, retry-cnt:%d\n",
				intr_status, hba->ufs_stats.last_intr_status,
				hba->ufs_stats.last_intr_ts, wait_retries);
			if (wait_retries--)
				goto more_wait;

			/*
			 * If same state continues event after more wait time,
			 * something must be hogging CPU.
			 */
			BUG_ON(hba->crash_on_err);
		}
		ret = -ETIMEDOUT;
		goto out;
	}