Commit 9ec5128a authored by Avri Altman's avatar Avri Altman Committed by Martin K. Petersen
Browse files

scsi: ufs: ufshpb: Properly handle max-single-cmd

The spec recommends that for transfer length larger than the max-single-cmd
attribute (bMAX_DATA_SIZE_FOR_HPB_SINGLE_CMD) it is possible to couple
pre-requests with the HPB-READ command.  Being a recommendation, using
pre-requests can be perceived merely as a means of optimization.  A common
practice was to send pre-requests for chunks within some interval, and
leave the READ10 untouched if larger.

Now that the pre-request flows have been removed, all the commands are
single commands.  Properly handle this attribute and do not send HPB-READ
for transfer lengths larger than max-single-cmd.

[mkp: resolve conflict]

Fixes: 09d9e4d0 ("scsi: ufs: ufshpb: Remove HPB2.0 flows")
Link: https://lore.kernel.org/r/20211031123654.17719-1-avri.altman@wdc.com


Reviewed-by: default avatarDaejun Park <daejun7.park@samsung.com>
Signed-off-by: default avatarAvri Altman <avri.altman@wdc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6266f7df
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -394,8 +394,6 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
	if (!ufshpb_is_supported_chunk(hpb, transfer_len))
		return 0;

	WARN_ON_ONCE(transfer_len > HPB_MULTI_CHUNK_HIGH);

	if (hpb->is_hcm) {
		/*
		 * in host control mode, reads are the main source for
@@ -1572,7 +1570,7 @@ static void ufshpb_lu_parameter_init(struct ufs_hba *hba,
	if (ufshpb_is_legacy(hba))
		hpb->pre_req_max_tr_len = HPB_LEGACY_CHUNK_HIGH;
	else
		hpb->pre_req_max_tr_len = HPB_MULTI_CHUNK_HIGH;
		hpb->pre_req_max_tr_len = hpb_dev_info->max_hpb_single_cmd;

	hpb->lu_pinned_start = hpb_lu_info->pinned_start;
	hpb->lu_pinned_end = hpb_lu_info->num_pinned ?
@@ -2582,7 +2580,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
{
	struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev;
	int version, ret;
	u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW;
	int max_single_cmd;

	hpb_dev_info->control_mode = desc_buf[DEVICE_DESC_PARAM_HPB_CONTROL];

@@ -2598,18 +2596,22 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
	if (version == HPB_SUPPORT_LEGACY_VERSION)
		hpb_dev_info->is_legacy = true;

	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
		QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_hpb_single_cmd);
	if (ret)
		dev_err(hba->dev, "%s: idn: read max size of single hpb cmd query request failed",
			__func__);
	hpb_dev_info->max_hpb_single_cmd = max_hpb_single_cmd;

	/*
	 * Get the number of user logical unit to check whether all
	 * scsi_device finish initialization
	 */
	hpb_dev_info->num_lu = desc_buf[DEVICE_DESC_PARAM_NUM_LU];

	if (hpb_dev_info->is_legacy)
		return;

	ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
		QUERY_ATTR_IDN_MAX_HPB_SINGLE_CMD, 0, 0, &max_single_cmd);

	if (ret)
		hpb_dev_info->max_hpb_single_cmd = HPB_LEGACY_CHUNK_HIGH;
	else
		hpb_dev_info->max_hpb_single_cmd = min(max_single_cmd + 1, HPB_MULTI_CHUNK_HIGH);
}

void ufshpb_init(struct ufs_hba *hba)
+0 −1
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@

/* hpb support chunk size */
#define HPB_LEGACY_CHUNK_HIGH			1
#define HPB_MULTI_CHUNK_LOW			7
#define HPB_MULTI_CHUNK_HIGH			255

/* hpb vender defined opcode */