Message ID | 20210804182128.458356-2-huobean@gmail.com |
---|---|
State | New |
Headers | show |
Series | two changes for UFS/HPB | expand |
> From: Bean Huo <beanhuo@micron.com> > > For the Micron UFS, L2P entry need to be swapped in HPB READ command > before sending HPB READ command to the UFS device. Add this quirk > UFS_DEVICE_QUIRK_SWAP_L2P_ENTRY_FOR_HPB_READ to fix this > inconsistency. > > Fixes: 2fff76f87542 ("scsi: ufs: ufshpb: Prepare HPB read for cached sub- > region") Not really needed - the patch is fine. > Signed-off-by: Bean Huo <beanhuo@micron.com> Reviewed-by: Avri Altman <avri.altman@wdc.com> > --- > drivers/scsi/ufs/ufs_quirks.h | 6 ++++++ > drivers/scsi/ufs/ufshcd.c | 3 ++- > drivers/scsi/ufs/ufshpb.c | 15 ++++++++++----- > 3 files changed, 18 insertions(+), 6 deletions(-) > > diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h > index 07f559ac5883..35ec9ea79869 100644 > --- a/drivers/scsi/ufs/ufs_quirks.h > +++ b/drivers/scsi/ufs/ufs_quirks.h > @@ -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_ */ > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c > index 47a5085f16a9..c3a14d3b0030 100644 > --- a/drivers/scsi/ufs/ufshcd.c > +++ b/drivers/scsi/ufs/ufshcd.c > @@ -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 | > diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c > index 54e8e019bdbe..d0eb14be47a3 100644 > --- a/drivers/scsi/ufs/ufshpb.c > +++ b/drivers/scsi/ufs/ufshpb.c > @@ -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; > -- > 2.25.1
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index 07f559ac5883..35ec9ea79869 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -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_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 47a5085f16a9..c3a14d3b0030 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -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 | diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c index 54e8e019bdbe..d0eb14be47a3 100644 --- a/drivers/scsi/ufs/ufshpb.c +++ b/drivers/scsi/ufs/ufshpb.c @@ -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;