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

Commit 7c7954f2 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by Sujit Reddy Thumma
Browse files

scsi: ufs: refactor query descriptor API support



Currently reading query descriptor is more tightened to each
descriptor type. This patch generalize the approach and allows
reading any parameter from any query descriptor.

Change-Id: I79fd505ce31d04f2490d88a4e6ab1497a0077462
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent 6b3e34cc
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
#define UFS_UPIU_MAX_UNIT_NUM_ID	0x7F
#define UFS_MAX_LUNS		(SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
#define UFS_UPIU_WLUN_ID	(1 << 7)
#define UFS_UPIU_MAX_GENERAL_LUN	8

/* Well known logical unit id in LUN field of UPIU */
enum {
@@ -150,10 +151,29 @@ enum desc_idn {
	QUERY_DESC_IDN_RFU_1		= 0x6,
	QUERY_DESC_IDN_GEOMETRY		= 0x7,
	QUERY_DESC_IDN_POWER		= 0x8,
	QUERY_DESC_IDN_RFU_2		= 0x9,
	QUERY_DESC_IDN_MAX,
};

enum desc_header_offset {
	QUERY_DESC_LENGTH_OFFSET	= 0x00,
	QUERY_DESC_DESC_TYPE_OFFSET	= 0x01,
};

enum ufs_desc_max_size {
	QUERY_DESC_DEVICE_MAX_SIZE		= 0x1F,
	QUERY_DESC_CONFIGURAION_MAX_SIZE	= 0x90,
	QUERY_DESC_UNIT_MAX_SIZE		= 0x23,
	QUERY_DESC_INTERCONNECT_MAX_SIZE	= 0x06,
	/*
	 * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes
	 * of descriptor header.
	 */
	QUERY_DESC_STRING_MAX_SIZE		= 0xFE,
	QUERY_DESC_GEOMETRY_MAZ_SIZE		= 0x44,
	QUERY_DESC_POWER_MAX_SIZE		= 0x62,
	QUERY_DESC_RFU_MAX_SIZE			= 0x00,
};

#define UNIT_DESC_MAX_SIZE       0x22
/* Unit descriptor parameters offsets in bytes*/
enum unit_desc_param {
	UNIT_DESC_PARAM_LEN			= 0x0,
@@ -182,7 +202,6 @@ enum {
	UFSHCD_AMP		= 3,
};

#define POWER_DESC_MAX_SIZE			0x62
#define POWER_DESC_MAX_ACTV_ICC_LVLS		16

/* Attribute  bActiveICCLevel parameter bit masks definitions */
+141 −42
Original line number Diff line number Diff line
@@ -100,6 +100,19 @@ print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, false)
/* Interrupt aggregation default timeout, unit: 40us */
#define INT_AGGR_DEF_TO	0x02

static u32 ufs_query_desc_max_size[] = {
	QUERY_DESC_DEVICE_MAX_SIZE,
	QUERY_DESC_CONFIGURAION_MAX_SIZE,
	QUERY_DESC_UNIT_MAX_SIZE,
	QUERY_DESC_RFU_MAX_SIZE,
	QUERY_DESC_INTERCONNECT_MAX_SIZE,
	QUERY_DESC_STRING_MAX_SIZE,
	QUERY_DESC_RFU_MAX_SIZE,
	QUERY_DESC_GEOMETRY_MAZ_SIZE,
	QUERY_DESC_POWER_MAX_SIZE,
	QUERY_DESC_RFU_MAX_SIZE,
};

enum {
	UFSHCD_MAX_CHANNEL	= 0,
	UFSHCD_MAX_ID		= 1,
@@ -178,10 +191,14 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba);
static void ufshcd_async_scan(void *data, async_cookie_t cookie);
static int ufshcd_reset_and_restore(struct ufs_hba *hba);
static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag);
static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
					struct scsi_device *sdev);
static void ufshcd_hba_exit(struct ufs_hba *hba);
static int ufshcd_probe_hba(struct ufs_hba *hba);
static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
					      int lun,
					      enum unit_desc_param param_offset,
					      u8 *param_read_buf,
					      u32 param_size);

static inline void ufshcd_enable_irq(struct ufs_hba *hba)
{
	if (!hba->is_irq_enabled) {
@@ -1571,6 +1588,116 @@ out:
	return err;
}

/**
 * ufshcd_read_desc_param - read the specified descriptor parameter
 * @hba: Pointer to adapter instance
 * @desc_id: descriptor idn value
 * @desc_index: descriptor index
 * @param_offset: offset of the parameter to read
 * @param_read_buf: pointer to buffer where parameter would be read
 * @param_size: sizeof(param_read_buf)
 *
 * Return 0 in case of success, non-zero otherwise
 */
static int ufshcd_read_desc_param(struct ufs_hba *hba,
				  enum desc_idn desc_id,
				  int desc_index,
				  u32 param_offset,
				  u8 *param_read_buf,
				  u32 param_size)
{
	int ret;
	u8 *desc_buf;
	u32 buff_len;
	bool is_kmalloc = true;

	/* safety checks */
	if (desc_id >= QUERY_DESC_IDN_MAX)
		return -EINVAL;

	buff_len = ufs_query_desc_max_size[desc_id];
	if ((param_offset + param_size) > buff_len)
		return -EINVAL;

	if (!param_offset && (param_size == buff_len)) {
		/* memory space already available to hold full descriptor */
		desc_buf = param_read_buf;
		is_kmalloc = false;
	} else {
		/* allocate memory to hold full descriptor */
		desc_buf = kmalloc(buff_len, GFP_KERNEL);
		if (!desc_buf)
			return -ENOMEM;
	}

	ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
				      desc_id, desc_index, 0, desc_buf,
				      &buff_len);

	if (ret || (buff_len < ufs_query_desc_max_size[desc_id]) ||
	    (desc_buf[QUERY_DESC_LENGTH_OFFSET] !=
	     ufs_query_desc_max_size[desc_id])
	    || (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id)) {
		dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d param_offset %d buff_len %d ret %d",
			__func__, desc_id, param_offset, buff_len, ret);
		if (!ret)
			ret = -EINVAL;

		goto out;
	}

	if (is_kmalloc)
		memcpy(param_read_buf, &desc_buf[param_offset], param_size);
out:
	if (is_kmalloc)
		kfree(desc_buf);
	return ret;
}

static inline int ufshcd_read_desc(struct ufs_hba *hba,
				   enum desc_idn desc_id,
				   int desc_index,
				   u8 *buf,
				   u32 size)
{
	return ufshcd_read_desc_param(hba, desc_id, desc_index, 0, buf, size);
}

static inline int ufshcd_read_power_desc(struct ufs_hba *hba,
					 u8 *buf,
					 u32 size)
{
	return ufshcd_read_desc(hba, QUERY_DESC_IDN_POWER, 0, buf, size);
}

/**
 * ufshcd_read_unit_desc_param - read the specified unit descriptor parameter
 * @hba: Pointer to adapter instance
 * @lun: lun id
 * @param_offset: offset of the parameter to read
 * @param_read_buf: pointer to buffer where parameter would be read
 * @param_size: sizeof(param_read_buf)
 *
 * Return 0 in case of success, non-zero otherwise
 */
static inline int ufshcd_read_unit_desc_param(struct ufs_hba *hba,
					      int lun,
					      enum unit_desc_param param_offset,
					      u8 *param_read_buf,
					      u32 param_size)
{
	/*
	 * Unit descriptors are only available for general purpose LUs (LUN id
	 * from 0 to 7) and RPMB Well known LU.
	 */
	if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
		return -EOPNOTSUPP;

	return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
				      param_offset, param_read_buf, param_size);
}


/**
 * ufshcd_memory_alloc - allocate memory for host memory space data structures
 * @hba: per adapter instance
@@ -2257,7 +2384,8 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba)
static int ufshcd_slave_alloc(struct scsi_device *sdev)
{
	struct ufs_hba *hba;
	int lun_qdepth;
	u8 lun_qdepth;
	int ret;

	hba = shost_priv(sdev->host);
	sdev->tagged_supported = 1;
@@ -2275,8 +2403,12 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev)
	/* try read capactiy (10) first as rc_16 is optional in UFS spec. */
	sdev->try_rc_10_first = 1;

	lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev);
	if (lun_qdepth <= 0)
	ret = ufshcd_read_unit_desc_param(hba,
					  ufshcd_scsi_to_upiu_lun(sdev->lun),
					  UNIT_DESC_PARAM_LU_Q_DEPTH,
					  &lun_qdepth,
					  sizeof(lun_qdepth));
	if (!ret || !lun_qdepth)
		/* eventually, we can figure out the real queue depth */
		lun_qdepth = hba->nutrs;
	else
@@ -3432,38 +3564,6 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
	return err;
}

/**
 * ufshcd_read_sdev_qdepth - read the lun command queue depth
 * @hba: Pointer to adapter instance
 * @sdev: pointer to SCSI device
 *
 * Return in case of success the lun's queue depth else error.
 */
static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba,
				struct scsi_device *sdev)
{
	int ret;
	int buff_len = UNIT_DESC_MAX_SIZE;
	u8 desc_buf[UNIT_DESC_MAX_SIZE];

	ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
			QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len);

	if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) {
		dev_err(hba->dev,
			"%s:Failed reading unit descriptor. len = %d ret = %d"
			, __func__, buff_len, ret);
		if (!ret)
			ret = -EINVAL;

		goto out;
	}

	ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF;
out:
	return ret;
}

/**
 * ufshcd_get_max_icc_level - calculate the ICC level
 * @sup_curr_uA: max. current supported by the regulator
@@ -3551,13 +3651,12 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
{
	u32 icc_level;
	int ret;
	int buff_len = POWER_DESC_MAX_SIZE;
	u8 desc_buf[POWER_DESC_MAX_SIZE];
	int buff_len = QUERY_DESC_POWER_MAX_SIZE;
	u8 desc_buf[QUERY_DESC_POWER_MAX_SIZE];

	ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC,
			QUERY_DESC_IDN_POWER, 0, 0, desc_buf, &buff_len);
	ret = ufshcd_read_power_desc(hba, desc_buf, buff_len);

	if (ret || (buff_len < POWER_DESC_MAX_SIZE)) {
	if (ret) {
		dev_err(hba->dev,
			"%s: Failed reading power descriptor.len = %d ret = %d",
			__func__, buff_len, ret);