diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index f42d99ce5bf1..536805f6c4e1 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -241,6 +241,14 @@ static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
 		hba->vops->config_scaling_param(hba, p, data);
 }
 
+static inline u32 ufshcd_vops_config_qos_vote(struct ufs_hba *hba)
+{
+	if (hba->vops && hba->vops->config_qos_vote)
+		return hba->vops->config_qos_vote(hba);
+
+	return UFSHCD_QOS_DEFAULT_VOTE;
+}
+
 static inline void ufshcd_vops_reinit_notify(struct ufs_hba *hba)
 {
 	if (hba->vops && hba->vops->reinit_notify)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index ae9936fc6ffb..13370febd2b5 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -1001,6 +1001,20 @@ static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)
 	return ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6;
 }
 
+/**
+ * ufshcd_pm_qos_perf - vote for PM QoS performance or power save mode
+ * @hba: per adapter instance
+ * @on: If True, vote for perf PM QoS mode otherwise power save mode
+ */
+static void ufshcd_pm_qos_perf(struct ufs_hba *hba, bool on)
+{
+	if (!hba->pm_qos_init)
+		return;
+
+	cpu_latency_qos_update_request(&hba->pm_qos_req, on ? hba->qos_vote
+							: PM_QOS_DEFAULT_VALUE);
+}
+
 /**
  * ufshcd_set_clk_freq - set UFS controller clock frequencies
  * @hba: per adapter instance
@@ -1153,6 +1167,10 @@ static int ufshcd_scale_clks(struct ufs_hba *hba, unsigned long freq,
 	trace_ufshcd_profile_clk_scaling(dev_name(hba->dev),
 			(scale_up ? "up" : "down"),
 			ktime_to_us(ktime_sub(ktime_get(), start)), ret);
+
+	if (!ret)
+		ufshcd_pm_qos_perf(hba, scale_up);
+
 	return ret;
 }
 
@@ -9204,6 +9222,8 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on)
 	if (ret)
 		return ret;
 
+	if (!ufshcd_is_clkscaling_supported(hba))
+		ufshcd_pm_qos_perf(hba, on);
 out:
 	if (ret) {
 		list_for_each_entry(clki, head, list) {
@@ -9296,6 +9316,45 @@ static int ufshcd_init_clocks(struct ufs_hba *hba)
 	return ret;
 }
 
+/**
+ * ufshcd_pm_qos_init - initialize PM QoS instance
+ * @hba: per adapter instance
+ */
+static void ufshcd_pm_qos_init(struct ufs_hba *hba)
+{
+	if (!(hba->caps & UFSHCD_CAP_PM_QOS))
+		return;
+
+	/*
+	 * called to configure PM QoS vote value for UFS host,
+	 * expecting qos vote return value from caller else
+	 * default vote value will be return.
+	 */
+	hba->qos_vote = ufshcd_vops_config_qos_vote(hba);
+	cpu_latency_qos_add_request(&hba->pm_qos_req,
+					PM_QOS_DEFAULT_VALUE);
+
+	if (cpu_latency_qos_request_active(&hba->pm_qos_req))
+		hba->pm_qos_init = true;
+
+	dev_dbg(hba->dev, "%s: QoS %s, qos_vote: %u\n", __func__,
+		hba->pm_qos_init ? "initialized" : "uninitialized",
+		hba->qos_vote);
+}
+
+/**
+ * ufshcd_pm_qos_exit - remove instance from PM QoS
+ * @hba: per adapter instance
+ */
+static void ufshcd_pm_qos_exit(struct ufs_hba *hba)
+{
+	if (!hba->pm_qos_init)
+		return;
+
+	cpu_latency_qos_remove_request(&hba->pm_qos_req);
+	hba->pm_qos_init = false;
+}
+
 static int ufshcd_variant_hba_init(struct ufs_hba *hba)
 {
 	int err = 0;
@@ -9381,6 +9440,7 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
 static void ufshcd_hba_exit(struct ufs_hba *hba)
 {
 	if (hba->is_powered) {
+		ufshcd_pm_qos_exit(hba);
 		ufshcd_exit_clk_scaling(hba);
 		ufshcd_exit_clk_gating(hba);
 		if (hba->eh_wq)
@@ -10030,6 +10090,7 @@ static int ufshcd_suspend(struct ufs_hba *hba)
 	ufshcd_vreg_set_lpm(hba);
 	/* Put the host controller in low power mode if possible */
 	ufshcd_hba_vreg_set_lpm(hba);
+	ufshcd_pm_qos_perf(hba, false);
 	return ret;
 }
 
@@ -10576,6 +10637,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 	ufs_sysfs_add_nodes(hba->dev);
 
 	device_enable_async_suspend(dev);
+	ufshcd_pm_qos_init(hba);
 	return 0;
 
 free_tmf_queue:
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index d862c8ddce03..e9f2bad8934e 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -320,6 +320,9 @@ struct ufs_pwr_mode_info {
  * @phy_initialization: used to initialize phys
  * @device_reset: called to issue a reset pulse on the UFS device
  * @config_scaling_param: called to configure clock scaling parameters
+ * @config_qos_vote: called to configure PM QoS vote value for UFS host,
+ *		     expecting qos vote return value from caller else
+		     default vote value will be return
  * @program_key: program or evict an inline encryption key
  * @event_notify: called to notify important events
  * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
@@ -362,6 +365,7 @@ struct ufs_hba_variant_ops {
 	void	(*config_scaling_param)(struct ufs_hba *hba,
 				struct devfreq_dev_profile *profile,
 				struct devfreq_simple_ondemand_data *data);
+	u32	(*config_qos_vote)(struct ufs_hba *hba);
 	int	(*program_key)(struct ufs_hba *hba,
 			       const union ufs_crypto_cfg_entry *cfg, int slot);
 	void	(*event_notify)(struct ufs_hba *hba,
@@ -720,6 +724,11 @@ enum ufshcd_caps {
 	 * WriteBooster when scaling the clock down.
 	 */
 	UFSHCD_CAP_WB_WITH_CLK_SCALING			= 1 << 12,
+
+	/* This capability allows the host controller driver to use the PM QoS
+	 * feature.
+	 */
+	UFSHCD_CAP_PM_QOS				= 1 << 13,
 };
 
 struct ufs_hba_variant_params {
@@ -793,6 +802,8 @@ enum ufshcd_mcq_opr {
 	OPR_MAX,
 };
 
+#define UFSHCD_QOS_DEFAULT_VOTE 0
+
 /**
  * struct ufs_hba - per adapter private structure
  * @mmio_base: UFSHCI base register address
@@ -912,6 +923,8 @@ enum ufshcd_mcq_opr {
  * @mcq_base: Multi circular queue registers base address
  * @uhq: array of supported hardware queues
  * @dev_cmd_queue: Queue for issuing device management commands
+ * @pm_qos_req: PM QoS request handle
+ * @pm_qos_init: flag to check if pm qos init completed
  */
 struct ufs_hba {
 	void __iomem *mmio_base;
@@ -1076,6 +1089,9 @@ struct ufs_hba {
 	struct ufs_hw_queue *uhq;
 	struct ufs_hw_queue *dev_cmd_queue;
 	struct ufshcd_mcq_opr_info_t mcq_opr[OPR_MAX];
+	struct pm_qos_request pm_qos_req;
+	bool pm_qos_init;
+	u32 qos_vote;
 };
 
 /**
