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

Commit a983672d authored by Subhash Jadavani's avatar Subhash Jadavani
Browse files

scsi: ufs: reduce the delay before DME access commands



If UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS quirk is enabled then we are always
adding 1ms delay before issuing DME commands but after experiments show
that 700us delay is more than enough. As we have atleast 20 different DME
commands issued during link initialization phase (as part of UFS device
detection), this change should help reduce the total UFS device detection
time by atleast 6ms.

Change-Id: I495cec3916dbaa974d204d790f0dbc3d6753ba6f
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent b1932bb3
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -293,6 +293,8 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused);
static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba);
static inline void ufshcd_save_tstamp_of_last_dme_cmd(struct ufs_hba *hba);
static int ufshcd_host_reset_and_restore(struct ufs_hba *hba);
static void ufshcd_resume_clkscaling(struct ufs_hba *hba);
static void ufshcd_suspend_clkscaling(struct ufs_hba *hba);
@@ -1884,12 +1886,15 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)

	ufshcd_hold_all(hba);
	mutex_lock(&hba->uic_cmd_mutex);
	ufshcd_add_delay_before_dme_cmd(hba);

	spin_lock_irqsave(hba->host->host_lock, flags);
	ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
	spin_unlock_irqrestore(hba->host->host_lock, flags);
	if (!ret)
		ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);

	ufshcd_save_tstamp_of_last_dme_cmd(hba);
	mutex_unlock(&hba->uic_cmd_mutex);
	ufshcd_release_all(hba);
	return ret;
@@ -3178,6 +3183,44 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
	return ret;
}

static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba)
{
	#define MIN_DELAY_BEFORE_DME_CMDS_US	700
	unsigned long min_sleep_time_us;

	if (!(hba->quirks & UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS))
		return;

	/*
	 * last_dme_cmd_tstamp will be 0 only for 1st call to
	 * this function
	 */
	if (unlikely(!ktime_to_us(hba->last_dme_cmd_tstamp))) {
		min_sleep_time_us = MIN_DELAY_BEFORE_DME_CMDS_US;
	} else {
		unsigned long delta =
			(unsigned long) ktime_to_us(
				ktime_sub(ktime_get(),
				hba->last_dme_cmd_tstamp));

		if (delta < MIN_DELAY_BEFORE_DME_CMDS_US)
			min_sleep_time_us =
				MIN_DELAY_BEFORE_DME_CMDS_US - delta;
		else
			return; /* no more delay required */
	}

	/* allow sleep for extra 50us if needed */
	usleep_range(min_sleep_time_us, min_sleep_time_us + 50);
}

static inline void ufshcd_save_tstamp_of_last_dme_cmd(
			struct ufs_hba *hba)
{
	if (hba->quirks & UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS)
		hba->last_dme_cmd_tstamp = ktime_get();
}

/**
 * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
 * @hba: per adapter instance
@@ -3207,16 +3250,11 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
	uic_cmd.argument3 = mib_val;

	do {
		/* for stability purposes */
		if (hba->quirks & UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS)
			usleep_range(1000, 1100);

		/* for peer attributes we retry upon failure */
		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
		if (ret)
			dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
				set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);

	} while (ret && peer && --retries);

	if (!retries)
@@ -3279,10 +3317,6 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
	uic_cmd.argument1 = attr_sel;

	do {
		/* for stability purposes */
		if (hba->quirks & UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS)
			usleep_range(1000, 1100);

		/* for peer attributes we retry upon failure */
		ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
		if (ret)
@@ -3330,6 +3364,7 @@ int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)

	mutex_lock(&hba->uic_cmd_mutex);
	init_completion(&uic_async_done);
	ufshcd_add_delay_before_dme_cmd(hba);

	spin_lock_irqsave(hba->host->host_lock, flags);
	hba->uic_async_done = &uic_async_done;
@@ -3366,6 +3401,7 @@ int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
		ret = (status != PWR_OK) ? status : -1;
	}
out:
	ufshcd_save_tstamp_of_last_dme_cmd(hba);
	spin_lock_irqsave(hba->host->host_lock, flags);
	hba->uic_async_done = NULL;
	spin_unlock_irqrestore(hba->host->host_lock, flags);
+2 −0
Original line number Diff line number Diff line
@@ -513,6 +513,7 @@ struct ufshcd_pm_qos {
 * @saved_err: sticky error mask
 * @saved_uic_err: sticky UIC error mask
 * @dev_cmd: ufs device management command information
 * @last_dme_cmd_tstamp: time stamp of the last completed DME command
 * @auto_bkops_enabled: to track whether bkops is enabled in device
 * @vreg_info: UFS device voltage regulator information
 * @clk_list_head: UFS host controller clocks list node head
@@ -633,6 +634,7 @@ struct ufs_hba {

	/* Device management request data */
	struct ufs_dev_cmd dev_cmd;
	ktime_t last_dme_cmd_tstamp;

	/* Keeps information of the UFS device connected to this host */
	struct ufs_dev_info dev_info;