FROMLIST: scsi: ufs: Transform set_dirty to iterate_rgn

Given a transfer length, set_dirty meticulously runs over all the
entries, across subregions and regions if needed. Currently its only use
is to mark dirty blocks, but soon HCM may profit from it as well, when
managing its read counters.

Bug: 183467926
Bug: 170940265
Bug: 183454255

Link: https://lore.kernel.org/lkml/20210607061401.58884-4-avri.altman@wdc.com/
Signed-off-by: Avri Altman <avri.altman@wdc.com>
Reviewed-by: Daejun Park <daejun7.park@samsung.com>
Change-Id: I916f4bf80490e31e5ef797d67647a41a07cefa02
This commit is contained in:
Avri Altman
2021-03-27 14:18:36 +03:00
committed by Todd Kjos
parent a210fd6f26
commit ac898f51d1

View File

@@ -145,13 +145,14 @@ static bool ufshpb_is_hpb_rsp_valid(struct ufs_hba *hba,
return true; return true;
} }
static void ufshpb_set_ppn_dirty(struct ufshpb_lu *hpb, int rgn_idx, static void ufshpb_iterate_rgn(struct ufshpb_lu *hpb, int rgn_idx, int srgn_idx,
int srgn_idx, int srgn_offset, int cnt) int srgn_offset, int cnt, bool set_dirty)
{ {
struct ufshpb_region *rgn; struct ufshpb_region *rgn;
struct ufshpb_subregion *srgn; struct ufshpb_subregion *srgn;
int set_bit_len; int set_bit_len;
int bitmap_len; int bitmap_len;
unsigned long flags;
next_srgn: next_srgn:
rgn = hpb->rgn_tbl + rgn_idx; rgn = hpb->rgn_tbl + rgn_idx;
@@ -167,11 +168,14 @@ next_srgn:
else else
set_bit_len = cnt; set_bit_len = cnt;
if (set_dirty)
set_bit(RGN_FLAG_DIRTY, &rgn->rgn_flags); set_bit(RGN_FLAG_DIRTY, &rgn->rgn_flags);
if (rgn->rgn_state != HPB_RGN_INACTIVE && spin_lock_irqsave(&hpb->rgn_state_lock, flags);
if (set_dirty && rgn->rgn_state != HPB_RGN_INACTIVE &&
srgn->srgn_state == HPB_SRGN_VALID) srgn->srgn_state == HPB_SRGN_VALID)
bitmap_set(srgn->mctx->ppn_dirty, srgn_offset, set_bit_len); bitmap_set(srgn->mctx->ppn_dirty, srgn_offset, set_bit_len);
spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
srgn_offset = 0; srgn_offset = 0;
if (++srgn_idx == hpb->srgns_per_rgn) { if (++srgn_idx == hpb->srgns_per_rgn) {
@@ -591,10 +595,8 @@ int ufshpb_prep(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
/* If command type is WRITE or DISCARD, set bitmap as drity */ /* If command type is WRITE or DISCARD, set bitmap as drity */
if (ufshpb_is_write_or_discard(cmd)) { if (ufshpb_is_write_or_discard(cmd)) {
spin_lock_irqsave(&hpb->rgn_state_lock, flags); ufshpb_iterate_rgn(hpb, rgn_idx, srgn_idx, srgn_offset,
ufshpb_set_ppn_dirty(hpb, rgn_idx, srgn_idx, srgn_offset, transfer_len, true);
transfer_len);
spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
return 0; return 0;
} }