Commit 2d95c6de authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "scsi: ufs: core: Always read the descriptors with max length"

Arthur Simchaev <Arthur.Simchaev@wdc.com> says:

Read any descriptor with a maximum size of QUERY_DESC_MAX_SIZE.
According to the spec the device returns the actual size.  Thus can
improve code readability and save CPU cycles.  While at it, clean up
few leftovers around the descriptor size parameter.

Link: https://lore.kernel.org/r/1670763911-8695-1-git-send-email-Arthur.Simchaev@wdc.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 4a5bd1a9 16ed9d31
Loading
Loading
Loading
Loading
+1 −6
Original line number Original line Diff line number Diff line
@@ -17,16 +17,11 @@ static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
				       struct utp_upiu_query *qr)
				       struct utp_upiu_query *qr)
{
{
	int desc_size = be16_to_cpu(qr->length);
	int desc_size = be16_to_cpu(qr->length);
	int desc_id = qr->idn;


	if (desc_size <= 0)
	if (desc_size <= 0)
		return -EINVAL;
		return -EINVAL;


	ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
	*desc_len = min_t(int, QUERY_DESC_MAX_SIZE, desc_size);
	if (!*desc_len)
		return -EINVAL;

	*desc_len = min_t(int, *desc_len, desc_size);


	return 0;
	return 0;
}
}
+0 −3
Original line number Original line Diff line number Diff line
@@ -70,9 +70,6 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
int ufshcd_hold(struct ufs_hba *hba, bool async);
int ufshcd_hold(struct ufs_hba *hba, bool async);
void ufshcd_release(struct ufs_hba *hba);
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_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);


int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
+25 −78
Original line number Original line Diff line number Diff line
@@ -3399,37 +3399,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
	return err;
	return err;
}
}


/**
 * ufshcd_map_desc_id_to_length - map descriptor IDN to its length
 * @hba: Pointer to adapter instance
 * @desc_id: descriptor idn value
 * @desc_len: mapped desc length (out)
 */
void ufshcd_map_desc_id_to_length(struct ufs_hba *hba, enum desc_idn desc_id,
				  int *desc_len)
{
	if (desc_id >= QUERY_DESC_IDN_MAX || desc_id == QUERY_DESC_IDN_RFU_0 ||
	    desc_id == QUERY_DESC_IDN_RFU_1)
		*desc_len = 0;
	else
		*desc_len = hba->desc_size[desc_id];
}
EXPORT_SYMBOL(ufshcd_map_desc_id_to_length);

static void ufshcd_update_desc_length(struct ufs_hba *hba,
				      enum desc_idn desc_id, int desc_index,
				      unsigned char desc_len)
{
	if (hba->desc_size[desc_id] == QUERY_DESC_MAX_SIZE &&
	    desc_id != QUERY_DESC_IDN_STRING && desc_index != UFS_RPMB_UNIT)
		/* For UFS 3.1, the normal unit descriptor is 10 bytes larger
		 * than the RPMB unit, however, both descriptors share the same
		 * desc_idn, to cover both unit descriptors with one length, we
		 * choose the normal unit descriptor length by desc_index.
		 */
		hba->desc_size[desc_id] = desc_len;
}

/**
/**
 * ufshcd_read_desc_param - read the specified descriptor parameter
 * ufshcd_read_desc_param - read the specified descriptor parameter
 * @hba: Pointer to adapter instance
 * @hba: Pointer to adapter instance
@@ -3450,26 +3419,13 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
{
{
	int ret;
	int ret;
	u8 *desc_buf;
	u8 *desc_buf;
	int buff_len;
	int buff_len = QUERY_DESC_MAX_SIZE;
	bool is_kmalloc = true;
	bool is_kmalloc = true;


	/* Safety check */
	/* Safety check */
	if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
	if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
		return -EINVAL;
		return -EINVAL;


	/* Get the length of descriptor */
	ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
	if (!buff_len) {
		dev_err(hba->dev, "%s: Failed to get desc length\n", __func__);
		return -EINVAL;
	}

	if (param_offset >= buff_len) {
		dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
			__func__, param_offset, desc_id, buff_len);
		return -EINVAL;
	}

	/* Check whether we need temp memory */
	/* Check whether we need temp memory */
	if (param_offset != 0 || param_size < buff_len) {
	if (param_offset != 0 || param_size < buff_len) {
		desc_buf = kzalloc(buff_len, GFP_KERNEL);
		desc_buf = kzalloc(buff_len, GFP_KERNEL);
@@ -3484,13 +3440,21 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
	ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
	ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
					    desc_id, desc_index, 0,
					    desc_id, desc_index, 0,
					    desc_buf, &buff_len);
					    desc_buf, &buff_len);

	if (ret) {
	if (ret) {
		dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
		dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
			__func__, desc_id, desc_index, param_offset, ret);
			__func__, desc_id, desc_index, param_offset, ret);
		goto out;
		goto out;
	}
	}


	/* Update descriptor length */
	buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];

	if (param_offset >= buff_len) {
		dev_err(hba->dev, "%s: Invalid offset 0x%x in descriptor IDN 0x%x, length 0x%x\n",
			__func__, param_offset, desc_id, buff_len);
		return -EINVAL;
	}

	/* Sanity check */
	/* Sanity check */
	if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
	if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) {
		dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
		dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n",
@@ -3499,10 +3463,6 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
		goto out;
		goto out;
	}
	}


	/* Update descriptor length */
	buff_len = desc_buf[QUERY_DESC_LENGTH_OFFSET];
	ufshcd_update_desc_length(hba, desc_id, desc_index, buff_len);

	if (is_kmalloc) {
	if (is_kmalloc) {
		/* Make sure we don't copy more data than available */
		/* Make sure we don't copy more data than available */
		if (param_offset >= buff_len)
		if (param_offset >= buff_len)
@@ -4940,7 +4900,7 @@ static void ufshcd_setup_links(struct ufs_hba *hba, struct scsi_device *sdev)
 */
 */
static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev)
static void ufshcd_lu_init(struct ufs_hba *hba, struct scsi_device *sdev)
{
{
	int len = hba->desc_size[QUERY_DESC_IDN_UNIT];
	int len = QUERY_DESC_MAX_SIZE;
	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
	u8 lun = ufshcd_scsi_to_upiu_lun(sdev->lun);
	u8 lun_qdepth = hba->nutrs;
	u8 lun_qdepth = hba->nutrs;
	u8 *desc_buf;
	u8 *desc_buf;
@@ -7564,12 +7524,11 @@ static u32 ufshcd_get_max_icc_level(int sup_curr_uA, u32 start_scan,
 * In case regulators are not initialized we'll return 0
 * In case regulators are not initialized we'll return 0
 * @hba: per-adapter instance
 * @hba: per-adapter instance
 * @desc_buf: power descriptor buffer to extract ICC levels from.
 * @desc_buf: power descriptor buffer to extract ICC levels from.
 * @len: length of desc_buff
 *
 *
 * Returns calculated ICC level
 * Returns calculated ICC level
 */
 */
static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
						const u8 *desc_buf, int len)
						const u8 *desc_buf)
{
{
	u32 icc_level = 0;
	u32 icc_level = 0;


@@ -7611,25 +7570,23 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba,
static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
static void ufshcd_set_active_icc_lvl(struct ufs_hba *hba)
{
{
	int ret;
	int ret;
	int buff_len = hba->desc_size[QUERY_DESC_IDN_POWER];
	u8 *desc_buf;
	u8 *desc_buf;
	u32 icc_level;
	u32 icc_level;


	desc_buf = kmalloc(buff_len, GFP_KERNEL);
	desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
	if (!desc_buf)
	if (!desc_buf)
		return;
		return;


	ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, 0,
	ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_POWER, 0, 0,
				     desc_buf, buff_len);
				     desc_buf, QUERY_DESC_MAX_SIZE);
	if (ret) {
	if (ret) {
		dev_err(hba->dev,
		dev_err(hba->dev,
			"%s: Failed reading power descriptor.len = %d ret = %d",
			"%s: Failed reading power descriptor ret = %d",
			__func__, buff_len, ret);
			__func__, ret);
		goto out;
		goto out;
	}
	}


	icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf,
	icc_level = ufshcd_find_max_sup_active_icc_level(hba, desc_buf);
							 buff_len);
	dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level);
	dev_dbg(hba->dev, "%s: setting icc_level 0x%x", __func__, icc_level);


	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
@@ -7739,10 +7696,6 @@ static void ufshcd_wb_probe(struct ufs_hba *hba, const u8 *desc_buf)
	     (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)))
	     (hba->dev_quirks & UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES)))
		goto wb_disabled;
		goto wb_disabled;


	if (hba->desc_size[QUERY_DESC_IDN_DEVICE] <
	    DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP + 4)
		goto wb_disabled;

	ext_ufs_feature = get_unaligned_be32(desc_buf +
	ext_ufs_feature = get_unaligned_be32(desc_buf +
					DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);
					DEVICE_DESC_PARAM_EXT_UFS_FEATURE_SUP);


@@ -7850,14 +7803,14 @@ static int ufs_get_device_desc(struct ufs_hba *hba)
	u8 *desc_buf;
	u8 *desc_buf;
	struct ufs_dev_info *dev_info = &hba->dev_info;
	struct ufs_dev_info *dev_info = &hba->dev_info;


	desc_buf = kmalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
	desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
	if (!desc_buf) {
	if (!desc_buf) {
		err = -ENOMEM;
		err = -ENOMEM;
		goto out;
		goto out;
	}
	}


	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf,
	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_DEVICE, 0, 0, desc_buf,
				     hba->desc_size[QUERY_DESC_IDN_DEVICE]);
				     QUERY_DESC_MAX_SIZE);
	if (err) {
	if (err) {
		dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
		dev_err(hba->dev, "%s: Failed reading Device Desc. err = %d\n",
			__func__, err);
			__func__, err);
@@ -8104,18 +8057,16 @@ static void ufshcd_clear_dbg_ufs_stats(struct ufs_hba *hba)
static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
{
{
	int err;
	int err;
	size_t buff_len;
	u8 *desc_buf;
	u8 *desc_buf;


	buff_len = hba->desc_size[QUERY_DESC_IDN_GEOMETRY];
	desc_buf = kzalloc(QUERY_DESC_MAX_SIZE, GFP_KERNEL);
	desc_buf = kmalloc(buff_len, GFP_KERNEL);
	if (!desc_buf) {
	if (!desc_buf) {
		err = -ENOMEM;
		err = -ENOMEM;
		goto out;
		goto out;
	}
	}


	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
				     desc_buf, buff_len);
				     desc_buf, QUERY_DESC_MAX_SIZE);
	if (err) {
	if (err) {
		dev_err(hba->dev, "%s: Failed reading Geometry Desc. err = %d\n",
		dev_err(hba->dev, "%s: Failed reading Geometry Desc. err = %d\n",
				__func__, err);
				__func__, err);
@@ -8127,7 +8078,7 @@ static int ufshcd_device_geo_params_init(struct ufs_hba *hba)
	else if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 0)
	else if (desc_buf[GEOMETRY_DESC_PARAM_MAX_NUM_LUN] == 0)
		hba->dev_info.max_lu_supported = 8;
		hba->dev_info.max_lu_supported = 8;


	if (hba->desc_size[QUERY_DESC_IDN_GEOMETRY] >=
	if (desc_buf[QUERY_DESC_LENGTH_OFFSET] >=
		GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS)
		GEOMETRY_DESC_PARAM_HPB_MAX_ACTIVE_REGS)
		ufshpb_get_geo_info(hba, desc_buf);
		ufshpb_get_geo_info(hba, desc_buf);


@@ -8212,11 +8163,7 @@ static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba)
static int ufshcd_device_params_init(struct ufs_hba *hba)
static int ufshcd_device_params_init(struct ufs_hba *hba)
{
{
	bool flag;
	bool flag;
	int ret, i;
	int ret;

	 /* Init device descriptor sizes */
	for (i = 0; i < QUERY_DESC_IDN_MAX; i++)
		hba->desc_size[i] = QUERY_DESC_MAX_SIZE;


	/* Init UFS geometry descriptor related parameters */
	/* Init UFS geometry descriptor related parameters */
	ret = ufshcd_device_geo_params_init(hba);
	ret = ufshcd_device_geo_params_init(hba);
+1 −3
Original line number Original line Diff line number Diff line
@@ -2382,12 +2382,10 @@ static int ufshpb_get_lu_info(struct ufs_hba *hba, int lun,
{
{
	u16 max_active_rgns;
	u16 max_active_rgns;
	u8 lu_enable;
	u8 lu_enable;
	int size;
	int size = QUERY_DESC_MAX_SIZE;
	int ret;
	int ret;
	char desc_buf[QUERY_DESC_MAX_SIZE];
	char desc_buf[QUERY_DESC_MAX_SIZE];


	ufshcd_map_desc_id_to_length(hba, QUERY_DESC_IDN_UNIT, &size);

	ufshcd_rpm_get_sync(hba);
	ufshcd_rpm_get_sync(hba);
	ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
	ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_READ_DESC,
					    QUERY_DESC_IDN_UNIT, lun, 0,
					    QUERY_DESC_IDN_UNIT, lun, 0,
+0 −1
Original line number Original line Diff line number Diff line
@@ -38,7 +38,6 @@
#define UFS_UPIU_MAX_UNIT_NUM_ID	0x7F
#define UFS_UPIU_MAX_UNIT_NUM_ID	0x7F
#define UFS_MAX_LUNS		(SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
#define UFS_MAX_LUNS		(SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID)
#define UFS_UPIU_WLUN_ID	(1 << 7)
#define UFS_UPIU_WLUN_ID	(1 << 7)
#define UFS_RPMB_UNIT		0xC4


/* WriteBooster buffer is available only for the logical unit from 0 to 7 */
/* WriteBooster buffer is available only for the logical unit from 0 to 7 */
#define UFS_UPIU_MAX_WB_LUN_ID	8
#define UFS_UPIU_MAX_WB_LUN_ID	8
Loading