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

Commit 6949de30 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: refactor query descriptor API support"

parents a81021ed 7c7954f2
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
@@ -2295,7 +2422,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;
@@ -2313,8 +2441,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
@@ -3470,38 +3602,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
@@ -3589,13 +3689,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);