From 0a81142619ded5b3f24cca651fa59ea17f7a7119 Mon Sep 17 00:00:00 2001 From: Subhash Jadavani Date: Thu, 25 Sep 2014 14:23:18 -0700 Subject: [PATCH] scsi: ufs: move dme peer quirk handling to ufshcd_dme_get_attr() Some UFS host controllers may only allow accessing the peer DME attribute in AUTO mode (FAST AUTO or SLOW AUTO) hence we had added a quirk for switching to AUTO power mode before accessing the peer DME attribute. But this quirk handling was only done in UFS driver's debugfs handling hence this patch moves it to main driver ufshcd.c so that this quirk handling is applied to all the peer DME accesses. As we are doing this, this patch fixes 2 more related problem: 1. Current quirk was only handling the switch from FAST to FAST AUTO hence this change adds the handling for SLOW to SLOW AUTO mode change as well. 2. ufsdbg_dme_read() helper function was always reading the local DME attribute hence this change fix the same. Change-Id: I475375fb57cd27cdafe1573c14d09dc7f9a2791b Signed-off-by: Subhash Jadavani [venkatg@codeaurora.org: resolved trivial merge conflicts] Signed-off-by: Venkat Gopalakrishnan --- drivers/scsi/ufs/debugfs.c | 40 +++++++++------------------------------- drivers/scsi/ufs/ufs-qcom.c | 2 +- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/drivers/scsi/ufs/debugfs.c b/drivers/scsi/ufs/debugfs.c index 9cfb12cdbcfe..50e23d08407f 100644 --- a/drivers/scsi/ufs/debugfs.c +++ b/drivers/scsi/ufs/debugfs.c @@ -42,6 +42,8 @@ struct desc_field_offset { } \ } while (0) +#define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */ + #ifdef CONFIG_UFS_FAULT_INJECTION #define INJECT_COMMAND_HANG (0x0) @@ -756,7 +758,6 @@ out: static int ufsdbg_config_pwr_mode(struct ufs_hba *hba, struct ufs_pa_layer_attr *desired_pwr_mode) { - #define DOORBELL_CLR_TOUT_US (1000 * 1000) /* 1 sec */ int ret; pm_runtime_get_sync(hba->dev); @@ -854,7 +855,11 @@ static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer) attr_id = peer ? hba->debugfs_files.dme_peer_attr_id : hba->debugfs_files.dme_local_attr_id; pm_runtime_get_sync(hba->dev); - ret = ufshcd_dme_get(hba, UIC_ARG_MIB(attr_id), &read_val); + scsi_block_requests(hba->host); + ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US); + if (!ret) + ret = read_func(hba, UIC_ARG_MIB(attr_id), &read_val); + scsi_unblock_requests(hba->host); pm_runtime_put_sync(hba->dev); if (!ret) @@ -887,39 +892,12 @@ DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_local_read_ops, static int ufsdbg_dme_peer_read(void *data, u64 *attr_val) { - int ret; struct ufs_hba *hba = data; - struct ufs_pa_layer_attr orig_pwr_info; - struct ufs_pa_layer_attr temp_pwr_info; - bool restore_pwr_mode = false; if (!hba) return -EINVAL; - - if (hba->quirks & UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE) { - orig_pwr_info = hba->pwr_info; - temp_pwr_info = orig_pwr_info; - if (orig_pwr_info.pwr_tx == FAST_MODE || - orig_pwr_info.pwr_rx == FAST_MODE) { - temp_pwr_info.pwr_tx = FASTAUTO_MODE; - temp_pwr_info.pwr_rx = FASTAUTO_MODE; - ret = ufsdbg_config_pwr_mode(hba, &temp_pwr_info); - if (ret) - goto out; - else - restore_pwr_mode = true; - } - } - - ret = ufsdbg_dme_read(data, attr_val, true); - - if (hba->quirks & UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE) { - if (restore_pwr_mode) - ufsdbg_config_pwr_mode(hba, &orig_pwr_info); - } - -out: - return ret; + else + return ufsdbg_dme_read(data, attr_val, true); } static int ufsdbg_dme_peer_set_attr_id(void *data, u64 attr_id) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 036b0a7a3238..ae206fd87550 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -768,7 +768,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP | UFSHCD_QUIRK_BROKEN_LCC - | UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE); + | UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE); if ((minor == 0x001) && (step == 0x0001)) hba->quirks |= UFSHCD_QUIRK_BROKEN_INTR_AGGR; -- 2.11.0