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

Commit 6334ec60 authored by Dov Levenglick's avatar Dov Levenglick Committed by Gerrit - the friendly Code Review server
Browse files

scsi: ufs: splits vops and creates wrapper functions



This patch splits the vops by type and creates wrapper
functions for all vops.
Used in order clarify the runtime code and to allow
further types of vops.
This is the first step towards rearchitecting the
variant implementation of the UFS driver - per requirement
from the community. As this will become a full-blown
rearchitecture - incrementing the driver version.

Change-Id: Ifd0a5412a608590bc6c761caf0b3a87aed37f70b
Signed-off-by: default avatarDov Levenglick <dovl@codeaurora.org>
parent 1977b7ce
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -1681,8 +1681,7 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)

	ufsdbg_setup_fault_injection(hba);

	if (hba->vops && hba->vops->add_debugfs)
		hba->vops->add_debugfs(hba, hba->debugfs_files.debugfs_root);
	ufshcd_vops_add_debugfs(hba, hba->debugfs_files.debugfs_root);

	return;

@@ -1695,8 +1694,7 @@ err_no_root:

void ufsdbg_remove_debugfs(struct ufs_hba *hba)
{
	if (hba->vops && hba->vops->remove_debugfs)
		hba->vops->remove_debugfs(hba);
	ufshcd_vops_remove_debugfs(hba);
	debugfs_remove_recursive(hba->debugfs_files.debugfs_root);
	kfree(hba->ufs_stats.tag_stats);

+20 −13
Original line number Diff line number Diff line
@@ -1807,8 +1807,7 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
 * The variant operations configure the necessary controller and PHY
 * handshake during initialization.
 */
const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
	.name                   = "qcom",
static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
	.init			= ufs_qcom_init,
	.exit			= ufs_qcom_exit,
	.get_ufs_hci_version	= ufs_qcom_get_ufs_hci_version,
@@ -1821,17 +1820,25 @@ const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
	.resume			= ufs_qcom_resume,
	.full_reset		= ufs_qcom_full_reset,
	.update_sec_cfg		= ufs_qcom_update_sec_cfg,
	.dbg_register_dump	= ufs_qcom_dump_dbg_regs,
#ifdef CONFIG_DEBUG_FS
	.add_debugfs		= ufs_qcom_dbg_add_debugfs,
#endif
};

static struct ufs_hba_crypto_variant_ops ufs_hba_crypto_variant_ops = {
	.crypto_engine_cfg	= ufs_qcom_crytpo_engine_cfg,
	.crypto_engine_reset	= ufs_qcom_crytpo_engine_reset,
	.crypto_engine_eh	= ufs_qcom_crypto_engine_eh,
	.crypto_engine_get_err	= ufs_qcom_crypto_engine_get_err,
	.crypto_engine_reset_err = ufs_qcom_crypto_engine_reset_err,
	.dbg_register_dump	= ufs_qcom_dump_dbg_regs,
#ifdef CONFIG_DEBUG_FS
	.add_debugfs		= ufs_qcom_dbg_add_debugfs,
#endif
};
EXPORT_SYMBOL(ufs_hba_qcom_vops);

static struct ufs_hba_variant ufs_hba_qcom_variant = {
	.name		= "qcom",
	.vops		= &ufs_hba_qcom_vops,
	.crypto_vops	= &ufs_hba_crypto_variant_ops,
};

/**
 * ufs_qcom_probe - probe routine of the driver
@@ -1841,7 +1848,7 @@ EXPORT_SYMBOL(ufs_hba_qcom_vops);
 */
static int ufs_qcom_probe(struct platform_device *pdev)
{
	dev_set_drvdata(&pdev->dev, (void *)&ufs_hba_qcom_vops);
	dev_set_drvdata(&pdev->dev, (void *)&ufs_hba_qcom_variant);
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -377,7 +377,7 @@ static int ufshcd_pltfrm_probe(struct platform_device *pdev)
				of_find_device_by_node(ufs_variant_node);

			if (ufs_variant_pdev)
				hba->vops = (struct ufs_hba_variant_ops *)
				hba->var = (struct ufs_hba_variant *)
				     dev_get_drvdata(&ufs_variant_pdev->dev);
		}
	}
+68 −105
Original line number Diff line number Diff line
@@ -528,8 +528,7 @@ static void ufshcd_print_host_regs(struct ufs_hba *hba)

	ufshcd_print_clk_freqs(hba);

	if (hba->vops && hba->vops->dbg_register_dump)
		hba->vops->dbg_register_dump(hba);
	ufshcd_vops_dbg_register_dump(hba);
}

static
@@ -709,8 +708,7 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
{
	if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
		if (hba->vops && hba->vops->get_ufs_hci_version)
			return hba->vops->get_ufs_hci_version(hba);
		return ufshcd_vops_get_ufs_hci_version(hba);
	}

	return ufshcd_readl(hba, REG_UFS_VERSION);
@@ -1099,23 +1097,19 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up)
{
	int ret = 0;

	if (hba->vops && hba->vops->clk_scale_notify) {
		ret = hba->vops->clk_scale_notify(hba, scale_up, PRE_CHANGE);
	ret = ufshcd_vops_clk_scale_notify(hba, scale_up, PRE_CHANGE);
	if (ret)
		return ret;
	}

	ret = ufshcd_set_clk_freq(hba, scale_up);
	if (ret)
		return ret;

	if (hba->vops && hba->vops->clk_scale_notify) {
		ret = hba->vops->clk_scale_notify(hba, scale_up, POST_CHANGE);
	ret = ufshcd_vops_clk_scale_notify(hba, scale_up, POST_CHANGE);
	if (ret) {
		ufshcd_set_clk_freq(hba, !scale_up);
		return ret;
	}
	}

	return ret;
}
@@ -1947,15 +1941,13 @@ int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
{
	int ret = 0;

	if (hba->vops && hba->vops->crypto_engine_cfg) {
		ret = hba->vops->crypto_engine_cfg(hba, task_tag);
	ret = ufshcd_vops_crypto_engine_cfg(hba, task_tag);
	if (ret) {
		dev_err(hba->dev,
			"%s: failed to configure crypto engine %d\n",
			__func__, ret);
		return ret;
	}
	}

	hba->lrb[task_tag].issue_time_stamp = ktime_get();
	hba->lrb[task_tag].complete_time_stamp = ktime_set(0, 0);
@@ -3893,13 +3885,11 @@ static int ufshcd_link_recovery(struct ufs_hba *hba)
	ufshcd_set_eh_in_progress(hba);
	spin_unlock_irqrestore(hba->host->host_lock, flags);

	if (hba->vops && hba->vops->full_reset) {
		ret = hba->vops->full_reset(hba);
	ret = ufshcd_vops_full_reset(hba);
	if (ret)
		dev_warn(hba->dev,
			"full reset returned %d, trying to recover the link\n",
			ret);
	}

	ret = ufshcd_host_reset_and_restore(hba);

@@ -4133,9 +4123,8 @@ int ufshcd_change_power_mode(struct ufs_hba *hba,
		dev_err(hba->dev,
			"%s: power mode change failed %d\n", __func__, ret);
	} else {
		if (hba->vops && hba->vops->pwr_change_notify)
			hba->vops->pwr_change_notify(hba,
				POST_CHANGE, NULL, pwr_mode);
		ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
						pwr_mode);

		memcpy(&hba->pwr_info, pwr_mode,
			sizeof(struct ufs_pa_layer_attr));
@@ -4159,9 +4148,9 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
	int ret;

	/* Get the connected lane count */
	if (hba->vops && hba->vops->pwr_change_notify)
		hba->vops->pwr_change_notify(hba,
		     PRE_CHANGE, desired_pwr_mode, &final_params);
	if (hba->var && hba->var->vops && hba->var->vops->pwr_change_notify)
		ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE,
					desired_pwr_mode, &final_params);
	else
		memcpy(&final_params, desired_pwr_mode, sizeof(final_params));

@@ -4314,8 +4303,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
	/* UniPro link is disabled at this point */
	ufshcd_set_link_off(hba);

	if (hba->vops && hba->vops->hce_enable_notify)
		hba->vops->hce_enable_notify(hba, PRE_CHANGE);
	ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);

	/* start controller initialization sequence */
	ufshcd_hba_start(hba);
@@ -4348,8 +4336,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
	/* enable UIC related interrupts */
	ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);

	if (hba->vops && hba->vops->hce_enable_notify)
		hba->vops->hce_enable_notify(hba, POST_CHANGE);
	ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);

	return 0;
}
@@ -4407,8 +4394,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
	int retries = DME_LINKSTARTUP_RETRIES;

	do {
		if (hba->vops && hba->vops->link_startup_notify)
			hba->vops->link_startup_notify(hba, PRE_CHANGE);
		ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);

		ret = ufshcd_dme_link_startup(hba);
		if (ret)
@@ -4452,11 +4438,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
	}

	/* Include any host controller configuration via UIC commands */
	if (hba->vops && hba->vops->link_startup_notify) {
		ret = hba->vops->link_startup_notify(hba, POST_CHANGE);
	ret = ufshcd_vops_link_startup_notify(hba, POST_CHANGE);
	if (ret)
		goto out;
	}

	ret = ufshcd_make_hba_operational(hba);
out:
@@ -5475,8 +5459,7 @@ static void ufshcd_err_handler(struct work_struct *work)
		}
	}

	if (hba->vops && hba->vops->crypto_engine_get_err)
		crypto_engine_err = hba->vops->crypto_engine_get_err(hba);
	crypto_engine_err = ufshcd_vops_crypto_engine_get_err(hba);

	if ((hba->saved_err & INT_FATAL_ERRORS) || crypto_engine_err ||
	    ((hba->saved_err & UIC_ERROR) &&
@@ -5563,8 +5546,7 @@ skip_pending_xfer_clear:
		scsi_report_bus_reset(hba->host, 0);
		hba->saved_err = 0;
		hba->saved_uic_err = 0;
		if (hba->vops && hba->vops->crypto_engine_reset_err)
			hba->vops->crypto_engine_reset_err(hba);
		ufshcd_vops_crypto_engine_reset_err(hba);
	}

skip_err_handling:
@@ -5662,8 +5644,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba)
	bool queue_eh_work = false;
	int crypto_engine_err = 0;

	if (hba->vops && hba->vops->crypto_engine_get_err)
		crypto_engine_err = hba->vops->crypto_engine_get_err(hba);
	crypto_engine_err = ufshcd_vops_crypto_engine_get_err(hba);

	if (hba->errors & INT_FATAL_ERRORS || crypto_engine_err)
		queue_eh_work = true;
@@ -5725,8 +5706,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status)
	ufsdbg_error_inject_dispatcher(hba,
		ERR_INJECT_INTR, intr_status, &intr_status);

	if (hba->vops && hba->vops->crypto_engine_eh)
		crypto_engine_err = hba->vops->crypto_engine_eh(hba);
	ufshcd_vops_crypto_engine_eh(hba);

	hba->errors = UFSHCD_ERROR_MASK & intr_status;
	if (hba->errors || crypto_engine_err)
@@ -6160,8 +6140,8 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
		goto out;
	}

	if (!err && hba->vops && hba->vops->crypto_engine_reset) {
		err = hba->vops->crypto_engine_reset(hba);
	if (!err) {
		err = ufshcd_vops_crypto_engine_reset(hba);
		if (err) {
			dev_err(hba->dev,
				"%s: failed to reset crypto engine %d\n",
@@ -7178,8 +7158,8 @@ static int ufshcd_setup_hba_vreg(struct ufs_hba *hba, bool on)
	if (info->vdd_hba) {
		ret = ufshcd_toggle_vreg(hba->dev, info->vdd_hba, on);

		if (!ret && hba->vops && hba->vops->update_sec_cfg)
			hba->vops->update_sec_cfg(hba, on);
		if (!ret)
			ufshcd_vops_update_sec_cfg(hba, on);
	}

	return ret;
@@ -7282,8 +7262,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
	 * this standard driver hence call the vendor specific setup_clocks
	 * before disabling the clocks managed here.
	 */
	if (hba->vops && hba->vops->setup_clocks && !on) {
		ret = hba->vops->setup_clocks(hba, on);
	if (!on) {
		ret = ufshcd_vops_setup_clocks(hba, on);
		if (ret)
			return ret;
	}
@@ -7315,8 +7295,8 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
	 * this standard driver hence call the vendor specific setup_clocks
	 * after enabling the clocks managed here.
	 */
	if (hba->vops && hba->vops->setup_clocks && on)
		ret = hba->vops->setup_clocks(hba, on);
	if (on)
		ret = ufshcd_vops_setup_clocks(hba, on);

out:
	if (ret) {
@@ -7331,8 +7311,7 @@ out:
			hba->clk_gating.state);
		spin_unlock_irqrestore(hba->host->host_lock, flags);
		/* restore the secure configuration as clocks are enabled */
		if (hba->vops && hba->vops->update_sec_cfg)
			hba->vops->update_sec_cfg(hba, true);
		ufshcd_vops_update_sec_cfg(hba, true);
	}

	if (clk_state_changed)
@@ -7390,46 +7369,38 @@ static int ufshcd_variant_hba_init(struct ufs_hba *hba)
{
	int err = 0;

	if (!hba->vops)
	if (!hba->var || !hba->var->vops)
		goto out;

	if (hba->vops->init) {
		err = hba->vops->init(hba);
	err = ufshcd_vops_init(hba);
	if (err)
		goto out;
	}

	if (hba->vops->setup_regulators) {
		err = hba->vops->setup_regulators(hba, true);
	err = ufshcd_vops_setup_regulators(hba, true);
	if (err)
		goto out_exit;
	}

	goto out;

out_exit:
	if (hba->vops->exit)
		hba->vops->exit(hba);
	ufshcd_vops_exit(hba);
out:
	if (err)
		dev_err(hba->dev, "%s: variant %s init failed err %d\n",
			__func__, hba->vops ? hba->vops->name : "", err);
			__func__, ufshcd_get_var_name(hba), err);
	return err;
}

static void ufshcd_variant_hba_exit(struct ufs_hba *hba)
{
	if (!hba->vops)
	if (!hba->var || !hba->var->vops)
		return;

	if (hba->vops->setup_clocks)
		hba->vops->setup_clocks(hba, false);
	ufshcd_vops_setup_clocks(hba, false);

	if (hba->vops->setup_regulators)
		hba->vops->setup_regulators(hba, false);
	ufshcd_vops_setup_regulators(hba, false);

	if (hba->vops->exit)
		hba->vops->exit(hba);
	ufshcd_vops_exit(hba);
}

static int ufshcd_hba_init(struct ufs_hba *hba)
@@ -7839,17 +7810,13 @@ disable_clks:
	 * vendor specific host controller register space call them before the
	 * host clocks are ON.
	 */
	if (hba->vops && hba->vops->suspend) {
		ret = hba->vops->suspend(hba, pm_op);
	ret = ufshcd_vops_suspend(hba, pm_op);
	if (ret)
		goto set_link_active;
	}

	if (hba->vops && hba->vops->setup_clocks) {
		ret = hba->vops->setup_clocks(hba, false);
	ret = ufshcd_vops_setup_clocks(hba, false);
	if (ret)
		goto vops_resume;
	}

	if (!ufshcd_is_link_active(hba))
		ufshcd_setup_clocks(hba, false);
@@ -7869,8 +7836,7 @@ disable_clks:
	goto out;

vops_resume:
	if (hba->vops && hba->vops->resume)
		hba->vops->resume(hba, pm_op);
	ufshcd_vops_resume(hba, pm_op);
set_link_active:
	ufshcd_resume_clkscaling(hba);
	ufshcd_vreg_set_hpm(hba);
@@ -7939,11 +7905,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
	 * vendor specific host controller register space call them when the
	 * host clocks are ON.
	 */
	if (hba->vops && hba->vops->resume) {
		ret = hba->vops->resume(hba, pm_op);
	ret = ufshcd_vops_resume(hba, pm_op);
	if (ret)
		goto disable_vreg;
	}

	if (ufshcd_is_link_hibern8(hba)) {
		ret = ufshcd_uic_hibern8_exit(hba);
@@ -7999,8 +7963,7 @@ set_old_link_state:
	if (ufshcd_is_link_hibern8(hba))
		hba->hibern8_on_idle.state = HIBERN8_ENTERED;
vendor_suspend:
	if (hba->vops && hba->vops->suspend)
		hba->vops->suspend(hba, pm_op);
	ufshcd_vops_suspend(hba, pm_op);
disable_vreg:
	ufshcd_vreg_set_lpm(hba);
disable_irq_and_vops_clks:
+229 −29
Original line number Diff line number Diff line
@@ -69,9 +69,10 @@

#include <linux/fault-inject.h>
#include "ufs.h"
#include "ufshci.h"

#define UFSHCD "ufshcd"
#define UFSHCD_DRIVER_VERSION "0.2"
#define UFSHCD_DRIVER_VERSION "0.3"

#define UFS_BIT(x)	BIT(x)

@@ -284,7 +285,6 @@ struct ufs_pwr_mode_info {

/**
 * struct ufs_hba_variant_ops - variant specific callbacks
 * @name: variant name
 * @init: called when the driver is initialized
 * @exit: called to cleanup everything done in init
 * @get_ufs_hci_version: called to get UFS HCI version
@@ -302,23 +302,12 @@ struct ufs_pwr_mode_info {
 * @resume: called during host controller PM callback
 * @full_reset:  called during link recovery for handling variant specific
 *		 implementations of resetting the hci
 * @update_sec_cfg: called to restore host controller secure configuration
 * @crypto_engine_cfg: configure cryptographic engine according to tag parameter
 * @crypto_engine_eh: cryptographic engine error handling.
 *                Return true is it detects an error, false on
 *                success
 * @crypto_engine_get_err: returns the saved error status of the
 *                         cryptographic engine.If a positive
 *                         value is returned, host controller
 *                         should be reset.
 * @crypto_engine_reset_err: resets the saved error status of
 *                         the cryptographic engine
 * @dbg_register_dump: used to dump controller debug information
 * @update_sec_cfg: called to restore host controller secure configuration
 * @add_debugfs: used to add debugfs entries
 * @remove_debugfs: used to remove debugfs entries
 */
struct ufs_hba_variant_ops {
	const char *name;
	int	(*init)(struct ufs_hba *);
	void	(*exit)(struct ufs_hba *);
	u32	(*get_ufs_hci_version)(struct ufs_hba *);
@@ -333,19 +322,46 @@ struct ufs_hba_variant_ops {
	int	(*suspend)(struct ufs_hba *, enum ufs_pm_op);
	int	(*resume)(struct ufs_hba *, enum ufs_pm_op);
	int	(*full_reset)(struct ufs_hba *);
	void	(*dbg_register_dump)(struct ufs_hba *hba);
	int	(*update_sec_cfg)(struct ufs_hba *hba, bool restore_sec_cfg);
#ifdef CONFIG_DEBUG_FS
	void	(*add_debugfs)(struct ufs_hba *hba, struct dentry *root);
	void	(*remove_debugfs)(struct ufs_hba *hba);
#endif
};

/**
 * struct ufs_hba_crypto_variant_ops - variant specific crypto callbacks
 * @crypto_engine_cfg: configure cryptographic engine according to tag parameter
 * @crypto_engine_eh: cryptographic engine error handling.
 *                Return true is it detects an error, false on
 *                success
 * @crypto_engine_get_err: returns the saved error status of the
 *                         cryptographic engine.If a positive
 *                         value is returned, host controller
 *                         should be reset.
 * @crypto_engine_reset_err: resets the saved error status of
 *                         the cryptographic engine
 */
struct ufs_hba_crypto_variant_ops {
	int	(*crypto_engine_cfg)(struct ufs_hba *, unsigned int);
	int	(*crypto_engine_reset)(struct ufs_hba *);
	int	(*crypto_engine_eh)(struct ufs_hba *);
	int	(*crypto_engine_get_err)(struct ufs_hba *);
	void	(*crypto_engine_reset_err)(struct ufs_hba *);
	void	(*dbg_register_dump)(struct ufs_hba *hba);
#ifdef CONFIG_DEBUG_FS
	void	(*add_debugfs)(struct ufs_hba *hba, struct dentry *root);
	void	(*remove_debugfs)(struct ufs_hba *hba);
#endif
};

/**
 * struct ufs_hba_variant - variant specific parameters
 * @name: variant name
 */
struct ufs_hba_variant {
	const char				*name;
	struct ufs_hba_variant_ops		*vops;
	struct ufs_hba_crypto_variant_ops	*crypto_vops;
};


/* clock gating state  */
enum clk_gating_state {
	CLKS_OFF,
@@ -613,7 +629,7 @@ struct ufshcd_pm_qos {
 * @nutrs: Transfer Request Queue depth supported by controller
 * @nutmrs: Task Management Queue depth supported by controller
 * @ufs_version: UFS Version to which controller complies
 * @vops: pointer to variant specific operations
 * @var: pointer to variant specific data
 * @priv: pointer to variant specific private data
 * @irq: Irq number of the controller
 * @active_uic_cmd: handle of active UIC command
@@ -692,7 +708,7 @@ struct ufs_hba {
	int nutrs;
	int nutmrs;
	u32 ufs_version;
	struct ufs_hba_variant_ops *vops;
	struct ufs_hba_variant *var;
	void *priv;
	unsigned int irq;
	bool is_irq_enabled;
@@ -1023,6 +1039,23 @@ static inline void ufshcd_init_req_stats(struct ufs_hba *hba) {}
int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
				u32 size, bool ascii);

/* Expose Query-Request API */
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
	enum flag_idn idn, bool *flag_res);
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
	enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
int ufshcd_query_descriptor(struct ufs_hba *hba, enum query_opcode opcode,
	enum desc_idn idn, u8 index, u8 selector, u8 *desc_buf, int *buf_len);

int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba, bool no_sched);
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);
void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba,
		int result);
u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);

#ifndef CONFIG_SMP
static inline int ufshcd_pm_qos_init(struct ufs_hba *hba)
{
@@ -1066,12 +1099,179 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
int ufshcd_query_descriptor(struct ufs_hba *hba, enum query_opcode opcode,
	enum desc_idn idn, u8 index, u8 selector, u8 *desc_buf, int *buf_len);

int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba, bool no_sched);
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);
void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba,
		int result);
u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba);
/* Wrapper functions for safely calling variant operations */
static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
{
	if (hba->var && hba->var->name)
		return hba->var->name;
	return "";
}

static inline int ufshcd_vops_init(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->init)
		return hba->var->vops->init(hba);
	return 0;
}

static inline void ufshcd_vops_exit(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->exit)
		hba->var->vops->exit(hba);
}

static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->get_ufs_hci_version)
		return hba->var->vops->get_ufs_hci_version(hba);
	return ufshcd_readl(hba, REG_UFS_VERSION);
}

static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
						bool up, bool status)
{
	if (hba->var && hba->var->vops && hba->var->vops->clk_scale_notify)
		return hba->var->vops->clk_scale_notify(hba, up, status);
	return 0;
}

static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on)
{
	if (hba->var && hba->var->vops && hba->var->vops->setup_clocks)
		return hba->var->vops->setup_clocks(hba, on);
	return 0;
}

static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status)
{
	if (hba->var && hba->var->vops && hba->var->vops->setup_regulators)
		return hba->var->vops->setup_regulators(hba, status);
	return 0;
}

static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
						bool status)
{
	if (hba->var && hba->var->vops && hba->var->vops->hce_enable_notify)
		hba->var->vops->hce_enable_notify(hba, status);
	return 0;
}
static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
						bool status)
{
	if (hba->var && hba->var->vops && hba->var->vops->link_startup_notify)
		return hba->var->vops->link_startup_notify(hba, status);
	return 0;
}

static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
				  bool status,
				  struct ufs_pa_layer_attr *dev_max_params,
				  struct ufs_pa_layer_attr *dev_req_params)
{
	if (hba->var && hba->var->vops && hba->var->vops->pwr_change_notify)
		return hba->var->vops->pwr_change_notify(hba, status,
					dev_max_params, dev_req_params);
	return 0;
}

static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
{
	if (hba->var && hba->var->vops && hba->var->vops->suspend)
		return hba->var->vops->suspend(hba, op);
	return 0;
}

static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
{
	if (hba->var && hba->var->vops && hba->var->vops->resume)
		return hba->var->vops->resume(hba, op);
	return 0;
}

static inline int ufshcd_vops_full_reset(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->full_reset)
		return hba->var->vops->full_reset(hba);
	return 0;
}


static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->dbg_register_dump)
		hba->var->vops->dbg_register_dump(hba);
}

static inline int ufshcd_vops_update_sec_cfg(struct ufs_hba *hba,
						bool restore_sec_cfg)
{
	if (hba->var && hba->var->vops && hba->var->vops->update_sec_cfg)
		return hba->var->vops->update_sec_cfg(hba, restore_sec_cfg);
	return 0;
}

#ifdef CONFIG_DEBUG_FS
static inline void ufshcd_vops_add_debugfs(struct ufs_hba *hba,
						struct dentry *root)
{
	if (hba->var && hba->var->vops && hba->var->vops->add_debugfs)
		hba->var->vops->add_debugfs(hba, root);
}

static inline void ufshcd_vops_remove_debugfs(struct ufs_hba *hba)
{
	if (hba->var && hba->var->vops && hba->var->vops->remove_debugfs)
		hba->var->vops->remove_debugfs(hba);
}
#else
static inline void ufshcd_vops_add_debugfs(struct ufs_hba *hba, struct dentry *)
{
}

static inline void ufshcd_vops_remove_debugfs(struct ufs_hba *hba)
{
}
#endif

static inline int ufshcd_vops_crypto_engine_cfg(struct ufs_hba *hba,
						unsigned int task_tag)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_cfg)
		return hba->var->crypto_vops->crypto_engine_cfg(hba, task_tag);
	return 0;
}

static inline int ufshcd_vops_crypto_engine_reset(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_reset)
		return hba->var->crypto_vops->crypto_engine_reset(hba);
	return 0;
}

static inline int ufshcd_vops_crypto_engine_eh(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_eh)
		return hba->var->crypto_vops->crypto_engine_eh(hba);
	return 0;
}

static inline int ufshcd_vops_crypto_engine_get_err(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_get_err)
		return hba->var->crypto_vops->crypto_engine_get_err(hba);
	return 0;
}

static inline void ufshcd_vops_crypto_engine_reset_err(struct ufs_hba *hba)
{
	if (hba->var && hba->var->crypto_vops &&
	    hba->var->crypto_vops->crypto_engine_reset_err)
		hba->var->crypto_vops->crypto_engine_reset_err(hba);
}

#endif /* End of Header */