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

Commit 3997870e authored by Yaniv Gardi's avatar Yaniv Gardi Committed by David Keitel
Browse files

scsi: ufs: fix bug when changing power mode via debugfs



So far when required to change UFS power mode via debugfs the final power
parameters to which the UFS device is configured were determined based on
comparison between the new required power (gear, lane, mode) and qcom
pre-defined power preferences, and the minimum between them was the
configured power which is incorrect.
This change fixes this issue so what is done is a comparison between
the new required power and the device maximum supported power
parameters. If the new required power parameters exceed the device
maximum supported power, then the UFS power mode is not changed.

This change also contains a few cosmetic changes that simplify
code that is related to the above power change.

Change-Id: If08d3ce50af2dc17a6f68583dd1e7973aeb3c33a
Signed-off-by: default avatarYaniv Gardi <ygardi@codeaurora.org>
[subhashj@codeaurora.org: resolved merge conflicts]
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
[venkatg@codeaurora.org: resolved trivial merge conflicts]
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
parent a343f60a
Loading
Loading
Loading
Loading
+120 −15
Original line number Diff line number Diff line
@@ -642,28 +642,124 @@ static int ufsdbg_power_mode_show(struct seq_file *file, void *data)
static bool ufsdbg_power_mode_validate(struct ufs_pa_layer_attr *pwr_mode)
{
	if (pwr_mode->gear_rx < UFS_PWM_G1 || pwr_mode->gear_rx > UFS_PWM_G7 ||
		pwr_mode->gear_tx < UFS_PWM_G1 || pwr_mode->gear_tx > UFS_PWM_G7
		|| pwr_mode->lane_rx < 1 || pwr_mode->lane_rx > 2 ||
	    pwr_mode->gear_tx < UFS_PWM_G1 || pwr_mode->gear_tx > UFS_PWM_G7 ||
	    pwr_mode->lane_rx < 1 || pwr_mode->lane_rx > 2 ||
	    pwr_mode->lane_tx < 1 || pwr_mode->lane_tx > 2 ||
		(pwr_mode->pwr_rx != FAST_MODE &&
		pwr_mode->pwr_rx != SLOW_MODE &&
	    (pwr_mode->pwr_rx != FAST_MODE && pwr_mode->pwr_rx != SLOW_MODE &&
	     pwr_mode->pwr_rx != FASTAUTO_MODE &&
	     pwr_mode->pwr_rx != SLOWAUTO_MODE) ||
		(pwr_mode->pwr_tx != FAST_MODE &&
		pwr_mode->pwr_tx != SLOW_MODE &&
	    (pwr_mode->pwr_tx != FAST_MODE && pwr_mode->pwr_tx != SLOW_MODE &&
	     pwr_mode->pwr_tx != FASTAUTO_MODE &&
		pwr_mode->pwr_tx != SLOWAUTO_MODE))
	     pwr_mode->pwr_tx != SLOWAUTO_MODE)) {
		pr_err("%s: power parameters are not valid\n", __func__);
		return false;
	}

	return true;
}

static int ufsdbg_cfg_pwr_param(struct ufs_hba *hba,
				struct ufs_pa_layer_attr *new_pwr,
				struct ufs_pa_layer_attr *final_pwr)
{
	int ret = 0;
	bool is_dev_sup_hs = false;
	bool is_new_pwr_hs = false;
	int dev_pwm_max_rx_gear;
	int dev_pwm_max_tx_gear;

	if (!hba->max_pwr_info.is_valid) {
		dev_err(hba->dev, "%s: device max power is not valid. can't configure power\n",
			__func__);
		return -EINVAL;
	}

	if (hba->max_pwr_info.info.pwr_rx == FAST_MODE)
		is_dev_sup_hs = true;

	if (new_pwr->pwr_rx == FAST_MODE || new_pwr->pwr_rx == FASTAUTO_MODE)
		is_new_pwr_hs = true;

	final_pwr->lane_rx = hba->max_pwr_info.info.lane_rx;
	final_pwr->lane_tx = hba->max_pwr_info.info.lane_tx;

	/* device doesn't support HS but requested power is HS */
	if (!is_dev_sup_hs && is_new_pwr_hs) {
		pr_err("%s: device doesn't support HS. requested power is HS\n",
			__func__);
		return -ENOTSUPP;
	} else if ((is_dev_sup_hs && is_new_pwr_hs) ||
		   (!is_dev_sup_hs && !is_new_pwr_hs)) {
		/*
		 * If device and requested power mode are both HS or both PWM
		 * then dev_max->gear_xx are the gears to be assign to
		 * final_pwr->gear_xx
		 */
		final_pwr->gear_rx = hba->max_pwr_info.info.gear_rx;
		final_pwr->gear_tx = hba->max_pwr_info.info.gear_tx;
	} else if (is_dev_sup_hs && !is_new_pwr_hs) {
		/*
		 * If device supports HS but requested power is PWM, then we
		 * need to find out what is the max gear in PWM the device
		 * supports
		 */

		ufshcd_dme_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR),
			       &dev_pwm_max_rx_gear);

		if (!dev_pwm_max_rx_gear) {
			pr_err("%s: couldn't get device max pwm rx gear\n",
				__func__);
			ret = -EINVAL;
			goto out;
		}

		ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXPWMGEAR),
				    &dev_pwm_max_tx_gear);

		if (!dev_pwm_max_tx_gear) {
			pr_err("%s: couldn't get device max pwm tx gear\n",
				__func__);
			ret = -EINVAL;
			goto out;
		}

		final_pwr->gear_rx = dev_pwm_max_rx_gear;
		final_pwr->gear_tx = dev_pwm_max_tx_gear;
	}

	if ((new_pwr->gear_rx > final_pwr->gear_rx) ||
	    (new_pwr->gear_tx > final_pwr->gear_tx) ||
	    (new_pwr->lane_rx > final_pwr->lane_rx) ||
	    (new_pwr->lane_tx > final_pwr->lane_tx)) {
		pr_err("%s: (RX,TX) GG,LL: in PWM/HS new pwr [%d%d,%d%d] exceeds device limitation [%d%d,%d%d]\n",
			__func__,
			new_pwr->gear_rx, new_pwr->gear_tx,
			new_pwr->lane_rx, new_pwr->lane_tx,
			final_pwr->gear_rx, final_pwr->gear_tx,
			final_pwr->lane_rx, final_pwr->lane_tx);
		return -ENOTSUPP;
	}

	final_pwr->gear_rx = new_pwr->gear_rx;
	final_pwr->gear_tx = new_pwr->gear_tx;
	final_pwr->lane_rx = new_pwr->lane_rx;
	final_pwr->lane_tx = new_pwr->lane_tx;
	final_pwr->pwr_rx = new_pwr->pwr_rx;
	final_pwr->pwr_tx = new_pwr->pwr_tx;
	final_pwr->hs_rate = new_pwr->hs_rate;

out:
	return ret;
}

static ssize_t ufsdbg_power_mode_write(struct file *file,
				const char __user *ubuf, size_t cnt,
				loff_t *ppos)
{
	struct ufs_hba *hba = file->f_mapping->host->i_private;
	struct ufs_pa_layer_attr pwr_mode;
	struct ufs_pa_layer_attr final_pwr_mode;
	char pwr_mode_str[BUFF_LINE_CAPACITY] = {0};
	loff_t buff_pos = 0;
	int ret;
@@ -679,6 +775,7 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
	pwr_mode.lane_tx = pwr_mode_str[idx++] - '0';
	pwr_mode.pwr_rx = pwr_mode_str[idx++] - '0';
	pwr_mode.pwr_tx = pwr_mode_str[idx++] - '0';

	/*
	 * Switching between rates is not currently supported so use the
	 * current rate.
@@ -690,16 +787,24 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
	if (!ufsdbg_power_mode_validate(&pwr_mode))
		return -EINVAL;

	pr_debug(
		"%s: new power mode requested [RX,TX]: Gear=[%d,%d] Lanes=[%d,%d], Mode=[%d,%d]\n",
		__func__, pwr_mode.gear_rx, pwr_mode.gear_tx, pwr_mode.lane_rx,
	pr_debug("%s: new power mode requested [RX,TX]: Gear=[%d,%d], Lane=[%d,%d], Mode=[%d,%d]\n",
		__func__,
		pwr_mode.gear_rx, pwr_mode.gear_tx, pwr_mode.lane_rx,
		pwr_mode.lane_tx, pwr_mode.pwr_rx, pwr_mode.pwr_tx);

	ret = ufsdbg_cfg_pwr_param(hba, &pwr_mode, &final_pwr_mode);
	if (ret) {
		dev_err(hba->dev,
			"%s: failed to configure new power parameters, ret = %d\n",
			__func__, ret);
		return cnt;
	}

	pm_runtime_get_sync(hba->dev);
	scsi_block_requests(hba->host);
	ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US);
	if (!ret)
		ret = ufshcd_config_pwr_mode(hba, &pwr_mode);
		ret = ufshcd_change_power_mode(hba, &final_pwr_mode);
	scsi_unblock_requests(hba->host);
	pm_runtime_put_sync(hba->dev);
	if (ret == -EBUSY)
+76 −159
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@
#include "ufs-qcom.h"
#include "ufshci.h"

static int ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
		const char *speed_mode);
static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
@@ -546,157 +546,86 @@ struct ufs_qcom_dev_params {
	u32 desired_working_mode;
};

/**
 * as every power mode, according to the UFS spec, have a defined
 * number that are not corresponed to their order or power
 * consumption (i.e 5, 2, 4, 1 respectively from low to high),
 * we need to map them into array, so we can scan it easily
 * in order to find the minimum required power mode.
 * also, we can use this routine to go the other way around,
 * and from array index, the fetch the correspond power mode.
 */
static int map_unmap_pwr_mode(u32 mode, bool is_pwr_to_arr)
{
	enum {SL_MD = 0, SLA_MD = 1, FS_MD = 2, FSA_MD = 3, UNDEF = 4};
	int ret = -EINVAL;

	if (is_pwr_to_arr) {
		switch (mode) {
		case SLOW_MODE:
			ret = SL_MD;
			break;
		case SLOWAUTO_MODE:
			ret = SLA_MD;
			break;
		case FAST_MODE:
			ret = FS_MD;
			break;
		case FASTAUTO_MODE:
			ret = FSA_MD;
			break;
		default:
			ret = UNDEF;
			break;
		}
	} else {
		switch (mode) {
		case SL_MD:
			ret = SLOW_MODE;
			break;
		case SLA_MD:
			ret = SLOWAUTO_MODE;
			break;
		case FS_MD:
			ret = FAST_MODE;
			break;
		case FSA_MD:
			ret = FASTAUTO_MODE;
			break;
		default:
			ret = -EINVAL;
			break;
		}
	}

	return ret;
}

#define NUM_OF_SUPPORTED_MODES	5
static int get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param,
static int ufs_qcom_get_pwr_dev_param(struct ufs_qcom_dev_params *qcom_param,
				      struct ufs_pa_layer_attr *dev_max,
			     struct ufs_pa_layer_attr *dev_req)
				      struct ufs_pa_layer_attr *agreed_pwr)
{
	int arr[NUM_OF_SUPPORTED_MODES] = {0};
	int i;
	int min_power;
	int min_qcom_gear;
	int min_dev_gear;
	bool is_max_dev_hs;
	bool is_max_qcom_hs;
	bool is_dev_sup_hs = false;
	bool is_qcom_max_hs = false;

	/**
	 * mapping the max. supported power mode of the device
	 * and the max. pre-defined support power mode of the vendor
	 * in order to scan them easily
	 */
	arr[map_unmap_pwr_mode(dev_max->pwr_rx, true)]++;
	arr[map_unmap_pwr_mode(dev_max->pwr_tx, true)]++;
	if (dev_max->pwr_rx == FAST_MODE)
		is_dev_sup_hs = true;

	if (qcom_param->desired_working_mode == SLOW) {
		arr[map_unmap_pwr_mode(qcom_param->rx_pwr_pwm, true)]++;
		arr[map_unmap_pwr_mode(qcom_param->tx_pwr_pwm, true)]++;
	if (qcom_param->desired_working_mode == FAST) {
		is_qcom_max_hs = true;
		min_qcom_gear = min_t(u32, qcom_param->hs_rx_gear,
				      qcom_param->hs_tx_gear);
	} else {
		arr[map_unmap_pwr_mode(qcom_param->rx_pwr_hs, true)]++;
		arr[map_unmap_pwr_mode(qcom_param->tx_pwr_hs, true)]++;
	}

	for (i = 0; i < NUM_OF_SUPPORTED_MODES; ++i) {
		if (arr[i] != 0)
			break;
		min_qcom_gear = min_t(u32, qcom_param->pwm_rx_gear,
				      qcom_param->pwm_tx_gear);
	}

	/* no supported power mode found */
	if (i == NUM_OF_SUPPORTED_MODES) {
		return -EINVAL;
	/*
	 * device doesn't support HS but qcom_param->desired_working_mode is
	 * HS, thus device and qcom_param don't agree
	 */
	if (!is_dev_sup_hs && is_qcom_max_hs) {
		pr_err("%s: failed to agree on power mode (device doesn't support HS but requested power is HS)\n",
			__func__);
		return -ENOTSUPP;
	} else if (is_dev_sup_hs && is_qcom_max_hs) {
		/*
		 * since device supports HS, it supports FAST_MODE.
		 * since qcom_param->desired_working_mode is also HS
		 * then final decision (FAST/FASTAUTO) is done according
		 * to qcom_params as it is the restricting factor
		 */
		agreed_pwr->pwr_rx = agreed_pwr->pwr_tx =
						qcom_param->rx_pwr_hs;
	} else {
		min_power = map_unmap_pwr_mode(i, false);
		if (min_power >= 0)
			dev_req->pwr_rx = dev_req->pwr_tx = min_power;
		else
			return -EINVAL;
		/*
		 * here qcom_param->desired_working_mode is PWM.
		 * it doesn't matter whether device supports HS or PWM,
		 * in both cases qcom_param->desired_working_mode will
		 * determine the mode
		 */
		 agreed_pwr->pwr_rx = agreed_pwr->pwr_tx =
						qcom_param->rx_pwr_pwm;
	}

	/**
	/*
	 * we would like tx to work in the minimum number of lanes
	 * between device capability and vendor preferences.
	 * the same decision will be made for rx.
	 * the same decision will be made for rx
	 */
	dev_req->lane_tx = min_t(u32, dev_max->lane_tx, qcom_param->tx_lanes);
	dev_req->lane_rx = min_t(u32, dev_max->lane_rx, qcom_param->rx_lanes);

	if (dev_max->pwr_rx == SLOW_MODE ||
	    dev_max->pwr_rx == SLOWAUTO_MODE)
		is_max_dev_hs = false;
	else
		is_max_dev_hs = true;
	agreed_pwr->lane_tx = min_t(u32, dev_max->lane_tx,
						qcom_param->tx_lanes);
	agreed_pwr->lane_rx = min_t(u32, dev_max->lane_rx,
						qcom_param->rx_lanes);

	/* setting the device maximum gear */
	/* device maximum gear is the minimum between device rx and tx gears */
	min_dev_gear = min_t(u32, dev_max->gear_rx, dev_max->gear_tx);

	/**
	 * setting the desired gear to be the minimum according to the desired
	 * power mode
	 */
	if (qcom_param->desired_working_mode == SLOW) {
		is_max_qcom_hs = false;
		min_qcom_gear = min_t(u32, qcom_param->pwm_rx_gear,
						qcom_param->pwm_tx_gear);
	} else {
		is_max_qcom_hs = true;
		min_qcom_gear = min_t(u32, qcom_param->hs_rx_gear,
						qcom_param->hs_tx_gear);
	}

	/**
	/*
	 * if both device capabilities and vendor pre-defined preferences are
	 * both HS or both PWM then set the minimum gear to be the
	 * chosen working gear.
	 * both HS or both PWM then set the minimum gear to be the chosen
	 * working gear.
	 * if one is PWM and one is HS then the one that is PWM get to decide
	 * what the gear, as he is the one that also decided previously what
	 * what is the gear, as it is the one that also decided previously what
	 * pwr the device will be configured to.
	 */
	if ((is_max_dev_hs && is_max_qcom_hs) ||
	    (!is_max_dev_hs && !is_max_qcom_hs)) {
		dev_req->gear_rx = dev_req->gear_tx =
	if ((is_dev_sup_hs && is_qcom_max_hs) ||
	    (!is_dev_sup_hs && !is_qcom_max_hs))
		agreed_pwr->gear_rx = agreed_pwr->gear_tx =
			min_t(u32, min_dev_gear, min_qcom_gear);
	} else if (!is_max_dev_hs) {
		dev_req->gear_rx = dev_req->gear_tx = min_dev_gear;
	} else {
		dev_req->gear_rx = dev_req->gear_tx = min_qcom_gear;
	}

	dev_req->hs_rate = qcom_param->hs_rate;
	else if (!is_dev_sup_hs)
		agreed_pwr->gear_rx = agreed_pwr->gear_tx = min_dev_gear;
	else
		agreed_pwr->gear_rx = agreed_pwr->gear_tx = min_qcom_gear;

	agreed_pwr->hs_rate = qcom_param->hs_rate;
	return 0;
}

@@ -706,9 +635,7 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
	int err = 0;
	char mode[BUS_VECTOR_NAME_LEN];

	err = ufs_qcom_get_speed_mode(&host->dev_req_params, mode);
	if (err)
		goto out;
	ufs_qcom_get_speed_mode(&host->dev_req_params, mode);

	vote = ufs_qcom_get_bus_vote(host, mode);
	if (vote >= 0)
@@ -716,7 +643,6 @@ static int ufs_qcom_update_bus_bw_vote(struct ufs_qcom_host *host)
	else
		err = vote;

out:
	if (err)
		dev_err(host->hba->dev, "%s: failed %d\n", __func__, err);
	else
@@ -758,7 +684,8 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
		ufs_qcom_cap.desired_working_mode =
					UFS_QCOM_LIMIT_DESIRED_MODE;

		ret = get_pwr_dev_param(&ufs_qcom_cap, dev_max_params,
		ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap,
						 dev_max_params,
						 dev_req_params);
		if (ret) {
			pr_err("%s: failed to determine capabilities\n",
@@ -875,13 +802,11 @@ out:
	return err;
}

static int ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
{
	int err = 0;
	int gear = max_t(u32, p->gear_rx, p->gear_tx);
	int lanes = max_t(u32, p->lane_rx, p->lane_tx);
	int pwr = max_t(u32, map_unmap_pwr_mode(p->pwr_rx, true),
			map_unmap_pwr_mode(p->pwr_tx, true));
	int pwr;

	/* default to PWM Gear 1, Lane 1 if power mode is not initialized */
	if (!gear)
@@ -891,26 +816,18 @@ static int ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result)
		lanes = 1;

	if (!p->pwr_rx && !p->pwr_tx)
		pwr = 0;

	pwr = map_unmap_pwr_mode(pwr, false);
	if (pwr < 0) {
		err = pwr;
		goto out;
	}

	if (pwr == FAST_MODE || pwr == FASTAUTO_MODE)
		pwr = SLOWAUTO_MODE;
	else if (p->pwr_rx == FAST_MODE || p->pwr_rx == FASTAUTO_MODE ||
		 p->pwr_tx == FAST_MODE || p->pwr_tx == FASTAUTO_MODE) {
		pwr = FAST_MODE;
		snprintf(result, BUS_VECTOR_NAME_LEN, "%s_R%s_G%d_L%d", "HS",
				p->hs_rate == PA_HS_MODE_B ? "B" : "A",
				gear, lanes);
	else
			 p->hs_rate == PA_HS_MODE_B ? "B" : "A", gear, lanes);
	} else {
		pwr = SLOW_MODE;
		snprintf(result, BUS_VECTOR_NAME_LEN, "%s_G%d_L%d",
			 "PWM", gear, lanes);
out:
	return err;
	}


}

static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
{
+6 −8
Original line number Diff line number Diff line
@@ -291,8 +291,6 @@ 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);
static irqreturn_t ufshcd_intr(int irq, void *__hba);
static int ufshcd_change_power_mode(struct ufs_hba *hba,
			     struct ufs_pa_layer_attr *pwr_mode);

static inline int ufshcd_enable_irq(struct ufs_hba *hba)
{
@@ -2913,8 +2911,8 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
	if (hba->max_pwr_info.is_valid)
		return 0;

	pwr_info->pwr_tx = FASTAUTO_MODE;
	pwr_info->pwr_rx = FASTAUTO_MODE;
	pwr_info->pwr_tx = FAST_MODE;
	pwr_info->pwr_rx = FAST_MODE;
	pwr_info->hs_rate = PA_HS_MODE_B;

	/* Get the connected lane count */
@@ -2945,7 +2943,7 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
				__func__, pwr_info->gear_rx);
			return -EINVAL;
		}
		pwr_info->pwr_rx = SLOWAUTO_MODE;
		pwr_info->pwr_rx = SLOW_MODE;
	}

	ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_MAXRXHSGEAR),
@@ -2958,14 +2956,14 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba)
				__func__, pwr_info->gear_tx);
			return -EINVAL;
		}
		pwr_info->pwr_tx = SLOWAUTO_MODE;
		pwr_info->pwr_tx = SLOW_MODE;
	}

	hba->max_pwr_info.is_valid = true;
	return 0;
}

static int ufshcd_change_power_mode(struct ufs_hba *hba,
int ufshcd_change_power_mode(struct ufs_hba *hba,
			     struct ufs_pa_layer_attr *pwr_mode)
{
	int ret;
@@ -3038,7 +3036,7 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
 * @hba: per-adapter instance
 * @desired_pwr_mode: desired power configuration
 */
int ufshcd_config_pwr_mode(struct ufs_hba *hba,
static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
		struct ufs_pa_layer_attr *desired_pwr_mode)
{
	struct ufs_pa_layer_attr final_params = { 0 };
+2 −2
Original line number Diff line number Diff line
@@ -699,8 +699,6 @@ extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
			       u8 attr_set, u32 mib_val, u8 peer);
extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
			       u32 *mib_val, u8 peer);
extern int ufshcd_config_pwr_mode(struct ufs_hba *hba,
		struct ufs_pa_layer_attr *desired_pwr_mode);

/* UIC command interfaces for DME primitives */
#define DME_LOCAL	0
@@ -774,6 +772,8 @@ int ufshcd_query_descriptor(struct ufs_hba *hba, enum query_opcode opcode,
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us);
int ufshcd_change_power_mode(struct ufs_hba *hba,
			     struct ufs_pa_layer_attr *pwr_mode);

/* Wrapper functions for safely calling variant operations */
static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)