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

Commit 06eef38e authored by Can Guo's avatar Can Guo
Browse files

scsi: ufs: add support to double check the presence of UFS card



When UFS card is removed, as the extcon gpio has a debounce delay, the
state of the card is not updated simultaneously. If the presence of
UFS card is critical to decide if errors are caused by card removal in some
paths, such as error handler path, it would be not enough just check its
state. This change adds one func to check the presence of the UFS card. If
the state of the card is offline, then return false. If the state says
online then sleep 300ms, which is longer than the extcon gpio debounce
delay, then check the state again, if state is changed, it means the card
is removed.

Change-Id: I246d7444497793f55999bb9618612ade40bd36b5
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
parent cf8acfa8
Loading
Loading
Loading
Loading
+37 −26
Original line number Diff line number Diff line
@@ -375,6 +375,25 @@ static inline bool ufshcd_is_card_offline(struct ufs_hba *hba)
	return (atomic_read(&hba->card_state) == UFS_CARD_STATE_OFFLINE);
}

static bool ufshcd_is_card_present(struct ufs_hba *hba)
{
	if (ufshcd_is_card_online(hba))
		/*
		 * TODO: need better way to ensure that this delay is
		 * more than extcon's debounce-ms
		 */
		msleep(300);

	/*
	 * Check if card was online and offline/removed now or
	 * card was already offline.
	 */
	if (ufshcd_is_card_offline(hba))
		return false;

	return true;
}

static inline enum ufs_pm_level
ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
					enum uic_link_state link_state)
@@ -5126,7 +5145,9 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
	ufshcd_dme_cmd_log(hba, "dme_cmpl_2", hba->active_uic_cmd->command);

out:
	if (ret && !(hba->extcon && ufshcd_is_card_offline(hba))) {
	if (ret) {
		if (hba->extcon && !ufshcd_is_card_present(hba))
			goto skip_dump;
		ufsdbg_set_err_state(hba);
		ufshcd_print_host_state(hba);
		ufshcd_print_pwr_info(hba);
@@ -5135,6 +5156,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
		BUG_ON(hba->crash_on_err);
	}

skip_dump:
	ufshcd_save_tstamp_of_last_dme_cmd(hba);
	spin_lock_irqsave(hba->host->host_lock, flags);
	hba->active_uic_cmd = NULL;
@@ -6951,23 +6973,8 @@ static void ufshcd_err_handler(struct work_struct *work)

	hba = container_of(work, struct ufs_hba, eh_work);

	if (hba->extcon && !ufshcd_is_card_present(hba)) {
		spin_lock_irqsave(hba->host->host_lock, flags);
	if (hba->extcon) {
		if (ufshcd_is_card_online(hba)) {
			spin_unlock_irqrestore(hba->host->host_lock, flags);
			/*
			 * TODO: need better way to ensure that this delay is
			 * more than extcon's debounce-ms
			 */
			msleep(300);
			spin_lock_irqsave(hba->host->host_lock, flags);
		}

		/*
		 * ignore error if card was online and offline/removed now or
		 * card was already offline.
		 */
		if (ufshcd_is_card_offline(hba)) {
		hba->saved_err = 0;
		hba->saved_uic_err = 0;
		hba->saved_ce_err = 0;
@@ -6976,8 +6983,8 @@ static void ufshcd_err_handler(struct work_struct *work)
		hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL;
		goto out;
	}
	}

	spin_lock_irqsave(hba->host->host_lock, flags);
	ufsdbg_set_err_state(hba);

	if (hba->ufshcd_state == UFSHCD_STATE_RESET)
@@ -7165,6 +7172,10 @@ static void ufshcd_rls_handler(struct work_struct *work)
	u32 mode;

	hba = container_of(work, struct ufs_hba, rls_work);

	if (hba->extcon && !ufshcd_is_card_present(hba))
		return;

	pm_runtime_get_sync(hba->dev);
	ufshcd_scsi_block_requests(hba);
	down_write(&hba->lock);