Commit 63522bf3 authored by Bean Huo's avatar Bean Huo Committed by Martin K. Petersen
Browse files

scsi: ufs: core: Add L2P entry swap quirk for Micron UFS

For Micron UFS devices the L2P entry need to be byteswapped before sending
an HPB READ command to the UFS device. Add the quirk
UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ to address this.

Link: https://lore.kernel.org/r/20210804182128.458356-2-huobean@gmail.com


Reviewed-by: default avatarAvri Altman <avri.altman@wdc.com>
Signed-off-by: default avatarBean Huo <beanhuo@micron.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f0101af4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -116,4 +116,10 @@ struct ufs_dev_fix {
 */
#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM        (1 << 11)

/*
 * Some UFS devices require L2P entry should be swapped before being sent to the
 * UFS device for HPB READ command.
 */
#define UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ (1 << 12)

#endif /* UFS_QUIRKS_H_ */
+2 −1
Original line number Diff line number Diff line
@@ -199,7 +199,8 @@ ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state,
static struct ufs_dev_fix ufs_fixups[] = {
	/* UFS cards deviations table */
	UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL,
		UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
		UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
		UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ),
	UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
		UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM |
		UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE |
+10 −5
Original line number Diff line number Diff line
@@ -323,15 +323,19 @@ ufshpb_get_pos_from_lpn(struct ufshpb_lu *hpb, unsigned long lpn, int *rgn_idx,
}

static void
ufshpb_set_hpb_read_to_upiu(struct ufshpb_lu *hpb, struct ufshcd_lrb *lrbp,
			    u32 lpn, __be64 ppn, u8 transfer_len, int read_id)
ufshpb_set_hpb_read_to_upiu(struct ufs_hba *hba, struct ufshpb_lu *hpb,
			    struct ufshcd_lrb *lrbp, u32 lpn, __be64 ppn,
			    u8 transfer_len, int read_id)
{
	unsigned char *cdb = lrbp->cmd->cmnd;

	__be64 ppn_tmp = ppn;
	cdb[0] = UFSHPB_READ;

	if (hba->dev_quirks & UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ)
		ppn_tmp = swab64(ppn);

	/* ppn value is stored as big-endian in the host memory */
	memcpy(&cdb[6], &ppn, sizeof(__be64));
	memcpy(&cdb[6], &ppn_tmp, sizeof(__be64));
	cdb[14] = transfer_len;
	cdb[15] = read_id;

@@ -689,7 +693,8 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
		}
	}

	ufshpb_set_hpb_read_to_upiu(hpb, lrbp, lpn, ppn, transfer_len, read_id);
	ufshpb_set_hpb_read_to_upiu(hba, hpb, lrbp, lpn, ppn, transfer_len,
				    read_id);

	hpb->stats.hit_cnt++;
	return 0;