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

Commit f401cfdf authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs: debugfs: add option to read peer DME attribute"

parents 658f4ef4 311f54ae
Loading
Loading
Loading
Loading
+95 −13
Original line number Diff line number Diff line
@@ -753,6 +753,23 @@ out:
	return ret;
}

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);
	scsi_block_requests(hba->host);
	ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US);
	if (!ret)
		ret = ufshcd_change_power_mode(hba, desired_pwr_mode);
	scsi_unblock_requests(hba->host);
	pm_runtime_put_sync(hba->dev);

	return ret;
}

static ssize_t ufsdbg_power_mode_write(struct file *file,
				const char __user *ubuf, size_t cnt,
				loff_t *ppos)
@@ -764,7 +781,6 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
	loff_t buff_pos = 0;
	int ret;
	int idx = 0;
	#define DOORBELL_CLR_TOUT_US	(1000 * 1000) /* 1 sec */

	ret = simple_write_to_buffer(pwr_mode_str, BUFF_LINE_CAPACITY,
		&buff_pos, ubuf, cnt);
@@ -800,13 +816,7 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
		return cnt;
	}

	pm_runtime_get_sync(hba->dev);
	scsi_block_requests(hba->host);
	ret = ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US);
	if (!ret)
		ret = ufshcd_change_power_mode(hba, &final_pwr_mode);
	scsi_unblock_requests(hba->host);
	pm_runtime_put_sync(hba->dev);
	ret = ufsdbg_config_pwr_mode(hba, &final_pwr_mode);
	if (ret == -EBUSY)
		dev_err(hba->dev,
			"%s: ufshcd_config_pwr_mode failed: system is busy, try again\n",
@@ -830,19 +840,21 @@ static const struct file_operations ufsdbg_power_mode_desc = {
	.write		= ufsdbg_power_mode_write,
};

static int ufsdbg_dme_local_read(void *data, u64 *attr_val)
static int ufsdbg_dme_read(void *data, u64 *attr_val, bool peer)
{
	int ret;
	struct ufs_hba *hba = data;
	u32 read_val = 0;
	u32 attr_id, read_val = 0;
	int (*read_func) (struct ufs_hba *, u32, u32 *);

	if (!hba)
		return -EINVAL;

	read_func = peer ? ufshcd_dme_peer_get : ufshcd_dme_get;
	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(hba->debugfs_files.dme_local_attr_id),
			&read_val);
	ret = ufshcd_dme_get(hba, UIC_ARG_MIB(attr_id), &read_val);
	pm_runtime_put_sync(hba->dev);

	if (!ret)
@@ -863,11 +875,70 @@ static int ufsdbg_dme_local_set_attr_id(void *data, u64 attr_id)
	return 0;
}

static int ufsdbg_dme_local_read(void *data, u64 *attr_val)
{
	return ufsdbg_dme_read(data, attr_val, false);
}

DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_local_read_ops,
			ufsdbg_dme_local_read,
			ufsdbg_dme_local_set_attr_id,
			"%llu\n");

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;
}

static int ufsdbg_dme_peer_set_attr_id(void *data, u64 attr_id)
{
	struct ufs_hba *hba = data;

	if (!hba)
		return -EINVAL;

	hba->debugfs_files.dme_peer_attr_id = (u32)attr_id;

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(ufsdbg_dme_peer_read_ops,
			ufsdbg_dme_peer_read,
			ufsdbg_dme_peer_set_attr_id,
			"%llu\n");

void ufsdbg_add_debugfs(struct ufs_hba *hba)
{
	if (!hba) {
@@ -962,6 +1033,17 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba)
		goto err;
	}

	hba->debugfs_files.dme_peer_read =
		debugfs_create_file("dme_peer_read", S_IRUSR | S_IWUSR,
				    hba->debugfs_files.debugfs_root, hba,
				    &ufsdbg_dme_peer_read_ops);
	if (!hba->debugfs_files.dme_peer_read) {
		dev_err(hba->dev,
			"%s:  failed create dme_peer_read debugfs entry\n",
			__func__);
		goto err;
	}

	ufsdbg_setup_fault_injection(hba);

	return;
+2 −0
Original line number Diff line number Diff line
@@ -750,6 +750,8 @@ 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);

	hba->quirks |= UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE;
}

static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
+2 −0
Original line number Diff line number Diff line
@@ -2705,6 +2705,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us)
	bool timeout = false;
	ktime_t start = ktime_get();

	ufshcd_hold(hba, false);
	spin_lock_irqsave(hba->host->host_lock, flags);
	if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
		ret = -EBUSY;
@@ -2739,6 +2740,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us)
	}
out:
	spin_unlock_irqrestore(hba->host->host_lock, flags);
	ufshcd_release(hba);
	return ret;
}

+8 −0
Original line number Diff line number Diff line
@@ -240,7 +240,9 @@ struct debugfs_files {
	struct dentry *dump_dev_desc;
	struct dentry *power_mode;
	struct dentry *dme_local_read;
	struct dentry *dme_peer_read;
	u32 dme_local_attr_id;
	u32 dme_peer_attr_id;
#ifdef CONFIG_UFS_FAULT_INJECTION
	struct fault_attr fail_attr;
#endif
@@ -507,6 +509,12 @@ struct ufs_hba {
	 */
	#define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP		UFS_BIT(3)

	/*
	 * This quirk needs to be enabled if the host contoller doesn't
	 * allow reading the dme attributes of peer UniPro in FAST_MODE.
	 */
	#define UFSHCD_QUIRK_DME_PEER_GET_FAST_MODE		UFS_BIT(4)

	unsigned int quirks;	/* Deviations from standard UFSHCI spec. */

	/* Device deviations from standard UFS device spec. */