summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-05-26 05:09:48 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-05-26 05:09:48 +0300
commitfbe86daca0ba878b04fa241b85e26e54d17d4229 (patch)
treea179e18657e4ed82005c6e8846fd2c297c471a8c /drivers/scsi/ufs
parentd7227785e384d4422b3ca189aa5bf19f462337cc (diff)
parent325d5c5fb216674296f3902a8902b942da3adc5b (diff)
downloadlinux-fbe86daca0ba878b04fa241b85e26e54d17d4229.tar.xz
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This consists of a small set of driver updates (lpfc, ufs, mpt3sas mpi3mr, iscsi target). Apart from that this is mostly small fixes with very few core changes (the biggest one being VPD caching)" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (177 commits) scsi: target: tcmu: Avoid holding XArray lock when calling lock_page scsi: elx: efct: Remove NULL check after calling container_of() scsi: dpt_i2o: Drop redundant spinlock initialization scsi: qedf: Remove redundant variable op scsi: hisi_sas: Fix memory ordering in hisi_sas_task_deliver() scsi: fnic: Replace DMA mask of 64 bits with 47 bits scsi: mpi3mr: Add target device related sysfs attributes scsi: mpi3mr: Add shost related sysfs attributes scsi: elx: efct: Remove redundant memset() statement scsi: megaraid_sas: Remove redundant memset() statement scsi: mpi3mr: Return error if dma_alloc_coherent() fails scsi: hisi_sas: Fix rescan after deleting a disk scsi: hisi_sas: Use sas_ata_wait_after_reset() in IT nexus reset scsi: libsas: Refactor sas_ata_hard_reset() scsi: mpt3sas: Update driver version to 42.100.00.00 scsi: mpt3sas: Fix junk chars displayed while printing ChipName scsi: ipr: Use kobj_to_dev() scsi: mpi3mr: Fix a NULL vs IS_ERR() bug in mpi3mr_bsg_init() scsi: bnx2fc: Avoid using get_cpu() in bnx2fc_cmd_alloc() scsi: libfc: Remove get_cpu() semantics in fc_exch_em_alloc() ...
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r--drivers/scsi/ufs/Kconfig26
-rw-r--r--drivers/scsi/ufs/cdns-pltfrm.c2
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210-pci.c1
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210-pltfrm.c1
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210.c2
-rw-r--r--drivers/scsi/ufs/tc-dwc-g210.h2
-rw-r--r--drivers/scsi/ufs/ti-j721e-ufs.c6
-rw-r--r--drivers/scsi/ufs/ufs-debugfs.c1
-rw-r--r--drivers/scsi/ufs/ufs-exynos.c5
-rw-r--r--drivers/scsi/ufs/ufs-exynos.h8
-rw-r--r--drivers/scsi/ufs/ufs-hisi.c2
-rw-r--r--drivers/scsi/ufs/ufs-hwmon.c1
-rw-r--r--drivers/scsi/ufs/ufs-mediatek.c31
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c2
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c73
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h6
-rw-r--r--drivers/scsi/ufs/ufs-sysfs.c1
-rw-r--r--drivers/scsi/ufs/ufs-sysfs.h3
-rw-r--r--drivers/scsi/ufs/ufs.h35
-rw-r--r--drivers/scsi/ufs/ufs_bsg.c6
-rw-r--r--drivers/scsi/ufs/ufs_bsg.h7
-rw-r--r--drivers/scsi/ufs/ufs_quirks.h15
-rw-r--r--drivers/scsi/ufs/ufshcd-crypto.h5
-rw-r--r--drivers/scsi/ufs/ufshcd-dwc.c2
-rw-r--r--drivers/scsi/ufs/ufshcd-dwc.h2
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c4
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c38
-rw-r--r--drivers/scsi/ufs/ufshcd-priv.h298
-rw-r--r--drivers/scsi/ufs/ufshcd.c247
-rw-r--r--drivers/scsi/ufs/ufshcd.h368
-rw-r--r--drivers/scsi/ufs/ufshci.h2
-rw-r--r--drivers/scsi/ufs/ufshpb.c203
-rw-r--r--drivers/scsi/ufs/ufshpb.h16
-rw-r--r--drivers/scsi/ufs/unipro.h18
34 files changed, 720 insertions, 719 deletions
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 9fe27b01904e..393b9a01da36 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -1,36 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0+
#
# Kernel configuration file for the UFS Host Controller
#
-# This code is based on drivers/scsi/ufs/Kconfig
# Copyright (C) 2011-2013 Samsung India Software Operations
#
# Authors:
# Santosh Yaraganavi <santosh.sy@samsung.com>
# Vinayak Holikatti <h.vinayak@samsung.com>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-# See the COPYING file in the top-level directory or visit
-# <http://www.gnu.org/licenses/gpl-2.0.html>
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# This program is provided "AS IS" and "WITH ALL FAULTS" and
-# without warranty of any kind. You are solely responsible for
-# determining the appropriateness of using and distributing
-# the program and assume all risks associated with your exercise
-# of rights with respect to the program, including but not limited
-# to infringement of third party rights, the risks and costs of
-# program errors, damage to or loss of data, programs or equipment,
-# and unavailability or interruption of operations. Under no
-# circumstances will the contributor of this Program be liable for
-# any damages of any kind arising from your use or distribution of
-# this program.
config SCSI_UFSHCD
tristate "Universal Flash Storage Controller Driver Core"
diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c
index 7da8be2f35c4..e05c0ae64eea 100644
--- a/drivers/scsi/ufs/cdns-pltfrm.c
+++ b/drivers/scsi/ufs/cdns-pltfrm.c
@@ -9,6 +9,7 @@
*
*/
+#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -340,4 +341,3 @@ module_platform_driver(cdns_ufs_pltfrm_driver);
MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
MODULE_DESCRIPTION("Cadence UFS host controller platform driver");
MODULE_LICENSE("GPL v2");
-MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pci.c b/drivers/scsi/ufs/tc-dwc-g210-pci.c
index 7b08e2e07cc5..e635c211c783 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pci.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pci.c
@@ -11,6 +11,7 @@
#include "ufshcd-dwc.h"
#include "tc-dwc-g210.h"
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
diff --git a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
index 783ec43efa78..f15a84d0c176 100644
--- a/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
+++ b/drivers/scsi/ufs/tc-dwc-g210-pltfrm.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include "ufshcd-pltfrm.h"
#include "ufshcd-dwc.h"
diff --git a/drivers/scsi/ufs/tc-dwc-g210.c b/drivers/scsi/ufs/tc-dwc-g210.c
index f954a68f6b4c..7ef67c9fc5b8 100644
--- a/drivers/scsi/ufs/tc-dwc-g210.c
+++ b/drivers/scsi/ufs/tc-dwc-g210.c
@@ -7,6 +7,8 @@
* Authors: Joao Pinto <jpinto@synopsys.com>
*/
+#include <linux/module.h>
+
#include "ufshcd.h"
#include "unipro.h"
diff --git a/drivers/scsi/ufs/tc-dwc-g210.h b/drivers/scsi/ufs/tc-dwc-g210.h
index 5a506da03f4a..f7154012f5c7 100644
--- a/drivers/scsi/ufs/tc-dwc-g210.h
+++ b/drivers/scsi/ufs/tc-dwc-g210.h
@@ -10,6 +10,8 @@
#ifndef _TC_DWC_G210_H
#define _TC_DWC_G210_H
+struct ufs_hba;
+
int tc_dwc_g210_config_40_bit(struct ufs_hba *hba);
int tc_dwc_g210_config_20_bit(struct ufs_hba *hba);
diff --git a/drivers/scsi/ufs/ti-j721e-ufs.c b/drivers/scsi/ufs/ti-j721e-ufs.c
index eafe0db98d54..122d650d0810 100644
--- a/drivers/scsi/ufs/ti-j721e-ufs.c
+++ b/drivers/scsi/ufs/ti-j721e-ufs.c
@@ -29,11 +29,9 @@ static int ti_j721e_ufs_probe(struct platform_device *pdev)
return PTR_ERR(regbase);
pm_runtime_enable(dev);
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pm_runtime_put_noidle(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
goto disable_pm;
- }
/* Select MPHY refclk frequency */
clk = devm_clk_get(dev, NULL);
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 4a0bbcf1757a..c10a8f09682b 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -5,6 +5,7 @@
#include "ufs-debugfs.h"
#include "ufshcd.h"
+#include "ufshcd-priv.h"
static struct dentry *ufs_debugfs_root;
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
index 474a4a064a68..ddb2d42605c5 100644
--- a/drivers/scsi/ufs/ufs-exynos.c
+++ b/drivers/scsi/ufs/ufs-exynos.c
@@ -9,6 +9,7 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -704,7 +705,7 @@ static void exynos_ufs_establish_connt(struct exynos_ufs *ufs)
/* local unipro attributes */
ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID), DEV_ID);
- ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(N_DEVICEID_VALID), true);
ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERDEVICEID), PEER_DEV_ID);
ufshcd_dme_set(hba, UIC_ARG_MIB(T_PEERCPORTID), PEER_CPORT_ID);
ufshcd_dme_set(hba, UIC_ARG_MIB(T_CPORTFLAGS), CPORT_DEF_FLAGS);
@@ -1028,7 +1029,7 @@ static int exynos_ufs_post_link(struct ufs_hba *hba)
if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB)
ufshcd_dme_set(hba,
- UIC_ARG_MIB(T_DBG_SKIP_INIT_HIBERN8_EXIT), TRUE);
+ UIC_ARG_MIB(T_DBG_SKIP_INIT_HIBERN8_EXIT), true);
if (attr->pa_granularity) {
exynos_ufs_enable_dbg_mode(hba);
diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h
index 1c33e5466082..0b0a3d530ca6 100644
--- a/drivers/scsi/ufs/ufs-exynos.h
+++ b/drivers/scsi/ufs/ufs-exynos.h
@@ -248,22 +248,22 @@ long exynos_ufs_calc_time_cntr(struct exynos_ufs *, long);
static inline void exynos_ufs_enable_ov_tm(struct ufs_hba *hba)
{
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), true);
}
static inline void exynos_ufs_disable_ov_tm(struct ufs_hba *hba)
{
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), FALSE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_OV_TM), false);
}
static inline void exynos_ufs_enable_dbg_mode(struct ufs_hba *hba)
{
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), true);
}
static inline void exynos_ufs_disable_dbg_mode(struct ufs_hba *hba)
{
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), FALSE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_DBG_MODE), false);
}
#endif /* _UFS_EXYNOS_H_ */
diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c
index ab1a7ebd89b1..7046143063ee 100644
--- a/drivers/scsi/ufs/ufs-hisi.c
+++ b/drivers/scsi/ufs/ufs-hisi.c
@@ -7,6 +7,8 @@
*/
#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/dma-mapping.h>
diff --git a/drivers/scsi/ufs/ufs-hwmon.c b/drivers/scsi/ufs/ufs-hwmon.c
index 74855491dc8f..c38d9d98a86d 100644
--- a/drivers/scsi/ufs/ufs-hwmon.c
+++ b/drivers/scsi/ufs/ufs-hwmon.c
@@ -8,6 +8,7 @@
#include <linux/units.h>
#include "ufshcd.h"
+#include "ufshcd-priv.h"
struct ufs_hwmon_data {
struct ufs_hba *hba;
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c
index 86a938075f30..083d6bd4d561 100644
--- a/drivers/scsi/ufs/ufs-mediatek.c
+++ b/drivers/scsi/ufs/ufs-mediatek.c
@@ -8,6 +8,9 @@
#include <linux/arm-smccc.h>
#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
@@ -19,7 +22,6 @@
#include <linux/soc/mediatek/mtk_sip_svc.h>
#include "ufshcd.h"
-#include "ufshcd-crypto.h"
#include "ufshcd-pltfrm.h"
#include "ufs_quirks.h"
#include "unipro.h"
@@ -44,12 +46,14 @@
#define ufs_mtk_device_reset_ctrl(high, res) \
ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res)
-static struct ufs_dev_fix ufs_mtk_dev_fixups[] = {
- UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_AFTER_LPM),
- UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR",
- UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES),
- END_FIX
+static const struct ufs_dev_quirk ufs_mtk_dev_fixups[] = {
+ { .wmanufacturerid = UFS_VENDOR_MICRON,
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_DELAY_AFTER_LPM },
+ { .wmanufacturerid = UFS_VENDOR_SKHYNIX,
+ .model = "H9HQ21AFAMZDAR",
+ .quirk = UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES },
+ {}
};
static const struct of_device_id ufs_mtk_of_match[] = {
@@ -169,7 +173,6 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba,
enum ufs_notify_change_status status)
{
struct ufs_mtk_host *host = ufshcd_get_variant(hba);
- unsigned long flags;
if (status == PRE_CHANGE) {
if (host->unipro_lpm) {
@@ -183,12 +186,8 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba,
ufs_mtk_crypto_enable(hba);
if (host->caps & UFS_MTK_CAP_DISABLE_AH8) {
- spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_writel(hba, 0,
REG_AUTO_HIBERNATE_IDLE_TIMER);
- spin_unlock_irqrestore(hba->host->host_lock,
- flags);
-
hba->capabilities &= ~MASK_AUTO_HIBERN8_SUPPORT;
hba->ahit = 0;
}
@@ -860,7 +859,6 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba)
static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba)
{
- unsigned long flags;
u32 ah_ms;
if (ufshcd_is_clkgating_allowed(hba)) {
@@ -869,9 +867,7 @@ static void ufs_mtk_setup_clk_gating(struct ufs_hba *hba)
hba->ahit);
else
ah_ms = 10;
- spin_lock_irqsave(hba->host->host_lock, flags);
- hba->clk_gating.delay_ms = ah_ms + 5;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
+ ufshcd_clkgate_delay_set(hba->dev, ah_ms + 5);
}
}
@@ -992,13 +988,10 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
static void ufs_mtk_auto_hibern8_disable(struct ufs_hba *hba)
{
- unsigned long flags;
int ret;
/* disable auto-hibern8 */
- spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_writel(hba, 0, REG_AUTO_HIBERNATE_IDLE_TIMER);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
/* wait host return to idle state when auto-hibern8 off */
ufs_mtk_wait_idle_state(hba, 5);
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index bbb0ad7590ec..745e48ec598f 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -6,10 +6,10 @@
* Copyright 2019 Google LLC
*/
+#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/qcom_scm.h>
-#include "ufshcd-crypto.h"
#include "ufs-qcom.h"
#define AES_256_XTS_KEY_SIZE 64
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 586c0e567ff9..4dcb232facaa 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -5,6 +5,9 @@
#include <linux/acpi.h>
#include <linux/time.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
@@ -18,6 +21,7 @@
#include "ufs-qcom.h"
#include "ufshci.h"
#include "ufs_quirks.h"
+
#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
(UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
@@ -299,8 +303,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
struct phy *phy = host->generic_phy;
int ret = 0;
- bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
- ? true : false;
+ bool is_rate_B = UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B;
/* Reset UFS Host Controller and PHY */
ret = ufs_qcom_host_reset(hba);
@@ -641,12 +644,7 @@ static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
return err;
}
- err = ufs_qcom_ice_resume(host);
- if (err)
- return err;
-
- hba->is_sys_suspended = false;
- return 0;
+ return ufs_qcom_ice_resume(host);
}
static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
@@ -687,8 +685,11 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
writel_relaxed(temp, host->dev_ref_clk_ctrl_mmio);
- /* ensure that ref_clk is enabled/disabled before we return */
- wmb();
+ /*
+ * Make sure the write to ref_clk reaches the destination and
+ * not stored in a Write Buffer (WB).
+ */
+ readl(host->dev_ref_clk_ctrl_mmio);
/*
* If we call hibern8 exit after this, we need to make sure that
@@ -873,6 +874,7 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba)
hba->caps |= UFSHCD_CAP_WB_EN;
hba->caps |= UFSHCD_CAP_CRYPTO;
hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE;
+ hba->caps |= UFSHCD_CAP_RPM_AUTOSUSPEND;
if (host->hw_ver.major >= 0x2) {
host->caps = UFS_QCOM_CAP_QUNIPRO |
@@ -987,13 +989,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
host->hba = hba;
ufshcd_set_variant(hba, host);
- /* Setup the reset control of HCI */
- host->core_reset = devm_reset_control_get(hba->dev, "rst");
+ /* Setup the optional reset control of HCI */
+ host->core_reset = devm_reset_control_get_optional(hba->dev, "rst");
if (IS_ERR(host->core_reset)) {
- err = PTR_ERR(host->core_reset);
- dev_warn(dev, "Failed to get reset control %d\n", err);
- host->core_reset = NULL;
- err = 0;
+ err = dev_err_probe(dev, PTR_ERR(host->core_reset),
+ "Failed to get reset control\n");
+ goto out_variant_clear;
}
/* Fire up the reset controller. Failure here is non-fatal. */
@@ -1007,28 +1008,10 @@ static int ufs_qcom_init(struct ufs_hba *hba)
err = 0;
}
- /*
- * voting/devoting device ref_clk source is time consuming hence
- * skip devoting it during aggressive clock gating. This clock
- * will still be gated off during runtime suspend.
- */
- host->generic_phy = devm_phy_get(dev, "ufsphy");
-
- if (host->generic_phy == ERR_PTR(-EPROBE_DEFER)) {
- /*
- * UFS driver might be probed before the phy driver does.
- * In that case we would like to return EPROBE_DEFER code.
- */
- err = -EPROBE_DEFER;
- dev_warn(dev, "%s: required phy device. hasn't probed yet. err = %d\n",
- __func__, err);
- goto out_variant_clear;
- } else if (IS_ERR(host->generic_phy)) {
- if (has_acpi_companion(dev)) {
- host->generic_phy = NULL;
- } else {
- err = PTR_ERR(host->generic_phy);
- dev_err(dev, "%s: PHY get failed %d\n", __func__, err);
+ if (!has_acpi_companion(dev)) {
+ host->generic_phy = devm_phy_get(dev, "ufsphy");
+ if (IS_ERR(host->generic_phy)) {
+ err = dev_err_probe(dev, PTR_ERR(host->generic_phy), "Failed to get PHY\n");
goto out_variant_clear;
}
}
@@ -1449,23 +1432,17 @@ static int ufs_qcom_device_reset(struct ufs_hba *hba)
#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
- struct devfreq_dev_profile *p,
- void *data)
+ struct devfreq_dev_profile *p,
+ struct devfreq_simple_ondemand_data *d)
{
- static struct devfreq_simple_ondemand_data *d;
-
- if (!data)
- return;
-
- d = (struct devfreq_simple_ondemand_data *)data;
p->polling_ms = 60;
d->upthreshold = 70;
d->downdifferential = 5;
}
#else
static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
- struct devfreq_dev_profile *p,
- void *data)
+ struct devfreq_dev_profile *p,
+ struct devfreq_simple_ondemand_data *data)
{
}
#endif
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 8208e3a3ef59..771bc95d02c7 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -7,6 +7,7 @@
#include <linux/reset-controller.h>
#include <linux/reset.h>
+#include "ufshcd.h"
#define MAX_UFS_QCOM_HOSTS 1
#define MAX_U32 (~(u32)0)
@@ -239,10 +240,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
{
- if (host->caps & UFS_QCOM_CAP_QUNIPRO)
- return true;
- else
- return false;
+ return host->caps & UFS_QCOM_CAP_QUNIPRO;
}
/* ufs-qcom-ice.c */
diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c
index 5c405ff7b6ea..8a3c6442f291 100644
--- a/drivers/scsi/ufs/ufs-sysfs.c
+++ b/drivers/scsi/ufs/ufs-sysfs.c
@@ -8,6 +8,7 @@
#include "ufs.h"
#include "ufs-sysfs.h"
+#include "ufshcd-priv.h"
static const char *ufshcd_uic_link_state_to_string(
enum uic_link_state state)
diff --git a/drivers/scsi/ufs/ufs-sysfs.h b/drivers/scsi/ufs/ufs-sysfs.h
index 0f4e750a6748..8d94af3b8077 100644
--- a/drivers/scsi/ufs/ufs-sysfs.h
+++ b/drivers/scsi/ufs/ufs-sysfs.h
@@ -7,11 +7,12 @@
#include <linux/sysfs.h>
-#include "ufshcd.h"
+struct device;
void ufs_sysfs_add_nodes(struct device *dev);
void ufs_sysfs_remove_nodes(struct device *dev);
extern const struct attribute_group ufs_sysfs_unit_descriptor_group;
extern const struct attribute_group ufs_sysfs_lun_attributes_group;
+
#endif
diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 4a00c24a3209..1bba3fead2ce 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -415,11 +415,6 @@ enum ufs_ref_clk_freq {
REF_CLK_FREQ_INVAL = -1,
};
-struct ufs_ref_clk {
- unsigned long freq_hz;
- enum ufs_ref_clk_freq val;
-};
-
/* Query response result code */
enum {
QUERY_RESULT_SUCCESS = 0x00,
@@ -562,15 +557,6 @@ struct ufs_query_res {
struct utp_upiu_query upiu_res;
};
-#define UFS_VREG_VCC_MIN_UV 2700000 /* uV */
-#define UFS_VREG_VCC_MAX_UV 3600000 /* uV */
-#define UFS_VREG_VCC_1P8_MIN_UV 1700000 /* uV */
-#define UFS_VREG_VCC_1P8_MAX_UV 1950000 /* uV */
-#define UFS_VREG_VCCQ_MIN_UV 1140000 /* uV */
-#define UFS_VREG_VCCQ_MAX_UV 1260000 /* uV */
-#define UFS_VREG_VCCQ2_MIN_UV 1700000 /* uV */
-#define UFS_VREG_VCCQ2_MAX_UV 1950000 /* uV */
-
/*
* VCCQ & VCCQ2 current requirement when UFS device is in sleep state
* and link is in Hibern8 state.
@@ -582,8 +568,6 @@ struct ufs_vreg {
const char *name;
bool always_on;
bool enabled;
- int min_uV;
- int max_uV;
int max_uA;
};
@@ -636,23 +620,4 @@ enum ufs_trace_tsf_t {
UFS_TSF_CDB, UFS_TSF_OSF, UFS_TSF_TM_INPUT, UFS_TSF_TM_OUTPUT
};
-/**
- * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
- * @dev_info: pointer of instance of struct ufs_dev_info
- * @lun: LU number to check
- * @return: true if the lun has a matching unit descriptor, false otherwise
- */
-static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info,
- u8 lun, u8 param_offset)
-{
- if (!dev_info || !dev_info->max_lu_supported) {
- pr_err("Max General LU supported by UFS isn't initialized\n");
- return false;
- }
- /* WB is available only for the logical unit from 0 to 7 */
- if (param_offset == UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS)
- return lun < UFS_UPIU_MAX_WB_LUN_ID;
- return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported);
-}
-
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c
index 39bf204c6ec3..9e9b93867cab 100644
--- a/drivers/scsi/ufs/ufs_bsg.c
+++ b/drivers/scsi/ufs/ufs_bsg.c
@@ -4,7 +4,13 @@
*
* Copyright (C) 2018 Western Digital Corporation
*/
+
+#include <linux/bsg-lib.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
#include "ufs_bsg.h"
+#include "ufshcd.h"
+#include "ufshcd-priv.h"
static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
struct utp_upiu_query *qr)
diff --git a/drivers/scsi/ufs/ufs_bsg.h b/drivers/scsi/ufs/ufs_bsg.h
index d09918758631..57712d2656d2 100644
--- a/drivers/scsi/ufs/ufs_bsg.h
+++ b/drivers/scsi/ufs/ufs_bsg.h
@@ -5,12 +5,7 @@
#ifndef UFS_BSG_H
#define UFS_BSG_H
-#include <linux/bsg-lib.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-
-#include "ufshcd.h"
-#include "ufs.h"
+struct ufs_hba;
#ifdef CONFIG_SCSI_UFS_BSG
void ufs_bsg_remove(struct ufs_hba *hba);
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 35ec9ea79869..bcb4f004bed5 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -19,25 +19,16 @@
#define UFS_VENDOR_WDC 0x145
/**
- * ufs_dev_fix - ufs device quirk info
+ * ufs_dev_quirk - ufs device quirk info
* @card: ufs card details
* @quirk: device quirk
*/
-struct ufs_dev_fix {
+struct ufs_dev_quirk {
u16 wmanufacturerid;
- u8 *model;
+ const u8 *model;
unsigned int quirk;
};
-#define END_FIX { }
-
-/* add specific device quirk */
-#define UFS_FIX(_vendor, _model, _quirk) { \
- .wmanufacturerid = (_vendor),\
- .model = (_model), \
- .quirk = (_quirk), \
-}
-
/*
* Some vendor's UFS device sends back to back NACs for the DL data frames
* causing the host controller to raise the DFES error status. Sometimes
diff --git a/drivers/scsi/ufs/ufshcd-crypto.h b/drivers/scsi/ufs/ufshcd-crypto.h
index e18c01276873..9f98f18f9646 100644
--- a/drivers/scsi/ufs/ufshcd-crypto.h
+++ b/drivers/scsi/ufs/ufshcd-crypto.h
@@ -6,10 +6,13 @@
#ifndef _UFSHCD_CRYPTO_H
#define _UFSHCD_CRYPTO_H
-#ifdef CONFIG_SCSI_UFS_CRYPTO
+#include <scsi/scsi_cmnd.h>
#include "ufshcd.h"
+#include "ufshcd-priv.h"
#include "ufshci.h"
+#ifdef CONFIG_SCSI_UFS_CRYPTO
+
static inline void ufshcd_prepare_lrbp_crypto(struct request *rq,
struct ufshcd_lrb *lrbp)
{
diff --git a/drivers/scsi/ufs/ufshcd-dwc.c b/drivers/scsi/ufs/ufshcd-dwc.c
index 5bb9d3a88795..a57973c8d2a1 100644
--- a/drivers/scsi/ufs/ufshcd-dwc.c
+++ b/drivers/scsi/ufs/ufshcd-dwc.c
@@ -7,6 +7,8 @@
* Authors: Joao Pinto <jpinto@synopsys.com>
*/
+#include <linux/module.h>
+
#include "ufshcd.h"
#include "unipro.h"
diff --git a/drivers/scsi/ufs/ufshcd-dwc.h b/drivers/scsi/ufs/ufshcd-dwc.h
index 4268ca2eb64c..43b70794e24f 100644
--- a/drivers/scsi/ufs/ufshcd-dwc.h
+++ b/drivers/scsi/ufs/ufshcd-dwc.h
@@ -10,6 +10,8 @@
#ifndef _UFSHCD_DWC_H
#define _UFSHCD_DWC_H
+#include "ufshcd.h"
+
struct ufshcd_dme_attr_val {
u32 attr_sel;
u32 mib_val;
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index e892b9feffb1..20af2fbc3af1 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -2,7 +2,6 @@
/*
* Universal Flash Storage Host controller PCI glue driver
*
- * This code is based on drivers/scsi/ufs/ufshcd-pci.c
* Copyright (C) 2011-2013 Samsung India Software Operations
*
* Authors:
@@ -11,6 +10,8 @@
*/
#include "ufshcd.h"
+#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
@@ -618,4 +619,3 @@ MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
MODULE_DESCRIPTION("UFS host controller PCI glue driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index 87975d1a21c8..f5313f407617 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -8,6 +8,7 @@
* Vinayak Holikatti <h.vinayak@samsung.com>
*/
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
@@ -297,18 +298,20 @@ EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param);
void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param)
{
- dev_param->tx_lanes = 2;
- dev_param->rx_lanes = 2;
- dev_param->hs_rx_gear = UFS_HS_G3;
- dev_param->hs_tx_gear = UFS_HS_G3;
- dev_param->pwm_rx_gear = UFS_PWM_G4;
- dev_param->pwm_tx_gear = UFS_PWM_G4;
- dev_param->rx_pwr_pwm = SLOW_MODE;
- dev_param->tx_pwr_pwm = SLOW_MODE;
- dev_param->rx_pwr_hs = FAST_MODE;
- dev_param->tx_pwr_hs = FAST_MODE;
- dev_param->hs_rate = PA_HS_MODE_B;
- dev_param->desired_working_mode = UFS_HS_MODE;
+ *dev_param = (struct ufs_dev_params){
+ .tx_lanes = 2,
+ .rx_lanes = 2,
+ .hs_rx_gear = UFS_HS_G3,
+ .hs_tx_gear = UFS_HS_G3,
+ .pwm_rx_gear = UFS_PWM_G4,
+ .pwm_tx_gear = UFS_PWM_G4,
+ .rx_pwr_pwm = SLOW_MODE,
+ .tx_pwr_pwm = SLOW_MODE,
+ .rx_pwr_hs = FAST_MODE,
+ .tx_pwr_hs = FAST_MODE,
+ .hs_rate = PA_HS_MODE_B,
+ .desired_working_mode = UFS_HS_MODE,
+ };
}
EXPORT_SYMBOL_GPL(ufshcd_init_pwr_dev_param);
@@ -341,7 +344,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
err = ufshcd_alloc_host(dev, &hba);
if (err) {
- dev_err(&pdev->dev, "Allocation failed\n");
+ dev_err(dev, "Allocation failed\n");
goto out;
}
@@ -349,13 +352,13 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
err = ufshcd_parse_clock_info(hba);
if (err) {
- dev_err(&pdev->dev, "%s: clock parse failed %d\n",
+ dev_err(dev, "%s: clock parse failed %d\n",
__func__, err);
goto dealloc_host;
}
err = ufshcd_parse_regulator_info(hba);
if (err) {
- dev_err(&pdev->dev, "%s: regulator init failed %d\n",
+ dev_err(dev, "%s: regulator init failed %d\n",
__func__, err);
goto dealloc_host;
}
@@ -368,8 +371,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev,
goto dealloc_host;
}
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
return 0;
@@ -384,4 +387,3 @@ MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
MODULE_LICENSE("GPL");
-MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd-priv.h b/drivers/scsi/ufs/ufshcd-priv.h
new file mode 100644
index 000000000000..38bc77d3dbbd
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-priv.h
@@ -0,0 +1,298 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _UFSHCD_PRIV_H_
+#define _UFSHCD_PRIV_H_
+
+#include <linux/pm_runtime.h>
+#include "ufshcd.h"
+
+static inline bool ufshcd_is_user_access_allowed(struct ufs_hba *hba)
+{
+ return !hba->shutting_down;
+}
+
+void ufshcd_schedule_eh_work(struct ufs_hba *hba);
+
+static inline bool ufshcd_keep_autobkops_enabled_except_suspend(
+ struct ufs_hba *hba)
+{
+ return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND;
+}
+
+static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
+{
+ if (hba->dev_info.wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
+ return hba->dev_info.wb_dedicated_lu;
+ return 0;
+}
+
+#ifdef CONFIG_SCSI_UFS_HWMON
+void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
+void ufs_hwmon_remove(struct ufs_hba *hba);
+void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask);
+#else
+static inline void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) {}
+static inline void ufs_hwmon_remove(struct ufs_hba *hba) {}
+static inline void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask) {}
+#endif
+
+int ufshcd_read_desc_param(struct ufs_hba *hba,
+ enum desc_idn desc_id,
+ int desc_index,
+ u8 param_offset,
+ u8 *param_read_buf,
+ u8 param_size);
+int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode,
+ enum attr_idn idn, u8 index, u8 selector,
+ u32 *attr_val);
+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_flag(struct ufs_hba *hba, enum query_opcode opcode,
+ enum flag_idn idn, u8 index, bool *flag_res);
+void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
+
+#define SD_ASCII_STD true
+#define SD_RAW false
+int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
+ u8 **buf, bool ascii);
+
+int ufshcd_hold(struct ufs_hba *hba, bool async);
+void ufshcd_release(struct ufs_hba *hba);
+
+void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
+ int *desc_length);
+
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+
+int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
+ struct utp_upiu_req *req_upiu,
+ struct utp_upiu_req *rsp_upiu,
+ int msgcode,
+ u8 *desc_buff, int *buff_len,
+ enum query_opcode desc_op);
+
+int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable);
+
+/* Wrapper functions for safely calling variant operations */
+static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
+{
+ if (hba->vops)
+ return hba->vops->name;
+ return "";
+}
+
+static inline void ufshcd_vops_exit(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->exit)
+ return hba->vops->exit(hba);
+}
+
+static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->get_ufs_hci_version)
+ return hba->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, enum ufs_notify_change_status status)
+{
+ if (hba->vops && hba->vops->clk_scale_notify)
+ return hba->vops->clk_scale_notify(hba, up, status);
+ return 0;
+}
+
+static inline void ufshcd_vops_event_notify(struct ufs_hba *hba,
+ enum ufs_event_type evt,
+ void *data)
+{
+ if (hba->vops && hba->vops->event_notify)
+ hba->vops->event_notify(hba, evt, data);
+}
+
+static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on,
+ enum ufs_notify_change_status status)
+{
+ if (hba->vops && hba->vops->setup_clocks)
+ return hba->vops->setup_clocks(hba, on, status);
+ return 0;
+}
+
+static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
+ bool status)
+{
+ if (hba->vops && hba->vops->hce_enable_notify)
+ return hba->vops->hce_enable_notify(hba, status);
+
+ return 0;
+}
+static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
+ bool status)
+{
+ if (hba->vops && hba->vops->link_startup_notify)
+ return hba->vops->link_startup_notify(hba, status);
+
+ return 0;
+}
+
+static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status,
+ struct ufs_pa_layer_attr *dev_max_params,
+ struct ufs_pa_layer_attr *dev_req_params)
+{
+ if (hba->vops && hba->vops->pwr_change_notify)
+ return hba->vops->pwr_change_notify(hba, status,
+ dev_max_params, dev_req_params);
+
+ return -ENOTSUPP;
+}
+
+static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
+ int tag, u8 tm_function)
+{
+ if (hba->vops && hba->vops->setup_task_mgmt)
+ return hba->vops->setup_task_mgmt(hba, tag, tm_function);
+}
+
+static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
+ enum uic_cmd_dme cmd,
+ enum ufs_notify_change_status status)
+{
+ if (hba->vops && hba->vops->hibern8_notify)
+ return hba->vops->hibern8_notify(hba, cmd, status);
+}
+
+static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->apply_dev_quirks)
+ return hba->vops->apply_dev_quirks(hba);
+ return 0;
+}
+
+static inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->fixup_dev_quirks)
+ hba->vops->fixup_dev_quirks(hba);
+}
+
+static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op,
+ enum ufs_notify_change_status status)
+{
+ if (hba->vops && hba->vops->suspend)
+ return hba->vops->suspend(hba, op, status);
+
+ return 0;
+}
+
+static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
+{
+ if (hba->vops && hba->vops->resume)
+ return hba->vops->resume(hba, op);
+
+ return 0;
+}
+
+static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->dbg_register_dump)
+ hba->vops->dbg_register_dump(hba);
+}
+
+static inline int ufshcd_vops_device_reset(struct ufs_hba *hba)
+{
+ if (hba->vops && hba->vops->device_reset)
+ return hba->vops->device_reset(hba);
+
+ return -EOPNOTSUPP;
+}
+
+static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
+ struct devfreq_dev_profile *p,
+ struct devfreq_simple_ondemand_data *data)
+{
+ if (hba->vops && hba->vops->config_scaling_param)
+ hba->vops->config_scaling_param(hba, p, data);
+}
+
+extern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
+
+/**
+ * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
+ * @scsi_lun: scsi LUN id
+ *
+ * Returns UPIU LUN id
+ */
+static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
+{
+ if (scsi_is_wlun(scsi_lun))
+ return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
+ | UFS_UPIU_WLUN_ID;
+ else
+ return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
+}
+
+int __ufshcd_write_ee_control(struct ufs_hba *hba, u32 ee_ctrl_mask);
+int ufshcd_write_ee_control(struct ufs_hba *hba);
+int ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask, u16 *other_mask,
+ u16 set, u16 clr);
+
+static inline int ufshcd_update_ee_drv_mask(struct ufs_hba *hba,
+ u16 set, u16 clr)
+{
+ return ufshcd_update_ee_control(hba, &hba->ee_drv_mask,
+ &hba->ee_usr_mask, set, clr);
+}
+
+static inline int ufshcd_update_ee_usr_mask(struct ufs_hba *hba,
+ u16 set, u16 clr)
+{
+ return ufshcd_update_ee_control(hba, &hba->ee_usr_mask,
+ &hba->ee_drv_mask, set, clr);
+}
+
+static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba)
+{
+ return pm_runtime_get_sync(&hba->ufs_device_wlun->sdev_gendev);
+}
+
+static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
+{
+ return pm_runtime_put_sync(&hba->ufs_device_wlun->sdev_gendev);
+}
+
+static inline void ufshcd_rpm_get_noresume(struct ufs_hba *hba)
+{
+ pm_runtime_get_noresume(&hba->ufs_device_wlun->sdev_gendev);
+}
+
+static inline int ufshcd_rpm_resume(struct ufs_hba *hba)
+{
+ return pm_runtime_resume(&hba->ufs_device_wlun->sdev_gendev);
+}
+
+static inline int ufshcd_rpm_put(struct ufs_hba *hba)
+{
+ return pm_runtime_put(&hba->ufs_device_wlun->sdev_gendev);
+}
+
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @dev_info: pointer of instance of struct ufs_dev_info
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(struct ufs_dev_info *dev_info,
+ u8 lun, u8 param_offset)
+{
+ if (!dev_info || !dev_info->max_lu_supported) {
+ pr_err("Max General LU supported by UFS isn't initialized\n");
+ return false;
+ }
+ /* WB is available only for the logical unit from 0 to 7 */
+ if (param_offset == UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS)
+ return lun < UFS_UPIU_MAX_WB_LUN_ID;
+ return lun == UFS_UPIU_RPMB_WLUN || (lun < dev_info->max_lu_supported);
+}
+
+#endif /* _UFSHCD_PRIV_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 3f9caafa91bf..1fb3a8b9b03e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -16,8 +16,16 @@
#include <linux/bitfield.h>
#include <linux/blk-pm.h>
#include <linux/blkdev.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
#include <scsi/scsi_driver.h>
-#include "ufshcd.h"
+#include <scsi/scsi_eh.h>
+#include "ufshcd-priv.h"
#include "ufs_quirks.h"
#include "unipro.h"
#include "ufs-sysfs.h"
@@ -113,8 +121,13 @@ int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
if (!regs)
return -ENOMEM;
- for (pos = 0; pos < len; pos += 4)
+ for (pos = 0; pos < len; pos += 4) {
+ if (offset == 0 &&
+ pos >= REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER &&
+ pos <= REG_UIC_ERROR_CODE_DME)
+ continue;
regs[pos / 4] = ufshcd_readl(hba, offset + pos);
+ }
ufshcd_hex_dump(prefix, regs, len);
kfree(regs);
@@ -204,26 +217,33 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
return UFS_PM_LVL_0;
}
-static struct ufs_dev_fix ufs_fixups[] = {
+static const struct ufs_dev_quirk ufs_fixups[] = {
/* UFS cards deviations table */
- UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
- UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ),
- UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
- UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
- UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
- UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
- UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
- UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
- UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
- UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
- UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
- UFS_DEVICE_QUIRK_PA_TACTIVATE),
- UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
- UFS_DEVICE_QUIRK_PA_TACTIVATE),
- END_FIX
+ { .wmanufacturerid = UFS_VENDOR_MICRON,
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ },
+ { .wmanufacturerid = UFS_VENDOR_SAMSUNG,
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
+ UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
+ UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS },
+ { .wmanufacturerid = UFS_VENDOR_SKHYNIX,
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME },
+ { .wmanufacturerid = UFS_VENDOR_SKHYNIX,
+ .model = "hB8aL1" /*H28U62301AMR*/,
+ .quirk = UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME },
+ { .wmanufacturerid = UFS_VENDOR_TOSHIBA,
+ .model = UFS_ANY_MODEL,
+ .quirk = UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM },
+ { .wmanufacturerid = UFS_VENDOR_TOSHIBA,
+ .model = "THGLF2G9C8KBADG",
+ .quirk = UFS_DEVICE_QUIRK_PA_TACTIVATE },
+ { .wmanufacturerid = UFS_VENDOR_TOSHIBA,
+ .model = "THGLF2G9D8KBADG",
+ .quirk = UFS_DEVICE_QUIRK_PA_TACTIVATE },
+ {}
};
static irqreturn_t ufshcd_tmc_handler(struct ufs_hba *hba);
@@ -533,7 +553,7 @@ static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
static void ufshcd_print_host_state(struct ufs_hba *hba)
{
- struct scsi_device *sdev_ufs = hba->sdev_ufs_device;
+ struct scsi_device *sdev_ufs = hba->ufs_device_wlun;
dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
dev_err(hba->dev, "outstanding reqs=0x%lx tasks=0x%lx\n",
@@ -639,7 +659,7 @@ EXPORT_SYMBOL_GPL(ufshcd_delay_us);
* Return:
* -ETIMEDOUT on error, zero on success.
*/
-int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
+static int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
u32 val, unsigned long interval_us,
unsigned long timeout_ms)
{
@@ -712,8 +732,7 @@ static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
*/
static inline bool ufshcd_is_device_present(struct ufs_hba *hba)
{
- return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) &
- DEVICE_PRESENT) ? true : false;
+ return ufshcd_readl(hba, REG_CONTROLLER_STATUS) & DEVICE_PRESENT;
}
/**
@@ -840,7 +859,7 @@ ufshcd_get_rsp_upiu_data_seg_len(struct utp_upiu_rsp *ucd_rsp_ptr)
static inline bool ufshcd_is_exception_event(struct utp_upiu_rsp *ucd_rsp_ptr)
{
return be32_to_cpu(ucd_rsp_ptr->header.dword_2) &
- MASK_RSP_EXCEPTION_EVENT ? true : false;
+ MASK_RSP_EXCEPTION_EVENT;
}
/**
@@ -911,12 +930,11 @@ static inline void ufshcd_hba_start(struct ufs_hba *hba)
* ufshcd_is_hba_active - Get controller state
* @hba: per adapter instance
*
- * Returns false if controller is active, true otherwise
+ * Returns true if and only if the controller is active.
*/
static inline bool ufshcd_is_hba_active(struct ufs_hba *hba)
{
- return (ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & CONTROLLER_ENABLE)
- ? false : true;
+ return ufshcd_readl(hba, REG_CONTROLLER_ENABLE) & CONTROLLER_ENABLE;
}
u32 ufshcd_get_local_unipro_ver(struct ufs_hba *hba)
@@ -940,10 +958,7 @@ static bool ufshcd_is_unipro_pa_params_tuning_req(struct ufs_hba *hba)
* logic simple, we will only do manual tuning if local unipro version
* doesn't support ver1.6 or later.
*/
- if (ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6)
- return true;
- else
- return false;
+ return ufshcd_get_local_unipro_ver(hba) < UFS_UNIPRO_VER_1_6;
}
/**
@@ -1350,7 +1365,7 @@ static int ufshcd_devfreq_target(struct device *dev,
}
/* Decide based on the rounded-off frequency and update */
- scale_up = (*freq == clki->max_freq) ? true : false;
+ scale_up = *freq == clki->max_freq;
if (!scale_up)
*freq = clki->min_freq;
/* Update the frequency */
@@ -1862,18 +1877,26 @@ static ssize_t ufshcd_clkgate_delay_show(struct device *dev,
return sysfs_emit(buf, "%lu\n", hba->clk_gating.delay_ms);
}
+void ufshcd_clkgate_delay_set(struct device *dev, unsigned long value)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->clk_gating.delay_ms = value;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+}
+EXPORT_SYMBOL_GPL(ufshcd_clkgate_delay_set);
+
static ssize_t ufshcd_clkgate_delay_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct ufs_hba *hba = dev_get_drvdata(dev);
- unsigned long flags, value;
+ unsigned long value;
if (kstrtoul(buf, 0, &value))
return -EINVAL;
- spin_lock_irqsave(hba->host->host_lock, flags);
- hba->clk_gating.delay_ms = value;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
+ ufshcd_clkgate_delay_set(dev, value);
return count;
}
@@ -2120,9 +2143,6 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
__set_bit(task_tag, &hba->outstanding_reqs);
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
spin_unlock_irqrestore(&hba->outstanding_lock, flags);
-
- /* Make sure that doorbell is committed immediately */
- wmb();
}
/**
@@ -2131,15 +2151,17 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
*/
static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp)
{
+ u8 *const sense_buffer = lrbp->cmd->sense_buffer;
int len;
- if (lrbp->sense_buffer &&
+
+ if (sense_buffer &&
ufshcd_get_rsp_upiu_data_seg_len(lrbp->ucd_rsp_ptr)) {
int len_to_copy;
len = be16_to_cpu(lrbp->ucd_rsp_ptr->sr.sense_data_len);
len_to_copy = min_t(int, UFS_SENSE_SIZE, len);
- memcpy(lrbp->sense_buffer, lrbp->ucd_rsp_ptr->sr.sense_data,
+ memcpy(sense_buffer, lrbp->ucd_rsp_ptr->sr.sense_data,
len_to_copy);
}
}
@@ -2217,10 +2239,7 @@ static inline int ufshcd_hba_capabilities(struct ufs_hba *hba)
*/
static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
{
- if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY)
- return true;
- else
- return false;
+ return ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY;
}
/**
@@ -2796,11 +2815,9 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
lrbp->cmd = cmd;
- lrbp->sense_bufflen = UFS_SENSE_SIZE;
- lrbp->sense_buffer = cmd->sense_buffer;
lrbp->task_tag = tag;
lrbp->lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun);
- lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba) ? true : false;
+ lrbp->intr_cmd = !ufshcd_is_intr_aggr_allowed(hba);
ufshcd_prepare_lrbp_crypto(scsi_cmd_to_rq(cmd), lrbp);
@@ -2837,8 +2854,6 @@ static int ufshcd_compose_dev_cmd(struct ufs_hba *hba,
struct ufshcd_lrb *lrbp, enum dev_cmd_type cmd_type, int tag)
{
lrbp->cmd = NULL;
- lrbp->sense_bufflen = 0;
- lrbp->sense_buffer = NULL;
lrbp->task_tag = tag;
lrbp->lun = 0; /* device management cmd is not specific to any LUN */
lrbp->intr_cmd = true; /* No interrupt aggregation */
@@ -4198,7 +4213,7 @@ void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit)
spin_unlock_irqrestore(hba->host->host_lock, flags);
if (update &&
- !pm_runtime_suspended(&hba->sdev_ufs_device->sdev_gendev)) {
+ !pm_runtime_suspended(&hba->ufs_device_wlun->sdev_gendev)) {
ufshcd_rpm_get_sync(hba);
ufshcd_hold(hba, false);
ufshcd_auto_hibern8_enable(hba);
@@ -4210,14 +4225,10 @@ EXPORT_SYMBOL_GPL(ufshcd_auto_hibern8_update);
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba)
{
- unsigned long flags;
-
if (!ufshcd_is_auto_hibern8_supported(hba))
return;
- spin_lock_irqsave(hba->host->host_lock, flags);
ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER);
- spin_unlock_irqrestore(hba->host->host_lock, flags);
}
/**
@@ -4328,18 +4339,18 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
pwr_mode->lane_rx);
if (pwr_mode->pwr_rx == FASTAUTO_MODE ||
pwr_mode->pwr_rx == FAST_MODE)
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), true);
else
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), FALSE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_RXTERMINATION), false);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXGEAR), pwr_mode->gear_tx);
ufshcd_dme_set(hba, UIC_ARG_MIB(PA_ACTIVETXDATALANES),
pwr_mode->lane_tx);
if (pwr_mode->pwr_tx == FASTAUTO_MODE ||
pwr_mode->pwr_tx == FAST_MODE)
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), TRUE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), true);
else
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), FALSE);
+ ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXTERMINATION), false);
if (pwr_mode->pwr_rx == FASTAUTO_MODE ||
pwr_mode->pwr_tx == FASTAUTO_MODE ||
@@ -4438,7 +4449,7 @@ static int ufshcd_complete_dev_init(struct ufs_hba *hba)
QUERY_FLAG_IDN_FDEVICEINIT, 0, &flag_res);
if (!flag_res)
break;
- usleep_range(5000, 10000);
+ usleep_range(500, 1000);
} while (ktime_before(ktime_get(), timeout));
if (err) {
@@ -4554,7 +4565,7 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba)
int retry_inner;
start:
- if (!ufshcd_is_hba_active(hba))
+ if (ufshcd_is_hba_active(hba))
/* change controller state to "reset state" */
ufshcd_hba_stop(hba);
@@ -4580,7 +4591,7 @@ start:
/* wait for the host controller to complete initialization */
retry_inner = 50;
- while (ufshcd_is_hba_active(hba)) {
+ while (!ufshcd_is_hba_active(hba)) {
if (retry_inner) {
retry_inner--;
} else {
@@ -4914,13 +4925,13 @@ static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
* Device wlun is the supplier & rest of the luns are consumers.
* This ensures that device wlun suspends after all other luns.
*/
- if (hba->sdev_ufs_device) {
+ if (hba->ufs_device_wlun) {
link = device_link_add(&sdev->sdev_gendev,
- &hba->sdev_ufs_device->sdev_gendev,
+ &hba->ufs_device_wlun->sdev_gendev,
DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
if (!link) {
dev_err(&sdev->sdev_gendev, "Failed establishing link - %s\n",
- dev_name(&hba->sdev_ufs_device->sdev_gendev));
+ dev_name(&hba->ufs_device_wlun->sdev_gendev));
return;
}
hba->luns_avail--;
@@ -5056,15 +5067,15 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev)
/* Drop the reference as it won't be needed anymore */
if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) {
spin_lock_irqsave(hba->host->host_lock, flags);
- hba->sdev_ufs_device = NULL;
+ hba->ufs_device_wlun = NULL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
- } else if (hba->sdev_ufs_device) {
+ } else if (hba->ufs_device_wlun) {
struct device *supplier = NULL;
/* Ensure UFS Device WLUN exists and does not disappear */
spin_lock_irqsave(hba->host->host_lock, flags);
- if (hba->sdev_ufs_device) {
- supplier = &hba->sdev_ufs_device->sdev_gendev;
+ if (hba->ufs_device_wlun) {
+ supplier = &hba->ufs_device_wlun->sdev_gendev;
get_device(supplier);
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -5782,10 +5793,7 @@ static bool ufshcd_wb_presrv_usrspc_keep_vcc_on(struct ufs_hba *hba,
return false;
}
/* Let it continue to flush when available buffer exceeds threshold */
- if (avail_buf < hba->vps->wb_flush_threshold)
- return true;
-
- return false;
+ return avail_buf < hba->vps->wb_flush_threshold;
}
static void ufshcd_wb_force_disable(struct ufs_hba *hba)
@@ -5864,11 +5872,8 @@ static bool ufshcd_wb_need_flush(struct ufs_hba *hba)
return false;
}
- if (!hba->dev_info.b_presrv_uspc_en) {
- if (avail_buf <= UFS_WB_BUF_REMAIN_PERCENT(10))
- return true;
- return false;
- }
+ if (!hba->dev_info.b_presrv_uspc_en)
+ return avail_buf <= UFS_WB_BUF_REMAIN_PERCENT(10);
return ufshcd_wb_presrv_usrspc_keep_vcc_on(hba, avail_buf);
}
@@ -6046,7 +6051,7 @@ static void ufshcd_clk_scaling_suspend(struct ufs_hba *hba, bool suspend)
static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
{
ufshcd_rpm_get_sync(hba);
- if (pm_runtime_status_suspended(&hba->sdev_ufs_device->sdev_gendev) ||
+ if (pm_runtime_status_suspended(&hba->ufs_device_wlun->sdev_gendev) ||
hba->is_sys_suspended) {
enum ufs_pm_op pm_op;
@@ -6091,7 +6096,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba)
{
return (!hba->is_powered || hba->shutting_down ||
- !hba->sdev_ufs_device ||
+ !hba->ufs_device_wlun ||
hba->ufshcd_state == UFSHCD_STATE_ERROR ||
(!(hba->saved_err || hba->saved_uic_err || hba->force_reset ||
ufshcd_is_link_broken(hba))));
@@ -6110,7 +6115,7 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba)
* Set RPM status of wlun device to RPM_ACTIVE,
* this also clears its runtime error.
*/
- ret = pm_runtime_set_active(&hba->sdev_ufs_device->sdev_gendev);
+ ret = pm_runtime_set_active(&hba->ufs_device_wlun->sdev_gendev);
/* hba device might have a runtime error otherwise */
if (ret)
@@ -6815,8 +6820,6 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
lrbp = &hba->lrb[tag];
WARN_ON(lrbp->cmd);
lrbp->cmd = NULL;
- lrbp->sense_bufflen = 0;
- lrbp->sense_buffer = NULL;
lrbp->task_tag = tag;
lrbp->lun = 0;
lrbp->intr_cmd = true;
@@ -7223,7 +7226,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
* Stop the host controller and complete the requests
* cleared by h/w
*/
- ufshpb_reset_host(hba);
+ ufshpb_toggle_state(hba, HPB_PRESENT, HPB_RESET);
ufshcd_hba_stop(hba);
hba->silence_err_logs = true;
ufshcd_complete_requests(hba);
@@ -7351,7 +7354,7 @@ static u32 ufshcd_get_max_icc_level(int sup_curr_uA, u32 start_scan, char *buff)
u16 unit;
for (i = start_scan; i >= 0; i--) {
- data = be16_to_cpup((__be16 *)&buff[2 * i]);
+ data = get_unaligned_be16(&buff[2 * i]);
unit = (data & ATTR_ICC_LVL_UNIT_MASK) >>
ATTR_ICC_LVL_UNIT_OFFSET;
curr_uA = data & ATTR_ICC_LVL_VALUE_MASK;
@@ -7506,20 +7509,20 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
int ret = 0;
struct scsi_device *sdev_boot, *sdev_rpmb;
- hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0,
+ hba->ufs_device_wlun = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_UFS_DEVICE_WLUN), NULL);
- if (IS_ERR(hba->sdev_ufs_device)) {
- ret = PTR_ERR(hba->sdev_ufs_device);
- hba->sdev_ufs_device = NULL;
+ if (IS_ERR(hba->ufs_device_wlun)) {
+ ret = PTR_ERR(hba->ufs_device_wlun);
+ hba->ufs_device_wlun = NULL;
goto out;
}
- scsi_device_put(hba->sdev_ufs_device);
+ scsi_device_put(hba->ufs_device_wlun);
sdev_rpmb = __scsi_add_device(hba->host, 0, 0,
ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL);
if (IS_ERR(sdev_rpmb)) {
ret = PTR_ERR(sdev_rpmb);
- goto remove_sdev_ufs_device;
+ goto remove_ufs_device_wlun;
}
ufshcd_blk_pm_runtime_init(sdev_rpmb);
scsi_device_put(sdev_rpmb);
@@ -7534,8 +7537,8 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba)
}
goto out;
-remove_sdev_ufs_device:
- scsi_remove_device(hba->sdev_ufs_device);
+remove_ufs_device_wlun:
+ scsi_remove_device(hba->ufs_device_wlun);
out:
return ret;
}
@@ -7634,9 +7637,10 @@ static void ufshcd_temp_notif_probe(struct ufs_hba *hba, u8 *desc_buf)
}
}
-void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups)
+void ufshcd_fixup_dev_quirks(struct ufs_hba *hba,
+ const struct ufs_dev_quirk *fixups)
{
- struct ufs_dev_fix *f;
+ const struct ufs_dev_quirk *f;
struct ufs_dev_info *dev_info = &hba->dev_info;
if (!fixups)
@@ -7956,6 +7960,11 @@ out:
return err;
}
+struct ufs_ref_clk {
+ unsigned long freq_hz;
+ enum ufs_ref_clk_freq val;
+};
+
static struct ufs_ref_clk ufs_ref_clk_freqs[] = {
{19200000, REF_CLK_FREQ_19_2_MHZ},
{26000000, REF_CLK_FREQ_26_MHZ},
@@ -8184,7 +8193,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
/* Enable Auto-Hibernate if configured */
ufshcd_auto_hibern8_enable(hba);
- ufshpb_reset(hba);
+ ufshpb_toggle_state(hba, HPB_RESET, HPB_PRESENT);
out:
spin_lock_irqsave(hba->host->host_lock, flags);
if (ret)
@@ -8319,33 +8328,10 @@ static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
static int ufshcd_config_vreg(struct device *dev,
struct ufs_vreg *vreg, bool on)
{
- int ret = 0;
- struct regulator *reg;
- const char *name;
- int min_uV, uA_load;
-
- BUG_ON(!vreg);
-
- reg = vreg->reg;
- name = vreg->name;
-
- if (regulator_count_voltages(reg) > 0) {
- uA_load = on ? vreg->max_uA : 0;
- ret = ufshcd_config_vreg_load(dev, vreg, uA_load);
- if (ret)
- goto out;
+ if (regulator_count_voltages(vreg->reg) <= 0)
+ return 0;
- if (vreg->min_uV && vreg->max_uV) {
- min_uV = on ? vreg->min_uV : 0;
- ret = regulator_set_voltage(reg, min_uV, vreg->max_uV);
- if (ret)
- dev_err(dev,
- "%s: %s set voltage failed, err=%d\n",
- __func__, name, ret);
- }
- }
-out:
- return ret;
+ return ufshcd_config_vreg_load(dev, vreg, on ? vreg->max_uA : 0);
}
static int ufshcd_enable_vreg(struct device *dev, struct ufs_vreg *vreg)
@@ -8693,7 +8679,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
int ret, retries;
spin_lock_irqsave(hba->host->host_lock, flags);
- sdp = hba->sdev_ufs_device;
+ sdp = hba->ufs_device_wlun;
if (sdp) {
ret = scsi_device_get(sdp);
if (!ret && !scsi_device_online(sdp)) {
@@ -9257,7 +9243,7 @@ static void ufshcd_wl_shutdown(struct device *dev)
ufshcd_rpm_get_sync(hba);
scsi_device_quiesce(sdev);
shost_for_each_device(sdev, hba->host) {
- if (sdev == hba->sdev_ufs_device)
+ if (sdev == hba->ufs_device_wlun)
continue;
scsi_device_quiesce(sdev);
}
@@ -9478,7 +9464,7 @@ EXPORT_SYMBOL(ufshcd_shutdown);
*/
void ufshcd_remove(struct ufs_hba *hba)
{
- if (hba->sdev_ufs_device)
+ if (hba->ufs_device_wlun)
ufshcd_rpm_get_sync(hba);
ufs_hwmon_remove(hba);
ufs_bsg_remove(hba);
@@ -9806,7 +9792,7 @@ EXPORT_SYMBOL_GPL(ufshcd_resume_complete);
static bool ufshcd_rpm_ok_for_spm(struct ufs_hba *hba)
{
- struct device *dev = &hba->sdev_ufs_device->sdev_gendev;
+ struct device *dev = &hba->ufs_device_wlun->sdev_gendev;
enum ufs_dev_pwr_mode dev_pwr_mode;
enum uic_link_state link_state;
unsigned long flags;
@@ -9835,7 +9821,7 @@ int __ufshcd_suspend_prepare(struct device *dev, bool rpm_ok_for_spm)
* if it's runtime suspended. But ufs doesn't follow that.
* Refer ufshcd_resume_complete()
*/
- if (hba->sdev_ufs_device) {
+ if (hba->ufs_device_wlun) {
/* Prevent runtime suspend */
ufshcd_rpm_get_noresume(hba);
/*
@@ -9956,4 +9942,3 @@ MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
MODULE_DESCRIPTION("Generic UFS host controller driver Core");
MODULE_LICENSE("GPL");
-MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 94f545be183a..2b0f3441b813 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -12,44 +12,18 @@
#ifndef _UFSHCD_H
#define _UFSHCD_H
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/rwsem.h>
-#include <linux/workqueue.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/bitops.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/completion.h>
-#include <linux/regulator/consumer.h>
#include <linux/bitfield.h>
-#include <linux/devfreq.h>
#include <linux/blk-crypto-profile.h>
+#include <linux/blk-mq.h>
+#include <linux/devfreq.h>
+#include <linux/pm_runtime.h>
+#include <scsi/scsi_device.h>
#include "unipro.h"
-
-#include <asm/irq.h>
-#include <asm/byteorder.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_eh.h>
-
#include "ufs.h"
#include "ufs_quirks.h"
#include "ufshci.h"
#define UFSHCD "ufshcd"
-#define UFSHCD_DRIVER_VERSION "0.2"
struct ufs_hba;
@@ -181,8 +155,6 @@ struct ufs_pm_lvl_states {
* @ucd_rsp_dma_addr: UPIU response dma address for debug
* @ucd_req_dma_addr: UPIU request dma address for debug
* @cmd: pointer to SCSI command
- * @sense_buffer: pointer to sense buffer address of the SCSI command
- * @sense_bufflen: Length of the sense buffer
* @scsi_status: SCSI status of the command
* @command_type: SCSI, UFS, Query.
* @task_tag: Task tag of the command
@@ -206,8 +178,6 @@ struct ufshcd_lrb {
dma_addr_t ucd_prdt_dma_addr;
struct scsi_cmnd *cmd;
- u8 *sense_buffer;
- unsigned int sense_bufflen;
int scsi_status;
int command_type;
@@ -241,6 +211,7 @@ struct ufs_query {
* @type: device management command type - Query, NOP OUT
* @lock: lock to allow one command at a time
* @complete: internal commands completion
+ * @query: Device management query information
*/
struct ufs_dev_cmd {
enum dev_cmd_type type;
@@ -258,7 +229,7 @@ struct ufs_dev_cmd {
* @min_freq: min frequency that can be used for clock scaling
* @curr_freq: indicates the current frequency that it is set to
* @keep_link_active: indicates that the clk should not be disabled if
- link is active
+ * link is active
* @enabled: variable to check against multiple enable/disable
*/
struct ufs_clk_info {
@@ -313,11 +284,13 @@ struct ufs_pwr_mode_info {
* to set some things
* @hibern8_notify: called around hibern8 enter/exit
* @apply_dev_quirks: called to apply device specific quirks
+ * @fixup_dev_quirks: called to modify device specific quirks
* @suspend: called during host controller PM callback
* @resume: called during host controller PM callback
* @dbg_register_dump: used to dump controller debug information
* @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
* @program_key: program or evict an inline encryption key
* @event_notify: called to notify important events
*/
@@ -352,8 +325,8 @@ struct ufs_hba_variant_ops {
int (*phy_initialization)(struct ufs_hba *);
int (*device_reset)(struct ufs_hba *hba);
void (*config_scaling_param)(struct ufs_hba *hba,
- struct devfreq_dev_profile *profile,
- void *data);
+ struct devfreq_dev_profile *profile,
+ struct devfreq_simple_ondemand_data *data);
int (*program_key)(struct ufs_hba *hba,
const union ufs_crypto_cfg_entry *cfg, int slot);
void (*event_notify)(struct ufs_hba *hba,
@@ -384,6 +357,7 @@ enum clk_gating_state {
* @is_initialized: Indicates whether clock gating is initialized or not
* @active_reqs: number of requests that are pending and should be waited for
* completion before gating clocks.
+ * @clk_gating_workq: workqueue for clock gating work.
*/
struct ufs_clk_gating {
struct delayed_work gate_work;
@@ -420,9 +394,9 @@ struct ufs_saved_pwr_info {
* @resume_work: worker to resume devfreq
* @min_gear: lowest HS gear to scale down to
* @is_enabled: tracks if scaling is currently enabled or not, controlled by
- clkscale_enable sysfs node
+ * clkscale_enable sysfs node
* @is_allowed: tracks if scaling is currently allowed or not, used to block
- clock scaling which is not invoked from devfreq governor
+ * clock scaling which is not invoked from devfreq governor
* @is_initialized: Indicates whether clock scaling is initialized or not
* @is_busy_started: tracks if busy period has started or not
* @is_suspended: tracks if devfreq is suspended or not
@@ -449,7 +423,7 @@ struct ufs_clk_scaling {
/**
* struct ufs_event_hist - keeps history of errors
* @pos: index to indicate cyclic buffer position
- * @reg: cyclic buffer for registers value
+ * @val: cyclic buffer for registers value
* @tstamp: cyclic buffer for time stamp
* @cnt: error counter
*/
@@ -468,6 +442,7 @@ struct ufs_event_hist {
* reset this after link-startup.
* @last_hibern8_exit_tstamp: Set time after the hibern8 exit.
* Clear after the first successful command completion.
+ * @event: array with event history.
*/
struct ufs_stats {
u32 last_intr_status;
@@ -737,6 +712,14 @@ struct ufs_hba_monitor {
* @utmrdl_dma_addr: UTMRDL DMA address
* @host: Scsi_Host instance of the driver
* @dev: device handle
+ * @ufs_device_wlun: WLUN that controls the entire UFS device.
+ * @hwmon_device: device instance registered with the hwmon core.
+ * @curr_dev_pwr_mode: active UFS device power mode.
+ * @uic_link_state: active state of the link to the UFS device.
+ * @rpm_lvl: desired UFS power management level during runtime PM.
+ * @spm_lvl: desired UFS power management level during system PM.
+ * @pm_op_in_progress: whether or not a PM operation is in progress.
+ * @ahit: value of Auto-Hibernate Idle Timer register.
* @lrb: local reference block
* @outstanding_tasks: Bits representing outstanding task requests
* @outstanding_lock: Protects @outstanding_reqs.
@@ -747,17 +730,26 @@ struct ufs_hba_monitor {
* @reserved_slot: Used to submit device commands. Protected by @dev_cmd.lock.
* @ufs_version: UFS Version to which controller complies
* @vops: pointer to variant specific operations
+ * @vps: pointer to variant specific parameters
* @priv: pointer to variant specific private data
* @irq: Irq number of the controller
- * @active_uic_cmd: handle of active UIC command
- * @uic_cmd_mutex: mutex for UIC command
+ * @is_irq_enabled: whether or not the UFS controller interrupt is enabled.
+ * @dev_ref_clk_freq: reference clock frequency
+ * @quirks: bitmask with information about deviations from the UFSHCI standard.
+ * @dev_quirks: bitmask with information about deviations from the UFS standard.
* @tmf_tag_set: TMF tag set.
* @tmf_queue: Used to allocate TMF tags.
- * @pwr_done: completion for power mode change
+ * @tmf_rqs: array with pointers to TMF requests while these are in progress.
+ * @active_uic_cmd: handle of active UIC command
+ * @uic_cmd_mutex: mutex for UIC command
+ * @uic_async_done: completion used during UIC processing
* @ufshcd_state: UFSHCD state
* @eh_flags: Error handling flags
* @intr_mask: Interrupt Mask Bits
* @ee_ctrl_mask: Exception event control mask
+ * @ee_drv_mask: Exception event mask for driver
+ * @ee_usr_mask: Exception event mask for user (set via debugfs)
+ * @ee_ctrl_mutex: Used to serialize exception event information.
* @is_powered: flag to check if HBA is powered
* @shutting_down: flag to check if shutdown has been invoked
* @host_sem: semaphore used to serialize concurrent contexts
@@ -768,26 +760,52 @@ struct ufs_hba_monitor {
* @uic_error: UFS interconnect layer error status
* @saved_err: sticky error mask
* @saved_uic_err: sticky UIC error mask
+ * @ufs_stats: various error counters
* @force_reset: flag to force eh_work perform a full reset
* @force_pmc: flag to force a power mode change
* @silence_err_logs: flag to silence error logs
* @dev_cmd: ufs device management command information
* @last_dme_cmd_tstamp: time stamp of the last completed DME command
+ * @nop_out_timeout: NOP OUT timeout value
+ * @dev_info: information about the UFS device
* @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
+ * @req_abort_count: number of times ufshcd_abort() has been called
+ * @lanes_per_direction: number of lanes per data direction between the UFS
+ * controller and the UFS device.
* @pwr_info: holds current power mode
* @max_pwr_info: keeps the device max valid pwm
- * @clk_scaling_lock: used to serialize device commands and clock scaling
- * @desc_size: descriptor sizes reported by device
+ * @clk_gating: information related to clock gating
+ * @caps: bitmask with information about UFS controller capabilities
+ * @devfreq: frequency scaling information owned by the devfreq core
+ * @clk_scaling: frequency scaling information owned by the UFS driver
+ * @is_sys_suspended: whether or not the entire system has been suspended
* @urgent_bkops_lvl: keeps track of urgent bkops level for device
* @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
* device is known or not.
+ * @clk_scaling_lock: used to serialize device commands and clock scaling
+ * @desc_size: descriptor sizes reported by device
* @scsi_block_reqs_cnt: reference counting for scsi block requests
+ * @bsg_dev: struct device associated with the BSG queue
+ * @bsg_queue: BSG queue associated with the UFS controller
+ * @rpm_dev_flush_recheck_work: used to suspend from RPM (runtime power
+ * management) after the UFS device has finished a WriteBooster buffer
+ * flush or auto BKOP.
+ * @ufshpb_dev: information related to HPB (Host Performance Booster).
+ * @monitor: statistics about UFS commands
* @crypto_capabilities: Content of crypto capabilities register (0x100)
* @crypto_cap_array: Array of crypto capabilities
* @crypto_cfg_register: Start of the crypto cfg array
* @crypto_profile: the crypto profile of this hba (if applicable)
+ * @debugfs_root: UFS controller debugfs root directory
+ * @debugfs_ee_work: used to restore ee_ctrl_mask after a delay
+ * @debugfs_ee_rate_limit_ms: user configurable delay after which to restore
+ * ee_ctrl_mask
+ * @luns_avail: number of regular and well known LUNs supported by the UFS
+ * device
+ * @complete_put: whether or not to call ufshcd_rpm_put() from inside
+ * ufshcd_resume_complete()
*/
struct ufs_hba {
void __iomem *mmio_base;
@@ -804,11 +822,7 @@ struct ufs_hba {
struct Scsi_Host *host;
struct device *dev;
- /*
- * This field is to keep a reference to "scsi_device" corresponding to
- * "UFS device" W-LU.
- */
- struct scsi_device *sdev_ufs_device;
+ struct scsi_device *ufs_device_wlun;
#ifdef CONFIG_SCSI_UFS_HWMON
struct device *hwmon_device;
@@ -859,9 +873,9 @@ struct ufs_hba {
enum ufshcd_state ufshcd_state;
u32 eh_flags;
u32 intr_mask;
- u16 ee_ctrl_mask; /* Exception event mask */
- u16 ee_drv_mask; /* Exception event mask for driver */
- u16 ee_usr_mask; /* Exception event mask for user (via debugfs) */
+ u16 ee_ctrl_mask;
+ u16 ee_drv_mask;
+ u16 ee_usr_mask;
struct mutex ee_ctrl_mutex;
bool is_powered;
bool shutting_down;
@@ -983,7 +997,7 @@ static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba)
static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba)
{
- return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false;
+ return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit);
}
static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
@@ -991,22 +1005,17 @@ static inline bool ufshcd_is_wb_allowed(struct ufs_hba *hba)
return hba->caps & UFSHCD_CAP_WB_EN;
}
-static inline bool ufshcd_is_user_access_allowed(struct ufs_hba *hba)
-{
- return !hba->shutting_down;
-}
-
#define ufshcd_writel(hba, val, reg) \
writel((val), (hba)->mmio_base + (reg))
#define ufshcd_readl(hba, reg) \
readl((hba)->mmio_base + (reg))
/**
- * ufshcd_rmwl - read modify write into a register
- * @hba - per adapter instance
- * @mask - mask to apply on read value
- * @val - actual value to write
- * @reg - register address
+ * ufshcd_rmwl - perform read/modify/write for a controller register
+ * @hba: per adapter instance
+ * @mask: mask to apply on read value
+ * @val: actual value to write
+ * @reg: register address
*/
static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg)
{
@@ -1028,9 +1037,6 @@ void ufshcd_remove(struct ufs_hba *);
int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
void ufshcd_delay_us(unsigned long us, unsigned long tolerance);
-int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask,
- u32 val, unsigned long interval_us,
- unsigned long timeout_ms);
void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk);
void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val);
void ufshcd_hba_stop(struct ufs_hba *hba);
@@ -1044,8 +1050,8 @@ static inline void check_upiu_size(void)
/**
* ufshcd_set_variant - set variant specific data to the hba
- * @hba - per adapter instance
- * @variant - pointer to variant specific data
+ * @hba: per adapter instance
+ * @variant: pointer to variant specific data
*/
static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
{
@@ -1055,35 +1061,13 @@ static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant)
/**
* ufshcd_get_variant - get variant specific data from the hba
- * @hba - per adapter instance
+ * @hba: per adapter instance
*/
static inline void *ufshcd_get_variant(struct ufs_hba *hba)
{
BUG_ON(!hba);
return hba->priv;
}
-static inline bool ufshcd_keep_autobkops_enabled_except_suspend(
- struct ufs_hba *hba)
-{
- return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND;
-}
-
-static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
-{
- if (hba->dev_info.wb_buffer_type == WB_BUF_MODE_LU_DEDICATED)
- return hba->dev_info.wb_dedicated_lu;
- return 0;
-}
-
-#ifdef CONFIG_SCSI_UFS_HWMON
-void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask);
-void ufs_hwmon_remove(struct ufs_hba *hba);
-void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask);
-#else
-static inline void ufs_hwmon_probe(struct ufs_hba *hba, u8 mask) {}
-static inline void ufs_hwmon_remove(struct ufs_hba *hba) {}
-static inline void ufs_hwmon_notify_event(struct ufs_hba *hba, u8 ee_mask) {}
-#endif
#ifdef CONFIG_PM
extern int ufshcd_runtime_suspend(struct device *dev);
@@ -1185,7 +1169,8 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
void ufshcd_auto_hibern8_enable(struct ufs_hba *hba);
void ufshcd_auto_hibern8_update(struct ufs_hba *hba, u32 ahit);
-void ufshcd_fixup_dev_quirks(struct ufs_hba *hba, struct ufs_dev_fix *fixups);
+void ufshcd_fixup_dev_quirks(struct ufs_hba *hba,
+ const struct ufs_dev_quirk *fixups);
#define SD_ASCII_STD true
#define SD_RAW false
int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
@@ -1194,6 +1179,8 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
+void ufshcd_clkgate_delay_set(struct device *dev, unsigned long value);
+
void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
int *desc_length);
@@ -1214,13 +1201,6 @@ int __ufshcd_suspend_prepare(struct device *dev, bool rpm_ok_for_spm);
void ufshcd_resume_complete(struct device *dev);
/* Wrapper functions for safely calling variant operations */
-static inline const char *ufshcd_get_var_name(struct ufs_hba *hba)
-{
- if (hba->vops)
- return hba->vops->name;
- return "";
-}
-
static inline int ufshcd_vops_init(struct ufs_hba *hba)
{
if (hba->vops && hba->vops->init)
@@ -1229,61 +1209,6 @@ static inline int ufshcd_vops_init(struct ufs_hba *hba)
return 0;
}
-static inline void ufshcd_vops_exit(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->exit)
- return hba->vops->exit(hba);
-}
-
-static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->get_ufs_hci_version)
- return hba->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, enum ufs_notify_change_status status)
-{
- if (hba->vops && hba->vops->clk_scale_notify)
- return hba->vops->clk_scale_notify(hba, up, status);
- return 0;
-}
-
-static inline void ufshcd_vops_event_notify(struct ufs_hba *hba,
- enum ufs_event_type evt,
- void *data)
-{
- if (hba->vops && hba->vops->event_notify)
- hba->vops->event_notify(hba, evt, data);
-}
-
-static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on,
- enum ufs_notify_change_status status)
-{
- if (hba->vops && hba->vops->setup_clocks)
- return hba->vops->setup_clocks(hba, on, status);
- return 0;
-}
-
-static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba,
- bool status)
-{
- if (hba->vops && hba->vops->hce_enable_notify)
- return hba->vops->hce_enable_notify(hba, status);
-
- return 0;
-}
-static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba,
- bool status)
-{
- if (hba->vops && hba->vops->link_startup_notify)
- return hba->vops->link_startup_notify(hba, status);
-
- return 0;
-}
-
static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba)
{
if (hba->vops && hba->vops->phy_initialization)
@@ -1292,102 +1217,8 @@ static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba)
return 0;
}
-static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
- enum ufs_notify_change_status status,
- struct ufs_pa_layer_attr *dev_max_params,
- struct ufs_pa_layer_attr *dev_req_params)
-{
- if (hba->vops && hba->vops->pwr_change_notify)
- return hba->vops->pwr_change_notify(hba, status,
- dev_max_params, dev_req_params);
-
- return -ENOTSUPP;
-}
-
-static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
- int tag, u8 tm_function)
-{
- if (hba->vops && hba->vops->setup_task_mgmt)
- return hba->vops->setup_task_mgmt(hba, tag, tm_function);
-}
-
-static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
- enum uic_cmd_dme cmd,
- enum ufs_notify_change_status status)
-{
- if (hba->vops && hba->vops->hibern8_notify)
- return hba->vops->hibern8_notify(hba, cmd, status);
-}
-
-static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->apply_dev_quirks)
- return hba->vops->apply_dev_quirks(hba);
- return 0;
-}
-
-static inline void ufshcd_vops_fixup_dev_quirks(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->fixup_dev_quirks)
- hba->vops->fixup_dev_quirks(hba);
-}
-
-static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op,
- enum ufs_notify_change_status status)
-{
- if (hba->vops && hba->vops->suspend)
- return hba->vops->suspend(hba, op, status);
-
- return 0;
-}
-
-static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op)
-{
- if (hba->vops && hba->vops->resume)
- return hba->vops->resume(hba, op);
-
- return 0;
-}
-
-static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->dbg_register_dump)
- hba->vops->dbg_register_dump(hba);
-}
-
-static inline int ufshcd_vops_device_reset(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->device_reset)
- return hba->vops->device_reset(hba);
-
- return -EOPNOTSUPP;
-}
-
-static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
- struct devfreq_dev_profile
- *profile, void *data)
-{
- if (hba->vops && hba->vops->config_scaling_param)
- hba->vops->config_scaling_param(hba, profile, data);
-}
-
extern struct ufs_pm_lvl_states ufs_pm_lvl_states[];
-/*
- * ufshcd_scsi_to_upiu_lun - maps scsi LUN to UPIU LUN
- * @scsi_lun: scsi LUN id
- *
- * Returns UPIU LUN id
- */
-static inline u8 ufshcd_scsi_to_upiu_lun(unsigned int scsi_lun)
-{
- if (scsi_is_wlun(scsi_lun))
- return (scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID)
- | UFS_UPIU_WLUN_ID;
- else
- return scsi_lun & UFS_UPIU_MAX_UNIT_NUM_ID;
-}
-
int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
const char *prefix);
@@ -1396,43 +1227,4 @@ int ufshcd_write_ee_control(struct ufs_hba *hba);
int ufshcd_update_ee_control(struct ufs_hba *hba, u16 *mask, u16 *other_mask,
u16 set, u16 clr);
-static inline int ufshcd_update_ee_drv_mask(struct ufs_hba *hba,
- u16 set, u16 clr)
-{
- return ufshcd_update_ee_control(hba, &hba->ee_drv_mask,
- &hba->ee_usr_mask, set, clr);
-}
-
-static inline int ufshcd_update_ee_usr_mask(struct ufs_hba *hba,
- u16 set, u16 clr)
-{
- return ufshcd_update_ee_control(hba, &hba->ee_usr_mask,
- &hba->ee_drv_mask, set, clr);
-}
-
-static inline int ufshcd_rpm_get_sync(struct ufs_hba *hba)
-{
- return pm_runtime_get_sync(&hba->sdev_ufs_device->sdev_gendev);
-}
-
-static inline int ufshcd_rpm_put_sync(struct ufs_hba *hba)
-{
- return pm_runtime_put_sync(&hba->sdev_ufs_device->sdev_gendev);
-}
-
-static inline void ufshcd_rpm_get_noresume(struct ufs_hba *hba)
-{
- pm_runtime_get_noresume(&hba->sdev_ufs_device->sdev_gendev);
-}
-
-static inline int ufshcd_rpm_resume(struct ufs_hba *hba)
-{
- return pm_runtime_resume(&hba->sdev_ufs_device->sdev_gendev);
-}
-
-static inline int ufshcd_rpm_put(struct ufs_hba *hba)
-{
- return pm_runtime_put(&hba->sdev_ufs_device->sdev_gendev);
-}
-
#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index a7ff0e5b5494..f81aa95ffbc4 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -11,6 +11,8 @@
#ifndef _UFSHCI_H
#define _UFSHCI_H
+#include <scsi/scsi_host.h>
+
enum {
TASK_REQ_UPIU_SIZE_DWORDS = 8,
TASK_RSP_UPIU_SIZE_DWORDS = 8,
diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
index 588c0329b80c..8882b47f76d3 100644
--- a/drivers/scsi/ufs/ufshpb.c
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -10,8 +10,12 @@
*/
#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <scsi/scsi_cmnd.h>
-#include "ufshcd.h"
+#include "ufshcd-priv.h"
#include "ufshpb.h"
#include "../sd.h"
@@ -90,12 +94,8 @@ static bool ufshpb_is_general_lun(int lun)
static bool ufshpb_is_pinned_region(struct ufshpb_lu *hpb, int rgn_idx)
{
- if (hpb->lu_pinned_end != PINNED_NOT_SET &&
- rgn_idx >= hpb->lu_pinned_start &&
- rgn_idx <= hpb->lu_pinned_end)
- return true;
-
- return false;
+ return hpb->lu_pinned_end != PINNED_NOT_SET &&
+ rgn_idx >= hpb->lu_pinned_start && rgn_idx <= hpb->lu_pinned_end;
}
static void ufshpb_kick_map_work(struct ufshpb_lu *hpb)
@@ -563,7 +563,7 @@ static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx,
if (list_empty(&srgn->list_act_srgn))
list_add_tail(&srgn->list_act_srgn, &hpb->lh_act_srgn);
- hpb->stats.rb_active_cnt++;
+ hpb->stats.rcmd_active_cnt++;
}
static void ufshpb_update_inactive_info(struct ufshpb_lu *hpb, int rgn_idx)
@@ -580,7 +580,7 @@ static void ufshpb_update_inactive_info(struct ufshpb_lu *hpb, int rgn_idx)
if (list_empty(&rgn->list_inact_rgn))
list_add_tail(&rgn->list_inact_rgn, &hpb->lh_inact_rgn);
- hpb->stats.rb_inactive_cnt++;
+ hpb->stats.rcmd_inactive_cnt++;
}
static void ufshpb_activate_subregion(struct ufshpb_lu *hpb,
@@ -930,11 +930,6 @@ static int ufshpb_issue_umap_single_req(struct ufshpb_lu *hpb,
return ufshpb_issue_umap_req(hpb, rgn, true);
}
-static int ufshpb_issue_umap_all_req(struct ufshpb_lu *hpb)
-{
- return ufshpb_issue_umap_req(hpb, NULL, false);
-}
-
static void __ufshpb_evict_region(struct ufshpb_lu *hpb,
struct ufshpb_region *rgn)
{
@@ -1142,6 +1137,39 @@ out:
spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
return ret;
}
+/**
+ *ufshpb_submit_region_inactive() - submit a region to be inactivated later
+ *@hpb: per-LU HPB instance
+ *@region_index: the index associated with the region that will be inactivated later
+ */
+static void ufshpb_submit_region_inactive(struct ufshpb_lu *hpb, int region_index)
+{
+ int subregion_index;
+ struct ufshpb_region *rgn;
+ struct ufshpb_subregion *srgn;
+
+ /*
+ * Remove this region from active region list and add it to inactive list
+ */
+ spin_lock(&hpb->rsp_list_lock);
+ ufshpb_update_inactive_info(hpb, region_index);
+ spin_unlock(&hpb->rsp_list_lock);
+
+ rgn = hpb->rgn_tbl + region_index;
+
+ /*
+ * Set subregion state to be HPB_SRGN_INVALID, there will no HPB read on this subregion
+ */
+ spin_lock(&hpb->rgn_state_lock);
+ if (rgn->rgn_state != HPB_RGN_INACTIVE) {
+ for (subregion_index = 0; subregion_index < rgn->srgn_cnt; subregion_index++) {
+ srgn = rgn->srgn_tbl + subregion_index;
+ if (srgn->srgn_state == HPB_SRGN_VALID)
+ srgn->srgn_state = HPB_SRGN_INVALID;
+ }
+ }
+ spin_unlock(&hpb->rgn_state_lock);
+}
static void ufshpb_rsp_req_region_update(struct ufshpb_lu *hpb,
struct utp_hpb_rsp *rsp_field)
@@ -1201,25 +1229,8 @@ static void ufshpb_rsp_req_region_update(struct ufshpb_lu *hpb,
for (i = 0; i < rsp_field->inactive_rgn_cnt; i++) {
rgn_i = be16_to_cpu(rsp_field->hpb_inactive_field[i]);
- dev_dbg(&hpb->sdev_ufs_lu->sdev_dev,
- "inactivate(%d) region %d\n", i, rgn_i);
-
- spin_lock(&hpb->rsp_list_lock);
- ufshpb_update_inactive_info(hpb, rgn_i);
- spin_unlock(&hpb->rsp_list_lock);
-
- rgn = hpb->rgn_tbl + rgn_i;
-
- spin_lock(&hpb->rgn_state_lock);
- if (rgn->rgn_state != HPB_RGN_INACTIVE) {
- for (srgn_i = 0; srgn_i < rgn->srgn_cnt; srgn_i++) {
- srgn = rgn->srgn_tbl + srgn_i;
- if (srgn->srgn_state == HPB_SRGN_VALID)
- srgn->srgn_state = HPB_SRGN_INVALID;
- }
- }
- spin_unlock(&hpb->rgn_state_lock);
-
+ dev_dbg(&hpb->sdev_ufs_lu->sdev_dev, "inactivate(%d) region %d\n", i, rgn_i);
+ ufshpb_submit_region_inactive(hpb, rgn_i);
}
out:
@@ -1230,7 +1241,10 @@ out:
queue_work(ufshpb_wq, &hpb->map_work);
}
-static void ufshpb_dev_reset_handler(struct ufshpb_lu *hpb)
+/*
+ * Set the flags of all active regions to RGN_FLAG_UPDATE to let host side reload L2P entries later
+ */
+static void ufshpb_set_regions_update(struct ufshpb_lu *hpb)
{
struct victim_select_info *lru_info = &hpb->lru_info;
struct ufshpb_region *rgn;
@@ -1244,6 +1258,42 @@ static void ufshpb_dev_reset_handler(struct ufshpb_lu *hpb)
spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
}
+static void ufshpb_dev_reset_handler(struct ufs_hba *hba)
+{
+ struct scsi_device *sdev;
+ struct ufshpb_lu *hpb;
+
+ __shost_for_each_device(sdev, hba->host) {
+ hpb = ufshpb_get_hpb_data(sdev);
+ if (!hpb)
+ continue;
+
+ if (hpb->is_hcm) {
+ /*
+ * For the HPB host control mode, in case device powered up and lost HPB
+ * information, we will set the region flag to be RGN_FLAG_UPDATE, it will
+ * let host reload its L2P entries(reactivate region in the UFS device).
+ */
+ ufshpb_set_regions_update(hpb);
+ } else {
+ /*
+ * For the HPB device control mode, if host side receives 02h:HPB Operation
+ * in UPIU response, which means device recommends the host side should
+ * inactivate all active regions. Here we add all active regions to inactive
+ * list, they will be inactivated later in ufshpb_map_work_handler().
+ */
+ struct victim_select_info *lru_info = &hpb->lru_info;
+ struct ufshpb_region *rgn;
+
+ list_for_each_entry(rgn, &lru_info->lh_lru_rgn, list_lru_rgn)
+ ufshpb_submit_region_inactive(hpb, rgn->rgn_idx);
+
+ if (ufshpb_get_state(hpb) == HPB_PRESENT)
+ queue_work(ufshpb_wq, &hpb->map_work);
+ }
+ }
+}
+
/*
* This function will parse recommended active subregion information in sense
* data field of response UPIU with SAM_STAT_GOOD state.
@@ -1300,7 +1350,7 @@ void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
if (!ufshpb_is_hpb_rsp_valid(hba, lrbp, rsp_field))
return;
- hpb->stats.rb_noti_cnt++;
+ hpb->stats.rcmd_noti_cnt++;
switch (rsp_field->hpb_op) {
case HPB_RSP_REQ_REGION_UPDATE:
@@ -1313,17 +1363,7 @@ void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
case HPB_RSP_DEV_RESET:
dev_warn(&hpb->sdev_ufs_lu->sdev_dev,
"UFS device lost HPB information during PM.\n");
-
- if (hpb->is_hcm) {
- struct scsi_device *sdev;
-
- __shost_for_each_device(sdev, hba->host) {
- struct ufshpb_lu *h = sdev->hostdata;
-
- if (h)
- ufshpb_dev_reset_handler(h);
- }
- }
+ ufshpb_dev_reset_handler(hba);
break;
default:
@@ -1713,18 +1753,18 @@ static DEVICE_ATTR_RO(__name)
ufshpb_sysfs_attr_show_func(hit_cnt);
ufshpb_sysfs_attr_show_func(miss_cnt);
-ufshpb_sysfs_attr_show_func(rb_noti_cnt);
-ufshpb_sysfs_attr_show_func(rb_active_cnt);
-ufshpb_sysfs_attr_show_func(rb_inactive_cnt);
+ufshpb_sysfs_attr_show_func(rcmd_noti_cnt);
+ufshpb_sysfs_attr_show_func(rcmd_active_cnt);
+ufshpb_sysfs_attr_show_func(rcmd_inactive_cnt);
ufshpb_sysfs_attr_show_func(map_req_cnt);
ufshpb_sysfs_attr_show_func(umap_req_cnt);
static struct attribute *hpb_dev_stat_attrs[] = {
&dev_attr_hit_cnt.attr,
&dev_attr_miss_cnt.attr,
- &dev_attr_rb_noti_cnt.attr,
- &dev_attr_rb_active_cnt.attr,
- &dev_attr_rb_inactive_cnt.attr,
+ &dev_attr_rcmd_noti_cnt.attr,
+ &dev_attr_rcmd_active_cnt.attr,
+ &dev_attr_rcmd_inactive_cnt.attr,
&dev_attr_map_req_cnt.attr,
&dev_attr_umap_req_cnt.attr,
NULL,
@@ -2087,9 +2127,9 @@ static void ufshpb_stat_init(struct ufshpb_lu *hpb)
{
hpb->stats.hit_cnt = 0;
hpb->stats.miss_cnt = 0;
- hpb->stats.rb_noti_cnt = 0;
- hpb->stats.rb_active_cnt = 0;
- hpb->stats.rb_inactive_cnt = 0;
+ hpb->stats.rcmd_noti_cnt = 0;
+ hpb->stats.rcmd_active_cnt = 0;
+ hpb->stats.rcmd_inactive_cnt = 0;
hpb->stats.map_req_cnt = 0;
hpb->stats.umap_req_cnt = 0;
}
@@ -2272,38 +2312,28 @@ out:
return flag_res;
}
-void ufshpb_reset(struct ufs_hba *hba)
+/**
+ * ufshpb_toggle_state - switch HPB state of all LUs
+ * @hba: per-adapter instance
+ * @src: expected current HPB state
+ * @dest: target HPB state to switch to
+ */
+void ufshpb_toggle_state(struct ufs_hba *hba, enum UFSHPB_STATE src, enum UFSHPB_STATE dest)
{
struct ufshpb_lu *hpb;
struct scsi_device *sdev;
shost_for_each_device(sdev, hba->host) {
hpb = ufshpb_get_hpb_data(sdev);
- if (!hpb)
- continue;
- if (ufshpb_get_state(hpb) != HPB_RESET)
+ if (!hpb || ufshpb_get_state(hpb) != src)
continue;
+ ufshpb_set_state(hpb, dest);
- ufshpb_set_state(hpb, HPB_PRESENT);
- }
-}
-
-void ufshpb_reset_host(struct ufs_hba *hba)
-{
- struct ufshpb_lu *hpb;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, hba->host) {
- hpb = ufshpb_get_hpb_data(sdev);
- if (!hpb)
- continue;
-
- if (ufshpb_get_state(hpb) != HPB_PRESENT)
- continue;
- ufshpb_set_state(hpb, HPB_RESET);
- ufshpb_cancel_jobs(hpb);
- ufshpb_discard_rsp_lists(hpb);
+ if (dest == HPB_RESET) {
+ ufshpb_cancel_jobs(hpb);
+ ufshpb_discard_rsp_lists(hpb);
+ }
}
}
@@ -2314,11 +2344,9 @@ void ufshpb_suspend(struct ufs_hba *hba)
shost_for_each_device(sdev, hba->host) {
hpb = ufshpb_get_hpb_data(sdev);
- if (!hpb)
+ if (!hpb || ufshpb_get_state(hpb) != HPB_PRESENT)
continue;
- if (ufshpb_get_state(hpb) != HPB_PRESENT)
- continue;
ufshpb_set_state(hpb, HPB_SUSPEND);
ufshpb_cancel_jobs(hpb);
}
@@ -2331,20 +2359,15 @@ void ufshpb_resume(struct ufs_hba *hba)
shost_for_each_device(sdev, hba->host) {
hpb = ufshpb_get_hpb_data(sdev);
- if (!hpb)
+ if (!hpb || ufshpb_get_state(hpb) != HPB_SUSPEND)
continue;
- if ((ufshpb_get_state(hpb) != HPB_PRESENT) &&
- (ufshpb_get_state(hpb) != HPB_SUSPEND))
- continue;
ufshpb_set_state(hpb, HPB_PRESENT);
ufshpb_kick_map_work(hpb);
if (hpb->is_hcm) {
- unsigned int poll =
- hpb->params.timeout_polling_interval_ms;
+ unsigned int poll = hpb->params.timeout_polling_interval_ms;
- schedule_delayed_work(&hpb->ufshpb_read_to_work,
- msecs_to_jiffies(poll));
+ schedule_delayed_work(&hpb->ufshpb_read_to_work, msecs_to_jiffies(poll));
}
}
}
@@ -2450,8 +2473,6 @@ static void ufshpb_hpb_lu_prepared(struct ufs_hba *hba)
ufshpb_set_state(hpb, HPB_PRESENT);
if ((hpb->lu_pinned_end - hpb->lu_pinned_start) > 0)
queue_work(ufshpb_wq, &hpb->map_work);
- if (!hpb->is_hcm)
- ufshpb_issue_umap_all_req(hpb);
} else {
dev_err(hba->dev, "destroy HPB lu %d\n", hpb->lun);
ufshpb_destroy_lu(hba, sdev);
diff --git a/drivers/scsi/ufs/ufshpb.h b/drivers/scsi/ufs/ufshpb.h
index b475dbd78988..0d6e6004d783 100644
--- a/drivers/scsi/ufs/ufshpb.h
+++ b/drivers/scsi/ufs/ufshpb.h
@@ -59,8 +59,8 @@ enum UFSHPB_MODE {
};
enum UFSHPB_STATE {
- HPB_INIT = 0,
- HPB_PRESENT = 1,
+ HPB_INIT,
+ HPB_PRESENT,
HPB_SUSPEND,
HPB_FAILED,
HPB_RESET,
@@ -211,9 +211,9 @@ struct ufshpb_params {
struct ufshpb_stats {
u64 hit_cnt;
u64 miss_cnt;
- u64 rb_noti_cnt;
- u64 rb_active_cnt;
- u64 rb_inactive_cnt;
+ u64 rcmd_noti_cnt;
+ u64 rcmd_active_cnt;
+ u64 rcmd_inactive_cnt;
u64 map_req_cnt;
u64 pre_req_cnt;
u64 umap_req_cnt;
@@ -288,8 +288,7 @@ static int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { return 0;
static void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) {}
static void ufshpb_resume(struct ufs_hba *hba) {}
static void ufshpb_suspend(struct ufs_hba *hba) {}
-static void ufshpb_reset(struct ufs_hba *hba) {}
-static void ufshpb_reset_host(struct ufs_hba *hba) {}
+static void ufshpb_toggle_state(struct ufs_hba *hba, enum UFSHPB_STATE src, enum UFSHPB_STATE dest) {}
static void ufshpb_init(struct ufs_hba *hba) {}
static void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev) {}
static void ufshpb_destroy_lu(struct ufs_hba *hba, struct scsi_device *sdev) {}
@@ -303,8 +302,7 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp);
void ufshpb_rsp_upiu(struct ufs_hba *hba, struct ufshcd_lrb *lrbp);
void ufshpb_resume(struct ufs_hba *hba);
void ufshpb_suspend(struct ufs_hba *hba);
-void ufshpb_reset(struct ufs_hba *hba);
-void ufshpb_reset_host(struct ufs_hba *hba);
+void ufshpb_toggle_state(struct ufs_hba *hba, enum UFSHPB_STATE src, enum UFSHPB_STATE dest);
void ufshpb_init(struct ufs_hba *hba);
void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev);
void ufshpb_destroy_lu(struct ufs_hba *hba, struct scsi_device *sdev);
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
index 8e9e486a4f7b..0521f887e3ac 100644
--- a/drivers/scsi/ufs/unipro.h
+++ b/drivers/scsi/ufs/unipro.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * drivers/scsi/ufs/unipro.h
- *
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
*/
@@ -103,7 +101,7 @@
#define UNIPRO_CB_OFFSET(x) (0x8000 | x)
/*
- * PHY Adpater attributes
+ * PHY Adapter attributes
*/
#define PA_ACTIVETXDATALANES 0x1560
#define PA_ACTIVERXDATALANES 0x1580
@@ -300,20 +298,6 @@ enum ufs_unipro_ver {
#define T_TC0TXMAXSDUSIZE 0x4060
#define T_TC1TXMAXSDUSIZE 0x4061
-#ifdef FALSE
-#undef FALSE
-#endif
-
-#ifdef TRUE
-#undef TRUE
-#endif
-
-/* Boolean attribute values */
-enum {
- FALSE = 0,
- TRUE,
-};
-
/* CPort setting */
#define E2EFC_ON (1 << 0)
#define E2EFC_OFF (0 << 0)